aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2015-05-28 13:49:20 -0700
committerKeith Randall <khr@golang.org>2015-05-28 13:51:18 -0700
commit067e8dfd82163ddcbde248dbe5a1187a417e5d36 (patch)
tree7bfb46b901d03498c7739c92bec21d81d3a2c485 /src/cmd
parent247786c1745abc0c7185f7c15ca256edf68ed6d6 (diff)
parentccc037699e2966b7c79ba84c67471cef5e67a3b8 (diff)
downloadgo-067e8dfd82163ddcbde248dbe5a1187a417e5d36.tar.xz
[dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch
Semi-regular merge of tip to dev.ssa. Complicated a bit by the move of cmd/internal/* to cmd/compile/internal/*. Change-Id: I1c66d3c29bb95cce4a53c5a3476373aa5245303d
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/6l/z.go1
-rw-r--r--src/cmd/asm/internal/asm/asm.go5
-rw-r--r--src/cmd/asm/internal/flags/flags.go4
-rw-r--r--src/cmd/asm/internal/lex/input.go3
-rw-r--r--src/cmd/asm/internal/lex/tokenizer.go6
-rw-r--r--src/cmd/asm/main.go2
-rw-r--r--src/cmd/cgo/out.go15
-rw-r--r--src/cmd/compile/internal/amd64/cgen.go (renamed from src/cmd/6g/cgen.go)4
-rw-r--r--src/cmd/compile/internal/amd64/galign.go (renamed from src/cmd/6g/galign.go)7
-rw-r--r--src/cmd/compile/internal/amd64/ggen.go (renamed from src/cmd/6g/ggen.go)18
-rw-r--r--src/cmd/compile/internal/amd64/gsubr.go (renamed from src/cmd/6g/gsubr.go)82
-rw-r--r--src/cmd/compile/internal/amd64/peep.go (renamed from src/cmd/6g/peep.go)4
-rw-r--r--src/cmd/compile/internal/amd64/prog.go (renamed from src/cmd/6g/prog.go)4
-rw-r--r--src/cmd/compile/internal/amd64/reg.go (renamed from src/cmd/6g/reg.go)4
-rw-r--r--src/cmd/compile/internal/arm/cgen.go (renamed from src/cmd/5g/cgen.go)26
-rw-r--r--src/cmd/compile/internal/arm/cgen64.go (renamed from src/cmd/5g/cgen64.go)10
-rw-r--r--src/cmd/compile/internal/arm/galign.go (renamed from src/cmd/5g/galign.go)7
-rw-r--r--src/cmd/compile/internal/arm/ggen.go (renamed from src/cmd/5g/ggen.go)36
-rw-r--r--src/cmd/compile/internal/arm/gsubr.go (renamed from src/cmd/5g/gsubr.go)20
-rw-r--r--src/cmd/compile/internal/arm/peep.go (renamed from src/cmd/5g/peep.go)4
-rw-r--r--src/cmd/compile/internal/arm/prog.go (renamed from src/cmd/5g/prog.go)4
-rw-r--r--src/cmd/compile/internal/arm/reg.go (renamed from src/cmd/5g/reg.go)4
-rw-r--r--src/cmd/compile/internal/arm64/cgen.go (renamed from src/cmd/7g/cgen.go)4
-rw-r--r--src/cmd/compile/internal/arm64/galign.go (renamed from src/cmd/7g/galign.go)7
-rw-r--r--src/cmd/compile/internal/arm64/ggen.go (renamed from src/cmd/7g/ggen.go)12
-rw-r--r--src/cmd/compile/internal/arm64/gsubr.go (renamed from src/cmd/7g/gsubr.go)51
-rw-r--r--src/cmd/compile/internal/arm64/peep.go (renamed from src/cmd/7g/peep.go)8
-rw-r--r--src/cmd/compile/internal/arm64/prog.go (renamed from src/cmd/7g/prog.go)4
-rw-r--r--src/cmd/compile/internal/arm64/reg.go (renamed from src/cmd/7g/reg.go)4
-rw-r--r--src/cmd/compile/internal/big/accuracy_string.go (renamed from src/cmd/internal/gc/big/accuracy_string.go)0
-rw-r--r--src/cmd/compile/internal/big/arith.go (renamed from src/cmd/internal/gc/big/arith.go)1
-rw-r--r--src/cmd/compile/internal/big/arith_decl.go (renamed from src/cmd/internal/gc/big/arith_decl.go)0
-rw-r--r--src/cmd/compile/internal/big/arith_test.go (renamed from src/cmd/internal/gc/big/arith_test.go)1
-rw-r--r--src/cmd/compile/internal/big/bits_test.go (renamed from src/cmd/internal/gc/big/bits_test.go)0
-rw-r--r--src/cmd/compile/internal/big/calibrate_test.go (renamed from src/cmd/internal/gc/big/calibrate_test.go)0
-rw-r--r--src/cmd/compile/internal/big/decimal.go (renamed from src/cmd/internal/gc/big/decimal.go)0
-rw-r--r--src/cmd/compile/internal/big/decimal_test.go (renamed from src/cmd/internal/gc/big/decimal_test.go)0
-rw-r--r--src/cmd/compile/internal/big/example_test.go (renamed from src/cmd/internal/gc/big/example_test.go)2
-rw-r--r--src/cmd/compile/internal/big/float.go (renamed from src/cmd/internal/gc/big/float.go)151
-rw-r--r--src/cmd/compile/internal/big/float_test.go (renamed from src/cmd/internal/gc/big/float_test.go)185
-rw-r--r--src/cmd/compile/internal/big/floatconv.go (renamed from src/cmd/internal/gc/big/floatconv.go)0
-rw-r--r--src/cmd/compile/internal/big/floatconv_test.go (renamed from src/cmd/internal/gc/big/floatconv_test.go)0
-rw-r--r--src/cmd/compile/internal/big/floatexample_test.go (renamed from src/cmd/internal/gc/big/floatexample_test.go)2
-rw-r--r--src/cmd/compile/internal/big/ftoa.go (renamed from src/cmd/internal/gc/big/ftoa.go)0
-rw-r--r--src/cmd/compile/internal/big/gcd_test.go (renamed from src/cmd/internal/gc/big/gcd_test.go)0
-rw-r--r--src/cmd/compile/internal/big/hilbert_test.go (renamed from src/cmd/internal/gc/big/hilbert_test.go)0
-rw-r--r--src/cmd/compile/internal/big/int.go (renamed from src/cmd/internal/gc/big/int.go)118
-rw-r--r--src/cmd/compile/internal/big/int_test.go (renamed from src/cmd/internal/gc/big/int_test.go)138
-rw-r--r--src/cmd/compile/internal/big/intconv.go (renamed from src/cmd/internal/gc/big/intconv.go)0
-rw-r--r--src/cmd/compile/internal/big/intconv_test.go (renamed from src/cmd/internal/gc/big/intconv_test.go)0
-rw-r--r--src/cmd/compile/internal/big/nat.go (renamed from src/cmd/internal/gc/big/nat.go)121
-rw-r--r--src/cmd/compile/internal/big/nat_test.go (renamed from src/cmd/internal/gc/big/nat_test.go)61
-rw-r--r--src/cmd/compile/internal/big/natconv.go (renamed from src/cmd/internal/gc/big/natconv.go)0
-rw-r--r--src/cmd/compile/internal/big/natconv_test.go (renamed from src/cmd/internal/gc/big/natconv_test.go)0
-rw-r--r--src/cmd/compile/internal/big/rat.go (renamed from src/cmd/internal/gc/big/rat.go)0
-rw-r--r--src/cmd/compile/internal/big/rat_test.go (renamed from src/cmd/internal/gc/big/rat_test.go)0
-rw-r--r--src/cmd/compile/internal/big/ratconv.go (renamed from src/cmd/internal/gc/big/ratconv.go)0
-rw-r--r--src/cmd/compile/internal/big/ratconv_test.go (renamed from src/cmd/internal/gc/big/ratconv_test.go)0
-rw-r--r--src/cmd/compile/internal/big/roundingmode_string.go (renamed from src/cmd/internal/gc/big/roundingmode_string.go)0
-rwxr-xr-xsrc/cmd/compile/internal/big/vendor.bash (renamed from src/cmd/internal/gc/big/vendor.bash)8
-rw-r--r--src/cmd/compile/internal/gc/align.go (renamed from src/cmd/internal/gc/align.go)4
-rw-r--r--src/cmd/compile/internal/gc/builtin.go (renamed from src/cmd/internal/gc/builtin.go)0
-rw-r--r--src/cmd/compile/internal/gc/builtin/runtime.go (renamed from src/cmd/internal/gc/builtin/runtime.go)0
-rw-r--r--src/cmd/compile/internal/gc/builtin/unsafe.go (renamed from src/cmd/internal/gc/builtin/unsafe.go)0
-rw-r--r--src/cmd/compile/internal/gc/bv.go (renamed from src/cmd/internal/gc/bv.go)0
-rw-r--r--src/cmd/compile/internal/gc/cgen.go (renamed from src/cmd/internal/gc/cgen.go)927
-rw-r--r--src/cmd/compile/internal/gc/closure.go (renamed from src/cmd/internal/gc/closure.go)76
-rw-r--r--src/cmd/compile/internal/gc/const.go (renamed from src/cmd/internal/gc/const.go)282
-rw-r--r--src/cmd/compile/internal/gc/cplx.go (renamed from src/cmd/internal/gc/cplx.go)6
-rw-r--r--src/cmd/compile/internal/gc/dcl.go (renamed from src/cmd/internal/gc/dcl.go)47
-rw-r--r--src/cmd/compile/internal/gc/esc.go (renamed from src/cmd/internal/gc/esc.go)198
-rw-r--r--src/cmd/compile/internal/gc/export.go (renamed from src/cmd/internal/gc/export.go)2
-rw-r--r--src/cmd/compile/internal/gc/fmt.go (renamed from src/cmd/internal/gc/fmt.go)44
-rw-r--r--src/cmd/compile/internal/gc/gen.go (renamed from src/cmd/internal/gc/gen.go)163
-rw-r--r--src/cmd/compile/internal/gc/go.go (renamed from src/cmd/internal/gc/go.go)34
-rw-r--r--src/cmd/compile/internal/gc/go.y (renamed from src/cmd/internal/gc/go.y)100
-rw-r--r--src/cmd/compile/internal/gc/gsubr.go (renamed from src/cmd/internal/gc/gsubr.go)20
-rw-r--r--src/cmd/compile/internal/gc/init.go (renamed from src/cmd/internal/gc/init.go)2
-rw-r--r--src/cmd/compile/internal/gc/inl.go (renamed from src/cmd/internal/gc/inl.go)22
-rw-r--r--src/cmd/compile/internal/gc/lex.go (renamed from src/cmd/internal/gc/lex.go)103
-rw-r--r--src/cmd/compile/internal/gc/mkbuiltin.go (renamed from src/cmd/internal/gc/mkbuiltin.go)17
-rw-r--r--src/cmd/compile/internal/gc/mparith2.go (renamed from src/cmd/internal/gc/mparith2.go)4
-rw-r--r--src/cmd/compile/internal/gc/mparith3.go (renamed from src/cmd/internal/gc/mparith3.go)36
-rw-r--r--src/cmd/compile/internal/gc/obj.go (renamed from src/cmd/internal/gc/obj.go)7
-rw-r--r--src/cmd/compile/internal/gc/opnames.go (renamed from src/cmd/internal/gc/opnames.go)0
-rw-r--r--src/cmd/compile/internal/gc/order.go (renamed from src/cmd/internal/gc/order.go)157
-rw-r--r--src/cmd/compile/internal/gc/pgen.go (renamed from src/cmd/internal/gc/pgen.go)25
-rw-r--r--src/cmd/compile/internal/gc/plive.go (renamed from src/cmd/internal/gc/plive.go)6
-rw-r--r--src/cmd/compile/internal/gc/popt.go (renamed from src/cmd/internal/gc/popt.go)0
-rw-r--r--src/cmd/compile/internal/gc/racewalk.go (renamed from src/cmd/internal/gc/racewalk.go)30
-rw-r--r--src/cmd/compile/internal/gc/range.go (renamed from src/cmd/internal/gc/range.go)0
-rw-r--r--src/cmd/compile/internal/gc/reflect.go (renamed from src/cmd/internal/gc/reflect.go)425
-rw-r--r--src/cmd/compile/internal/gc/reg.go (renamed from src/cmd/internal/gc/reg.go)0
-rw-r--r--src/cmd/compile/internal/gc/select.go (renamed from src/cmd/internal/gc/select.go)0
-rw-r--r--src/cmd/compile/internal/gc/sinit.go (renamed from src/cmd/internal/gc/sinit.go)28
-rw-r--r--src/cmd/compile/internal/gc/ssa.go (renamed from src/cmd/internal/gc/ssa.go)4
-rw-r--r--src/cmd/compile/internal/gc/subr.go (renamed from src/cmd/internal/gc/subr.go)121
-rw-r--r--src/cmd/compile/internal/gc/swt.go (renamed from src/cmd/internal/gc/swt.go)14
-rw-r--r--src/cmd/compile/internal/gc/syntax.go (renamed from src/cmd/internal/gc/syntax.go)133
-rw-r--r--src/cmd/compile/internal/gc/type.go (renamed from src/cmd/internal/gc/type.go)2
-rw-r--r--src/cmd/compile/internal/gc/typecheck.go (renamed from src/cmd/internal/gc/typecheck.go)165
-rw-r--r--src/cmd/compile/internal/gc/unsafe.go (renamed from src/cmd/internal/gc/unsafe.go)4
-rw-r--r--src/cmd/compile/internal/gc/util.go (renamed from src/cmd/internal/gc/util.go)3
-rw-r--r--src/cmd/compile/internal/gc/walk.go (renamed from src/cmd/internal/gc/walk.go)506
-rw-r--r--src/cmd/compile/internal/gc/y.go (renamed from src/cmd/internal/gc/y.go)623
-rw-r--r--src/cmd/compile/internal/gc/y.output (renamed from src/cmd/internal/gc/y.output)972
-rw-r--r--src/cmd/compile/internal/ppc64/cgen.go (renamed from src/cmd/9g/cgen.go)4
-rw-r--r--src/cmd/compile/internal/ppc64/galign.go (renamed from src/cmd/9g/galign.go)7
-rw-r--r--src/cmd/compile/internal/ppc64/ggen.go (renamed from src/cmd/9g/ggen.go)12
-rw-r--r--src/cmd/compile/internal/ppc64/gsubr.go (renamed from src/cmd/9g/gsubr.go)80
-rw-r--r--src/cmd/compile/internal/ppc64/opt.go (renamed from src/cmd/9g/opt.go)2
-rw-r--r--src/cmd/compile/internal/ppc64/peep.go (renamed from src/cmd/9g/peep.go)4
-rw-r--r--src/cmd/compile/internal/ppc64/prog.go (renamed from src/cmd/9g/prog.go)4
-rw-r--r--src/cmd/compile/internal/ppc64/reg.go (renamed from src/cmd/9g/reg.go)4
-rw-r--r--src/cmd/compile/internal/ssa/TODO (renamed from src/cmd/internal/ssa/TODO)0
-rw-r--r--src/cmd/compile/internal/ssa/block.go (renamed from src/cmd/internal/ssa/block.go)0
-rw-r--r--src/cmd/compile/internal/ssa/blockkind_string.go (renamed from src/cmd/internal/ssa/blockkind_string.go)0
-rw-r--r--src/cmd/compile/internal/ssa/cgen.go (renamed from src/cmd/internal/ssa/cgen.go)0
-rw-r--r--src/cmd/compile/internal/ssa/check.go (renamed from src/cmd/internal/ssa/check.go)0
-rw-r--r--src/cmd/compile/internal/ssa/compile.go (renamed from src/cmd/internal/ssa/compile.go)0
-rw-r--r--src/cmd/compile/internal/ssa/config.go (renamed from src/cmd/internal/ssa/config.go)0
-rw-r--r--src/cmd/compile/internal/ssa/copyelim.go (renamed from src/cmd/internal/ssa/copyelim.go)0
-rw-r--r--src/cmd/compile/internal/ssa/critical.go (renamed from src/cmd/internal/ssa/critical.go)0
-rw-r--r--src/cmd/compile/internal/ssa/cse.go (renamed from src/cmd/internal/ssa/cse.go)0
-rw-r--r--src/cmd/compile/internal/ssa/deadcode.go (renamed from src/cmd/internal/ssa/deadcode.go)0
-rw-r--r--src/cmd/compile/internal/ssa/deadcode_test.go (renamed from src/cmd/internal/ssa/deadcode_test.go)0
-rw-r--r--src/cmd/compile/internal/ssa/dom.go (renamed from src/cmd/internal/ssa/dom.go)0
-rw-r--r--src/cmd/compile/internal/ssa/export_test.go (renamed from src/cmd/internal/ssa/export_test.go)0
-rw-r--r--src/cmd/compile/internal/ssa/func.go (renamed from src/cmd/internal/ssa/func.go)0
-rw-r--r--src/cmd/compile/internal/ssa/func_test.go (renamed from src/cmd/internal/ssa/func_test.go)0
-rw-r--r--src/cmd/compile/internal/ssa/fuse.go (renamed from src/cmd/internal/ssa/fuse.go)0
-rw-r--r--src/cmd/compile/internal/ssa/generic.go (renamed from src/cmd/internal/ssa/generic.go)0
-rw-r--r--src/cmd/compile/internal/ssa/id.go (renamed from src/cmd/internal/ssa/id.go)0
-rw-r--r--src/cmd/compile/internal/ssa/layout.go (renamed from src/cmd/internal/ssa/layout.go)0
-rw-r--r--src/cmd/compile/internal/ssa/location.go (renamed from src/cmd/internal/ssa/location.go)0
-rw-r--r--src/cmd/compile/internal/ssa/lower.go (renamed from src/cmd/internal/ssa/lower.go)0
-rw-r--r--src/cmd/compile/internal/ssa/lowerAmd64.go (renamed from src/cmd/internal/ssa/lowerAmd64.go)0
-rw-r--r--src/cmd/compile/internal/ssa/op.go (renamed from src/cmd/internal/ssa/op.go)0
-rw-r--r--src/cmd/compile/internal/ssa/op_string.go (renamed from src/cmd/internal/ssa/op_string.go)0
-rw-r--r--src/cmd/compile/internal/ssa/opamd64.go (renamed from src/cmd/internal/ssa/opamd64.go)0
-rw-r--r--src/cmd/compile/internal/ssa/opt.go (renamed from src/cmd/internal/ssa/opt.go)0
-rw-r--r--src/cmd/compile/internal/ssa/phielim.go (renamed from src/cmd/internal/ssa/phielim.go)0
-rw-r--r--src/cmd/compile/internal/ssa/print.go (renamed from src/cmd/internal/ssa/print.go)0
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go (renamed from src/cmd/internal/ssa/regalloc.go)0
-rw-r--r--src/cmd/compile/internal/ssa/rewrite.go (renamed from src/cmd/internal/ssa/rewrite.go)0
-rw-r--r--src/cmd/compile/internal/ssa/rulegen/generic.rules (renamed from src/cmd/internal/ssa/rulegen/generic.rules)0
-rw-r--r--src/cmd/compile/internal/ssa/rulegen/lower_amd64.rules (renamed from src/cmd/internal/ssa/rulegen/lower_amd64.rules)0
-rw-r--r--src/cmd/compile/internal/ssa/rulegen/rulegen.go (renamed from src/cmd/internal/ssa/rulegen/rulegen.go)0
-rw-r--r--src/cmd/compile/internal/ssa/schedule.go (renamed from src/cmd/internal/ssa/schedule.go)0
-rw-r--r--src/cmd/compile/internal/ssa/sparseset.go (renamed from src/cmd/internal/ssa/sparseset.go)0
-rw-r--r--src/cmd/compile/internal/ssa/stackalloc.go (renamed from src/cmd/internal/ssa/stackalloc.go)0
-rw-r--r--src/cmd/compile/internal/ssa/type.go (renamed from src/cmd/internal/ssa/type.go)0
-rw-r--r--src/cmd/compile/internal/ssa/value.go (renamed from src/cmd/internal/ssa/value.go)0
-rw-r--r--src/cmd/compile/internal/x86/cgen.go (renamed from src/cmd/8g/cgen.go)6
-rw-r--r--src/cmd/compile/internal/x86/cgen64.go (renamed from src/cmd/8g/cgen64.go)15
-rw-r--r--src/cmd/compile/internal/x86/galign.go (renamed from src/cmd/8g/galign.go)7
-rw-r--r--src/cmd/compile/internal/x86/ggen.go (renamed from src/cmd/8g/ggen.go)12
-rw-r--r--src/cmd/compile/internal/x86/gsubr.go (renamed from src/cmd/8g/gsubr.go)102
-rw-r--r--src/cmd/compile/internal/x86/peep.go (renamed from src/cmd/8g/peep.go)4
-rw-r--r--src/cmd/compile/internal/x86/prog.go (renamed from src/cmd/8g/prog.go)4
-rw-r--r--src/cmd/compile/internal/x86/reg.go (renamed from src/cmd/8g/reg.go)4
-rw-r--r--src/cmd/compile/main.go34
-rw-r--r--src/cmd/dist/build.go69
-rw-r--r--src/cmd/dist/buildtool.go31
-rw-r--r--src/cmd/dist/test.go197
-rw-r--r--src/cmd/doc/main.go3
-rw-r--r--src/cmd/doc/pkg.go72
-rw-r--r--src/cmd/go/alldocs.go3
-rw-r--r--src/cmd/go/build.go70
-rw-r--r--src/cmd/go/env.go4
-rw-r--r--src/cmd/go/fmt.go28
-rw-r--r--src/cmd/go/help.go2
-rw-r--r--src/cmd/go/pkg.go19
-rw-r--r--src/cmd/go/vcs.go8
-rw-r--r--src/cmd/internal/asm/lexbody.go4
-rw-r--r--src/cmd/internal/asm/macbody.go5
-rw-r--r--src/cmd/internal/gc/go.errors81
-rw-r--r--src/cmd/internal/gc/yaccerrors.go194
-rw-r--r--src/cmd/internal/gc/yymsg.go83
-rw-r--r--src/cmd/internal/gcprog/gcprog.go298
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go4
-rw-r--r--src/cmd/internal/obj/line_test.go14
-rw-r--r--src/cmd/internal/obj/link.go3
-rw-r--r--src/cmd/internal/obj/mgc0.go10
-rw-r--r--src/cmd/internal/obj/obj.go33
-rw-r--r--src/cmd/internal/obj/util.go17
-rw-r--r--src/cmd/internal/obj/x86/asm6.go5
-rw-r--r--src/cmd/internal/obj/x86/obj6.go3
-rw-r--r--src/cmd/internal/objfile/macho.go11
-rw-r--r--src/cmd/link/internal/amd64/asm.go (renamed from src/cmd/6l/asm.go)110
-rw-r--r--src/cmd/link/internal/amd64/l.go (renamed from src/cmd/6l/l.go)5
-rw-r--r--src/cmd/link/internal/amd64/obj.go (renamed from src/cmd/6l/obj.go)19
-rw-r--r--src/cmd/link/internal/amd64/z.go1
-rw-r--r--src/cmd/link/internal/arm/asm.go (renamed from src/cmd/5l/asm.go)112
-rw-r--r--src/cmd/link/internal/arm/l.go (renamed from src/cmd/5l/l.go)5
-rw-r--r--src/cmd/link/internal/arm/obj.go (renamed from src/cmd/5l/obj.go)9
-rw-r--r--src/cmd/link/internal/arm64/asm.go (renamed from src/cmd/7l/asm.go)62
-rw-r--r--src/cmd/link/internal/arm64/l.go (renamed from src/cmd/7l/l.go)5
-rw-r--r--src/cmd/link/internal/arm64/obj.go (renamed from src/cmd/7l/obj.go)9
-rw-r--r--src/cmd/link/internal/ld/ar.go (renamed from src/cmd/internal/ld/ar.go)0
-rw-r--r--src/cmd/link/internal/ld/arch.go (renamed from src/cmd/internal/ld/arch.go)0
-rw-r--r--src/cmd/link/internal/ld/data.go (renamed from src/cmd/internal/ld/data.go)232
-rw-r--r--src/cmd/link/internal/ld/decodesym.go (renamed from src/cmd/internal/ld/decodesym.go)59
-rw-r--r--src/cmd/link/internal/ld/dwarf.go (renamed from src/cmd/internal/ld/dwarf.go)188
-rw-r--r--src/cmd/link/internal/ld/dwarf_defs.go (renamed from src/cmd/internal/ld/dwarf_defs.go)0
-rw-r--r--src/cmd/link/internal/ld/elf.go (renamed from src/cmd/internal/ld/elf.go)212
-rw-r--r--src/cmd/link/internal/ld/go.go (renamed from src/cmd/internal/ld/go.go)57
-rw-r--r--src/cmd/link/internal/ld/ld.go (renamed from src/cmd/internal/ld/ld.go)4
-rw-r--r--src/cmd/link/internal/ld/ldelf.go (renamed from src/cmd/internal/ld/ldelf.go)0
-rw-r--r--src/cmd/link/internal/ld/ldmacho.go (renamed from src/cmd/internal/ld/ldmacho.go)0
-rw-r--r--src/cmd/link/internal/ld/ldpe.go (renamed from src/cmd/internal/ld/ldpe.go)0
-rw-r--r--src/cmd/link/internal/ld/lib.go (renamed from src/cmd/internal/ld/lib.go)280
-rw-r--r--src/cmd/link/internal/ld/link.go (renamed from src/cmd/internal/ld/link.go)23
-rw-r--r--src/cmd/link/internal/ld/macho.go (renamed from src/cmd/internal/ld/macho.go)10
-rw-r--r--src/cmd/link/internal/ld/macho_combine_dwarf.go369
-rw-r--r--src/cmd/link/internal/ld/objfile.go (renamed from src/cmd/internal/ld/objfile.go)2
-rw-r--r--src/cmd/link/internal/ld/pcln.go (renamed from src/cmd/internal/ld/pcln.go)0
-rw-r--r--src/cmd/link/internal/ld/pe.go (renamed from src/cmd/internal/ld/pe.go)0
-rw-r--r--src/cmd/link/internal/ld/pobj.go (renamed from src/cmd/internal/ld/pobj.go)5
-rw-r--r--src/cmd/link/internal/ld/sym.go (renamed from src/cmd/internal/ld/sym.go)0
-rw-r--r--src/cmd/link/internal/ld/symtab.go (renamed from src/cmd/internal/ld/symtab.go)63
-rw-r--r--src/cmd/link/internal/ld/textflag.go (renamed from src/cmd/internal/ld/textflag.go)0
-rw-r--r--src/cmd/link/internal/ld/util.go (renamed from src/cmd/internal/ld/util.go)0
-rw-r--r--src/cmd/link/internal/ppc64/asm.go (renamed from src/cmd/9l/asm.go)90
-rw-r--r--src/cmd/link/internal/ppc64/l.go (renamed from src/cmd/9l/l.go)5
-rw-r--r--src/cmd/link/internal/ppc64/obj.go (renamed from src/cmd/9l/obj.go)9
-rw-r--r--src/cmd/link/internal/x86/asm.go (renamed from src/cmd/8l/asm.go)106
-rw-r--r--src/cmd/link/internal/x86/l.go (renamed from src/cmd/8l/l.go)5
-rw-r--r--src/cmd/link/internal/x86/obj.go (renamed from src/cmd/8l/obj.go)9
-rw-r--r--src/cmd/link/main.go33
-rw-r--r--src/cmd/newlink/auto.go (renamed from src/cmd/link/auto.go)0
-rw-r--r--src/cmd/newlink/auto_test.go (renamed from src/cmd/link/auto_test.go)0
-rw-r--r--src/cmd/newlink/dead.go (renamed from src/cmd/link/dead.go)0
-rw-r--r--src/cmd/newlink/dead_test.go (renamed from src/cmd/link/dead_test.go)0
-rw-r--r--src/cmd/newlink/debug.go (renamed from src/cmd/link/debug.go)0
-rw-r--r--src/cmd/newlink/hex_test.go (renamed from src/cmd/link/hex_test.go)0
-rw-r--r--src/cmd/newlink/layout.go (renamed from src/cmd/link/layout.go)0
-rw-r--r--src/cmd/newlink/layout_test.go (renamed from src/cmd/link/layout_test.go)0
-rw-r--r--src/cmd/newlink/link_test.go (renamed from src/cmd/link/link_test.go)0
-rw-r--r--src/cmd/newlink/load.go (renamed from src/cmd/link/load.go)0
-rw-r--r--src/cmd/newlink/macho.go (renamed from src/cmd/link/macho.go)0
-rw-r--r--src/cmd/newlink/macho_test.go (renamed from src/cmd/link/macho_test.go)0
-rw-r--r--src/cmd/newlink/main.go9
-rw-r--r--src/cmd/newlink/pclntab.go (renamed from src/cmd/link/pclntab.go)0
-rw-r--r--src/cmd/newlink/pclntab_test.go (renamed from src/cmd/link/pclntab_test.go)0
-rw-r--r--src/cmd/newlink/prog.go (renamed from src/cmd/link/prog.go)0
-rw-r--r--src/cmd/newlink/prog_test.go (renamed from src/cmd/link/prog_test.go)0
-rw-r--r--src/cmd/newlink/runtime.go (renamed from src/cmd/link/runtime.go)0
-rw-r--r--src/cmd/newlink/scan.go (renamed from src/cmd/link/scan.go)0
-rw-r--r--src/cmd/newlink/testdata/Makefile (renamed from src/cmd/link/testdata/Makefile)0
-rw-r--r--src/cmd/newlink/testdata/autosection.6 (renamed from src/cmd/link/testdata/autosection.6)bin937 -> 937 bytes
-rw-r--r--src/cmd/newlink/testdata/autosection.s (renamed from src/cmd/link/testdata/autosection.s)0
-rw-r--r--src/cmd/newlink/testdata/autoweak.6 (renamed from src/cmd/link/testdata/autoweak.6)bin386 -> 386 bytes
-rw-r--r--src/cmd/newlink/testdata/autoweak.s (renamed from src/cmd/link/testdata/autoweak.s)0
-rw-r--r--src/cmd/newlink/testdata/dead.6 (renamed from src/cmd/link/testdata/dead.6)bin849 -> 849 bytes
-rw-r--r--src/cmd/newlink/testdata/dead.s (renamed from src/cmd/link/testdata/dead.s)0
-rw-r--r--src/cmd/newlink/testdata/genpcln.go (renamed from src/cmd/link/testdata/genpcln.go)0
-rw-r--r--src/cmd/newlink/testdata/hello.6 (renamed from src/cmd/link/testdata/hello.6)bin229 -> 229 bytes
-rw-r--r--src/cmd/newlink/testdata/hello.s (renamed from src/cmd/link/testdata/hello.s)0
-rw-r--r--src/cmd/newlink/testdata/layout.6 (renamed from src/cmd/link/testdata/layout.6)bin396 -> 396 bytes
-rw-r--r--src/cmd/newlink/testdata/layout.s (renamed from src/cmd/link/testdata/layout.s)0
-rw-r--r--src/cmd/newlink/testdata/link.hello.darwin.amd64 (renamed from src/cmd/link/testdata/link.hello.darwin.amd64)0
-rw-r--r--src/cmd/newlink/testdata/macho.amd64.exit9 (renamed from src/cmd/link/testdata/macho.amd64.exit9)0
-rw-r--r--src/cmd/newlink/testdata/macho.amd64.hello (renamed from src/cmd/link/testdata/macho.amd64.hello)0
-rw-r--r--src/cmd/newlink/testdata/macho.amd64.helloro (renamed from src/cmd/link/testdata/macho.amd64.helloro)0
-rw-r--r--src/cmd/newlink/testdata/pclntab.6 (renamed from src/cmd/link/testdata/pclntab.6)bin3804 -> 3804 bytes
-rw-r--r--src/cmd/newlink/testdata/pclntab.s (renamed from src/cmd/link/testdata/pclntab.s)0
-rw-r--r--src/cmd/newlink/util.go (renamed from src/cmd/link/util.go)0
-rw-r--r--src/cmd/newlink/write.go (renamed from src/cmd/link/write.go)0
-rw-r--r--src/cmd/pack/pack_test.go33
-rw-r--r--src/cmd/pprof/internal/profile/legacy_profile.go3
-rw-r--r--src/cmd/yacc/yacc.go128
272 files changed, 5962 insertions, 4345 deletions
diff --git a/src/cmd/6l/z.go b/src/cmd/6l/z.go
deleted file mode 100644
index 06ab7d0f9a..0000000000
--- a/src/cmd/6l/z.go
+++ /dev/null
@@ -1 +0,0 @@
-package main
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
index 725c6352cb..d5d2772ef3 100644
--- a/src/cmd/asm/internal/asm/asm.go
+++ b/src/cmd/asm/internal/asm/asm.go
@@ -493,7 +493,10 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
if arch.IsARM64STLXR(op) {
prog.From = a[0]
prog.To = a[1]
- prog.To2 = a[2]
+ if a[2].Type != obj.TYPE_REG {
+ p.errorf("invalid addressing modes for third operand to %s instruction, must be register", obj.Aconv(op))
+ }
+ prog.RegTo2 = a[2].Reg
break
}
prog.From = a[0]
diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go
index c74f26974a..bf5cb1eef3 100644
--- a/src/cmd/asm/internal/flags/flags.go
+++ b/src/cmd/asm/internal/flags/flags.go
@@ -51,7 +51,7 @@ func Usage() {
os.Exit(2)
}
-func Parse(theChar int) {
+func Parse() {
flag.Usage = Usage
flag.Parse()
if flag.NArg() != 1 {
@@ -64,6 +64,6 @@ func Parse(theChar int) {
if strings.HasSuffix(input, ".s") {
input = input[:len(input)-2]
}
- *OutputFile = fmt.Sprintf("%s.%c", input, theChar)
+ *OutputFile = fmt.Sprintf("%s.o", input)
}
}
diff --git a/src/cmd/asm/internal/lex/input.go b/src/cmd/asm/internal/lex/input.go
index 730042b149..7e495b8edf 100644
--- a/src/cmd/asm/internal/lex/input.go
+++ b/src/cmd/asm/internal/lex/input.go
@@ -13,7 +13,6 @@ import (
"text/scanner"
"cmd/asm/internal/flags"
- "cmd/internal/obj"
)
// Input is the main input: a stack of readers and some macro definitions.
@@ -436,7 +435,7 @@ func (in *Input) line() {
if tok != '\n' {
in.Error("unexpected token at end of #line: ", tok)
}
- obj.Linklinehist(linkCtxt, histLine, file, line)
+ linkCtxt.LineHist.Update(histLine, file, line)
in.Stack.SetPos(line, file)
}
diff --git a/src/cmd/asm/internal/lex/tokenizer.go b/src/cmd/asm/internal/lex/tokenizer.go
index 28a4b85253..6a4d95491f 100644
--- a/src/cmd/asm/internal/lex/tokenizer.go
+++ b/src/cmd/asm/internal/lex/tokenizer.go
@@ -10,8 +10,6 @@ import (
"strings"
"text/scanner"
"unicode"
-
- "cmd/internal/obj"
)
// A Tokenizer is a simple wrapping of text/scanner.Scanner, configured
@@ -40,7 +38,7 @@ func NewTokenizer(name string, r io.Reader, file *os.File) *Tokenizer {
s.Position.Filename = name
s.IsIdentRune = isIdentRune
if file != nil {
- obj.Linklinehist(linkCtxt, histLine, name, 0)
+ linkCtxt.LineHist.Push(histLine, name)
}
return &Tokenizer{
s: &s,
@@ -149,6 +147,6 @@ func (t *Tokenizer) Close() {
if t.file != nil {
t.file.Close()
// It's an open file, so pop the line history.
- obj.Linklinehist(linkCtxt, histLine, "<pop>", 0)
+ linkCtxt.LineHist.Pop(histLine)
}
}
diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go
index 32bdee6624..db0e28e2e5 100644
--- a/src/cmd/asm/main.go
+++ b/src/cmd/asm/main.go
@@ -29,7 +29,7 @@ func main() {
log.Fatalf("asm: unrecognized architecture %s", GOARCH)
}
- flags.Parse(architecture.Thechar)
+ flags.Parse()
// Create object file, write header.
fd, err := os.Create(*flags.OutputFile)
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 30f828c4e9..87f21ed822 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -846,6 +846,8 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
fmt.Fprint(fgo2, "}\n")
}
}
+
+ fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
}
// Write out the C header allowing C code to call exported gccgo functions.
@@ -1009,6 +1011,8 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
fmt.Fprint(fgo2, ")\n")
fmt.Fprint(fgo2, "}\n")
}
+
+ fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
}
// writeExportHeader writes out the start of the _cgo_export.h file.
@@ -1374,6 +1378,17 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+`
+
+// gccExportHeaderEpilog goes at the end of the generated header file.
+const gccExportHeaderEpilog = `
+#ifdef __cplusplus
+}
+#endif
`
// gccgoExportFileProlog is written to the _cgo_export.c file when
diff --git a/src/cmd/6g/cgen.go b/src/cmd/compile/internal/amd64/cgen.go
index 23e2d1b57f..71f8f88322 100644
--- a/src/cmd/6g/cgen.go
+++ b/src/cmd/compile/internal/amd64/cgen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package amd64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
diff --git a/src/cmd/6g/galign.go b/src/cmd/compile/internal/amd64/galign.go
index 0ca87537ff..79bf94a075 100644
--- a/src/cmd/6g/galign.go
+++ b/src/cmd/compile/internal/amd64/galign.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package amd64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
@@ -65,7 +65,7 @@ func betypeinit() {
}
}
-func main() {
+func Main() {
if obj.Getgoos() == "nacl" {
resvd = append(resvd, x86.REG_BP, x86.REG_R15)
} else if obj.Framepointer_enabled != 0 {
@@ -101,6 +101,7 @@ func main() {
gc.Thearch.Getg = getg
gc.Thearch.Gins = gins
gc.Thearch.Ginsboolval = ginsboolval
+ gc.Thearch.Ginscmp = ginscmp
gc.Thearch.Ginscon = ginscon
gc.Thearch.Ginsnop = ginsnop
gc.Thearch.Gmove = gmove
diff --git a/src/cmd/6g/ggen.go b/src/cmd/compile/internal/amd64/ggen.go
index 6e5e6bc4ca..6425633818 100644
--- a/src/cmd/6g/ggen.go
+++ b/src/cmd/compile/internal/amd64/ggen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package amd64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
@@ -32,7 +32,7 @@ func defframe(ptxt *obj.Prog) {
// iterate through declarations - they are sorted in decreasing xoffset order.
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
n = l.N
- if !n.Needzero {
+ if !n.Name.Needzero {
continue
}
if n.Class != gc.PAUTO {
@@ -190,9 +190,9 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
check := 0
if gc.Issigned[t.Etype] {
check = 1
- if gc.Isconst(nl, gc.CTINT) && gc.Mpgetfix(nl.Val.U.Xval) != -(1<<uint64(t.Width*8-1)) {
+ if gc.Isconst(nl, gc.CTINT) && nl.Int() != -(1<<uint64(t.Width*8-1)) {
check = 0
- } else if gc.Isconst(nr, gc.CTINT) && gc.Mpgetfix(nr.Val.U.Xval) != -1 {
+ } else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
check = 0
}
}
@@ -306,7 +306,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
* known to be dead.
*/
func savex(dr int, x *gc.Node, oldx *gc.Node, res *gc.Node, t *gc.Type) {
- r := int(reg[dr])
+ r := reg[dr]
// save current ax and dx if they are live
// and not the destination
@@ -318,7 +318,7 @@ func savex(dr int, x *gc.Node, oldx *gc.Node, res *gc.Node, t *gc.Type) {
x.Type = gc.Types[gc.TINT64]
gmove(x, oldx)
x.Type = t
- oldx.Ostk = int32(r) // squirrel away old r value
+ oldx.Etype = r // squirrel away old r value
reg[dr] = 1
}
}
@@ -326,7 +326,7 @@ func savex(dr int, x *gc.Node, oldx *gc.Node, res *gc.Node, t *gc.Type) {
func restx(x *gc.Node, oldx *gc.Node) {
if oldx.Op != 0 {
x.Type = gc.Types[gc.TINT64]
- reg[x.Reg] = uint8(oldx.Ostk)
+ reg[x.Reg] = oldx.Etype
gmove(oldx, x)
gc.Regfree(oldx)
}
@@ -381,7 +381,7 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, res)
gc.Cgen(nl, &n1)
- sc := uint64(gc.Mpgetfix(nr.Val.U.Xval))
+ sc := uint64(nr.Int())
if sc >= uint64(nl.Type.Width*8) {
// large shift gets 2 shifts by width-1
var n3 gc.Node
diff --git a/src/cmd/6g/gsubr.go b/src/cmd/compile/internal/amd64/gsubr.go
index 53d0f038d9..a8e4170bee 100644
--- a/src/cmd/6g/gsubr.go
+++ b/src/cmd/compile/internal/amd64/gsubr.go
@@ -28,10 +28,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package amd64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/big"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
"fmt"
@@ -99,33 +100,67 @@ func ginscon(as int, c int64, n2 *gc.Node) {
gins(as, &n1, n2)
}
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+ if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && gc.Smallintconst(n1) && n2.Op != gc.OLITERAL {
+ // Reverse comparison to place constant last.
+ op = gc.Brrev(op)
+ n1, n2 = n2, n1
+ }
+ // General case.
+ var r1, r2, g1, g2 gc.Node
+ if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
+ r1 = *n1
+ } else {
+ gc.Regalloc(&r1, t, n1)
+ gc.Regalloc(&g1, n1.Type, &r1)
+ gc.Cgen(n1, &g1)
+ gmove(&g1, &r1)
+ }
+ if n2.Op == gc.OLITERAL && gc.Isint[t.Etype] && gc.Smallintconst(n2) {
+ r2 = *n2
+ } else {
+ gc.Regalloc(&r2, t, n2)
+ gc.Regalloc(&g2, n1.Type, &r2)
+ gc.Cgen(n2, &g2)
+ gmove(&g2, &r2)
+ }
+ gins(optoas(gc.OCMP, t), &r1, &r2)
+ if r1.Op == gc.OREGISTER {
+ gc.Regfree(&g1)
+ gc.Regfree(&r1)
+ }
+ if r2.Op == gc.OREGISTER {
+ gc.Regfree(&g2)
+ gc.Regfree(&r2)
+ }
+ return gc.Gbranch(optoas(op, t), nil, likely)
+}
+
func ginsboolval(a int, n *gc.Node) {
gins(jmptoset(a), nil, n)
}
-/*
- * set up nodes representing 2^63
- */
-var bigi gc.Node
-
-var bigf gc.Node
-
-var bignodes_did int
+// set up nodes representing 2^63
+var (
+ bigi gc.Node
+ bigf gc.Node
+ bignodes_did bool
+)
func bignodes() {
- if bignodes_did != 0 {
+ if bignodes_did {
return
}
- bignodes_did = 1
+ bignodes_did = true
+
+ var i big.Int
+ i.SetInt64(1)
+ i.Lsh(&i, 63)
- gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 1)
- gc.Mpshiftfix(bigi.Val.U.Xval, 63)
+ gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
+ bigi.SetBigInt(&i)
- bigf = bigi
- bigf.Type = gc.Types[gc.TFLOAT64]
- bigf.Val.Ctype = gc.CTFLT
- bigf.Val.U.Fval = new(gc.Mpflt)
- gc.Mpmovefixflt(bigf.Val.U.Fval, bigi.Val.U.Xval)
+ bigi.Convconst(&bigf, gc.Types[gc.TFLOAT64])
}
/*
@@ -156,7 +191,7 @@ func gmove(f *gc.Node, t *gc.Node) {
// convert constant to desired type
if f.Op == gc.OLITERAL {
var con gc.Node
- gc.Convconst(&con, t.Type, &f.Val)
+ f.Convconst(&con, t.Type)
f = &con
ft = tt // so big switch will choose a simple mov
@@ -170,10 +205,7 @@ func gmove(f *gc.Node, t *gc.Node) {
// 64-bit immediates are really 32-bit sign-extended
// unless moving into a register.
if gc.Isint[tt] {
- if gc.Mpcmpfixfix(con.Val.U.Xval, gc.Minintval[gc.TINT32]) < 0 {
- goto hard
- }
- if gc.Mpcmpfixfix(con.Val.U.Xval, gc.Maxintval[gc.TINT32]) > 0 {
+ if i := con.Int(); int64(int32(i)) != i {
goto hard
}
}
@@ -1237,7 +1269,7 @@ func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
if !gc.Isconst(n, gc.CTINT) {
break
}
- v := gc.Mpgetfix(n.Val.U.Xval)
+ v := n.Int()
if v >= 32000 || v <= -32000 {
break
}
diff --git a/src/cmd/6g/peep.go b/src/cmd/compile/internal/amd64/peep.go
index cd07199ed1..19db68e944 100644
--- a/src/cmd/6g/peep.go
+++ b/src/cmd/compile/internal/amd64/peep.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package amd64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
"fmt"
diff --git a/src/cmd/6g/prog.go b/src/cmd/compile/internal/amd64/prog.go
index 5f604742c3..00918c8691 100644
--- a/src/cmd/6g/prog.go
+++ b/src/cmd/compile/internal/amd64/prog.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package amd64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
diff --git a/src/cmd/6g/reg.go b/src/cmd/compile/internal/amd64/reg.go
index cab07b5b4e..7d4f40641d 100644
--- a/src/cmd/6g/reg.go
+++ b/src/cmd/compile/internal/amd64/reg.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package amd64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
diff --git a/src/cmd/5g/cgen.go b/src/cmd/compile/internal/arm/cgen.go
index 2e922391cb..8ea6c5f3f2 100644
--- a/src/cmd/5g/cgen.go
+++ b/src/cmd/compile/internal/arm/cgen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package arm
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm"
)
@@ -53,28 +53,6 @@ func igenindex(n *gc.Node, res *gc.Node, bounded bool) *obj.Prog {
return cgenindex(n, res, bounded)
}
-func gencmp0(n *gc.Node, t *gc.Type, o int, likely int, to *obj.Prog) {
- var n1 gc.Node
-
- gc.Regalloc(&n1, t, nil)
- gc.Cgen(n, &n1)
- a := optoas(gc.OCMP, t)
- if a != arm.ACMP {
- var n2 gc.Node
- gc.Nodconst(&n2, t, 0)
- var n3 gc.Node
- gc.Regalloc(&n3, t, nil)
- gmove(&n2, &n3)
- gins(a, &n1, &n3)
- gc.Regfree(&n3)
- } else {
- gins(arm.ATST, &n1, nil)
- }
- a = optoas(o, t)
- gc.Patch(gc.Gbranch(a, t, likely), to)
- gc.Regfree(&n1)
-}
-
func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
// determine alignment.
// want to avoid unaligned access, so have to use
diff --git a/src/cmd/5g/cgen64.go b/src/cmd/compile/internal/arm/cgen64.go
index 699e555f71..6c88b76e20 100644
--- a/src/cmd/5g/cgen64.go
+++ b/src/cmd/compile/internal/arm/cgen64.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package arm
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm"
)
@@ -237,7 +237,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
// shld hi:lo, c
// shld lo:t, c
case gc.OLROT:
- v := uint64(gc.Mpgetfix(r.Val.U.Xval))
+ v := uint64(r.Int())
var bl gc.Node
gc.Regalloc(&bl, lo1.Type, nil)
@@ -291,7 +291,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
var p4 *obj.Prog
var p5 *obj.Prog
if r.Op == gc.OLITERAL {
- v := uint64(gc.Mpgetfix(r.Val.U.Xval))
+ v := uint64(r.Int())
if v >= 64 {
// TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
// here and below (verify it optimizes to EOR)
@@ -452,7 +452,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
var creg gc.Node
var p3 *obj.Prog
if r.Op == gc.OLITERAL {
- v := uint64(gc.Mpgetfix(r.Val.U.Xval))
+ v := uint64(r.Int())
if v >= 64 {
if bh.Type.Etype == gc.TINT32 {
// MOVW bh->31, al
diff --git a/src/cmd/5g/galign.go b/src/cmd/compile/internal/arm/galign.go
index 3c8ba519eb..60a39d3fe4 100644
--- a/src/cmd/5g/galign.go
+++ b/src/cmd/compile/internal/arm/galign.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package arm
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm"
)
@@ -37,7 +37,7 @@ func betypeinit() {
gc.Widthreg = 4
}
-func main() {
+func Main() {
gc.Thearch.Thechar = thechar
gc.Thearch.Thestring = thestring
gc.Thearch.Thelinkarch = thelinkarch
@@ -65,6 +65,7 @@ func main() {
gc.Thearch.Expandchecks = expandchecks
gc.Thearch.Getg = getg
gc.Thearch.Gins = gins
+ gc.Thearch.Ginscmp = ginscmp
gc.Thearch.Ginscon = ginscon
gc.Thearch.Ginsnop = ginsnop
gc.Thearch.Gmove = gmove
diff --git a/src/cmd/5g/ggen.go b/src/cmd/compile/internal/arm/ggen.go
index 0cf0d9299c..6633351032 100644
--- a/src/cmd/5g/ggen.go
+++ b/src/cmd/compile/internal/arm/ggen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package arm
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm"
)
@@ -30,7 +30,7 @@ func defframe(ptxt *obj.Prog) {
r0 := uint32(0)
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
n = l.N
- if !n.Needzero {
+ if !n.Name.Needzero {
continue
}
if n.Class != gc.PAUTO {
@@ -183,7 +183,7 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
w := int(nl.Type.Width * 8)
if op == gc.OLROT {
- v := int(gc.Mpgetfix(nr.Val.U.Xval))
+ v := nr.Int()
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, res)
if w == 32 {
@@ -210,7 +210,7 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, res)
gc.Cgen(nl, &n1)
- sc := uint64(gc.Mpgetfix(nr.Val.U.Xval))
+ sc := uint64(nr.Int())
if sc == 0 {
} else // nothing to do
if sc >= uint64(nl.Type.Width*8) {
@@ -479,6 +479,32 @@ func ginscon(as int, c int64, n *gc.Node) {
gc.Regfree(&n2)
}
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+ if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n1.Int() == 0 && n2.Op != gc.OLITERAL {
+ op = gc.Brrev(op)
+ n1, n2 = n2, n1
+ }
+ var r1, r2, g1, g2 gc.Node
+ gc.Regalloc(&r1, t, n1)
+ gc.Regalloc(&g1, n1.Type, &r1)
+ gc.Cgen(n1, &g1)
+ gmove(&g1, &r1)
+ if gc.Isint[t.Etype] && n2.Op == gc.OLITERAL && n2.Int() == 0 {
+ gins(arm.ACMP, &r1, n2)
+ } else {
+ gc.Regalloc(&r2, t, n2)
+ gc.Regalloc(&g2, n1.Type, &r2)
+ gc.Cgen(n2, &g2)
+ gmove(&g2, &r2)
+ gins(optoas(gc.OCMP, t), &r1, &r2)
+ gc.Regfree(&g2)
+ gc.Regfree(&r2)
+ }
+ gc.Regfree(&g1)
+ gc.Regfree(&r1)
+ return gc.Gbranch(optoas(op, t), nil, likely)
+}
+
// addr += index*width if possible.
func addindex(index *gc.Node, width int64, addr *gc.Node) bool {
switch width {
diff --git a/src/cmd/5g/gsubr.go b/src/cmd/compile/internal/arm/gsubr.go
index 57d511e6f6..5263f15ac2 100644
--- a/src/cmd/5g/gsubr.go
+++ b/src/cmd/compile/internal/arm/gsubr.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm"
"fmt"
@@ -53,7 +53,7 @@ func ncon(i uint32) *gc.Node {
if ncon_n.Type == nil {
gc.Nodconst(&ncon_n, gc.Types[gc.TUINT32], 0)
}
- gc.Mpmovecfix(ncon_n.Val.U.Xval, int64(i))
+ ncon_n.SetInt(int64(i))
return &ncon_n
}
@@ -89,7 +89,7 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
case gc.ONAME:
if n.Class == gc.PPARAMREF {
var n1 gc.Node
- gc.Cgen(n.Heapaddr, &n1)
+ gc.Cgen(n.Name.Heapaddr, &n1)
sclean[nsclean-1] = n1
n = &n1
}
@@ -111,8 +111,8 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
case gc.OLITERAL:
var n1 gc.Node
- gc.Convconst(&n1, n.Type, &n.Val)
- i := gc.Mpgetfix(n1.Val.U.Xval)
+ n.Convconst(&n1, n.Type)
+ i := n1.Int()
gc.Nodconst(lo, gc.Types[gc.TUINT32], int64(uint32(i)))
i >>= 32
if n.Type.Etype == gc.TINT64 {
@@ -160,12 +160,12 @@ func gmove(f *gc.Node, t *gc.Node) {
var con gc.Node
switch tt {
default:
- gc.Convconst(&con, t.Type, &f.Val)
+ f.Convconst(&con, t.Type)
case gc.TINT16,
gc.TINT8:
var con gc.Node
- gc.Convconst(&con, gc.Types[gc.TINT32], &f.Val)
+ f.Convconst(&con, gc.Types[gc.TINT32])
var r1 gc.Node
gc.Regalloc(&r1, con.Type, t)
gins(arm.AMOVW, &con, &r1)
@@ -176,7 +176,7 @@ func gmove(f *gc.Node, t *gc.Node) {
case gc.TUINT16,
gc.TUINT8:
var con gc.Node
- gc.Convconst(&con, gc.Types[gc.TUINT32], &f.Val)
+ f.Convconst(&con, gc.Types[gc.TUINT32])
var r1 gc.Node
gc.Regalloc(&r1, con.Type, t)
gins(arm.AMOVW, &con, &r1)
@@ -1118,7 +1118,7 @@ func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
if !gc.Isconst(n, gc.CTINT) {
break
}
- v := gc.Mpgetfix(n.Val.U.Xval)
+ v := n.Int()
if v >= 32000 || v <= -32000 {
break
}
diff --git a/src/cmd/5g/peep.go b/src/cmd/compile/internal/arm/peep.go
index b76719d74e..66eba417c0 100644
--- a/src/cmd/5g/peep.go
+++ b/src/cmd/compile/internal/arm/peep.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm"
"fmt"
diff --git a/src/cmd/5g/prog.go b/src/cmd/compile/internal/arm/prog.go
index c472cdf042..cdf9d29192 100644
--- a/src/cmd/5g/prog.go
+++ b/src/cmd/compile/internal/arm/prog.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package arm
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm"
)
diff --git a/src/cmd/5g/reg.go b/src/cmd/compile/internal/arm/reg.go
index 2afdf12416..b72ccc9815 100644
--- a/src/cmd/5g/reg.go
+++ b/src/cmd/compile/internal/arm/reg.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm
import "cmd/internal/obj/arm"
-import "cmd/internal/gc"
+import "cmd/compile/internal/gc"
const (
NREGVAR = 32
diff --git a/src/cmd/7g/cgen.go b/src/cmd/compile/internal/arm64/cgen.go
index 6f268b4185..30326d73e2 100644
--- a/src/cmd/7g/cgen.go
+++ b/src/cmd/compile/internal/arm64/cgen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package arm64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm64"
)
diff --git a/src/cmd/7g/galign.go b/src/cmd/compile/internal/arm64/galign.go
index 34b4ab6142..38def8f5a4 100644
--- a/src/cmd/7g/galign.go
+++ b/src/cmd/compile/internal/arm64/galign.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package arm64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm64"
)
@@ -37,7 +37,7 @@ func betypeinit() {
gc.Widthreg = 8
}
-func main() {
+func Main() {
gc.Thearch.Thechar = thechar
gc.Thearch.Thestring = thestring
gc.Thearch.Thelinkarch = thelinkarch
@@ -65,6 +65,7 @@ func main() {
gc.Thearch.Expandchecks = expandchecks
gc.Thearch.Getg = getg
gc.Thearch.Gins = gins
+ gc.Thearch.Ginscmp = ginscmp
gc.Thearch.Ginscon = ginscon
gc.Thearch.Ginsnop = ginsnop
gc.Thearch.Gmove = gmove
diff --git a/src/cmd/7g/ggen.go b/src/cmd/compile/internal/arm64/ggen.go
index b824a3a18c..851ca4e30f 100644
--- a/src/cmd/7g/ggen.go
+++ b/src/cmd/compile/internal/arm64/ggen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package arm64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm64"
"fmt"
@@ -32,7 +32,7 @@ func defframe(ptxt *obj.Prog) {
// iterate through declarations - they are sorted in decreasing xoffset order.
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
n = l.N
- if !n.Needzero {
+ if !n.Name.Needzero {
continue
}
if n.Class != gc.PAUTO {
@@ -147,9 +147,9 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
check := 0
if gc.Issigned[t.Etype] {
check = 1
- if gc.Isconst(nl, gc.CTINT) && gc.Mpgetfix(nl.Val.U.Xval) != -(1<<uint64(t.Width*8-1)) {
+ if gc.Isconst(nl, gc.CTINT) && nl.Int() != -(1<<uint64(t.Width*8-1)) {
check = 0
- } else if gc.Isconst(nr, gc.CTINT) && gc.Mpgetfix(nr.Val.U.Xval) != -1 {
+ } else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
check = 0
}
}
@@ -312,7 +312,7 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, res)
gc.Cgen(nl, &n1)
- sc := uint64(uint64(gc.Mpgetfix(nr.Val.U.Xval)))
+ sc := uint64(nr.Int())
if sc >= uint64(nl.Type.Width*8) {
// large shift gets 2 shifts by width-1
var n3 gc.Node
diff --git a/src/cmd/7g/gsubr.go b/src/cmd/compile/internal/arm64/gsubr.go
index a34a4306ae..0a14654d83 100644
--- a/src/cmd/7g/gsubr.go
+++ b/src/cmd/compile/internal/arm64/gsubr.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm64"
"fmt"
@@ -102,6 +102,34 @@ func ginscon2(as int, n2 *gc.Node, c int64) {
gc.Regfree(&ntmp)
}
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+ if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
+ // Reverse comparison to place constant last.
+ op = gc.Brrev(op)
+ n1, n2 = n2, n1
+ }
+
+ var r1, r2, g1, g2 gc.Node
+ gc.Regalloc(&r1, t, n1)
+ gc.Regalloc(&g1, n1.Type, &r1)
+ gc.Cgen(n1, &g1)
+ gmove(&g1, &r1)
+ if gc.Isint[t.Etype] && gc.Isconst(n2, gc.CTINT) {
+ ginscon2(optoas(gc.OCMP, t), &r1, n2.Int())
+ } else {
+ gc.Regalloc(&r2, t, n2)
+ gc.Regalloc(&g2, n1.Type, &r2)
+ gc.Cgen(n2, &g2)
+ gmove(&g2, &r2)
+ gcmp(optoas(gc.OCMP, t), &r1, &r2)
+ gc.Regfree(&g2)
+ gc.Regfree(&r2)
+ }
+ gc.Regfree(&g1)
+ gc.Regfree(&r1)
+ return gc.Gbranch(optoas(op, t), nil, likely)
+}
+
/*
* generate move:
* t = f
@@ -133,13 +161,13 @@ func gmove(f *gc.Node, t *gc.Node) {
var con gc.Node
switch tt {
default:
- gc.Convconst(&con, t.Type, &f.Val)
+ f.Convconst(&con, t.Type)
case gc.TINT32,
gc.TINT16,
gc.TINT8:
var con gc.Node
- gc.Convconst(&con, gc.Types[gc.TINT64], &f.Val)
+ f.Convconst(&con, gc.Types[gc.TINT64])
var r1 gc.Node
gc.Regalloc(&r1, con.Type, t)
gins(arm64.AMOVD, &con, &r1)
@@ -151,7 +179,7 @@ func gmove(f *gc.Node, t *gc.Node) {
gc.TUINT16,
gc.TUINT8:
var con gc.Node
- gc.Convconst(&con, gc.Types[gc.TUINT64], &f.Val)
+ f.Convconst(&con, gc.Types[gc.TUINT64])
var r1 gc.Node
gc.Regalloc(&r1, con.Type, t)
gins(arm64.AMOVD, &con, &r1)
@@ -440,14 +468,13 @@ hard:
}
func intLiteral(n *gc.Node) (x int64, ok bool) {
- if n == nil || n.Op != gc.OLITERAL {
+ switch {
+ case n == nil:
return
- }
- switch n.Val.Ctype {
- case gc.CTINT, gc.CTRUNE:
- return gc.Mpgetfix(n.Val.U.Xval), true
- case gc.CTBOOL:
- return int64(obj.Bool2int(n.Val.U.Bval)), true
+ case gc.Isconst(n, gc.CTINT):
+ return n.Int(), true
+ case gc.Isconst(n, gc.CTBOOL):
+ return int64(obj.Bool2int(n.Bool())), true
}
return
}
diff --git a/src/cmd/7g/peep.go b/src/cmd/compile/internal/arm64/peep.go
index 49bc69b132..3dbccb70b2 100644
--- a/src/cmd/7g/peep.go
+++ b/src/cmd/compile/internal/arm64/peep.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm64"
"fmt"
@@ -422,9 +422,9 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
// 7g never generates a from3
fmt.Printf("copyu: from3 (%v) not implemented\n", gc.Ctxt.Dconv(&p.From3))
}
- if p.To2.Type != obj.TYPE_NONE {
+ if p.RegTo2 != obj.REG_NONE {
// 7g never generates a to2
- fmt.Printf("copyu: to2 (%v) not implemented\n", gc.Ctxt.Dconv(&p.To2))
+ fmt.Printf("copyu: RegTo2 (%v) not implemented\n", obj.Rconv(int(p.RegTo2)))
}
switch p.As {
diff --git a/src/cmd/7g/prog.go b/src/cmd/compile/internal/arm64/prog.go
index 023f302e14..1106e788a5 100644
--- a/src/cmd/7g/prog.go
+++ b/src/cmd/compile/internal/arm64/prog.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package arm64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/arm64"
)
diff --git a/src/cmd/7g/reg.go b/src/cmd/compile/internal/arm64/reg.go
index 0e5ac73499..7bc756b7bf 100644
--- a/src/cmd/7g/reg.go
+++ b/src/cmd/compile/internal/arm64/reg.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj/arm64"
)
diff --git a/src/cmd/internal/gc/big/accuracy_string.go b/src/cmd/compile/internal/big/accuracy_string.go
index 24ef7f1077..24ef7f1077 100644
--- a/src/cmd/internal/gc/big/accuracy_string.go
+++ b/src/cmd/compile/internal/big/accuracy_string.go
diff --git a/src/cmd/internal/gc/big/arith.go b/src/cmd/compile/internal/big/arith.go
index 328c85c4f7..1ff6349d9d 100644
--- a/src/cmd/internal/gc/big/arith.go
+++ b/src/cmd/compile/internal/big/arith.go
@@ -196,7 +196,6 @@ func subVV_g(z, x, y []Word) (c Word) {
return
}
-// Argument y must be either 0 or 1.
// The resulting carry c is either 0 or 1.
func addVW_g(z, x []Word, y Word) (c Word) {
if use_addWW_g {
diff --git a/src/cmd/internal/gc/big/arith_decl.go b/src/cmd/compile/internal/big/arith_decl.go
index fe13577203..fe13577203 100644
--- a/src/cmd/internal/gc/big/arith_decl.go
+++ b/src/cmd/compile/internal/big/arith_decl.go
diff --git a/src/cmd/internal/gc/big/arith_test.go b/src/cmd/compile/internal/big/arith_test.go
index cd92dd7173..f46a494f17 100644
--- a/src/cmd/internal/gc/big/arith_test.go
+++ b/src/cmd/compile/internal/big/arith_test.go
@@ -155,6 +155,7 @@ var sumVW = []argVW{
{nat{1}, nat{1}, 0, 0},
{nat{0}, nat{_M}, 1, 1},
{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, 1, 1},
+ {nat{585}, nat{314}, 271, 0},
}
var prodVW = []argVW{
diff --git a/src/cmd/internal/gc/big/bits_test.go b/src/cmd/compile/internal/big/bits_test.go
index 3ce24222d7..3ce24222d7 100644
--- a/src/cmd/internal/gc/big/bits_test.go
+++ b/src/cmd/compile/internal/big/bits_test.go
diff --git a/src/cmd/internal/gc/big/calibrate_test.go b/src/cmd/compile/internal/big/calibrate_test.go
index f69ffbf5cf..f69ffbf5cf 100644
--- a/src/cmd/internal/gc/big/calibrate_test.go
+++ b/src/cmd/compile/internal/big/calibrate_test.go
diff --git a/src/cmd/internal/gc/big/decimal.go b/src/cmd/compile/internal/big/decimal.go
index 3d024dce68..3d024dce68 100644
--- a/src/cmd/internal/gc/big/decimal.go
+++ b/src/cmd/compile/internal/big/decimal.go
diff --git a/src/cmd/internal/gc/big/decimal_test.go b/src/cmd/compile/internal/big/decimal_test.go
index 81e022a47d..81e022a47d 100644
--- a/src/cmd/internal/gc/big/decimal_test.go
+++ b/src/cmd/compile/internal/big/decimal_test.go
diff --git a/src/cmd/internal/gc/big/example_test.go b/src/cmd/compile/internal/big/example_test.go
index 078be47f95..cb91bc23bd 100644
--- a/src/cmd/internal/gc/big/example_test.go
+++ b/src/cmd/compile/internal/big/example_test.go
@@ -5,9 +5,9 @@
package big_test
import (
+ "cmd/compile/internal/big"
"fmt"
"log"
- "math/big"
)
func ExampleRat_SetString() {
diff --git a/src/cmd/internal/gc/big/float.go b/src/cmd/compile/internal/big/float.go
index ed55e8e513..dcb72c5754 100644
--- a/src/cmd/internal/gc/big/float.go
+++ b/src/cmd/compile/internal/big/float.go
@@ -65,12 +65,16 @@ type Float struct {
exp int32
}
-// Float operations that would lead to a NaN under IEEE-754 rules cause
-// a run-time panic of ErrNaN type.
+// An ErrNaN panic is raised by a Float operation that would lead to
+// a NaN under IEEE-754 rules. An ErrNaN implements the error interface.
type ErrNaN struct {
msg string
}
+func (err ErrNaN) Error() string {
+ return err.msg
+}
+
// NewFloat allocates and returns a new Float set to x,
// with precision 53 and rounding mode ToNearestEven.
// NewFloat panics with ErrNaN if x is a NaN.
@@ -849,9 +853,6 @@ func (x *Float) Int64() (int64, Accuracy) {
panic("unreachable")
}
-// TODO(gri) Float32 and Float64 are very similar internally but for the
-// floatxx parameters and some conversions. Should factor out shared code.
-
// Float32 returns the float32 value nearest to x. If x is too small to be
// represented by a float32 (|x| < math.SmallestNonzeroFloat32), the result
// is (0, Below) or (-0, Above), respectively, depending on the sign of x.
@@ -876,64 +877,70 @@ func (x *Float) Float32() (float32, Accuracy) {
emax = bias // 127 largest unbiased exponent (normal)
)
- // Float mantissae m have an explicit msb and are in the range 0.5 <= m < 1.0.
- // floatxx mantissae have an implicit msb and are in the range 1.0 <= m < 2.0.
- // For a given mantissa m, we need to add 1 to a floatxx exponent to get the
- // corresponding Float exponent.
- // (see also implementation of math.Ldexp for similar code)
+ // Float mantissa m is 0.5 <= m < 1.0; compute exponent for floatxx mantissa.
+ e := x.exp - 1 // exponent for mantissa m with 1.0 <= m < 2.0
+ p := mbits + 1 // precision of normal float
- if x.exp < dmin+1 {
- // underflow
- if x.neg {
- var z float32
- return -z, Above
+ // If the exponent is too small, we may have a denormal number
+ // in which case we have fewer mantissa bits available: reduce
+ // precision accordingly.
+ if e < emin {
+ p -= emin - int(e)
+ // Make sure we have at least 1 bit so that we don't
+ // lose numbers rounded up to the smallest denormal.
+ if p < 1 {
+ p = 1
}
- return 0.0, Below
}
- // x.exp >= dmin+1
+ // round
var r Float
- r.prec = mbits + 1 // +1 for implicit msb
- if x.exp < emin+1 {
- // denormal number - round to fewer bits
- r.prec = uint32(x.exp - dmin)
- }
+ r.prec = uint32(p)
r.Set(x)
+ e = r.exp - 1
// Rounding may have caused r to overflow to ±Inf
// (rounding never causes underflows to 0).
if r.form == inf {
- r.exp = emax + 2 // cause overflow below
+ e = emax + 1 // cause overflow below
}
- if r.exp > emax+1 {
+ // If the exponent is too large, overflow to ±Inf.
+ if e > emax {
// overflow
if x.neg {
return float32(math.Inf(-1)), Below
}
return float32(math.Inf(+1)), Above
}
- // dmin+1 <= r.exp <= emax+1
- var s uint32
- if r.neg {
- s = 1 << (fbits - 1)
+ // Determine sign, biased exponent, and mantissa.
+ var sign, bexp, mant uint32
+ if x.neg {
+ sign = 1 << (fbits - 1)
}
- m := high32(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
-
// Rounding may have caused a denormal number to
// become normal. Check again.
- c := float32(1.0)
- if r.exp < emin+1 {
+ if e < emin {
// denormal number
- r.exp += mbits
- c = 1.0 / (1 << mbits) // 2**-mbits
+ if e < dmin {
+ // underflow to ±0
+ if x.neg {
+ var z float32
+ return -z, Above
+ }
+ return 0.0, Below
+ }
+ // bexp = 0
+ mant = high32(r.mant) >> (fbits - r.prec)
+ } else {
+ // normal number: emin <= e <= emax
+ bexp = uint32(e+bias) << mbits
+ mant = high32(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
}
- // emin+1 <= r.exp <= emax+1
- e := uint32(r.exp-emin) << mbits
- return c * math.Float32frombits(s|e|m), r.acc
+ return math.Float32frombits(sign | bexp | mant), r.acc
case zero:
if x.neg {
@@ -976,64 +983,70 @@ func (x *Float) Float64() (float64, Accuracy) {
emax = bias // 1023 largest unbiased exponent (normal)
)
- // Float mantissae m have an explicit msb and are in the range 0.5 <= m < 1.0.
- // floatxx mantissae have an implicit msb and are in the range 1.0 <= m < 2.0.
- // For a given mantissa m, we need to add 1 to a floatxx exponent to get the
- // corresponding Float exponent.
- // (see also implementation of math.Ldexp for similar code)
+ // Float mantissa m is 0.5 <= m < 1.0; compute exponent for floatxx mantissa.
+ e := x.exp - 1 // exponent for mantissa m with 1.0 <= m < 2.0
+ p := mbits + 1 // precision of normal float
- if x.exp < dmin+1 {
- // underflow
- if x.neg {
- var z float64
- return -z, Above
+ // If the exponent is too small, we may have a denormal number
+ // in which case we have fewer mantissa bits available: reduce
+ // precision accordingly.
+ if e < emin {
+ p -= emin - int(e)
+ // Make sure we have at least 1 bit so that we don't
+ // lose numbers rounded up to the smallest denormal.
+ if p < 1 {
+ p = 1
}
- return 0.0, Below
}
- // x.exp >= dmin+1
+ // round
var r Float
- r.prec = mbits + 1 // +1 for implicit msb
- if x.exp < emin+1 {
- // denormal number - round to fewer bits
- r.prec = uint32(x.exp - dmin)
- }
+ r.prec = uint32(p)
r.Set(x)
+ e = r.exp - 1
// Rounding may have caused r to overflow to ±Inf
// (rounding never causes underflows to 0).
if r.form == inf {
- r.exp = emax + 2 // cause overflow below
+ e = emax + 1 // cause overflow below
}
- if r.exp > emax+1 {
+ // If the exponent is too large, overflow to ±Inf.
+ if e > emax {
// overflow
if x.neg {
return math.Inf(-1), Below
}
return math.Inf(+1), Above
}
- // dmin+1 <= r.exp <= emax+1
- var s uint64
- if r.neg {
- s = 1 << (fbits - 1)
+ // Determine sign, biased exponent, and mantissa.
+ var sign, bexp, mant uint64
+ if x.neg {
+ sign = 1 << (fbits - 1)
}
- m := high64(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
-
// Rounding may have caused a denormal number to
// become normal. Check again.
- c := 1.0
- if r.exp < emin+1 {
+ if e < emin {
// denormal number
- r.exp += mbits
- c = 1.0 / (1 << mbits) // 2**-mbits
+ if e < dmin {
+ // underflow to ±0
+ if x.neg {
+ var z float64
+ return -z, Above
+ }
+ return 0.0, Below
+ }
+ // bexp = 0
+ mant = high64(r.mant) >> (fbits - r.prec)
+ } else {
+ // normal number: emin <= e <= emax
+ bexp = uint64(e+bias) << mbits
+ mant = high64(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
}
- // emin+1 <= r.exp <= emax+1
- e := uint64(r.exp-emin) << mbits
- return c * math.Float64frombits(s|e|m), r.acc
+ return math.Float64frombits(sign | bexp | mant), r.acc
case zero:
if x.neg {
diff --git a/src/cmd/internal/gc/big/float_test.go b/src/cmd/compile/internal/big/float_test.go
index 2a48ec4465..8bd3a9c8c9 100644
--- a/src/cmd/internal/gc/big/float_test.go
+++ b/src/cmd/compile/internal/big/float_test.go
@@ -12,6 +12,9 @@ import (
"testing"
)
+// Verify that ErrNaN implements the error interface.
+var _ error = ErrNaN{}
+
func (x *Float) uint64() uint64 {
u, acc := x.Uint64()
if acc != Exact {
@@ -200,6 +203,18 @@ func alike(x, y *Float) bool {
return x.Cmp(y) == 0 && x.Signbit() == y.Signbit()
}
+func alike32(x, y float32) bool {
+ // we can ignore NaNs
+ return x == y && math.Signbit(float64(x)) == math.Signbit(float64(y))
+
+}
+
+func alike64(x, y float64) bool {
+ // we can ignore NaNs
+ return x == y && math.Signbit(x) == math.Signbit(y)
+
+}
+
func TestFloatMantExp(t *testing.T) {
for _, test := range []struct {
x string
@@ -825,52 +840,69 @@ func TestFloatFloat32(t *testing.T) {
out float32
acc Accuracy
}{
- {"-Inf", float32(math.Inf(-1)), Exact},
- {"-0x1.ffffff0p2147483646", float32(-math.Inf(+1)), Below}, // overflow in rounding
- {"-1e10000", float32(math.Inf(-1)), Below}, // overflow
- {"-0x1p128", float32(math.Inf(-1)), Below}, // overflow
- {"-0x1.ffffff0p127", float32(-math.Inf(+1)), Below}, // overflow
- {"-0x1.fffffe8p127", -math.MaxFloat32, Above},
- {"-0x1.fffffe0p127", -math.MaxFloat32, Exact},
- {"-12345.000000000000000000001", -12345, Above},
- {"-12345.0", -12345, Exact},
- {"-1.000000000000000000001", -1, Above},
- {"-1", -1, Exact},
- {"-0x0.000002p-126", -math.SmallestNonzeroFloat32, Exact},
- {"-0x0.000002p-127", -0, Above}, // underflow
- {"-1e-1000", -0, Above}, // underflow
{"0", 0, Exact},
- {"1e-1000", 0, Below}, // underflow
- {"0x0.000002p-127", 0, Below}, // underflow
- {"0x0.000002p-126", math.SmallestNonzeroFloat32, Exact},
+
+ // underflow
+ {"1e-1000", 0, Below},
+ {"0x0.000002p-127", 0, Below},
+ {"0x.0000010p-126", 0, Below},
+
+ // denormals
+ {"1.401298464e-45", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
+ {"0x.ffffff8p-149", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
+ {"0x.0000018p-126", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal
+ {"0x.0000020p-126", math.SmallestNonzeroFloat32, Exact},
+ {"0x.8p-148", math.SmallestNonzeroFloat32, Exact},
+ {"1p-149", math.SmallestNonzeroFloat32, Exact},
+ {"0x.fffffep-126", math.Float32frombits(0x7fffff), Exact}, // largest denormal
+
+ // normals
+ {"0x.ffffffp-126", math.Float32frombits(0x00800000), Above}, // rounded up to smallest normal
+ {"1p-126", math.Float32frombits(0x00800000), Exact}, // smallest normal
+ {"0x1.fffffep-126", math.Float32frombits(0x00ffffff), Exact},
+ {"0x1.ffffffp-126", math.Float32frombits(0x01000000), Above}, // rounded up
{"1", 1, Exact},
{"1.000000000000000000001", 1, Below},
{"12345.0", 12345, Exact},
{"12345.000000000000000000001", 12345, Below},
{"0x1.fffffe0p127", math.MaxFloat32, Exact},
{"0x1.fffffe8p127", math.MaxFloat32, Below},
- {"0x1.ffffff0p127", float32(math.Inf(+1)), Above}, // overflow
- {"0x1p128", float32(math.Inf(+1)), Above}, // overflow
- {"1e10000", float32(math.Inf(+1)), Above}, // overflow
+
+ // overflow
+ {"0x1.ffffff0p127", float32(math.Inf(+1)), Above},
+ {"0x1p128", float32(math.Inf(+1)), Above},
+ {"1e10000", float32(math.Inf(+1)), Above},
{"0x1.ffffff0p2147483646", float32(math.Inf(+1)), Above}, // overflow in rounding
- {"+Inf", float32(math.Inf(+1)), Exact},
+
+ // inf
+ {"Inf", float32(math.Inf(+1)), Exact},
} {
- // conversion should match strconv where syntax is agreeable
- if f, err := strconv.ParseFloat(test.x, 32); err == nil && float32(f) != test.out {
- t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out)
- }
+ for i := 0; i < 2; i++ {
+ // test both signs
+ tx, tout, tacc := test.x, test.out, test.acc
+ if i != 0 {
+ tx = "-" + tx
+ tout = -tout
+ tacc = -tacc
+ }
- x := makeFloat(test.x)
- out, acc := x.Float32()
- if out != test.out || acc != test.acc {
- t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), test.acc)
- }
+ // conversion should match strconv where syntax is agreeable
+ if f, err := strconv.ParseFloat(tx, 32); err == nil && !alike32(float32(f), tout) {
+ t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout)
+ }
+
+ x := makeFloat(tx)
+ out, acc := x.Float32()
+ if !alike32(out, tout) || acc != tacc {
+ t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", tx, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), tacc)
+ }
- // test that x.SetFloat64(float64(f)).Float32() == f
- var x2 Float
- out2, acc2 := x2.SetFloat64(float64(out)).Float32()
- if out2 != out || acc2 != Exact {
- t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
+ // test that x.SetFloat64(float64(f)).Float32() == f
+ var x2 Float
+ out2, acc2 := x2.SetFloat64(float64(out)).Float32()
+ if !alike32(out2, out) || acc2 != Exact {
+ t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
+ }
}
}
}
@@ -882,35 +914,36 @@ func TestFloatFloat64(t *testing.T) {
out float64
acc Accuracy
}{
- {"-Inf", math.Inf(-1), Exact},
- {"-0x1.fffffffffffff8p2147483646", -math.Inf(+1), Below}, // overflow in rounding
- {"-1e10000", math.Inf(-1), Below}, // overflow
- {"-0x1p1024", math.Inf(-1), Below}, // overflow
- {"-0x1.fffffffffffff8p1023", -math.Inf(+1), Below}, // overflow
- {"-0x1.fffffffffffff4p1023", -math.MaxFloat64, Above},
- {"-0x1.fffffffffffff0p1023", -math.MaxFloat64, Exact},
- {"-12345.000000000000000000001", -12345, Above},
- {"-12345.0", -12345, Exact},
- {"-1.000000000000000000001", -1, Above},
- {"-1", -1, Exact},
- {"-0x0.0000000000001p-1022", -math.SmallestNonzeroFloat64, Exact},
- {"-0x0.0000000000001p-1023", -0, Above}, // underflow
- {"-1e-1000", -0, Above}, // underflow
{"0", 0, Exact},
- {"1e-1000", 0, Below}, // underflow
- {"0x0.0000000000001p-1023", 0, Below}, // underflow
- {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64, Exact},
+
+ // underflow
+ {"1e-1000", 0, Below},
+ {"0x0.0000000000001p-1023", 0, Below},
+ {"0x0.00000000000008p-1022", 0, Below},
+
+ // denormals
+ {"0x0.0000000000000cp-1022", math.SmallestNonzeroFloat64, Above}, // rounded up to smallest denormal
+ {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64, Exact}, // smallest denormal
+ {"0x.8p-1073", math.SmallestNonzeroFloat64, Exact},
+ {"1p-1074", math.SmallestNonzeroFloat64, Exact},
+ {"0x.fffffffffffffp-1022", math.Float64frombits(0x000fffffffffffff), Exact}, // largest denormal
+
+ // normals
+ {"0x.fffffffffffff8p-1022", math.Float64frombits(0x0010000000000000), Above}, // rounded up to smallest normal
+ {"1p-1022", math.Float64frombits(0x0010000000000000), Exact}, // smallest normal
{"1", 1, Exact},
{"1.000000000000000000001", 1, Below},
{"12345.0", 12345, Exact},
{"12345.000000000000000000001", 12345, Below},
{"0x1.fffffffffffff0p1023", math.MaxFloat64, Exact},
{"0x1.fffffffffffff4p1023", math.MaxFloat64, Below},
- {"0x1.fffffffffffff8p1023", math.Inf(+1), Above}, // overflow
- {"0x1p1024", math.Inf(+1), Above}, // overflow
- {"1e10000", math.Inf(+1), Above}, // overflow
+
+ // overflow
+ {"0x1.fffffffffffff8p1023", math.Inf(+1), Above},
+ {"0x1p1024", math.Inf(+1), Above},
+ {"1e10000", math.Inf(+1), Above},
{"0x1.fffffffffffff8p2147483646", math.Inf(+1), Above}, // overflow in rounding
- {"+Inf", math.Inf(+1), Exact},
+ {"Inf", math.Inf(+1), Exact},
// selected denormalized values that were handled incorrectly in the past
{"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
@@ -921,22 +954,32 @@ func TestFloatFloat64(t *testing.T) {
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
{"2.2250738585072012e-308", 2.2250738585072014e-308, Above},
} {
- // conversion should match strconv where syntax is agreeable
- if f, err := strconv.ParseFloat(test.x, 64); err == nil && f != test.out {
- t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out)
- }
+ for i := 0; i < 2; i++ {
+ // test both signs
+ tx, tout, tacc := test.x, test.out, test.acc
+ if i != 0 {
+ tx = "-" + tx
+ tout = -tout
+ tacc = -tacc
+ }
- x := makeFloat(test.x)
- out, acc := x.Float64()
- if out != test.out || acc != test.acc {
- t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), test.acc)
- }
+ // conversion should match strconv where syntax is agreeable
+ if f, err := strconv.ParseFloat(tx, 64); err == nil && !alike64(f, tout) {
+ t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout)
+ }
- // test that x.SetFloat64(f).Float64() == f
- var x2 Float
- out2, acc2 := x2.SetFloat64(out).Float64()
- if out2 != out || acc2 != Exact {
- t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
+ x := makeFloat(tx)
+ out, acc := x.Float64()
+ if !alike64(out, tout) || acc != tacc {
+ t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", tx, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), tacc)
+ }
+
+ // test that x.SetFloat64(f).Float64() == f
+ var x2 Float
+ out2, acc2 := x2.SetFloat64(out).Float64()
+ if !alike64(out2, out) || acc2 != Exact {
+ t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
+ }
}
}
}
@@ -1656,7 +1699,7 @@ func TestFloatCmpSpecialValues(t *testing.T) {
want = +1
}
if got != want {
- t.Errorf("(%g).Cmp(%g) = %s; want %s", x, y, got, want)
+ t.Errorf("(%g).Cmp(%g) = %v; want %v", x, y, got, want)
}
}
}
diff --git a/src/cmd/internal/gc/big/floatconv.go b/src/cmd/compile/internal/big/floatconv.go
index b929d1202c..b929d1202c 100644
--- a/src/cmd/internal/gc/big/floatconv.go
+++ b/src/cmd/compile/internal/big/floatconv.go
diff --git a/src/cmd/internal/gc/big/floatconv_test.go b/src/cmd/compile/internal/big/floatconv_test.go
index 96c01eed81..96c01eed81 100644
--- a/src/cmd/internal/gc/big/floatconv_test.go
+++ b/src/cmd/compile/internal/big/floatconv_test.go
diff --git a/src/cmd/internal/gc/big/floatexample_test.go b/src/cmd/compile/internal/big/floatexample_test.go
index 7db10238bc..0ac9617c06 100644
--- a/src/cmd/internal/gc/big/floatexample_test.go
+++ b/src/cmd/compile/internal/big/floatexample_test.go
@@ -5,9 +5,9 @@
package big_test
import (
+ "cmd/compile/internal/big"
"fmt"
"math"
- "math/big"
)
func ExampleFloat_Add() {
diff --git a/src/cmd/internal/gc/big/ftoa.go b/src/cmd/compile/internal/big/ftoa.go
index 0a9edfd7b2..0a9edfd7b2 100644
--- a/src/cmd/internal/gc/big/ftoa.go
+++ b/src/cmd/compile/internal/big/ftoa.go
diff --git a/src/cmd/internal/gc/big/gcd_test.go b/src/cmd/compile/internal/big/gcd_test.go
index c0b9f58300..c0b9f58300 100644
--- a/src/cmd/internal/gc/big/gcd_test.go
+++ b/src/cmd/compile/internal/big/gcd_test.go
diff --git a/src/cmd/internal/gc/big/hilbert_test.go b/src/cmd/compile/internal/big/hilbert_test.go
index 1a84341b3c..1a84341b3c 100644
--- a/src/cmd/internal/gc/big/hilbert_test.go
+++ b/src/cmd/compile/internal/big/hilbert_test.go
diff --git a/src/cmd/internal/gc/big/int.go b/src/cmd/compile/internal/big/int.go
index 7b419bf688..5e3125375b 100644
--- a/src/cmd/internal/gc/big/int.go
+++ b/src/cmd/compile/internal/big/int.go
@@ -583,6 +583,124 @@ func (z *Int) ModInverse(g, n *Int) *Int {
return z
}
+// Jacobi returns the Jacobi symbol (x/y), either +1, -1, or 0.
+// The y argument must be an odd integer.
+func Jacobi(x, y *Int) int {
+ if len(y.abs) == 0 || y.abs[0]&1 == 0 {
+ panic(fmt.Sprintf("big: invalid 2nd argument to Int.Jacobi: need odd integer but got %s", y))
+ }
+
+ // We use the formulation described in chapter 2, section 2.4,
+ // "The Yacas Book of Algorithms":
+ // http://yacas.sourceforge.net/Algo.book.pdf
+
+ var a, b, c Int
+ a.Set(x)
+ b.Set(y)
+ j := 1
+
+ if b.neg {
+ if a.neg {
+ j = -1
+ }
+ b.neg = false
+ }
+
+ for {
+ if b.Cmp(intOne) == 0 {
+ return j
+ }
+ if len(a.abs) == 0 {
+ return 0
+ }
+ a.Mod(&a, &b)
+ if len(a.abs) == 0 {
+ return 0
+ }
+ // a > 0
+
+ // handle factors of 2 in 'a'
+ s := a.abs.trailingZeroBits()
+ if s&1 != 0 {
+ bmod8 := b.abs[0] & 7
+ if bmod8 == 3 || bmod8 == 5 {
+ j = -j
+ }
+ }
+ c.Rsh(&a, s) // a = 2^s*c
+
+ // swap numerator and denominator
+ if b.abs[0]&3 == 3 && c.abs[0]&3 == 3 {
+ j = -j
+ }
+ a.Set(&b)
+ b.Set(&c)
+ }
+}
+
+// ModSqrt sets z to a square root of x mod p if such a square root exists, and
+// returns z. The modulus p must be an odd prime. If x is not a square mod p,
+// ModSqrt leaves z unchanged and returns nil. This function panics if p is
+// not an odd integer.
+func (z *Int) ModSqrt(x, p *Int) *Int {
+ switch Jacobi(x, p) {
+ case -1:
+ return nil // x is not a square mod p
+ case 0:
+ return z.SetInt64(0) // sqrt(0) mod p = 0
+ case 1:
+ break
+ }
+ if x.neg || x.Cmp(p) >= 0 { // ensure 0 <= x < p
+ x = new(Int).Mod(x, p)
+ }
+
+ // Break p-1 into s*2^e such that s is odd.
+ var s Int
+ s.Sub(p, intOne)
+ e := s.abs.trailingZeroBits()
+ s.Rsh(&s, e)
+
+ // find some non-square n
+ var n Int
+ n.SetInt64(2)
+ for Jacobi(&n, p) != -1 {
+ n.Add(&n, intOne)
+ }
+
+ // Core of the Tonelli-Shanks algorithm. Follows the description in
+ // section 6 of "Square roots from 1; 24, 51, 10 to Dan Shanks" by Ezra
+ // Brown:
+ // https://www.maa.org/sites/default/files/pdf/upload_library/22/Polya/07468342.di020786.02p0470a.pdf
+ var y, b, g, t Int
+ y.Add(&s, intOne)
+ y.Rsh(&y, 1)
+ y.Exp(x, &y, p) // y = x^((s+1)/2)
+ b.Exp(x, &s, p) // b = x^s
+ g.Exp(&n, &s, p) // g = n^s
+ r := e
+ for {
+ // find the least m such that ord_p(b) = 2^m
+ var m uint
+ t.Set(&b)
+ for t.Cmp(intOne) != 0 {
+ t.Mul(&t, &t).Mod(&t, p)
+ m++
+ }
+
+ if m == 0 {
+ return z.Set(&y)
+ }
+
+ t.SetInt64(0).SetBit(&t, int(r-m-1), 1).Exp(&g, &t, p)
+ // t = g^(2^(r-m-1)) mod p
+ g.Mul(&t, &t).Mod(&g, p) // g = g^(2^(r-m)) mod p
+ y.Mul(&y, &t).Mod(&y, p)
+ b.Mul(&b, &g).Mod(&b, p)
+ r = m
+ }
+}
+
// Lsh sets z = x << n and returns z.
func (z *Int) Lsh(x *Int, n uint) *Int {
z.abs = z.abs.shl(x.abs, n)
diff --git a/src/cmd/internal/gc/big/int_test.go b/src/cmd/compile/internal/big/int_test.go
index a972a7249b..c19e88addb 100644
--- a/src/cmd/internal/gc/big/int_test.go
+++ b/src/cmd/compile/internal/big/int_test.go
@@ -525,6 +525,7 @@ var expTests = []struct {
{"1234", "-1", "1", "0"},
// misc
+ {"5", "1", "3", "2"},
{"5", "-7", "", "1"},
{"-5", "-7", "", "1"},
{"5", "0", "", "1"},
@@ -703,6 +704,13 @@ var primes = []string{
"230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593",
"5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993",
"203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123",
+
+ // ECC primes: http://tools.ietf.org/html/draft-ladd-safecurves-02
+ "3618502788666131106986593281521497120414687020801267626233049500247285301239", // Curve1174: 2^251-9
+ "57896044618658097711785492504343953926634992332820282019728792003956564819949", // Curve25519: 2^255-19
+ "9850501549098619803069760025035903451269934817616361666987073351061430442874302652853566563721228910201656997576599", // E-382: 2^382-105
+ "42307582002575910332922579714097346549017899709713998034217522897561970639123926132812109468141778230245837569601494931472367", // Curve41417: 2^414-17
+ "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", // E-521: 2^521-1
}
var composites = []string{
@@ -1248,6 +1256,136 @@ func TestModInverse(t *testing.T) {
}
}
+// testModSqrt is a helper for TestModSqrt,
+// which checks that ModSqrt can compute a square-root of elt^2.
+func testModSqrt(t *testing.T, elt, mod, sq, sqrt *Int) bool {
+ var sqChk, sqrtChk, sqrtsq Int
+ sq.Mul(elt, elt)
+ sq.Mod(sq, mod)
+ z := sqrt.ModSqrt(sq, mod)
+ if z != sqrt {
+ t.Errorf("ModSqrt returned wrong value %s", z)
+ }
+
+ // test ModSqrt arguments outside the range [0,mod)
+ sqChk.Add(sq, mod)
+ z = sqrtChk.ModSqrt(&sqChk, mod)
+ if z != &sqrtChk || z.Cmp(sqrt) != 0 {
+ t.Errorf("ModSqrt returned inconsistent value %s", z)
+ }
+ sqChk.Sub(sq, mod)
+ z = sqrtChk.ModSqrt(&sqChk, mod)
+ if z != &sqrtChk || z.Cmp(sqrt) != 0 {
+ t.Errorf("ModSqrt returned inconsistent value %s", z)
+ }
+
+ // make sure we actually got a square root
+ if sqrt.Cmp(elt) == 0 {
+ return true // we found the "desired" square root
+ }
+ sqrtsq.Mul(sqrt, sqrt) // make sure we found the "other" one
+ sqrtsq.Mod(&sqrtsq, mod)
+ return sq.Cmp(&sqrtsq) == 0
+}
+
+func TestModSqrt(t *testing.T) {
+ var elt, mod, modx4, sq, sqrt Int
+ r := rand.New(rand.NewSource(9))
+ for i, s := range primes[1:] { // skip 2, use only odd primes
+ mod.SetString(s, 10)
+ modx4.Lsh(&mod, 2)
+
+ // test a few random elements per prime
+ for x := 1; x < 5; x++ {
+ elt.Rand(r, &modx4)
+ elt.Sub(&elt, &mod) // test range [-mod, 3*mod)
+ if !testModSqrt(t, &elt, &mod, &sq, &sqrt) {
+ t.Errorf("#%d: failed (sqrt(e) = %s)", i, &sqrt)
+ }
+ }
+ }
+
+ // exhaustive test for small values
+ for n := 3; n < 100; n++ {
+ mod.SetInt64(int64(n))
+ if !mod.ProbablyPrime(10) {
+ continue
+ }
+ isSquare := make([]bool, n)
+
+ // test all the squares
+ for x := 1; x < n; x++ {
+ elt.SetInt64(int64(x))
+ if !testModSqrt(t, &elt, &mod, &sq, &sqrt) {
+ t.Errorf("#%d: failed (sqrt(%d,%d) = %s)", x, &elt, &mod, &sqrt)
+ }
+ isSquare[sq.Uint64()] = true
+ }
+
+ // test all non-squares
+ for x := 1; x < n; x++ {
+ sq.SetInt64(int64(x))
+ z := sqrt.ModSqrt(&sq, &mod)
+ if !isSquare[x] && z != nil {
+ t.Errorf("#%d: failed (sqrt(%d,%d) = nil)", x, &sqrt, &mod)
+ }
+ }
+ }
+}
+
+func TestJacobi(t *testing.T) {
+ testCases := []struct {
+ x, y int64
+ result int
+ }{
+ {0, 1, 1},
+ {0, -1, 1},
+ {1, 1, 1},
+ {1, -1, 1},
+ {0, 5, 0},
+ {1, 5, 1},
+ {2, 5, -1},
+ {-2, 5, -1},
+ {2, -5, -1},
+ {-2, -5, 1},
+ {3, 5, -1},
+ {5, 5, 0},
+ {-5, 5, 0},
+ {6, 5, 1},
+ {6, -5, 1},
+ {-6, 5, 1},
+ {-6, -5, -1},
+ }
+
+ var x, y Int
+
+ for i, test := range testCases {
+ x.SetInt64(test.x)
+ y.SetInt64(test.y)
+ expected := test.result
+ actual := Jacobi(&x, &y)
+ if actual != expected {
+ t.Errorf("#%d: Jacobi(%d, %d) = %d, but expected %d", i, test.x, test.y, actual, expected)
+ }
+ }
+}
+
+func TestJacobiPanic(t *testing.T) {
+ const failureMsg = "test failure"
+ defer func() {
+ msg := recover()
+ if msg == nil || msg == failureMsg {
+ panic(msg)
+ }
+ t.Log(msg)
+ }()
+ x := NewInt(1)
+ y := NewInt(2)
+ // Jacobi should panic when the second argument is even.
+ Jacobi(x, y)
+ panic(failureMsg)
+}
+
var encodingTests = []string{
"-539345864568634858364538753846587364875430589374589",
"-678645873",
diff --git a/src/cmd/internal/gc/big/intconv.go b/src/cmd/compile/internal/big/intconv.go
index 9c68a22bed..9c68a22bed 100644
--- a/src/cmd/internal/gc/big/intconv.go
+++ b/src/cmd/compile/internal/big/intconv.go
diff --git a/src/cmd/internal/gc/big/intconv_test.go b/src/cmd/compile/internal/big/intconv_test.go
index 2deb84b48f..2deb84b48f 100644
--- a/src/cmd/internal/gc/big/intconv_test.go
+++ b/src/cmd/compile/internal/big/intconv_test.go
diff --git a/src/cmd/internal/gc/big/nat.go b/src/cmd/compile/internal/big/nat.go
index 2a279d186c..c3eef76fa1 100644
--- a/src/cmd/internal/gc/big/nat.go
+++ b/src/cmd/compile/internal/big/nat.go
@@ -216,6 +216,34 @@ func basicMul(z, x, y nat) {
}
}
+// montgomery computes x*y*2^(-n*_W) mod m,
+// assuming k = -1/m mod 2^_W.
+// z is used for storing the result which is returned;
+// z must not alias x, y or m.
+func (z nat) montgomery(x, y, m nat, k Word, n int) nat {
+ var c1, c2 Word
+ z = z.make(n)
+ z.clear()
+ for i := 0; i < n; i++ {
+ d := y[i]
+ c1 += addMulVVW(z, x, d)
+ t := z[0] * k
+ c2 = addMulVVW(z, m, t)
+
+ copy(z, z[1:])
+ z[n-1] = c1 + c2
+ if z[n-1] < c1 {
+ c1 = 1
+ } else {
+ c1 = 0
+ }
+ }
+ if c1 != 0 {
+ subVV(z, z, m)
+ }
+ return z
+}
+
// Fast version of z[0:n+n>>1].add(z[0:n+n>>1], x[0:n]) w/o bounds checks.
// Factored out for readability - do not use outside karatsuba.
func karatsubaAdd(z, x nat, n int) {
@@ -888,6 +916,13 @@ func (z nat) expNN(x, y, m nat) nat {
}
// y > 0
+ // x**1 mod m == x mod m
+ if len(y) == 1 && y[0] == 1 && len(m) != 0 {
+ _, z = z.div(z, x, m)
+ return z
+ }
+ // y > 1
+
if len(m) != 0 {
// We likely end up being as long as the modulus.
z = z.make(len(m))
@@ -898,8 +933,11 @@ func (z nat) expNN(x, y, m nat) nat {
// 4-bit, windowed exponentiation. This involves precomputing 14 values
// (x^2...x^15) but then reduces the number of multiply-reduces by a
// third. Even for a 32-bit exponent, this reduces the number of
- // operations.
+ // operations. Uses Montgomery method for odd moduli.
if len(x) > 1 && len(y) > 1 && len(m) > 0 {
+ if m[0]&1 == 1 {
+ return z.expNNMontgomery(x, y, m)
+ }
return z.expNNWindowed(x, y, m)
}
@@ -1022,6 +1060,87 @@ func (z nat) expNNWindowed(x, y, m nat) nat {
return z.norm()
}
+// expNNMontgomery calculates x**y mod m using a fixed, 4-bit window.
+// Uses Montgomery representation.
+func (z nat) expNNMontgomery(x, y, m nat) nat {
+ var zz, one, rr, RR nat
+
+ numWords := len(m)
+
+ // We want the lengths of x and m to be equal.
+ if len(x) > numWords {
+ _, rr = rr.div(rr, x, m)
+ } else if len(x) < numWords {
+ rr = rr.make(numWords)
+ rr.clear()
+ for i := range x {
+ rr[i] = x[i]
+ }
+ } else {
+ rr = x
+ }
+ x = rr
+
+ // Ideally the precomputations would be performed outside, and reused
+ // k0 = -mˆ-1 mod 2ˆ_W. Algorithm from: Dumas, J.G. "On Newton–Raphson
+ // Iteration for Multiplicative Inverses Modulo Prime Powers".
+ k0 := 2 - m[0]
+ t := m[0] - 1
+ for i := 1; i < _W; i <<= 1 {
+ t *= t
+ k0 *= (t + 1)
+ }
+ k0 = -k0
+
+ // RR = 2ˆ(2*_W*len(m)) mod m
+ RR = RR.setWord(1)
+ zz = zz.shl(RR, uint(2*numWords*_W))
+ _, RR = RR.div(RR, zz, m)
+ if len(RR) < numWords {
+ zz = zz.make(numWords)
+ copy(zz, RR)
+ RR = zz
+ }
+ // one = 1, with equal length to that of m
+ one = one.make(numWords)
+ one.clear()
+ one[0] = 1
+
+ const n = 4
+ // powers[i] contains x^i
+ var powers [1 << n]nat
+ powers[0] = powers[0].montgomery(one, RR, m, k0, numWords)
+ powers[1] = powers[1].montgomery(x, RR, m, k0, numWords)
+ for i := 2; i < 1<<n; i++ {
+ powers[i] = powers[i].montgomery(powers[i-1], powers[1], m, k0, numWords)
+ }
+
+ // initialize z = 1 (Montgomery 1)
+ z = z.make(numWords)
+ copy(z, powers[0])
+
+ zz = zz.make(numWords)
+
+ // same windowed exponent, but with Montgomery multiplications
+ for i := len(y) - 1; i >= 0; i-- {
+ yi := y[i]
+ for j := 0; j < _W; j += n {
+ if i != len(y)-1 || j != 0 {
+ zz = zz.montgomery(z, z, m, k0, numWords)
+ z = z.montgomery(zz, zz, m, k0, numWords)
+ zz = zz.montgomery(z, z, m, k0, numWords)
+ z = z.montgomery(zz, zz, m, k0, numWords)
+ }
+ zz = zz.montgomery(z, powers[yi>>(_W-n)], m, k0, numWords)
+ z, zz = zz, z
+ yi <<= n
+ }
+ }
+ // convert to regular number
+ zz = zz.montgomery(z, one, m, k0, numWords)
+ return zz.norm()
+}
+
// probablyPrime performs reps Miller-Rabin tests to check whether n is prime.
// If it returns true, n is prime with probability 1 - 1/4^reps.
// If it returns false, n is not prime.
diff --git a/src/cmd/internal/gc/big/nat_test.go b/src/cmd/compile/internal/big/nat_test.go
index b25a89f731..a15a2bcac0 100644
--- a/src/cmd/internal/gc/big/nat_test.go
+++ b/src/cmd/compile/internal/big/nat_test.go
@@ -332,6 +332,67 @@ func TestTrailingZeroBits(t *testing.T) {
}
}
+var montgomeryTests = []struct {
+ x, y, m string
+ k0 uint64
+ out32, out64 string
+}{
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffff",
+ 0x0000000000000000,
+ "0xffffffffffffffffffffffffffffffffffffffffff",
+ "0xffffffffffffffffffffffffffffffffff",
+ },
+ {
+ "0x0000000080000000",
+ "0x00000000ffffffff",
+ "0x0000000010000001",
+ 0xff0000000fffffff,
+ "0x0000000088000000",
+ "0x0000000007800001",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
+ "0xffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc",
+ "0x33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
+ 0xdecc8f1249812adf,
+ "0x22bb05b6d95eaaeca2bb7c05e51f807bce9064b5fbad177161695e4558f9474e91cd79",
+ "0x14beb58d230f85b6d95eaaeca2bb7c05e51f807bce9064b5fb45669afa695f228e48cd",
+ },
+ {
+ "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
+ "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
+ 0xdecc8f1249812adf,
+ "0x5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d7a11c7772cba02c22f9711078d51a3797eb18e691295293284d988e349fa6deba46b25a4ecd9f715",
+ "0x92fcad4b5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d799c32fe2f3cc5422f9711078d51a3797eb18e691295293284d8f5e69caf6decddfe1df6",
+ },
+}
+
+func TestMontgomery(t *testing.T) {
+ for i, test := range montgomeryTests {
+ x := natFromString(test.x)
+ y := natFromString(test.y)
+ m := natFromString(test.m)
+
+ var out nat
+ if _W == 32 {
+ out = natFromString(test.out32)
+ } else {
+ out = natFromString(test.out64)
+ }
+
+ k0 := Word(test.k0 & _M) // mask k0 to ensure that it fits for 32-bit systems.
+ z := nat(nil).montgomery(x, y, m, k0, len(m))
+ z = z.norm()
+ if z.cmp(out) != 0 {
+ t.Errorf("#%d got %s want %s", i, z.decimalString(), out.decimalString())
+ }
+ }
+}
+
var expNNTests = []struct {
x, y, m string
out string
diff --git a/src/cmd/internal/gc/big/natconv.go b/src/cmd/compile/internal/big/natconv.go
index 022dcfe38c..022dcfe38c 100644
--- a/src/cmd/internal/gc/big/natconv.go
+++ b/src/cmd/compile/internal/big/natconv.go
diff --git a/src/cmd/internal/gc/big/natconv_test.go b/src/cmd/compile/internal/big/natconv_test.go
index f321fbc2df..f321fbc2df 100644
--- a/src/cmd/internal/gc/big/natconv_test.go
+++ b/src/cmd/compile/internal/big/natconv_test.go
diff --git a/src/cmd/internal/gc/big/rat.go b/src/cmd/compile/internal/big/rat.go
index fb16f18a96..fb16f18a96 100644
--- a/src/cmd/internal/gc/big/rat.go
+++ b/src/cmd/compile/internal/big/rat.go
diff --git a/src/cmd/internal/gc/big/rat_test.go b/src/cmd/compile/internal/big/rat_test.go
index 012d0c47ec..012d0c47ec 100644
--- a/src/cmd/internal/gc/big/rat_test.go
+++ b/src/cmd/compile/internal/big/rat_test.go
diff --git a/src/cmd/internal/gc/big/ratconv.go b/src/cmd/compile/internal/big/ratconv.go
index 778077b96e..778077b96e 100644
--- a/src/cmd/internal/gc/big/ratconv.go
+++ b/src/cmd/compile/internal/big/ratconv.go
diff --git a/src/cmd/internal/gc/big/ratconv_test.go b/src/cmd/compile/internal/big/ratconv_test.go
index 16b3a19418..16b3a19418 100644
--- a/src/cmd/internal/gc/big/ratconv_test.go
+++ b/src/cmd/compile/internal/big/ratconv_test.go
diff --git a/src/cmd/internal/gc/big/roundingmode_string.go b/src/cmd/compile/internal/big/roundingmode_string.go
index 05024b8065..05024b8065 100644
--- a/src/cmd/internal/gc/big/roundingmode_string.go
+++ b/src/cmd/compile/internal/big/roundingmode_string.go
diff --git a/src/cmd/internal/gc/big/vendor.bash b/src/cmd/compile/internal/big/vendor.bash
index 84aa750462..1b191ccb8f 100755
--- a/src/cmd/internal/gc/big/vendor.bash
+++ b/src/cmd/compile/internal/big/vendor.bash
@@ -15,9 +15,15 @@ rm *.go
cp $BIGDIR/*.go .
# Use pure Go arith ops w/o build tag.
-sed 's/^\/\/ \+build math_big_pure_go$//' arith_decl_pure.go > arith_decl.go
+sed 's|^// \+build math_big_pure_go$||' arith_decl_pure.go > arith_decl.go
rm arith_decl_pure.go
+# Import vendored math/big in external tests (e.g., floatexample_test.go).
+for f in *_test.go; do
+ sed 's|"math/big"|"cmd/compile/internal/big"|' $f > foo.go
+ mv foo.go $f
+done
+
# gofmt to clean up after sed
gofmt -w .
diff --git a/src/cmd/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go
index 789e59bfd0..892595a214 100644
--- a/src/cmd/internal/gc/align.go
+++ b/src/cmd/compile/internal/gc/align.go
@@ -71,8 +71,8 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 {
// in typecheck.c. usually addrescapes runs after
// widstruct, in which case we could drop this,
// but function closure functions are the exception.
- if f.Nname.Stackparam != nil {
- f.Nname.Stackparam.Xoffset = o
+ if f.Nname.Param.Stackparam != nil {
+ f.Nname.Param.Stackparam.Xoffset = o
f.Nname.Xoffset = 0
} else {
f.Nname.Xoffset = o
diff --git a/src/cmd/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index 6bdf78c8ab..6bdf78c8ab 100644
--- a/src/cmd/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
diff --git a/src/cmd/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go
index 179a4ddd9a..179a4ddd9a 100644
--- a/src/cmd/internal/gc/builtin/runtime.go
+++ b/src/cmd/compile/internal/gc/builtin/runtime.go
diff --git a/src/cmd/internal/gc/builtin/unsafe.go b/src/cmd/compile/internal/gc/builtin/unsafe.go
index ce508692eb..ce508692eb 100644
--- a/src/cmd/internal/gc/builtin/unsafe.go
+++ b/src/cmd/compile/internal/gc/builtin/unsafe.go
diff --git a/src/cmd/internal/gc/bv.go b/src/cmd/compile/internal/gc/bv.go
index 2b988e6547..2b988e6547 100644
--- a/src/cmd/internal/gc/bv.go
+++ b/src/cmd/compile/internal/gc/bv.go
diff --git a/src/cmd/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go
index 501cdcb1c8..ca58b1c6a3 100644
--- a/src/cmd/internal/gc/cgen.go
+++ b/src/cmd/compile/internal/gc/cgen.go
@@ -43,14 +43,7 @@ func cgen_wb(n, res *Node, wb bool) {
switch n.Op {
case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
- if res.Op != ONAME || !res.Addable || wb {
- var n1 Node
- Tempname(&n1, n.Type)
- Cgen_slice(n, &n1)
- cgen_wb(&n1, res, wb)
- } else {
- Cgen_slice(n, res)
- }
+ cgen_slice(n, res, wb)
return
case OEFACE:
@@ -67,6 +60,10 @@ func cgen_wb(n, res *Node, wb bool) {
case ODOTTYPE:
cgen_dottype(n, res, nil, wb)
return
+
+ case OAPPEND:
+ cgen_append(n, res)
+ return
}
if n.Ullman >= UINF {
@@ -545,7 +542,7 @@ func cgen_wb(n, res *Node, wb bool) {
var n1 Node
Regalloc(&n1, Types[Tptr], res)
p1 := Thearch.Gins(Thearch.Optoas(OAS, n1.Type), nil, &n1)
- Datastring(nl.Val.U.Sval, &p1.From)
+ Datastring(nl.Val.U.(string), &p1.From)
p1.From.Type = obj.TYPE_ADDR
Thearch.Gmove(&n1, res)
Regfree(&n1)
@@ -569,8 +566,7 @@ func cgen_wb(n, res *Node, wb bool) {
var n2 Node
Nodconst(&n2, Types[Tptr], 0)
- Thearch.Gins(Thearch.Optoas(OCMP, Types[Tptr]), &n1, &n2)
- p1 := Gbranch(Thearch.Optoas(OEQ, Types[Tptr]), nil, 0)
+ p1 := Thearch.Ginscmp(OEQ, Types[Tptr], &n1, &n2, 0)
n2 = n1
n2.Op = OINDREG
@@ -610,8 +606,7 @@ func cgen_wb(n, res *Node, wb bool) {
var n2 Node
Nodconst(&n2, Types[Tptr], 0)
- Thearch.Gins(Thearch.Optoas(OCMP, Types[Tptr]), &n1, &n2)
- p1 := Gbranch(Thearch.Optoas(OEQ, Types[Tptr]), nil, 0)
+ p1 := Thearch.Ginscmp(OEQ, Types[Tptr], &n1, &n2, 0)
n2 = n1
n2.Op = OINDREG
@@ -790,6 +785,9 @@ abop: // asymmetric binary
var sys_wbptr *Node
func cgen_wbptr(n, res *Node) {
+ if Curfn != nil && Curfn.Func.Nowritebarrier {
+ Yyerror("write barrier prohibited")
+ }
if Debug_wb > 0 {
Warn("write barrier")
}
@@ -804,19 +802,7 @@ func cgen_wbptr(n, res *Node) {
}
wbEnabled := syslook("writeBarrierEnabled", 0)
- switch Ctxt.Arch.Thechar {
- default:
- Fatal("cgen_wbptr: unknown architecture")
- case '5', '7', '9':
- var tmp Node
- Regalloc(&tmp, Types[TUINT8], nil)
- Thearch.Gmove(wbEnabled, &tmp)
- Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT8]), &tmp, Nodintconst(0))
- Regfree(&tmp)
- case '6', '8':
- Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT8]), wbEnabled, Nodintconst(0))
- }
- pbr := Gbranch(Thearch.Optoas(ONE, Types[TUINT8]), nil, -1)
+ pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)
pjmp := Gbranch(obj.AJMP, nil, 0)
Patch(pbr, Pc)
@@ -845,6 +831,9 @@ func cgen_wbptr(n, res *Node) {
}
func cgen_wbfat(n, res *Node) {
+ if Curfn != nil && Curfn.Func.Nowritebarrier {
+ Yyerror("write barrier prohibited")
+ }
if Debug_wb > 0 {
Warn("write barrier")
}
@@ -1047,7 +1036,7 @@ func Agenr(n *Node, a *Node, res *Node) {
if Isconst(nl, CTSTR) {
Fatal("constant string constant index")
}
- v := uint64(Mpgetfix(nr.Val.U.Xval))
+ v := uint64(Mpgetfix(nr.Val.U.(*Mpint)))
var n2 Node
if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
if Debug['B'] == 0 && !n.Bounded {
@@ -1055,14 +1044,9 @@ func Agenr(n *Node, a *Node, res *Node) {
n1.Op = OINDREG
n1.Type = Types[Tptr]
n1.Xoffset = int64(Array_nel)
- var n4 Node
- Regalloc(&n4, n1.Type, nil)
- Thearch.Gmove(&n1, &n4)
Nodconst(&n2, Types[TUINT32], int64(v))
- Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT32]), &n4, &n2)
- Regfree(&n4)
- p1 := Gbranch(Thearch.Optoas(OGT, Types[TUINT32]), nil, +1)
- Ginscall(Panicindex, 0)
+ p1 := Thearch.Ginscmp(OGT, Types[TUINT32], &n1, &n2, +1)
+ Ginscall(Panicindex, -1)
Patch(p1, Pc)
}
@@ -1088,7 +1072,7 @@ func Agenr(n *Node, a *Node, res *Node) {
if Debug['B'] == 0 && !n.Bounded {
// check bounds
if Isconst(nl, CTSTR) {
- Nodconst(&n4, Types[TUINT32], int64(len(nl.Val.U.Sval)))
+ Nodconst(&n4, Types[TUINT32], int64(len(nl.Val.U.(string))))
} else if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
n1 = n3
n1.Op = OINDREG
@@ -1099,23 +1083,21 @@ func Agenr(n *Node, a *Node, res *Node) {
} else {
Nodconst(&n4, Types[TUINT32], nl.Type.Bound)
}
-
- Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT32]), &n2, &n4)
+ p1 := Thearch.Ginscmp(OLT, Types[TUINT32], &n2, &n4, +1)
if n4.Op == OREGISTER {
Regfree(&n4)
}
- p1 := Gbranch(Thearch.Optoas(OLT, Types[TUINT32]), nil, +1)
if p2 != nil {
Patch(p2, Pc)
}
- Ginscall(Panicindex, 0)
+ Ginscall(Panicindex, -1)
Patch(p1, Pc)
}
if Isconst(nl, CTSTR) {
Regalloc(&n3, Types[Tptr], res)
p1 := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), nil, &n3)
- Datastring(nl.Val.U.Sval, &p1.From)
+ Datastring(nl.Val.U.(string), &p1.From)
p1.From.Type = obj.TYPE_ADDR
} else if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
n1 = n3
@@ -1206,15 +1188,14 @@ func Agenr(n *Node, a *Node, res *Node) {
if Isconst(nl, CTSTR) {
Fatal("constant string constant index") // front end should handle
}
- v := uint64(Mpgetfix(nr.Val.U.Xval))
+ v := uint64(Mpgetfix(nr.Val.U.(*Mpint)))
if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
if Debug['B'] == 0 && !n.Bounded {
nlen := n3
nlen.Type = Types[TUINT32]
nlen.Xoffset += int64(Array_nel)
Nodconst(&n2, Types[TUINT32], int64(v))
- Thearch.Gins(Thearch.Optoas(OCMP, Types[TUINT32]), &nlen, &n2)
- p1 := Gbranch(Thearch.Optoas(OGT, Types[TUINT32]), nil, +1)
+ p1 := Thearch.Ginscmp(OGT, Types[TUINT32], &nlen, &n2, +1)
Ginscall(Panicindex, -1)
Patch(p1, Pc)
}
@@ -1252,7 +1233,7 @@ func Agenr(n *Node, a *Node, res *Node) {
var nlen Node
if Isconst(nl, CTSTR) {
- Nodconst(&nlen, t, int64(len(nl.Val.U.Sval)))
+ Nodconst(&nlen, t, int64(len(nl.Val.U.(string))))
} else if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
nlen = n3
nlen.Type = t
@@ -1261,8 +1242,7 @@ func Agenr(n *Node, a *Node, res *Node) {
Nodconst(&nlen, t, nl.Type.Bound)
}
- Thearch.Gins(Thearch.Optoas(OCMP, t), &n2, &nlen)
- p1 := Gbranch(Thearch.Optoas(OLT, t), nil, +1)
+ p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
if p2 != nil {
Patch(p2, Pc)
}
@@ -1273,7 +1253,7 @@ func Agenr(n *Node, a *Node, res *Node) {
if Isconst(nl, CTSTR) {
Regalloc(&n3, Types[Tptr], res)
p1 := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), nil, &n3)
- Datastring(nl.Val.U.Sval, &p1.From)
+ Datastring(nl.Val.U.(string), &p1.From)
p1.From.Type = obj.TYPE_ADDR
Thearch.Gins(Thearch.Optoas(OADD, n3.Type), &n2, &n3)
goto indexdone1
@@ -1398,28 +1378,10 @@ func Agenr(n *Node, a *Node, res *Node) {
if Isconst(nl, CTSTR) {
Fatal("constant string constant index") // front end should handle
}
- v := uint64(Mpgetfix(nr.Val.U.Xval))
+ v := uint64(Mpgetfix(nr.Val.U.(*Mpint)))
if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
if Debug['B'] == 0 && !n.Bounded {
- if nlen.Op != OREGISTER && (Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9') {
- var tmp2 Node
- Regalloc(&tmp2, Types[Simtype[TUINT]], nil)
- Thearch.Gmove(&nlen, &tmp2)
- Regfree(&nlen) // in case it is OINDREG
- nlen = tmp2
- }
- var n2 Node
- Nodconst(&n2, Types[Simtype[TUINT]], int64(v))
- if Smallintconst(nr) {
- Thearch.Gins(Thearch.Optoas(OCMP, Types[Simtype[TUINT]]), &nlen, &n2)
- } else {
- Regalloc(&tmp, Types[Simtype[TUINT]], nil)
- Thearch.Gmove(&n2, &tmp)
- Thearch.Gins(Thearch.Optoas(OCMP, Types[Simtype[TUINT]]), &nlen, &tmp)
- Regfree(&tmp)
- }
-
- p1 := Gbranch(Thearch.Optoas(OGT, Types[Simtype[TUINT]]), nil, +1)
+ p1 := Thearch.Ginscmp(OGT, Types[Simtype[TUINT]], &nlen, Nodintconst(int64(v)), +1)
Ginscall(Panicindex, -1)
Patch(p1, Pc)
}
@@ -1454,28 +1416,14 @@ func Agenr(n *Node, a *Node, res *Node) {
t = Types[TUINT64]
}
if Isconst(nl, CTSTR) {
- Nodconst(&nlen, t, int64(len(nl.Val.U.Sval)))
+ Nodconst(&nlen, t, int64(len(nl.Val.U.(string))))
} else if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
- if Is64(nr.Type) || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
- var n5 Node
- Regalloc(&n5, t, nil)
- Thearch.Gmove(&nlen, &n5)
- Regfree(&nlen)
- nlen = n5
- }
+ // nlen already initialized
} else {
Nodconst(&nlen, t, nl.Type.Bound)
- if !Smallintconst(&nlen) {
- var n5 Node
- Regalloc(&n5, t, nil)
- Thearch.Gmove(&nlen, &n5)
- nlen = n5
- freelen = 1
- }
}
- Thearch.Gins(Thearch.Optoas(OCMP, t), &n2, &nlen)
- p1 := Gbranch(Thearch.Optoas(OLT, t), nil, +1)
+ p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
Ginscall(Panicindex, -1)
Patch(p1, Pc)
}
@@ -1483,7 +1431,7 @@ func Agenr(n *Node, a *Node, res *Node) {
if Isconst(nl, CTSTR) {
Regalloc(&n3, Types[Tptr], res)
p1 := Thearch.Gins(Thearch.Optoas(OAS, n3.Type), nil, &n3) // XXX was LEAQ!
- Datastring(nl.Val.U.Sval, &p1.From)
+ Datastring(nl.Val.U.(string), &p1.From)
p1.From.Type = obj.TYPE_ADDR
Thearch.Gins(Thearch.Optoas(OADD, n3.Type), &n2, &n3)
goto indexdone
@@ -1637,7 +1585,7 @@ func Agen(n *Node, res *Node) {
Fatal("agen: bad ONAME class %#x", n.Class)
}
- Cgen(n.Heapaddr, res)
+ Cgen(n.Name.Heapaddr, res)
if n.Xoffset != 0 {
addOffset(res, n.Xoffset)
}
@@ -1770,7 +1718,7 @@ func Igen(n *Node, a *Node, res *Node) {
// Compute &a[i] as &a + i*width.
a.Type = n.Type
- a.Xoffset += Mpgetfix(n.Right.Val.U.Xval) * n.Type.Width
+ a.Xoffset += Mpgetfix(n.Right.Val.U.(*Mpint)) * n.Type.Width
Fixlargeoffset(a)
return
}
@@ -1920,11 +1868,11 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
Fatal("bgen: non-bool const %v\n", Nconv(n, obj.FmtLong))
}
if genval {
- Cgen(Nodbool(wantTrue == n.Val.U.Bval), res)
+ Cgen(Nodbool(wantTrue == n.Val.U.(bool)), res)
return
}
// If n == wantTrue, jump; otherwise do nothing.
- if wantTrue == n.Val.U.Bval {
+ if wantTrue == n.Val.U.(bool) {
Patch(Gbranch(obj.AJMP, nil, likely), to)
}
return
@@ -2214,14 +2162,27 @@ func bins(typ *Type, res *Node, a, likely int, to *obj.Prog) {
}
}
-/*
- * n is on stack, either local variable
- * or return value from function call.
- * return n's offset from SP.
- */
+// stkof returns n's offset from SP if n is on the stack
+// (either a local variable or the return value from a function call
+// or the arguments to a function call).
+// If n is not on the stack, stkof returns -1000.
+// If n is on the stack but in an unknown location
+// (due to array index arithmetic), stkof returns +1000.
+//
+// NOTE(rsc): It is possible that the ODOT and OINDEX cases
+// are not relevant here, since it shouldn't be possible for them
+// to be involved in an overlapping copy. Only function results
+// from one call and the arguments to the next can overlap in
+// any non-trivial way. If they can be dropped, then this function
+// becomes much simpler and also more trustworthy.
+// The fact that it works at all today is probably due to the fact
+// that ODOT and OINDEX are irrelevant.
func stkof(n *Node) int64 {
switch n.Op {
case OINDREG:
+ if n.Reg != int16(Thearch.REGSP) {
+ return -1000 // not on stack
+ }
return n.Xoffset
case ODOT:
@@ -2230,7 +2191,7 @@ func stkof(n *Node) int64 {
break
}
off := stkof(n.Left)
- if off == -1000 || off == 1000 {
+ if off == -1000 || off == +1000 {
return off
}
return off + n.Xoffset
@@ -2241,13 +2202,13 @@ func stkof(n *Node) int64 {
break
}
off := stkof(n.Left)
- if off == -1000 || off == 1000 {
+ if off == -1000 || off == +1000 {
return off
}
if Isconst(n.Right, CTINT) {
- return off + t.Type.Width*Mpgetfix(n.Right.Val.U.Xval)
+ return off + t.Type.Width*Mpgetfix(n.Right.Val.U.(*Mpint))
}
- return 1000
+ return +1000 // on stack but not sure exactly where
case OCALLMETH, OCALLINTER, OCALLFUNC:
t := n.Left.Type
@@ -2268,7 +2229,7 @@ func stkof(n *Node) int64 {
// botch - probably failing to recognize address
// arithmetic on the above. eg INDEX and DOT
- return -1000
+ return -1000 // not on stack
}
/*
@@ -2446,8 +2407,7 @@ func Ginscall(f *Node, proc int) {
if proc == 2 {
Nodreg(&reg, Types[TINT32], Thearch.REGRETURN)
- Thearch.Gins(Thearch.Optoas(OCMP, Types[TINT32]), &reg, Nodintconst(0))
- p := Gbranch(Thearch.Optoas(OEQ, Types[TINT32]), nil, +1)
+ p := Thearch.Ginscmp(OEQ, Types[TINT32], &reg, Nodintconst(0), +1)
cgen_ret(nil)
Patch(p, Pc)
}
@@ -2576,7 +2536,7 @@ func cgen_call(n *Node, proc int) {
}
// call direct
- n.Left.Method = true
+ n.Left.Name.Method = true
Ginscall(n.Left, proc)
}
@@ -2701,7 +2661,7 @@ func cgen_div(op int, nl *Node, nr *Node, res *Node) {
case TUINT64:
var m Magic
m.W = w
- m.Ud = uint64(Mpgetfix(nr.Val.U.Xval))
+ m.Ud = uint64(Mpgetfix(nr.Val.U.(*Mpint)))
Umagic(&m)
if m.Bad != 0 {
break
@@ -2739,7 +2699,7 @@ func cgen_div(op int, nl *Node, nr *Node, res *Node) {
case TINT64:
var m Magic
m.W = w
- m.Sd = Mpgetfix(nr.Val.U.Xval)
+ m.Sd = Mpgetfix(nr.Val.U.(*Mpint))
Smagic(&m)
if m.Bad != 0 {
break
@@ -2843,3 +2803,762 @@ func Fixlargeoffset(n *Node) {
n.Xoffset = 0
}
}
+
+func cgen_append(n, res *Node) {
+ if Debug['g'] != 0 {
+ Dump("cgen_append-n", n)
+ Dump("cgen_append-res", res)
+ }
+ if res.Op != ONAME && !samesafeexpr(res, n.List.N) {
+ Dump("cgen_append-n", n)
+ Dump("cgen_append-res", res)
+ Fatal("append not lowered")
+ }
+ for l := n.List; l != nil; l = l.Next {
+ if l.N.Ullman >= UINF {
+ Fatal("append with function call arguments")
+ }
+ }
+
+ // res = append(src, x, y, z)
+ //
+ // If res and src are the same, we can avoid writing to base and cap
+ // unless we grow the underlying array.
+ needFullUpdate := !samesafeexpr(res, n.List.N)
+
+ // Copy src triple into base, len, cap.
+ base := temp(Types[Tptr])
+ len := temp(Types[TUINT])
+ cap := temp(Types[TUINT])
+
+ var src Node
+ Igen(n.List.N, &src, nil)
+ src.Type = Types[Tptr]
+ Thearch.Gmove(&src, base)
+ src.Type = Types[TUINT]
+ src.Xoffset += int64(Widthptr)
+ Thearch.Gmove(&src, len)
+ src.Xoffset += int64(Widthptr)
+ Thearch.Gmove(&src, cap)
+
+ // if len+argc <= cap goto L1
+ var rlen Node
+ Regalloc(&rlen, Types[TUINT], nil)
+ Thearch.Gmove(len, &rlen)
+ Thearch.Ginscon(Thearch.Optoas(OADD, Types[TUINT]), int64(count(n.List)-1), &rlen)
+ p := Thearch.Ginscmp(OLE, Types[TUINT], &rlen, cap, +1)
+ // Note: rlen and src are Regrealloc'ed below at the target of the
+ // branch we just emitted; do not reuse these Go variables for
+ // other purposes. They need to still describe the same things
+ // below that they describe right here.
+ Regfree(&src)
+
+ // base, len, cap = growslice(type, base, len, cap, newlen)
+ var arg Node
+ arg.Op = OINDREG
+ arg.Reg = int16(Thearch.REGSP)
+ arg.Addable = true
+ arg.Xoffset = 0
+ if HasLinkRegister() {
+ arg.Xoffset = int64(Ctxt.Arch.Ptrsize)
+ }
+ arg.Type = Ptrto(Types[TUINT8])
+ Cgen(typename(res.Type), &arg)
+ arg.Xoffset += int64(Widthptr)
+
+ arg.Type = Types[Tptr]
+ Cgen(base, &arg)
+ arg.Xoffset += int64(Widthptr)
+
+ arg.Type = Types[TUINT]
+ Cgen(len, &arg)
+ arg.Xoffset += int64(Widthptr)
+
+ arg.Type = Types[TUINT]
+ Cgen(cap, &arg)
+ arg.Xoffset += int64(Widthptr)
+
+ arg.Type = Types[TUINT]
+ Cgen(&rlen, &arg)
+ arg.Xoffset += int64(Widthptr)
+ Regfree(&rlen)
+
+ fn := syslook("growslice", 1)
+ substArgTypes(fn, res.Type.Type, res.Type.Type)
+ Ginscall(fn, 0)
+
+ if Widthptr == 4 && Widthreg == 8 {
+ arg.Xoffset += 4
+ }
+
+ arg.Type = Types[Tptr]
+ Cgen(&arg, base)
+ arg.Xoffset += int64(Widthptr)
+
+ arg.Type = Types[TUINT]
+ Cgen(&arg, len)
+ arg.Xoffset += int64(Widthptr)
+
+ arg.Type = Types[TUINT]
+ Cgen(&arg, cap)
+
+ // Update res with base, len+argc, cap.
+ if needFullUpdate {
+ if Debug_append > 0 {
+ Warn("append: full update")
+ }
+ Patch(p, Pc)
+ }
+ if res.Op == ONAME {
+ Gvardef(res)
+ }
+ var dst, r1 Node
+ Igen(res, &dst, nil)
+ dst.Type = Types[TUINT]
+ dst.Xoffset += int64(Widthptr)
+ Regalloc(&r1, Types[TUINT], nil)
+ Thearch.Gmove(len, &r1)
+ Thearch.Ginscon(Thearch.Optoas(OADD, Types[TUINT]), int64(count(n.List)-1), &r1)
+ Thearch.Gmove(&r1, &dst)
+ Regfree(&r1)
+ dst.Xoffset += int64(Widthptr)
+ Thearch.Gmove(cap, &dst)
+ dst.Type = Types[Tptr]
+ dst.Xoffset -= 2 * int64(Widthptr)
+ cgen_wb(base, &dst, needwritebarrier(&dst, base))
+ Regfree(&dst)
+
+ if !needFullUpdate {
+ if Debug_append > 0 {
+ Warn("append: len-only update")
+ }
+ // goto L2;
+ // L1:
+ // update len only
+ // L2:
+ q := Gbranch(obj.AJMP, nil, 0)
+ Patch(p, Pc)
+ // At the goto above, src refers to cap and rlen holds the new len
+ if src.Op == OREGISTER || src.Op == OINDREG {
+ Regrealloc(&src)
+ }
+ Regrealloc(&rlen)
+ src.Xoffset -= int64(Widthptr)
+ Thearch.Gmove(&rlen, &src)
+ Regfree(&src)
+ Regfree(&rlen)
+ Patch(q, Pc)
+ }
+
+ // Copy data into place.
+ // Could do write barrier check around entire copy instead of each element.
+ // Could avoid reloading registers on each iteration if we know the cgen_wb
+ // is not going to use a write barrier.
+ i := 0
+ var r2 Node
+ for l := n.List.Next; l != nil; l = l.Next {
+ Regalloc(&r1, Types[Tptr], nil)
+ Thearch.Gmove(base, &r1)
+ Regalloc(&r2, Types[TUINT], nil)
+ Thearch.Gmove(len, &r2)
+ if i > 0 {
+ Thearch.Gins(Thearch.Optoas(OADD, Types[TUINT]), Nodintconst(int64(i)), &r2)
+ }
+ w := res.Type.Type.Width
+ if Thearch.AddIndex != nil && Thearch.AddIndex(&r2, w, &r1) {
+ // r1 updated by back end
+ } else if w == 1 {
+ Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &r2, &r1)
+ } else {
+ Thearch.Ginscon(Thearch.Optoas(OMUL, Types[TUINT]), int64(w), &r2)
+ Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &r2, &r1)
+ }
+ Regfree(&r2)
+
+ r1.Op = OINDREG
+ r1.Type = res.Type.Type
+ cgen_wb(l.N, &r1, needwritebarrier(&r1, l.N))
+ Regfree(&r1)
+ i++
+ }
+}
+
+// Generate res = n, where n is x[i:j] or x[i:j:k].
+// If wb is true, need write barrier updating res's base pointer.
+// On systems with 32-bit ints, i, j, k are guaranteed to be 32-bit values.
+func cgen_slice(n, res *Node, wb bool) {
+ if Debug['g'] != 0 {
+ Dump("cgen_slice-n", n)
+ Dump("cgen_slice-res", res)
+ }
+
+ needFullUpdate := !samesafeexpr(n.Left, res)
+
+ // orderexpr has made sure that x is safe (but possibly expensive)
+ // and i, j, k are cheap. On a system with registers (anything but 386)
+ // we can evaluate x first and then know we have enough registers
+ // for i, j, k as well.
+ var x, xbase, xlen, xcap, i, j, k Node
+ if n.Op != OSLICEARR && n.Op != OSLICE3ARR {
+ Igen(n.Left, &x, nil)
+ }
+
+ indexRegType := Types[TUINT]
+ if Widthreg > Widthptr { // amd64p32
+ indexRegType = Types[TUINT64]
+ }
+
+ // On most systems, we use registers.
+ // The 386 has basically no registers, so substitute functions
+ // that can work with temporaries instead.
+ regalloc := Regalloc
+ ginscon := Thearch.Ginscon
+ gins := Thearch.Gins
+ if Thearch.Thechar == '8' {
+ regalloc = func(n *Node, t *Type, reuse *Node) {
+ Tempname(n, t)
+ }
+ ginscon = func(as int, c int64, n *Node) {
+ var n1 Node
+ Regalloc(&n1, n.Type, n)
+ Thearch.Gmove(n, &n1)
+ Thearch.Ginscon(as, c, &n1)
+ Thearch.Gmove(&n1, n)
+ Regfree(&n1)
+ }
+ gins = func(as int, f, t *Node) *obj.Prog {
+ var n1 Node
+ Regalloc(&n1, t.Type, t)
+ Thearch.Gmove(t, &n1)
+ Thearch.Gins(as, f, &n1)
+ Thearch.Gmove(&n1, t)
+ Regfree(&n1)
+ return nil
+ }
+ }
+
+ panics := make([]*obj.Prog, 0, 6) // 3 loads + 3 checks
+
+ loadlen := func() {
+ if xlen.Op != 0 {
+ return
+ }
+ if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
+ Nodconst(&xlen, indexRegType, n.Left.Type.Type.Bound)
+ return
+ }
+ if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
+ Nodconst(&xlen, indexRegType, int64(len(n.Left.Val.U.(string))))
+ return
+ }
+ regalloc(&xlen, indexRegType, nil)
+ x.Xoffset += int64(Widthptr)
+ x.Type = Types[TUINT]
+ Thearch.Gmove(&x, &xlen)
+ x.Xoffset -= int64(Widthptr)
+ }
+
+ loadcap := func() {
+ if xcap.Op != 0 {
+ return
+ }
+ if n.Op == OSLICEARR || n.Op == OSLICE3ARR || n.Op == OSLICESTR {
+ loadlen()
+ xcap = xlen
+ if xcap.Op == OREGISTER {
+ Regrealloc(&xcap)
+ }
+ return
+ }
+ regalloc(&xcap, indexRegType, nil)
+ x.Xoffset += 2 * int64(Widthptr)
+ x.Type = Types[TUINT]
+ Thearch.Gmove(&x, &xcap)
+ x.Xoffset -= 2 * int64(Widthptr)
+ }
+
+ var x1, x2, x3 *Node // unevaluated index arguments
+ x1 = n.Right.Left
+ switch n.Op {
+ default:
+ x2 = n.Right.Right
+ case OSLICE3, OSLICE3ARR:
+ x2 = n.Right.Right.Left
+ x3 = n.Right.Right.Right
+ }
+
+ // load computes src into targ, but if src refers to the len or cap of n.Left,
+ // load copies those from xlen, xcap, loading xlen if needed.
+ // If targ.Op == OREGISTER on return, it must be Regfreed,
+ // but it should not be modified without first checking whether it is
+ // xlen or xcap's register.
+ load := func(src, targ *Node) {
+ if src == nil {
+ return
+ }
+ switch src.Op {
+ case OLITERAL:
+ *targ = *src
+ return
+ case OLEN:
+ // NOTE(rsc): This doesn't actually trigger, because order.go
+ // has pulled all the len and cap calls into separate assignments
+ // to temporaries. There are tests in test/sliceopt.go that could
+ // be enabled if this is fixed.
+ if samesafeexpr(n.Left, src.Left) {
+ if Debug_slice > 0 {
+ Warn("slice: reuse len")
+ }
+ loadlen()
+ *targ = xlen
+ if targ.Op == OREGISTER {
+ Regrealloc(targ)
+ }
+ return
+ }
+ case OCAP:
+ // NOTE(rsc): This doesn't actually trigger; see note in case OLEN above.
+ if samesafeexpr(n.Left, src.Left) {
+ if Debug_slice > 0 {
+ Warn("slice: reuse cap")
+ }
+ loadcap()
+ *targ = xcap
+ if targ.Op == OREGISTER {
+ Regrealloc(targ)
+ }
+ return
+ }
+ }
+ if i.Op != 0 && samesafeexpr(x1, src) {
+ if Debug_slice > 0 {
+ Warn("slice: reuse 1st index")
+ }
+ *targ = i
+ if targ.Op == OREGISTER {
+ Regrealloc(targ)
+ }
+ return
+ }
+ if j.Op != 0 && samesafeexpr(x2, src) {
+ if Debug_slice > 0 {
+ Warn("slice: reuse 2nd index")
+ }
+ *targ = j
+ if targ.Op == OREGISTER {
+ Regrealloc(targ)
+ }
+ return
+ }
+ if Thearch.Cgenindex != nil {
+ regalloc(targ, indexRegType, nil)
+ p := Thearch.Cgenindex(src, targ, false)
+ if p != nil {
+ panics = append(panics, p)
+ }
+ } else if Thearch.Igenindex != nil {
+ p := Thearch.Igenindex(src, targ, false)
+ if p != nil {
+ panics = append(panics, p)
+ }
+ } else {
+ regalloc(targ, indexRegType, nil)
+ var tmp Node
+ Cgenr(src, &tmp, targ)
+ Thearch.Gmove(&tmp, targ)
+ Regfree(&tmp)
+ }
+ }
+
+ load(x1, &i)
+ load(x2, &j)
+ load(x3, &k)
+
+ // i defaults to 0.
+ if i.Op == 0 {
+ Nodconst(&i, indexRegType, 0)
+ }
+
+ // j defaults to len(x)
+ if j.Op == 0 {
+ loadlen()
+ j = xlen
+ if j.Op == OREGISTER {
+ Regrealloc(&j)
+ }
+ }
+
+ // k defaults to cap(x)
+ // Only need to load it if we're recalculating cap or doing a full update.
+ if k.Op == 0 && n.Op != OSLICESTR && (!iszero(&i) || needFullUpdate) {
+ loadcap()
+ k = xcap
+ if k.Op == OREGISTER {
+ Regrealloc(&k)
+ }
+ }
+
+ // Check constant indexes for negative values, and against constant length if known.
+ // The func obvious below checks for out-of-order constant indexes.
+ var bound int64 = -1
+ if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
+ bound = n.Left.Type.Type.Bound
+ } else if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
+ bound = int64(len(n.Left.Val.U.(string)))
+ }
+ if Isconst(&i, CTINT) {
+ if mpcmpfixc(i.Val.U.(*Mpint), 0) < 0 || bound >= 0 && mpcmpfixc(i.Val.U.(*Mpint), bound) > 0 {
+ Yyerror("slice index out of bounds")
+ }
+ }
+ if Isconst(&j, CTINT) {
+ if mpcmpfixc(j.Val.U.(*Mpint), 0) < 0 || bound >= 0 && mpcmpfixc(j.Val.U.(*Mpint), bound) > 0 {
+ Yyerror("slice index out of bounds")
+ }
+ }
+ if Isconst(&k, CTINT) {
+ if mpcmpfixc(k.Val.U.(*Mpint), 0) < 0 || bound >= 0 && mpcmpfixc(k.Val.U.(*Mpint), bound) > 0 {
+ Yyerror("slice index out of bounds")
+ }
+ }
+
+ // same reports whether n1 and n2 are the same register or constant.
+ same := func(n1, n2 *Node) bool {
+ return n1.Op == OREGISTER && n2.Op == OREGISTER && n1.Reg == n2.Reg ||
+ n1.Op == ONAME && n2.Op == ONAME && n1.Orig == n2.Orig && n1.Type == n2.Type && n1.Xoffset == n2.Xoffset ||
+ n1.Op == OLITERAL && n2.Op == OLITERAL && Mpcmpfixfix(n1.Val.U.(*Mpint), n2.Val.U.(*Mpint)) == 0
+ }
+
+ // obvious reports whether n1 <= n2 is obviously true,
+ // and it calls Yyerror if n1 <= n2 is obviously false.
+ obvious := func(n1, n2 *Node) bool {
+ if Debug['B'] != 0 { // -B disables bounds checks
+ return true
+ }
+ if same(n1, n2) {
+ return true // n1 == n2
+ }
+ if iszero(n1) {
+ return true // using unsigned compare, so 0 <= n2 always true
+ }
+ if xlen.Op != 0 && same(n1, &xlen) && xcap.Op != 0 && same(n2, &xcap) {
+ return true // len(x) <= cap(x) always true
+ }
+ if Isconst(n1, CTINT) && Isconst(n2, CTINT) {
+ if Mpcmpfixfix(n1.Val.U.(*Mpint), n2.Val.U.(*Mpint)) <= 0 {
+ return true // n1, n2 constants such that n1 <= n2
+ }
+ Yyerror("slice index out of bounds")
+ return true
+ }
+ return false
+ }
+
+ compare := func(n1, n2 *Node) {
+ // n1 might be a 64-bit constant, even on 32-bit architectures,
+ // but it will be represented in 32 bits.
+ if Ctxt.Arch.Regsize == 4 && Is64(n1.Type) {
+ if mpcmpfixc(n1.Val.U.(*Mpint), 1<<31) >= 0 {
+ Fatal("missed slice out of bounds check")
+ }
+ var tmp Node
+ Nodconst(&tmp, indexRegType, Mpgetfix(n1.Val.U.(*Mpint)))
+ n1 = &tmp
+ }
+ p := Thearch.Ginscmp(OGT, indexRegType, n1, n2, -1)
+ panics = append(panics, p)
+ }
+
+ loadcap()
+ max := &xcap
+ if k.Op != 0 && (n.Op == OSLICE3 || n.Op == OSLICE3ARR) {
+ if obvious(&k, max) {
+ if Debug_slice > 0 {
+ Warn("slice: omit check for 3rd index")
+ }
+ } else {
+ compare(&k, max)
+ }
+ max = &k
+ }
+ if j.Op != 0 {
+ if obvious(&j, max) {
+ if Debug_slice > 0 {
+ Warn("slice: omit check for 2nd index")
+ }
+ } else {
+ compare(&j, max)
+ }
+ max = &j
+ }
+ if i.Op != 0 {
+ if obvious(&i, max) {
+ if Debug_slice > 0 {
+ Warn("slice: omit check for 1st index")
+ }
+ } else {
+ compare(&i, max)
+ }
+ max = &i
+ }
+ if k.Op != 0 && i.Op != 0 {
+ obvious(&i, &k) // emit compile-time error for x[3:n:2]
+ }
+
+ if len(panics) > 0 {
+ p := Gbranch(obj.AJMP, nil, 0)
+ for _, q := range panics {
+ Patch(q, Pc)
+ }
+ Ginscall(panicslice, -1)
+ Patch(p, Pc)
+ }
+
+ // Checks are done.
+ // Compute new len as j-i, cap as k-i.
+ // If i and j are same register, len is constant 0.
+ // If i and k are same register, cap is constant 0.
+ // If j and k are same register, len and cap are same.
+
+ // Done with xlen and xcap.
+ // Now safe to modify j and k even if they alias xlen, xcap.
+ if xlen.Op == OREGISTER {
+ Regfree(&xlen)
+ }
+ if xcap.Op == OREGISTER {
+ Regfree(&xcap)
+ }
+
+ // are j and k the same value?
+ sameJK := same(&j, &k)
+
+ if i.Op != 0 {
+ // j -= i
+ if same(&i, &j) {
+ if Debug_slice > 0 {
+ Warn("slice: result len == 0")
+ }
+ if j.Op == OREGISTER {
+ Regfree(&j)
+ }
+ Nodconst(&j, indexRegType, 0)
+ } else {
+ switch j.Op {
+ case OLITERAL:
+ if Isconst(&i, CTINT) {
+ Nodconst(&j, indexRegType, Mpgetfix(j.Val.U.(*Mpint))-Mpgetfix(i.Val.U.(*Mpint)))
+ if Debug_slice > 0 {
+ Warn("slice: result len == %d", Mpgetfix(j.Val.U.(*Mpint)))
+ }
+ break
+ }
+ fallthrough
+ case ONAME:
+ if !istemp(&j) {
+ var r Node
+ regalloc(&r, indexRegType, nil)
+ Thearch.Gmove(&j, &r)
+ j = r
+ }
+ fallthrough
+ case OREGISTER:
+ if i.Op == OLITERAL {
+ v := Mpgetfix(i.Val.U.(*Mpint))
+ if v != 0 {
+ ginscon(Thearch.Optoas(OSUB, indexRegType), v, &j)
+ }
+ } else {
+ gins(Thearch.Optoas(OSUB, indexRegType), &i, &j)
+ }
+ }
+ }
+
+ // k -= i if k different from j and cap is needed.j
+ // (The modifications to j above cannot affect i: if j and i were aliased,
+ // we replace j with a constant 0 instead of doing a subtraction,
+ // leaving i unmodified.)
+ if k.Op == 0 {
+ if Debug_slice > 0 && n.Op != OSLICESTR {
+ Warn("slice: result cap not computed")
+ }
+ // no need
+ } else if same(&i, &k) {
+ if k.Op == OREGISTER {
+ Regfree(&k)
+ }
+ Nodconst(&k, indexRegType, 0)
+ if Debug_slice > 0 {
+ Warn("slice: result cap == 0")
+ }
+ } else if sameJK {
+ if Debug_slice > 0 {
+ Warn("slice: result cap == result len")
+ }
+ // k and j were the same value; make k-i the same as j-i.
+ if k.Op == OREGISTER {
+ Regfree(&k)
+ }
+ k = j
+ if k.Op == OREGISTER {
+ Regrealloc(&k)
+ }
+ } else {
+ switch k.Op {
+ case OLITERAL:
+ if Isconst(&i, CTINT) {
+ Nodconst(&k, indexRegType, Mpgetfix(k.Val.U.(*Mpint))-Mpgetfix(i.Val.U.(*Mpint)))
+ if Debug_slice > 0 {
+ Warn("slice: result cap == %d", Mpgetfix(k.Val.U.(*Mpint)))
+ }
+ break
+ }
+ fallthrough
+ case ONAME:
+ if !istemp(&k) {
+ var r Node
+ regalloc(&r, indexRegType, nil)
+ Thearch.Gmove(&k, &r)
+ k = r
+ }
+ fallthrough
+ case OREGISTER:
+ if same(&i, &k) {
+ Regfree(&k)
+ Nodconst(&k, indexRegType, 0)
+ if Debug_slice > 0 {
+ Warn("slice: result cap == 0")
+ }
+ } else if i.Op == OLITERAL {
+ v := Mpgetfix(i.Val.U.(*Mpint))
+ if v != 0 {
+ ginscon(Thearch.Optoas(OSUB, indexRegType), v, &k)
+ }
+ } else {
+ gins(Thearch.Optoas(OSUB, indexRegType), &i, &k)
+ }
+ }
+ }
+ }
+
+ adjustBase := true
+ if i.Op == 0 || iszero(&i) {
+ if Debug_slice > 0 {
+ Warn("slice: skip base adjustment for 1st index 0")
+ }
+ adjustBase = false
+ } else if k.Op != 0 && iszero(&k) || k.Op == 0 && iszero(&j) {
+ if Debug_slice > 0 {
+ if n.Op == OSLICESTR {
+ Warn("slice: skip base adjustment for string len == 0")
+ } else {
+ Warn("slice: skip base adjustment for cap == 0")
+ }
+ }
+ adjustBase = false
+ }
+
+ if !adjustBase && !needFullUpdate {
+ if Debug_slice > 0 {
+ if k.Op != 0 {
+ Warn("slice: len/cap-only update")
+ } else {
+ Warn("slice: len-only update")
+ }
+ }
+ if i.Op == OREGISTER {
+ Regfree(&i)
+ }
+ // Write len (and cap if needed) back to x.
+ x.Xoffset += int64(Widthptr)
+ x.Type = Types[TUINT]
+ Thearch.Gmove(&j, &x)
+ x.Xoffset -= int64(Widthptr)
+ if k.Op != 0 {
+ x.Xoffset += 2 * int64(Widthptr)
+ x.Type = Types[TUINT]
+ Thearch.Gmove(&k, &x)
+ x.Xoffset -= 2 * int64(Widthptr)
+ }
+ Regfree(&x)
+ } else {
+ // Compute new base. May smash i.
+ if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
+ Cgenr(n.Left, &xbase, nil)
+ Cgen_checknil(&xbase)
+ } else {
+ regalloc(&xbase, Ptrto(res.Type.Type), nil)
+ x.Type = xbase.Type
+ Thearch.Gmove(&x, &xbase)
+ Regfree(&x)
+ }
+ if i.Op != 0 && adjustBase {
+ // Branch around the base adjustment if the resulting cap will be 0.
+ var p *obj.Prog
+ size := &k
+ if k.Op == 0 {
+ size = &j
+ }
+ if Isconst(size, CTINT) {
+ // zero was checked above, must be non-zero.
+ } else {
+ var tmp Node
+ Nodconst(&tmp, indexRegType, 0)
+ p = Thearch.Ginscmp(OEQ, indexRegType, size, &tmp, -1)
+ }
+ var w int64
+ if n.Op == OSLICESTR {
+ w = 1 // res is string, elem size is 1 (byte)
+ } else {
+ w = res.Type.Type.Width // res is []T, elem size is T.width
+ }
+ if Isconst(&i, CTINT) {
+ ginscon(Thearch.Optoas(OADD, xbase.Type), Mpgetfix(i.Val.U.(*Mpint))*w, &xbase)
+ } else if Thearch.AddIndex != nil && Thearch.AddIndex(&i, w, &xbase) {
+ // done by back end
+ } else if w == 1 {
+ gins(Thearch.Optoas(OADD, xbase.Type), &i, &xbase)
+ } else {
+ if i.Op == ONAME && !istemp(&i) {
+ var tmp Node
+ Tempname(&tmp, i.Type)
+ Thearch.Gmove(&i, &tmp)
+ i = tmp
+ }
+ ginscon(Thearch.Optoas(OMUL, i.Type), w, &i)
+ gins(Thearch.Optoas(OADD, xbase.Type), &i, &xbase)
+ }
+ if p != nil {
+ Patch(p, Pc)
+ }
+ }
+ if i.Op == OREGISTER {
+ Regfree(&i)
+ }
+
+ // Write len, cap, base to result.
+ if res.Op == ONAME {
+ Gvardef(res)
+ }
+ Igen(res, &x, nil)
+ x.Xoffset += int64(Widthptr)
+ x.Type = Types[TUINT]
+ Thearch.Gmove(&j, &x)
+ x.Xoffset -= int64(Widthptr)
+ if k.Op != 0 {
+ x.Xoffset += 2 * int64(Widthptr)
+ Thearch.Gmove(&k, &x)
+ x.Xoffset -= 2 * int64(Widthptr)
+ }
+ x.Type = xbase.Type
+ cgen_wb(&xbase, &x, wb)
+ Regfree(&xbase)
+ Regfree(&x)
+ }
+
+ if j.Op == OREGISTER {
+ Regfree(&j)
+ }
+ if k.Op == OREGISTER {
+ Regfree(&k)
+ }
+}
diff --git a/src/cmd/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go
index 8d5fd5a600..64cd97206c 100644
--- a/src/cmd/internal/gc/closure.go
+++ b/src/cmd/compile/internal/gc/closure.go
@@ -17,7 +17,7 @@ func closurehdr(ntype *Node) {
var a *Node
n := Nod(OCLOSURE, nil, nil)
- n.Ntype = ntype
+ n.Param.Ntype = ntype
n.Funcdepth = Funcdepth
n.Func.Outerfunc = Curfn
@@ -72,8 +72,8 @@ func closurebody(body *NodeList) *Node {
var v *Node
for l := func_.Func.Cvars; l != nil; l = l.Next {
v = l.N
- v.Closure.Closure = v.Outer
- v.Outerexpr = oldname(v.Sym)
+ v.Param.Closure.Param.Closure = v.Param.Outer
+ v.Param.Outerexpr = oldname(v.Sym)
}
return func_
@@ -83,16 +83,16 @@ func typecheckclosure(func_ *Node, top int) {
var n *Node
for l := func_.Func.Cvars; l != nil; l = l.Next {
- n = l.N.Closure
- if !n.Captured {
- n.Captured = true
- if n.Decldepth == 0 {
+ n = l.N.Param.Closure
+ if !n.Name.Captured {
+ n.Name.Captured = true
+ if n.Name.Decldepth == 0 {
Fatal("typecheckclosure: var %v does not have decldepth assigned", Nconv(n, obj.FmtShort))
}
// Ignore assignments to the variable in straightline code
// preceding the first capturing by a closure.
- if n.Decldepth == decldepth {
+ if n.Name.Decldepth == decldepth {
n.Assigned = false
}
}
@@ -100,14 +100,14 @@ func typecheckclosure(func_ *Node, top int) {
for l := func_.Func.Dcl; l != nil; l = l.Next {
if l.N.Op == ONAME && (l.N.Class == PPARAM || l.N.Class == PPARAMOUT) {
- l.N.Decldepth = 1
+ l.N.Name.Decldepth = 1
}
}
oldfn := Curfn
- typecheck(&func_.Ntype, Etype)
- func_.Type = func_.Ntype.Type
- func_.Top = top
+ typecheck(&func_.Param.Ntype, Etype)
+ func_.Type = func_.Param.Ntype.Type
+ func_.Param.Top = top
// Type check the body now, but only if we're inside a function.
// At top level (in a variable initialization: curfn==nil) we're not
@@ -193,7 +193,7 @@ func makeclosure(func_ *Node) *Node {
xfunc.Nname = newfuncname(closurename(func_))
xfunc.Nname.Sym.Flags |= SymExported // disable export
- xfunc.Nname.Ntype = xtype
+ xfunc.Nname.Param.Ntype = xtype
xfunc.Nname.Defn = xfunc
declare(xfunc.Nname, PFUNC)
xfunc.Nname.Funcdepth = func_.Funcdepth
@@ -207,8 +207,8 @@ func makeclosure(func_ *Node) *Node {
}
typecheck(&xfunc, Etop)
- xfunc.Closure = func_
- func_.Closure = xfunc
+ xfunc.Param.Closure = func_
+ func_.Param.Closure = xfunc
func_.Nbody = nil
func_.List = nil
@@ -229,7 +229,7 @@ func capturevars(xfunc *Node) {
lno := int(lineno)
lineno = xfunc.Lineno
- func_ := xfunc.Closure
+ func_ := xfunc.Param.Closure
func_.Func.Enter = nil
for l := func_.Func.Cvars; l != nil; l = l.Next {
v = l.N
@@ -249,14 +249,14 @@ func capturevars(xfunc *Node) {
// so that the outer frame also grabs them and knows they escape.
dowidth(v.Type)
- outer = v.Outerexpr
- v.Outerexpr = nil
+ outer = v.Param.Outerexpr
+ v.Param.Outerexpr = nil
// out parameters will be assigned to implicitly upon return.
- if outer.Class != PPARAMOUT && !v.Closure.Addrtaken && !v.Closure.Assigned && v.Type.Width <= 128 {
- v.Byval = true
+ if outer.Class != PPARAMOUT && !v.Param.Closure.Addrtaken && !v.Param.Closure.Assigned && v.Type.Width <= 128 {
+ v.Name.Byval = true
} else {
- v.Closure.Addrtaken = true
+ v.Param.Closure.Addrtaken = true
outer = Nod(OADDR, outer, nil)
}
@@ -266,10 +266,10 @@ func capturevars(xfunc *Node) {
name = v.Curfn.Nname.Sym
}
how := "ref"
- if v.Byval {
+ if v.Name.Byval {
how = "value"
}
- Warnl(int(v.Lineno), "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym, v.Closure.Addrtaken, v.Closure.Assigned, int32(v.Type.Width))
+ Warnl(int(v.Lineno), "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym, v.Param.Closure.Addrtaken, v.Param.Closure.Assigned, int32(v.Type.Width))
}
typecheck(&outer, Erv)
@@ -284,9 +284,9 @@ func capturevars(xfunc *Node) {
func transformclosure(xfunc *Node) {
lno := int(lineno)
lineno = xfunc.Lineno
- func_ := xfunc.Closure
+ func_ := xfunc.Param.Closure
- if func_.Top&Ecall != 0 {
+ if func_.Param.Top&Ecall != 0 {
// If the closure is directly called, we transform it to a plain function call
// with variables passed as args. This avoids allocation of a closure object.
// Here we do only a part of the transformation. Walk of OCALLFUNC(OCLOSURE)
@@ -321,7 +321,7 @@ func transformclosure(xfunc *Node) {
}
fld = typ(TFIELD)
fld.Funarg = 1
- if v.Byval {
+ if v.Name.Byval {
// If v is captured by value, we merely downgrade it to PPARAM.
v.Class = PPARAM
@@ -335,7 +335,7 @@ func transformclosure(xfunc *Node) {
addr = newname(Lookupf("&%s", v.Sym.Name))
addr.Type = Ptrto(v.Type)
addr.Class = PPARAM
- v.Heapaddr = addr
+ v.Name.Heapaddr = addr
fld.Nname = addr
}
@@ -375,14 +375,14 @@ func transformclosure(xfunc *Node) {
cv = Nod(OCLOSUREVAR, nil, nil)
cv.Type = v.Type
- if !v.Byval {
+ if !v.Name.Byval {
cv.Type = Ptrto(v.Type)
}
offset = Rnd(offset, int64(cv.Type.Align))
cv.Xoffset = offset
offset += cv.Type.Width
- if v.Byval && v.Type.Width <= int64(2*Widthptr) && Thearch.Thechar == '6' {
+ if v.Name.Byval && v.Type.Width <= int64(2*Widthptr) && Thearch.Thechar == '6' {
// If it is a small variable captured by value, downgrade it to PAUTO.
// This optimization is currently enabled only for amd64, see:
// https://github.com/golang/go/issues/9865
@@ -395,13 +395,13 @@ func transformclosure(xfunc *Node) {
// Declare variable holding addresses taken from closure
// and initialize in entry prologue.
addr = newname(Lookupf("&%s", v.Sym.Name))
- addr.Ntype = Nod(OIND, typenod(v.Type), nil)
+ addr.Param.Ntype = Nod(OIND, typenod(v.Type), nil)
addr.Class = PAUTO
addr.Used = true
addr.Curfn = xfunc
xfunc.Func.Dcl = list(xfunc.Func.Dcl, addr)
- v.Heapaddr = addr
- if v.Byval {
+ v.Name.Heapaddr = addr
+ if v.Name.Byval {
cv = Nod(OADDR, cv, nil)
}
body = list(body, Nod(OAS, addr, cv))
@@ -420,7 +420,7 @@ func transformclosure(xfunc *Node) {
func walkclosure(func_ *Node, init **NodeList) *Node {
// If no closure vars, don't bother wrapping.
if func_.Func.Cvars == nil {
- return func_.Closure.Nname
+ return func_.Param.Closure.Nname
}
// Create closure in the form of a composite literal.
@@ -448,7 +448,7 @@ func walkclosure(func_ *Node, init **NodeList) *Node {
continue
}
typ1 = typenod(v.Type)
- if !v.Byval {
+ if !v.Name.Byval {
typ1 = Nod(OIND, typ1, nil)
}
typ.List = list(typ.List, Nod(ODCLFIELD, newname(v.Sym), typ1))
@@ -457,7 +457,7 @@ func walkclosure(func_ *Node, init **NodeList) *Node {
clos := Nod(OCOMPLIT, nil, Nod(OIND, typ, nil))
clos.Esc = func_.Esc
clos.Right.Implicit = true
- clos.List = concat(list1(Nod(OCFUNC, func_.Closure.Nname, nil)), func_.Func.Enter)
+ clos.List = concat(list1(Nod(OCFUNC, func_.Param.Closure.Nname, nil)), func_.Func.Enter)
// Force type conversion from *struct to the func type.
clos = Nod(OCONVNOP, clos, nil)
@@ -583,7 +583,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
xfunc.Func.Dupok = true
xfunc.Nname = newfuncname(sym)
xfunc.Nname.Sym.Flags |= SymExported // disable export
- xfunc.Nname.Ntype = xtype
+ xfunc.Nname.Param.Ntype = xtype
xfunc.Nname.Defn = xfunc
declare(xfunc.Nname, PFUNC)
@@ -606,10 +606,10 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
xfunc.Func.Dcl = list(xfunc.Func.Dcl, ptr)
var body *NodeList
if Isptr[rcvrtype.Etype] || Isinter(rcvrtype) {
- ptr.Ntype = typenod(rcvrtype)
+ ptr.Param.Ntype = typenod(rcvrtype)
body = list(body, Nod(OAS, ptr, cv))
} else {
- ptr.Ntype = typenod(Ptrto(rcvrtype))
+ ptr.Param.Ntype = typenod(Ptrto(rcvrtype))
body = list(body, Nod(OAS, ptr, Nod(OADDR, cv, nil)))
}
diff --git a/src/cmd/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go
index ad2915812e..b3605ab206 100644
--- a/src/cmd/internal/gc/const.go
+++ b/src/cmd/compile/internal/gc/const.go
@@ -5,10 +5,47 @@
package gc
import (
+ "cmd/compile/internal/big"
"cmd/internal/obj"
"strings"
)
+// Int returns n as an int.
+// n must be an integer constant.
+func (n *Node) Int() int64 {
+ if !Isconst(n, CTINT) {
+ Fatal("Int(%v)", n)
+ }
+ return Mpgetfix(n.Val.U.(*Mpint))
+}
+
+// SetInt sets n's value to i.
+// n must be an integer constant.
+func (n *Node) SetInt(i int64) {
+ if !Isconst(n, CTINT) {
+ Fatal("SetInt(%v)", n)
+ }
+ Mpmovecfix(n.Val.U.(*Mpint), i)
+}
+
+// SetBigInt sets n's value to x.
+// n must be an integer constant.
+func (n *Node) SetBigInt(x *big.Int) {
+ if !Isconst(n, CTINT) {
+ Fatal("SetBigInt(%v)", n)
+ }
+ n.Val.U.(*Mpint).Val.Set(x)
+}
+
+// Bool returns n as an bool.
+// n must be an boolean constant.
+func (n *Node) Bool() bool {
+ if !Isconst(n, CTBOOL) {
+ Fatal("Int(%v)", n)
+ }
+ return n.Val.U.(bool)
+}
+
/*
* truncate float literal fv to 32-bit or 64-bit precision
* according to type; return truncated value.
@@ -20,7 +57,7 @@ func truncfltlit(oldv *Mpflt, t *Type) *Mpflt {
var v Val
v.Ctype = CTFLT
- v.U.Fval = oldv
+ v.U = oldv
overflow(v, t)
fv := newMpflt()
@@ -190,8 +227,8 @@ func convlit1(np **Node, t *Type, explicit bool) {
// if it is an unsafe.Pointer
case TUINTPTR:
if n.Type.Etype == TUNSAFEPTR {
- n.Val.U.Xval = new(Mpint)
- Mpmovecfix(n.Val.U.Xval, 0)
+ n.Val.U = new(Mpint)
+ Mpmovecfix(n.Val.U.(*Mpint), 0)
n.Val.Ctype = CTINT
} else {
goto bad
@@ -204,6 +241,9 @@ func convlit1(np **Node, t *Type, explicit bool) {
}
case CTINT, CTRUNE, CTFLT, CTCPLX:
+ if n.Type.Etype == TUNSAFEPTR && t.Etype != TUINTPTR {
+ goto bad
+ }
ct := int(n.Val.Ctype)
if Isint[et] {
switch ct {
@@ -229,7 +269,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
// flowthrough
case CTFLT:
- n.Val.U.Fval = truncfltlit(n.Val.U.Fval, t)
+ n.Val.U = truncfltlit(n.Val.U.(*Mpflt), t)
}
} else if Iscomplex[et] {
switch ct {
@@ -264,27 +304,25 @@ bad:
defaultlit(&n, nil)
*np = n
}
-
- return
}
func copyval(v Val) Val {
switch v.Ctype {
case CTINT, CTRUNE:
i := new(Mpint)
- mpmovefixfix(i, v.U.Xval)
- v.U.Xval = i
+ mpmovefixfix(i, v.U.(*Mpint))
+ v.U = i
case CTFLT:
f := newMpflt()
- mpmovefltflt(f, v.U.Fval)
- v.U.Fval = f
+ mpmovefltflt(f, v.U.(*Mpflt))
+ v.U = f
case CTCPLX:
c := new(Mpcplx)
- mpmovefltflt(&c.Real, &v.U.Cval.Real)
- mpmovefltflt(&c.Imag, &v.U.Cval.Imag)
- v.U.Cval = c
+ mpmovefltflt(&c.Real, &v.U.(*Mpcplx).Real)
+ mpmovefltflt(&c.Imag, &v.U.(*Mpcplx).Imag)
+ v.U = c
}
return v
@@ -294,17 +332,17 @@ func tocplx(v Val) Val {
switch v.Ctype {
case CTINT, CTRUNE:
c := new(Mpcplx)
- Mpmovefixflt(&c.Real, v.U.Xval)
+ Mpmovefixflt(&c.Real, v.U.(*Mpint))
Mpmovecflt(&c.Imag, 0.0)
v.Ctype = CTCPLX
- v.U.Cval = c
+ v.U = c
case CTFLT:
c := new(Mpcplx)
- mpmovefltflt(&c.Real, v.U.Fval)
+ mpmovefltflt(&c.Real, v.U.(*Mpflt))
Mpmovecflt(&c.Imag, 0.0)
v.Ctype = CTCPLX
- v.U.Cval = c
+ v.U = c
}
return v
@@ -314,18 +352,18 @@ func toflt(v Val) Val {
switch v.Ctype {
case CTINT, CTRUNE:
f := newMpflt()
- Mpmovefixflt(f, v.U.Xval)
+ Mpmovefixflt(f, v.U.(*Mpint))
v.Ctype = CTFLT
- v.U.Fval = f
+ v.U = f
case CTCPLX:
f := newMpflt()
- mpmovefltflt(f, &v.U.Cval.Real)
- if mpcmpfltc(&v.U.Cval.Imag, 0) != 0 {
- Yyerror("constant %v%vi truncated to real", Fconv(&v.U.Cval.Real, obj.FmtSharp), Fconv(&v.U.Cval.Imag, obj.FmtSharp|obj.FmtSign))
+ mpmovefltflt(f, &v.U.(*Mpcplx).Real)
+ if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) != 0 {
+ Yyerror("constant %v%vi truncated to real", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp|obj.FmtSign))
}
v.Ctype = CTFLT
- v.U.Fval = f
+ v.U = f
}
return v
@@ -338,22 +376,22 @@ func toint(v Val) Val {
case CTFLT:
i := new(Mpint)
- if mpmovefltfix(i, v.U.Fval) < 0 {
- Yyerror("constant %v truncated to integer", Fconv(v.U.Fval, obj.FmtSharp))
+ if mpmovefltfix(i, v.U.(*Mpflt)) < 0 {
+ Yyerror("constant %v truncated to integer", Fconv(v.U.(*Mpflt), obj.FmtSharp))
}
v.Ctype = CTINT
- v.U.Xval = i
+ v.U = i
case CTCPLX:
i := new(Mpint)
- if mpmovefltfix(i, &v.U.Cval.Real) < 0 {
- Yyerror("constant %v%vi truncated to integer", Fconv(&v.U.Cval.Real, obj.FmtSharp), Fconv(&v.U.Cval.Imag, obj.FmtSharp|obj.FmtSign))
+ if mpmovefltfix(i, &v.U.(*Mpcplx).Real) < 0 {
+ Yyerror("constant %v%vi truncated to integer", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp|obj.FmtSign))
}
- if mpcmpfltc(&v.U.Cval.Imag, 0) != 0 {
- Yyerror("constant %v%vi truncated to real", Fconv(&v.U.Cval.Real, obj.FmtSharp), Fconv(&v.U.Cval.Imag, obj.FmtSharp|obj.FmtSign))
+ if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) != 0 {
+ Yyerror("constant %v%vi truncated to real", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp|obj.FmtSign))
}
v.Ctype = CTINT
- v.U.Xval = i
+ v.U = i
}
return v
@@ -365,7 +403,7 @@ func doesoverflow(v Val, t *Type) bool {
if !Isint[t.Etype] {
Fatal("overflow: %v integer constant", t)
}
- if Mpcmpfixfix(v.U.Xval, Minintval[t.Etype]) < 0 || Mpcmpfixfix(v.U.Xval, Maxintval[t.Etype]) > 0 {
+ if Mpcmpfixfix(v.U.(*Mpint), Minintval[t.Etype]) < 0 || Mpcmpfixfix(v.U.(*Mpint), Maxintval[t.Etype]) > 0 {
return true
}
@@ -373,7 +411,7 @@ func doesoverflow(v Val, t *Type) bool {
if !Isfloat[t.Etype] {
Fatal("overflow: %v floating-point constant", t)
}
- if mpcmpfltflt(v.U.Fval, minfltval[t.Etype]) <= 0 || mpcmpfltflt(v.U.Fval, maxfltval[t.Etype]) >= 0 {
+ if mpcmpfltflt(v.U.(*Mpflt), minfltval[t.Etype]) <= 0 || mpcmpfltflt(v.U.(*Mpflt), maxfltval[t.Etype]) >= 0 {
return true
}
@@ -381,7 +419,7 @@ func doesoverflow(v Val, t *Type) bool {
if !Iscomplex[t.Etype] {
Fatal("overflow: %v complex constant", t)
}
- if mpcmpfltflt(&v.U.Cval.Real, minfltval[t.Etype]) <= 0 || mpcmpfltflt(&v.U.Cval.Real, maxfltval[t.Etype]) >= 0 || mpcmpfltflt(&v.U.Cval.Imag, minfltval[t.Etype]) <= 0 || mpcmpfltflt(&v.U.Cval.Imag, maxfltval[t.Etype]) >= 0 {
+ if mpcmpfltflt(&v.U.(*Mpcplx).Real, minfltval[t.Etype]) <= 0 || mpcmpfltflt(&v.U.(*Mpcplx).Real, maxfltval[t.Etype]) >= 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, minfltval[t.Etype]) <= 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, maxfltval[t.Etype]) >= 0 {
return true
}
}
@@ -396,32 +434,37 @@ func overflow(v Val, t *Type) {
return
}
+ // Only uintptrs may be converted to unsafe.Pointer, which cannot overflow.
+ if t.Etype == TUNSAFEPTR {
+ return
+ }
+
if !doesoverflow(v, t) {
return
}
switch v.Ctype {
case CTINT, CTRUNE:
- Yyerror("constant %v overflows %v", v.U.Xval, t)
+ Yyerror("constant %v overflows %v", v.U.(*Mpint), t)
case CTFLT:
- Yyerror("constant %v overflows %v", Fconv(v.U.Fval, obj.FmtSharp), t)
+ Yyerror("constant %v overflows %v", Fconv(v.U.(*Mpflt), obj.FmtSharp), t)
case CTCPLX:
- Yyerror("constant %v overflows %v", Fconv(v.U.Fval, obj.FmtSharp), t)
+ Yyerror("constant %v overflows %v", Fconv(v.U.(*Mpflt), obj.FmtSharp), t)
}
}
func tostr(v Val) Val {
switch v.Ctype {
case CTINT, CTRUNE:
- if Mpcmpfixfix(v.U.Xval, Minintval[TINT]) < 0 || Mpcmpfixfix(v.U.Xval, Maxintval[TINT]) > 0 {
+ if Mpcmpfixfix(v.U.(*Mpint), Minintval[TINT]) < 0 || Mpcmpfixfix(v.U.(*Mpint), Maxintval[TINT]) > 0 {
Yyerror("overflow in int -> string")
}
- r := uint(Mpgetfix(v.U.Xval))
+ r := uint(Mpgetfix(v.U.(*Mpint)))
v = Val{}
v.Ctype = CTSTR
- v.U.Sval = string(r)
+ v.U = string(r)
case CTFLT:
Yyerror("no float -> string")
@@ -430,7 +473,7 @@ func tostr(v Val) Val {
case CTNIL:
v = Val{}
v.Ctype = CTSTR
- v.U.Sval = ""
+ v.U = ""
}
return v
@@ -519,7 +562,7 @@ func evconst(n *Node) {
l2 = l1
for l2 != nil && Isconst(l2.N, CTSTR) {
nr = l2.N
- strs = append(strs, nr.Val.U.Sval)
+ strs = append(strs, nr.Val.U.(string))
l2 = l2.Next
}
@@ -527,7 +570,7 @@ func evconst(n *Node) {
*nl = *l1.N
nl.Orig = nl
nl.Val.Ctype = CTSTR
- nl.Val.U.Sval = strings.Join(strs, "")
+ nl.Val.U = strings.Join(strs, "")
l1.N = nl
l1.Next = l2
}
@@ -607,7 +650,7 @@ func evconst(n *Node) {
case OMINUS<<16 | CTINT,
OMINUS<<16 | CTRUNE:
- mpnegfix(v.U.Xval)
+ mpnegfix(v.U.(*Mpint))
case OCOM<<16 | CTINT,
OCOM<<16 | CTRUNE:
@@ -634,23 +677,23 @@ func evconst(n *Node) {
mpmovefixfix(&b, Maxintval[et])
}
- mpxorfixfix(v.U.Xval, &b)
+ mpxorfixfix(v.U.(*Mpint), &b)
case OPLUS<<16 | CTFLT:
break
case OMINUS<<16 | CTFLT:
- mpnegflt(v.U.Fval)
+ mpnegflt(v.U.(*Mpflt))
case OPLUS<<16 | CTCPLX:
break
case OMINUS<<16 | CTCPLX:
- mpnegflt(&v.U.Cval.Real)
- mpnegflt(&v.U.Cval.Imag)
+ mpnegflt(&v.U.(*Mpcplx).Real)
+ mpnegflt(&v.U.(*Mpcplx).Imag)
case ONOT<<16 | CTBOOL:
- if !v.U.Bval {
+ if !v.U.(bool) {
goto settrue
}
goto setfalse
@@ -754,77 +797,77 @@ func evconst(n *Node) {
case OADD<<16 | CTINT,
OADD<<16 | CTRUNE:
- mpaddfixfix(v.U.Xval, rv.U.Xval, 0)
+ mpaddfixfix(v.U.(*Mpint), rv.U.(*Mpint), 0)
case OSUB<<16 | CTINT,
OSUB<<16 | CTRUNE:
- mpsubfixfix(v.U.Xval, rv.U.Xval)
+ mpsubfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case OMUL<<16 | CTINT,
OMUL<<16 | CTRUNE:
- mpmulfixfix(v.U.Xval, rv.U.Xval)
+ mpmulfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case ODIV<<16 | CTINT,
ODIV<<16 | CTRUNE:
- if mpcmpfixc(rv.U.Xval, 0) == 0 {
+ if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
Yyerror("division by zero")
- Mpmovecfix(v.U.Xval, 1)
+ mpsetovf(v.U.(*Mpint))
break
}
- mpdivfixfix(v.U.Xval, rv.U.Xval)
+ mpdivfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case OMOD<<16 | CTINT,
OMOD<<16 | CTRUNE:
- if mpcmpfixc(rv.U.Xval, 0) == 0 {
+ if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
Yyerror("division by zero")
- Mpmovecfix(v.U.Xval, 1)
+ mpsetovf(v.U.(*Mpint))
break
}
- mpmodfixfix(v.U.Xval, rv.U.Xval)
+ mpmodfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case OLSH<<16 | CTINT,
OLSH<<16 | CTRUNE:
- mplshfixfix(v.U.Xval, rv.U.Xval)
+ mplshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case ORSH<<16 | CTINT,
ORSH<<16 | CTRUNE:
- mprshfixfix(v.U.Xval, rv.U.Xval)
+ mprshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case OOR<<16 | CTINT,
OOR<<16 | CTRUNE:
- mporfixfix(v.U.Xval, rv.U.Xval)
+ mporfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case OAND<<16 | CTINT,
OAND<<16 | CTRUNE:
- mpandfixfix(v.U.Xval, rv.U.Xval)
+ mpandfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case OANDNOT<<16 | CTINT,
OANDNOT<<16 | CTRUNE:
- mpandnotfixfix(v.U.Xval, rv.U.Xval)
+ mpandnotfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case OXOR<<16 | CTINT,
OXOR<<16 | CTRUNE:
- mpxorfixfix(v.U.Xval, rv.U.Xval)
+ mpxorfixfix(v.U.(*Mpint), rv.U.(*Mpint))
case OADD<<16 | CTFLT:
- mpaddfltflt(v.U.Fval, rv.U.Fval)
+ mpaddfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
case OSUB<<16 | CTFLT:
- mpsubfltflt(v.U.Fval, rv.U.Fval)
+ mpsubfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
case OMUL<<16 | CTFLT:
- mpmulfltflt(v.U.Fval, rv.U.Fval)
+ mpmulfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
case ODIV<<16 | CTFLT:
- if mpcmpfltc(rv.U.Fval, 0) == 0 {
+ if mpcmpfltc(rv.U.(*Mpflt), 0) == 0 {
Yyerror("division by zero")
- Mpmovecflt(v.U.Fval, 1.0)
+ Mpmovecflt(v.U.(*Mpflt), 1.0)
break
}
- mpdivfltflt(v.U.Fval, rv.U.Fval)
+ mpdivfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
// The default case above would print 'ideal % ideal',
// which is not quite an ideal error.
@@ -837,25 +880,25 @@ func evconst(n *Node) {
return
case OADD<<16 | CTCPLX:
- mpaddfltflt(&v.U.Cval.Real, &rv.U.Cval.Real)
- mpaddfltflt(&v.U.Cval.Imag, &rv.U.Cval.Imag)
+ mpaddfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
+ mpaddfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
case OSUB<<16 | CTCPLX:
- mpsubfltflt(&v.U.Cval.Real, &rv.U.Cval.Real)
- mpsubfltflt(&v.U.Cval.Imag, &rv.U.Cval.Imag)
+ mpsubfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
+ mpsubfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
case OMUL<<16 | CTCPLX:
- cmplxmpy(v.U.Cval, rv.U.Cval)
+ cmplxmpy(v.U.(*Mpcplx), rv.U.(*Mpcplx))
case ODIV<<16 | CTCPLX:
- if mpcmpfltc(&rv.U.Cval.Real, 0) == 0 && mpcmpfltc(&rv.U.Cval.Imag, 0) == 0 {
+ if mpcmpfltc(&rv.U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&rv.U.(*Mpcplx).Imag, 0) == 0 {
Yyerror("complex division by zero")
- Mpmovecflt(&rv.U.Cval.Real, 1.0)
- Mpmovecflt(&rv.U.Cval.Imag, 0.0)
+ Mpmovecflt(&rv.U.(*Mpcplx).Real, 1.0)
+ Mpmovecflt(&rv.U.(*Mpcplx).Imag, 0.0)
break
}
- cmplxdiv(v.U.Cval, rv.U.Cval)
+ cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx))
case OEQ<<16 | CTNIL:
goto settrue
@@ -865,90 +908,90 @@ func evconst(n *Node) {
case OEQ<<16 | CTINT,
OEQ<<16 | CTRUNE:
- if Mpcmpfixfix(v.U.Xval, rv.U.Xval) == 0 {
+ if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) == 0 {
goto settrue
}
goto setfalse
case ONE<<16 | CTINT,
ONE<<16 | CTRUNE:
- if Mpcmpfixfix(v.U.Xval, rv.U.Xval) != 0 {
+ if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) != 0 {
goto settrue
}
goto setfalse
case OLT<<16 | CTINT,
OLT<<16 | CTRUNE:
- if Mpcmpfixfix(v.U.Xval, rv.U.Xval) < 0 {
+ if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) < 0 {
goto settrue
}
goto setfalse
case OLE<<16 | CTINT,
OLE<<16 | CTRUNE:
- if Mpcmpfixfix(v.U.Xval, rv.U.Xval) <= 0 {
+ if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) <= 0 {
goto settrue
}
goto setfalse
case OGE<<16 | CTINT,
OGE<<16 | CTRUNE:
- if Mpcmpfixfix(v.U.Xval, rv.U.Xval) >= 0 {
+ if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) >= 0 {
goto settrue
}
goto setfalse
case OGT<<16 | CTINT,
OGT<<16 | CTRUNE:
- if Mpcmpfixfix(v.U.Xval, rv.U.Xval) > 0 {
+ if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) > 0 {
goto settrue
}
goto setfalse
case OEQ<<16 | CTFLT:
- if mpcmpfltflt(v.U.Fval, rv.U.Fval) == 0 {
+ if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) == 0 {
goto settrue
}
goto setfalse
case ONE<<16 | CTFLT:
- if mpcmpfltflt(v.U.Fval, rv.U.Fval) != 0 {
+ if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) != 0 {
goto settrue
}
goto setfalse
case OLT<<16 | CTFLT:
- if mpcmpfltflt(v.U.Fval, rv.U.Fval) < 0 {
+ if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) < 0 {
goto settrue
}
goto setfalse
case OLE<<16 | CTFLT:
- if mpcmpfltflt(v.U.Fval, rv.U.Fval) <= 0 {
+ if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) <= 0 {
goto settrue
}
goto setfalse
case OGE<<16 | CTFLT:
- if mpcmpfltflt(v.U.Fval, rv.U.Fval) >= 0 {
+ if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) >= 0 {
goto settrue
}
goto setfalse
case OGT<<16 | CTFLT:
- if mpcmpfltflt(v.U.Fval, rv.U.Fval) > 0 {
+ if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) > 0 {
goto settrue
}
goto setfalse
case OEQ<<16 | CTCPLX:
- if mpcmpfltflt(&v.U.Cval.Real, &rv.U.Cval.Real) == 0 && mpcmpfltflt(&v.U.Cval.Imag, &rv.U.Cval.Imag) == 0 {
+ if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) == 0 && mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) == 0 {
goto settrue
}
goto setfalse
case ONE<<16 | CTCPLX:
- if mpcmpfltflt(&v.U.Cval.Real, &rv.U.Cval.Real) != 0 || mpcmpfltflt(&v.U.Cval.Imag, &rv.U.Cval.Imag) != 0 {
+ if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) != 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) != 0 {
goto settrue
}
goto setfalse
@@ -990,25 +1033,25 @@ func evconst(n *Node) {
goto setfalse
case OOROR<<16 | CTBOOL:
- if v.U.Bval || rv.U.Bval {
+ if v.U.(bool) || rv.U.(bool) {
goto settrue
}
goto setfalse
case OANDAND<<16 | CTBOOL:
- if v.U.Bval && rv.U.Bval {
+ if v.U.(bool) && rv.U.(bool) {
goto settrue
}
goto setfalse
case OEQ<<16 | CTBOOL:
- if v.U.Bval == rv.U.Bval {
+ if v.U.(bool) == rv.U.(bool) {
goto settrue
}
goto setfalse
case ONE<<16 | CTBOOL:
- if v.U.Bval != rv.U.Bval {
+ if v.U.(bool) != rv.U.(bool) {
goto settrue
}
goto setfalse
@@ -1033,7 +1076,7 @@ ret:
// truncate precision for non-ideal float.
if v.Ctype == CTFLT && n.Type.Etype != TIDEAL {
- n.Val.U.Fval = truncfltlit(v.U.Fval, n.Type)
+ n.Val.U = truncfltlit(v.U.(*Mpflt), n.Type)
}
return
@@ -1088,15 +1131,15 @@ func nodcplxlit(r Val, i Val) *Node {
c := new(Mpcplx)
n := Nod(OLITERAL, nil, nil)
n.Type = Types[TIDEAL]
- n.Val.U.Cval = c
+ n.Val.U = c
n.Val.Ctype = CTCPLX
if r.Ctype != CTFLT || i.Ctype != CTFLT {
Fatal("nodcplxlit ctype %d/%d", r.Ctype, i.Ctype)
}
- mpmovefltflt(&c.Real, r.U.Fval)
- mpmovefltflt(&c.Imag, i.U.Fval)
+ mpmovefltflt(&c.Real, r.U.(*Mpflt))
+ mpmovefltflt(&c.Imag, i.U.(*Mpflt))
return n
}
@@ -1311,7 +1354,7 @@ func defaultlit2(lp **Node, rp **Node, force int) {
}
func cmpslit(l, r *Node) int {
- return stringsCompare(l.Val.U.Sval, r.Val.U.Sval)
+ return stringsCompare(l.Val.U.(string), r.Val.U.(string))
}
func Smallintconst(n *Node) bool {
@@ -1328,7 +1371,7 @@ func Smallintconst(n *Node) bool {
return true
case TIDEAL, TINT64, TUINT64, TPTR64:
- if Mpcmpfixfix(n.Val.U.Xval, Minintval[TINT32]) < 0 || Mpcmpfixfix(n.Val.U.Xval, Maxintval[TINT32]) > 0 {
+ if Mpcmpfixfix(n.Val.U.(*Mpint), Minintval[TINT32]) < 0 || Mpcmpfixfix(n.Val.U.(*Mpint), Maxintval[TINT32]) > 0 {
break
}
return true
@@ -1351,10 +1394,10 @@ func nonnegconst(n *Node) int {
TINT64,
TUINT64,
TIDEAL:
- if Mpcmpfixfix(n.Val.U.Xval, Minintval[TUINT32]) < 0 || Mpcmpfixfix(n.Val.U.Xval, Maxintval[TINT32]) > 0 {
+ if Mpcmpfixfix(n.Val.U.(*Mpint), Minintval[TUINT32]) < 0 || Mpcmpfixfix(n.Val.U.(*Mpint), Maxintval[TINT32]) > 0 {
break
}
- return int(Mpgetfix(n.Val.U.Xval))
+ return int(Mpgetfix(n.Val.U.(*Mpint)))
}
}
@@ -1392,39 +1435,37 @@ func iconv(x int64, et int) int64 {
return x
}
-/*
- * convert constant val to type t; leave in con.
- * for back end.
- */
-func Convconst(con *Node, t *Type, val *Val) {
+// Convconst converts constant node n to type t and
+// places the result in con.
+func (n *Node) Convconst(con *Node, t *Type) {
tt := Simsimtype(t)
// copy the constant for conversion
Nodconst(con, Types[TINT8], 0)
con.Type = t
- con.Val = *val
+ con.Val = n.Val
if Isint[tt] {
con.Val.Ctype = CTINT
- con.Val.U.Xval = new(Mpint)
+ con.Val.U = new(Mpint)
var i int64
- switch val.Ctype {
+ switch n.Val.Ctype {
default:
- Fatal("convconst ctype=%d %v", val.Ctype, Tconv(t, obj.FmtLong))
+ Fatal("convconst ctype=%d %v", n.Val.Ctype, Tconv(t, obj.FmtLong))
case CTINT, CTRUNE:
- i = Mpgetfix(val.U.Xval)
+ i = Mpgetfix(n.Val.U.(*Mpint))
case CTBOOL:
- i = int64(obj.Bool2int(val.U.Bval))
+ i = int64(obj.Bool2int(n.Val.U.(bool)))
case CTNIL:
i = 0
}
i = iconv(i, tt)
- Mpmovecfix(con.Val.U.Xval, i)
+ Mpmovecfix(con.Val.U.(*Mpint), i)
return
}
@@ -1434,7 +1475,7 @@ func Convconst(con *Node, t *Type, val *Val) {
Fatal("convconst ctype=%d %v", con.Val.Ctype, t)
}
if tt == TFLOAT32 {
- con.Val.U.Fval = truncfltlit(con.Val.U.Fval, t)
+ con.Val.U = truncfltlit(con.Val.U.(*Mpflt), t)
}
return
}
@@ -1442,10 +1483,9 @@ func Convconst(con *Node, t *Type, val *Val) {
if Iscomplex[tt] {
con.Val = tocplx(con.Val)
if tt == TCOMPLEX64 {
- con.Val.U.Cval.Real = *truncfltlit(&con.Val.U.Cval.Real, Types[TFLOAT32])
- con.Val.U.Cval.Imag = *truncfltlit(&con.Val.U.Cval.Imag, Types[TFLOAT32])
+ con.Val.U.(*Mpcplx).Real = *truncfltlit(&con.Val.U.(*Mpcplx).Real, Types[TFLOAT32])
+ con.Val.U.(*Mpcplx).Imag = *truncfltlit(&con.Val.U.(*Mpcplx).Imag, Types[TFLOAT32])
}
-
return
}
diff --git a/src/cmd/internal/gc/cplx.go b/src/cmd/compile/internal/gc/cplx.go
index cf48c922d7..56a4892636 100644
--- a/src/cmd/internal/gc/cplx.go
+++ b/src/cmd/compile/internal/gc/cplx.go
@@ -89,8 +89,8 @@ func subnode(nr *Node, ni *Node, nc *Node) {
t := Types[tc]
if nc.Op == OLITERAL {
- nodfconst(nr, t, &nc.Val.U.Cval.Real)
- nodfconst(ni, t, &nc.Val.U.Cval.Imag)
+ nodfconst(nr, t, &nc.Val.U.(*Mpcplx).Real)
+ nodfconst(ni, t, &nc.Val.U.(*Mpcplx).Imag)
return
}
@@ -226,7 +226,7 @@ func nodfconst(n *Node, t *Type, fval *Mpflt) {
n.Op = OLITERAL
n.Addable = true
ullmancalc(n)
- n.Val.U.Fval = fval
+ n.Val.U = fval
n.Val.Ctype = CTFLT
n.Type = t
diff --git a/src/cmd/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go
index 08d2469094..4a9cb295c8 100644
--- a/src/cmd/internal/gc/dcl.go
+++ b/src/cmd/compile/internal/gc/dcl.go
@@ -183,7 +183,7 @@ func declare(n *Node, ctxt uint8) {
}
if ctxt == PEXTERN && s.Name == "init" {
- Yyerror("cannot declare init - must be func", s)
+ Yyerror("cannot declare init - must be func")
}
gen := 0
@@ -260,7 +260,7 @@ func variter(vl *NodeList, t *Node, el *NodeList) *NodeList {
v = vl.N
v.Op = ONAME
declare(v, dclcontext)
- v.Ntype = t
+ v.Param.Ntype = t
v.Defn = as2
if Funcdepth > 0 {
init = list(init, Nod(ODCL, v, nil))
@@ -288,7 +288,7 @@ func variter(vl *NodeList, t *Node, el *NodeList) *NodeList {
v = vl.N
v.Op = ONAME
declare(v, dclcontext)
- v.Ntype = t
+ v.Param.Ntype = t
if e != nil || Funcdepth > 0 || isblank(v) {
if Funcdepth > 0 {
@@ -313,18 +313,19 @@ func variter(vl *NodeList, t *Node, el *NodeList) *NodeList {
* new_name_list [[type] = expr_list]
*/
func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
+ lno := int32(0) // default is to leave line number alone in listtreecopy
if cl == nil {
if t != nil {
Yyerror("const declaration cannot have type without expression")
}
cl = lastconst
t = lasttype
+ lno = vl.N.Lineno
} else {
lastconst = cl
lasttype = t
}
-
- cl = listtreecopy(cl)
+ cl = listtreecopy(cl, lno)
var v *Node
var c *Node
@@ -342,7 +343,7 @@ func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
v.Op = OLITERAL
declare(v, dclcontext)
- v.Ntype = t
+ v.Param.Ntype = t
v.Defn = c
vv = list(vv, Nod(ODCLCONST, v, nil))
@@ -430,7 +431,7 @@ func oldname(s *Sym) *Node {
// are parsing x := 5 inside the closure, until we get to
// the := it looks like a reference to the outer x so we'll
// make x a closure variable unnecessarily.
- if n.Closure == nil || n.Closure.Funcdepth != Funcdepth {
+ if n.Param.Closure == nil || n.Param.Closure.Funcdepth != Funcdepth {
// create new closure var.
c := Nod(ONAME, nil, nil)
@@ -441,15 +442,15 @@ func oldname(s *Sym) *Node {
c.Addable = false
c.Ullman = 2
c.Funcdepth = Funcdepth
- c.Outer = n.Closure
- n.Closure = c
- c.Closure = n
+ c.Param.Outer = n.Param.Closure
+ n.Param.Closure = c
+ c.Param.Closure = n
c.Xoffset = 0
Curfn.Func.Cvars = list(Curfn.Func.Cvars, c)
}
// return ref to closure var, not original
- return n.Closure
+ return n.Param.Closure
}
return n
@@ -554,7 +555,7 @@ func ifacedcl(n *Node) {
dclcontext = PPARAM
markdcl()
Funcdepth++
- n.Outer = Curfn
+ n.Param.Outer = Curfn
Curfn = n
funcargs(n.Right)
@@ -583,13 +584,13 @@ func funchdr(n *Node) {
markdcl()
Funcdepth++
- n.Outer = Curfn
+ n.Param.Outer = Curfn
Curfn = n
if n.Nname != nil {
- funcargs(n.Nname.Ntype)
- } else if n.Ntype != nil {
- funcargs(n.Ntype)
+ funcargs(n.Nname.Param.Ntype)
+ } else if n.Param.Ntype != nil {
+ funcargs(n.Param.Ntype)
} else {
funcargs2(n.Type)
}
@@ -615,7 +616,7 @@ func funcargs(nt *Node) {
}
if n.Left != nil {
n.Left.Op = ONAME
- n.Left.Ntype = n.Right
+ n.Left.Param.Ntype = n.Right
declare(n.Left, PPARAM)
if dclcontext == PAUTO {
vargen++
@@ -632,7 +633,7 @@ func funcargs(nt *Node) {
}
if n.Left != nil {
n.Left.Op = ONAME
- n.Left.Ntype = n.Right
+ n.Left.Param.Ntype = n.Right
declare(n.Left, PPARAM)
if dclcontext == PAUTO {
vargen++
@@ -679,7 +680,7 @@ func funcargs(nt *Node) {
n.Left = nn
}
- n.Left.Ntype = n.Right
+ n.Left.Param.Ntype = n.Right
declare(n.Left, PPARAMOUT)
if dclcontext == PAUTO {
i++
@@ -747,8 +748,8 @@ func funcbody(n *Node) {
}
popdcl()
Funcdepth--
- Curfn = n.Outer
- n.Outer = nil
+ Curfn = n.Param.Outer
+ n.Param.Outer = nil
if Funcdepth == 0 {
dclcontext = PEXTERN
}
@@ -770,7 +771,7 @@ func typedcl0(s *Sym) *Node {
* return the ODCLTYPE node to use.
*/
func typedcl1(n *Node, t *Node, local bool) *Node {
- n.Ntype = t
+ n.Param.Ntype = t
n.Local = local
return Nod(ODCLTYPE, n, nil)
}
@@ -830,7 +831,7 @@ func structfield(n *Node) *Type {
switch n.Val.Ctype {
case CTSTR:
f.Note = new(string)
- *f.Note = n.Val.U.Sval
+ *f.Note = n.Val.U.(string)
default:
Yyerror("field annotation must be string")
diff --git a/src/cmd/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go
index c816feaa7f..2c134933c4 100644
--- a/src/cmd/internal/gc/esc.go
+++ b/src/cmd/compile/internal/gc/esc.go
@@ -154,7 +154,7 @@ func (v *bottomUpVisitor) visitcode(n *Node, min uint32) uint32 {
}
if n.Op == OCLOSURE {
- m := v.visit(n.Closure)
+ m := v.visit(n.Param.Closure)
if m < min {
min = m
}
@@ -379,7 +379,7 @@ type EscState struct {
theSink Node
dsts *NodeList // all dst nodes
- loopdepth int // for detecting nested loop scopes
+ loopdepth int32 // for detecting nested loop scopes
pdepth int // for debug printing in recursions.
dstcount int // diagnostic
edgecount int // diagnostic
@@ -387,6 +387,19 @@ type EscState struct {
recursive bool // recursive function or group of mutually recursive functions.
}
+// funcSym returns n.Nname.Sym if no nils are encountered along the way.
+func funcSym(n *Node) *Sym {
+ if n == nil || n.Nname == nil {
+ return nil
+ }
+ return n.Nname.Sym
+}
+
+// curfnSym returns n.Curfn.Nname.Sym if no nils are encountered along the way.
+func curfnSym(n *Node) *Sym {
+ return funcSym(n.Curfn)
+}
+
func escAnalyze(all *NodeList, recursive bool) {
var es EscState
e := &es
@@ -428,13 +441,7 @@ func escAnalyze(all *NodeList, recursive bool) {
if Debug['m'] != 0 {
for l := e.noesc; l != nil; l = l.Next {
if l.N.Esc == EscNone {
- var tmp *Sym
- if l.N.Curfn != nil && l.N.Curfn.Nname != nil {
- tmp = l.N.Curfn.Nname.Sym
- } else {
- tmp = nil
- }
- Warnl(int(l.N.Lineno), "%v %v does not escape", tmp, Nconv(l.N, obj.FmtShort))
+ Warnl(int(l.N.Lineno), "%v %v does not escape", curfnSym(l.N), Nconv(l.N, obj.FmtShort))
}
}
}
@@ -579,6 +586,19 @@ func esc(e *EscState, n *Node, up *Node) {
}
}
+ // Big stuff escapes unconditionally
+ // "Big" conditions that were scattered around in walk have been gathered here
+ if n.Esc != EscHeap && n.Type != nil && (n.Type.Width > MaxStackVarSize ||
+ n.Op == ONEW && n.Type.Type.Width >= 1<<16 ||
+ n.Op == OMAKESLICE && !isSmallMakeSlice(n)) {
+ if Debug['m'] > 1 {
+ Warnl(int(n.Lineno), "%v is too large for stack", n)
+ }
+ n.Esc = EscHeap
+ addrescapes(n)
+ escassign(e, &e.theSink, n)
+ }
+
esc(e, n.Left, n)
esc(e, n.Right, n)
esc(e, n.Ntest, n)
@@ -593,13 +613,7 @@ func esc(e *EscState, n *Node, up *Node) {
}
if Debug['m'] > 1 {
- var tmp *Sym
- if Curfn != nil && Curfn.Nname != nil {
- tmp = Curfn.Nname.Sym
- } else {
- tmp = nil
- }
- fmt.Printf("%v:[%d] %v esc: %v\n", Ctxt.Line(int(lineno)), e.loopdepth, tmp, n)
+ fmt.Printf("%v:[%d] %v esc: %v\n", Ctxt.Line(int(lineno)), e.loopdepth, funcSym(Curfn), n)
}
switch n.Op {
@@ -629,8 +643,12 @@ func esc(e *EscState, n *Node, up *Node) {
// Everything but fixed array is a dereference.
case ORANGE:
- if Isfixedarray(n.Type) && n.List != nil && n.List.Next != nil {
- escassign(e, n.List.Next.N, n.Right)
+ if n.List != nil && n.List.Next != nil {
+ if Isfixedarray(n.Type) {
+ escassign(e, n.List.Next.N, n.Right)
+ } else {
+ escassign(e, n.List.Next.N, addDereference(n.Right))
+ }
}
case OSWITCH:
@@ -670,13 +688,7 @@ func esc(e *EscState, n *Node, up *Node) {
// b escapes as well. If we ignore such OSLICEARR, we will conclude
// that b does not escape when b contents do.
if Debug['m'] != 0 {
- var tmp *Sym
- if n.Curfn != nil && n.Curfn.Nname != nil {
- tmp = n.Curfn.Nname.Sym
- } else {
- tmp = nil
- }
- Warnl(int(n.Lineno), "%v ignoring self-assignment to %v", tmp, Nconv(n.Left, obj.FmtShort))
+ Warnl(int(n.Lineno), "%v ignoring self-assignment to %v", curfnSym(n), Nconv(n.Left, obj.FmtShort))
}
break
@@ -763,7 +775,15 @@ func esc(e *EscState, n *Node, up *Node) {
for ll := n.List.Next; ll != nil; ll = ll.Next {
escassign(e, &e.theSink, ll.N) // lose track of assign to dereference
}
+ } else {
+ // append(slice1, slice2...) -- slice2 itself does not escape, but contents do.
+ slice2 := n.List.Next.N
+ escassign(e, &e.theSink, addDereference(slice2)) // lose track of assign of dereference
+ if Debug['m'] > 2 {
+ Warnl(int(n.Lineno), "%v special treatment of append(slice1, slice2...) %v", curfnSym(n), Nconv(n, obj.FmtShort))
+ }
}
+ escassign(e, &e.theSink, addDereference(n.List.N)) // The original elements are now leaked, too
case OCONV, OCONVNOP:
escassign(e, n, n.Left)
@@ -776,19 +796,15 @@ func esc(e *EscState, n *Node, up *Node) {
case OARRAYLIT:
if Isslice(n.Type) {
- n.Esc = EscNone // until proven otherwise
+ // Slice itself is not leaked until proven otherwise
+ n.Esc = EscNone
e.noesc = list(e.noesc, n)
n.Escloopdepth = e.loopdepth
+ }
- // Values make it to memory, lose track.
- for ll := n.List; ll != nil; ll = ll.Next {
- escassign(e, &e.theSink, ll.N.Right)
- }
- } else {
- // Link values to array.
- for ll := n.List; ll != nil; ll = ll.Next {
- escassign(e, n, ll.N.Right)
- }
+ // Link values to array/slice
+ for ll := n.List; ll != nil; ll = ll.Next {
+ escassign(e, n, ll.N.Right)
}
// Link values to struct.
@@ -833,8 +849,8 @@ func esc(e *EscState, n *Node, up *Node) {
if v.Op == OXXX { // unnamed out argument; see dcl.c:/^funcargs
continue
}
- a = v.Closure
- if !v.Byval {
+ a = v.Param.Closure
+ if !v.Name.Byval {
a = Nod(OADDR, a, nil)
a.Lineno = v.Lineno
a.Escloopdepth = e.loopdepth
@@ -909,14 +925,8 @@ func escassign(e *EscState, dst *Node, src *Node) {
}
if Debug['m'] > 1 {
- var tmp *Sym
- if Curfn != nil && Curfn.Nname != nil {
- tmp = Curfn.Nname.Sym
- } else {
- tmp = nil
- }
fmt.Printf("%v:[%d] %v escassign: %v(%v)[%v] = %v(%v)[%v]\n",
- Ctxt.Line(int(lineno)), e.loopdepth, tmp,
+ Ctxt.Line(int(lineno)), e.loopdepth, funcSym(Curfn),
Nconv(dst, obj.FmtShort), Jconv(dst, obj.FmtShort), Oconv(int(dst.Op), 0),
Nconv(src, obj.FmtShort), Jconv(src, obj.FmtShort), Oconv(int(src.Op), 0))
}
@@ -1038,12 +1048,15 @@ func escassign(e *EscState, dst *Node, src *Node) {
case OAPPEND:
// Append returns first argument.
+ // Subsequent arguments are already leaked because they are operands to append.
escassign(e, dst, src.List.N)
case OINDEX:
// Index of array preserves input value.
if Isfixedarray(src.Left.Type) {
escassign(e, dst, src.Left)
+ } else {
+ escflows(e, dst, src)
}
// Might be pointer arithmetic, in which case
@@ -1269,6 +1282,24 @@ func escNoteOutputParamFlow(e uint16, vargen int32, level Level) uint16 {
return (e &^ (bitsMaskForTag << shift)) | encodedFlow
}
+func initEscretval(e *EscState, n *Node, fntype *Type) {
+ i := 0
+ n.Escretval = nil // Suspect this is not nil for indirect calls.
+ for t := getoutargx(fntype).Type; t != nil; t = t.Down {
+ src := Nod(ONAME, nil, nil)
+ buf := fmt.Sprintf(".out%d", i)
+ i++
+ src.Sym = Lookup(buf)
+ src.Type = t.Type
+ src.Class = PAUTO
+ src.Curfn = Curfn
+ src.Escloopdepth = e.loopdepth
+ src.Used = true
+ src.Lineno = n.Lineno
+ n.Escretval = list(n.Escretval, src)
+ }
+}
+
// This is a bit messier than fortunate, pulled out of esc's big
// switch for clarity. We either have the paramnodes, which may be
// connected to other things through flows or we have the parameter type
@@ -1277,7 +1308,7 @@ func escNoteOutputParamFlow(e uint16, vargen int32, level Level) uint16 {
// this-package
func esccall(e *EscState, n *Node, up *Node) {
var fntype *Type
-
+ var indirect bool
var fn *Node
switch n.Op {
default:
@@ -1286,6 +1317,7 @@ func esccall(e *EscState, n *Node, up *Node) {
case OCALLFUNC:
fn = n.Left
fntype = fn.Type
+ indirect = fn.Op != ONAME || fn.Class != PFUNC
case OCALLMETH:
fn = n.Left.Right.Sym.Def
@@ -1297,6 +1329,7 @@ func esccall(e *EscState, n *Node, up *Node) {
case OCALLINTER:
fntype = n.Left.Type
+ indirect = true
}
ll := n.List
@@ -1307,8 +1340,30 @@ func esccall(e *EscState, n *Node, up *Node) {
}
}
+ if indirect {
+ // We know nothing!
+ // Leak all the parameters
+ for ; ll != nil; ll = ll.Next {
+ escassign(e, &e.theSink, ll.N)
+ if Debug['m'] > 2 {
+ fmt.Printf("%v::esccall:: indirect call <- %v, untracked\n", Ctxt.Line(int(lineno)), Nconv(ll.N, obj.FmtShort))
+ }
+ }
+ // Set up bogus outputs
+ initEscretval(e, n, fntype)
+ // If there is a receiver, it also leaks to heap.
+ if n.Op != OCALLFUNC {
+ t := getthisx(fntype).Type
+ src := n.Left.Left
+ if haspointers(t.Type) {
+ escassign(e, &e.theSink, src)
+ }
+ }
+ return
+ }
+
if fn != nil && fn.Op == ONAME && fn.Class == PFUNC &&
- fn.Defn != nil && fn.Defn.Nbody != nil && fn.Ntype != nil && fn.Defn.Esc < EscFuncTagged {
+ fn.Defn != nil && fn.Defn.Nbody != nil && fn.Param.Ntype != nil && fn.Defn.Esc < EscFuncTagged {
if Debug['m'] > 2 {
fmt.Printf("%v::esccall:: %v in recursive group\n", Ctxt.Line(int(lineno)), Nconv(n, obj.FmtShort))
}
@@ -1320,17 +1375,17 @@ func esccall(e *EscState, n *Node, up *Node) {
}
// set up out list on this call node
- for lr := fn.Ntype.Rlist; lr != nil; lr = lr.Next {
+ for lr := fn.Param.Ntype.Rlist; lr != nil; lr = lr.Next {
n.Escretval = list(n.Escretval, lr.N.Left) // type.rlist -> dclfield -> ONAME (PPARAMOUT)
}
// Receiver.
if n.Op != OCALLFUNC {
- escassign(e, fn.Ntype.Left.Left, n.Left.Left)
+ escassign(e, fn.Param.Ntype.Left.Left, n.Left.Left)
}
var src *Node
- for lr := fn.Ntype.List; ll != nil && lr != nil; ll, lr = ll.Next, lr.Next {
+ for lr := fn.Param.Ntype.List; ll != nil && lr != nil; ll, lr = ll.Next, lr.Next {
src = ll.N
if lr.N.Isddd && !n.Isddd {
// Introduce ODDDARG node to represent ... allocation.
@@ -1376,23 +1431,7 @@ func esccall(e *EscState, n *Node, up *Node) {
}
// set up out list on this call node with dummy auto ONAMES in the current (calling) function.
- i := 0
-
- var src *Node
- var buf string
- for t := getoutargx(fntype).Type; t != nil; t = t.Down {
- src = Nod(ONAME, nil, nil)
- buf = fmt.Sprintf(".out%d", i)
- i++
- src.Sym = Lookup(buf)
- src.Type = t.Type
- src.Class = PAUTO
- src.Curfn = Curfn
- src.Escloopdepth = e.loopdepth
- src.Used = true
- src.Lineno = n.Lineno
- n.Escretval = list(n.Escretval, src)
- }
+ initEscretval(e, n, fntype)
// print("esc analyzed fn: %#N (%+T) returning (%+H)\n", fn, fntype, n->escretval);
@@ -1405,9 +1444,8 @@ func esccall(e *EscState, n *Node, up *Node) {
}
}
- var a *Node
for t := getinargx(fntype).Type; ll != nil; ll = ll.Next {
- src = ll.N
+ src := ll.N
if t.Isddd && !n.Isddd {
// Introduce ODDDARG node to represent ... allocation.
src = Nod(ODDDARG, nil, nil)
@@ -1425,7 +1463,7 @@ func esccall(e *EscState, n *Node, up *Node) {
if haspointers(t.Type) {
if escassignfromtag(e, t.Note, n.Escretval, src) == EscNone && up.Op != ODEFER && up.Op != OPROC {
- a = src
+ a := src
for a.Op == OCONVNOP {
a = a.Left
}
@@ -1510,13 +1548,7 @@ func escflood(e *EscState, dst *Node) {
}
if Debug['m'] > 1 {
- var tmp *Sym
- if dst.Curfn != nil && dst.Curfn.Nname != nil {
- tmp = dst.Curfn.Nname.Sym
- } else {
- tmp = nil
- }
- fmt.Printf("\nescflood:%d: dst %v scope:%v[%d]\n", walkgen, Nconv(dst, obj.FmtShort), tmp, dst.Escloopdepth)
+ fmt.Printf("\nescflood:%d: dst %v scope:%v[%d]\n", walkgen, Nconv(dst, obj.FmtShort), curfnSym(dst), dst.Escloopdepth)
}
for l := dst.Escflowsrc; l != nil; l = l.Next {
@@ -1548,14 +1580,8 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
src.Esclevel = level
if Debug['m'] > 1 {
- var tmp *Sym
- if src.Curfn != nil && src.Curfn.Nname != nil {
- tmp = src.Curfn.Nname.Sym
- } else {
- tmp = nil
- }
fmt.Printf("escwalk: level:%d depth:%d %.*s op=%v %v(%v) scope:%v[%d]\n",
- level, e.pdepth, e.pdepth, "\t\t\t\t\t\t\t\t\t\t", Oconv(int(src.Op), 0), Nconv(src, obj.FmtShort), Jconv(src, obj.FmtShort), tmp, src.Escloopdepth)
+ level, e.pdepth, e.pdepth, "\t\t\t\t\t\t\t\t\t\t", Oconv(int(src.Op), 0), Nconv(src, obj.FmtShort), Jconv(src, obj.FmtShort), curfnSym(src), src.Escloopdepth)
}
e.pdepth++
@@ -1627,7 +1653,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
if leaks && Debug['m'] != 0 {
Warnl(int(src.Lineno), "leaking closure reference %v", Nconv(src, obj.FmtShort))
}
- escwalk(e, level, dst, src.Closure)
+ escwalk(e, level, dst, src.Param.Closure)
}
case OPTRLIT, OADDR:
@@ -1657,6 +1683,10 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
if Isfixedarray(src.Type) {
break
}
+ for ll := src.List; ll != nil; ll = ll.Next {
+ escwalk(e, level.dec(), dst, ll.N.Right)
+ }
+
fallthrough
case ODDDARG,
diff --git a/src/cmd/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index 1efc8150c5..5117490ac8 100644
--- a/src/cmd/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -64,7 +64,7 @@ func autoexport(n *Node, ctxt uint8) {
if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN {
return
}
- if n.Ntype != nil && n.Ntype.Op == OTFUNC && n.Ntype.Left != nil { // method
+ if n.Param != nil && n.Param.Ntype != nil && n.Param.Ntype.Op == OTFUNC && n.Param.Ntype.Left != nil { // method
return
}
diff --git a/src/cmd/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index 1a991a0a65..4b93363c73 100644
--- a/src/cmd/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -302,12 +302,12 @@ func Vconv(v *Val, flag int) string {
switch v.Ctype {
case CTINT:
if (flag&obj.FmtSharp != 0) || fmtmode == FExp {
- return Bconv(v.U.Xval, obj.FmtSharp)
+ return Bconv(v.U.(*Mpint), obj.FmtSharp)
}
- return Bconv(v.U.Xval, 0)
+ return Bconv(v.U.(*Mpint), 0)
case CTRUNE:
- x := Mpgetfix(v.U.Xval)
+ x := Mpgetfix(v.U.(*Mpint))
if ' ' <= x && x < 0x80 && x != '\\' && x != '\'' {
return fmt.Sprintf("'%c'", int(x))
}
@@ -317,34 +317,34 @@ func Vconv(v *Val, flag int) string {
if 0 <= x && x <= utf8.MaxRune {
return fmt.Sprintf("'\\U%08x'", uint64(x))
}
- return fmt.Sprintf("('\\x00' + %v)", v.U.Xval)
+ return fmt.Sprintf("('\\x00' + %v)", v.U.(*Mpint))
case CTFLT:
if (flag&obj.FmtSharp != 0) || fmtmode == FExp {
- return Fconv(v.U.Fval, 0)
+ return Fconv(v.U.(*Mpflt), 0)
}
- return Fconv(v.U.Fval, obj.FmtSharp)
+ return Fconv(v.U.(*Mpflt), obj.FmtSharp)
case CTCPLX:
if (flag&obj.FmtSharp != 0) || fmtmode == FExp {
- return fmt.Sprintf("(%v+%vi)", &v.U.Cval.Real, &v.U.Cval.Imag)
+ return fmt.Sprintf("(%v+%vi)", &v.U.(*Mpcplx).Real, &v.U.(*Mpcplx).Imag)
}
- if mpcmpfltc(&v.U.Cval.Real, 0) == 0 {
- return fmt.Sprintf("%vi", Fconv(&v.U.Cval.Imag, obj.FmtSharp))
+ if mpcmpfltc(&v.U.(*Mpcplx).Real, 0) == 0 {
+ return fmt.Sprintf("%vi", Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp))
}
- if mpcmpfltc(&v.U.Cval.Imag, 0) == 0 {
- return Fconv(&v.U.Cval.Real, obj.FmtSharp)
+ if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) == 0 {
+ return Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp)
}
- if mpcmpfltc(&v.U.Cval.Imag, 0) < 0 {
- return fmt.Sprintf("(%v%vi)", Fconv(&v.U.Cval.Real, obj.FmtSharp), Fconv(&v.U.Cval.Imag, obj.FmtSharp))
+ if mpcmpfltc(&v.U.(*Mpcplx).Imag, 0) < 0 {
+ return fmt.Sprintf("(%v%vi)", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp))
}
- return fmt.Sprintf("(%v+%vi)", Fconv(&v.U.Cval.Real, obj.FmtSharp), Fconv(&v.U.Cval.Imag, obj.FmtSharp))
+ return fmt.Sprintf("(%v+%vi)", Fconv(&v.U.(*Mpcplx).Real, obj.FmtSharp), Fconv(&v.U.(*Mpcplx).Imag, obj.FmtSharp))
case CTSTR:
- return strconv.Quote(v.U.Sval)
+ return strconv.Quote(v.U.(string))
case CTBOOL:
- if v.U.Bval {
+ if v.U.(bool) {
return "true"
}
return "false"
@@ -1127,7 +1127,7 @@ func exprfmt(n *Node, prec int) string {
// Special case: name used as local variable in export.
// _ becomes ~b%d internally; print as _ for export
case ONAME:
- if fmtmode == FExp && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
+ if (fmtmode == FExp || fmtmode == FErr) && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
return "_"
}
if fmtmode == FExp && n.Sym != nil && !isblank(n) && n.Vargen > 0 {
@@ -1199,7 +1199,7 @@ func exprfmt(n *Node, prec int) string {
if n.Nbody != nil {
return fmt.Sprintf("%v { %v }", n.Type, n.Nbody)
}
- return fmt.Sprintf("%v { %v }", n.Type, n.Closure.Nbody)
+ return fmt.Sprintf("%v { %v }", n.Type, n.Param.Closure.Nbody)
case OCOMPLIT:
ptrlit := n.Right != nil && n.Right.Implicit && n.Right.Type != nil && Isptr[n.Right.Type.Etype]
@@ -1521,9 +1521,9 @@ func nodedump(n *Node, flag int) string {
} else {
fmt.Fprintf(&buf, "%v%v", Oconv(int(n.Op), 0), Jconv(n, 0))
}
- if recur && n.Type == nil && n.Ntype != nil {
+ if recur && n.Type == nil && n.Param.Ntype != nil {
indent(&buf)
- fmt.Fprintf(&buf, "%v-ntype%v", Oconv(int(n.Op), 0), n.Ntype)
+ fmt.Fprintf(&buf, "%v-ntype%v", Oconv(int(n.Op), 0), n.Param.Ntype)
}
case OASOP:
@@ -1531,9 +1531,9 @@ func nodedump(n *Node, flag int) string {
case OTYPE:
fmt.Fprintf(&buf, "%v %v%v type=%v", Oconv(int(n.Op), 0), n.Sym, Jconv(n, 0), n.Type)
- if recur && n.Type == nil && n.Ntype != nil {
+ if recur && n.Type == nil && n.Param.Ntype != nil {
indent(&buf)
- fmt.Fprintf(&buf, "%v-ntype%v", Oconv(int(n.Op), 0), n.Ntype)
+ fmt.Fprintf(&buf, "%v-ntype%v", Oconv(int(n.Op), 0), n.Param.Ntype)
}
}
diff --git a/src/cmd/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go
index e6af897033..c0dd9964ea 100644
--- a/src/cmd/internal/gc/gen.go
+++ b/src/cmd/compile/internal/gc/gen.go
@@ -57,14 +57,14 @@ func addrescapes(n *Node) {
// expression to refer to stack copy
case PPARAM, PPARAMOUT:
- n.Stackparam = Nod(OPARAM, n, nil)
+ n.Param.Stackparam = Nod(OPARAM, n, nil)
- n.Stackparam.Type = n.Type
- n.Stackparam.Addable = true
+ n.Param.Stackparam.Type = n.Type
+ n.Param.Stackparam.Addable = true
if n.Xoffset == BADWIDTH {
Fatal("addrescapes before param assignment")
}
- n.Stackparam.Xoffset = n.Xoffset
+ n.Param.Stackparam.Xoffset = n.Xoffset
fallthrough
case PAUTO:
@@ -78,10 +78,10 @@ func addrescapes(n *Node) {
oldfn := Curfn
Curfn = n.Curfn
- n.Heapaddr = temp(Ptrto(n.Type))
+ n.Name.Heapaddr = temp(Ptrto(n.Type))
buf := fmt.Sprintf("&%v", n.Sym)
- n.Heapaddr.Sym = Lookup(buf)
- n.Heapaddr.Orig.Sym = n.Heapaddr.Sym
+ n.Name.Heapaddr.Sym = Lookup(buf)
+ n.Name.Heapaddr.Orig.Sym = n.Name.Heapaddr.Sym
n.Esc = EscHeap
if Debug['m'] != 0 {
fmt.Printf("%v: moved to heap: %v\n", n.Line(), n)
@@ -262,7 +262,7 @@ func cgen_dcl(n *Node) {
if n.Alloc == nil {
n.Alloc = callnew(n.Type)
}
- Cgen_as(n.Heapaddr, n.Alloc)
+ Cgen_as(n.Name.Heapaddr, n.Alloc)
}
/*
@@ -333,21 +333,22 @@ func Clearslim(n *Node) {
switch Simtype[n.Type.Etype] {
case TCOMPLEX64, TCOMPLEX128:
- z.Val.U.Cval = new(Mpcplx)
- Mpmovecflt(&z.Val.U.Cval.Real, 0.0)
- Mpmovecflt(&z.Val.U.Cval.Imag, 0.0)
+ z.Val.U = new(Mpcplx)
+ Mpmovecflt(&z.Val.U.(*Mpcplx).Real, 0.0)
+ Mpmovecflt(&z.Val.U.(*Mpcplx).Imag, 0.0)
case TFLOAT32, TFLOAT64:
var zero Mpflt
Mpmovecflt(&zero, 0.0)
z.Val.Ctype = CTFLT
- z.Val.U.Fval = &zero
+ z.Val.U = &zero
case TPTR32, TPTR64, TCHAN, TMAP:
z.Val.Ctype = CTNIL
case TBOOL:
z.Val.Ctype = CTBOOL
+ z.Val.U = false
case TINT8,
TINT16,
@@ -358,8 +359,8 @@ func Clearslim(n *Node) {
TUINT32,
TUINT64:
z.Val.Ctype = CTINT
- z.Val.U.Xval = new(Mpint)
- Mpmovecfix(z.Val.U.Xval, 0)
+ z.Val.U = new(Mpint)
+ Mpmovecfix(z.Val.U.(*Mpint), 0)
default:
Fatal("clearslim called on type %v", n.Type)
@@ -428,8 +429,7 @@ func cgen_dottype(n *Node, res, resok *Node, wb bool) {
Cgen(&iface, &r1)
if !isnilinter(n.Left.Type) {
// Holding itab, want concrete type in second word.
- Thearch.Gins(Thearch.Optoas(OCMP, byteptr), &r1, Nodintconst(0))
- p := Gbranch(Thearch.Optoas(OEQ, byteptr), nil, -1)
+ p := Thearch.Ginscmp(OEQ, byteptr, &r1, Nodintconst(0), -1)
r2 = r1
r2.Op = OINDREG
r2.Xoffset = int64(Widthptr)
@@ -438,8 +438,7 @@ func cgen_dottype(n *Node, res, resok *Node, wb bool) {
}
Regalloc(&r2, byteptr, nil)
Cgen(typename(n.Type), &r2)
- Thearch.Gins(Thearch.Optoas(OCMP, byteptr), &r1, &r2)
- p := Gbranch(Thearch.Optoas(ONE, byteptr), nil, -1)
+ p := Thearch.Ginscmp(ONE, byteptr, &r1, &r2, -1)
Regfree(&r2) // not needed for success path; reclaimed on one failure path
iface.Xoffset += int64(Widthptr)
Cgen(&iface, &r1)
@@ -521,8 +520,7 @@ func Cgen_As2dottype(n, res, resok *Node) {
Cgen(&iface, &r1)
if !isnilinter(n.Left.Type) {
// Holding itab, want concrete type in second word.
- Thearch.Gins(Thearch.Optoas(OCMP, byteptr), &r1, Nodintconst(0))
- p := Gbranch(Thearch.Optoas(OEQ, byteptr), nil, -1)
+ p := Thearch.Ginscmp(OEQ, byteptr, &r1, Nodintconst(0), -1)
r2 = r1
r2.Op = OINDREG
r2.Xoffset = int64(Widthptr)
@@ -531,8 +529,7 @@ func Cgen_As2dottype(n, res, resok *Node) {
}
Regalloc(&r2, byteptr, nil)
Cgen(typename(n.Type), &r2)
- Thearch.Gins(Thearch.Optoas(OCMP, byteptr), &r1, &r2)
- p := Gbranch(Thearch.Optoas(ONE, byteptr), nil, -1)
+ p := Thearch.Ginscmp(ONE, byteptr, &r1, &r2, -1)
iface.Type = n.Type
iface.Xoffset += int64(Widthptr)
Cgen(&iface, &r1)
@@ -556,122 +553,6 @@ func Cgen_As2dottype(n, res, resok *Node) {
}
/*
- * generate:
- * res = s[lo, hi];
- * n->left is s
- * n->list is (cap(s)-lo(TUINT), hi-lo(TUINT)[, lo*width(TUINTPTR)])
- * caller (cgen) guarantees res is an addable ONAME.
- *
- * called for OSLICE, OSLICE3, OSLICEARR, OSLICE3ARR, OSLICESTR.
- */
-func Cgen_slice(n *Node, res *Node) {
- cap := n.List.N
- len := n.List.Next.N
- var offs *Node
- if n.List.Next.Next != nil {
- offs = n.List.Next.Next.N
- }
-
- // evaluate base pointer first, because it is the only
- // possibly complex expression. once that is evaluated
- // and stored, updating the len and cap can be done
- // without making any calls, so without doing anything that
- // might cause preemption or garbage collection.
- // this makes the whole slice update atomic as far as the
- // garbage collector can see.
- base := temp(Types[TUINTPTR])
-
- tmplen := temp(Types[TINT])
- var tmpcap *Node
- if n.Op != OSLICESTR {
- tmpcap = temp(Types[TINT])
- } else {
- tmpcap = tmplen
- }
-
- var src Node
- if isnil(n.Left) {
- Tempname(&src, n.Left.Type)
- Cgen(n.Left, &src)
- } else {
- src = *n.Left
- }
- if n.Op == OSLICE || n.Op == OSLICE3 || n.Op == OSLICESTR {
- src.Xoffset += int64(Array_array)
- }
-
- if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
- if !Isptr[n.Left.Type.Etype] {
- Fatal("slicearr is supposed to work on pointer: %v\n", Nconv(n, obj.FmtSign))
- }
- Cgen(&src, base)
- Cgen_checknil(base)
- } else {
- src.Type = Types[Tptr]
- Cgen(&src, base)
- }
-
- // committed to the update
- Gvardef(res)
-
- // compute len and cap.
- // len = n-i, cap = m-i, and offs = i*width.
- // computing offs last lets the multiply overwrite i.
- Cgen((*Node)(len), tmplen)
-
- if n.Op != OSLICESTR {
- Cgen(cap, tmpcap)
- }
-
- // if new cap != 0 { base += add }
- // This avoids advancing base past the end of the underlying array/string,
- // so that it cannot point at the next object in memory.
- // If cap == 0, the base doesn't matter except insofar as it is 0 or non-zero.
- // In essence we are replacing x[i:j:k] where i == j == k
- // or x[i:j] where i == j == cap(x) with x[0:0:0].
- if offs != nil {
- p1 := gjmp(nil)
- p2 := gjmp(nil)
- Patch(p1, Pc)
-
- var con Node
- Nodconst(&con, tmpcap.Type, 0)
- cmp := Nod(OEQ, tmpcap, &con)
- typecheck(&cmp, Erv)
- Bgen(cmp, true, -1, p2)
-
- add := Nod(OADD, base, offs)
- typecheck(&add, Erv)
- Cgen(add, base)
-
- Patch(p2, Pc)
- }
-
- // dst.array = src.array [ + lo *width ]
- dst := *res
-
- dst.Xoffset += int64(Array_array)
- dst.Type = Types[Tptr]
- Cgen(base, &dst)
-
- // dst.len = hi [ - lo ]
- dst = *res
-
- dst.Xoffset += int64(Array_nel)
- dst.Type = Types[Simtype[TUINT]]
- Cgen(tmplen, &dst)
-
- if n.Op != OSLICESTR {
- // dst.cap = cap [ - lo ]
- dst = *res
-
- dst.Xoffset += int64(Array_cap)
- dst.Type = Types[Simtype[TUINT]]
- Cgen(tmpcap, &dst)
- }
-}
-
-/*
* gather series of offsets
* >=0 is direct addressed field
* <0 is pointer to next field (+1)
@@ -1085,7 +966,7 @@ func cgen_callmeth(n *Node, proc int) {
l := n.Left
if l.Op != ODOTMETH {
- Fatal("cgen_callmeth: not dotmethod: %v")
+ Fatal("cgen_callmeth: not dotmethod: %v", l)
}
n2 := *n
@@ -1241,7 +1122,7 @@ func componentgen_wb(nr, nl *Node, wb bool) bool {
nodl.Type = Ptrto(Types[TUINT8])
Regalloc(&nodr, Types[Tptr], nil)
p := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), nil, &nodr)
- Datastring(nr.Val.U.Sval, &p.From)
+ Datastring(nr.Val.U.(string), &p.From)
p.From.Type = obj.TYPE_ADDR
Thearch.Gmove(&nodr, &nodl)
Regfree(&nodr)
@@ -1249,7 +1130,7 @@ func componentgen_wb(nr, nl *Node, wb bool) bool {
// length
nodl.Type = Types[Simtype[TUINT]]
nodl.Xoffset += int64(Array_nel) - int64(Array_array)
- Nodconst(&nodr, nodl.Type, int64(len(nr.Val.U.Sval)))
+ Nodconst(&nodr, nodl.Type, int64(len(nr.Val.U.(string))))
Thearch.Gmove(&nodr, &nodl)
return true
}
diff --git a/src/cmd/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go
index 71bce0bf2c..dc33f62ba4 100644
--- a/src/cmd/internal/gc/go.go
+++ b/src/cmd/compile/internal/gc/go.go
@@ -6,7 +6,7 @@ package gc
import (
"bytes"
- "cmd/internal/gc/big"
+ "cmd/compile/internal/big"
"cmd/internal/obj"
)
@@ -83,13 +83,13 @@ type Mpcplx struct {
type Val struct {
Ctype int16
- U struct {
- Bval bool // bool value CTBOOL
- Xval *Mpint // int CTINT, rune CTRUNE
- Fval *Mpflt // float CTFLT
- Cval *Mpcplx // float CTCPLX
- Sval string // string CTSTR
- }
+ // U contains one of:
+ // bool bool when Ctype == CTBOOL
+ // *Mpint int when Ctype == CTINT, rune when Ctype == CTRUNE
+ // *Mpflt float when Ctype == CTFLT
+ // *Mpcplx pair of floats when Ctype == CTCPLX
+ // string string when Ctype == CTSTR
+ U interface{}
}
type Pkg struct {
@@ -448,7 +448,7 @@ var nsavederrors int
var nsyntaxerrors int
-var decldepth int
+var decldepth int32
var safemode int
@@ -778,13 +778,27 @@ type Arch struct {
Expandchecks func(*obj.Prog)
Getg func(*Node)
Gins func(int, *Node, *Node) *obj.Prog
+
+ // Ginscmp generates code comparing n1 to n2 and jumping away if op is satisfied.
+ // The returned prog should be Patch'ed with the jump target.
+ // If op is not satisfied, code falls through to the next emitted instruction.
+ // Likely is the branch prediction hint: +1 for likely, -1 for unlikely, 0 for no opinion.
+ //
+ // Ginscmp must be able to handle all kinds of arguments for n1 and n2,
+ // not just simple registers, although it can assume that there are no
+ // function calls needed during the evaluation, and on 32-bit systems
+ // the values are guaranteed not to be 64-bit values, so no in-memory
+ // temporaries are necessary.
+ Ginscmp func(op int, t *Type, n1, n2 *Node, likely int) *obj.Prog
+
// Ginsboolval inserts instructions to convert the result
// of a just-completed comparison to a boolean value.
// The first argument is the conditional jump instruction
// corresponding to the desired value.
// The second argument is the destination.
// If not present, Ginsboolval will be emulated with jumps.
- Ginsboolval func(int, *Node)
+ Ginsboolval func(int, *Node)
+
Ginscon func(int, int64, *Node)
Ginsnop func()
Gmove func(*Node, *Node)
diff --git a/src/cmd/internal/gc/go.y b/src/cmd/compile/internal/gc/go.y
index f1904b0085..ae2e7613ab 100644
--- a/src/cmd/internal/gc/go.y
+++ b/src/cmd/compile/internal/gc/go.y
@@ -21,6 +21,7 @@
package gc
import (
+ "fmt"
"strings"
)
%}
@@ -116,7 +117,68 @@ import (
%left ')'
%left PreferToRightParen
-// TODO(rsc): Add %error-verbose
+%error loadsys package LIMPORT '(' LLITERAL import_package import_there ',':
+ "unexpected comma during import block"
+
+%error loadsys package LIMPORT LNAME ';':
+ "missing import path; require quoted string"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header ';':
+ "missing { after if clause"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' LSWITCH if_header ';':
+ "missing { after switch clause"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' LFOR for_header ';':
+ "missing { after for clause"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' LFOR ';' LBODY:
+ "missing { after for clause"
+
+%error loadsys package imports LFUNC LNAME '(' ')' ';' '{':
+ "unexpected semicolon or newline before {"
+
+%error loadsys package imports LTYPE LNAME ';':
+ "unexpected semicolon or newline in type declaration"
+
+%error loadsys package imports LCHAN '}':
+ "unexpected } in channel type"
+
+%error loadsys package imports LCHAN ')':
+ "unexpected ) in channel type"
+
+%error loadsys package imports LCHAN ',':
+ "unexpected comma in channel type"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' if_stmt ';' LELSE:
+ "unexpected semicolon or newline before else"
+
+%error loadsys package imports LTYPE LNAME LINTERFACE '{' LNAME ',' LNAME:
+ "name list not allowed in interface type"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' LFOR LVAR LNAME '=' LNAME:
+ "var declaration not allowed in for initializer"
+
+%error loadsys package imports LVAR LNAME '[' ']' LNAME '{':
+ "unexpected { at end of statement"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' LVAR LNAME '[' ']' LNAME '{':
+ "unexpected { at end of statement"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' LDEFER LNAME ';':
+ "argument to go/defer must be function call"
+
+%error loadsys package imports LVAR LNAME '=' LNAME '{' LNAME ';':
+ "need trailing comma before newline in composite literal"
+
+%error loadsys package imports LVAR LNAME '=' comptype '{' LNAME ';':
+ "need trailing comma before newline in composite literal"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' LFUNC LNAME:
+ "nested func not allowed"
+
+%error loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header loop_body LELSE ';':
+ "else must be followed by if or statement block"
%%
file:
@@ -1130,13 +1192,13 @@ hidden_importsym:
{
var p *Pkg
- if $2.U.Sval == "" {
+ if $2.U.(string) == "" {
p = importpkg;
} else {
- if isbadimport($2.U.Sval) {
+ if isbadimport($2.U.(string)) {
errorexit();
}
- p = mkpkg($2.U.Sval);
+ p = mkpkg($2.U.(string));
}
$$ = Pkglookup($4.Name, p);
}
@@ -1144,13 +1206,13 @@ hidden_importsym:
{
var p *Pkg
- if $2.U.Sval == "" {
+ if $2.U.(string) == "" {
p = importpkg;
} else {
- if isbadimport($2.U.Sval) {
+ if isbadimport($2.U.(string)) {
errorexit();
}
- p = mkpkg($2.U.Sval);
+ p = mkpkg($2.U.(string));
}
$$ = Pkglookup("?", p);
}
@@ -1360,7 +1422,7 @@ fndcl:
$$ = Nod(ODCLFUNC, nil, nil);
$$.Nname = newfuncname($1);
$$.Nname.Defn = $$;
- $$.Nname.Ntype = t; // TODO: check if nname already has an ntype
+ $$.Nname.Param.Ntype = t; // TODO: check if nname already has an ntype
declare($$.Nname, PFUNC);
funchdr($$);
@@ -1395,7 +1457,7 @@ fndcl:
$$.Func.Shortname = newfuncname($4);
$$.Nname = methodname1($$.Func.Shortname, rcvr.Right);
$$.Nname.Defn = $$;
- $$.Nname.Ntype = t;
+ $$.Nname.Param.Ntype = t;
$$.Nname.Nointerface = nointerface;
declare($$.Nname, PFUNC);
@@ -1944,7 +2006,7 @@ oliteral:
hidden_import:
LIMPORT LNAME LLITERAL ';'
{
- importimport($2, $3.U.Sval);
+ importimport($2, $3.U.(string));
}
| LVAR hidden_pkg_importsym hidden_type ';'
{
@@ -1975,9 +2037,9 @@ hidden_import:
importlist = list(importlist, $2);
if Debug['E'] > 0 {
- print("import [%q] func %lN \n", importpkg.Path, $2);
+ fmt.Printf("import [%q] func %v \n", importpkg.Path, $2)
if Debug['m'] > 2 && $2.Func.Inl != nil {
- print("inl body:%+H\n", $2.Func.Inl);
+ fmt.Printf("inl body:%v\n", $2.Func.Inl)
}
}
}
@@ -2171,14 +2233,14 @@ hidden_literal:
$$ = nodlit($2);
switch($$.Val.Ctype){
case CTINT, CTRUNE:
- mpnegfix($$.Val.U.Xval);
+ mpnegfix($$.Val.U.(*Mpint));
break;
case CTFLT:
- mpnegflt($$.Val.U.Fval);
+ mpnegflt($$.Val.U.(*Mpflt));
break;
case CTCPLX:
- mpnegflt(&$$.Val.U.Cval.Real);
- mpnegflt(&$$.Val.U.Cval.Imag);
+ mpnegflt(&$$.Val.U.(*Mpcplx).Real);
+ mpnegflt(&$$.Val.U.(*Mpcplx).Imag);
break;
default:
Yyerror("bad negated constant");
@@ -2198,11 +2260,11 @@ hidden_constant:
{
if $2.Val.Ctype == CTRUNE && $4.Val.Ctype == CTINT {
$$ = $2;
- mpaddfixfix($2.Val.U.Xval, $4.Val.U.Xval, 0);
+ mpaddfixfix($2.Val.U.(*Mpint), $4.Val.U.(*Mpint), 0);
break;
}
- $4.Val.U.Cval.Real = $4.Val.U.Cval.Imag;
- Mpmovecflt(&$4.Val.U.Cval.Imag, 0.0);
+ $4.Val.U.(*Mpcplx).Real = $4.Val.U.(*Mpcplx).Imag;
+ Mpmovecflt(&$4.Val.U.(*Mpcplx).Imag, 0.0);
$$ = nodcplxlit($2.Val, $4.Val);
}
diff --git a/src/cmd/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go
index 53b3f6c41d..5ec4587e74 100644
--- a/src/cmd/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -90,6 +90,10 @@ func Gbranch(as int, t *Type, likely int) *obj.Prog {
p.From.Offset = int64(obj.Bool2int(likely > 0))
}
+ if Debug['g'] != 0 {
+ fmt.Printf("%v\n", p)
+ }
+
return p
}
@@ -210,7 +214,7 @@ func ggloblnod(nam *Node) {
p.To.Sym = nil
p.To.Type = obj.TYPE_CONST
p.To.Offset = nam.Type.Width
- if nam.Readonly {
+ if nam.Name.Readonly {
p.From3.Offset = obj.RODATA
}
if nam.Type != nil && !haspointers(nam.Type) {
@@ -365,7 +369,7 @@ func Naddr(a *obj.Addr, n *Node) {
if s == nil {
s = Lookup(".noname")
}
- if n.Method {
+ if n.Name.Method {
if n.Type != nil {
if n.Type.Sym != nil {
if n.Type.Sym.Pkg != nil {
@@ -408,20 +412,20 @@ func Naddr(a *obj.Addr, n *Node) {
case CTFLT:
a.Type = obj.TYPE_FCONST
- a.Val = mpgetflt(n.Val.U.Fval)
+ a.Val = mpgetflt(n.Val.U.(*Mpflt))
case CTINT, CTRUNE:
a.Sym = nil
a.Type = obj.TYPE_CONST
- a.Offset = Mpgetfix(n.Val.U.Xval)
+ a.Offset = Mpgetfix(n.Val.U.(*Mpint))
case CTSTR:
- datagostring(n.Val.U.Sval, a)
+ datagostring(n.Val.U.(string), a)
case CTBOOL:
a.Sym = nil
a.Type = obj.TYPE_CONST
- a.Offset = int64(obj.Bool2int(n.Val.U.Bval))
+ a.Offset = int64(obj.Bool2int(n.Val.U.(bool)))
case CTNIL:
a.Sym = nil
@@ -621,20 +625,20 @@ func gclean() {
for r := Thearch.REGMIN; r <= Thearch.REGMAX; r++ {
n := reg[r-Thearch.REGMIN]
if n != 0 {
- Yyerror("reg %v left allocated", obj.Rconv(r))
if Debug['v'] != 0 {
Regdump()
}
+ Yyerror("reg %v left allocated", obj.Rconv(r))
}
}
for r := Thearch.FREGMIN; r <= Thearch.FREGMAX; r++ {
n := reg[r-Thearch.REGMIN]
if n != 0 {
- Yyerror("reg %v left allocated", obj.Rconv(r))
if Debug['v'] != 0 {
Regdump()
}
+ Yyerror("reg %v left allocated", obj.Rconv(r))
}
}
}
diff --git a/src/cmd/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go
index b5d1e505a5..92bfeecdef 100644
--- a/src/cmd/internal/gc/init.go
+++ b/src/cmd/compile/internal/gc/init.go
@@ -116,7 +116,7 @@ func fninit(n *NodeList) {
initsym := Lookup("init")
fn.Nname = newname(initsym)
fn.Nname.Defn = fn
- fn.Nname.Ntype = Nod(OTFUNC, nil, nil)
+ fn.Nname.Param.Ntype = Nod(OTFUNC, nil, nil)
declare(fn.Nname, PFUNC)
funchdr(fn)
diff --git a/src/cmd/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go
index dd2087dec3..22a5d3d9fe 100644
--- a/src/cmd/internal/gc/inl.go
+++ b/src/cmd/compile/internal/gc/inl.go
@@ -511,10 +511,10 @@ func mkinlcall(np **Node, fn *Node, isddd bool) {
func tinlvar(t *Type) *Node {
if t.Nname != nil && !isblank(t.Nname) {
- if t.Nname.Inlvar == nil {
+ if t.Nname.Name.Inlvar == nil {
Fatal("missing inlvar for %v\n", t.Nname)
}
- return t.Nname.Inlvar
+ return t.Nname.Name.Inlvar
}
typecheck(&nblank, Erv|Easgn)
@@ -577,13 +577,13 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
continue
}
if ll.N.Op == ONAME {
- ll.N.Inlvar = inlvar(ll.N)
+ ll.N.Name.Inlvar = inlvar(ll.N)
// Typecheck because inlvar is not necessarily a function parameter.
- typecheck(&ll.N.Inlvar, Erv)
+ typecheck(&ll.N.Name.Inlvar, Erv)
if ll.N.Class&^PHEAP != PAUTO {
- ninit = list(ninit, Nod(ODCL, ll.N.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs
+ ninit = list(ninit, Nod(ODCL, ll.N.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs
}
}
}
@@ -594,7 +594,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
if t != nil && t.Nname != nil && !isblank(t.Nname) {
m = inlvar(t.Nname)
typecheck(&m, Erv)
- t.Nname.Inlvar = m
+ t.Nname.Name.Inlvar = m
} else {
// anonymous return values, synthesize names for use in assignment that replaces return
m = retvar(t, i)
@@ -611,7 +611,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
// method call with a receiver.
t := getthisx(fn.Type).Type
- if t != nil && t.Nname != nil && !isblank(t.Nname) && t.Nname.Inlvar == nil {
+ if t != nil && t.Nname != nil && !isblank(t.Nname) && t.Nname.Name.Inlvar == nil {
Fatal("missing inlvar for %v\n", t.Nname)
}
if n.Left.Left == nil {
@@ -680,7 +680,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
// append receiver inlvar to LHS.
t := getthisx(fn.Type).Type
- if t != nil && t.Nname != nil && !isblank(t.Nname) && t.Nname.Inlvar == nil {
+ if t != nil && t.Nname != nil && !isblank(t.Nname) && t.Nname.Name.Inlvar == nil {
Fatal("missing inlvar for %v\n", t.Nname)
}
if t == nil {
@@ -907,11 +907,11 @@ func inlsubst(n *Node) *Node {
switch n.Op {
case ONAME:
- if n.Inlvar != nil { // These will be set during inlnode
+ if n.Name.Inlvar != nil { // These will be set during inlnode
if Debug['m'] > 2 {
- fmt.Printf("substituting name %v -> %v\n", Nconv(n, obj.FmtSign), Nconv(n.Inlvar, obj.FmtSign))
+ fmt.Printf("substituting name %v -> %v\n", Nconv(n, obj.FmtSign), Nconv(n.Name.Inlvar, obj.FmtSign))
}
- return n.Inlvar
+ return n.Name.Inlvar
}
if Debug['m'] > 2 {
diff --git a/src/cmd/internal/gc/lex.go b/src/cmd/compile/internal/gc/lex.go
index 4bbda957a5..cf41c40964 100644
--- a/src/cmd/internal/gc/lex.go
+++ b/src/cmd/compile/internal/gc/lex.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:generate go tool yacc go.y
-//go:generate go run yaccerrors.go
//go:generate go run mkbuiltin.go runtime unsafe
package gc
@@ -35,7 +34,11 @@ var goarch string
var goroot string
-var Debug_wb int
+var (
+ Debug_wb int
+ Debug_append int
+ Debug_slice int
+)
// Debug arguments.
// These can be specified with the -d flag, as in "-d nil"
@@ -45,9 +48,12 @@ var debugtab = []struct {
name string
val *int
}{
+ {"append", &Debug_append}, // print information about append compilation
+ {"disablenil", &Disable_checknil}, // disable nil checks
+ {"gcprog", &Debug_gcprog}, // print dump of GC programs
{"nil", &Debug_checknil}, // print information about nil checks
+ {"slice", &Debug_slice}, // print information about slice compilation
{"typeassert", &Debug_typeassert}, // print information about type assertion inlining
- {"disablenil", &Disable_checknil}, // disable nil checks
{"wb", &Debug_wb}, // print information about write barriers
}
@@ -308,7 +314,7 @@ func Main() {
lexlineno = 1
for _, infile = range flag.Args() {
- linehist(infile, 0, 0)
+ linehistpush(infile)
curio.infile = infile
var err error
@@ -339,7 +345,7 @@ func Main() {
errorexit()
}
- linehist("<pop>", 0, 0)
+ linehistpop()
if curio.bin != nil {
obj.Bterm(curio.bin)
}
@@ -394,7 +400,7 @@ func Main() {
// This needs to run before escape analysis,
// because variables captured by value do not escape.
for l := xtop; l != nil; l = l.Next {
- if l.N.Op == ODCLFUNC && l.N.Closure != nil {
+ if l.N.Op == ODCLFUNC && l.N.Param.Closure != nil {
Curfn = l.N
capturevars(l.N)
}
@@ -440,17 +446,15 @@ func Main() {
// which stores the addresses of stack variables into the closure.
// If the closure does not escape, it needs to be on the stack
// or else the stack copier will not update it.
+ // Large values are also moved off stack in escape analysis;
+ // because large values may contain pointers, it must happen early.
escapes(xtop)
- // Escape analysis moved escaped values off stack.
- // Move large values off stack too.
- movelarge(xtop)
-
// Phase 7: Transform closure bodies to properly reference captured variables.
// This needs to happen before walk, because closures must be transformed
// before walk reaches a call of a closure.
for l := xtop; l != nil; l = l.Next {
- if l.N.Op == ODCLFUNC && l.N.Closure != nil {
+ if l.N.Op == ODCLFUNC && l.N.Param.Closure != nil {
Curfn = l.N
transformclosure(l.N)
}
@@ -577,7 +581,7 @@ func findpkg(name string) (file string, ok bool) {
if obj.Access(file, 0) >= 0 {
return file, true
}
- file = fmt.Sprintf("%s.%c", name, Thearch.Thechar)
+ file = fmt.Sprintf("%s.o", name)
if obj.Access(file, 0) >= 0 {
return file, true
}
@@ -599,7 +603,7 @@ func findpkg(name string) (file string, ok bool) {
if obj.Access(file, 0) >= 0 {
return file, true
}
- file = fmt.Sprintf("%s/%s.%c", p.dir, name, Thearch.Thechar)
+ file = fmt.Sprintf("%s/%s.o", p.dir, name)
if obj.Access(file, 0) >= 0 {
return file, true
}
@@ -620,7 +624,7 @@ func findpkg(name string) (file string, ok bool) {
if obj.Access(file, 0) >= 0 {
return file, true
}
- file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.%c", goroot, goos, goarch, suffixsep, suffix, name, Thearch.Thechar)
+ file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.o", goroot, goos, goarch, suffixsep, suffix, name)
if obj.Access(file, 0) >= 0 {
return file, true
}
@@ -631,7 +635,7 @@ func findpkg(name string) (file string, ok bool) {
func fakeimport() {
importpkg = mkpkg("fake")
- cannedimports("fake.6", "$$\n")
+ cannedimports("fake.o", "$$\n")
}
func importfile(f *Val, line int) {
@@ -641,13 +645,13 @@ func importfile(f *Val, line int) {
return
}
- if len(f.U.Sval) == 0 {
+ if len(f.U.(string)) == 0 {
Yyerror("import path is empty")
fakeimport()
return
}
- if isbadimport(f.U.Sval) {
+ if isbadimport(f.U.(string)) {
fakeimport()
return
}
@@ -656,29 +660,29 @@ func importfile(f *Val, line int) {
// but we reserve the import path "main" to identify
// the main package, just as we reserve the import
// path "math" to identify the standard math package.
- if f.U.Sval == "main" {
+ if f.U.(string) == "main" {
Yyerror("cannot import \"main\"")
errorexit()
}
- if myimportpath != "" && f.U.Sval == myimportpath {
- Yyerror("import %q while compiling that package (import cycle)", f.U.Sval)
+ if myimportpath != "" && f.U.(string) == myimportpath {
+ Yyerror("import %q while compiling that package (import cycle)", f.U.(string))
errorexit()
}
- if f.U.Sval == "unsafe" {
+ if f.U.(string) == "unsafe" {
if safemode != 0 {
Yyerror("cannot import package unsafe")
errorexit()
}
- importpkg = mkpkg(f.U.Sval)
- cannedimports("unsafe.6", unsafeimport)
+ importpkg = mkpkg(f.U.(string))
+ cannedimports("unsafe.o", unsafeimport)
imported_unsafe = 1
return
}
- path_ := f.U.Sval
+ path_ := f.U.(string)
if islocalname(path_) {
if path_[0] == '/' {
Yyerror("import path cannot be absolute path")
@@ -704,7 +708,7 @@ func importfile(f *Val, line int) {
file, found := findpkg(path_)
if !found {
- Yyerror("can't find import: %q", f.U.Sval)
+ Yyerror("can't find import: %q", f.U.(string))
errorexit()
}
@@ -729,7 +733,7 @@ func importfile(f *Val, line int) {
var imp *obj.Biobuf
imp, err = obj.Bopenr(file)
if err != nil {
- Yyerror("can't open import: %q: %v", f.U.Sval, err)
+ Yyerror("can't open import: %q: %v", f.U.(string), err)
errorexit()
}
@@ -758,7 +762,7 @@ func importfile(f *Val, line int) {
// assume files move (get installed)
// so don't record the full path.
- linehist(file[len(file)-len(path_)-2:], -1, 1) // acts as #pragma lib
+ linehistpragma(file[len(file)-len(path_)-2:]) // acts as #pragma lib
/*
* position the input right
@@ -792,7 +796,7 @@ func importfile(f *Val, line int) {
return
}
- Yyerror("no import in %q", f.U.Sval)
+ Yyerror("no import in %q", f.U.(string))
unimportfile()
}
@@ -1060,8 +1064,8 @@ l0:
ungetc(int(v))
}
- yylval.val.U.Xval = new(Mpint)
- Mpmovecfix(yylval.val.U.Xval, v)
+ yylval.val.U = new(Mpint)
+ Mpmovecfix(yylval.val.U.(*Mpint), v)
yylval.val.Ctype = CTRUNE
if Debug['x'] != 0 {
fmt.Printf("lex: codepoint literal\n")
@@ -1399,11 +1403,11 @@ ncu:
ungetc(c)
str = lexbuf.String()
- yylval.val.U.Xval = new(Mpint)
- mpatofix(yylval.val.U.Xval, str)
- if yylval.val.U.Xval.Ovf {
+ yylval.val.U = new(Mpint)
+ mpatofix(yylval.val.U.(*Mpint), str)
+ if yylval.val.U.(*Mpint).Ovf {
Yyerror("overflow in constant")
- Mpmovecfix(yylval.val.U.Xval, 0)
+ Mpmovecfix(yylval.val.U.(*Mpint), 0)
}
yylval.val.Ctype = CTINT
@@ -1430,6 +1434,11 @@ casedot:
}
caseep:
+ if importpkg == nil && (c == 'p' || c == 'P') {
+ // <mantissa>p<base-2-exponent> is allowed in .a/.o imports,
+ // but not in .go sources. See #9036.
+ Yyerror("malformed floating point constant")
+ }
cp.WriteByte(byte(c))
c = getc()
if c == '+' || c == '-' {
@@ -1438,7 +1447,7 @@ caseep:
}
if !yy_isdigit(c) {
- Yyerror("malformed fp constant exponent")
+ Yyerror("malformed floating point constant exponent")
}
for yy_isdigit(c) {
cp.WriteByte(byte(c))
@@ -1455,12 +1464,12 @@ casei:
cp = nil
str = lexbuf.String()
- yylval.val.U.Cval = new(Mpcplx)
- Mpmovecflt(&yylval.val.U.Cval.Real, 0.0)
- mpatoflt(&yylval.val.U.Cval.Imag, str)
- if yylval.val.U.Cval.Imag.Val.IsInf() {
+ yylval.val.U = new(Mpcplx)
+ Mpmovecflt(&yylval.val.U.(*Mpcplx).Real, 0.0)
+ mpatoflt(&yylval.val.U.(*Mpcplx).Imag, str)
+ if yylval.val.U.(*Mpcplx).Imag.Val.IsInf() {
Yyerror("overflow in imaginary constant")
- Mpmovecflt(&yylval.val.U.Cval.Real, 0.0)
+ Mpmovecflt(&yylval.val.U.(*Mpcplx).Real, 0.0)
}
yylval.val.Ctype = CTCPLX
@@ -1475,11 +1484,11 @@ caseout:
ungetc(c)
str = lexbuf.String()
- yylval.val.U.Fval = newMpflt()
- mpatoflt(yylval.val.U.Fval, str)
- if yylval.val.U.Fval.Val.IsInf() {
+ yylval.val.U = newMpflt()
+ mpatoflt(yylval.val.U.(*Mpflt), str)
+ if yylval.val.U.(*Mpflt).Val.IsInf() {
Yyerror("overflow in float constant")
- Mpmovecflt(yylval.val.U.Fval, 0.0)
+ Mpmovecflt(yylval.val.U.(*Mpflt), 0.0)
}
yylval.val.Ctype = CTFLT
@@ -1490,7 +1499,7 @@ caseout:
return LLITERAL
strlit:
- yylval.val.U.Sval = internString(cp.Bytes())
+ yylval.val.U = internString(cp.Bytes())
yylval.val.Ctype = CTSTR
if Debug['x'] != 0 {
fmt.Printf("lex: string literal\n")
@@ -1649,7 +1658,7 @@ func getlinepragma() int {
}
name = text[:linep-1]
- linehist(name, int32(n), 0)
+ linehistupdate(name, n)
return c
out:
@@ -2590,6 +2599,6 @@ func mkpackage(pkgname string) {
if i := strings.LastIndex(p, "."); i >= 0 {
p = p[:i]
}
- outfile = fmt.Sprintf("%s.%c", p, Thearch.Thechar)
+ outfile = fmt.Sprintf("%s.o", p)
}
}
diff --git a/src/cmd/internal/gc/mkbuiltin.go b/src/cmd/compile/internal/gc/mkbuiltin.go
index b2362a6f01..f4569b48c2 100644
--- a/src/cmd/internal/gc/mkbuiltin.go
+++ b/src/cmd/compile/internal/gc/mkbuiltin.go
@@ -13,21 +13,14 @@ package main
import (
"bufio"
"fmt"
- "go/build"
"io"
"log"
"os"
"os/exec"
- "runtime"
"strings"
)
func main() {
- gochar, err := build.ArchChar(runtime.GOARCH)
- if err != nil {
- log.Fatal(err)
- }
-
f, err := os.Create("builtin.go")
if err != nil {
log.Fatal(err)
@@ -40,7 +33,7 @@ func main() {
fmt.Fprintln(w, "package gc")
for _, name := range os.Args[1:] {
- mkbuiltin(w, gochar, name)
+ mkbuiltin(w, name)
}
if err := w.Flush(); err != nil {
@@ -49,11 +42,11 @@ func main() {
}
// Compile .go file, import data from .6 file, and write Go string version.
-func mkbuiltin(w io.Writer, gochar string, name string) {
- if err := exec.Command("go", "tool", gochar+"g", "-A", "builtin/"+name+".go").Run(); err != nil {
+func mkbuiltin(w io.Writer, name string) {
+ if err := exec.Command("go", "tool", "compile", "-A", "builtin/"+name+".go").Run(); err != nil {
log.Fatal(err)
}
- obj := fmt.Sprintf("%s.%s", name, gochar)
+ obj := "name.o"
defer os.Remove(obj)
r, err := os.Open(obj)
@@ -77,7 +70,7 @@ Begin:
fmt.Fprintf(w, "\nconst %simport = \"\" +\n", name)
// sys.go claims to be in package PACKAGE to avoid
- // conflicts during "6g sys.go". Rename PACKAGE to $2.
+ // conflicts during "go tool compile sys.go". Rename PACKAGE to $2.
replacer := strings.NewReplacer("PACKAGE", name)
// Process imports, stopping at $$ that closes them.
diff --git a/src/cmd/internal/gc/mparith2.go b/src/cmd/compile/internal/gc/mparith2.go
index de96e97809..2c7e5176ac 100644
--- a/src/cmd/internal/gc/mparith2.go
+++ b/src/cmd/compile/internal/gc/mparith2.go
@@ -5,7 +5,7 @@
package gc
import (
- "cmd/internal/gc/big"
+ "cmd/compile/internal/big"
"cmd/internal/obj"
"fmt"
)
@@ -13,7 +13,7 @@ import (
/// implements fix arithmetic
func mpsetovf(a *Mpint) {
- a.Val.SetUint64(0)
+ a.Val.SetUint64(1) // avoid spurious div-zero errors
a.Ovf = true
}
diff --git a/src/cmd/internal/gc/mparith3.go b/src/cmd/compile/internal/gc/mparith3.go
index 2700b64a89..0e0b626475 100644
--- a/src/cmd/internal/gc/mparith3.go
+++ b/src/cmd/compile/internal/gc/mparith3.go
@@ -5,7 +5,7 @@
package gc
import (
- "cmd/internal/gc/big"
+ "cmd/compile/internal/big"
"cmd/internal/obj"
"fmt"
"math"
@@ -105,24 +105,8 @@ func mpcmpfltc(b *Mpflt, c float64) int {
return mpcmpfltflt(b, &a)
}
-func mpgetfltN(a *Mpflt, prec int, bias int) float64 {
- var x float64
- switch prec {
- case 53:
- x, _ = a.Val.Float64()
- case 24:
- // We should be using a.Val.Float32() here but that seems incorrect
- // for certain denormal values (all.bash fails). The current code
- // appears to work for all existing test cases, though there ought
- // to be issues with denormal numbers that are incorrectly rounded.
- // TODO(gri) replace with a.Val.Float32() once correctly working
- // See also: https://github.com/golang/go/issues/10321
- var t Mpflt
- t.Val.SetPrec(24).Set(&a.Val)
- x, _ = t.Val.Float64()
- default:
- panic("unreachable")
- }
+func mpgetflt(a *Mpflt) float64 {
+ x, _ := a.Val.Float64()
// check for overflow
if math.IsInf(x, 0) && nsavederrors+nerrors == 0 {
@@ -132,12 +116,16 @@ func mpgetfltN(a *Mpflt, prec int, bias int) float64 {
return x
}
-func mpgetflt(a *Mpflt) float64 {
- return mpgetfltN(a, 53, -1023)
-}
-
func mpgetflt32(a *Mpflt) float64 {
- return mpgetfltN(a, 24, -127)
+ x32, _ := a.Val.Float32()
+ x := float64(x32)
+
+ // check for overflow
+ if math.IsInf(x, 0) && nsavederrors+nerrors == 0 {
+ Yyerror("mpgetflt32 ovf")
+ }
+
+ return x
}
func Mpmovecflt(a *Mpflt, c float64) {
diff --git a/src/cmd/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index 05c5b1a811..9bb334ca34 100644
--- a/src/cmd/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -102,8 +102,7 @@ func dumpobj() {
obj.Bputc(bout, 0)
}
obj.Bseek(bout, startobj-ArhdrSize, 0)
- name := fmt.Sprintf("_go_.%c", Thearch.Thechar)
- formathdr(arhdr[:], name, size)
+ formathdr(arhdr[:], "_go_.o", size)
bout.Write(arhdr[:])
}
@@ -382,11 +381,11 @@ func gdata(nam *Node, nr *Node, wid int) {
if nr.Op == OLITERAL {
switch nr.Val.Ctype {
case CTCPLX:
- gdatacomplex(nam, nr.Val.U.Cval)
+ gdatacomplex(nam, nr.Val.U.(*Mpcplx))
return
case CTSTR:
- gdatastring(nam, nr.Val.U.Sval)
+ gdatastring(nam, nr.Val.U.(string))
return
}
}
diff --git a/src/cmd/internal/gc/opnames.go b/src/cmd/compile/internal/gc/opnames.go
index fc03ec6666..fc03ec6666 100644
--- a/src/cmd/internal/gc/opnames.go
+++ b/src/cmd/compile/internal/gc/opnames.go
diff --git a/src/cmd/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index f08f5f20fe..ee0ec52e7b 100644
--- a/src/cmd/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -104,9 +104,23 @@ func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node {
// If not, ordercheapexpr allocates a new tmp, emits tmp = n,
// and then returns tmp.
func ordercheapexpr(n *Node, order *Order) *Node {
+ if n == nil {
+ return nil
+ }
switch n.Op {
case ONAME, OLITERAL:
return n
+ case OLEN, OCAP:
+ l := ordercheapexpr(n.Left, order)
+ if l == n.Left {
+ return n
+ }
+ a := Nod(OXXX, nil, nil)
+ *a = *n
+ a.Orig = a
+ a.Left = l
+ typecheck(&a, Erv)
+ return a
}
return ordercopyexpr(n, n.Type, order, 0)
@@ -124,7 +138,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
case ONAME, OLITERAL:
return n
- case ODOT:
+ case ODOT, OLEN, OCAP:
l := ordersafeexpr(n.Left, order)
if l == n.Left {
return n
@@ -264,7 +278,7 @@ func orderblock(l **NodeList) {
func orderexprinplace(np **Node, outer *Order) {
n := *np
var order Order
- orderexpr(&n, &order)
+ orderexpr(&n, &order, nil)
addinit(&n, order.out)
// insert new temporaries from order
@@ -358,8 +372,8 @@ func ordercallargs(l **NodeList, order *Order) {
// Ordercall orders the call expression n.
// n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
func ordercall(n *Node, order *Order) {
- orderexpr(&n.Left, order)
- orderexpr(&n.Right, order) // ODDDARG temp
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right, order, nil) // ODDDARG temp
ordercallargs(&n.List, order)
}
@@ -447,8 +461,14 @@ func orderstmt(n *Node, order *Order) {
case OVARKILL:
order.out = list(order.out, n)
- case OAS,
- OAS2,
+ case OAS:
+ t := marktemp(order)
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right, order, n.Left)
+ ordermapassign(n, order)
+ cleantemp(t, order)
+
+ case OAS2,
OCLOSE,
OCOPY,
OPRINT,
@@ -456,38 +476,36 @@ func orderstmt(n *Node, order *Order) {
ORECOVER,
ORECV:
t := marktemp(order)
- orderexpr(&n.Left, order)
- orderexpr(&n.Right, order)
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right, order, nil)
orderexprlist(n.List, order)
orderexprlist(n.Rlist, order)
switch n.Op {
- case OAS, OAS2, OAS2DOTTYPE:
+ case OAS2, OAS2DOTTYPE:
ordermapassign(n, order)
-
default:
order.out = list(order.out, n)
}
-
cleantemp(t, order)
- // Special: rewrite l op= r into l = l op r.
- // This simplies quite a few operations;
- // most important is that it lets us separate
- // out map read from map write when l is
- // a map index expression.
case OASOP:
+ // Special: rewrite l op= r into l = l op r.
+ // This simplies quite a few operations;
+ // most important is that it lets us separate
+ // out map read from map write when l is
+ // a map index expression.
t := marktemp(order)
- orderexpr(&n.Left, order)
+ orderexpr(&n.Left, order, nil)
n.Left = ordersafeexpr(n.Left, order)
- tmp1 := treecopy(n.Left)
+ tmp1 := treecopy(n.Left, 0)
if tmp1.Op == OINDEXMAP {
tmp1.Etype = 0 // now an rvalue not an lvalue
}
tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
n.Right = Nod(int(n.Etype), tmp1, n.Right)
typecheck(&n.Right, Erv)
- orderexpr(&n.Right, order)
+ orderexpr(&n.Right, order, nil)
n.Etype = 0
n.Op = OAS
ordermapassign(n, order)
@@ -500,8 +518,8 @@ func orderstmt(n *Node, order *Order) {
orderexprlist(n.List, order)
r := n.Rlist.N
- orderexpr(&r.Left, order)
- orderexpr(&r.Right, order)
+ orderexpr(&r.Left, order, nil)
+ orderexpr(&r.Right, order, nil)
// See case OINDEXMAP below.
if r.Right.Op == OARRAYBYTESTR {
@@ -527,7 +545,7 @@ func orderstmt(n *Node, order *Order) {
t := marktemp(order)
orderexprlist(n.List, order)
- orderexpr(&n.Rlist.N.Left, order) // i in i.(T)
+ orderexpr(&n.Rlist.N.Left, order, nil) // i in i.(T)
if isblank(n.List.N) {
order.out = list(order.out, n)
} else {
@@ -548,7 +566,7 @@ func orderstmt(n *Node, order *Order) {
t := marktemp(order)
orderexprlist(n.List, order)
- orderexpr(&n.Rlist.N.Left, order) // arg to recv
+ orderexpr(&n.Rlist.N.Left, order, nil) // arg to recv
ch := n.Rlist.N.Left.Type
tmp1 := ordertemp(ch.Type, order, haspointers(ch.Type))
var tmp2 *Node
@@ -617,8 +635,8 @@ func orderstmt(n *Node, order *Order) {
case ODELETE:
t := marktemp(order)
- orderexpr(&n.List.N, order)
- orderexpr(&n.List.Next.N, order)
+ orderexpr(&n.List.N, order, nil)
+ orderexpr(&n.List.Next.N, order, nil)
orderaddrtemp(&n.List.Next.N, order) // map key
order.out = list(order.out, n)
cleantemp(t, order)
@@ -659,7 +677,7 @@ func orderstmt(n *Node, order *Order) {
case OPANIC:
t := marktemp(order)
- orderexpr(&n.Left, order)
+ orderexpr(&n.Left, order, nil)
if !Isinter(n.Left.Type) {
orderaddrtemp(&n.Left, order)
}
@@ -677,7 +695,7 @@ func orderstmt(n *Node, order *Order) {
case ORANGE:
t := marktemp(order)
- orderexpr(&n.Right, order)
+ orderexpr(&n.Right, order, nil)
switch n.Type.Etype {
default:
Fatal("orderstmt range %v", n.Type)
@@ -793,7 +811,7 @@ func orderstmt(n *Node, order *Order) {
// r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
// r->left == N means 'case <-c'.
// c is always evaluated; x and ok are only evaluated when assigned.
- orderexpr(&r.Right.Left, order)
+ orderexpr(&r.Right.Left, order, nil)
if r.Right.Left.Op != ONAME {
r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0)
@@ -853,12 +871,12 @@ func orderstmt(n *Node, order *Order) {
// case c <- x
// r->left is c, r->right is x, both are always evaluated.
- orderexpr(&r.Left, order)
+ orderexpr(&r.Left, order, nil)
if !istemp(r.Left) {
r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0)
}
- orderexpr(&r.Right, order)
+ orderexpr(&r.Right, order, nil)
if !istemp(r.Right) {
r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0)
}
@@ -884,8 +902,8 @@ func orderstmt(n *Node, order *Order) {
case OSEND:
t := marktemp(order)
- orderexpr(&n.Left, order)
- orderexpr(&n.Right, order)
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right, order, nil)
orderaddrtemp(&n.Right, order)
order.out = list(order.out, n)
cleantemp(t, order)
@@ -900,7 +918,7 @@ func orderstmt(n *Node, order *Order) {
case OSWITCH:
t := marktemp(order)
- orderexpr(&n.Ntest, order)
+ orderexpr(&n.Ntest, order, nil)
for l := n.List; l != nil; l = l.Next {
if l.N.Op != OXCASE {
Fatal("order switch case %v", Oconv(int(l.N.Op), 0))
@@ -919,7 +937,7 @@ func orderstmt(n *Node, order *Order) {
// Orderexprlist orders the expression list l into order.
func orderexprlist(l *NodeList, order *Order) {
for ; l != nil; l = l.Next {
- orderexpr(&l.N, order)
+ orderexpr(&l.N, order, nil)
}
}
@@ -933,7 +951,10 @@ func orderexprlistinplace(l *NodeList, order *Order) {
// Orderexpr orders a single expression, appending side
// effects to order->out as needed.
-func orderexpr(np **Node, order *Order) {
+// If this is part of an assignment lhs = *np, lhs is given.
+// Otherwise lhs == nil. (When lhs != nil it may be possible
+// to avoid copying the result of the expression to a temporary.)
+func orderexpr(np **Node, order *Order, lhs *Node) {
n := *np
if n == nil {
return
@@ -944,8 +965,8 @@ func orderexpr(np **Node, order *Order) {
switch n.Op {
default:
- orderexpr(&n.Left, order)
- orderexpr(&n.Right, order)
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right, order, nil)
orderexprlist(n.List, order)
orderexprlist(n.Rlist, order)
@@ -974,7 +995,7 @@ func orderexpr(np **Node, order *Order) {
haslit := false
for l := n.List; l != nil; l = l.Next {
hasbyte = hasbyte || l.N.Op == OARRAYBYTESTR
- haslit = haslit || l.N.Op == OLITERAL && len(l.N.Val.U.Sval) != 0
+ haslit = haslit || l.N.Op == OLITERAL && len(l.N.Val.U.(string)) != 0
}
if haslit && hasbyte {
@@ -986,8 +1007,8 @@ func orderexpr(np **Node, order *Order) {
}
case OCMPSTR:
- orderexpr(&n.Left, order)
- orderexpr(&n.Right, order)
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right, order, nil)
// Mark string(byteSlice) arguments to reuse byteSlice backing
// buffer during conversion. String comparison does not
@@ -1001,9 +1022,9 @@ func orderexpr(np **Node, order *Order) {
// key must be addressable
case OINDEXMAP:
- orderexpr(&n.Left, order)
+ orderexpr(&n.Left, order, nil)
- orderexpr(&n.Right, order)
+ orderexpr(&n.Right, order, nil)
// For x = m[string(k)] where k is []byte, the allocation of
// backing bytes for the string can be avoided by reusing
@@ -1029,7 +1050,7 @@ func orderexpr(np **Node, order *Order) {
// concrete type (not interface) argument must be addressable
// temporary to pass to runtime.
case OCONVIFACE:
- orderexpr(&n.Left, order)
+ orderexpr(&n.Left, order, nil)
if !Isinter(n.Left.Type) {
orderaddrtemp(&n.Left, order)
@@ -1037,7 +1058,7 @@ func orderexpr(np **Node, order *Order) {
case OANDAND, OOROR:
mark := marktemp(order)
- orderexpr(&n.Left, order)
+ orderexpr(&n.Left, order, nil)
// Clean temporaries from first branch at beginning of second.
// Leave them on the stack so that they can be killed in the outer
@@ -1048,8 +1069,7 @@ func orderexpr(np **Node, order *Order) {
n.Right.Ninit = concat(l, n.Right.Ninit)
orderexprinplace(&n.Right, order)
- case OAPPEND,
- OCALLFUNC,
+ case OCALLFUNC,
OCALLINTER,
OCALLMETH,
OCAP,
@@ -1064,7 +1084,37 @@ func orderexpr(np **Node, order *Order) {
OREAL,
ORECOVER:
ordercall(n, order)
- n = ordercopyexpr(n, n.Type, order, 0)
+ if lhs == nil || lhs.Op != ONAME || flag_race != 0 {
+ n = ordercopyexpr(n, n.Type, order, 0)
+ }
+
+ case OAPPEND:
+ ordercallargs(&n.List, order)
+ if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.N) {
+ n = ordercopyexpr(n, n.Type, order, 0)
+ }
+
+ case OSLICE, OSLICEARR, OSLICESTR:
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right.Left, order, nil)
+ n.Right.Left = ordercheapexpr(n.Right.Left, order)
+ orderexpr(&n.Right.Right, order, nil)
+ n.Right.Right = ordercheapexpr(n.Right.Right, order)
+ if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
+ n = ordercopyexpr(n, n.Type, order, 0)
+ }
+
+ case OSLICE3, OSLICE3ARR:
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right.Left, order, nil)
+ n.Right.Left = ordercheapexpr(n.Right.Left, order)
+ orderexpr(&n.Right.Right.Left, order, nil)
+ n.Right.Right.Left = ordercheapexpr(n.Right.Right.Left, order)
+ orderexpr(&n.Right.Right.Right, order, nil)
+ n.Right.Right.Right = ordercheapexpr(n.Right.Right.Right, order)
+ if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
+ n = ordercopyexpr(n, n.Type, order, 0)
+ }
case OCLOSURE:
if n.Noescape && n.Func.Cvars != nil {
@@ -1072,8 +1122,8 @@ func orderexpr(np **Node, order *Order) {
}
case OARRAYLIT, OCALLPART:
- orderexpr(&n.Left, order)
- orderexpr(&n.Right, order)
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right, order, nil)
orderexprlist(n.List, order)
orderexprlist(n.Rlist, order)
if n.Noescape {
@@ -1090,7 +1140,7 @@ func orderexpr(np **Node, order *Order) {
}
case ODOTTYPE, ODOTTYPE2:
- orderexpr(&n.Left, order)
+ orderexpr(&n.Left, order, nil)
// TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
// It needs to be removed in all three places.
// That would allow inlining x.(struct{*int}) the same as x.(*int).
@@ -1099,18 +1149,17 @@ func orderexpr(np **Node, order *Order) {
}
case ORECV:
- orderexpr(&n.Left, order)
+ orderexpr(&n.Left, order, nil)
n = ordercopyexpr(n, n.Type, order, 1)
case OEQ, ONE:
- orderexpr(&n.Left, order)
- orderexpr(&n.Right, order)
+ orderexpr(&n.Left, order, nil)
+ orderexpr(&n.Right, order, nil)
t := n.Left.Type
if t.Etype == TSTRUCT || Isfixedarray(t) {
// for complex comparisons, we need both args to be
// addressable so we can pass them to the runtime.
orderaddrtemp(&n.Left, order)
-
orderaddrtemp(&n.Right, order)
}
}
diff --git a/src/cmd/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index 2c225c8778..c170060896 100644
--- a/src/cmd/internal/gc/pgen.go
+++ b/src/cmd/compile/internal/gc/pgen.go
@@ -5,8 +5,8 @@
package gc
import (
+ "cmd/compile/internal/ssa"
"cmd/internal/obj"
- "cmd/internal/ssa"
"crypto/md5"
"fmt"
"strings"
@@ -201,8 +201,8 @@ func cmpstackvar(a *Node, b *Node) int {
return bp - ap
}
- ap = obj.Bool2int(a.Needzero)
- bp = obj.Bool2int(b.Needzero)
+ ap = obj.Bool2int(a.Name.Needzero)
+ bp = obj.Bool2int(b.Name.Needzero)
if ap != bp {
return bp - ap
}
@@ -302,25 +302,6 @@ func allocauto(ptxt *obj.Prog) {
}
}
-func movelarge(l *NodeList) {
- for ; l != nil; l = l.Next {
- if l.N.Op == ODCLFUNC {
- movelargefn(l.N)
- }
- }
-}
-
-func movelargefn(fn *Node) {
- var n *Node
-
- for l := fn.Func.Dcl; l != nil; l = l.Next {
- n = l.N
- if n.Class == PAUTO && n.Type != nil && n.Type.Width > MaxStackVarSize {
- addrescapes(n)
- }
- }
-}
-
func Cgen_checknil(n *Node) {
if Disable_checknil != 0 {
return
diff --git a/src/cmd/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go
index 040a77814e..b4d0699d1f 100644
--- a/src/cmd/internal/gc/plive.go
+++ b/src/cmd/compile/internal/gc/plive.go
@@ -944,7 +944,7 @@ func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
*xoffset += t.Width
case TARRAY:
- // The value of t->bound is -1 for slices types and >0 for
+ // The value of t->bound is -1 for slices types and >=0 for
// for fixed array types. All other values are invalid.
if t.Bound < -1 {
Fatal("onebitwalktype1: invalid bound, %v", t)
@@ -1281,8 +1281,8 @@ func livenessepilogue(lv *Liveness) {
}
bvset(all, pos) // silence future warnings in this block
n = lv.vars[pos]
- if !n.Needzero {
- n.Needzero = true
+ if !n.Name.Needzero {
+ n.Name.Needzero = true
if debuglive >= 1 {
Warnl(int(p.Lineno), "%v: %v is ambiguously live", Curfn.Nname, Nconv(n, obj.FmtLong))
}
diff --git a/src/cmd/internal/gc/popt.go b/src/cmd/compile/internal/gc/popt.go
index ce904e155b..ce904e155b 100644
--- a/src/cmd/internal/gc/popt.go
+++ b/src/cmd/compile/internal/gc/popt.go
diff --git a/src/cmd/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go
index e7f35006dc..05a902e8c1 100644
--- a/src/cmd/internal/gc/racewalk.go
+++ b/src/cmd/compile/internal/gc/racewalk.go
@@ -186,31 +186,6 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
// as we do not instrument runtime code.
// typedslicecopy is instrumented in runtime.
case OCALLFUNC:
- if n.Left.Sym != nil && n.Left.Sym.Pkg == Runtimepkg && (strings.HasPrefix(n.Left.Sym.Name, "writebarrier") || n.Left.Sym.Name == "typedmemmove") {
- // Find the dst argument.
- // The list can be reordered, so it's not necessary just the first or the second element.
- var l *NodeList
- for l = n.List; l != nil; l = l.Next {
- if n.Left.Sym.Name == "typedmemmove" {
- if l.N.Left.Xoffset == int64(Widthptr) {
- break
- }
- } else {
- if l.N.Left.Xoffset == 0 {
- break
- }
- }
- }
-
- if l == nil {
- Fatal("racewalk: writebarrier no arg")
- }
- if l.N.Right.Op != OADDR {
- Fatal("racewalk: writebarrier bad arg")
- }
- callinstr(&l.N.Right.Left, init, 1, 0)
- }
-
racewalknode(&n.Left, init, 0, 0)
goto ret
@@ -324,9 +299,8 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
}
goto ret
- // Seems to only lead to double instrumentation.
- //racewalknode(&n->left, init, 0, 0);
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR:
+ racewalknode(&n.Left, init, 0, 0)
goto ret
case OADDR:
@@ -509,7 +483,7 @@ func callinstr(np **Node, init **NodeList, wr int, skip int) bool {
*np = n
}
- n = treecopy(n)
+ n = treecopy(n, 0)
makeaddable(n)
var f *Node
if t.Etype == TSTRUCT || Isfixedarray(t) {
diff --git a/src/cmd/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go
index 03beb1c673..03beb1c673 100644
--- a/src/cmd/internal/gc/range.go
+++ b/src/cmd/compile/internal/gc/range.go
diff --git a/src/cmd/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index 9979fe85fd..6c0962f258 100644
--- a/src/cmd/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -5,8 +5,10 @@
package gc
import (
+ "cmd/internal/gcprog"
"cmd/internal/obj"
"fmt"
+ "os"
)
/*
@@ -687,7 +689,7 @@ func haspointers(t *Type) bool {
// typeptrdata returns the length in bytes of the prefix of t
// containing pointer data. Anything after this offset is scalar data.
-func typeptrdata(t *Type) uint64 {
+func typeptrdata(t *Type) int64 {
if !haspointers(t) {
return 0
}
@@ -699,24 +701,24 @@ func typeptrdata(t *Type) uint64 {
TFUNC,
TCHAN,
TMAP:
- return uint64(Widthptr)
+ return int64(Widthptr)
case TSTRING:
// struct { byte *str; intgo len; }
- return uint64(Widthptr)
+ return int64(Widthptr)
case TINTER:
// struct { Itab *tab; void *data; } or
// struct { Type *type; void *data; }
- return 2 * uint64(Widthptr)
+ return 2 * int64(Widthptr)
case TARRAY:
if Isslice(t) {
// struct { byte *array; uintgo len; uintgo cap; }
- return uint64(Widthptr)
+ return int64(Widthptr)
}
// haspointers already eliminated t.Bound == 0.
- return uint64(t.Bound-1)*uint64(t.Type.Width) + typeptrdata(t.Type)
+ return (t.Bound-1)*t.Type.Width + typeptrdata(t.Type)
case TSTRUCT:
// Find the last field that has pointers.
@@ -726,7 +728,7 @@ func typeptrdata(t *Type) uint64 {
lastPtrField = t1
}
}
- return uint64(lastPtrField.Width) + typeptrdata(lastPtrField.Type)
+ return lastPtrField.Width + typeptrdata(lastPtrField.Type)
default:
Fatal("typeptrdata: unexpected type, %v", t)
@@ -771,6 +773,8 @@ func dcommontype(s *Sym, ot int, t *Type) int {
// The linker magically takes the max of all the sizes.
zero := Pkglookup("zerovalue", Runtimepkg)
+ gcsym, useGCProg, ptrdata := dgcsym(t)
+
// We use size 0 here so we get the pointer to the zero value,
// but don't allocate space for the zero value unless we need it.
// TODO: how do we get this symbol into bss? We really want
@@ -787,14 +791,14 @@ func dcommontype(s *Sym, ot int, t *Type) int {
// fieldAlign uint8
// kind uint8
// alg unsafe.Pointer
- // gc unsafe.Pointer
+ // gcdata unsafe.Pointer
// string *string
// *extraType
// ptrToThis *Type
// zero unsafe.Pointer
// }
ot = duintptr(s, ot, uint64(t.Width))
- ot = duintptr(s, ot, typeptrdata(t))
+ ot = duintptr(s, ot, uint64(ptrdata))
ot = duint32(s, ot, typehash(t))
ot = duint8(s, ot, 0) // unused
@@ -811,8 +815,6 @@ func dcommontype(s *Sym, ot int, t *Type) int {
ot = duint8(s, ot, t.Align) // align
ot = duint8(s, ot, t.Align) // fieldAlign
- gcprog := usegcprog(t)
-
i = kinds[t.Etype]
if t.Etype == TARRAY && t.Bound < 0 {
i = obj.KindSlice
@@ -823,7 +825,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
if isdirectiface(t) {
i |= obj.KindDirectIface
}
- if gcprog {
+ if useGCProg {
i |= obj.KindGCProg
}
ot = duint8(s, ot, uint8(i)) // kind
@@ -832,48 +834,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
} else {
ot = dsymptr(s, ot, algsym, 0)
}
-
- // gc
- if gcprog {
- var gcprog1 *Sym
- var gcprog0 *Sym
- gengcprog(t, &gcprog0, &gcprog1)
- if gcprog0 != nil {
- ot = dsymptr(s, ot, gcprog0, 0)
- } else {
- ot = duintptr(s, ot, 0)
- }
- ot = dsymptr(s, ot, gcprog1, 0)
- } else {
- var gcmask [16]uint8
- gengcmask(t, gcmask[:])
- x1 := uint64(0)
- for i := 0; i < 8; i++ {
- x1 = x1<<8 | uint64(gcmask[i])
- }
- var p string
- if Widthptr == 4 {
- p = fmt.Sprintf("gcbits.0x%016x", x1)
- } else {
- x2 := uint64(0)
- for i := 0; i < 8; i++ {
- x2 = x2<<8 | uint64(gcmask[i+8])
- }
- p = fmt.Sprintf("gcbits.0x%016x%016x", x1, x2)
- }
-
- sbits := Pkglookup(p, Runtimepkg)
- if sbits.Flags&SymUniq == 0 {
- sbits.Flags |= SymUniq
- for i := 0; i < 2*Widthptr; i++ {
- duint8(sbits, i, gcmask[i])
- }
- ggloblsym(sbits, 2*int32(Widthptr), obj.DUPOK|obj.RODATA|obj.LOCAL)
- }
-
- ot = dsymptr(s, ot, sbits, 0)
- ot = duintptr(s, ot, 0)
- }
+ ot = dsymptr(s, ot, gcsym, 0)
p := Tconv(t, obj.FmtLeft|obj.FmtUnsigned)
@@ -1419,269 +1380,193 @@ func dalgsym(t *Type) *Sym {
return s
}
-func usegcprog(t *Type) bool {
- if !haspointers(t) {
- return false
- }
- if t.Width == BADWIDTH {
- dowidth(t)
+// maxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
+// which holds 1-bit entries describing where pointers are in a given type.
+// 16 bytes is enough to describe 128 pointer-sized words, 512 or 1024 bytes
+// depending on the system. Above this length, the GC information is
+// recorded as a GC program, which can express repetition compactly.
+// In either form, the information is used by the runtime to initialize the
+// heap bitmap, and for large types (like 128 or more words), they are
+// roughly the same speed. GC programs are never much larger and often
+// more compact. (If large arrays are involved, they can be arbitrarily more
+// compact.)
+//
+// The cutoff must be large enough that any allocation large enough to
+// use a GC program is large enough that it does not share heap bitmap
+// bytes with any other objects, allowing the GC program execution to
+// assume an aligned start and not use atomic operations. In the current
+// runtime, this means all malloc size classes larger than the cutoff must
+// be multiples of four words. On 32-bit systems that's 16 bytes, and
+// all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
+// On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
+// for size classes >= 256 bytes. On a 64-bit sytem, 256 bytes allocated
+// is 32 pointers, the bits for which fit in 4 bytes. So maxPtrmaskBytes
+// must be >= 4.
+//
+// We use 16 because the GC programs do have some constant overhead
+// to get started, and processing 128 pointers seems to be enough to
+// amortize that overhead well.
+const maxPtrmaskBytes = 16
+
+// dgcsym emits and returns a data symbol containing GC information for type t,
+// along with a boolean reporting whether the UseGCProg bit should be set in
+// the type kind, and the ptrdata field to record in the reflect type information.
+func dgcsym(t *Type) (sym *Sym, useGCProg bool, ptrdata int64) {
+ ptrdata = typeptrdata(t)
+ if ptrdata/int64(Widthptr) <= maxPtrmaskBytes*8 {
+ sym = dgcptrmask(t)
+ return
}
- // Calculate size of the unrolled GC mask.
- nptr := (t.Width + int64(Widthptr) - 1) / int64(Widthptr)
+ useGCProg = true
+ sym, ptrdata = dgcprog(t)
+ return
+}
+
+// dgcptrmask emits and returns the symbol containing a pointer mask for type t.
+func dgcptrmask(t *Type) *Sym {
+ ptrmask := make([]byte, (typeptrdata(t)/int64(Widthptr)+7)/8)
+ fillptrmask(t, ptrmask)
+ p := fmt.Sprintf("gcbits.%x", ptrmask)
- size := nptr
- if size%2 != 0 {
- size *= 2 // repeated
+ sym := Pkglookup(p, Runtimepkg)
+ if sym.Flags&SymUniq == 0 {
+ sym.Flags |= SymUniq
+ for i, x := range ptrmask {
+ duint8(sym, i, x)
+ }
+ ggloblsym(sym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL)
}
- size = size * obj.GcBits / 8 // 4 bits per word
-
- // Decide whether to use unrolled GC mask or GC program.
- // We could use a more elaborate condition, but this seems to work well in practice.
- // For small objects GC program can't give significant reduction.
- // While large objects usually contain arrays; and even if it don't
- // the program uses 2-bits per word while mask uses 4-bits per word,
- // so the program is still smaller.
- return size > int64(2*Widthptr)
+ return sym
}
-// Generates sparse GC bitmask (4 bits per word).
-func gengcmask(t *Type, gcmask []byte) {
- for i := int64(0); i < 16; i++ {
- gcmask[i] = 0
+// fillptrmask fills in ptrmask with 1s corresponding to the
+// word offsets in t that hold pointers.
+// ptrmask is assumed to fit at least typeptrdata(t)/Widthptr bits.
+func fillptrmask(t *Type, ptrmask []byte) {
+ for i := range ptrmask {
+ ptrmask[i] = 0
}
if !haspointers(t) {
return
}
- // Generate compact mask as stacks use.
+ vec := bvalloc(8 * int32(len(ptrmask)))
xoffset := int64(0)
-
- vec := bvalloc(2 * int32(Widthptr) * 8)
onebitwalktype1(t, &xoffset, vec)
- // Unfold the mask for the GC bitmap format:
- // 4 bits per word, 2 high bits encode pointer info.
- pos := gcmask
-
- nptr := (t.Width + int64(Widthptr) - 1) / int64(Widthptr)
- half := false
-
- // If number of words is odd, repeat the mask.
- // This makes simpler handling of arrays in runtime.
- var i int64
- var bits uint8
- for j := int64(0); j <= (nptr % 2); j++ {
- for i = 0; i < nptr; i++ {
- // convert 0=scalar / 1=pointer to GC bit encoding
- if bvget(vec, int32(i)) == 0 {
- bits = obj.BitsScalar
- } else {
- bits = obj.BitsPointer
- }
- bits <<= 2
- if half {
- bits <<= 4
- }
- pos[0] |= byte(bits)
- half = !half
- if !half {
- pos = pos[1:]
- }
+ nptr := typeptrdata(t) / int64(Widthptr)
+ for i := int64(0); i < nptr; i++ {
+ if bvget(vec, int32(i)) == 1 {
+ ptrmask[i/8] |= 1 << (uint(i) % 8)
}
}
}
-// Helper object for generation of GC programs.
-type ProgGen struct {
- s *Sym
- datasize int32
- data [256 / obj.PointersPerByte]uint8
- ot int64
-}
-
-func proggeninit(g *ProgGen, s *Sym) {
- g.s = s
- g.datasize = 0
- g.ot = 0
- g.data = [256 / obj.PointersPerByte]uint8{}
-}
-
-func proggenemit(g *ProgGen, v uint8) {
- g.ot = int64(duint8(g.s, int(g.ot), v))
-}
-
-// Emits insData block from g->data.
-func proggendataflush(g *ProgGen) {
- if g.datasize == 0 {
- return
+// dgcprog emits and returns the symbol containing a GC program for type t
+// along with the size of the data described by the program (in the range [typeptrdata(t), t.Width]).
+// In practice, the size is typeptrdata(t) except for non-trivial arrays.
+// For non-trivial arrays, the program describes the full t.Width size.
+func dgcprog(t *Type) (*Sym, int64) {
+ dowidth(t)
+ if t.Width == BADWIDTH {
+ Fatal("dgcprog: %v badwidth", t)
}
- proggenemit(g, obj.InsData)
- proggenemit(g, uint8(g.datasize))
- s := (g.datasize + obj.PointersPerByte - 1) / obj.PointersPerByte
- for i := int32(0); i < s; i++ {
- proggenemit(g, g.data[i])
+ sym := typesymprefix(".gcprog", t)
+ var p GCProg
+ p.init(sym)
+ p.emit(t, 0)
+ offset := p.w.BitIndex() * int64(Widthptr)
+ p.end()
+ if ptrdata := typeptrdata(t); offset < ptrdata || offset > t.Width {
+ Fatal("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Width)
}
- g.datasize = 0
- g.data = [256 / obj.PointersPerByte]uint8{}
+ return sym, offset
}
-func proggendata(g *ProgGen, d uint8) {
- g.data[g.datasize/obj.PointersPerByte] |= d << uint((g.datasize%obj.PointersPerByte)*obj.BitsPerPointer)
- g.datasize++
- if g.datasize == 255 {
- proggendataflush(g)
- }
+type GCProg struct {
+ sym *Sym
+ symoff int
+ w gcprog.Writer
}
-// Skip v bytes due to alignment, etc.
-func proggenskip(g *ProgGen, off int64, v int64) {
- for i := off; i < off+v; i++ {
- if (i % int64(Widthptr)) == 0 {
- proggendata(g, obj.BitsScalar)
- }
- }
-}
+var Debug_gcprog int // set by -d gcprog
-// Emit insArray instruction.
-func proggenarray(g *ProgGen, len int64) {
- proggendataflush(g)
- proggenemit(g, obj.InsArray)
- for i := int32(0); i < int32(Widthptr); i, len = i+1, len>>8 {
- proggenemit(g, uint8(len))
+func (p *GCProg) init(sym *Sym) {
+ p.sym = sym
+ p.symoff = 4 // first 4 bytes hold program length
+ p.w.Init(p.writeByte)
+ if Debug_gcprog > 0 {
+ fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", sym)
+ p.w.Debug(os.Stderr)
}
}
-func proggenarrayend(g *ProgGen) {
- proggendataflush(g)
- proggenemit(g, obj.InsArrayEnd)
+func (p *GCProg) writeByte(x byte) {
+ p.symoff = duint8(p.sym, p.symoff, x)
}
-func proggenfini(g *ProgGen) int64 {
- proggendataflush(g)
- proggenemit(g, obj.InsEnd)
- return g.ot
+func (p *GCProg) end() {
+ p.w.End()
+ duint32(p.sym, 0, uint32(p.symoff-4))
+ ggloblsym(p.sym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL)
+ if Debug_gcprog > 0 {
+ fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.sym)
+ }
}
-// Generates GC program for large types.
-func gengcprog(t *Type, pgc0 **Sym, pgc1 **Sym) {
- nptr := (t.Width + int64(Widthptr) - 1) / int64(Widthptr)
- size := nptr
- if size%2 != 0 {
- size *= 2 // repeated twice
+func (p *GCProg) emit(t *Type, offset int64) {
+ dowidth(t)
+ if !haspointers(t) {
+ return
}
- size = size * obj.PointersPerByte / 8 // 4 bits per word
- size++ // unroll flag in the beginning, used by runtime (see runtime.markallocated)
-
- // emity space in BSS for unrolled program
- *pgc0 = nil
-
- // Don't generate it if it's too large, runtime will unroll directly into GC bitmap.
- if size <= obj.MaxGCMask {
- gc0 := typesymprefix(".gc", t)
- ggloblsym(gc0, int32(size), obj.DUPOK|obj.NOPTR)
- *pgc0 = gc0
+ if t.Width == int64(Widthptr) {
+ p.w.Ptr(offset / int64(Widthptr))
+ return
}
-
- // program in RODATA
- gc1 := typesymprefix(".gcprog", t)
-
- var g ProgGen
- proggeninit(&g, gc1)
- xoffset := int64(0)
- gengcprog1(&g, t, &xoffset)
- ot := proggenfini(&g)
- ggloblsym(gc1, int32(ot), obj.DUPOK|obj.RODATA)
- *pgc1 = gc1
-}
-
-// Recursively walks type t and writes GC program into g.
-func gengcprog1(g *ProgGen, t *Type, xoffset *int64) {
switch t.Etype {
- case TINT8,
- TUINT8,
- TINT16,
- TUINT16,
- TINT32,
- TUINT32,
- TINT64,
- TUINT64,
- TINT,
- TUINT,
- TUINTPTR,
- TBOOL,
- TFLOAT32,
- TFLOAT64,
- TCOMPLEX64,
- TCOMPLEX128:
- proggenskip(g, *xoffset, t.Width)
- *xoffset += t.Width
-
- case TPTR32,
- TPTR64,
- TUNSAFEPTR,
- TFUNC,
- TCHAN,
- TMAP:
- proggendata(g, obj.BitsPointer)
- *xoffset += t.Width
+ default:
+ Fatal("GCProg.emit: unexpected type %v", t)
case TSTRING:
- proggendata(g, obj.BitsPointer)
- proggendata(g, obj.BitsScalar)
- *xoffset += t.Width
+ p.w.Ptr(offset / int64(Widthptr))
- // Assuming IfacePointerOnly=1.
case TINTER:
- proggendata(g, obj.BitsPointer)
-
- proggendata(g, obj.BitsPointer)
- *xoffset += t.Width
+ p.w.Ptr(offset / int64(Widthptr))
+ p.w.Ptr(offset/int64(Widthptr) + 1)
case TARRAY:
if Isslice(t) {
- proggendata(g, obj.BitsPointer)
- proggendata(g, obj.BitsScalar)
- proggendata(g, obj.BitsScalar)
- } else {
- t1 := t.Type
- if t1.Width == 0 {
- }
- // ignore
- if t.Bound <= 1 || t.Bound*t1.Width < int64(32*Widthptr) {
- for i := int64(0); i < t.Bound; i++ {
- gengcprog1(g, t1, xoffset)
- }
- } else if !haspointers(t1) {
- n := t.Width
- n -= -*xoffset & (int64(Widthptr) - 1) // skip to next ptr boundary
- proggenarray(g, (n+int64(Widthptr)-1)/int64(Widthptr))
- proggendata(g, obj.BitsScalar)
- proggenarrayend(g)
- *xoffset -= (n+int64(Widthptr)-1)/int64(Widthptr)*int64(Widthptr) - t.Width
- } else {
- proggenarray(g, t.Bound)
- gengcprog1(g, t1, xoffset)
- *xoffset += (t.Bound - 1) * t1.Width
- proggenarrayend(g)
+ p.w.Ptr(offset / int64(Widthptr))
+ return
+ }
+ if t.Bound == 0 {
+ // should have been handled by haspointers check above
+ Fatal("GCProg.emit: empty array")
+ }
+
+ // Flatten array-of-array-of-array to just a big array by multiplying counts.
+ count := t.Bound
+ elem := t.Type
+ for Isfixedarray(elem) {
+ count *= elem.Bound
+ elem = elem.Type
+ }
+
+ if !p.w.ShouldRepeat(elem.Width/int64(Widthptr), count) {
+ // Cheaper to just emit the bits.
+ for i := int64(0); i < count; i++ {
+ p.emit(elem, offset+i*elem.Width)
}
+ return
}
+ p.emit(elem, offset)
+ p.w.ZeroUntil((offset + elem.Width) / int64(Widthptr))
+ p.w.Repeat(elem.Width/int64(Widthptr), count-1)
case TSTRUCT:
- o := int64(0)
- var fieldoffset int64
for t1 := t.Type; t1 != nil; t1 = t1.Down {
- fieldoffset = t1.Width
- proggenskip(g, *xoffset, fieldoffset-o)
- *xoffset += fieldoffset - o
- gengcprog1(g, t1.Type, xoffset)
- o = fieldoffset + t1.Type.Width
+ p.emit(t1.Type, offset+t1.Width)
}
-
- proggenskip(g, *xoffset, t.Width-o)
- *xoffset += t.Width - o
-
- default:
- Fatal("gengcprog1: unexpected type, %v", t)
}
}
diff --git a/src/cmd/internal/gc/reg.go b/src/cmd/compile/internal/gc/reg.go
index afe95230c7..afe95230c7 100644
--- a/src/cmd/internal/gc/reg.go
+++ b/src/cmd/compile/internal/gc/reg.go
diff --git a/src/cmd/internal/gc/select.go b/src/cmd/compile/internal/gc/select.go
index 3a28ea3c77..3a28ea3c77 100644
--- a/src/cmd/internal/gc/select.go
+++ b/src/cmd/compile/internal/gc/select.go
diff --git a/src/cmd/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go
index a9af9450ae..b5427a338c 100644
--- a/src/cmd/internal/gc/sinit.go
+++ b/src/cmd/compile/internal/gc/sinit.go
@@ -221,7 +221,7 @@ func init2(n *Node, out **NodeList) {
init2list(n.Nelse, out)
if n.Op == OCLOSURE {
- init2list(n.Closure.Nbody, out)
+ init2list(n.Param.Closure.Nbody, out)
}
if n.Op == ODOTMETH || n.Op == OCALLPART {
init2(n.Type.Nname, out)
@@ -437,7 +437,7 @@ func staticassign(l *Node, r *Node, out **NodeList) bool {
case OSTRARRAYBYTE:
if l.Class == PEXTERN && r.Left.Op == OLITERAL {
- sval := r.Left.Val.U.Sval
+ sval := r.Left.Val.U.(string)
slicebytes(l, sval, len(sval))
return true
}
@@ -449,7 +449,7 @@ func staticassign(l *Node, r *Node, out **NodeList) bool {
ta := typ(TARRAY)
ta.Type = r.Type.Type
- ta.Bound = Mpgetfix(r.Right.Val.U.Xval)
+ ta.Bound = Mpgetfix(r.Right.Val.U.(*Mpint))
a := staticname(ta, 1)
r.Nname = a
n1 = *l
@@ -510,7 +510,7 @@ func staticname(t *Type, ctxt int) *Node {
n := newname(Lookupf("statictmp_%.4d", statuniqgen))
statuniqgen++
if ctxt == 0 {
- n.Readonly = true
+ n.Name.Readonly = true
}
addvar(n, t, PEXTERN)
return n
@@ -722,7 +722,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init **NodeList) {
// make an array type
t := shallow(n.Type)
- t.Bound = Mpgetfix(n.Right.Val.U.Xval)
+ t.Bound = Mpgetfix(n.Right.Val.U.(*Mpint))
t.Width = 0
t.Sym = nil
t.Haspointers = 0
@@ -1226,7 +1226,7 @@ func oaslit(n *Node, init **NodeList) bool {
func getlit(lit *Node) int {
if Smallintconst(lit) {
- return int(Mpgetfix(lit.Val.U.Xval))
+ return int(Mpgetfix(lit.Val.U.(*Mpint)))
}
return -1
}
@@ -1290,7 +1290,7 @@ func initplan(n *Node) {
if a.Op != OKEY || !Smallintconst(a.Left) {
Fatal("initplan arraylit")
}
- addvalue(p, n.Type.Type.Width*Mpgetfix(a.Left.Val.U.Xval), nil, a.Right)
+ addvalue(p, n.Type.Type.Width*Mpgetfix(a.Left.Val.U.(*Mpint)), nil, a.Right)
}
case OSTRUCTLIT:
@@ -1360,19 +1360,19 @@ func iszero(n *Node) bool {
return true
case CTSTR:
- return n.Val.U.Sval == ""
+ return n.Val.U.(string) == ""
case CTBOOL:
- return !n.Val.U.Bval
+ return !n.Val.U.(bool)
case CTINT, CTRUNE:
- return mpcmpfixc(n.Val.U.Xval, 0) == 0
+ return mpcmpfixc(n.Val.U.(*Mpint), 0) == 0
case CTFLT:
- return mpcmpfltc(n.Val.U.Fval, 0) == 0
+ return mpcmpfltc(n.Val.U.(*Mpflt), 0) == 0
case CTCPLX:
- return mpcmpfltc(&n.Val.U.Cval.Real, 0) == 0 && mpcmpfltc(&n.Val.U.Cval.Imag, 0) == 0
+ return mpcmpfltc(&n.Val.U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&n.Val.U.(*Mpcplx).Imag, 0) == 0
}
case OARRAYLIT:
@@ -1510,10 +1510,10 @@ func gen_as_init(n *Node) bool {
gdata(&nam, nr, int(nr.Type.Width))
case TCOMPLEX64, TCOMPLEX128:
- gdatacomplex(&nam, nr.Val.U.Cval)
+ gdatacomplex(&nam, nr.Val.U.(*Mpcplx))
case TSTRING:
- gdatastring(&nam, nr.Val.U.Sval)
+ gdatastring(&nam, nr.Val.U.(string))
}
return true
diff --git a/src/cmd/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index bb4d278383..7f78fce17e 100644
--- a/src/cmd/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -7,9 +7,9 @@ package gc
import (
"log"
+ "cmd/compile/internal/ssa"
"cmd/internal/obj"
"cmd/internal/obj/x86" // TODO: remove
- "cmd/internal/ssa"
)
func buildssa(fn *Node) *ssa.Func {
@@ -267,7 +267,7 @@ func (s *state) expr(n *Node) *ssa.Value {
case OLITERAL:
switch n.Val.Ctype {
case CTINT:
- return s.f.ConstInt(n.Type, Mpgetfix(n.Val.U.Xval))
+ return s.f.ConstInt(n.Type, Mpgetfix(n.Val.U.(*Mpint)))
default:
log.Fatalf("unhandled OLITERAL %v", n.Val.Ctype)
return nil
diff --git a/src/cmd/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index 06ceff5844..ed5001a983 100644
--- a/src/cmd/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -125,13 +125,6 @@ func Yyerror(format string, args ...interface{}) {
if strings.HasPrefix(msg, "syntax error") {
nsyntaxerrors++
- yystate := theparser.(*yyParserImpl).state()
- yychar := theparser.Lookahead()
-
- if Debug['x'] != 0 {
- fmt.Printf("yyerror: yystate=%d yychar=%d\n", yystate, yychar)
- }
-
// An unexpected EOF caused a syntax error. Use the previous
// line number since getc generated a fake newline character.
if curio.eofnl != 0 {
@@ -144,14 +137,6 @@ func Yyerror(format string, args ...interface{}) {
}
yyerror_lastsyntax = int(lexlineno)
- // look for parse state-specific errors in list (see go.errors).
- for i := range yymsg {
- if yymsg[i].yystate == yystate && yymsg[i].yychar == yychar {
- yyerrorl(int(lexlineno), "syntax error: %s", yymsg[i].msg)
- return
- }
- }
-
// plain "syntax error" gets "near foo" added
if msg == "syntax error" {
yyerrorl(int(lexlineno), "syntax error near %s", lexbuf.String())
@@ -214,26 +199,32 @@ func Fatal(fmt_ string, args ...interface{}) {
errorexit()
}
-func linehist(file string, off int32, relative int) {
+func linehistpragma(file string) {
if Debug['i'] != 0 {
- if file != "" {
- if off < 0 {
- fmt.Printf("pragma %s", file)
- } else if off > 0 {
- fmt.Printf("line %s", file)
- } else {
- fmt.Printf("import %s", file)
- }
- } else {
- fmt.Printf("end of import")
- }
- fmt.Printf(" at line %v\n", Ctxt.Line(int(lexlineno)))
+ fmt.Printf("pragma %s at line %v\n", file, Ctxt.Line(int(lexlineno)))
+ }
+ Ctxt.AddImport(file)
+}
+
+func linehistpush(file string) {
+ if Debug['i'] != 0 {
+ fmt.Printf("import %s at line %v\n", file, Ctxt.Line(int(lexlineno)))
}
+ Ctxt.LineHist.Push(int(lexlineno), file)
+}
- if off < 0 && file[0] != '/' && relative == 0 {
- file = fmt.Sprintf("%s/%s", Ctxt.Pathname, file)
+func linehistpop() {
+ if Debug['i'] != 0 {
+ fmt.Printf("end of import at line %v\n", Ctxt.Line(int(lexlineno)))
}
- obj.Linklinehist(Ctxt, int(lexlineno), file, int(off))
+ Ctxt.LineHist.Pop(int(lexlineno))
+}
+
+func linehistupdate(file string, off int) {
+ if Debug['i'] != 0 {
+ fmt.Printf("line %s at line %v\n", file, Ctxt.Line(int(lexlineno)))
+ }
+ Ctxt.LineHist.Update(int(lexlineno), file, off)
}
func setlineno(n *Node) int32 {
@@ -380,6 +371,12 @@ func Nod(op int, nleft *Node, nright *Node) *Node {
switch op {
case OCLOSURE, ODCLFUNC:
n.Func = new(Func)
+ n.Param = new(Param)
+ case ONAME:
+ n.Name = new(Name)
+ n.Param = new(Param)
+ case ODCLFIELD:
+ n.Param = new(Param)
}
return n
}
@@ -666,8 +663,8 @@ func sortinter(t *Type) *Type {
func Nodintconst(v int64) *Node {
c := Nod(OLITERAL, nil, nil)
c.Addable = true
- c.Val.U.Xval = new(Mpint)
- Mpmovecfix(c.Val.U.Xval, v)
+ c.Val.U = new(Mpint)
+ Mpmovecfix(c.Val.U.(*Mpint), v)
c.Val.Ctype = CTINT
c.Type = Types[TIDEAL]
ullmancalc(c)
@@ -677,8 +674,8 @@ func Nodintconst(v int64) *Node {
func nodfltconst(v *Mpflt) *Node {
c := Nod(OLITERAL, nil, nil)
c.Addable = true
- c.Val.U.Fval = newMpflt()
- mpmovefltflt(c.Val.U.Fval, v)
+ c.Val.U = newMpflt()
+ mpmovefltflt(c.Val.U.(*Mpflt), v)
c.Val.Ctype = CTFLT
c.Type = Types[TIDEAL]
ullmancalc(c)
@@ -690,8 +687,8 @@ func Nodconst(n *Node, t *Type, v int64) {
n.Op = OLITERAL
n.Addable = true
ullmancalc(n)
- n.Val.U.Xval = new(Mpint)
- Mpmovecfix(n.Val.U.Xval, v)
+ n.Val.U = new(Mpint)
+ Mpmovecfix(n.Val.U.(*Mpint), v)
n.Val.Ctype = CTINT
n.Type = t
@@ -710,7 +707,7 @@ func nodnil() *Node {
func Nodbool(b bool) *Node {
c := Nodintconst(0)
c.Val.Ctype = CTBOOL
- c.Val.U.Bval = b
+ c.Val.U = b
c.Type = idealbool
return c
}
@@ -724,7 +721,7 @@ func aindex(b *Node, t *Type) *Type {
Yyerror("array bound must be an integer expression")
case CTINT, CTRUNE:
- bound = Mpgetfix(b.Val.U.Xval)
+ bound = Mpgetfix(b.Val.U.(*Mpint))
if bound < 0 {
Yyerror("array bound must be non negative")
}
@@ -739,7 +736,12 @@ func aindex(b *Node, t *Type) *Type {
return r
}
-func treecopy(n *Node) *Node {
+// treecopy recursively copies n, with the exception of
+// ONAME, OLITERAL, OTYPE, and non-iota ONONAME leaves.
+// Copies of iota ONONAME nodes are assigned the current
+// value of iota_. If lineno != 0, it sets the line number
+// of newly allocated nodes to lineno.
+func treecopy(n *Node, lineno int32) *Node {
if n == nil {
return nil
}
@@ -750,9 +752,12 @@ func treecopy(n *Node) *Node {
m = Nod(OXXX, nil, nil)
*m = *n
m.Orig = m
- m.Left = treecopy(n.Left)
- m.Right = treecopy(n.Right)
- m.List = listtreecopy(n.List)
+ m.Left = treecopy(n.Left, lineno)
+ m.Right = treecopy(n.Right, lineno)
+ m.List = listtreecopy(n.List, lineno)
+ if lineno != -1 {
+ m.Lineno = lineno
+ }
if m.Defn != nil {
panic("abort")
}
@@ -767,11 +772,13 @@ func treecopy(n *Node) *Node {
*m = *n
m.Iota = iota_
+ if lineno != 0 {
+ m.Lineno = lineno
+ }
break
}
fallthrough
- // fall through
case ONAME, OLITERAL, OTYPE:
m = n
}
@@ -1898,7 +1905,7 @@ func safeexpr(n *Node, init **NodeList) *Node {
case ONAME, OLITERAL:
return n
- case ODOT:
+ case ODOT, OLEN, OCAP:
l := safeexpr(n.Left, init)
if l == n.Left {
return n
@@ -2359,7 +2366,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
lineno = lexlineno
if genwrapper_linehistdone == 0 {
// All the wrappers can share the same linehist entry.
- linehist("<autogenerated>", 0, 0)
+ linehistpush("<autogenerated>")
genwrapper_linehistdone = 1
}
@@ -2368,7 +2375,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
markdcl()
this := Nod(ODCLFIELD, newname(Lookup(".this")), typenod(rcvr))
- this.Left.Ntype = this.Right
+ this.Left.Param.Ntype = this.Right
in := structargs(getinarg(method.Type), 1)
out := structargs(Getoutarg(method.Type), 0)
@@ -2394,7 +2401,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
fn := Nod(ODCLFUNC, nil, nil)
fn.Nname = newname(newnam)
fn.Nname.Defn = fn
- fn.Nname.Ntype = t
+ fn.Nname.Param.Ntype = t
declare(fn.Nname, PFUNC)
funchdr(fn)
@@ -2422,11 +2429,11 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
var v Val
v.Ctype = CTSTR
- v.U.Sval = rcvr.Type.Sym.Pkg.Name // package name
+ v.U = rcvr.Type.Sym.Pkg.Name // package name
l = list(l, nodlit(v))
- v.U.Sval = rcvr.Type.Sym.Name // type name
+ v.U = rcvr.Type.Sym.Name // type name
l = list(l, nodlit(v))
- v.U.Sval = method.Sym.Name
+ v.U = method.Sym.Name
l = list(l, nodlit(v)) // method name
call := Nod(OCALL, syslook("panicwrap", 0), nil)
call.List = l
@@ -2568,7 +2575,7 @@ func genhash(sym *Sym, t *Type) {
fn.Nname = newname(sym)
fn.Nname.Class = PFUNC
tfn := Nod(OTFUNC, nil, nil)
- fn.Nname.Ntype = tfn
+ fn.Nname.Param.Ntype = tfn
n := Nod(ODCLFIELD, newname(Lookup("p")), typenod(Ptrto(t)))
tfn.List = list(tfn.List, n)
@@ -2580,7 +2587,7 @@ func genhash(sym *Sym, t *Type) {
tfn.Rlist = list(tfn.Rlist, n)
funchdr(fn)
- typecheck(&fn.Nname.Ntype, Etype)
+ typecheck(&fn.Nname.Param.Ntype, Etype)
// genhash is only called for types that have equality but
// cannot be handled by the standard algorithms,
@@ -2820,7 +2827,7 @@ func geneq(sym *Sym, t *Type) {
fn.Nname = newname(sym)
fn.Nname.Class = PFUNC
tfn := Nod(OTFUNC, nil, nil)
- fn.Nname.Ntype = tfn
+ fn.Nname.Param.Ntype = tfn
n := Nod(ODCLFIELD, newname(Lookup("p")), typenod(Ptrto(t)))
tfn.List = list(tfn.List, n)
@@ -3096,10 +3103,10 @@ func Simsimtype(t *Type) int {
return et
}
-func listtreecopy(l *NodeList) *NodeList {
+func listtreecopy(l *NodeList, lineno int32) *NodeList {
var out *NodeList
for ; l != nil; l = l.Next {
- out = list(out, treecopy(l.N))
+ out = list(out, treecopy(l.N, lineno))
}
return out
}
@@ -3139,7 +3146,7 @@ func powtwo(n *Node) int {
return -1
}
- v := uint64(Mpgetfix(n.Val.U.Xval))
+ v := uint64(Mpgetfix(n.Val.U.(*Mpint)))
b := uint64(1)
for i := 0; i < 64; i++ {
if b == v {
diff --git a/src/cmd/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go
index 7cb632cebe..221b1f43eb 100644
--- a/src/cmd/internal/gc/swt.go
+++ b/src/cmd/compile/internal/gc/swt.go
@@ -169,10 +169,10 @@ func typecheckswitch(n *Node) {
if nvar != nil {
if ll != nil && ll.Next == nil && ll.N.Type != nil && !Istype(ll.N.Type, TNIL) {
// single entry type switch
- nvar.Ntype = typenod(ll.N.Type)
+ nvar.Param.Ntype = typenod(ll.N.Type)
} else {
// multiple entry type switch or default
- nvar.Ntype = typenod(n.Type)
+ nvar.Param.Ntype = typenod(n.Type)
}
typecheck(&nvar, Erv|Easgn)
@@ -218,7 +218,7 @@ func (s *exprSwitch) walk(sw *Node) {
s.kind = switchKindExpr
if Isconst(sw.Ntest, CTBOOL) {
s.kind = switchKindTrue
- if !sw.Ntest.Val.U.Bval {
+ if !sw.Ntest.Val.U.(bool) {
s.kind = switchKindFalse
}
}
@@ -755,16 +755,16 @@ func exprcmp(c1, c2 *caseClause) int {
// sort by constant value to enable binary search
switch ct {
case CTFLT:
- return mpcmpfltflt(n1.Val.U.Fval, n2.Val.U.Fval)
+ return mpcmpfltflt(n1.Val.U.(*Mpflt), n2.Val.U.(*Mpflt))
case CTINT, CTRUNE:
- return Mpcmpfixfix(n1.Val.U.Xval, n2.Val.U.Xval)
+ return Mpcmpfixfix(n1.Val.U.(*Mpint), n2.Val.U.(*Mpint))
case CTSTR:
// Sort strings by length and then by value.
// It is much cheaper to compare lengths than values,
// and all we need here is consistency.
// We respect this sorting in exprSwitch.walkCases.
- a := n1.Val.U.Sval
- b := n2.Val.U.Sval
+ a := n1.Val.U.(string)
+ b := n2.Val.U.(string)
if len(a) < len(b) {
return -1
}
diff --git a/src/cmd/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index 7c9fb8d2b8..be4307690d 100644
--- a/src/cmd/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -23,14 +23,67 @@ type Node struct {
List *NodeList
Rlist *NodeList
+ // most nodes
+ Type *Type
+ Orig *Node // original form, for printing, and tracking copies of ONAMEs
+ Nname *Node
+
+ // func
+ Func *Func
+
+ // ONAME
+ Name *Name
+ Defn *Node // ONAME: initializing assignment; OLABEL: labeled statement
+ Pack *Node // real package for import . names
+ Curfn *Node // function for local variables
+ Paramfld *Type // TFIELD for this PPARAM; also for ODOT, curfn
+ Alloc *Node // allocation call
+ Param *Param
+
+ // OPACK
+ Pkg *Pkg
+
+ // OARRAYLIT, OMAPLIT, OSTRUCTLIT.
+ Initplan *InitPlan
+
+ // Escape analysis.
+ Escflowsrc *NodeList // flow(this, src)
+ Escretval *NodeList // on OCALLxxx, list of dummy return values
+
+ Sym *Sym // various
+
+ Opt interface{} // for optimization passes
+
+ // OLITERAL
+ Val Val
+
+ Xoffset int64
+ Stkdelta int64 // offset added by stack frame compaction phase.
+
+ // Escape analysis.
+ Escloopdepth int32 // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
+
+ Vargen int32 // unique name for OTYPE/ONAME within a function. Function outputs are numbered starting at one.
+ Lineno int32
+ Iota int32
+ Walkgen uint32
+
+ Funcdepth int32
+
+ // OREGISTER, OINDREG
+ Reg int16
+
+ // most nodes - smaller fields
+ Esclevel Level
+ Esc uint16 // EscXXX
+
Op uint8
Nointerface bool
Ullman uint8 // sethi/ullman number
Addable bool // addressable
- Etype uint8 // op for OASOP, etype for OTYPE, exclam for export
+ Etype uint8 // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg
Bounded bool // bounds check unnecessary
Class uint8 // PPARAM, PAUTO, PEXTERN, etc
- Method bool // OCALLMETH is direct method call
Embedded uint8 // ODCLFIELD embedded type
Colas bool // OAS resulting from :=
Diag uint8 // already printed error about this
@@ -42,76 +95,36 @@ type Node struct {
Initorder uint8
Used bool
Isddd bool // is the argument variadic
- Readonly bool
Implicit bool
- Addrtaken bool // address taken, even if not moved to heap
- Assigned bool // is the variable ever assigned to
- Captured bool // is the variable captured by a closure
- Byval bool // is the variable captured by value or by reference
- Reslice bool // this is a reslice x = x[0:y] or x = append(x, ...)
- Likely int8 // likeliness of if statement
- Hasbreak bool // has break statement
- Needzero bool // if it contains pointers, needs to be zeroed on function entry
- Esc uint16 // EscXXX
- Funcdepth int32
-
- // most nodes
- Type *Type
- Orig *Node // original form, for printing, and tracking copies of ONAMEs
- Nname *Node
-
- // func
- Func *Func
-
- // OLITERAL
- Val Val
+ Addrtaken bool // address taken, even if not moved to heap
+ Assigned bool // is the variable ever assigned to
+ Likely int8 // likeliness of if statement
+ Hasbreak bool // has break statement
+}
- // OREGISTER, OINDREG
- Reg int16
+// Name holds Node fields used only by ONAME nodes.
+type Name struct {
+ Heapaddr *Node // temp holding heap address of param
+ Inlvar *Node // ONAME substitute while inlining
+ Decldepth int32 // declaration loop depth, increased for every loop or label
+ Method bool // OCALLMETH name
+ Readonly bool
+ Captured bool // is the variable captured by a closure
+ Byval bool // is the variable captured by value or by reference
+ Needzero bool // if it contains pointers, needs to be zeroed on function entry
+}
- // ONAME
- Ntype *Node
- Defn *Node // ONAME: initializing assignment; OLABEL: labeled statement
- Pack *Node // real package for import . names
- Curfn *Node // function for local variables
- Paramfld *Type // TFIELD for this PPARAM; also for ODOT, curfn
- Decldepth int // declaration loop depth, increased for every loop or label
+type Param struct {
+ Ntype *Node
// ONAME func param with PHEAP
- Heapaddr *Node // temp holding heap address of param
Outerexpr *Node // expression copied into closure for variable
Stackparam *Node // OPARAM node referring to stack copy of param
- Alloc *Node // allocation call
// ONAME closure param with PPARAMREF
Outer *Node // outer PPARAMREF in nested closure
Closure *Node // ONAME/PHEAP <-> ONAME/PPARAMREF
Top int // top context (Ecall, Eproc, etc)
-
- // ONAME substitute while inlining
- Inlvar *Node
-
- // OPACK
- Pkg *Pkg
-
- // OARRAYLIT, OMAPLIT, OSTRUCTLIT.
- Initplan *InitPlan
-
- // Escape analysis.
- Escflowsrc *NodeList // flow(this, src)
- Escretval *NodeList // on OCALLxxx, list of dummy return values
- Escloopdepth int // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
-
- Sym *Sym // various
- Vargen int32 // unique name for OTYPE/ONAME within a function. Function outputs are numbered starting at one.
- Lineno int32
- Xoffset int64
- Stkdelta int64 // offset added by stack frame compaction phase.
- Ostk int32 // 6g only
- Iota int32
- Walkgen uint32
- Esclevel Level
- Opt interface{} // for optimization passes
}
// Func holds Node fields used only with function-like nodes.
diff --git a/src/cmd/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go
index 6f7830d70a..cf1589eb03 100644
--- a/src/cmd/internal/gc/type.go
+++ b/src/cmd/compile/internal/gc/type.go
@@ -10,7 +10,7 @@
package gc
import (
- "cmd/internal/ssa"
+ "cmd/compile/internal/ssa"
)
func (t *Type) Size() int64 {
diff --git a/src/cmd/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 6daf842474..2900da8be7 100644
--- a/src/cmd/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -311,8 +311,8 @@ OpSwitch:
break OpSwitch
case ONAME:
- if n.Decldepth == 0 {
- n.Decldepth = decldepth
+ if n.Name.Decldepth == 0 {
+ n.Name.Decldepth = decldepth
}
if n.Etype != 0 {
ok |= Ecall
@@ -392,7 +392,7 @@ OpSwitch:
return
}
- t.Bound = Mpgetfix(v.U.Xval)
+ t.Bound = Mpgetfix(v.U.(*Mpint))
if doesoverflow(v, Types[TINT]) {
Yyerror("array bound is too large")
n.Type = nil
@@ -770,7 +770,7 @@ OpSwitch:
}
if (op == ODIV || op == OMOD) && Isconst(r, CTINT) {
- if mpcmpfixc(r.Val.U.Xval, 0) == 0 {
+ if mpcmpfixc(r.Val.U.(*Mpint), 0) == 0 {
Yyerror("division by zero")
n.Type = nil
return
@@ -813,8 +813,8 @@ OpSwitch:
var l *Node
for l = n.Left; l != r; l = l.Left {
l.Addrtaken = true
- if l.Closure != nil {
- l.Closure.Addrtaken = true
+ if l.Param != nil && l.Param.Closure != nil {
+ l.Param.Closure.Addrtaken = true
}
}
@@ -822,8 +822,8 @@ OpSwitch:
Fatal("found non-orig name node %v", l)
}
l.Addrtaken = true
- if l.Closure != nil {
- l.Closure.Addrtaken = true
+ if l.Param != nil && l.Param.Closure != nil {
+ l.Param.Closure.Addrtaken = true
}
defaultlit(&n.Left, nil)
l = n.Left
@@ -891,6 +891,9 @@ OpSwitch:
}
n.Op = ONAME
+ if n.Name == nil {
+ n.Name = new(Name)
+ }
n.Sym = n.Right.Sym
n.Type = methodfunc(n.Type, n.Left.Type)
n.Xoffset = 0
@@ -1024,7 +1027,7 @@ OpSwitch:
case TSTRING, TARRAY:
indexlit(&n.Right)
if t.Etype == TSTRING {
- n.Type = Types[TUINT8]
+ n.Type = bytetype
} else {
n.Type = t.Type
}
@@ -1043,14 +1046,14 @@ OpSwitch:
}
if Isconst(n.Right, CTINT) {
- x := Mpgetfix(n.Right.Val.U.Xval)
+ x := Mpgetfix(n.Right.Val.U.(*Mpint))
if x < 0 {
Yyerror("invalid %s index %v (index must be non-negative)", why, n.Right)
} else if Isfixedarray(t) && t.Bound > 0 && x >= t.Bound {
Yyerror("invalid array index %v (out of bounds for %d-element array)", n.Right, t.Bound)
- } else if Isconst(n.Left, CTSTR) && x >= int64(len(n.Left.Val.U.Sval)) {
- Yyerror("invalid string index %v (out of bounds for %d-byte string)", n.Right, len(n.Left.Val.U.Sval))
- } else if Mpcmpfixfix(n.Right.Val.U.Xval, Maxintval[TINT]) > 0 {
+ } else if Isconst(n.Left, CTSTR) && x >= int64(len(n.Left.Val.U.(string))) {
+ Yyerror("invalid string index %v (out of bounds for %d-byte string)", n.Right, len(n.Left.Val.U.(string)))
+ } else if Mpcmpfixfix(n.Right.Val.U.(*Mpint), Maxintval[TINT]) > 0 {
Yyerror("invalid %s index %v (index too large)", why, n.Right)
}
}
@@ -1303,7 +1306,7 @@ OpSwitch:
if l.Op == OTYPE {
if n.Isddd || l.Type.Bound == -100 {
if l.Type.Broke == 0 {
- Yyerror("invalid use of ... in type conversion", l)
+ Yyerror("invalid use of ... in type conversion to %v", l.Type)
}
n.Diag = 1
}
@@ -1435,9 +1438,9 @@ OpSwitch:
if Isconst(l, CTCPLX) {
r := n
if n.Op == OREAL {
- n = nodfltconst(&l.Val.U.Cval.Real)
+ n = nodfltconst(&l.Val.U.(*Mpcplx).Real)
} else {
- n = nodfltconst(&l.Val.U.Cval.Imag)
+ n = nodfltconst(&l.Val.U.(*Mpcplx).Imag)
}
n.Orig = r
}
@@ -1451,7 +1454,7 @@ OpSwitch:
case TSTRING:
if Isconst(l, CTSTR) {
r := Nod(OXXX, nil, nil)
- Nodconst(r, Types[TINT], int64(len(l.Val.U.Sval)))
+ Nodconst(r, Types[TINT], int64(len(l.Val.U.(string))))
r.Orig = n
n = r
}
@@ -1528,7 +1531,7 @@ OpSwitch:
var t *Type
switch l.Type.Etype {
default:
- Yyerror("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type, r.Type)
+ Yyerror("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type)
n.Type = nil
return
@@ -1636,17 +1639,16 @@ OpSwitch:
}
// Unpack multiple-return result before type-checking.
+ var funarg *Type
if Istype(t, TSTRUCT) && t.Funarg != 0 {
- t = t.Type
- if Istype(t, TFIELD) {
- t = t.Type
- }
+ funarg = t
+ t = t.Type.Type
}
n.Type = t
if !Isslice(t) {
if Isconst(args.N, CTNIL) {
- Yyerror("first argument to append must be typed slice; have untyped nil", t)
+ Yyerror("first argument to append must be typed slice; have untyped nil")
n.Type = nil
return
}
@@ -1678,11 +1680,19 @@ OpSwitch:
break OpSwitch
}
- for args = args.Next; args != nil; args = args.Next {
- if args.N.Type == nil {
- continue
+ if funarg != nil {
+ for t := funarg.Type.Down; t != nil; t = t.Down {
+ if assignop(t.Type, n.Type.Type, nil) == 0 {
+ Yyerror("cannot append %v value to []%v", t.Type, n.Type.Type)
+ }
+ }
+ } else {
+ for args = args.Next; args != nil; args = args.Next {
+ if args.N.Type == nil {
+ continue
+ }
+ args.N = assignconv(args.N, t.Type, "append")
}
- args.N = assignconv(args.N, t.Type, "append")
}
break OpSwitch
@@ -1852,7 +1862,7 @@ OpSwitch:
n.Type = nil
return
}
- if Isconst(l, CTINT) && r != nil && Isconst(r, CTINT) && Mpcmpfixfix(l.Val.U.Xval, r.Val.U.Xval) > 0 {
+ if Isconst(l, CTINT) && r != nil && Isconst(r, CTINT) && Mpcmpfixfix(l.Val.U.(*Mpint), r.Val.U.(*Mpint)) > 0 {
Yyerror("len larger than cap in make(%v)", t)
n.Type = nil
return
@@ -2248,16 +2258,16 @@ func checksliceindex(l *Node, r *Node, tp *Type) int {
}
if r.Op == OLITERAL {
- if Mpgetfix(r.Val.U.Xval) < 0 {
+ if Mpgetfix(r.Val.U.(*Mpint)) < 0 {
Yyerror("invalid slice index %v (index must be non-negative)", r)
return -1
- } else if tp != nil && tp.Bound > 0 && Mpgetfix(r.Val.U.Xval) > tp.Bound {
+ } else if tp != nil && tp.Bound > 0 && Mpgetfix(r.Val.U.(*Mpint)) > tp.Bound {
Yyerror("invalid slice index %v (out of bounds for %d-element array)", r, tp.Bound)
return -1
- } else if Isconst(l, CTSTR) && Mpgetfix(r.Val.U.Xval) > int64(len(l.Val.U.Sval)) {
- Yyerror("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.Val.U.Sval))
+ } else if Isconst(l, CTSTR) && Mpgetfix(r.Val.U.(*Mpint)) > int64(len(l.Val.U.(string))) {
+ Yyerror("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.Val.U.(string)))
return -1
- } else if Mpcmpfixfix(r.Val.U.Xval, Maxintval[TINT]) > 0 {
+ } else if Mpcmpfixfix(r.Val.U.(*Mpint), Maxintval[TINT]) > 0 {
Yyerror("invalid slice index %v (index too large)", r)
return -1
}
@@ -2267,7 +2277,7 @@ func checksliceindex(l *Node, r *Node, tp *Type) int {
}
func checksliceconst(lo *Node, hi *Node) int {
- if lo != nil && hi != nil && lo.Op == OLITERAL && hi.Op == OLITERAL && Mpcmpfixfix(lo.Val.U.Xval, hi.Val.U.Xval) > 0 {
+ if lo != nil && hi != nil && lo.Op == OLITERAL && hi.Op == OLITERAL && Mpcmpfixfix(lo.Val.U.(*Mpint), hi.Val.U.(*Mpint)) > 0 {
Yyerror("invalid slice index: %v > %v", lo, hi)
return -1
}
@@ -2817,10 +2827,10 @@ func keydup(n *Node, hash []*Node) {
b = 23
case CTINT, CTRUNE:
- b = uint32(Mpgetfix(n.Val.U.Xval))
+ b = uint32(Mpgetfix(n.Val.U.(*Mpint)))
case CTFLT:
- d := mpgetflt(n.Val.U.Fval)
+ d := mpgetflt(n.Val.U.(*Mpflt))
x := math.Float64bits(d)
for i := 0; i < 8; i++ {
b = b*PRIME1 + uint32(x&0xFF)
@@ -2829,8 +2839,8 @@ func keydup(n *Node, hash []*Node) {
case CTSTR:
b = 0
- s := n.Val.U.Sval
- for i := len(n.Val.U.Sval); i > 0; i-- {
+ s := n.Val.U.(string)
+ for i := len(n.Val.U.(string)); i > 0; i-- {
b = b*PRIME1 + uint32(s[0])
s = s[1:]
}
@@ -2846,12 +2856,12 @@ func keydup(n *Node, hash []*Node) {
if Eqtype(a.Left.Type, n.Type) {
cmp.Right = a.Left
evconst(&cmp)
- b = uint32(obj.Bool2int(cmp.Val.U.Bval))
+ b = uint32(obj.Bool2int(cmp.Val.U.(bool)))
}
} else if Eqtype(a.Type, n.Type) {
cmp.Right = a
evconst(&cmp)
- b = uint32(obj.Bool2int(cmp.Val.U.Bval))
+ b = uint32(obj.Bool2int(cmp.Val.U.(bool)))
}
if b != 0 {
@@ -2869,11 +2879,11 @@ func indexdup(n *Node, hash []*Node) {
Fatal("indexdup: not OLITERAL")
}
- b := uint32(Mpgetfix(n.Val.U.Xval))
+ b := uint32(Mpgetfix(n.Val.U.(*Mpint)))
h := uint(b % uint32(len(hash)))
var c uint32
for a := hash[h]; a != nil; a = a.Ntest {
- c = uint32(Mpgetfix(a.Val.U.Xval))
+ c = uint32(Mpgetfix(a.Val.U.(*Mpint)))
if b == c {
Yyerror("duplicate index in array literal: %d", b)
return
@@ -3263,14 +3273,14 @@ func checkassign(stmt *Node, n *Node) {
var l *Node
for l = n; l != r; l = l.Left {
l.Assigned = true
- if l.Closure != nil {
- l.Closure.Assigned = true
+ if l.Param != nil && l.Param.Closure != nil {
+ l.Param.Closure.Assigned = true
}
}
l.Assigned = true
- if l.Closure != nil {
- l.Closure.Assigned = true
+ if l.Param != nil && l.Param.Closure != nil {
+ l.Param.Closure.Assigned = true
}
}
@@ -3335,7 +3345,7 @@ func typecheckas(n *Node) {
// so that the conversion below happens).
n.Left = resolve(n.Left)
- if n.Left.Defn != n || n.Left.Ntype != nil {
+ if n.Left.Defn != n || n.Left.Param.Ntype != nil {
typecheck(&n.Left, Erv|Easgn)
}
@@ -3347,7 +3357,7 @@ func typecheckas(n *Node) {
}
}
- if n.Left.Defn == n && n.Left.Ntype == nil {
+ if n.Left.Defn == n && n.Left.Param.Ntype == nil {
defaultlit(&n.Right, nil)
n.Left.Type = n.Right.Type
}
@@ -3360,29 +3370,6 @@ func typecheckas(n *Node) {
if n.Left.Typecheck == 0 {
typecheck(&n.Left, Erv|Easgn)
}
-
- // Recognize slices being updated in place, for better code generation later.
- // Don't rewrite if using race detector, to avoid needing to teach race detector
- // about this optimization.
- if n.Left != nil && n.Left.Op != OINDEXMAP && n.Right != nil && flag_race == 0 {
- switch n.Right.Op {
- // For x = x[0:y], x can be updated in place, without touching pointer.
- // TODO(rsc): Reenable once it is actually updated in place without touching the pointer.
- case OSLICE, OSLICE3, OSLICESTR:
- if false && samesafeexpr(n.Left, n.Right.Left) && (n.Right.Right.Left == nil || iszero(n.Right.Right.Left)) {
- n.Right.Reslice = true
- }
-
- // For x = append(x, ...), x can be updated in place when there is capacity,
- // without touching the pointer; otherwise the emitted code to growslice
- // can take care of updating the pointer, and only in that case.
- // TODO(rsc): Reenable once the emitted code does update the pointer.
- case OAPPEND:
- if false && n.Right.List != nil && samesafeexpr(n.Left, n.Right.List.N) {
- n.Right.Reslice = true
- }
- }
- }
}
func checkassignto(src *Type, dst *Node) {
@@ -3399,7 +3386,7 @@ func typecheckas2(n *Node) {
// delicate little dance.
ll.N = resolve(ll.N)
- if ll.N.Defn != n || ll.N.Ntype != nil {
+ if ll.N.Defn != n || ll.N.Param.Ntype != nil {
typecheck(&ll.N, Erv|Easgn)
}
}
@@ -3423,7 +3410,7 @@ func typecheckas2(n *Node) {
if ll.N.Type != nil && lr.N.Type != nil {
lr.N = assignconv(lr.N, ll.N.Type, "assignment")
}
- if ll.N.Defn == n && ll.N.Ntype == nil {
+ if ll.N.Defn == n && ll.N.Param.Ntype == nil {
defaultlit(&lr.N, nil)
ll.N.Type = lr.N.Type
}
@@ -3456,7 +3443,7 @@ func typecheckas2(n *Node) {
if t.Type != nil && ll.N.Type != nil {
checkassignto(t.Type, ll.N)
}
- if ll.N.Defn == n && ll.N.Ntype == nil {
+ if ll.N.Defn == n && ll.N.Param.Ntype == nil {
ll.N.Type = t.Type
}
t = structnext(&s)
@@ -3495,7 +3482,7 @@ func typecheckas2(n *Node) {
if l.Type != nil && l.Type.Etype != TBOOL {
checkassignto(Types[TBOOL], l)
}
- if l.Defn == n && l.Ntype == nil {
+ if l.Defn == n && l.Param.Ntype == nil {
l.Type = Types[TBOOL]
}
goto out
@@ -3534,7 +3521,7 @@ func typecheckfunc(n *Node) {
for l := n.Func.Dcl; l != nil; l = l.Next {
if l.N.Op == ONAME && (l.N.Class == PPARAM || l.N.Class == PPARAMOUT) {
- l.N.Decldepth = 1
+ l.N.Name.Decldepth = 1
}
}
}
@@ -3542,10 +3529,10 @@ func typecheckfunc(n *Node) {
func stringtoarraylit(np **Node) {
n := *np
if n.Left.Op != OLITERAL || n.Left.Val.Ctype != CTSTR {
- Fatal("stringtoarraylit %N", n)
+ Fatal("stringtoarraylit %v", n)
}
- s := n.Left.Val.U.Sval
+ s := n.Left.Val.U.(string)
var l *NodeList
if n.Type.Type.Etype == TUINT8 {
// []byte
@@ -3659,8 +3646,8 @@ func typecheckdeftype(n *Node) {
setlineno(n)
n.Type.Sym = n.Sym
n.Typecheck = 1
- typecheck(&n.Ntype, Etype)
- t := n.Ntype.Type
+ typecheck(&n.Param.Ntype, Etype)
+ t := n.Param.Ntype.Type
if t == nil {
n.Diag = 1
n.Type = nil
@@ -3770,10 +3757,10 @@ func typecheckdef(n *Node) *Node {
break
case OLITERAL:
- if n.Ntype != nil {
- typecheck(&n.Ntype, Etype)
- n.Type = n.Ntype.Type
- n.Ntype = nil
+ if n.Param.Ntype != nil {
+ typecheck(&n.Param.Ntype, Etype)
+ n.Type = n.Param.Ntype.Type
+ n.Param.Ntype = nil
if n.Type == nil {
n.Diag = 1
goto ret
@@ -3822,9 +3809,9 @@ func typecheckdef(n *Node) *Node {
n.Type = e.Type
case ONAME:
- if n.Ntype != nil {
- typecheck(&n.Ntype, Etype)
- n.Type = n.Ntype.Type
+ if n.Param.Ntype != nil {
+ typecheck(&n.Param.Ntype, Etype)
+ n.Type = n.Param.Ntype.Type
if n.Type == nil {
n.Diag = 1
@@ -3902,12 +3889,12 @@ func checkmake(t *Type, arg string, n *Node) int {
switch n.Val.Ctype {
case CTINT, CTRUNE, CTFLT, CTCPLX:
n.Val = toint(n.Val)
- if mpcmpfixc(n.Val.U.Xval, 0) < 0 {
+ if mpcmpfixc(n.Val.U.(*Mpint), 0) < 0 {
Yyerror("negative %s argument in make(%v)", arg, t)
return -1
}
- if Mpcmpfixfix(n.Val.U.Xval, Maxintval[TINT]) > 0 {
+ if Mpcmpfixfix(n.Val.U.(*Mpint), Maxintval[TINT]) > 0 {
Yyerror("%s argument too large in make(%v)", arg, t)
return -1
}
diff --git a/src/cmd/internal/gc/unsafe.go b/src/cmd/compile/internal/gc/unsafe.go
index aa90a19308..824ecd0339 100644
--- a/src/cmd/internal/gc/unsafe.go
+++ b/src/cmd/compile/internal/gc/unsafe.go
@@ -140,8 +140,8 @@ ret:
var val Val
val.Ctype = CTINT
- val.U.Xval = new(Mpint)
- Mpmovecfix(val.U.Xval, v)
+ val.U = new(Mpint)
+ Mpmovecfix(val.U.(*Mpint), v)
n := Nod(OLITERAL, nil, nil)
n.Orig = nn
n.Val = val
diff --git a/src/cmd/internal/gc/util.go b/src/cmd/compile/internal/gc/util.go
index 5dc6561b48..c59af0665b 100644
--- a/src/cmd/internal/gc/util.go
+++ b/src/cmd/compile/internal/gc/util.go
@@ -1,7 +1,6 @@
package gc
import (
- "cmd/internal/obj"
"os"
"runtime"
"runtime/pprof"
@@ -10,7 +9,7 @@ import (
)
func (n *Node) Line() string {
- return obj.Linklinefmt(Ctxt, int(n.Lineno), false, false)
+ return Ctxt.LineHist.LineString(int(n.Lineno))
}
func atoi(s string) int {
diff --git a/src/cmd/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index c32a8137d6..d5eb44c0bb 100644
--- a/src/cmd/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -352,6 +352,20 @@ func walkstmt(np **Node) {
*np = n
}
+func isSmallMakeSlice(n *Node) bool {
+ if n.Op != OMAKESLICE {
+ return false
+ }
+ l := n.Left
+ r := n.Right
+ if r == nil {
+ r = l
+ }
+ t := n.Type
+
+ return Smallintconst(l) && Smallintconst(r) && (t.Type.Width == 0 || Mpgetfix(r.Val.U.(*Mpint)) < (1<<16)/t.Type.Width)
+}
+
/*
* walk the whole tree of the body of an
* expression or simple statement.
@@ -601,7 +615,7 @@ func walkexpr(np **Node, init **NodeList) {
n.Left.Func.Enter = nil
// Replace OCLOSURE with ONAME/PFUNC.
- n.Left = n.Left.Closure.Nname
+ n.Left = n.Left.Param.Closure.Nname
// Update type of OCALLFUNC node.
// Output arguments had not changed, but their offsets could.
@@ -711,6 +725,23 @@ func walkexpr(np **Node, init **NodeList) {
n = mkcall1(chanfn("chanrecv1", 2, r.Type), nil, init, typename(r.Type), r, n1)
walkexpr(&n, init)
goto ret
+
+ case OAPPEND:
+ // x = append(...)
+ r := n.Right
+ if r.Isddd {
+ r = appendslice(r, init) // also works for append(slice, string).
+ } else {
+ r = walkappend(r, init, n)
+ }
+ n.Right = r
+ if r.Op == OAPPEND {
+ // Left in place for back end.
+ // Do not add a new write barrier.
+ goto ret
+ }
+ // Otherwise, lowered for race detector.
+ // Treat as ordinary assignment.
}
if n.Left != nil && n.Right != nil {
@@ -1189,7 +1220,7 @@ func walkexpr(np **Node, init **NodeList) {
Yyerror("index out of bounds")
}
} else if Isconst(n.Left, CTSTR) {
- n.Bounded = bounded(r, int64(len(n.Left.Val.U.Sval)))
+ n.Bounded = bounded(r, int64(len(n.Left.Val.U.(string))))
if Debug['m'] != 0 && n.Bounded && !Isconst(n.Right, CTINT) {
Warn("index bounds check elided")
}
@@ -1200,16 +1231,16 @@ func walkexpr(np **Node, init **NodeList) {
// replace "abc"[1] with 'b'.
// delayed until now because "abc"[1] is not
// an ideal constant.
- v := Mpgetfix(n.Right.Val.U.Xval)
+ v := Mpgetfix(n.Right.Val.U.(*Mpint))
- Nodconst(n, n.Type, int64(n.Left.Val.U.Sval[v]))
+ Nodconst(n, n.Type, int64(n.Left.Val.U.(string)[v]))
n.Typecheck = 1
}
}
}
if Isconst(n.Right, CTINT) {
- if Mpcmpfixfix(n.Right.Val.U.Xval, &mpzero) < 0 || Mpcmpfixfix(n.Right.Val.U.Xval, Maxintval[TINT]) > 0 {
+ if Mpcmpfixfix(n.Right.Val.U.(*Mpint), &mpzero) < 0 || Mpcmpfixfix(n.Right.Val.U.(*Mpint), Maxintval[TINT]) > 0 {
Yyerror("index out of bounds")
}
}
@@ -1263,56 +1294,39 @@ func walkexpr(np **Node, init **NodeList) {
case ORECV:
Fatal("walkexpr ORECV") // should see inside OAS only
- case OSLICE:
- if n.Right != nil && n.Right.Left == nil && n.Right.Right == nil { // noop
- walkexpr(&n.Left, init)
- n = n.Left
- goto ret
- }
- fallthrough
-
- case OSLICEARR, OSLICESTR:
- if n.Right == nil { // already processed
- goto ret
- }
-
+ case OSLICE, OSLICEARR, OSLICESTR:
walkexpr(&n.Left, init)
-
- // cgen_slice can't handle string literals as source
- // TODO the OINDEX case is a bug elsewhere that needs to be traced. it causes a crash on ([2][]int{ ... })[1][lo:hi]
- if (n.Op == OSLICESTR && n.Left.Op == OLITERAL) || (n.Left.Op == OINDEX) {
- n.Left = copyexpr(n.Left, n.Left.Type, init)
- } else {
- n.Left = safeexpr(n.Left, init)
- }
walkexpr(&n.Right.Left, init)
- n.Right.Left = safeexpr(n.Right.Left, init)
+ if n.Right.Left != nil && iszero(n.Right.Left) {
+ // Reduce x[0:j] to x[:j].
+ n.Right.Left = nil
+ }
walkexpr(&n.Right.Right, init)
- n.Right.Right = safeexpr(n.Right.Right, init)
- n = sliceany(n, init) // chops n.Right, sets n.List
+ n = reduceSlice(n)
goto ret
case OSLICE3, OSLICE3ARR:
- if n.Right == nil { // already processed
- goto ret
- }
-
walkexpr(&n.Left, init)
-
- // TODO the OINDEX case is a bug elsewhere that needs to be traced. it causes a crash on ([2][]int{ ... })[1][lo:hi]
- // TODO the comment on the previous line was copied from case OSLICE. it might not even be true.
- if n.Left.Op == OINDEX {
- n.Left = copyexpr(n.Left, n.Left.Type, init)
- } else {
- n.Left = safeexpr(n.Left, init)
- }
walkexpr(&n.Right.Left, init)
- n.Right.Left = safeexpr(n.Right.Left, init)
+ if n.Right.Left != nil && iszero(n.Right.Left) {
+ // Reduce x[0:j:k] to x[:j:k].
+ n.Right.Left = nil
+ }
walkexpr(&n.Right.Right.Left, init)
- n.Right.Right.Left = safeexpr(n.Right.Right.Left, init)
walkexpr(&n.Right.Right.Right, init)
- n.Right.Right.Right = safeexpr(n.Right.Right.Right, init)
- n = sliceany(n, init) // chops n.Right, sets n.List
+
+ r := n.Right.Right.Right
+ if r != nil && r.Op == OCAP && samesafeexpr(n.Left, r.Left) {
+ // Reduce x[i:j:cap(x)] to x[i:j].
+ n.Right.Right = n.Right.Right.Left
+ if n.Op == OSLICE3 {
+ n.Op = OSLICE
+ } else {
+ n.Op = OSLICEARR
+ }
+ n = reduceSlice(n)
+ goto ret
+ }
goto ret
case OADDR:
@@ -1320,7 +1334,10 @@ func walkexpr(np **Node, init **NodeList) {
goto ret
case ONEW:
- if n.Esc == EscNone && n.Type.Type.Width < 1<<16 {
+ if n.Esc == EscNone {
+ if n.Type.Type.Width >= 1<<16 {
+ Fatal("Large ONEW with EscNone, %v", n)
+ }
r := temp(n.Type.Type)
r = Nod(OAS, r, nil) // zero temp
typecheck(&r, Etop)
@@ -1338,7 +1355,7 @@ func walkexpr(np **Node, init **NodeList) {
// comparing the lengths instead will yield the same result
// without the function call.
case OCMPSTR:
- if (Isconst(n.Left, CTSTR) && len(n.Left.Val.U.Sval) == 0) || (Isconst(n.Right, CTSTR) && len(n.Right.Val.U.Sval) == 0) {
+ if (Isconst(n.Left, CTSTR) && len(n.Left.Val.U.(string)) == 0) || (Isconst(n.Right, CTSTR) && len(n.Right.Val.U.(string)) == 0) {
r := Nod(int(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
typecheck(&r, Erv)
walkexpr(&r, init)
@@ -1400,12 +1417,8 @@ func walkexpr(np **Node, init **NodeList) {
goto ret
case OAPPEND:
- if n.Isddd {
- n = appendslice(n, init) // also works for append(slice, string).
- } else {
- n = walkappend(n, init)
- }
- goto ret
+ // order should make sure we only see OAS(node, OAPPEND), which we handle above.
+ Fatal("append outside assignment")
case OCOPY:
n = copyany(n, init, flag_race)
@@ -1462,7 +1475,10 @@ func walkexpr(np **Node, init **NodeList) {
l = r
}
t := n.Type
- if n.Esc == EscNone && Smallintconst(l) && Smallintconst(r) && (t.Type.Width == 0 || Mpgetfix(r.Val.U.Xval) < (1<<16)/t.Type.Width) {
+ if n.Esc == EscNone {
+ if !isSmallMakeSlice(n) {
+ Fatal("Non-small OMAKESLICE with EscNone, %v", n)
+ }
// var arr [r]T
// n = arr[:l]
t = aindex(r, t.Type) // [r]T
@@ -1647,6 +1663,22 @@ ret:
*np = n
}
+func reduceSlice(n *Node) *Node {
+ r := n.Right.Right
+ if r != nil && r.Op == OLEN && samesafeexpr(n.Left, r.Left) {
+ // Reduce x[i:len(x)] to x[i:].
+ n.Right.Right = nil
+ }
+ if (n.Op == OSLICE || n.Op == OSLICESTR) && n.Right.Left == nil && n.Right.Right == nil {
+ // Reduce x[:] to x.
+ if Debug_slice > 0 {
+ Warn("slice: omit slice operation")
+ }
+ return n.Left
+ }
+ return n
+}
+
func ascompatee1(op int, l *Node, r *Node, init **NodeList) *Node {
// convas will turn map assigns into function calls,
// making it impossible for reorder3 to work.
@@ -2108,9 +2140,8 @@ func isstack(n *Node) bool {
}
switch n.Op {
- // OINDREG only ends up in walk if it's indirect of SP.
case OINDREG:
- return true
+ return n.Reg == int16(Thearch.REGSP)
case ONAME:
switch n.Class {
@@ -2185,26 +2216,6 @@ func needwritebarrier(l *Node, r *Node) bool {
return false
}
- // No write barrier for reslice: x = x[0:y] or x = append(x, ...).
- // Both are compiled to modify x directly.
- // In the case of append, a write barrier may still be needed
- // if the underlying array grows, but the append code can
- // generate the write barrier directly in that case.
- // (It does not yet, but the cost of the write barrier will be
- // small compared to the cost of the allocation.)
- if r.Reslice {
- switch r.Op {
- case OSLICE, OSLICE3, OSLICESTR, OAPPEND:
- break
-
- default:
- Dump("bad reslice-l", l)
- Dump("bad reslice-r", r)
- }
-
- return false
- }
-
// Otherwise, be conservative and use write barrier.
return true
}
@@ -2215,65 +2226,11 @@ var applywritebarrier_bv Bvec
func applywritebarrier(n *Node, init **NodeList) *Node {
if n.Left != nil && n.Right != nil && needwritebarrier(n.Left, n.Right) {
- if Curfn != nil && Curfn.Func.Nowritebarrier {
- Yyerror("write barrier prohibited")
- }
- if flag_race == 0 {
- if Debug_wb > 1 {
- Warnl(int(n.Lineno), "marking %v for barrier", Nconv(n.Left, 0))
- }
- n.Op = OASWB
- return n
- }
- // Use slow path always for race detector.
- if Debug_wb > 0 {
- Warnl(int(n.Lineno), "write barrier")
- }
- t := n.Left.Type
- l := Nod(OADDR, n.Left, nil)
- l.Etype = 1 // addr does not escape
- if t.Width == int64(Widthptr) {
- n = mkcall1(writebarrierfn("writebarrierptr", t, n.Right.Type), nil, init, l, n.Right)
- } else if t.Etype == TSTRING {
- n = mkcall1(writebarrierfn("writebarrierstring", t, n.Right.Type), nil, init, l, n.Right)
- } else if Isslice(t) {
- n = mkcall1(writebarrierfn("writebarrierslice", t, n.Right.Type), nil, init, l, n.Right)
- } else if Isinter(t) {
- n = mkcall1(writebarrierfn("writebarrieriface", t, n.Right.Type), nil, init, l, n.Right)
- } else if t.Width <= int64(4*Widthptr) {
- x := int64(0)
- if applywritebarrier_bv.b == nil {
- applywritebarrier_bv = bvalloc(4)
- }
- bvresetall(applywritebarrier_bv)
- onebitwalktype1(t, &x, applywritebarrier_bv)
- var name string
- switch t.Width / int64(Widthptr) {
- default:
- Fatal("found writebarrierfat for %d-byte object of type %v", int(t.Width), t)
-
- case 2:
- name = fmt.Sprintf("writebarrierfat%d%d", bvget(applywritebarrier_bv, 0), bvget(applywritebarrier_bv, 1))
-
- case 3:
- name = fmt.Sprintf("writebarrierfat%d%d%d", bvget(applywritebarrier_bv, 0), bvget(applywritebarrier_bv, 1), bvget(applywritebarrier_bv, 2))
-
- case 4:
- name = fmt.Sprintf("writebarrierfat%d%d%d%d", bvget(applywritebarrier_bv, 0), bvget(applywritebarrier_bv, 1), bvget(applywritebarrier_bv, 2), bvget(applywritebarrier_bv, 3))
- }
-
- n = mkcall1(writebarrierfn(name, t, n.Right.Type), nil, init, l, Nodintconst(0), n.Right)
- } else {
- r := n.Right
- for r.Op == OCONVNOP {
- r = r.Left
- }
- r = Nod(OADDR, r, nil)
- r.Etype = 1 // addr does not escape
-
- //warnl(n->lineno, "typedmemmove %T %N", t, r);
- n = mkcall1(writebarrierfn("typedmemmove", t, r.Left.Type), nil, init, typename(t), l, r)
+ if Debug_wb > 1 {
+ Warnl(int(n.Lineno), "marking %v for barrier", Nconv(n.Left, 0))
}
+ n.Op = OASWB
+ return n
}
return n
}
@@ -2728,10 +2685,10 @@ func paramstoheap(argin **Type, out int) *NodeList {
if v.Alloc == nil {
v.Alloc = callnew(v.Type)
}
- nn = list(nn, Nod(OAS, v.Heapaddr, v.Alloc))
+ nn = list(nn, Nod(OAS, v.Name.Heapaddr, v.Alloc))
if v.Class&^PHEAP != PPARAMOUT {
- as = Nod(OAS, v, v.Stackparam)
- v.Stackparam.Typecheck = 1
+ as = Nod(OAS, v, v.Param.Stackparam)
+ v.Param.Stackparam.Typecheck = 1
typecheck(&as, Etop)
as = applywritebarrier(as, &nn)
nn = list(nn, as)
@@ -2754,7 +2711,7 @@ func returnsfromheap(argin **Type) *NodeList {
if v == nil || v.Class != PHEAP|PPARAMOUT {
continue
}
- nn = list(nn, Nod(OAS, v.Stackparam, v))
+ nn = list(nn, Nod(OAS, v.Param.Stackparam, v))
}
return nn
@@ -2871,7 +2828,7 @@ func addstr(n *Node, init **NodeList) *Node {
sz := int64(0)
for l := n.List; l != nil; l = l.Next {
if n.Op == OLITERAL {
- sz += int64(len(n.Val.U.Sval))
+ sz += int64(len(n.Val.U.(string)))
}
}
@@ -3026,7 +2983,13 @@ func appendslice(n *Node, init **NodeList) *Node {
return s
}
-// expand append(src, a [, b]* ) to
+// Rewrite append(src, x, y, z) so that any side effects in
+// x, y, z (including runtime panics) are evaluated in
+// initialization statements before the append.
+// For normal code generation, stop there and leave the
+// rest to cgen_append.
+//
+// For race detector, expand append(src, a [, b]* ) to
//
// init {
// s := src
@@ -3041,13 +3004,21 @@ func appendslice(n *Node, init **NodeList) *Node {
// ...
// }
// s
-func walkappend(n *Node, init **NodeList) *Node {
- walkexprlistsafe(n.List, init)
+func walkappend(n *Node, init **NodeList, dst *Node) *Node {
+ if !samesafeexpr(dst, n.List.N) {
+ l := n.List
+ l.N = safeexpr(l.N, init)
+ walkexpr(&l.N, init)
+ }
+ walkexprlistsafe(n.List.Next, init)
// walkexprlistsafe will leave OINDEX (s[n]) alone if both s
// and n are name or literal, but those may index the slice we're
// modifying here. Fix explicitly.
- for l := n.List; l != nil; l = l.Next {
+ // Using cheapexpr also makes sure that the evaluation
+ // of all arguments (and especially any panics) happen
+ // before we begin to modify the slice in a visible way.
+ for l := n.List.Next; l != nil; l = l.Next {
l.N = cheapexpr(l.N, init)
}
@@ -3062,6 +3033,12 @@ func walkappend(n *Node, init **NodeList) *Node {
return nsrc
}
+ // General case, with no function calls left as arguments.
+ // Leave for gen, except that race detector requires old form
+ if flag_race == 0 {
+ return n
+ }
+
var l *NodeList
ns := temp(nsrc.Type)
@@ -3166,213 +3143,6 @@ func copyany(n *Node, init **NodeList, runtimecall int) *Node {
return nlen
}
-// Generate frontend part for OSLICE[3][ARR|STR]
-//
-func sliceany(n *Node, init **NodeList) *Node {
- var hb *Node
- var cb *Node
-
- // print("before sliceany: %+N\n", n);
-
- src := n.Left
-
- lb := n.Right.Left
- slice3 := n.Op == OSLICE3 || n.Op == OSLICE3ARR
- if slice3 {
- hb = n.Right.Right.Left
- cb = n.Right.Right.Right
- } else {
- hb = n.Right.Right
- cb = nil
- }
-
- bounded := int(n.Etype)
-
- var bound *Node
- if n.Op == OSLICESTR {
- bound = Nod(OLEN, src, nil)
- } else {
- bound = Nod(OCAP, src, nil)
- }
-
- typecheck(&bound, Erv)
- walkexpr(&bound, init) // if src is an array, bound will be a const now.
-
- // static checks if possible
- bv := int64(1 << 50)
-
- if Isconst(bound, CTINT) {
- if !Smallintconst(bound) {
- Yyerror("array len too large")
- } else {
- bv = Mpgetfix(bound.Val.U.Xval)
- }
- }
-
- if Isconst(cb, CTINT) {
- cbv := Mpgetfix(cb.Val.U.Xval)
- if cbv < 0 || cbv > bv {
- Yyerror("slice index out of bounds")
- }
- }
-
- if Isconst(hb, CTINT) {
- hbv := Mpgetfix(hb.Val.U.Xval)
- if hbv < 0 || hbv > bv {
- Yyerror("slice index out of bounds")
- }
- }
-
- if Isconst(lb, CTINT) {
- lbv := Mpgetfix(lb.Val.U.Xval)
- if lbv < 0 || lbv > bv {
- Yyerror("slice index out of bounds")
- lbv = -1
- }
-
- if lbv == 0 {
- lb = nil
- }
- }
-
- // Checking src[lb:hb:cb] or src[lb:hb].
- // if chk0 || chk1 || chk2 { panicslice() }
-
- // All comparisons are unsigned to avoid testing < 0.
- bt := Types[Simtype[TUINT]]
-
- if cb != nil && cb.Type.Width > 4 {
- bt = Types[TUINT64]
- }
- if hb != nil && hb.Type.Width > 4 {
- bt = Types[TUINT64]
- }
- if lb != nil && lb.Type.Width > 4 {
- bt = Types[TUINT64]
- }
-
- bound = cheapexpr(conv(bound, bt), init)
-
- var chk0 *Node // cap(src) < cb
- if cb != nil {
- cb = cheapexpr(conv(cb, bt), init)
- if bounded == 0 {
- chk0 = Nod(OLT, bound, cb)
- }
- } else if slice3 {
- // When we figure out what this means, implement it.
- Fatal("slice3 with cb == N") // rejected by parser
- }
-
- var chk1 *Node // cb < hb for src[lb:hb:cb]; cap(src) < hb for src[lb:hb]
- if hb != nil {
- hb = cheapexpr(conv(hb, bt), init)
- if bounded == 0 {
- if cb != nil {
- chk1 = Nod(OLT, cb, hb)
- } else {
- chk1 = Nod(OLT, bound, hb)
- }
- }
- } else if slice3 {
- // When we figure out what this means, implement it.
- Fatal("slice3 with hb == N") // rejected by parser
- } else if n.Op == OSLICEARR {
- hb = bound
- } else {
- hb = Nod(OLEN, src, nil)
- typecheck(&hb, Erv)
- walkexpr(&hb, init)
- hb = cheapexpr(conv(hb, bt), init)
- }
-
- var chk2 *Node // hb < lb
- if lb != nil {
- lb = cheapexpr(conv(lb, bt), init)
- if bounded == 0 {
- chk2 = Nod(OLT, hb, lb)
- }
- }
-
- if chk0 != nil || chk1 != nil || chk2 != nil {
- chk := Nod(OIF, nil, nil)
- chk.Nbody = list1(mkcall("panicslice", nil, init))
- chk.Likely = -1
- if chk0 != nil {
- chk.Ntest = chk0
- }
- if chk1 != nil {
- if chk.Ntest == nil {
- chk.Ntest = chk1
- } else {
- chk.Ntest = Nod(OOROR, chk.Ntest, chk1)
- }
- }
-
- if chk2 != nil {
- if chk.Ntest == nil {
- chk.Ntest = chk2
- } else {
- chk.Ntest = Nod(OOROR, chk.Ntest, chk2)
- }
- }
-
- typecheck(&chk, Etop)
- walkstmt(&chk)
- *init = concat(*init, chk.Ninit)
- chk.Ninit = nil
- *init = list(*init, chk)
- }
-
- // prepare new cap, len and offs for backend cgen_slice
- // cap = bound [ - lo ]
- n.Right = nil
-
- n.List = nil
- if !slice3 {
- cb = bound
- }
- if lb == nil {
- bound = conv(cb, Types[Simtype[TUINT]])
- } else {
- bound = Nod(OSUB, conv(cb, Types[Simtype[TUINT]]), conv(lb, Types[Simtype[TUINT]]))
- }
- typecheck(&bound, Erv)
- walkexpr(&bound, init)
- n.List = list(n.List, bound)
-
- // len = hi [ - lo]
- if lb == nil {
- hb = conv(hb, Types[Simtype[TUINT]])
- } else {
- hb = Nod(OSUB, conv(hb, Types[Simtype[TUINT]]), conv(lb, Types[Simtype[TUINT]]))
- }
- typecheck(&hb, Erv)
- walkexpr(&hb, init)
- n.List = list(n.List, hb)
-
- // offs = [width *] lo, but omit if zero
- if lb != nil {
- var w int64
- if n.Op == OSLICESTR {
- w = 1
- } else {
- w = n.Type.Type.Width
- }
- lb = conv(lb, Types[TUINTPTR])
- if w > 1 {
- lb = Nod(OMUL, Nodintconst(w), lb)
- }
- typecheck(&lb, Erv)
- walkexpr(&lb, init)
- n.List = list(n.List, lb)
- }
-
- // print("after sliceany: %+N\n", n);
-
- return n
-}
-
func eqfor(t *Type, needsize *int) *Node {
// Should only arrive here with large memory or
// a struct/array containing a non-memory field/element.
@@ -3611,7 +3381,7 @@ func samecheap(a *Node, b *Node) bool {
case OINDEX:
ar = a.Right
br = b.Right
- if !Isconst(ar, CTINT) || !Isconst(br, CTINT) || Mpcmpfixfix(ar.Val.U.Xval, br.Val.U.Xval) != 0 {
+ if !Isconst(ar, CTINT) || !Isconst(br, CTINT) || Mpcmpfixfix(ar.Val.U.(*Mpint), br.Val.U.(*Mpint)) != 0 {
return false
}
}
@@ -3647,9 +3417,9 @@ func walkrotate(np **Node) {
w := int(l.Type.Width * 8)
if Smallintconst(l.Right) && Smallintconst(r.Right) {
- sl := int(Mpgetfix(l.Right.Val.U.Xval))
+ sl := int(Mpgetfix(l.Right.Val.U.(*Mpint)))
if sl >= 0 {
- sr := int(Mpgetfix(r.Right.Val.U.Xval))
+ sr := int(Mpgetfix(r.Right.Val.U.(*Mpint)))
if sr >= 0 && sl+sr == w {
// Rewrite left shift half to left rotate.
if l.Op == OLSH {
@@ -3660,7 +3430,7 @@ func walkrotate(np **Node) {
n.Op = OLROT
// Remove rotate 0 and rotate w.
- s := int(Mpgetfix(n.Right.Val.U.Xval))
+ s := int(Mpgetfix(n.Right.Val.U.(*Mpint)))
if s == 0 || s == w {
n = n.Left
@@ -3703,7 +3473,7 @@ func walkmul(np **Node, init **NodeList) {
// x*0 is 0 (and side effects of x).
var pow int
var w int
- if Mpgetfix(nr.Val.U.Xval) == 0 {
+ if Mpgetfix(nr.Val.U.(*Mpint)) == 0 {
cheapexpr(nl, init)
Nodconst(n, n.Type, 0)
goto ret
@@ -3796,10 +3566,10 @@ func walkdiv(np **Node, init **NodeList) {
m.W = w
if Issigned[nl.Type.Etype] {
- m.Sd = Mpgetfix(nr.Val.U.Xval)
+ m.Sd = Mpgetfix(nr.Val.U.(*Mpint))
Smagic(&m)
} else {
- m.Ud = uint64(Mpgetfix(nr.Val.U.Xval))
+ m.Ud = uint64(Mpgetfix(nr.Val.U.(*Mpint)))
Umagic(&m)
}
@@ -3993,7 +3763,7 @@ func walkdiv(np **Node, init **NodeList) {
// n = nl & (nr-1)
n.Op = OAND
- Nodconst(nc, nl.Type, Mpgetfix(nr.Val.U.Xval)-1)
+ Nodconst(nc, nl.Type, Mpgetfix(nr.Val.U.(*Mpint))-1)
} else {
// n = nl >> pow
n.Op = ORSH
@@ -4023,7 +3793,7 @@ func bounded(n *Node, max int64) bool {
bits := int32(8 * n.Type.Width)
if Smallintconst(n) {
- v := Mpgetfix(n.Val.U.Xval)
+ v := Mpgetfix(n.Val.U.(*Mpint))
return 0 <= v && v < max
}
@@ -4031,9 +3801,9 @@ func bounded(n *Node, max int64) bool {
case OAND:
v := int64(-1)
if Smallintconst(n.Left) {
- v = Mpgetfix(n.Left.Val.U.Xval)
+ v = Mpgetfix(n.Left.Val.U.(*Mpint))
} else if Smallintconst(n.Right) {
- v = Mpgetfix(n.Right.Val.U.Xval)
+ v = Mpgetfix(n.Right.Val.U.(*Mpint))
}
if 0 <= v && v < max {
@@ -4042,7 +3812,7 @@ func bounded(n *Node, max int64) bool {
case OMOD:
if !sign && Smallintconst(n.Right) {
- v := Mpgetfix(n.Right.Val.U.Xval)
+ v := Mpgetfix(n.Right.Val.U.(*Mpint))
if 0 <= v && v <= max {
return true
}
@@ -4050,7 +3820,7 @@ func bounded(n *Node, max int64) bool {
case ODIV:
if !sign && Smallintconst(n.Right) {
- v := Mpgetfix(n.Right.Val.U.Xval)
+ v := Mpgetfix(n.Right.Val.U.(*Mpint))
for bits > 0 && v >= 2 {
bits--
v >>= 1
@@ -4059,7 +3829,7 @@ func bounded(n *Node, max int64) bool {
case ORSH:
if !sign && Smallintconst(n.Right) {
- v := Mpgetfix(n.Right.Val.U.Xval)
+ v := Mpgetfix(n.Right.Val.U.(*Mpint))
if v > int64(bits) {
return true
}
@@ -4192,17 +3962,17 @@ func candiscard(n *Node) bool {
// Discardable as long as we know it's not division by zero.
case ODIV, OMOD:
- if Isconst(n.Right, CTINT) && mpcmpfixc(n.Right.Val.U.Xval, 0) != 0 {
+ if Isconst(n.Right, CTINT) && mpcmpfixc(n.Right.Val.U.(*Mpint), 0) != 0 {
break
}
- if Isconst(n.Right, CTFLT) && mpcmpfltc(n.Right.Val.U.Fval, 0) != 0 {
+ if Isconst(n.Right, CTFLT) && mpcmpfltc(n.Right.Val.U.(*Mpflt), 0) != 0 {
break
}
return false
// Discardable as long as we know it won't fail because of a bad size.
case OMAKECHAN, OMAKEMAP:
- if Isconst(n.Left, CTINT) && mpcmpfixc(n.Left.Val.U.Xval, 0) == 0 {
+ if Isconst(n.Left, CTINT) && mpcmpfixc(n.Left.Val.U.(*Mpint), 0) == 0 {
break
}
return false
@@ -4256,7 +4026,7 @@ func walkprintfunc(np **Node, init **NodeList) {
buf = fmt.Sprintf("print·%d", walkprintfunc_prgen)
fn.Nname = newname(Lookup(buf))
fn.Nname.Defn = fn
- fn.Nname.Ntype = t
+ fn.Nname.Param.Ntype = t
declare(fn.Nname, PFUNC)
oldfn := Curfn
diff --git a/src/cmd/internal/gc/y.go b/src/cmd/compile/internal/gc/y.go
index f2c8b96982..56b9d04ecb 100644
--- a/src/cmd/internal/gc/y.go
+++ b/src/cmd/compile/internal/gc/y.go
@@ -5,10 +5,11 @@ import __yyfmt__ "fmt"
//line go.y:21
import (
+ "fmt"
"strings"
)
-//line go.y:27
+//line go.y:28
type yySymType struct {
yys int
node *Node
@@ -153,7 +154,7 @@ const yyEofCode = 1
const yyErrCode = 2
const yyMaxDepth = 200
-//line go.y:2242
+//line go.y:2304
func fixlbrace(lbr int) {
// If the opening brace was an LBODY,
// set up for another one now that we're done.
@@ -856,6 +857,34 @@ var yyTok3 = [...]int{
0,
}
+var yyErrorMessages = [...]struct {
+ state int
+ token int
+ msg string
+}{
+ {332, 76, "unexpected comma during import block"},
+ {89, 63, "missing import path; require quoted string"},
+ {390, 63, "missing { after if clause"},
+ {387, 63, "missing { after switch clause"},
+ {279, 63, "missing { after for clause"},
+ {498, 36, "missing { after for clause"},
+ {17, 68, "unexpected semicolon or newline before {"},
+ {111, 63, "unexpected semicolon or newline in type declaration"},
+ {78, 69, "unexpected } in channel type"},
+ {78, 61, "unexpected ) in channel type"},
+ {78, 76, "unexpected comma in channel type"},
+ {416, 15, "unexpected semicolon or newline before else"},
+ {329, 76, "name list not allowed in interface type"},
+ {279, 33, "var declaration not allowed in for initializer"},
+ {25, 68, "unexpected { at end of statement"},
+ {371, 68, "unexpected { at end of statement"},
+ {122, 63, "argument to go/defer must be function call"},
+ {398, 63, "need trailing comma before newline in composite literal"},
+ {414, 63, "need trailing comma before newline in composite literal"},
+ {124, 25, "nested func not allowed"},
+ {650, 63, "else must be followed by if or statement block"},
+}
+
//line yaccpar:1
/* parser for yacc output */
@@ -877,7 +906,6 @@ type yyParser interface {
type yyParserImpl struct {
lookahead func() int
- state func() int
}
func (p *yyParserImpl) Lookahead() int {
@@ -887,7 +915,6 @@ func (p *yyParserImpl) Lookahead() int {
func yyNewParser() yyParser {
p := &yyParserImpl{
lookahead: func() int { return -1 },
- state: func() int { return -1 },
}
return p
}
@@ -918,6 +945,13 @@ func yyErrorMessage(state, lookAhead int) string {
if !yyErrorVerbose {
return "syntax error"
}
+
+ for _, e := range yyErrorMessages {
+ if e.state == state && e.token == lookAhead {
+ return "syntax error: " + e.msg
+ }
+ }
+
res := "syntax error: unexpected " + yyTokname(lookAhead)
// To match Bison, suggest at most four expected tokens.
@@ -1020,7 +1054,6 @@ func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int {
yystate := 0
yychar := -1
yytoken := -1 // yychar translated into internal numbering
- yyrcvr.state = func() int { return yystate }
yyrcvr.lookahead = func() int { return yychar }
defer func() {
// Make sure we report no lookahead when not parsing.
@@ -1187,13 +1220,13 @@ yydefault:
case 1:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:127
+ //line go.y:189
{
xtop = concat(xtop, yyDollar[4].list)
}
case 2:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:133
+ //line go.y:195
{
prevlineno = lineno
Yyerror("package statement must be first")
@@ -1201,13 +1234,13 @@ yydefault:
}
case 3:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:139
+ //line go.y:201
{
mkpackage(yyDollar[2].sym.Name)
}
case 4:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:149
+ //line go.y:211
{
importpkg = Runtimepkg
@@ -1220,13 +1253,13 @@ yydefault:
}
case 5:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:161
+ //line go.y:223
{
importpkg = nil
}
case 11:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:175
+ //line go.y:237
{
ipkg := importpkg
my := importmyname
@@ -1263,7 +1296,7 @@ yydefault:
}
case 12:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:210
+ //line go.y:272
{
// When an invalid import path is passed to importfile,
// it calls Yyerror and then sets up a fake import with
@@ -1275,7 +1308,7 @@ yydefault:
}
case 15:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:226
+ //line go.y:288
{
// import with original name
yyVAL.i = parserline()
@@ -1284,7 +1317,7 @@ yydefault:
}
case 16:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:233
+ //line go.y:295
{
// import with given name
yyVAL.i = parserline()
@@ -1293,7 +1326,7 @@ yydefault:
}
case 17:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:240
+ //line go.y:302
{
// import into my name space
yyVAL.i = parserline()
@@ -1302,7 +1335,7 @@ yydefault:
}
case 18:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:249
+ //line go.y:311
{
if importpkg.Name == "" {
importpkg.Name = yyDollar[2].sym.Name
@@ -1319,7 +1352,7 @@ yydefault:
}
case 20:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:266
+ //line go.y:328
{
if yyDollar[1].sym.Name == "safe" {
curio.importsafe = true
@@ -1327,64 +1360,64 @@ yydefault:
}
case 21:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:273
+ //line go.y:335
{
defercheckwidth()
}
case 22:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:277
+ //line go.y:339
{
resumecheckwidth()
unimportfile()
}
case 23:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:286
+ //line go.y:348
{
Yyerror("empty top-level declaration")
yyVAL.list = nil
}
case 25:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:292
+ //line go.y:354
{
yyVAL.list = list1(yyDollar[1].node)
}
case 26:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:296
+ //line go.y:358
{
Yyerror("non-declaration statement outside function body")
yyVAL.list = nil
}
case 27:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:301
+ //line go.y:363
{
yyVAL.list = nil
}
case 28:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:307
+ //line go.y:369
{
yyVAL.list = yyDollar[2].list
}
case 29:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:311
+ //line go.y:373
{
yyVAL.list = yyDollar[3].list
}
case 30:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:315
+ //line go.y:377
{
yyVAL.list = nil
}
case 31:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:319
+ //line go.y:381
{
yyVAL.list = yyDollar[2].list
iota_ = -100000
@@ -1392,7 +1425,7 @@ yydefault:
}
case 32:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:325
+ //line go.y:387
{
yyVAL.list = yyDollar[3].list
iota_ = -100000
@@ -1400,7 +1433,7 @@ yydefault:
}
case 33:
yyDollar = yyS[yypt-7 : yypt+1]
- //line go.y:331
+ //line go.y:393
{
yyVAL.list = concat(yyDollar[3].list, yyDollar[5].list)
iota_ = -100000
@@ -1408,80 +1441,80 @@ yydefault:
}
case 34:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:337
+ //line go.y:399
{
yyVAL.list = nil
iota_ = -100000
}
case 35:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:342
+ //line go.y:404
{
yyVAL.list = list1(yyDollar[2].node)
}
case 36:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:346
+ //line go.y:408
{
yyVAL.list = yyDollar[3].list
}
case 37:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:350
+ //line go.y:412
{
yyVAL.list = nil
}
case 38:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:356
+ //line go.y:418
{
iota_ = 0
}
case 39:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:362
+ //line go.y:424
{
yyVAL.list = variter(yyDollar[1].list, yyDollar[2].node, nil)
}
case 40:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:366
+ //line go.y:428
{
yyVAL.list = variter(yyDollar[1].list, yyDollar[2].node, yyDollar[4].list)
}
case 41:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:370
+ //line go.y:432
{
yyVAL.list = variter(yyDollar[1].list, nil, yyDollar[3].list)
}
case 42:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:376
+ //line go.y:438
{
yyVAL.list = constiter(yyDollar[1].list, yyDollar[2].node, yyDollar[4].list)
}
case 43:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:380
+ //line go.y:442
{
yyVAL.list = constiter(yyDollar[1].list, nil, yyDollar[3].list)
}
case 45:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:387
+ //line go.y:449
{
yyVAL.list = constiter(yyDollar[1].list, yyDollar[2].node, nil)
}
case 46:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:391
+ //line go.y:453
{
yyVAL.list = constiter(yyDollar[1].list, nil, nil)
}
case 47:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:397
+ //line go.y:459
{
// different from dclname because the name
// becomes visible right here, not at the end
@@ -1490,13 +1523,13 @@ yydefault:
}
case 48:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:406
+ //line go.y:468
{
yyVAL.node = typedcl1(yyDollar[1].node, yyDollar[2].node, true)
}
case 49:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:412
+ //line go.y:474
{
yyVAL.node = yyDollar[1].node
@@ -1512,14 +1545,14 @@ yydefault:
}
case 50:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:426
+ //line go.y:488
{
yyVAL.node = Nod(OASOP, yyDollar[1].node, yyDollar[3].node)
yyVAL.node.Etype = uint8(yyDollar[2].i) // rathole to pass opcode
}
case 51:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:431
+ //line go.y:493
{
if yyDollar[1].list.Next == nil && yyDollar[3].list.Next == nil {
// simple
@@ -1533,7 +1566,7 @@ yydefault:
}
case 52:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:443
+ //line go.y:505
{
if yyDollar[3].list.N.Op == OTYPESW {
yyVAL.node = Nod(OTYPESW, nil, yyDollar[3].list.N.Right)
@@ -1553,7 +1586,7 @@ yydefault:
}
case 53:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:461
+ //line go.y:523
{
yyVAL.node = Nod(OASOP, yyDollar[1].node, Nodintconst(1))
yyVAL.node.Implicit = true
@@ -1561,7 +1594,7 @@ yydefault:
}
case 54:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:467
+ //line go.y:529
{
yyVAL.node = Nod(OASOP, yyDollar[1].node, Nodintconst(1))
yyVAL.node.Implicit = true
@@ -1569,7 +1602,7 @@ yydefault:
}
case 55:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:475
+ //line go.y:537
{
var n, nn *Node
@@ -1594,7 +1627,7 @@ yydefault:
}
case 56:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:498
+ //line go.y:560
{
var n *Node
@@ -1614,7 +1647,7 @@ yydefault:
}
case 57:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:516
+ //line go.y:578
{
// will be converted to OCASE
// right will point to next case
@@ -1625,7 +1658,7 @@ yydefault:
}
case 58:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:525
+ //line go.y:587
{
var n, nn *Node
@@ -1646,13 +1679,13 @@ yydefault:
}
case 59:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:546
+ //line go.y:608
{
markdcl()
}
case 60:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:550
+ //line go.y:612
{
if yyDollar[3].list == nil {
yyVAL.node = Nod(OEMPTY, nil, nil)
@@ -1663,7 +1696,7 @@ yydefault:
}
case 61:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:561
+ //line go.y:623
{
// If the last token read by the lexer was consumed
// as part of the case, clear it (parser has cleared yychar).
@@ -1676,7 +1709,7 @@ yydefault:
}
case 62:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:572
+ //line go.y:634
{
// This is the only place in the language where a statement
// list is not allowed to drop the final semicolon, because
@@ -1696,32 +1729,32 @@ yydefault:
}
case 63:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:591
+ //line go.y:653
{
yyVAL.list = nil
}
case 64:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:595
+ //line go.y:657
{
yyVAL.list = list(yyDollar[1].list, yyDollar[2].node)
}
case 65:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:601
+ //line go.y:663
{
markdcl()
}
case 66:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:605
+ //line go.y:667
{
yyVAL.list = yyDollar[3].list
popdcl()
}
case 67:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:612
+ //line go.y:674
{
yyVAL.node = Nod(ORANGE, nil, yyDollar[4].node)
yyVAL.node.List = yyDollar[1].list
@@ -1729,7 +1762,7 @@ yydefault:
}
case 68:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:618
+ //line go.y:680
{
yyVAL.node = Nod(ORANGE, nil, yyDollar[4].node)
yyVAL.node.List = yyDollar[1].list
@@ -1738,14 +1771,14 @@ yydefault:
}
case 69:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:625
+ //line go.y:687
{
yyVAL.node = Nod(ORANGE, nil, yyDollar[2].node)
yyVAL.node.Etype = 0 // := flag
}
case 70:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:632
+ //line go.y:694
{
// init ; test ; incr
if yyDollar[5].node != nil && yyDollar[5].node.Colas {
@@ -1760,7 +1793,7 @@ yydefault:
}
case 71:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:645
+ //line go.y:707
{
// normal test
yyVAL.node = Nod(OFOR, nil, nil)
@@ -1768,27 +1801,27 @@ yydefault:
}
case 73:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:654
+ //line go.y:716
{
yyVAL.node = yyDollar[1].node
yyVAL.node.Nbody = concat(yyVAL.node.Nbody, yyDollar[2].list)
}
case 74:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:661
+ //line go.y:723
{
markdcl()
}
case 75:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:665
+ //line go.y:727
{
yyVAL.node = yyDollar[3].node
popdcl()
}
case 76:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:672
+ //line go.y:734
{
// test
yyVAL.node = Nod(OIF, nil, nil)
@@ -1796,7 +1829,7 @@ yydefault:
}
case 77:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:678
+ //line go.y:740
{
// init ; test
yyVAL.node = Nod(OIF, nil, nil)
@@ -1807,13 +1840,13 @@ yydefault:
}
case 78:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:690
+ //line go.y:752
{
markdcl()
}
case 79:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:694
+ //line go.y:756
{
if yyDollar[3].node.Ntest == nil {
Yyerror("missing condition in if statement")
@@ -1821,13 +1854,13 @@ yydefault:
}
case 80:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:700
+ //line go.y:762
{
yyDollar[3].node.Nbody = yyDollar[5].list
}
case 81:
yyDollar = yyS[yypt-8 : yypt+1]
- //line go.y:704
+ //line go.y:766
{
var n *Node
var nn *NodeList
@@ -1845,13 +1878,13 @@ yydefault:
}
case 82:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:722
+ //line go.y:784
{
markdcl()
}
case 83:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:726
+ //line go.y:788
{
if yyDollar[4].node.Ntest == nil {
Yyerror("missing condition in if statement")
@@ -1861,25 +1894,25 @@ yydefault:
}
case 84:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:735
+ //line go.y:797
{
yyVAL.list = nil
}
case 85:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:739
+ //line go.y:801
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[2].list)
}
case 86:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:744
+ //line go.y:806
{
yyVAL.list = nil
}
case 87:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:748
+ //line go.y:810
{
l := &NodeList{N: yyDollar[2].node}
l.End = l
@@ -1887,13 +1920,13 @@ yydefault:
}
case 88:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:756
+ //line go.y:818
{
markdcl()
}
case 89:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:760
+ //line go.y:822
{
var n *Node
n = yyDollar[3].node.Ntest
@@ -1904,7 +1937,7 @@ yydefault:
}
case 90:
yyDollar = yyS[yypt-7 : yypt+1]
- //line go.y:769
+ //line go.y:831
{
yyVAL.node = yyDollar[3].node
yyVAL.node.Op = OSWITCH
@@ -1914,13 +1947,13 @@ yydefault:
}
case 91:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:779
+ //line go.y:841
{
typesw = Nod(OXXX, typesw, nil)
}
case 92:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:783
+ //line go.y:845
{
yyVAL.node = Nod(OSELECT, nil, nil)
yyVAL.node.Lineno = typesw.Lineno
@@ -1929,133 +1962,133 @@ yydefault:
}
case 94:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:796
+ //line go.y:858
{
yyVAL.node = Nod(OOROR, yyDollar[1].node, yyDollar[3].node)
}
case 95:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:800
+ //line go.y:862
{
yyVAL.node = Nod(OANDAND, yyDollar[1].node, yyDollar[3].node)
}
case 96:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:804
+ //line go.y:866
{
yyVAL.node = Nod(OEQ, yyDollar[1].node, yyDollar[3].node)
}
case 97:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:808
+ //line go.y:870
{
yyVAL.node = Nod(ONE, yyDollar[1].node, yyDollar[3].node)
}
case 98:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:812
+ //line go.y:874
{
yyVAL.node = Nod(OLT, yyDollar[1].node, yyDollar[3].node)
}
case 99:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:816
+ //line go.y:878
{
yyVAL.node = Nod(OLE, yyDollar[1].node, yyDollar[3].node)
}
case 100:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:820
+ //line go.y:882
{
yyVAL.node = Nod(OGE, yyDollar[1].node, yyDollar[3].node)
}
case 101:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:824
+ //line go.y:886
{
yyVAL.node = Nod(OGT, yyDollar[1].node, yyDollar[3].node)
}
case 102:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:828
+ //line go.y:890
{
yyVAL.node = Nod(OADD, yyDollar[1].node, yyDollar[3].node)
}
case 103:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:832
+ //line go.y:894
{
yyVAL.node = Nod(OSUB, yyDollar[1].node, yyDollar[3].node)
}
case 104:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:836
+ //line go.y:898
{
yyVAL.node = Nod(OOR, yyDollar[1].node, yyDollar[3].node)
}
case 105:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:840
+ //line go.y:902
{
yyVAL.node = Nod(OXOR, yyDollar[1].node, yyDollar[3].node)
}
case 106:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:844
+ //line go.y:906
{
yyVAL.node = Nod(OMUL, yyDollar[1].node, yyDollar[3].node)
}
case 107:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:848
+ //line go.y:910
{
yyVAL.node = Nod(ODIV, yyDollar[1].node, yyDollar[3].node)
}
case 108:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:852
+ //line go.y:914
{
yyVAL.node = Nod(OMOD, yyDollar[1].node, yyDollar[3].node)
}
case 109:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:856
+ //line go.y:918
{
yyVAL.node = Nod(OAND, yyDollar[1].node, yyDollar[3].node)
}
case 110:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:860
+ //line go.y:922
{
yyVAL.node = Nod(OANDNOT, yyDollar[1].node, yyDollar[3].node)
}
case 111:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:864
+ //line go.y:926
{
yyVAL.node = Nod(OLSH, yyDollar[1].node, yyDollar[3].node)
}
case 112:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:868
+ //line go.y:930
{
yyVAL.node = Nod(ORSH, yyDollar[1].node, yyDollar[3].node)
}
case 113:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:873
+ //line go.y:935
{
yyVAL.node = Nod(OSEND, yyDollar[1].node, yyDollar[3].node)
}
case 115:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:880
+ //line go.y:942
{
yyVAL.node = Nod(OIND, yyDollar[2].node, nil)
}
case 116:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:884
+ //line go.y:946
{
if yyDollar[2].node.Op == OCOMPLIT {
// Special case for &T{...}: turn into (*T){...}.
@@ -2068,57 +2101,57 @@ yydefault:
}
case 117:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:895
+ //line go.y:957
{
yyVAL.node = Nod(OPLUS, yyDollar[2].node, nil)
}
case 118:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:899
+ //line go.y:961
{
yyVAL.node = Nod(OMINUS, yyDollar[2].node, nil)
}
case 119:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:903
+ //line go.y:965
{
yyVAL.node = Nod(ONOT, yyDollar[2].node, nil)
}
case 120:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:907
+ //line go.y:969
{
Yyerror("the bitwise complement operator is ^")
yyVAL.node = Nod(OCOM, yyDollar[2].node, nil)
}
case 121:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:912
+ //line go.y:974
{
yyVAL.node = Nod(OCOM, yyDollar[2].node, nil)
}
case 122:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:916
+ //line go.y:978
{
yyVAL.node = Nod(ORECV, yyDollar[2].node, nil)
}
case 123:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:926
+ //line go.y:988
{
yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
}
case 124:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:930
+ //line go.y:992
{
yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
yyVAL.node.List = yyDollar[3].list
}
case 125:
yyDollar = yyS[yypt-6 : yypt+1]
- //line go.y:935
+ //line go.y:997
{
yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
yyVAL.node.List = yyDollar[3].list
@@ -2126,13 +2159,13 @@ yydefault:
}
case 126:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:943
+ //line go.y:1005
{
yyVAL.node = nodlit(yyDollar[1].val)
}
case 128:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:948
+ //line go.y:1010
{
if yyDollar[1].node.Op == OPACK {
var s *Sym
@@ -2145,31 +2178,31 @@ yydefault:
}
case 129:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:959
+ //line go.y:1021
{
yyVAL.node = Nod(ODOTTYPE, yyDollar[1].node, yyDollar[4].node)
}
case 130:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:963
+ //line go.y:1025
{
yyVAL.node = Nod(OTYPESW, nil, yyDollar[1].node)
}
case 131:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:967
+ //line go.y:1029
{
yyVAL.node = Nod(OINDEX, yyDollar[1].node, yyDollar[3].node)
}
case 132:
yyDollar = yyS[yypt-6 : yypt+1]
- //line go.y:971
+ //line go.y:1033
{
yyVAL.node = Nod(OSLICE, yyDollar[1].node, Nod(OKEY, yyDollar[3].node, yyDollar[5].node))
}
case 133:
yyDollar = yyS[yypt-8 : yypt+1]
- //line go.y:975
+ //line go.y:1037
{
if yyDollar[5].node == nil {
Yyerror("middle index required in 3-index slice")
@@ -2181,7 +2214,7 @@ yydefault:
}
case 135:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:986
+ //line go.y:1048
{
// conversion
yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
@@ -2189,7 +2222,7 @@ yydefault:
}
case 136:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:992
+ //line go.y:1054
{
yyVAL.node = yyDollar[3].node
yyVAL.node.Right = yyDollar[1].node
@@ -2198,7 +2231,7 @@ yydefault:
}
case 137:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:999
+ //line go.y:1061
{
yyVAL.node = yyDollar[3].node
yyVAL.node.Right = yyDollar[1].node
@@ -2206,7 +2239,7 @@ yydefault:
}
case 138:
yyDollar = yyS[yypt-7 : yypt+1]
- //line go.y:1005
+ //line go.y:1067
{
Yyerror("cannot parenthesize type in composite literal")
yyVAL.node = yyDollar[5].node
@@ -2215,7 +2248,7 @@ yydefault:
}
case 140:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1014
+ //line go.y:1076
{
// composite expression.
// make node early so we get the right line number.
@@ -2223,13 +2256,13 @@ yydefault:
}
case 141:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1022
+ //line go.y:1084
{
yyVAL.node = Nod(OKEY, yyDollar[1].node, yyDollar[3].node)
}
case 142:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1028
+ //line go.y:1090
{
// These nodes do not carry line numbers.
// Since a composite literal commonly spans several lines,
@@ -2244,21 +2277,21 @@ yydefault:
}
case 143:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1041
+ //line go.y:1103
{
yyVAL.node = yyDollar[2].node
yyVAL.node.List = yyDollar[3].list
}
case 145:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1049
+ //line go.y:1111
{
yyVAL.node = yyDollar[2].node
yyVAL.node.List = yyDollar[3].list
}
case 147:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1057
+ //line go.y:1119
{
yyVAL.node = yyDollar[2].node
@@ -2272,19 +2305,19 @@ yydefault:
}
case 151:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1078
+ //line go.y:1140
{
yyVAL.i = LBODY
}
case 152:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1082
+ //line go.y:1144
{
yyVAL.i = '{'
}
case 153:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1093
+ //line go.y:1155
{
if yyDollar[1].sym == nil {
yyVAL.node = nil
@@ -2294,19 +2327,19 @@ yydefault:
}
case 154:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1103
+ //line go.y:1165
{
yyVAL.node = dclname(yyDollar[1].sym)
}
case 155:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1108
+ //line go.y:1170
{
yyVAL.node = nil
}
case 157:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1115
+ //line go.y:1177
{
yyVAL.sym = yyDollar[1].sym
// during imports, unqualified non-exported identifiers are from builtinpkg
@@ -2316,45 +2349,45 @@ yydefault:
}
case 159:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1124
+ //line go.y:1186
{
yyVAL.sym = nil
}
case 160:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1130
+ //line go.y:1192
{
var p *Pkg
- if yyDollar[2].val.U.Sval == "" {
+ if yyDollar[2].val.U.(string) == "" {
p = importpkg
} else {
- if isbadimport(yyDollar[2].val.U.Sval) {
+ if isbadimport(yyDollar[2].val.U.(string)) {
errorexit()
}
- p = mkpkg(yyDollar[2].val.U.Sval)
+ p = mkpkg(yyDollar[2].val.U.(string))
}
yyVAL.sym = Pkglookup(yyDollar[4].sym.Name, p)
}
case 161:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1144
+ //line go.y:1206
{
var p *Pkg
- if yyDollar[2].val.U.Sval == "" {
+ if yyDollar[2].val.U.(string) == "" {
p = importpkg
} else {
- if isbadimport(yyDollar[2].val.U.Sval) {
+ if isbadimport(yyDollar[2].val.U.(string)) {
errorexit()
}
- p = mkpkg(yyDollar[2].val.U.Sval)
+ p = mkpkg(yyDollar[2].val.U.(string))
}
yyVAL.sym = Pkglookup("?", p)
}
case 162:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1160
+ //line go.y:1222
{
yyVAL.node = oldname(yyDollar[1].sym)
if yyVAL.node.Pack != nil {
@@ -2363,38 +2396,38 @@ yydefault:
}
case 164:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1181
+ //line go.y:1243
{
Yyerror("final argument in variadic function missing type")
yyVAL.node = Nod(ODDD, typenod(typ(TINTER)), nil)
}
case 165:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1186
+ //line go.y:1248
{
yyVAL.node = Nod(ODDD, yyDollar[2].node, nil)
}
case 171:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1197
+ //line go.y:1259
{
yyVAL.node = yyDollar[2].node
}
case 175:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1206
+ //line go.y:1268
{
yyVAL.node = Nod(OIND, yyDollar[2].node, nil)
}
case 180:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1216
+ //line go.y:1278
{
yyVAL.node = yyDollar[2].node
}
case 190:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1237
+ //line go.y:1299
{
if yyDollar[1].node.Op == OPACK {
var s *Sym
@@ -2407,53 +2440,53 @@ yydefault:
}
case 191:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1250
+ //line go.y:1312
{
yyVAL.node = Nod(OTARRAY, yyDollar[2].node, yyDollar[4].node)
}
case 192:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1254
+ //line go.y:1316
{
// array literal of nelem
yyVAL.node = Nod(OTARRAY, Nod(ODDD, nil, nil), yyDollar[4].node)
}
case 193:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1259
+ //line go.y:1321
{
yyVAL.node = Nod(OTCHAN, yyDollar[2].node, nil)
yyVAL.node.Etype = Cboth
}
case 194:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1264
+ //line go.y:1326
{
yyVAL.node = Nod(OTCHAN, yyDollar[3].node, nil)
yyVAL.node.Etype = Csend
}
case 195:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1269
+ //line go.y:1331
{
yyVAL.node = Nod(OTMAP, yyDollar[3].node, yyDollar[5].node)
}
case 198:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1277
+ //line go.y:1339
{
yyVAL.node = Nod(OIND, yyDollar[2].node, nil)
}
case 199:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1283
+ //line go.y:1345
{
yyVAL.node = Nod(OTCHAN, yyDollar[3].node, nil)
yyVAL.node.Etype = Crecv
}
case 200:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1290
+ //line go.y:1352
{
yyVAL.node = Nod(OTSTRUCT, nil, nil)
yyVAL.node.List = yyDollar[3].list
@@ -2461,14 +2494,14 @@ yydefault:
}
case 201:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1296
+ //line go.y:1358
{
yyVAL.node = Nod(OTSTRUCT, nil, nil)
fixlbrace(yyDollar[2].i)
}
case 202:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1303
+ //line go.y:1365
{
yyVAL.node = Nod(OTINTER, nil, nil)
yyVAL.node.List = yyDollar[3].list
@@ -2476,14 +2509,14 @@ yydefault:
}
case 203:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1309
+ //line go.y:1371
{
yyVAL.node = Nod(OTINTER, nil, nil)
fixlbrace(yyDollar[2].i)
}
case 204:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1320
+ //line go.y:1382
{
yyVAL.node = yyDollar[2].node
if yyVAL.node == nil {
@@ -2501,7 +2534,7 @@ yydefault:
}
case 205:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1338
+ //line go.y:1400
{
var t *Node
@@ -2527,14 +2560,14 @@ yydefault:
yyVAL.node = Nod(ODCLFUNC, nil, nil)
yyVAL.node.Nname = newfuncname(yyDollar[1].sym)
yyVAL.node.Nname.Defn = yyVAL.node
- yyVAL.node.Nname.Ntype = t // TODO: check if nname already has an ntype
+ yyVAL.node.Nname.Param.Ntype = t // TODO: check if nname already has an ntype
declare(yyVAL.node.Nname, PFUNC)
funchdr(yyVAL.node)
}
case 206:
yyDollar = yyS[yypt-8 : yypt+1]
- //line go.y:1369
+ //line go.y:1431
{
var rcvr, t *Node
@@ -2564,7 +2597,7 @@ yydefault:
yyVAL.node.Func.Shortname = newfuncname(yyDollar[4].sym)
yyVAL.node.Nname = methodname1(yyVAL.node.Func.Shortname, rcvr.Right)
yyVAL.node.Nname.Defn = yyVAL.node
- yyVAL.node.Nname.Ntype = t
+ yyVAL.node.Nname.Param.Ntype = t
yyVAL.node.Nname.Nointerface = nointerface
declare(yyVAL.node.Nname, PFUNC)
@@ -2572,7 +2605,7 @@ yydefault:
}
case 207:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1407
+ //line go.y:1469
{
var s *Sym
var t *Type
@@ -2599,7 +2632,7 @@ yydefault:
}
case 208:
yyDollar = yyS[yypt-8 : yypt+1]
- //line go.y:1432
+ //line go.y:1494
{
yyVAL.node = methodname1(newname(yyDollar[4].sym), yyDollar[2].list.N.Right)
yyVAL.node.Type = functype(yyDollar[2].list.N, yyDollar[6].list, yyDollar[8].list)
@@ -2617,7 +2650,7 @@ yydefault:
}
case 209:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1450
+ //line go.y:1512
{
yyDollar[3].list = checkarglist(yyDollar[3].list, 1)
yyVAL.node = Nod(OTFUNC, nil, nil)
@@ -2626,13 +2659,13 @@ yydefault:
}
case 210:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1458
+ //line go.y:1520
{
yyVAL.list = nil
}
case 211:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1462
+ //line go.y:1524
{
yyVAL.list = yyDollar[2].list
if yyVAL.list == nil {
@@ -2641,51 +2674,51 @@ yydefault:
}
case 212:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1471
+ //line go.y:1533
{
yyVAL.list = nil
}
case 213:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1475
+ //line go.y:1537
{
yyVAL.list = list1(Nod(ODCLFIELD, nil, yyDollar[1].node))
}
case 214:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1479
+ //line go.y:1541
{
yyDollar[2].list = checkarglist(yyDollar[2].list, 0)
yyVAL.list = yyDollar[2].list
}
case 215:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1486
+ //line go.y:1548
{
closurehdr(yyDollar[1].node)
}
case 216:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1492
+ //line go.y:1554
{
yyVAL.node = closurebody(yyDollar[3].list)
fixlbrace(yyDollar[2].i)
}
case 217:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1497
+ //line go.y:1559
{
yyVAL.node = closurebody(nil)
}
case 218:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1508
+ //line go.y:1570
{
yyVAL.list = nil
}
case 219:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1512
+ //line go.y:1574
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[2].list)
if nsyntaxerrors == 0 {
@@ -2698,49 +2731,49 @@ yydefault:
}
case 221:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1526
+ //line go.y:1588
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[3].list)
}
case 223:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1533
+ //line go.y:1595
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[3].list)
}
case 224:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1539
+ //line go.y:1601
{
yyVAL.list = list1(yyDollar[1].node)
}
case 225:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1543
+ //line go.y:1605
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 227:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1550
+ //line go.y:1612
{
yyVAL.list = concat(yyDollar[1].list, yyDollar[3].list)
}
case 228:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1556
+ //line go.y:1618
{
yyVAL.list = list1(yyDollar[1].node)
}
case 229:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1560
+ //line go.y:1622
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 230:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1566
+ //line go.y:1628
{
var l *NodeList
@@ -2766,14 +2799,14 @@ yydefault:
}
case 231:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1590
+ //line go.y:1652
{
yyDollar[1].node.Val = yyDollar[2].val
yyVAL.list = list1(yyDollar[1].node)
}
case 232:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1595
+ //line go.y:1657
{
yyDollar[2].node.Val = yyDollar[4].val
yyVAL.list = list1(yyDollar[2].node)
@@ -2781,7 +2814,7 @@ yydefault:
}
case 233:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1601
+ //line go.y:1663
{
yyDollar[2].node.Right = Nod(OIND, yyDollar[2].node.Right, nil)
yyDollar[2].node.Val = yyDollar[3].val
@@ -2789,7 +2822,7 @@ yydefault:
}
case 234:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1607
+ //line go.y:1669
{
yyDollar[3].node.Right = Nod(OIND, yyDollar[3].node.Right, nil)
yyDollar[3].node.Val = yyDollar[5].val
@@ -2798,7 +2831,7 @@ yydefault:
}
case 235:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1614
+ //line go.y:1676
{
yyDollar[3].node.Right = Nod(OIND, yyDollar[3].node.Right, nil)
yyDollar[3].node.Val = yyDollar[5].val
@@ -2807,7 +2840,7 @@ yydefault:
}
case 236:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1623
+ //line go.y:1685
{
var n *Node
@@ -2819,7 +2852,7 @@ yydefault:
}
case 237:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1633
+ //line go.y:1695
{
var pkg *Pkg
@@ -2834,33 +2867,33 @@ yydefault:
}
case 238:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1648
+ //line go.y:1710
{
yyVAL.node = embedded(yyDollar[1].sym, localpkg)
}
case 239:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1654
+ //line go.y:1716
{
yyVAL.node = Nod(ODCLFIELD, yyDollar[1].node, yyDollar[2].node)
ifacedcl(yyVAL.node)
}
case 240:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1659
+ //line go.y:1721
{
yyVAL.node = Nod(ODCLFIELD, nil, oldname(yyDollar[1].sym))
}
case 241:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1663
+ //line go.y:1725
{
yyVAL.node = Nod(ODCLFIELD, nil, oldname(yyDollar[2].sym))
Yyerror("cannot parenthesize embedded type")
}
case 242:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1670
+ //line go.y:1732
{
// without func keyword
yyDollar[2].list = checkarglist(yyDollar[2].list, 1)
@@ -2870,7 +2903,7 @@ yydefault:
}
case 244:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1684
+ //line go.y:1746
{
yyVAL.node = Nod(ONONAME, nil, nil)
yyVAL.node.Sym = yyDollar[1].sym
@@ -2878,7 +2911,7 @@ yydefault:
}
case 245:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1690
+ //line go.y:1752
{
yyVAL.node = Nod(ONONAME, nil, nil)
yyVAL.node.Sym = yyDollar[1].sym
@@ -2886,56 +2919,56 @@ yydefault:
}
case 247:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1699
+ //line go.y:1761
{
yyVAL.list = list1(yyDollar[1].node)
}
case 248:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1703
+ //line go.y:1765
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 249:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1708
+ //line go.y:1770
{
yyVAL.list = nil
}
case 250:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1712
+ //line go.y:1774
{
yyVAL.list = yyDollar[1].list
}
case 251:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1720
+ //line go.y:1782
{
yyVAL.node = nil
}
case 253:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1725
+ //line go.y:1787
{
yyVAL.node = liststmt(yyDollar[1].list)
}
case 255:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1730
+ //line go.y:1792
{
yyVAL.node = nil
}
case 261:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1741
+ //line go.y:1803
{
yyDollar[1].node = Nod(OLABEL, yyDollar[1].node, nil)
yyDollar[1].node.Sym = dclstack // context, for goto restrictions
}
case 262:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1746
+ //line go.y:1808
{
var l *NodeList
@@ -2948,7 +2981,7 @@ yydefault:
}
case 263:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1757
+ //line go.y:1819
{
// will be converted to OFALL
yyVAL.node = Nod(OXFALL, nil, nil)
@@ -2956,38 +2989,38 @@ yydefault:
}
case 264:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1763
+ //line go.y:1825
{
yyVAL.node = Nod(OBREAK, yyDollar[2].node, nil)
}
case 265:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1767
+ //line go.y:1829
{
yyVAL.node = Nod(OCONTINUE, yyDollar[2].node, nil)
}
case 266:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1771
+ //line go.y:1833
{
yyVAL.node = Nod(OPROC, yyDollar[2].node, nil)
}
case 267:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1775
+ //line go.y:1837
{
yyVAL.node = Nod(ODEFER, yyDollar[2].node, nil)
}
case 268:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1779
+ //line go.y:1841
{
yyVAL.node = Nod(OGOTO, yyDollar[2].node, nil)
yyVAL.node.Sym = dclstack // context, for goto restrictions
}
case 269:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1784
+ //line go.y:1846
{
yyVAL.node = Nod(ORETURN, nil, nil)
yyVAL.node.List = yyDollar[2].list
@@ -3009,7 +3042,7 @@ yydefault:
}
case 270:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1806
+ //line go.y:1868
{
yyVAL.list = nil
if yyDollar[1].node != nil {
@@ -3018,7 +3051,7 @@ yydefault:
}
case 271:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1813
+ //line go.y:1875
{
yyVAL.list = yyDollar[1].list
if yyDollar[3].node != nil {
@@ -3027,163 +3060,163 @@ yydefault:
}
case 272:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1822
+ //line go.y:1884
{
yyVAL.list = list1(yyDollar[1].node)
}
case 273:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1826
+ //line go.y:1888
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 274:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1832
+ //line go.y:1894
{
yyVAL.list = list1(yyDollar[1].node)
}
case 275:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1836
+ //line go.y:1898
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 276:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1842
+ //line go.y:1904
{
yyVAL.list = list1(yyDollar[1].node)
}
case 277:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1846
+ //line go.y:1908
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 278:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1852
+ //line go.y:1914
{
yyVAL.list = list1(yyDollar[1].node)
}
case 279:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1856
+ //line go.y:1918
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 280:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1865
+ //line go.y:1927
{
yyVAL.list = list1(yyDollar[1].node)
}
case 281:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1869
+ //line go.y:1931
{
yyVAL.list = list1(yyDollar[1].node)
}
case 282:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1873
+ //line go.y:1935
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 283:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:1877
+ //line go.y:1939
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 284:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1882
+ //line go.y:1944
{
yyVAL.list = nil
}
case 285:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:1886
+ //line go.y:1948
{
yyVAL.list = yyDollar[1].list
}
case 290:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1900
+ //line go.y:1962
{
yyVAL.node = nil
}
case 292:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1906
+ //line go.y:1968
{
yyVAL.list = nil
}
case 294:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1912
+ //line go.y:1974
{
yyVAL.node = nil
}
case 296:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1918
+ //line go.y:1980
{
yyVAL.list = nil
}
case 298:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1924
+ //line go.y:1986
{
yyVAL.list = nil
}
case 300:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1930
+ //line go.y:1992
{
yyVAL.list = nil
}
case 302:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:1936
+ //line go.y:1998
{
yyVAL.val.Ctype = CTxxx
}
case 304:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1946
+ //line go.y:2008
{
- importimport(yyDollar[2].sym, yyDollar[3].val.U.Sval)
+ importimport(yyDollar[2].sym, yyDollar[3].val.U.(string))
}
case 305:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1950
+ //line go.y:2012
{
importvar(yyDollar[2].sym, yyDollar[3].typ)
}
case 306:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:1954
+ //line go.y:2016
{
importconst(yyDollar[2].sym, Types[TIDEAL], yyDollar[4].node)
}
case 307:
yyDollar = yyS[yypt-6 : yypt+1]
- //line go.y:1958
+ //line go.y:2020
{
importconst(yyDollar[2].sym, yyDollar[3].typ, yyDollar[5].node)
}
case 308:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1962
+ //line go.y:2024
{
importtype(yyDollar[2].typ, yyDollar[3].typ)
}
case 309:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:1966
+ //line go.y:2028
{
if yyDollar[2].node == nil {
dclcontext = PEXTERN // since we skip the funcbody below
@@ -3196,35 +3229,35 @@ yydefault:
importlist = list(importlist, yyDollar[2].node)
if Debug['E'] > 0 {
- print("import [%q] func %lN \n", importpkg.Path, yyDollar[2].node)
+ fmt.Printf("import [%q] func %v \n", importpkg.Path, yyDollar[2].node)
if Debug['m'] > 2 && yyDollar[2].node.Func.Inl != nil {
- print("inl body:%+H\n", yyDollar[2].node.Func.Inl)
+ fmt.Printf("inl body:%v\n", yyDollar[2].node.Func.Inl)
}
}
}
case 310:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1987
+ //line go.y:2049
{
yyVAL.sym = yyDollar[1].sym
structpkg = yyVAL.sym.Pkg
}
case 311:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:1994
+ //line go.y:2056
{
yyVAL.typ = pkgtype(yyDollar[1].sym)
importsym(yyDollar[1].sym, OTYPE)
}
case 317:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2014
+ //line go.y:2076
{
yyVAL.typ = pkgtype(yyDollar[1].sym)
}
case 318:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2018
+ //line go.y:2080
{
// predefined name like uint8
yyDollar[1].sym = Pkglookup(yyDollar[1].sym.Name, builtinpkg)
@@ -3237,43 +3270,43 @@ yydefault:
}
case 319:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2029
+ //line go.y:2091
{
yyVAL.typ = aindex(nil, yyDollar[3].typ)
}
case 320:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2033
+ //line go.y:2095
{
yyVAL.typ = aindex(nodlit(yyDollar[2].val), yyDollar[4].typ)
}
case 321:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:2037
+ //line go.y:2099
{
yyVAL.typ = maptype(yyDollar[3].typ, yyDollar[5].typ)
}
case 322:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2041
+ //line go.y:2103
{
yyVAL.typ = tostruct(yyDollar[3].list)
}
case 323:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2045
+ //line go.y:2107
{
yyVAL.typ = tointerface(yyDollar[3].list)
}
case 324:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:2049
+ //line go.y:2111
{
yyVAL.typ = Ptrto(yyDollar[2].typ)
}
case 325:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:2053
+ //line go.y:2115
{
yyVAL.typ = typ(TCHAN)
yyVAL.typ.Type = yyDollar[2].typ
@@ -3281,7 +3314,7 @@ yydefault:
}
case 326:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2059
+ //line go.y:2121
{
yyVAL.typ = typ(TCHAN)
yyVAL.typ.Type = yyDollar[3].typ
@@ -3289,7 +3322,7 @@ yydefault:
}
case 327:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2065
+ //line go.y:2127
{
yyVAL.typ = typ(TCHAN)
yyVAL.typ.Type = yyDollar[3].typ
@@ -3297,7 +3330,7 @@ yydefault:
}
case 328:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2073
+ //line go.y:2135
{
yyVAL.typ = typ(TCHAN)
yyVAL.typ.Type = yyDollar[3].typ
@@ -3305,13 +3338,13 @@ yydefault:
}
case 329:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:2081
+ //line go.y:2143
{
yyVAL.typ = functype(nil, yyDollar[3].list, yyDollar[5].list)
}
case 330:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2087
+ //line go.y:2149
{
yyVAL.node = Nod(ODCLFIELD, nil, typenod(yyDollar[2].typ))
if yyDollar[1].sym != nil {
@@ -3321,7 +3354,7 @@ yydefault:
}
case 331:
yyDollar = yyS[yypt-4 : yypt+1]
- //line go.y:2095
+ //line go.y:2157
{
var t *Type
@@ -3338,7 +3371,7 @@ yydefault:
}
case 332:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2112
+ //line go.y:2174
{
var s *Sym
var p *Pkg
@@ -3362,55 +3395,55 @@ yydefault:
}
case 333:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:2136
+ //line go.y:2198
{
yyVAL.node = Nod(ODCLFIELD, newname(yyDollar[1].sym), typenod(functype(fakethis(), yyDollar[3].list, yyDollar[5].list)))
}
case 334:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2140
+ //line go.y:2202
{
yyVAL.node = Nod(ODCLFIELD, nil, typenod(yyDollar[1].typ))
}
case 335:
yyDollar = yyS[yypt-0 : yypt+1]
- //line go.y:2145
+ //line go.y:2207
{
yyVAL.list = nil
}
case 337:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2152
+ //line go.y:2214
{
yyVAL.list = yyDollar[2].list
}
case 338:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2156
+ //line go.y:2218
{
yyVAL.list = list1(Nod(ODCLFIELD, nil, typenod(yyDollar[1].typ)))
}
case 339:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2166
+ //line go.y:2228
{
yyVAL.node = nodlit(yyDollar[1].val)
}
case 340:
yyDollar = yyS[yypt-2 : yypt+1]
- //line go.y:2170
+ //line go.y:2232
{
yyVAL.node = nodlit(yyDollar[2].val)
switch yyVAL.node.Val.Ctype {
case CTINT, CTRUNE:
- mpnegfix(yyVAL.node.Val.U.Xval)
+ mpnegfix(yyVAL.node.Val.U.(*Mpint))
break
case CTFLT:
- mpnegflt(yyVAL.node.Val.U.Fval)
+ mpnegflt(yyVAL.node.Val.U.(*Mpflt))
break
case CTCPLX:
- mpnegflt(&yyVAL.node.Val.U.Cval.Real)
- mpnegflt(&yyVAL.node.Val.U.Cval.Imag)
+ mpnegflt(&yyVAL.node.Val.U.(*Mpcplx).Real)
+ mpnegflt(&yyVAL.node.Val.U.(*Mpcplx).Imag)
break
default:
Yyerror("bad negated constant")
@@ -3418,7 +3451,7 @@ yydefault:
}
case 341:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2188
+ //line go.y:2250
{
yyVAL.node = oldname(Pkglookup(yyDollar[1].sym.Name, builtinpkg))
if yyVAL.node.Op != OLITERAL {
@@ -3427,50 +3460,50 @@ yydefault:
}
case 343:
yyDollar = yyS[yypt-5 : yypt+1]
- //line go.y:2198
+ //line go.y:2260
{
if yyDollar[2].node.Val.Ctype == CTRUNE && yyDollar[4].node.Val.Ctype == CTINT {
yyVAL.node = yyDollar[2].node
- mpaddfixfix(yyDollar[2].node.Val.U.Xval, yyDollar[4].node.Val.U.Xval, 0)
+ mpaddfixfix(yyDollar[2].node.Val.U.(*Mpint), yyDollar[4].node.Val.U.(*Mpint), 0)
break
}
- yyDollar[4].node.Val.U.Cval.Real = yyDollar[4].node.Val.U.Cval.Imag
- Mpmovecflt(&yyDollar[4].node.Val.U.Cval.Imag, 0.0)
+ yyDollar[4].node.Val.U.(*Mpcplx).Real = yyDollar[4].node.Val.U.(*Mpcplx).Imag
+ Mpmovecflt(&yyDollar[4].node.Val.U.(*Mpcplx).Imag, 0.0)
yyVAL.node = nodcplxlit(yyDollar[2].node.Val, yyDollar[4].node.Val)
}
case 346:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2214
+ //line go.y:2276
{
yyVAL.list = list1(yyDollar[1].node)
}
case 347:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2218
+ //line go.y:2280
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 348:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2224
+ //line go.y:2286
{
yyVAL.list = list1(yyDollar[1].node)
}
case 349:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2228
+ //line go.y:2290
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
case 350:
yyDollar = yyS[yypt-1 : yypt+1]
- //line go.y:2234
+ //line go.y:2296
{
yyVAL.list = list1(yyDollar[1].node)
}
case 351:
yyDollar = yyS[yypt-3 : yypt+1]
- //line go.y:2238
+ //line go.y:2300
{
yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
}
diff --git a/src/cmd/internal/gc/y.output b/src/cmd/compile/internal/gc/y.output
index e4a5e5c212..2821702aea 100644
--- a/src/cmd/internal/gc/y.output
+++ b/src/cmd/compile/internal/gc/y.output
@@ -3,7 +3,7 @@ state 0
$accept: .file $end
$$4: . (4)
- . reduce 4 (src line 148)
+ . reduce 4 (src line 210)
file goto 1
loadsys goto 2
@@ -21,7 +21,7 @@ state 2
package: . (2)
LPACKAGE shift 5
- . reduce 2 (src line 131)
+ . reduce 2 (src line 193)
package goto 4
@@ -37,7 +37,7 @@ state 4
file: loadsys package.imports xdcl_list
imports: . (6)
- . reduce 6 (src line 165)
+ . reduce 6 (src line 227)
imports goto 8
@@ -56,7 +56,7 @@ state 6
loadsys: $$4 import_package.import_there
$$21: . (21)
- . reduce 21 (src line 272)
+ . reduce 21 (src line 334)
import_there goto 14
$$21 goto 15
@@ -74,7 +74,7 @@ state 8
xdcl_list: . (218)
LIMPORT shift 19
- . reduce 218 (src line 1507)
+ . reduce 218 (src line 1569)
xdcl_list goto 17
import goto 18
@@ -89,19 +89,19 @@ state 9
state 10
sym: LNAME. (157)
- . reduce 157 (src line 1113)
+ . reduce 157 (src line 1175)
state 11
sym: hidden_importsym. (158)
- . reduce 158 (src line 1122)
+ . reduce 158 (src line 1184)
state 12
sym: '?'. (159)
- . reduce 159 (src line 1123)
+ . reduce 159 (src line 1185)
state 13
@@ -115,14 +115,14 @@ state 13
state 14
loadsys: $$4 import_package import_there. (5)
- . reduce 5 (src line 159)
+ . reduce 5 (src line 221)
state 15
import_there: $$21.hidden_import_list '$' '$'
hidden_import_list: . (344)
- . reduce 344 (src line 2209)
+ . reduce 344 (src line 2271)
hidden_import_list goto 22
@@ -131,7 +131,7 @@ state 16
import_safety: . (19)
LNAME shift 24
- . reduce 19 (src line 264)
+ . reduce 19 (src line 326)
import_safety goto 23
@@ -140,7 +140,7 @@ state 17
xdcl_list: xdcl_list.xdcl ';'
xdcl: . (23)
- $end reduce 1 (src line 122)
+ $end reduce 1 (src line 184)
error shift 29
LLITERAL shift 68
LBREAK shift 41
@@ -170,7 +170,7 @@ state 17
'*' shift 58
'&' shift 59
'(' shift 67
- ';' reduce 23 (src line 285)
+ ';' reduce 23 (src line 347)
'!' shift 62
'~' shift 63
'[' shift 77
@@ -236,7 +236,7 @@ state 19
state 20
package: LPACKAGE sym ';'. (3)
- . reduce 3 (src line 138)
+ . reduce 3 (src line 200)
state 21
@@ -271,7 +271,7 @@ state 23
state 24
import_safety: LNAME. (20)
- . reduce 20 (src line 265)
+ . reduce 20 (src line 327)
state 25
@@ -284,25 +284,25 @@ state 25
state 26
xdcl: common_dcl. (24)
- . reduce 24 (src line 290)
+ . reduce 24 (src line 352)
state 27
xdcl: xfndcl. (25)
- . reduce 25 (src line 291)
+ . reduce 25 (src line 353)
state 28
xdcl: non_dcl_stmt. (26)
- . reduce 26 (src line 295)
+ . reduce 26 (src line 357)
state 29
xdcl: error. (27)
- . reduce 27 (src line 300)
+ . reduce 27 (src line 362)
state 30
@@ -373,31 +373,31 @@ state 33
state 34
non_dcl_stmt: simple_stmt. (256)
- . reduce 256 (src line 1734)
+ . reduce 256 (src line 1796)
state 35
non_dcl_stmt: for_stmt. (257)
- . reduce 257 (src line 1736)
+ . reduce 257 (src line 1798)
state 36
non_dcl_stmt: switch_stmt. (258)
- . reduce 258 (src line 1737)
+ . reduce 258 (src line 1799)
state 37
non_dcl_stmt: select_stmt. (259)
- . reduce 259 (src line 1738)
+ . reduce 259 (src line 1800)
state 38
non_dcl_stmt: if_stmt. (260)
- . reduce 260 (src line 1739)
+ . reduce 260 (src line 1801)
state 39
@@ -410,7 +410,7 @@ state 39
state 40
non_dcl_stmt: LFALL. (263)
- . reduce 263 (src line 1756)
+ . reduce 263 (src line 1818)
state 41
@@ -420,7 +420,7 @@ state 41
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 155 (src line 1107)
+ . reduce 155 (src line 1169)
sym goto 119
new_name goto 118
@@ -434,7 +434,7 @@ state 42
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 155 (src line 1107)
+ . reduce 155 (src line 1169)
sym goto 119
new_name goto 118
@@ -538,7 +538,7 @@ state 46
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 292 (src line 1905)
+ . reduce 292 (src line 1967)
sym goto 123
expr goto 129
@@ -562,7 +562,7 @@ state 46
state 47
lconst: LCONST. (38)
- . reduce 38 (src line 354)
+ . reduce 38 (src line 416)
state 48
@@ -593,7 +593,7 @@ state 48
expr_list: expr. (276)
LASOP shift 130
- LCOLAS reduce 276 (src line 1840)
+ LCOLAS reduce 276 (src line 1902)
LANDAND shift 134
LANDNOT shift 149
LCOMM shift 152
@@ -616,9 +616,9 @@ state 48
'/' shift 146
'%' shift 147
'&' shift 148
- '=' reduce 276 (src line 1840)
- ',' reduce 276 (src line 1840)
- . reduce 49 (src line 410)
+ '=' reduce 276 (src line 1902)
+ ',' reduce 276 (src line 1902)
+ . reduce 49 (src line 472)
state 49
@@ -636,7 +636,7 @@ state 50
for_stmt: LFOR.$$74 for_body
$$74: . (74)
- . reduce 74 (src line 659)
+ . reduce 74 (src line 721)
$$74 goto 156
@@ -644,7 +644,7 @@ state 51
switch_stmt: LSWITCH.$$88 if_header $$89 LBODY caseblock_list '}'
$$88: . (88)
- . reduce 88 (src line 754)
+ . reduce 88 (src line 816)
$$88 goto 157
@@ -652,7 +652,7 @@ state 52
select_stmt: LSELECT.$$91 LBODY caseblock_list '}'
$$91: . (91)
- . reduce 91 (src line 777)
+ . reduce 91 (src line 839)
$$91 goto 158
@@ -660,28 +660,28 @@ state 53
if_stmt: LIF.$$78 if_header $$79 loop_body $$80 elseif_list else
$$78: . (78)
- . reduce 78 (src line 688)
+ . reduce 78 (src line 750)
$$78 goto 159
state 54
labelname: new_name. (163)
- . reduce 163 (src line 1167)
+ . reduce 163 (src line 1229)
state 55
expr: uexpr. (93)
- . reduce 93 (src line 793)
+ . reduce 93 (src line 855)
state 56
new_name: sym. (153)
name: sym. (162)
- ':' reduce 153 (src line 1091)
- . reduce 162 (src line 1158)
+ ':' reduce 153 (src line 1153)
+ . reduce 162 (src line 1220)
state 57
@@ -699,7 +699,7 @@ state 57
'(' shift 160
'.' shift 161
'[' shift 162
- . reduce 114 (src line 877)
+ . reduce 114 (src line 939)
state 58
@@ -1027,7 +1027,7 @@ state 66
pexpr: pexpr_no_paren. (146)
'{' shift 171
- . reduce 146 (src line 1054)
+ . reduce 146 (src line 1116)
state 67
@@ -1078,19 +1078,19 @@ state 67
state 68
pexpr_no_paren: LLITERAL. (126)
- . reduce 126 (src line 941)
+ . reduce 126 (src line 1003)
state 69
pexpr_no_paren: name. (127)
- . reduce 127 (src line 946)
+ . reduce 127 (src line 1008)
state 70
pexpr_no_paren: pseudocall. (134)
- . reduce 134 (src line 984)
+ . reduce 134 (src line 1046)
state 71
@@ -1112,23 +1112,23 @@ state 72
state 73
pexpr_no_paren: fnliteral. (139)
- . reduce 139 (src line 1011)
+ . reduce 139 (src line 1073)
state 74
convtype: fntype. (181)
fnlitdcl: fntype. (215)
- '(' reduce 181 (src line 1220)
- . reduce 215 (src line 1484)
+ '(' reduce 181 (src line 1282)
+ . reduce 215 (src line 1546)
state 75
convtype: othertype. (182)
comptype: othertype. (183)
- '(' reduce 182 (src line 1222)
- . reduce 183 (src line 1224)
+ '(' reduce 182 (src line 1284)
+ . reduce 183 (src line 1286)
state 76
@@ -1167,7 +1167,7 @@ state 77
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 290 (src line 1899)
+ . reduce 290 (src line 1961)
sym goto 123
expr goto 188
@@ -1226,13 +1226,13 @@ state 79
state 80
othertype: structtype. (196)
- . reduce 196 (src line 1272)
+ . reduce 196 (src line 1334)
state 81
othertype: interfacetype. (197)
- . reduce 197 (src line 1273)
+ . reduce 197 (src line 1335)
state 82
@@ -1258,13 +1258,13 @@ state 83
state 84
imports: imports import ';'. (7)
- . reduce 7 (src line 166)
+ . reduce 7 (src line 228)
state 85
import: LIMPORT import_stmt. (8)
- . reduce 8 (src line 168)
+ . reduce 8 (src line 230)
state 86
@@ -1291,7 +1291,7 @@ state 87
$$21: . (21)
LPACKAGE shift 7
- . reduce 21 (src line 272)
+ . reduce 21 (src line 334)
import_package goto 204
import_there goto 205
@@ -1300,7 +1300,7 @@ state 87
state 88
import_here: LLITERAL. (15)
- . reduce 15 (src line 224)
+ . reduce 15 (src line 286)
state 89
@@ -1336,7 +1336,7 @@ state 92
state 93
hidden_import_list: hidden_import_list hidden_import. (345)
- . reduce 345 (src line 2210)
+ . reduce 345 (src line 2272)
state 94
@@ -1389,19 +1389,19 @@ state 98
state 99
import_package: LPACKAGE LNAME import_safety ';'. (18)
- . reduce 18 (src line 247)
+ . reduce 18 (src line 309)
state 100
xdcl_list: xdcl_list xdcl ';'. (219)
- . reduce 219 (src line 1511)
+ . reduce 219 (src line 1573)
state 101
common_dcl: LVAR vardcl. (28)
- . reduce 28 (src line 305)
+ . reduce 28 (src line 367)
state 102
@@ -1458,19 +1458,19 @@ state 103
state 104
dcl_name_list: dcl_name. (274)
- . reduce 274 (src line 1830)
+ . reduce 274 (src line 1892)
state 105
dcl_name: sym. (154)
- . reduce 154 (src line 1101)
+ . reduce 154 (src line 1163)
state 106
common_dcl: lconst constdcl. (31)
- . reduce 31 (src line 318)
+ . reduce 31 (src line 380)
state 107
@@ -1526,7 +1526,7 @@ state 108
state 109
common_dcl: LTYPE typedcl. (35)
- . reduce 35 (src line 341)
+ . reduce 35 (src line 403)
state 110
@@ -1577,7 +1577,7 @@ state 111
state 112
typedclname: sym. (47)
- . reduce 47 (src line 395)
+ . reduce 47 (src line 457)
state 113
@@ -1585,7 +1585,7 @@ state 113
fnbody: . (210)
'{' shift 242
- . reduce 210 (src line 1457)
+ . reduce 210 (src line 1519)
fnbody goto 241
@@ -1607,7 +1607,7 @@ state 114
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 249 (src line 1707)
+ . reduce 249 (src line 1769)
sym goto 247
ntype goto 249
@@ -1637,43 +1637,43 @@ state 116
non_dcl_stmt: labelname ':'.$$261 stmt
$$261: . (261)
- . reduce 261 (src line 1740)
+ . reduce 261 (src line 1802)
$$261 goto 252
state 117
non_dcl_stmt: LBREAK onew_name. (264)
- . reduce 264 (src line 1762)
+ . reduce 264 (src line 1824)
state 118
onew_name: new_name. (156)
- . reduce 156 (src line 1111)
+ . reduce 156 (src line 1173)
state 119
new_name: sym. (153)
- . reduce 153 (src line 1091)
+ . reduce 153 (src line 1153)
state 120
non_dcl_stmt: LCONTINUE onew_name. (265)
- . reduce 265 (src line 1766)
+ . reduce 265 (src line 1828)
state 121
pexpr_no_paren: pseudocall. (134)
non_dcl_stmt: LGO pseudocall. (266)
- '(' reduce 134 (src line 984)
- '.' reduce 134 (src line 984)
- '{' reduce 134 (src line 984)
- '[' reduce 134 (src line 984)
- . reduce 266 (src line 1770)
+ '(' reduce 134 (src line 1046)
+ '.' reduce 134 (src line 1046)
+ '{' reduce 134 (src line 1046)
+ '[' reduce 134 (src line 1046)
+ . reduce 266 (src line 1832)
state 122
@@ -1696,7 +1696,7 @@ state 122
state 123
name: sym. (162)
- . reduce 162 (src line 1158)
+ . reduce 162 (src line 1220)
state 124
@@ -1710,23 +1710,23 @@ state 125
pexpr_no_paren: pseudocall. (134)
non_dcl_stmt: LDEFER pseudocall. (267)
- '(' reduce 134 (src line 984)
- '.' reduce 134 (src line 984)
- '{' reduce 134 (src line 984)
- '[' reduce 134 (src line 984)
- . reduce 267 (src line 1774)
+ '(' reduce 134 (src line 1046)
+ '.' reduce 134 (src line 1046)
+ '{' reduce 134 (src line 1046)
+ '[' reduce 134 (src line 1046)
+ . reduce 267 (src line 1836)
state 126
non_dcl_stmt: LGOTO new_name. (268)
- . reduce 268 (src line 1778)
+ . reduce 268 (src line 1840)
state 127
non_dcl_stmt: LRETURN oexpr_list. (269)
- . reduce 269 (src line 1783)
+ . reduce 269 (src line 1845)
state 128
@@ -1734,7 +1734,7 @@ state 128
oexpr_list: expr_list. (293)
',' shift 155
- . reduce 293 (src line 1909)
+ . reduce 293 (src line 1971)
state 129
@@ -1780,7 +1780,7 @@ state 129
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 276 (src line 1840)
+ . reduce 276 (src line 1902)
state 130
@@ -1827,13 +1827,13 @@ state 130
state 131
simple_stmt: expr LINC. (53)
- . reduce 53 (src line 460)
+ . reduce 53 (src line 522)
state 132
simple_stmt: expr LDEC. (54)
- . reduce 54 (src line 466)
+ . reduce 54 (src line 528)
state 133
@@ -2805,7 +2805,7 @@ state 156
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 294 (src line 1911)
+ . reduce 294 (src line 1973)
sym goto 123
expr goto 48
@@ -2853,7 +2853,7 @@ state 157
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 294 (src line 1911)
+ . reduce 294 (src line 1973)
sym goto 123
expr goto 48
@@ -2906,7 +2906,7 @@ state 159
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 294 (src line 1911)
+ . reduce 294 (src line 1973)
sym goto 123
expr goto 48
@@ -3016,7 +3016,7 @@ state 162
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 290 (src line 1899)
+ . reduce 290 (src line 1961)
sym goto 123
expr goto 294
@@ -3039,56 +3039,56 @@ state 162
state 163
uexpr: '*' uexpr. (115)
- . reduce 115 (src line 879)
+ . reduce 115 (src line 941)
state 164
uexpr: '&' uexpr. (116)
- . reduce 116 (src line 883)
+ . reduce 116 (src line 945)
state 165
uexpr: '+' uexpr. (117)
- . reduce 117 (src line 894)
+ . reduce 117 (src line 956)
state 166
uexpr: '-' uexpr. (118)
- . reduce 118 (src line 898)
+ . reduce 118 (src line 960)
state 167
uexpr: '!' uexpr. (119)
- . reduce 119 (src line 902)
+ . reduce 119 (src line 964)
state 168
uexpr: '~' uexpr. (120)
- . reduce 120 (src line 906)
+ . reduce 120 (src line 968)
state 169
uexpr: '^' uexpr. (121)
- . reduce 121 (src line 911)
+ . reduce 121 (src line 973)
state 170
uexpr: LCOMM uexpr. (122)
- . reduce 122 (src line 915)
+ . reduce 122 (src line 977)
state 171
pexpr_no_paren: pexpr_no_paren '{'.start_complit braced_keyval_list '}'
start_complit: . (140)
- . reduce 140 (src line 1013)
+ . reduce 140 (src line 1075)
start_complit goto 296
@@ -3143,19 +3143,19 @@ state 173
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 148 (src line 1069)
+ . reduce 148 (src line 1131)
state 174
expr_or_type: non_expr_type. (149)
- . reduce 149 (src line 1071)
+ . reduce 149 (src line 1133)
state 175
non_expr_type: recvchantype. (172)
- . reduce 172 (src line 1201)
+ . reduce 172 (src line 1263)
state 176
@@ -3163,11 +3163,11 @@ state 176
convtype: fntype. (181)
fnlitdcl: fntype. (215)
- error reduce 215 (src line 1484)
- LBODY reduce 215 (src line 1484)
- '(' reduce 181 (src line 1220)
- '{' reduce 215 (src line 1484)
- . reduce 173 (src line 1203)
+ error reduce 215 (src line 1546)
+ LBODY reduce 215 (src line 1546)
+ '(' reduce 181 (src line 1282)
+ '{' reduce 215 (src line 1546)
+ . reduce 173 (src line 1265)
state 177
@@ -3175,10 +3175,10 @@ state 177
convtype: othertype. (182)
comptype: othertype. (183)
- LBODY reduce 183 (src line 1224)
- '(' reduce 182 (src line 1222)
- '{' reduce 183 (src line 1224)
- . reduce 174 (src line 1204)
+ LBODY reduce 183 (src line 1286)
+ '(' reduce 182 (src line 1284)
+ '{' reduce 183 (src line 1286)
+ . reduce 174 (src line 1266)
state 178
@@ -3310,20 +3310,20 @@ state 181
pexpr_no_paren: comptype lbrace.start_complit braced_keyval_list '}'
start_complit: . (140)
- . reduce 140 (src line 1013)
+ . reduce 140 (src line 1075)
start_complit goto 301
state 182
lbrace: LBODY. (151)
- . reduce 151 (src line 1076)
+ . reduce 151 (src line 1138)
state 183
lbrace: '{'. (152)
- . reduce 152 (src line 1081)
+ . reduce 152 (src line 1143)
state 184
@@ -3359,9 +3359,9 @@ state 184
'*' shift 58
'&' shift 59
'(' shift 67
- ';' reduce 251 (src line 1719)
+ ';' reduce 251 (src line 1781)
'{' shift 308
- '}' reduce 251 (src line 1719)
+ '}' reduce 251 (src line 1781)
'!' shift 62
'~' shift 63
'[' shift 77
@@ -3403,7 +3403,7 @@ state 184
state 185
fnliteral: fnlitdcl error. (217)
- . reduce 217 (src line 1496)
+ . reduce 217 (src line 1558)
state 186
@@ -3463,13 +3463,13 @@ state 188
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 291 (src line 1903)
+ . reduce 291 (src line 1965)
state 189
othertype: LCHAN non_recvchantype. (193)
- . reduce 193 (src line 1258)
+ . reduce 193 (src line 1320)
state 190
@@ -3504,25 +3504,25 @@ state 190
state 191
non_recvchantype: fntype. (176)
- . reduce 176 (src line 1210)
+ . reduce 176 (src line 1272)
state 192
non_recvchantype: othertype. (177)
- . reduce 177 (src line 1212)
+ . reduce 177 (src line 1274)
state 193
non_recvchantype: ptrtype. (178)
- . reduce 178 (src line 1213)
+ . reduce 178 (src line 1275)
state 194
non_recvchantype: dotname. (179)
- . reduce 179 (src line 1214)
+ . reduce 179 (src line 1276)
state 195
@@ -3588,7 +3588,7 @@ state 197
dotname: name.'.' sym
'.' shift 314
- . reduce 189 (src line 1234)
+ . reduce 189 (src line 1296)
state 198
@@ -3665,27 +3665,27 @@ state 201
osemi: . (286)
';' shift 333
- . reduce 286 (src line 1893)
+ . reduce 286 (src line 1955)
osemi goto 332
state 202
import: LIMPORT '(' ')'. (10)
- . reduce 10 (src line 171)
+ . reduce 10 (src line 233)
state 203
import_stmt_list: import_stmt. (13)
- . reduce 13 (src line 220)
+ . reduce 13 (src line 282)
state 204
import_stmt: import_here import_package.import_there
$$21: . (21)
- . reduce 21 (src line 272)
+ . reduce 21 (src line 334)
import_there goto 334
$$21 goto 15
@@ -3693,37 +3693,37 @@ state 204
state 205
import_stmt: import_here import_there. (12)
- . reduce 12 (src line 209)
+ . reduce 12 (src line 271)
state 206
import_here: sym LLITERAL. (16)
- . reduce 16 (src line 232)
+ . reduce 16 (src line 294)
state 207
import_here: '.' LLITERAL. (17)
- . reduce 17 (src line 239)
+ . reduce 17 (src line 301)
state 208
hidden_importsym: '@' LLITERAL '.' LNAME. (160)
- . reduce 160 (src line 1128)
+ . reduce 160 (src line 1190)
state 209
hidden_importsym: '@' LLITERAL '.' '?'. (161)
- . reduce 161 (src line 1143)
+ . reduce 161 (src line 1205)
state 210
import_there: $$21 hidden_import_list '$' '$'. (22)
- . reduce 22 (src line 276)
+ . reduce 22 (src line 338)
state 211
@@ -3757,7 +3757,7 @@ state 212
state 213
hidden_pkg_importsym: hidden_importsym. (310)
- . reduce 310 (src line 1985)
+ . reduce 310 (src line 2047)
state 214
@@ -3807,7 +3807,7 @@ state 215
state 216
hidden_pkgtype: hidden_pkg_importsym. (311)
- . reduce 311 (src line 1992)
+ . reduce 311 (src line 2054)
state 217
@@ -3815,7 +3815,7 @@ state 217
fnbody: . (210)
'{' shift 242
- . reduce 210 (src line 1457)
+ . reduce 210 (src line 1519)
fnbody goto 353
@@ -3845,20 +3845,20 @@ state 220
osemi: . (286)
';' shift 359
- . reduce 286 (src line 1893)
+ . reduce 286 (src line 1955)
osemi goto 358
state 221
common_dcl: LVAR '(' ')'. (30)
- . reduce 30 (src line 314)
+ . reduce 30 (src line 376)
state 222
vardcl_list: vardcl. (220)
- . reduce 220 (src line 1523)
+ . reduce 220 (src line 1585)
state 223
@@ -3866,7 +3866,7 @@ state 223
vardcl: dcl_name_list ntype.'=' expr_list
'=' shift 360
- . reduce 39 (src line 360)
+ . reduce 39 (src line 422)
state 224
@@ -3926,31 +3926,31 @@ state 225
state 226
ntype: recvchantype. (166)
- . reduce 166 (src line 1190)
+ . reduce 166 (src line 1252)
state 227
ntype: fntype. (167)
- . reduce 167 (src line 1192)
+ . reduce 167 (src line 1254)
state 228
ntype: othertype. (168)
- . reduce 168 (src line 1193)
+ . reduce 168 (src line 1255)
state 229
ntype: ptrtype. (169)
- . reduce 169 (src line 1194)
+ . reduce 169 (src line 1256)
state 230
ntype: dotname. (170)
- . reduce 170 (src line 1195)
+ . reduce 170 (src line 1257)
state 231
@@ -3995,14 +3995,14 @@ state 233
osemi: . (286)
';' shift 366
- . reduce 286 (src line 1893)
+ . reduce 286 (src line 1955)
osemi goto 365
state 234
common_dcl: lconst '(' ')'. (34)
- . reduce 34 (src line 336)
+ . reduce 34 (src line 398)
state 235
@@ -4060,32 +4060,32 @@ state 237
osemi: . (286)
';' shift 370
- . reduce 286 (src line 1893)
+ . reduce 286 (src line 1955)
osemi goto 369
state 238
common_dcl: LTYPE '(' ')'. (37)
- . reduce 37 (src line 349)
+ . reduce 37 (src line 411)
state 239
typedcl_list: typedcl. (224)
- . reduce 224 (src line 1537)
+ . reduce 224 (src line 1599)
state 240
typedcl: typedclname ntype. (48)
- . reduce 48 (src line 404)
+ . reduce 48 (src line 466)
state 241
xfndcl: LFUNC fndcl fnbody. (204)
- . reduce 204 (src line 1318)
+ . reduce 204 (src line 1380)
state 242
@@ -4121,9 +4121,9 @@ state 242
'*' shift 58
'&' shift 59
'(' shift 67
- ';' reduce 251 (src line 1719)
+ ';' reduce 251 (src line 1781)
'{' shift 308
- '}' reduce 251 (src line 1719)
+ '}' reduce 251 (src line 1781)
'!' shift 62
'~' shift 63
'[' shift 77
@@ -4176,20 +4176,20 @@ state 244
ocomma: . (288)
',' shift 373
- . reduce 288 (src line 1896)
+ . reduce 288 (src line 1958)
ocomma goto 374
state 245
arg_type_list: arg_type. (247)
- . reduce 247 (src line 1697)
+ . reduce 247 (src line 1759)
state 246
arg_type: name_or_type. (243)
- . reduce 243 (src line 1681)
+ . reduce 243 (src line 1743)
state 247
@@ -4210,7 +4210,7 @@ state 247
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 162 (src line 1158)
+ . reduce 162 (src line 1220)
sym goto 123
ntype goto 249
@@ -4229,13 +4229,13 @@ state 247
state 248
arg_type: dotdotdot. (246)
- . reduce 246 (src line 1695)
+ . reduce 246 (src line 1757)
state 249
name_or_type: ntype. (150)
- . reduce 150 (src line 1073)
+ . reduce 150 (src line 1135)
state 250
@@ -4254,7 +4254,7 @@ state 250
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 164 (src line 1179)
+ . reduce 164 (src line 1241)
sym goto 123
ntype goto 377
@@ -4285,7 +4285,7 @@ state 251
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 249 (src line 1707)
+ . reduce 249 (src line 1769)
sym goto 247
ntype goto 249
@@ -4311,11 +4311,11 @@ state 252
error shift 307
LLITERAL shift 68
LBREAK shift 41
- LCASE reduce 251 (src line 1719)
+ LCASE reduce 251 (src line 1781)
LCHAN shift 78
LCONST shift 47
LCONTINUE shift 42
- LDEFAULT reduce 251 (src line 1719)
+ LDEFAULT reduce 251 (src line 1781)
LDEFER shift 44
LFALL shift 40
LFOR shift 50
@@ -4339,9 +4339,9 @@ state 252
'*' shift 58
'&' shift 59
'(' shift 67
- ';' reduce 251 (src line 1719)
+ ';' reduce 251 (src line 1781)
'{' shift 308
- '}' reduce 251 (src line 1719)
+ '}' reduce 251 (src line 1781)
'!' shift 62
'~' shift 63
'[' shift 77
@@ -4396,7 +4396,7 @@ state 253
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 249 (src line 1707)
+ . reduce 249 (src line 1769)
sym goto 247
ntype goto 249
@@ -4458,7 +4458,7 @@ state 254
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 50 (src line 425)
+ . reduce 50 (src line 487)
state 255
@@ -4502,7 +4502,7 @@ state 255
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 94 (src line 795)
+ . reduce 94 (src line 857)
state 256
@@ -4545,7 +4545,7 @@ state 256
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 95 (src line 799)
+ . reduce 95 (src line 861)
state 257
@@ -4582,7 +4582,7 @@ state 257
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 96 (src line 803)
+ . reduce 96 (src line 865)
state 258
@@ -4619,7 +4619,7 @@ state 258
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 97 (src line 807)
+ . reduce 97 (src line 869)
state 259
@@ -4656,7 +4656,7 @@ state 259
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 98 (src line 811)
+ . reduce 98 (src line 873)
state 260
@@ -4693,7 +4693,7 @@ state 260
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 99 (src line 815)
+ . reduce 99 (src line 877)
state 261
@@ -4730,7 +4730,7 @@ state 261
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 100 (src line 819)
+ . reduce 100 (src line 881)
state 262
@@ -4767,7 +4767,7 @@ state 262
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 101 (src line 823)
+ . reduce 101 (src line 885)
state 263
@@ -4800,7 +4800,7 @@ state 263
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 102 (src line 827)
+ . reduce 102 (src line 889)
state 264
@@ -4833,7 +4833,7 @@ state 264
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 103 (src line 831)
+ . reduce 103 (src line 893)
state 265
@@ -4866,7 +4866,7 @@ state 265
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 104 (src line 835)
+ . reduce 104 (src line 897)
state 266
@@ -4899,7 +4899,7 @@ state 266
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 105 (src line 839)
+ . reduce 105 (src line 901)
state 267
@@ -4925,7 +4925,7 @@ state 267
expr: expr.LRSH expr
expr: expr.LCOMM expr
- . reduce 106 (src line 843)
+ . reduce 106 (src line 905)
state 268
@@ -4951,7 +4951,7 @@ state 268
expr: expr.LRSH expr
expr: expr.LCOMM expr
- . reduce 107 (src line 847)
+ . reduce 107 (src line 909)
state 269
@@ -4977,7 +4977,7 @@ state 269
expr: expr.LRSH expr
expr: expr.LCOMM expr
- . reduce 108 (src line 851)
+ . reduce 108 (src line 913)
state 270
@@ -5003,7 +5003,7 @@ state 270
expr: expr.LRSH expr
expr: expr.LCOMM expr
- . reduce 109 (src line 855)
+ . reduce 109 (src line 917)
state 271
@@ -5029,7 +5029,7 @@ state 271
expr: expr.LRSH expr
expr: expr.LCOMM expr
- . reduce 110 (src line 859)
+ . reduce 110 (src line 921)
state 272
@@ -5055,7 +5055,7 @@ state 272
expr: expr.LRSH expr
expr: expr.LCOMM expr
- . reduce 111 (src line 863)
+ . reduce 111 (src line 925)
state 273
@@ -5081,7 +5081,7 @@ state 273
expr: expr LRSH expr. (112)
expr: expr.LCOMM expr
- . reduce 112 (src line 867)
+ . reduce 112 (src line 929)
state 274
@@ -5126,7 +5126,7 @@ state 274
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 113 (src line 872)
+ . reduce 113 (src line 934)
state 275
@@ -5134,7 +5134,7 @@ state 275
expr_list: expr_list.',' expr
',' shift 155
- . reduce 51 (src line 430)
+ . reduce 51 (src line 492)
state 276
@@ -5142,7 +5142,7 @@ state 276
expr_list: expr_list.',' expr
',' shift 155
- . reduce 52 (src line 442)
+ . reduce 52 (src line 504)
state 277
@@ -5188,13 +5188,13 @@ state 277
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 277 (src line 1845)
+ . reduce 277 (src line 1907)
state 278
for_stmt: LFOR $$74 for_body. (75)
- . reduce 75 (src line 664)
+ . reduce 75 (src line 726)
state 279
@@ -5210,19 +5210,19 @@ state 280
for_header: osimple_stmt. (71)
';' shift 383
- . reduce 71 (src line 644)
+ . reduce 71 (src line 706)
state 281
for_header: range_stmt. (72)
- . reduce 72 (src line 650)
+ . reduce 72 (src line 712)
state 282
osimple_stmt: simple_stmt. (295)
- . reduce 295 (src line 1915)
+ . reduce 295 (src line 1977)
state 283
@@ -5283,7 +5283,7 @@ state 285
switch_stmt: LSWITCH $$88 if_header.$$89 LBODY caseblock_list '}'
$$89: . (89)
- . reduce 89 (src line 759)
+ . reduce 89 (src line 821)
$$89 goto 387
@@ -5292,14 +5292,14 @@ state 286
if_header: osimple_stmt.';' osimple_stmt
';' shift 388
- . reduce 76 (src line 670)
+ . reduce 76 (src line 732)
state 287
select_stmt: LSELECT $$91 LBODY.caseblock_list '}'
caseblock_list: . (63)
- . reduce 63 (src line 590)
+ . reduce 63 (src line 652)
caseblock_list goto 389
@@ -5307,14 +5307,14 @@ state 288
if_stmt: LIF $$78 if_header.$$79 loop_body $$80 elseif_list else
$$79: . (79)
- . reduce 79 (src line 693)
+ . reduce 79 (src line 755)
$$79 goto 390
state 289
pseudocall: pexpr '(' ')'. (123)
- . reduce 123 (src line 924)
+ . reduce 123 (src line 986)
state 290
@@ -5325,20 +5325,20 @@ state 290
LDDD shift 392
',' shift 393
- . reduce 288 (src line 1896)
+ . reduce 288 (src line 1958)
ocomma goto 391
state 291
expr_or_type_list: expr_or_type. (278)
- . reduce 278 (src line 1850)
+ . reduce 278 (src line 1912)
state 292
pexpr_no_paren: pexpr '.' sym. (128)
- . reduce 128 (src line 947)
+ . reduce 128 (src line 1009)
state 293
@@ -5432,7 +5432,7 @@ state 294
'%' shift 147
'&' shift 148
']' shift 396
- . reduce 291 (src line 1903)
+ . reduce 291 (src line 1965)
state 295
@@ -5467,7 +5467,7 @@ state 296
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 284 (src line 1881)
+ . reduce 284 (src line 1943)
sym goto 123
expr goto 402
@@ -5495,13 +5495,13 @@ state 297
pexpr: '(' expr_or_type ')'. (147)
'{' shift 404
- . reduce 147 (src line 1056)
+ . reduce 147 (src line 1118)
state 298
non_expr_type: '*' non_expr_type. (175)
- . reduce 175 (src line 1205)
+ . reduce 175 (src line 1267)
state 299
@@ -5581,7 +5581,7 @@ state 300
'%' shift 147
'&' shift 148
',' shift 413
- . reduce 288 (src line 1896)
+ . reduce 288 (src line 1958)
ocomma goto 412
@@ -5609,7 +5609,7 @@ state 301
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 284 (src line 1881)
+ . reduce 284 (src line 1943)
sym goto 123
expr goto 402
@@ -5644,38 +5644,38 @@ state 302
state 303
stmt_list: stmt. (270)
- . reduce 270 (src line 1804)
+ . reduce 270 (src line 1866)
state 304
stmt: compound_stmt. (252)
- . reduce 252 (src line 1723)
+ . reduce 252 (src line 1785)
state 305
stmt: common_dcl. (253)
- . reduce 253 (src line 1724)
+ . reduce 253 (src line 1786)
state 306
stmt: non_dcl_stmt. (254)
- . reduce 254 (src line 1728)
+ . reduce 254 (src line 1790)
state 307
stmt: error. (255)
- . reduce 255 (src line 1729)
+ . reduce 255 (src line 1791)
state 308
compound_stmt: '{'.$$59 stmt_list '}'
$$59: . (59)
- . reduce 59 (src line 544)
+ . reduce 59 (src line 606)
$$59 goto 417
@@ -5740,7 +5740,7 @@ state 310
state 311
othertype: LCHAN LCOMM ntype. (194)
- . reduce 194 (src line 1263)
+ . reduce 194 (src line 1325)
state 312
@@ -5753,7 +5753,7 @@ state 312
state 313
ptrtype: '*' ntype. (198)
- . reduce 198 (src line 1275)
+ . reduce 198 (src line 1337)
state 314
@@ -5780,20 +5780,20 @@ state 316
osemi: . (286)
';' shift 424
- . reduce 286 (src line 1893)
+ . reduce 286 (src line 1955)
osemi goto 423
state 317
structtype: LSTRUCT lbrace '}'. (201)
- . reduce 201 (src line 1295)
+ . reduce 201 (src line 1357)
state 318
structdcl_list: structdcl. (226)
- . reduce 226 (src line 1547)
+ . reduce 226 (src line 1609)
state 319
@@ -5832,7 +5832,7 @@ state 320
oliteral: . (302)
LLITERAL shift 428
- . reduce 302 (src line 1935)
+ . reduce 302 (src line 1997)
oliteral goto 427
@@ -5861,13 +5861,13 @@ state 322
state 323
new_name_list: new_name. (272)
- . reduce 272 (src line 1820)
+ . reduce 272 (src line 1882)
state 324
embed: packname. (238)
- . reduce 238 (src line 1646)
+ . reduce 238 (src line 1708)
state 325
@@ -5875,11 +5875,11 @@ state 325
packname: LNAME. (236)
packname: LNAME.'.' sym
- LLITERAL reduce 236 (src line 1621)
- ';' reduce 236 (src line 1621)
+ LLITERAL reduce 236 (src line 1683)
+ ';' reduce 236 (src line 1683)
'.' shift 434
- '}' reduce 236 (src line 1621)
- . reduce 157 (src line 1113)
+ '}' reduce 236 (src line 1683)
+ . reduce 157 (src line 1175)
state 326
@@ -5888,20 +5888,20 @@ state 326
osemi: . (286)
';' shift 436
- . reduce 286 (src line 1893)
+ . reduce 286 (src line 1955)
osemi goto 435
state 327
interfacetype: LINTERFACE lbrace '}'. (203)
- . reduce 203 (src line 1308)
+ . reduce 203 (src line 1370)
state 328
interfacedcl_list: interfacedcl. (228)
- . reduce 228 (src line 1554)
+ . reduce 228 (src line 1616)
state 329
@@ -5915,7 +5915,7 @@ state 329
state 330
interfacedcl: packname. (240)
- . reduce 240 (src line 1658)
+ . reduce 240 (src line 1720)
state 331
@@ -5942,7 +5942,7 @@ state 333
'.' shift 90
'?' shift 12
'@' shift 13
- . reduce 287 (src line 1894)
+ . reduce 287 (src line 1956)
import_here goto 87
sym goto 89
@@ -5952,7 +5952,7 @@ state 333
state 334
import_stmt: import_here import_package import_there. (11)
- . reduce 11 (src line 173)
+ . reduce 11 (src line 235)
state 335
@@ -5972,31 +5972,31 @@ state 336
state 337
hidden_type: hidden_type_misc. (312)
- . reduce 312 (src line 2003)
+ . reduce 312 (src line 2065)
state 338
hidden_type: hidden_type_recv_chan. (313)
- . reduce 313 (src line 2005)
+ . reduce 313 (src line 2067)
state 339
hidden_type: hidden_type_func. (314)
- . reduce 314 (src line 2006)
+ . reduce 314 (src line 2068)
state 340
hidden_type_misc: hidden_importsym. (317)
- . reduce 317 (src line 2012)
+ . reduce 317 (src line 2074)
state 341
hidden_type_misc: LNAME. (318)
- . reduce 318 (src line 2017)
+ . reduce 318 (src line 2079)
state 342
@@ -6131,7 +6131,7 @@ state 354
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 296 (src line 1917)
+ . reduce 296 (src line 1979)
sym goto 357
hidden_importsym goto 11
@@ -6151,7 +6151,7 @@ state 355
state 356
hidden_funarg_list: hidden_funarg. (346)
- . reduce 346 (src line 2212)
+ . reduce 346 (src line 2274)
state 357
@@ -6191,7 +6191,7 @@ state 359
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 287 (src line 1894)
+ . reduce 287 (src line 1956)
sym goto 105
dcl_name goto 104
@@ -6246,13 +6246,13 @@ state 361
expr_list: expr_list.',' expr
',' shift 155
- . reduce 41 (src line 369)
+ . reduce 41 (src line 431)
state 362
dcl_name_list: dcl_name_list ',' dcl_name. (275)
- . reduce 275 (src line 1835)
+ . reduce 275 (src line 1897)
state 363
@@ -6305,7 +6305,7 @@ state 366
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 287 (src line 1894)
+ . reduce 287 (src line 1956)
sym goto 105
dcl_name goto 104
@@ -6362,7 +6362,7 @@ state 368
expr_list: expr_list.',' expr
',' shift 155
- . reduce 43 (src line 379)
+ . reduce 43 (src line 441)
state 369
@@ -6379,7 +6379,7 @@ state 370
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 287 (src line 1894)
+ . reduce 287 (src line 1956)
sym goto 112
typedclname goto 111
@@ -6412,7 +6412,7 @@ state 372
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 212 (src line 1469)
+ . reduce 212 (src line 1531)
sym goto 485
dotname goto 493
@@ -6444,7 +6444,7 @@ state 373
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 289 (src line 1897)
+ . reduce 289 (src line 1959)
sym goto 247
ntype goto 249
@@ -6464,25 +6464,25 @@ state 373
state 374
oarg_type_list_ocomma: arg_type_list ocomma. (250)
- . reduce 250 (src line 1711)
+ . reduce 250 (src line 1773)
state 375
arg_type: sym name_or_type. (244)
- . reduce 244 (src line 1683)
+ . reduce 244 (src line 1745)
state 376
arg_type: sym dotdotdot. (245)
- . reduce 245 (src line 1689)
+ . reduce 245 (src line 1751)
state 377
dotdotdot: LDDD ntype. (165)
- . reduce 165 (src line 1185)
+ . reduce 165 (src line 1247)
state 378
@@ -6495,7 +6495,7 @@ state 378
state 379
non_dcl_stmt: labelname ':' $$261 stmt. (262)
- . reduce 262 (src line 1745)
+ . reduce 262 (src line 1807)
state 380
@@ -6508,14 +6508,14 @@ state 380
state 381
for_body: for_header loop_body. (73)
- . reduce 73 (src line 652)
+ . reduce 73 (src line 714)
state 382
loop_body: LBODY.$$65 stmt_list '}'
$$65: . (65)
- . reduce 65 (src line 599)
+ . reduce 65 (src line 661)
$$65 goto 497
@@ -6542,7 +6542,7 @@ state 383
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 294 (src line 1911)
+ . reduce 294 (src line 1973)
sym goto 123
expr goto 48
@@ -6695,7 +6695,7 @@ state 386
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 69 (src line 624)
+ . reduce 69 (src line 686)
state 387
@@ -6728,7 +6728,7 @@ state 388
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 294 (src line 1911)
+ . reduce 294 (src line 1973)
sym goto 123
expr goto 48
@@ -6782,7 +6782,7 @@ state 392
ocomma: . (288)
',' shift 413
- . reduce 288 (src line 1896)
+ . reduce 288 (src line 1958)
ocomma goto 510
@@ -6809,7 +6809,7 @@ state 393
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 289 (src line 1897)
+ . reduce 289 (src line 1959)
sym goto 123
expr goto 173
@@ -6848,7 +6848,7 @@ state 395
state 396
pexpr_no_paren: pexpr '[' expr ']'. (131)
- . reduce 131 (src line 966)
+ . reduce 131 (src line 1028)
state 397
@@ -6875,7 +6875,7 @@ state 397
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 290 (src line 1899)
+ . reduce 290 (src line 1961)
sym goto 123
expr goto 188
@@ -6909,20 +6909,20 @@ state 399
ocomma: . (288)
',' shift 516
- . reduce 288 (src line 1896)
+ . reduce 288 (src line 1958)
ocomma goto 517
state 400
keyval_list: keyval. (280)
- . reduce 280 (src line 1863)
+ . reduce 280 (src line 1925)
state 401
keyval_list: bare_complitexpr. (281)
- . reduce 281 (src line 1868)
+ . reduce 281 (src line 1930)
state 402
@@ -6970,14 +6970,14 @@ state 402
'%' shift 147
'&' shift 148
':' shift 518
- . reduce 142 (src line 1026)
+ . reduce 142 (src line 1088)
state 403
bare_complitexpr: '{'.start_complit braced_keyval_list '}'
start_complit: . (140)
- . reduce 140 (src line 1013)
+ . reduce 140 (src line 1075)
start_complit goto 519
@@ -6985,7 +6985,7 @@ state 404
pexpr_no_paren: '(' expr_or_type ')' '{'.start_complit braced_keyval_list '}'
start_complit: . (140)
- . reduce 140 (src line 1013)
+ . reduce 140 (src line 1075)
start_complit goto 520
@@ -7022,47 +7022,47 @@ state 405
state 406
recvchantype: LCOMM LCHAN ntype. (199)
- . reduce 199 (src line 1281)
+ . reduce 199 (src line 1343)
state 407
ntype: fntype. (167)
non_recvchantype: fntype. (176)
- LBODY reduce 176 (src line 1210)
- '(' reduce 176 (src line 1210)
- '{' reduce 176 (src line 1210)
- . reduce 167 (src line 1192)
+ LBODY reduce 176 (src line 1272)
+ '(' reduce 176 (src line 1272)
+ '{' reduce 176 (src line 1272)
+ . reduce 167 (src line 1254)
state 408
ntype: othertype. (168)
non_recvchantype: othertype. (177)
- LBODY reduce 177 (src line 1212)
- '(' reduce 177 (src line 1212)
- '{' reduce 177 (src line 1212)
- . reduce 168 (src line 1193)
+ LBODY reduce 177 (src line 1274)
+ '(' reduce 177 (src line 1274)
+ '{' reduce 177 (src line 1274)
+ . reduce 168 (src line 1255)
state 409
ntype: ptrtype. (169)
non_recvchantype: ptrtype. (178)
- LBODY reduce 178 (src line 1213)
- '(' reduce 178 (src line 1213)
- '{' reduce 178 (src line 1213)
- . reduce 169 (src line 1194)
+ LBODY reduce 178 (src line 1275)
+ '(' reduce 178 (src line 1275)
+ '{' reduce 178 (src line 1275)
+ . reduce 169 (src line 1256)
state 410
ntype: dotname. (170)
non_recvchantype: dotname. (179)
- LBODY reduce 179 (src line 1214)
- '(' reduce 179 (src line 1214)
- '{' reduce 179 (src line 1214)
- . reduce 170 (src line 1195)
+ LBODY reduce 179 (src line 1276)
+ '(' reduce 179 (src line 1276)
+ '{' reduce 179 (src line 1276)
+ . reduce 170 (src line 1257)
state 411
@@ -7105,7 +7105,7 @@ state 412
state 413
ocomma: ','. (289)
- . reduce 289 (src line 1897)
+ . reduce 289 (src line 1959)
state 414
@@ -7118,7 +7118,7 @@ state 414
state 415
fnliteral: fnlitdcl lbrace stmt_list '}'. (216)
- . reduce 216 (src line 1490)
+ . reduce 216 (src line 1552)
state 416
@@ -7128,11 +7128,11 @@ state 416
error shift 307
LLITERAL shift 68
LBREAK shift 41
- LCASE reduce 251 (src line 1719)
+ LCASE reduce 251 (src line 1781)
LCHAN shift 78
LCONST shift 47
LCONTINUE shift 42
- LDEFAULT reduce 251 (src line 1719)
+ LDEFAULT reduce 251 (src line 1781)
LDEFER shift 44
LFALL shift 40
LFOR shift 50
@@ -7156,9 +7156,9 @@ state 416
'*' shift 58
'&' shift 59
'(' shift 67
- ';' reduce 251 (src line 1719)
+ ';' reduce 251 (src line 1781)
'{' shift 308
- '}' reduce 251 (src line 1719)
+ '}' reduce 251 (src line 1781)
'!' shift 62
'~' shift 63
'[' shift 77
@@ -7229,9 +7229,9 @@ state 417
'*' shift 58
'&' shift 59
'(' shift 67
- ';' reduce 251 (src line 1719)
+ ';' reduce 251 (src line 1781)
'{' shift 308
- '}' reduce 251 (src line 1719)
+ '}' reduce 251 (src line 1781)
'!' shift 62
'~' shift 63
'[' shift 77
@@ -7273,25 +7273,25 @@ state 417
state 418
othertype: '[' oexpr ']' ntype. (191)
- . reduce 191 (src line 1248)
+ . reduce 191 (src line 1310)
state 419
othertype: '[' LDDD ']' ntype. (192)
- . reduce 192 (src line 1253)
+ . reduce 192 (src line 1315)
state 420
non_recvchantype: '(' ntype ')'. (180)
- . reduce 180 (src line 1215)
+ . reduce 180 (src line 1277)
state 421
dotname: name '.' sym. (190)
- . reduce 190 (src line 1236)
+ . reduce 190 (src line 1298)
state 422
@@ -7339,7 +7339,7 @@ state 424
'(' shift 321
'?' shift 12
'@' shift 13
- . reduce 287 (src line 1894)
+ . reduce 287 (src line 1956)
sym goto 119
packname goto 324
@@ -7354,7 +7354,7 @@ state 425
oliteral: . (302)
LLITERAL shift 428
- . reduce 302 (src line 1935)
+ . reduce 302 (src line 1997)
oliteral goto 529
@@ -7373,13 +7373,13 @@ state 426
state 427
structdcl: embed oliteral. (231)
- . reduce 231 (src line 1589)
+ . reduce 231 (src line 1651)
state 428
oliteral: LLITERAL. (303)
- . reduce 303 (src line 1939)
+ . reduce 303 (src line 2001)
state 429
@@ -7403,7 +7403,7 @@ state 431
packname: LNAME.'.' sym
'.' shift 434
- . reduce 236 (src line 1621)
+ . reduce 236 (src line 1683)
state 432
@@ -7411,7 +7411,7 @@ state 432
oliteral: . (302)
LLITERAL shift 428
- . reduce 302 (src line 1935)
+ . reduce 302 (src line 1997)
oliteral goto 533
@@ -7450,7 +7450,7 @@ state 436
'(' shift 331
'?' shift 12
'@' shift 13
- . reduce 287 (src line 1894)
+ . reduce 287 (src line 1956)
sym goto 119
packname goto 330
@@ -7461,7 +7461,7 @@ state 436
state 437
interfacedcl: new_name indcl. (239)
- . reduce 239 (src line 1652)
+ . reduce 239 (src line 1714)
state 438
@@ -7481,7 +7481,7 @@ state 438
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 249 (src line 1707)
+ . reduce 249 (src line 1769)
sym goto 247
ntype goto 249
@@ -7510,25 +7510,25 @@ state 439
state 440
import: LIMPORT '(' import_stmt_list osemi ')'. (9)
- . reduce 9 (src line 170)
+ . reduce 9 (src line 232)
state 441
import_stmt_list: import_stmt_list ';' import_stmt. (14)
- . reduce 14 (src line 222)
+ . reduce 14 (src line 284)
state 442
hidden_import: LIMPORT LNAME LLITERAL ';'. (304)
- . reduce 304 (src line 1944)
+ . reduce 304 (src line 2006)
state 443
hidden_import: LVAR hidden_pkg_importsym hidden_type ';'. (305)
- . reduce 305 (src line 1949)
+ . reduce 305 (src line 2011)
state 444
@@ -7587,7 +7587,7 @@ state 447
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 298 (src line 1923)
+ . reduce 298 (src line 1985)
sym goto 546
hidden_importsym goto 11
@@ -7610,7 +7610,7 @@ state 448
'[' shift 342
'?' shift 12
'@' shift 13
- . reduce 300 (src line 1929)
+ . reduce 300 (src line 1991)
sym goto 550
hidden_importsym goto 553
@@ -7625,13 +7625,13 @@ state 448
state 449
hidden_type_misc: '*' hidden_type. (324)
- . reduce 324 (src line 2048)
+ . reduce 324 (src line 2110)
state 450
hidden_type_misc: LCHAN hidden_type_non_recv_chan. (325)
- . reduce 325 (src line 2052)
+ . reduce 325 (src line 2114)
state 451
@@ -7666,13 +7666,13 @@ state 452
state 453
hidden_type_non_recv_chan: hidden_type_misc. (315)
- . reduce 315 (src line 2008)
+ . reduce 315 (src line 2070)
state 454
hidden_type_non_recv_chan: hidden_type_func. (316)
- . reduce 316 (src line 2010)
+ . reduce 316 (src line 2072)
state 455
@@ -7703,7 +7703,7 @@ state 456
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 296 (src line 1917)
+ . reduce 296 (src line 1979)
sym goto 357
hidden_importsym goto 11
@@ -7721,7 +7721,7 @@ state 457
state 458
hidden_constant: hidden_literal. (342)
- . reduce 342 (src line 2195)
+ . reduce 342 (src line 2257)
state 459
@@ -7741,7 +7741,7 @@ state 459
state 460
hidden_literal: LLITERAL. (339)
- . reduce 339 (src line 2164)
+ . reduce 339 (src line 2226)
state 461
@@ -7754,7 +7754,7 @@ state 461
state 462
hidden_literal: sym. (341)
- . reduce 341 (src line 2187)
+ . reduce 341 (src line 2249)
state 463
@@ -7776,13 +7776,13 @@ state 463
state 464
hidden_import: LTYPE hidden_pkgtype hidden_type ';'. (308)
- . reduce 308 (src line 1961)
+ . reduce 308 (src line 2023)
state 465
hidden_import: LFUNC hidden_fndcl fnbody ';'. (309)
- . reduce 309 (src line 1965)
+ . reduce 309 (src line 2027)
state 466
@@ -7797,7 +7797,7 @@ state 467
hidden_funarg_list: hidden_funarg_list.',' hidden_funarg
',' shift 469
- . reduce 297 (src line 1921)
+ . reduce 297 (src line 1983)
state 468
@@ -7828,7 +7828,7 @@ state 470
oliteral: . (302)
LLITERAL shift 428
- . reduce 302 (src line 1935)
+ . reduce 302 (src line 1997)
oliteral goto 565
@@ -7856,13 +7856,13 @@ state 471
state 472
common_dcl: LVAR '(' vardcl_list osemi ')'. (29)
- . reduce 29 (src line 310)
+ . reduce 29 (src line 372)
state 473
vardcl_list: vardcl_list ';' vardcl. (221)
- . reduce 221 (src line 1525)
+ . reduce 221 (src line 1587)
state 474
@@ -7870,19 +7870,19 @@ state 474
expr_list: expr_list.',' expr
',' shift 155
- . reduce 40 (src line 365)
+ . reduce 40 (src line 427)
state 475
ntype: '(' ntype ')'. (171)
- . reduce 171 (src line 1196)
+ . reduce 171 (src line 1258)
state 476
common_dcl: lconst '(' constdcl osemi ')'. (32)
- . reduce 32 (src line 324)
+ . reduce 32 (src line 386)
state 477
@@ -7891,20 +7891,20 @@ state 477
osemi: . (286)
';' shift 568
- . reduce 286 (src line 1893)
+ . reduce 286 (src line 1955)
osemi goto 567
state 478
constdcl_list: constdcl1. (222)
- . reduce 222 (src line 1530)
+ . reduce 222 (src line 1592)
state 479
constdcl1: constdcl. (44)
- . reduce 44 (src line 384)
+ . reduce 44 (src line 446)
state 480
@@ -7928,7 +7928,7 @@ state 480
'?' shift 12
'@' shift 13
',' shift 225
- . reduce 46 (src line 390)
+ . reduce 46 (src line 452)
sym goto 123
ntype goto 569
@@ -7947,25 +7947,25 @@ state 481
expr_list: expr_list.',' expr
',' shift 155
- . reduce 42 (src line 374)
+ . reduce 42 (src line 436)
state 482
common_dcl: LTYPE '(' typedcl_list osemi ')'. (36)
- . reduce 36 (src line 345)
+ . reduce 36 (src line 407)
state 483
typedcl_list: typedcl_list ';' typedcl. (225)
- . reduce 225 (src line 1542)
+ . reduce 225 (src line 1604)
state 484
fnbody: '{' stmt_list '}'. (211)
- . reduce 211 (src line 1461)
+ . reduce 211 (src line 1523)
state 485
@@ -7973,19 +7973,19 @@ state 485
fndcl: '(' oarg_type_list_ocomma ')' sym.'(' oarg_type_list_ocomma ')' fnres
'(' shift 570
- . reduce 162 (src line 1158)
+ . reduce 162 (src line 1220)
state 486
fntype: LFUNC '(' oarg_type_list_ocomma ')' fnres. (209)
- . reduce 209 (src line 1448)
+ . reduce 209 (src line 1510)
state 487
fnres: fnret_type. (213)
- . reduce 213 (src line 1474)
+ . reduce 213 (src line 1536)
state 488
@@ -8005,7 +8005,7 @@ state 488
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 249 (src line 1707)
+ . reduce 249 (src line 1769)
sym goto 247
ntype goto 249
@@ -8027,37 +8027,37 @@ state 488
state 489
fnret_type: recvchantype. (184)
- . reduce 184 (src line 1227)
+ . reduce 184 (src line 1289)
state 490
fnret_type: fntype. (185)
- . reduce 185 (src line 1229)
+ . reduce 185 (src line 1291)
state 491
fnret_type: othertype. (186)
- . reduce 186 (src line 1230)
+ . reduce 186 (src line 1292)
state 492
fnret_type: ptrtype. (187)
- . reduce 187 (src line 1231)
+ . reduce 187 (src line 1293)
state 493
fnret_type: dotname. (188)
- . reduce 188 (src line 1232)
+ . reduce 188 (src line 1294)
state 494
arg_type_list: arg_type_list ',' arg_type. (248)
- . reduce 248 (src line 1702)
+ . reduce 248 (src line 1764)
state 495
@@ -8076,7 +8076,7 @@ state 495
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 212 (src line 1469)
+ . reduce 212 (src line 1531)
sym goto 123
dotname goto 493
@@ -8107,7 +8107,7 @@ state 496
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 212 (src line 1469)
+ . reduce 212 (src line 1531)
sym goto 123
dotname goto 493
@@ -8155,9 +8155,9 @@ state 497
'*' shift 58
'&' shift 59
'(' shift 67
- ';' reduce 251 (src line 1719)
+ ';' reduce 251 (src line 1781)
'{' shift 308
- '}' reduce 251 (src line 1719)
+ '}' reduce 251 (src line 1781)
'!' shift 62
'~' shift 63
'[' shift 77
@@ -8289,33 +8289,33 @@ state 501
switch_stmt: LSWITCH $$88 if_header $$89 LBODY.caseblock_list '}'
caseblock_list: . (63)
- . reduce 63 (src line 590)
+ . reduce 63 (src line 652)
caseblock_list goto 577
state 502
if_header: osimple_stmt ';' osimple_stmt. (77)
- . reduce 77 (src line 677)
+ . reduce 77 (src line 739)
state 503
caseblock_list: caseblock_list caseblock. (64)
- . reduce 64 (src line 594)
+ . reduce 64 (src line 656)
state 504
select_stmt: LSELECT $$91 LBODY caseblock_list '}'. (92)
- . reduce 92 (src line 782)
+ . reduce 92 (src line 844)
state 505
caseblock: case.$$61 stmt_list
$$61: . (61)
- . reduce 61 (src line 559)
+ . reduce 61 (src line 621)
$$61 goto 578
@@ -8377,14 +8377,14 @@ state 508
if_stmt: LIF $$78 if_header $$79 loop_body.$$80 elseif_list else
$$80: . (80)
- . reduce 80 (src line 699)
+ . reduce 80 (src line 761)
$$80 goto 581
state 509
pseudocall: pexpr '(' expr_or_type_list ocomma ')'. (124)
- . reduce 124 (src line 929)
+ . reduce 124 (src line 991)
state 510
@@ -8397,19 +8397,19 @@ state 510
state 511
expr_or_type_list: expr_or_type_list ',' expr_or_type. (279)
- . reduce 279 (src line 1855)
+ . reduce 279 (src line 1917)
state 512
pexpr_no_paren: pexpr '.' '(' expr_or_type ')'. (129)
- . reduce 129 (src line 958)
+ . reduce 129 (src line 1020)
state 513
pexpr_no_paren: pexpr '.' '(' LTYPE ')'. (130)
- . reduce 130 (src line 962)
+ . reduce 130 (src line 1024)
state 514
@@ -8424,7 +8424,7 @@ state 514
state 515
pexpr_no_paren: pexpr_no_paren '{' start_complit braced_keyval_list '}'. (137)
- . reduce 137 (src line 998)
+ . reduce 137 (src line 1060)
state 516
@@ -8452,7 +8452,7 @@ state 516
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 289 (src line 1897)
+ . reduce 289 (src line 1959)
sym goto 123
expr goto 402
@@ -8476,7 +8476,7 @@ state 516
state 517
braced_keyval_list: keyval_list ocomma. (285)
- . reduce 285 (src line 1885)
+ . reduce 285 (src line 1947)
state 518
@@ -8546,7 +8546,7 @@ state 519
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 284 (src line 1881)
+ . reduce 284 (src line 1943)
sym goto 123
expr goto 402
@@ -8593,7 +8593,7 @@ state 520
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 284 (src line 1881)
+ . reduce 284 (src line 1943)
sym goto 123
expr goto 402
@@ -8627,19 +8627,19 @@ state 521
state 522
pexpr_no_paren: convtype '(' expr ocomma ')'. (135)
- . reduce 135 (src line 985)
+ . reduce 135 (src line 1047)
state 523
pexpr_no_paren: comptype lbrace start_complit braced_keyval_list '}'. (136)
- . reduce 136 (src line 991)
+ . reduce 136 (src line 1053)
state 524
stmt_list: stmt_list ';' stmt. (271)
- . reduce 271 (src line 1812)
+ . reduce 271 (src line 1874)
state 525
@@ -8654,31 +8654,31 @@ state 525
state 526
othertype: LMAP '[' ntype ']' ntype. (195)
- . reduce 195 (src line 1268)
+ . reduce 195 (src line 1330)
state 527
structtype: LSTRUCT lbrace structdcl_list osemi '}'. (200)
- . reduce 200 (src line 1288)
+ . reduce 200 (src line 1350)
state 528
structdcl_list: structdcl_list ';' structdcl. (227)
- . reduce 227 (src line 1549)
+ . reduce 227 (src line 1611)
state 529
structdcl: new_name_list ntype oliteral. (230)
- . reduce 230 (src line 1564)
+ . reduce 230 (src line 1626)
state 530
new_name_list: new_name_list ',' new_name. (273)
- . reduce 273 (src line 1825)
+ . reduce 273 (src line 1887)
state 531
@@ -8686,7 +8686,7 @@ state 531
oliteral: . (302)
LLITERAL shift 428
- . reduce 302 (src line 1935)
+ . reduce 302 (src line 1997)
oliteral goto 594
@@ -8700,7 +8700,7 @@ state 532
state 533
structdcl: '*' embed oliteral. (233)
- . reduce 233 (src line 1600)
+ . reduce 233 (src line 1662)
state 534
@@ -8713,19 +8713,19 @@ state 534
state 535
packname: LNAME '.' sym. (237)
- . reduce 237 (src line 1632)
+ . reduce 237 (src line 1694)
state 536
interfacetype: LINTERFACE lbrace interfacedcl_list osemi '}'. (202)
- . reduce 202 (src line 1301)
+ . reduce 202 (src line 1363)
state 537
interfacedcl_list: interfacedcl_list ';' interfacedcl. (229)
- . reduce 229 (src line 1559)
+ . reduce 229 (src line 1621)
state 538
@@ -8738,13 +8738,13 @@ state 538
state 539
interfacedcl: '(' packname ')'. (241)
- . reduce 241 (src line 1662)
+ . reduce 241 (src line 1724)
state 540
hidden_type_misc: '[' ']' hidden_type. (319)
- . reduce 319 (src line 2028)
+ . reduce 319 (src line 2090)
state 541
@@ -8787,13 +8787,13 @@ state 544
hidden_structdcl_list: hidden_structdcl_list.';' hidden_structdcl
';' shift 601
- . reduce 299 (src line 1927)
+ . reduce 299 (src line 1989)
state 545
hidden_structdcl_list: hidden_structdcl. (348)
- . reduce 348 (src line 2222)
+ . reduce 348 (src line 2284)
state 546
@@ -8829,13 +8829,13 @@ state 548
hidden_interfacedcl_list: hidden_interfacedcl_list.';' hidden_interfacedcl
';' shift 604
- . reduce 301 (src line 1933)
+ . reduce 301 (src line 1995)
state 549
hidden_interfacedcl_list: hidden_interfacedcl. (350)
- . reduce 350 (src line 2232)
+ . reduce 350 (src line 2294)
state 550
@@ -8848,23 +8848,23 @@ state 550
state 551
hidden_interfacedcl: hidden_type. (334)
- . reduce 334 (src line 2139)
+ . reduce 334 (src line 2201)
state 552
sym: LNAME. (157)
hidden_type_misc: LNAME. (318)
- '(' reduce 157 (src line 1113)
- . reduce 318 (src line 2017)
+ '(' reduce 157 (src line 1175)
+ . reduce 318 (src line 2079)
state 553
sym: hidden_importsym. (158)
hidden_type_misc: hidden_importsym. (317)
- '(' reduce 158 (src line 1122)
- . reduce 317 (src line 2012)
+ '(' reduce 158 (src line 1184)
+ . reduce 317 (src line 2074)
state 554
@@ -8877,13 +8877,13 @@ state 554
state 555
hidden_type_misc: LCHAN LCOMM hidden_type. (327)
- . reduce 327 (src line 2064)
+ . reduce 327 (src line 2126)
state 556
hidden_type_recv_chan: LCOMM LCHAN hidden_type. (328)
- . reduce 328 (src line 2071)
+ . reduce 328 (src line 2133)
state 557
@@ -8896,7 +8896,7 @@ state 557
state 558
hidden_import: LCONST hidden_pkg_importsym '=' hidden_constant ';'. (306)
- . reduce 306 (src line 1953)
+ . reduce 306 (src line 2015)
state 559
@@ -8909,7 +8909,7 @@ state 559
state 560
hidden_literal: '-' LLITERAL. (340)
- . reduce 340 (src line 2169)
+ . reduce 340 (src line 2231)
state 561
@@ -8934,7 +8934,7 @@ state 562
'(' shift 612
'[' shift 342
'@' shift 13
- . reduce 335 (src line 2144)
+ . reduce 335 (src line 2206)
hidden_importsym goto 340
hidden_funres goto 611
@@ -8954,13 +8954,13 @@ state 563
state 564
hidden_funarg_list: hidden_funarg_list ',' hidden_funarg. (347)
- . reduce 347 (src line 2217)
+ . reduce 347 (src line 2279)
state 565
hidden_funarg: sym hidden_type oliteral. (330)
- . reduce 330 (src line 2085)
+ . reduce 330 (src line 2147)
state 566
@@ -8968,7 +8968,7 @@ state 566
oliteral: . (302)
LLITERAL shift 428
- . reduce 302 (src line 1935)
+ . reduce 302 (src line 1997)
oliteral goto 615
@@ -8986,7 +8986,7 @@ state 568
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 287 (src line 1894)
+ . reduce 287 (src line 1956)
sym goto 105
dcl_name goto 104
@@ -9000,7 +9000,7 @@ state 569
constdcl1: dcl_name_list ntype. (45)
'=' shift 367
- . reduce 45 (src line 386)
+ . reduce 45 (src line 448)
state 570
@@ -9020,7 +9020,7 @@ state 570
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 249 (src line 1707)
+ . reduce 249 (src line 1769)
sym goto 247
ntype goto 249
@@ -9049,7 +9049,7 @@ state 571
state 572
fndcl: sym '(' oarg_type_list_ocomma ')' fnres. (205)
- . reduce 205 (src line 1336)
+ . reduce 205 (src line 1398)
state 573
@@ -9084,7 +9084,7 @@ state 574
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 294 (src line 1911)
+ . reduce 294 (src line 1973)
sym goto 123
expr goto 48
@@ -9149,7 +9149,7 @@ state 575
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 67 (src line 610)
+ . reduce 67 (src line 672)
state 576
@@ -9195,7 +9195,7 @@ state 576
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 68 (src line 617)
+ . reduce 68 (src line 679)
state 577
@@ -9217,11 +9217,11 @@ state 578
error shift 307
LLITERAL shift 68
LBREAK shift 41
- LCASE reduce 251 (src line 1719)
+ LCASE reduce 251 (src line 1781)
LCHAN shift 78
LCONST shift 47
LCONTINUE shift 42
- LDEFAULT reduce 251 (src line 1719)
+ LDEFAULT reduce 251 (src line 1781)
LDEFER shift 44
LFALL shift 40
LFOR shift 50
@@ -9245,9 +9245,9 @@ state 578
'*' shift 58
'&' shift 59
'(' shift 67
- ';' reduce 251 (src line 1719)
+ ';' reduce 251 (src line 1781)
'{' shift 308
- '}' reduce 251 (src line 1719)
+ '}' reduce 251 (src line 1781)
'!' shift 62
'~' shift 63
'[' shift 77
@@ -9302,27 +9302,27 @@ state 579
state 580
case: LDEFAULT ':'. (58)
- . reduce 58 (src line 524)
+ . reduce 58 (src line 586)
state 581
if_stmt: LIF $$78 if_header $$79 loop_body $$80.elseif_list else
elseif_list: . (84)
- . reduce 84 (src line 734)
+ . reduce 84 (src line 796)
elseif_list goto 628
state 582
pseudocall: pexpr '(' expr_or_type_list LDDD ocomma ')'. (125)
- . reduce 125 (src line 934)
+ . reduce 125 (src line 996)
state 583
pexpr_no_paren: pexpr '[' oexpr ':' oexpr ']'. (132)
- . reduce 132 (src line 970)
+ . reduce 132 (src line 1032)
state 584
@@ -9348,7 +9348,7 @@ state 584
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 290 (src line 1899)
+ . reduce 290 (src line 1961)
sym goto 123
expr goto 188
@@ -9371,19 +9371,19 @@ state 584
state 585
keyval_list: keyval_list ',' keyval. (282)
- . reduce 282 (src line 1872)
+ . reduce 282 (src line 1934)
state 586
keyval_list: keyval_list ',' bare_complitexpr. (283)
- . reduce 283 (src line 1876)
+ . reduce 283 (src line 1938)
state 587
keyval: expr ':' complitexpr. (141)
- . reduce 141 (src line 1020)
+ . reduce 141 (src line 1082)
state 588
@@ -9429,14 +9429,14 @@ state 588
'/' shift 146
'%' shift 147
'&' shift 148
- . reduce 144 (src line 1046)
+ . reduce 144 (src line 1108)
state 589
complitexpr: '{'.start_complit braced_keyval_list '}'
start_complit: . (140)
- . reduce 140 (src line 1013)
+ . reduce 140 (src line 1075)
start_complit goto 630
@@ -9458,22 +9458,22 @@ state 592
ntype: '(' ntype ')'. (171)
non_recvchantype: '(' ntype ')'. (180)
- LBODY reduce 180 (src line 1215)
- '(' reduce 180 (src line 1215)
- '{' reduce 180 (src line 1215)
- . reduce 171 (src line 1196)
+ LBODY reduce 180 (src line 1277)
+ '(' reduce 180 (src line 1277)
+ '{' reduce 180 (src line 1277)
+ . reduce 171 (src line 1258)
state 593
compound_stmt: '{' $$59 stmt_list '}'. (60)
- . reduce 60 (src line 549)
+ . reduce 60 (src line 611)
state 594
structdcl: '(' embed ')' oliteral. (232)
- . reduce 232 (src line 1594)
+ . reduce 232 (src line 1656)
state 595
@@ -9481,7 +9481,7 @@ state 595
oliteral: . (302)
LLITERAL shift 428
- . reduce 302 (src line 1935)
+ . reduce 302 (src line 1997)
oliteral goto 633
@@ -9490,7 +9490,7 @@ state 596
oliteral: . (302)
LLITERAL shift 428
- . reduce 302 (src line 1935)
+ . reduce 302 (src line 1997)
oliteral goto 634
@@ -9510,7 +9510,7 @@ state 597
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 212 (src line 1469)
+ . reduce 212 (src line 1531)
sym goto 123
dotname goto 493
@@ -9528,7 +9528,7 @@ state 597
state 598
hidden_type_misc: '[' LLITERAL ']' hidden_type. (320)
- . reduce 320 (src line 2032)
+ . reduce 320 (src line 2094)
state 599
@@ -9555,7 +9555,7 @@ state 599
state 600
hidden_type_misc: LSTRUCT '{' ohidden_structdcl_list '}'. (322)
- . reduce 322 (src line 2040)
+ . reduce 322 (src line 2102)
state 601
@@ -9575,14 +9575,14 @@ state 602
oliteral: . (302)
LLITERAL shift 428
- . reduce 302 (src line 1935)
+ . reduce 302 (src line 1997)
oliteral goto 638
state 603
hidden_type_misc: LINTERFACE '{' ohidden_interfacedcl_list '}'. (323)
- . reduce 323 (src line 2044)
+ . reduce 323 (src line 2106)
state 604
@@ -9616,7 +9616,7 @@ state 605
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 296 (src line 1917)
+ . reduce 296 (src line 1979)
sym goto 357
hidden_importsym goto 11
@@ -9627,7 +9627,7 @@ state 605
state 606
hidden_type_misc: LCHAN '(' hidden_type_recv_chan ')'. (326)
- . reduce 326 (src line 2058)
+ . reduce 326 (src line 2120)
state 607
@@ -9645,7 +9645,7 @@ state 607
'(' shift 612
'[' shift 342
'@' shift 13
- . reduce 335 (src line 2144)
+ . reduce 335 (src line 2206)
hidden_importsym goto 340
hidden_funres goto 611
@@ -9672,19 +9672,19 @@ state 608
state 609
hidden_import: LCONST hidden_pkg_importsym hidden_type '=' hidden_constant ';'. (307)
- . reduce 307 (src line 1957)
+ . reduce 307 (src line 2019)
state 610
hidden_fndcl: hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres. (207)
- . reduce 207 (src line 1405)
+ . reduce 207 (src line 1467)
state 611
ohidden_funres: hidden_funres. (336)
- . reduce 336 (src line 2148)
+ . reduce 336 (src line 2210)
state 612
@@ -9694,7 +9694,7 @@ state 612
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 296 (src line 1917)
+ . reduce 296 (src line 1979)
sym goto 357
hidden_importsym goto 11
@@ -9705,7 +9705,7 @@ state 612
state 613
hidden_funres: hidden_type. (338)
- . reduce 338 (src line 2155)
+ . reduce 338 (src line 2217)
state 614
@@ -9715,7 +9715,7 @@ state 614
LNAME shift 10
'?' shift 12
'@' shift 13
- . reduce 296 (src line 1917)
+ . reduce 296 (src line 1979)
sym goto 357
hidden_importsym goto 11
@@ -9726,19 +9726,19 @@ state 614
state 615
hidden_funarg: sym LDDD hidden_type oliteral. (331)
- . reduce 331 (src line 2094)
+ . reduce 331 (src line 2156)
state 616
common_dcl: lconst '(' constdcl ';' constdcl_list osemi ')'. (33)
- . reduce 33 (src line 330)
+ . reduce 33 (src line 392)
state 617
constdcl_list: constdcl_list ';' constdcl1. (223)
- . reduce 223 (src line 1532)
+ . reduce 223 (src line 1594)
state 618
@@ -9751,25 +9751,25 @@ state 618
state 619
fnres: '(' oarg_type_list_ocomma ')'. (214)
- . reduce 214 (src line 1478)
+ . reduce 214 (src line 1540)
state 620
loop_body: LBODY $$65 stmt_list '}'. (66)
- . reduce 66 (src line 604)
+ . reduce 66 (src line 666)
state 621
for_header: osimple_stmt ';' osimple_stmt ';' osimple_stmt. (70)
- . reduce 70 (src line 630)
+ . reduce 70 (src line 692)
state 622
switch_stmt: LSWITCH $$88 if_header $$89 LBODY caseblock_list '}'. (90)
- . reduce 90 (src line 768)
+ . reduce 90 (src line 830)
state 623
@@ -9777,13 +9777,13 @@ state 623
stmt_list: stmt_list.';' stmt
';' shift 416
- . reduce 62 (src line 571)
+ . reduce 62 (src line 633)
state 624
case: LCASE expr_or_type_list ':'. (55)
- . reduce 55 (src line 473)
+ . reduce 55 (src line 535)
state 625
@@ -9918,7 +9918,7 @@ state 628
else: . (86)
LELSE shift 650
- . reduce 86 (src line 743)
+ . reduce 86 (src line 805)
elseif goto 649
else goto 648
@@ -9954,7 +9954,7 @@ state 630
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 284 (src line 1881)
+ . reduce 284 (src line 1943)
sym goto 123
expr goto 402
@@ -9980,55 +9980,55 @@ state 630
state 631
bare_complitexpr: '{' start_complit braced_keyval_list '}'. (143)
- . reduce 143 (src line 1040)
+ . reduce 143 (src line 1102)
state 632
pexpr_no_paren: '(' expr_or_type ')' '{' start_complit braced_keyval_list '}'. (138)
- . reduce 138 (src line 1004)
+ . reduce 138 (src line 1066)
state 633
structdcl: '(' '*' embed ')' oliteral. (234)
- . reduce 234 (src line 1606)
+ . reduce 234 (src line 1668)
state 634
structdcl: '*' '(' embed ')' oliteral. (235)
- . reduce 235 (src line 1613)
+ . reduce 235 (src line 1675)
state 635
indcl: '(' oarg_type_list_ocomma ')' fnres. (242)
- . reduce 242 (src line 1668)
+ . reduce 242 (src line 1730)
state 636
hidden_type_misc: LMAP '[' hidden_type ']' hidden_type. (321)
- . reduce 321 (src line 2036)
+ . reduce 321 (src line 2098)
state 637
hidden_structdcl_list: hidden_structdcl_list ';' hidden_structdcl. (349)
- . reduce 349 (src line 2227)
+ . reduce 349 (src line 2289)
state 638
hidden_structdcl: sym hidden_type oliteral. (332)
- . reduce 332 (src line 2110)
+ . reduce 332 (src line 2172)
state 639
hidden_interfacedcl_list: hidden_interfacedcl_list ';' hidden_interfacedcl. (351)
- . reduce 351 (src line 2237)
+ . reduce 351 (src line 2299)
state 640
@@ -10041,7 +10041,7 @@ state 640
state 641
hidden_type_func: LFUNC '(' ohidden_funarg_list ')' ohidden_funres. (329)
- . reduce 329 (src line 2079)
+ . reduce 329 (src line 2141)
state 642
@@ -10081,7 +10081,7 @@ state 645
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 212 (src line 1469)
+ . reduce 212 (src line 1531)
sym goto 123
dotname goto 493
@@ -10193,13 +10193,13 @@ state 647
state 648
if_stmt: LIF $$78 if_header $$79 loop_body $$80 elseif_list else. (81)
- . reduce 81 (src line 703)
+ . reduce 81 (src line 765)
state 649
elseif_list: elseif_list elseif. (85)
- . reduce 85 (src line 738)
+ . reduce 85 (src line 800)
state 650
@@ -10215,7 +10215,7 @@ state 650
state 651
pexpr_no_paren: pexpr '[' oexpr ':' oexpr ':' oexpr ']'. (133)
- . reduce 133 (src line 974)
+ . reduce 133 (src line 1036)
state 652
@@ -10240,7 +10240,7 @@ state 653
'(' shift 612
'[' shift 342
'@' shift 13
- . reduce 335 (src line 2144)
+ . reduce 335 (src line 2206)
hidden_importsym goto 340
hidden_funres goto 611
@@ -10253,13 +10253,13 @@ state 653
state 654
hidden_constant: '(' hidden_literal '+' hidden_literal ')'. (343)
- . reduce 343 (src line 2197)
+ . reduce 343 (src line 2259)
state 655
hidden_funres: '(' ohidden_funarg_list ')'. (337)
- . reduce 337 (src line 2150)
+ . reduce 337 (src line 2212)
state 656
@@ -10277,7 +10277,7 @@ state 656
'(' shift 612
'[' shift 342
'@' shift 13
- . reduce 335 (src line 2144)
+ . reduce 335 (src line 2206)
hidden_importsym goto 340
hidden_funres goto 611
@@ -10290,51 +10290,51 @@ state 656
state 657
fndcl: '(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres. (206)
- . reduce 206 (src line 1368)
+ . reduce 206 (src line 1430)
state 658
case: LCASE expr_or_type_list '=' expr ':'. (56)
- . reduce 56 (src line 497)
+ . reduce 56 (src line 559)
state 659
case: LCASE expr_or_type_list LCOLAS expr ':'. (57)
- . reduce 57 (src line 515)
+ . reduce 57 (src line 577)
state 660
elseif: LELSE LIF.$$82 if_header loop_body
$$82: . (82)
- . reduce 82 (src line 720)
+ . reduce 82 (src line 782)
$$82 goto 665
state 661
else: LELSE compound_stmt. (87)
- . reduce 87 (src line 747)
+ . reduce 87 (src line 809)
state 662
complitexpr: '{' start_complit braced_keyval_list '}'. (145)
- . reduce 145 (src line 1048)
+ . reduce 145 (src line 1110)
state 663
hidden_interfacedcl: sym '(' ohidden_funarg_list ')' ohidden_funres. (333)
- . reduce 333 (src line 2134)
+ . reduce 333 (src line 2196)
state 664
hidden_fndcl: '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres. (208)
- . reduce 208 (src line 1431)
+ . reduce 208 (src line 1493)
state 665
@@ -10360,7 +10360,7 @@ state 665
'[' shift 77
'?' shift 12
'@' shift 13
- . reduce 294 (src line 1911)
+ . reduce 294 (src line 1973)
sym goto 123
expr goto 48
@@ -10394,7 +10394,7 @@ state 666
state 667
elseif: LELSE LIF $$82 if_header loop_body. (83)
- . reduce 83 (src line 725)
+ . reduce 83 (src line 787)
76 terminals, 142 nonterminals
diff --git a/src/cmd/9g/cgen.go b/src/cmd/compile/internal/ppc64/cgen.go
index 5d24a6ff67..37dd6cefb2 100644
--- a/src/cmd/9g/cgen.go
+++ b/src/cmd/compile/internal/ppc64/cgen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package ppc64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/ppc64"
)
diff --git a/src/cmd/9g/galign.go b/src/cmd/compile/internal/ppc64/galign.go
index a2f4a0ef89..73aef6fde9 100644
--- a/src/cmd/9g/galign.go
+++ b/src/cmd/compile/internal/ppc64/galign.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package ppc64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/ppc64"
)
@@ -45,7 +45,7 @@ func betypeinit() {
gc.Widthreg = 8
}
-func main() {
+func Main() {
gc.Thearch.Thechar = thechar
gc.Thearch.Thestring = thestring
gc.Thearch.Thelinkarch = thelinkarch
@@ -72,6 +72,7 @@ func main() {
gc.Thearch.Expandchecks = expandchecks
gc.Thearch.Getg = getg
gc.Thearch.Gins = gins
+ gc.Thearch.Ginscmp = ginscmp
gc.Thearch.Ginscon = ginscon
gc.Thearch.Ginsnop = ginsnop
gc.Thearch.Gmove = gmove
diff --git a/src/cmd/9g/ggen.go b/src/cmd/compile/internal/ppc64/ggen.go
index 28ebd9cc01..1b936b8a5f 100644
--- a/src/cmd/9g/ggen.go
+++ b/src/cmd/compile/internal/ppc64/ggen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package ppc64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/ppc64"
"fmt"
@@ -32,7 +32,7 @@ func defframe(ptxt *obj.Prog) {
// iterate through declarations - they are sorted in decreasing xoffset order.
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
n = l.N
- if !n.Needzero {
+ if !n.Name.Needzero {
continue
}
if n.Class != gc.PAUTO {
@@ -141,9 +141,9 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
check := 0
if gc.Issigned[t.Etype] {
check = 1
- if gc.Isconst(nl, gc.CTINT) && gc.Mpgetfix(nl.Val.U.Xval) != -(1<<uint64(t.Width*8-1)) {
+ if gc.Isconst(nl, gc.CTINT) && nl.Int() != -(1<<uint64(t.Width*8-1)) {
check = 0
- } else if gc.Isconst(nr, gc.CTINT) && gc.Mpgetfix(nr.Val.U.Xval) != -1 {
+ } else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
check = 0
}
}
@@ -308,7 +308,7 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, res)
gc.Cgen(nl, &n1)
- sc := uint64(uint64(gc.Mpgetfix(nr.Val.U.Xval)))
+ sc := uint64(nr.Int())
if sc >= uint64(nl.Type.Width*8) {
// large shift gets 2 shifts by width-1
var n3 gc.Node
diff --git a/src/cmd/9g/gsubr.go b/src/cmd/compile/internal/ppc64/gsubr.go
index 8223fe70b1..2501972846 100644
--- a/src/cmd/9g/gsubr.go
+++ b/src/cmd/compile/internal/ppc64/gsubr.go
@@ -28,10 +28,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package ppc64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/big"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/ppc64"
"fmt"
@@ -116,29 +117,55 @@ func ginscon2(as int, n2 *gc.Node, c int64) {
gc.Regfree(&ntmp)
}
-/*
- * set up nodes representing 2^63
- */
-var bigi gc.Node
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+ if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
+ // Reverse comparison to place constant last.
+ op = gc.Brrev(op)
+ n1, n2 = n2, n1
+ }
-var bigf gc.Node
+ var r1, r2, g1, g2 gc.Node
+ gc.Regalloc(&r1, t, n1)
+ gc.Regalloc(&g1, n1.Type, &r1)
+ gc.Cgen(n1, &g1)
+ gmove(&g1, &r1)
+ if gc.Isint[t.Etype] && gc.Isconst(n2, gc.CTINT) {
+ ginscon2(optoas(gc.OCMP, t), &r1, n2.Int())
+ } else {
+ gc.Regalloc(&r2, t, n2)
+ gc.Regalloc(&g2, n1.Type, &r2)
+ gc.Cgen(n2, &g2)
+ gmove(&g2, &r2)
+ rawgins(optoas(gc.OCMP, t), &r1, &r2)
+ gc.Regfree(&g2)
+ gc.Regfree(&r2)
+ }
+ gc.Regfree(&g1)
+ gc.Regfree(&r1)
+ return gc.Gbranch(optoas(op, t), nil, likely)
+}
-var bignodes_did int
+// set up nodes representing 2^63
+var (
+ bigi gc.Node
+ bigf gc.Node
+ bignodes_did bool
+)
func bignodes() {
- if bignodes_did != 0 {
+ if bignodes_did {
return
}
- bignodes_did = 1
+ bignodes_did = true
- gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 1)
- gc.Mpshiftfix(bigi.Val.U.Xval, 63)
+ var i big.Int
+ i.SetInt64(1)
+ i.Lsh(&i, 63)
- bigf = bigi
- bigf.Type = gc.Types[gc.TFLOAT64]
- bigf.Val.Ctype = gc.CTFLT
- bigf.Val.U.Fval = new(gc.Mpflt)
- gc.Mpmovefixflt(bigf.Val.U.Fval, bigi.Val.U.Xval)
+ gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
+ bigi.SetBigInt(&i)
+
+ bigi.Convconst(&bigf, gc.Types[gc.TFLOAT64])
}
/*
@@ -173,13 +200,13 @@ func gmove(f *gc.Node, t *gc.Node) {
var con gc.Node
switch tt {
default:
- gc.Convconst(&con, t.Type, &f.Val)
+ f.Convconst(&con, t.Type)
case gc.TINT32,
gc.TINT16,
gc.TINT8:
var con gc.Node
- gc.Convconst(&con, gc.Types[gc.TINT64], &f.Val)
+ f.Convconst(&con, gc.Types[gc.TINT64])
var r1 gc.Node
gc.Regalloc(&r1, con.Type, t)
gins(ppc64.AMOVD, &con, &r1)
@@ -191,7 +218,7 @@ func gmove(f *gc.Node, t *gc.Node) {
gc.TUINT16,
gc.TUINT8:
var con gc.Node
- gc.Convconst(&con, gc.Types[gc.TUINT64], &f.Val)
+ f.Convconst(&con, gc.Types[gc.TUINT64])
var r1 gc.Node
gc.Regalloc(&r1, con.Type, t)
gins(ppc64.AMOVD, &con, &r1)
@@ -519,14 +546,13 @@ hard:
}
func intLiteral(n *gc.Node) (x int64, ok bool) {
- if n == nil || n.Op != gc.OLITERAL {
+ switch {
+ case n == nil:
return
- }
- switch n.Val.Ctype {
- case gc.CTINT, gc.CTRUNE:
- return gc.Mpgetfix(n.Val.U.Xval), true
- case gc.CTBOOL:
- return int64(obj.Bool2int(n.Val.U.Bval)), true
+ case gc.Isconst(n, gc.CTINT):
+ return n.Int(), true
+ case gc.Isconst(n, gc.CTBOOL):
+ return int64(obj.Bool2int(n.Bool())), true
}
return
}
diff --git a/src/cmd/9g/opt.go b/src/cmd/compile/internal/ppc64/opt.go
index 4a134f134f..1704f63c48 100644
--- a/src/cmd/9g/opt.go
+++ b/src/cmd/compile/internal/ppc64/opt.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 main
+package ppc64
// Many Power ISA arithmetic and logical instructions come in four
// standard variants. These bits let us map between variants.
diff --git a/src/cmd/9g/peep.go b/src/cmd/compile/internal/ppc64/peep.go
index 94c9b1554b..16eeb39097 100644
--- a/src/cmd/9g/peep.go
+++ b/src/cmd/compile/internal/ppc64/peep.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package ppc64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/ppc64"
"fmt"
diff --git a/src/cmd/9g/prog.go b/src/cmd/compile/internal/ppc64/prog.go
index e28e389fac..c7e182769d 100644
--- a/src/cmd/9g/prog.go
+++ b/src/cmd/compile/internal/ppc64/prog.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package ppc64
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/ppc64"
)
diff --git a/src/cmd/9g/reg.go b/src/cmd/compile/internal/ppc64/reg.go
index fb0c2e37ec..fa1cb71975 100644
--- a/src/cmd/9g/reg.go
+++ b/src/cmd/compile/internal/ppc64/reg.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package ppc64
import "cmd/internal/obj/ppc64"
-import "cmd/internal/gc"
+import "cmd/compile/internal/gc"
const (
NREGVAR = 64 /* 32 general + 32 floating */
diff --git a/src/cmd/internal/ssa/TODO b/src/cmd/compile/internal/ssa/TODO
index afb723ae4c..afb723ae4c 100644
--- a/src/cmd/internal/ssa/TODO
+++ b/src/cmd/compile/internal/ssa/TODO
diff --git a/src/cmd/internal/ssa/block.go b/src/cmd/compile/internal/ssa/block.go
index dcf3676bc2..dcf3676bc2 100644
--- a/src/cmd/internal/ssa/block.go
+++ b/src/cmd/compile/internal/ssa/block.go
diff --git a/src/cmd/internal/ssa/blockkind_string.go b/src/cmd/compile/internal/ssa/blockkind_string.go
index 6204f1948f..6204f1948f 100644
--- a/src/cmd/internal/ssa/blockkind_string.go
+++ b/src/cmd/compile/internal/ssa/blockkind_string.go
diff --git a/src/cmd/internal/ssa/cgen.go b/src/cmd/compile/internal/ssa/cgen.go
index 51c72aacd9..51c72aacd9 100644
--- a/src/cmd/internal/ssa/cgen.go
+++ b/src/cmd/compile/internal/ssa/cgen.go
diff --git a/src/cmd/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go
index 667313ad9f..667313ad9f 100644
--- a/src/cmd/internal/ssa/check.go
+++ b/src/cmd/compile/internal/ssa/check.go
diff --git a/src/cmd/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go
index c1f7956791..c1f7956791 100644
--- a/src/cmd/internal/ssa/compile.go
+++ b/src/cmd/compile/internal/ssa/compile.go
diff --git a/src/cmd/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go
index 9f1d2a8593..9f1d2a8593 100644
--- a/src/cmd/internal/ssa/config.go
+++ b/src/cmd/compile/internal/ssa/config.go
diff --git a/src/cmd/internal/ssa/copyelim.go b/src/cmd/compile/internal/ssa/copyelim.go
index 10c2dcc440..10c2dcc440 100644
--- a/src/cmd/internal/ssa/copyelim.go
+++ b/src/cmd/compile/internal/ssa/copyelim.go
diff --git a/src/cmd/internal/ssa/critical.go b/src/cmd/compile/internal/ssa/critical.go
index 503681ffd3..503681ffd3 100644
--- a/src/cmd/internal/ssa/critical.go
+++ b/src/cmd/compile/internal/ssa/critical.go
diff --git a/src/cmd/internal/ssa/cse.go b/src/cmd/compile/internal/ssa/cse.go
index aba24aeabc..aba24aeabc 100644
--- a/src/cmd/internal/ssa/cse.go
+++ b/src/cmd/compile/internal/ssa/cse.go
diff --git a/src/cmd/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go
index a805861489..a805861489 100644
--- a/src/cmd/internal/ssa/deadcode.go
+++ b/src/cmd/compile/internal/ssa/deadcode.go
diff --git a/src/cmd/internal/ssa/deadcode_test.go b/src/cmd/compile/internal/ssa/deadcode_test.go
index ced46e524b..ced46e524b 100644
--- a/src/cmd/internal/ssa/deadcode_test.go
+++ b/src/cmd/compile/internal/ssa/deadcode_test.go
diff --git a/src/cmd/internal/ssa/dom.go b/src/cmd/compile/internal/ssa/dom.go
index aaf3ab3da1..aaf3ab3da1 100644
--- a/src/cmd/internal/ssa/dom.go
+++ b/src/cmd/compile/internal/ssa/dom.go
diff --git a/src/cmd/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go
index ab4ab82345..ab4ab82345 100644
--- a/src/cmd/internal/ssa/export_test.go
+++ b/src/cmd/compile/internal/ssa/export_test.go
diff --git a/src/cmd/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go
index 3e41ef3bc1..3e41ef3bc1 100644
--- a/src/cmd/internal/ssa/func.go
+++ b/src/cmd/compile/internal/ssa/func.go
diff --git a/src/cmd/internal/ssa/func_test.go b/src/cmd/compile/internal/ssa/func_test.go
index e7619ca4f8..e7619ca4f8 100644
--- a/src/cmd/internal/ssa/func_test.go
+++ b/src/cmd/compile/internal/ssa/func_test.go
diff --git a/src/cmd/internal/ssa/fuse.go b/src/cmd/compile/internal/ssa/fuse.go
index af3e8a8e14..af3e8a8e14 100644
--- a/src/cmd/internal/ssa/fuse.go
+++ b/src/cmd/compile/internal/ssa/fuse.go
diff --git a/src/cmd/internal/ssa/generic.go b/src/cmd/compile/internal/ssa/generic.go
index 91f9c17d11..91f9c17d11 100644
--- a/src/cmd/internal/ssa/generic.go
+++ b/src/cmd/compile/internal/ssa/generic.go
diff --git a/src/cmd/internal/ssa/id.go b/src/cmd/compile/internal/ssa/id.go
index 3f53e1a434..3f53e1a434 100644
--- a/src/cmd/internal/ssa/id.go
+++ b/src/cmd/compile/internal/ssa/id.go
diff --git a/src/cmd/internal/ssa/layout.go b/src/cmd/compile/internal/ssa/layout.go
index 7123397c4c..7123397c4c 100644
--- a/src/cmd/internal/ssa/layout.go
+++ b/src/cmd/compile/internal/ssa/layout.go
diff --git a/src/cmd/internal/ssa/location.go b/src/cmd/compile/internal/ssa/location.go
index 1b6f6d66c1..1b6f6d66c1 100644
--- a/src/cmd/internal/ssa/location.go
+++ b/src/cmd/compile/internal/ssa/location.go
diff --git a/src/cmd/internal/ssa/lower.go b/src/cmd/compile/internal/ssa/lower.go
index 44f0b83fa8..44f0b83fa8 100644
--- a/src/cmd/internal/ssa/lower.go
+++ b/src/cmd/compile/internal/ssa/lower.go
diff --git a/src/cmd/internal/ssa/lowerAmd64.go b/src/cmd/compile/internal/ssa/lowerAmd64.go
index 51cef97b30..51cef97b30 100644
--- a/src/cmd/internal/ssa/lowerAmd64.go
+++ b/src/cmd/compile/internal/ssa/lowerAmd64.go
diff --git a/src/cmd/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go
index f02c1ae0c0..f02c1ae0c0 100644
--- a/src/cmd/internal/ssa/op.go
+++ b/src/cmd/compile/internal/ssa/op.go
diff --git a/src/cmd/internal/ssa/op_string.go b/src/cmd/compile/internal/ssa/op_string.go
index c8f27bb2e4..c8f27bb2e4 100644
--- a/src/cmd/internal/ssa/op_string.go
+++ b/src/cmd/compile/internal/ssa/op_string.go
diff --git a/src/cmd/internal/ssa/opamd64.go b/src/cmd/compile/internal/ssa/opamd64.go
index 46a0069a18..46a0069a18 100644
--- a/src/cmd/internal/ssa/opamd64.go
+++ b/src/cmd/compile/internal/ssa/opamd64.go
diff --git a/src/cmd/internal/ssa/opt.go b/src/cmd/compile/internal/ssa/opt.go
index ea2bcf0e98..ea2bcf0e98 100644
--- a/src/cmd/internal/ssa/opt.go
+++ b/src/cmd/compile/internal/ssa/opt.go
diff --git a/src/cmd/internal/ssa/phielim.go b/src/cmd/compile/internal/ssa/phielim.go
index 19c0d077e5..19c0d077e5 100644
--- a/src/cmd/internal/ssa/phielim.go
+++ b/src/cmd/compile/internal/ssa/phielim.go
diff --git a/src/cmd/internal/ssa/print.go b/src/cmd/compile/internal/ssa/print.go
index eeea30d970..eeea30d970 100644
--- a/src/cmd/internal/ssa/print.go
+++ b/src/cmd/compile/internal/ssa/print.go
diff --git a/src/cmd/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index c798d2e936..c798d2e936 100644
--- a/src/cmd/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
diff --git a/src/cmd/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go
index 671270d7f2..671270d7f2 100644
--- a/src/cmd/internal/ssa/rewrite.go
+++ b/src/cmd/compile/internal/ssa/rewrite.go
diff --git a/src/cmd/internal/ssa/rulegen/generic.rules b/src/cmd/compile/internal/ssa/rulegen/generic.rules
index c49d9d9f2e..c49d9d9f2e 100644
--- a/src/cmd/internal/ssa/rulegen/generic.rules
+++ b/src/cmd/compile/internal/ssa/rulegen/generic.rules
diff --git a/src/cmd/internal/ssa/rulegen/lower_amd64.rules b/src/cmd/compile/internal/ssa/rulegen/lower_amd64.rules
index dc910b70b1..dc910b70b1 100644
--- a/src/cmd/internal/ssa/rulegen/lower_amd64.rules
+++ b/src/cmd/compile/internal/ssa/rulegen/lower_amd64.rules
diff --git a/src/cmd/internal/ssa/rulegen/rulegen.go b/src/cmd/compile/internal/ssa/rulegen/rulegen.go
index 4ac930298b..4ac930298b 100644
--- a/src/cmd/internal/ssa/rulegen/rulegen.go
+++ b/src/cmd/compile/internal/ssa/rulegen/rulegen.go
diff --git a/src/cmd/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go
index 0a89ac3773..0a89ac3773 100644
--- a/src/cmd/internal/ssa/schedule.go
+++ b/src/cmd/compile/internal/ssa/schedule.go
diff --git a/src/cmd/internal/ssa/sparseset.go b/src/cmd/compile/internal/ssa/sparseset.go
index b79aee8497..b79aee8497 100644
--- a/src/cmd/internal/ssa/sparseset.go
+++ b/src/cmd/compile/internal/ssa/sparseset.go
diff --git a/src/cmd/internal/ssa/stackalloc.go b/src/cmd/compile/internal/ssa/stackalloc.go
index ab686470be..ab686470be 100644
--- a/src/cmd/internal/ssa/stackalloc.go
+++ b/src/cmd/compile/internal/ssa/stackalloc.go
diff --git a/src/cmd/internal/ssa/type.go b/src/cmd/compile/internal/ssa/type.go
index 611c85834a..611c85834a 100644
--- a/src/cmd/internal/ssa/type.go
+++ b/src/cmd/compile/internal/ssa/type.go
diff --git a/src/cmd/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go
index dab6239dee..dab6239dee 100644
--- a/src/cmd/internal/ssa/value.go
+++ b/src/cmd/compile/internal/ssa/value.go
diff --git a/src/cmd/8g/cgen.go b/src/cmd/compile/internal/x86/cgen.go
index dfbdafefe3..1768674e42 100644
--- a/src/cmd/8g/cgen.go
+++ b/src/cmd/compile/internal/x86/cgen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package x86
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
@@ -17,7 +17,7 @@ import (
*/
func igenindex(n *gc.Node, res *gc.Node, bounded bool) *obj.Prog {
if !gc.Is64(n.Type) {
- if n.Addable {
+ if n.Addable && (gc.Simtype[n.Etype] == gc.TUINT32 || gc.Simtype[n.Etype] == gc.TINT32) {
// nothing to do.
*res = *n
} else {
diff --git a/src/cmd/8g/cgen64.go b/src/cmd/compile/internal/x86/cgen64.go
index a682e2fb44..0b061ffb60 100644
--- a/src/cmd/8g/cgen64.go
+++ b/src/cmd/compile/internal/x86/cgen64.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package x86
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
@@ -162,7 +162,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
// shld hi:lo, c
// shld lo:t, c
case gc.OLROT:
- v := uint64(gc.Mpgetfix(r.Val.U.Xval))
+ v := uint64(r.Int())
if v >= 32 {
// reverse during load to do the first 32 bits of rotate
@@ -189,7 +189,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
case gc.OLSH:
if r.Op == gc.OLITERAL {
- v := uint64(gc.Mpgetfix(r.Val.U.Xval))
+ v := uint64(r.Int())
if v >= 64 {
if gc.Is64(r.Type) {
splitclean()
@@ -278,7 +278,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
case gc.ORSH:
if r.Op == gc.OLITERAL {
- v := uint64(gc.Mpgetfix(r.Val.U.Xval))
+ v := uint64(r.Int())
if v >= 64 {
if gc.Is64(r.Type) {
splitclean()
@@ -400,9 +400,8 @@ func cgen64(n *gc.Node, res *gc.Node) {
if lo2.Op == gc.OLITERAL {
// special cases for constants.
- lv := uint32(gc.Mpgetfix(lo2.Val.U.Xval))
-
- hv := uint32(gc.Mpgetfix(hi2.Val.U.Xval))
+ lv := uint32(lo2.Int())
+ hv := uint32(hi2.Int())
splitclean() // right side
split64(res, &lo2, &hi2)
switch n.Op {
diff --git a/src/cmd/8g/galign.go b/src/cmd/compile/internal/x86/galign.go
index e96b628dcc..2b602e1bb3 100644
--- a/src/cmd/8g/galign.go
+++ b/src/cmd/compile/internal/x86/galign.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package x86
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
"fmt"
@@ -39,7 +39,7 @@ func betypeinit() {
gc.Widthreg = 4
}
-func main() {
+func Main() {
gc.Thearch.Thechar = thechar
gc.Thearch.Thestring = thestring
gc.Thearch.Thelinkarch = thelinkarch
@@ -81,6 +81,7 @@ func main() {
gc.Thearch.Expandchecks = expandchecks
gc.Thearch.Getg = getg
gc.Thearch.Gins = gins
+ gc.Thearch.Ginscmp = ginscmp
gc.Thearch.Ginscon = ginscon
gc.Thearch.Ginsnop = ginsnop
gc.Thearch.Gmove = gmove
diff --git a/src/cmd/8g/ggen.go b/src/cmd/compile/internal/x86/ggen.go
index 59025525fa..dabc139f30 100644
--- a/src/cmd/8g/ggen.go
+++ b/src/cmd/compile/internal/x86/ggen.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package x86
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
@@ -30,7 +30,7 @@ func defframe(ptxt *obj.Prog) {
ax := uint32(0)
for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
n = l.N
- if !n.Needzero {
+ if !n.Name.Needzero {
continue
}
if n.Class != gc.PAUTO {
@@ -216,9 +216,9 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.N
check := 0
if gc.Issigned[t.Etype] {
check = 1
- if gc.Isconst(nl, gc.CTINT) && gc.Mpgetfix(nl.Val.U.Xval) != -1<<uint64(t.Width*8-1) {
+ if gc.Isconst(nl, gc.CTINT) && nl.Int() != -1<<uint64(t.Width*8-1) {
check = 0
- } else if gc.Isconst(nr, gc.CTINT) && gc.Mpgetfix(nr.Val.U.Xval) != -1 {
+ } else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
check = 0
}
}
@@ -391,7 +391,7 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
var n1 gc.Node
gc.Regalloc(&n1, nl.Type, res)
gmove(&n2, &n1)
- sc := uint64(gc.Mpgetfix(nr.Val.U.Xval))
+ sc := uint64(nr.Int())
if sc >= uint64(nl.Type.Width*8) {
// large shift gets 2 shifts by width-1
gins(a, ncon(uint32(w)-1), &n1)
diff --git a/src/cmd/8g/gsubr.go b/src/cmd/compile/internal/x86/gsubr.go
index 34ddfe0619..baf251781c 100644
--- a/src/cmd/8g/gsubr.go
+++ b/src/cmd/compile/internal/x86/gsubr.go
@@ -28,10 +28,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package x86
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/big"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
"fmt"
@@ -582,6 +583,45 @@ func ginscon(as int, c int64, n2 *gc.Node) {
gins(as, &n1, n2)
}
+func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+ if gc.Isint[t.Etype] || int(t.Etype) == gc.Tptr {
+ if (n1.Op == gc.OLITERAL || n1.Op == gc.OADDR && n1.Left.Op == gc.ONAME) && n2.Op != gc.OLITERAL {
+ // Reverse comparison to place constant (including address constant) last.
+ op = gc.Brrev(op)
+ n1, n2 = n2, n1
+ }
+ }
+
+ // General case.
+ var r1, r2, g1, g2 gc.Node
+ if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
+ r1 = *n1
+ } else {
+ gc.Regalloc(&r1, t, n1)
+ gc.Regalloc(&g1, n1.Type, &r1)
+ gc.Cgen(n1, &g1)
+ gmove(&g1, &r1)
+ }
+ if n2.Op == gc.OLITERAL && gc.Isint[t.Etype] || n2.Op == gc.OADDR && n2.Left.Op == gc.ONAME && n2.Left.Class == gc.PEXTERN {
+ r2 = *n2
+ } else {
+ gc.Regalloc(&r2, t, n2)
+ gc.Regalloc(&g2, n1.Type, &r2)
+ gc.Cgen(n2, &g2)
+ gmove(&g2, &r2)
+ }
+ gins(optoas(gc.OCMP, t), &r1, &r2)
+ if r1.Op == gc.OREGISTER {
+ gc.Regfree(&g1)
+ gc.Regfree(&r1)
+ }
+ if r2.Op == gc.OREGISTER {
+ gc.Regfree(&g2)
+ gc.Regfree(&r2)
+ }
+ return gc.Gbranch(optoas(op, t), nil, likely)
+}
+
/*
* swap node contents
*/
@@ -602,7 +642,7 @@ func ncon(i uint32) *gc.Node {
if ncon_n.Type == nil {
gc.Nodconst(&ncon_n, gc.Types[gc.TUINT32], 0)
}
- gc.Mpmovecfix(ncon_n.Val.U.Xval, int64(i))
+ ncon_n.SetInt(int64(i))
return &ncon_n
}
@@ -638,7 +678,7 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
case gc.ONAME:
if n.Class == gc.PPARAMREF {
var n1 gc.Node
- gc.Cgen(n.Heapaddr, &n1)
+ gc.Cgen(n.Name.Heapaddr, &n1)
sclean[nsclean-1] = n1
n = &n1
}
@@ -660,8 +700,8 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
case gc.OLITERAL:
var n1 gc.Node
- gc.Convconst(&n1, n.Type, &n.Val)
- i := gc.Mpgetfix(n1.Val.U.Xval)
+ n.Convconst(&n1, n.Type)
+ i := n1.Int()
gc.Nodconst(lo, gc.Types[gc.TUINT32], int64(uint32(i)))
i >>= 32
if n.Type.Etype == gc.TINT64 {
@@ -682,36 +722,36 @@ func splitclean() {
}
}
-/*
- * set up nodes representing fp constants
- */
-var zerof gc.Node
-
-var two64f gc.Node
-
-var two63f gc.Node
-
-var bignodes_did int
+// set up nodes representing fp constants
+var (
+ zerof gc.Node
+ two63f gc.Node
+ two64f gc.Node
+ bignodes_did bool
+)
func bignodes() {
- if bignodes_did != 0 {
+ if bignodes_did {
return
}
- bignodes_did = 1
+ bignodes_did = true
+
+ gc.Nodconst(&zerof, gc.Types[gc.TINT64], 0)
+ zerof.Convconst(&zerof, gc.Types[gc.TFLOAT64])
- two64f = *ncon(0)
- two64f.Type = gc.Types[gc.TFLOAT64]
- two64f.Val.Ctype = gc.CTFLT
- two64f.Val.U.Fval = new(gc.Mpflt)
- gc.Mpmovecflt(two64f.Val.U.Fval, 18446744073709551616.)
+ var i big.Int
+ i.SetInt64(1)
+ i.Lsh(&i, 63)
+ var bigi gc.Node
- two63f = two64f
- two63f.Val.U.Fval = new(gc.Mpflt)
- gc.Mpmovecflt(two63f.Val.U.Fval, 9223372036854775808.)
+ gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
+ bigi.SetBigInt(&i)
+ bigi.Convconst(&two63f, gc.Types[gc.TFLOAT64])
- zerof = two64f
- zerof.Val.U.Fval = new(gc.Mpflt)
- gc.Mpmovecflt(zerof.Val.U.Fval, 0)
+ gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
+ i.Lsh(&i, 1)
+ bigi.SetBigInt(&i)
+ bigi.Convconst(&two64f, gc.Types[gc.TFLOAT64])
}
func memname(n *gc.Node, t *gc.Type) {
@@ -750,7 +790,7 @@ func gmove(f *gc.Node, t *gc.Node) {
// convert constant to desired type
if f.Op == gc.OLITERAL {
var con gc.Node
- gc.Convconst(&con, t.Type, &f.Val)
+ f.Convconst(&con, t.Type)
f = &con
ft = gc.Simsimtype(con.Type)
}
@@ -1021,7 +1061,7 @@ func floatmove(f *gc.Node, t *gc.Node) {
// convert constant to desired type
if f.Op == gc.OLITERAL {
var con gc.Node
- gc.Convconst(&con, t.Type, &f.Val)
+ f.Convconst(&con, t.Type)
f = &con
ft = gc.Simsimtype(con.Type)
diff --git a/src/cmd/8g/peep.go b/src/cmd/compile/internal/x86/peep.go
index e309aea785..8b50eab077 100644
--- a/src/cmd/8g/peep.go
+++ b/src/cmd/compile/internal/x86/peep.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package x86
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
"fmt"
diff --git a/src/cmd/8g/prog.go b/src/cmd/compile/internal/x86/prog.go
index 1346c20f2b..f96a1aa945 100644
--- a/src/cmd/8g/prog.go
+++ b/src/cmd/compile/internal/x86/prog.go
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package x86
import (
- "cmd/internal/gc"
+ "cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/x86"
)
diff --git a/src/cmd/8g/reg.go b/src/cmd/compile/internal/x86/reg.go
index 50b5b97ab1..8c97171e47 100644
--- a/src/cmd/8g/reg.go
+++ b/src/cmd/compile/internal/x86/reg.go
@@ -28,10 +28,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package x86
import "cmd/internal/obj/x86"
-import "cmd/internal/gc"
+import "cmd/compile/internal/gc"
const (
NREGVAR = 16 /* 8 integer + 8 floating */
diff --git a/src/cmd/compile/main.go b/src/cmd/compile/main.go
new file mode 100644
index 0000000000..7b69c34424
--- /dev/null
+++ b/src/cmd/compile/main.go
@@ -0,0 +1,34 @@
+// Copyright 2015 The Go 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 (
+ "cmd/compile/internal/amd64"
+ "cmd/compile/internal/arm"
+ "cmd/compile/internal/arm64"
+ "cmd/compile/internal/ppc64"
+ "cmd/compile/internal/x86"
+ "cmd/internal/obj"
+ "fmt"
+ "os"
+)
+
+func main() {
+ switch obj.Getgoarch() {
+ default:
+ fmt.Fprintf(os.Stderr, "compile: unknown architecture %q\n", obj.Getgoarch())
+ os.Exit(2)
+ case "386":
+ x86.Main()
+ case "amd64", "amd64p32":
+ amd64.Main()
+ case "arm":
+ arm.Main()
+ case "arm64":
+ arm64.Main()
+ case "ppc64", "ppc64le":
+ ppc64.Main()
+ }
+}
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index 64b2399972..0cdb7d69f7 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -20,7 +20,6 @@ var (
goarch string
gobin string
gohostarch string
- gohostchar string
gohostos string
goos string
goarm string
@@ -30,10 +29,8 @@ var (
goextlinkenabled string
workdir string
tooldir string
- gochar string
oldgoos string
oldgoarch string
- oldgochar string
slash string
exe string
defaultcc string
@@ -48,17 +45,13 @@ var (
vflag int // verbosity
)
-// The known architecture letters.
-var gochars = "5667899"
-
// The known architectures.
var okgoarch = []string{
- // same order as gochars
- "arm",
+ "386",
"amd64",
"amd64p32",
+ "arm",
"arm64",
- "386",
"ppc64",
"ppc64le",
}
@@ -147,22 +140,18 @@ func xinit() {
gohostarch = b
}
- i := find(gohostarch, okgoarch)
- if i < 0 {
+ if find(gohostarch, okgoarch) < 0 {
fatal("unknown $GOHOSTARCH %s", gohostarch)
}
- gohostchar = gochars[i : i+1]
b = os.Getenv("GOARCH")
if b == "" {
b = gohostarch
}
goarch = b
- i = find(goarch, okgoarch)
- if i < 0 {
+ if find(goarch, okgoarch) < 0 {
fatal("unknown $GOARCH %s", goarch)
}
- gochar = gochars[i : i+1]
b = os.Getenv("GO_EXTLINK_ENABLED")
if b != "" {
@@ -374,7 +363,7 @@ var oldtool = []string{
// Unreleased directories (relative to $GOROOT) that should
// not be in release branches.
var unreleased = []string{
- "src/cmd/link",
+ "src/cmd/newlink",
"src/cmd/objwriter",
"src/debug/goobj",
"src/old",
@@ -436,7 +425,7 @@ func setup() {
}
// If $GOBIN is set and has a Go compiler, it must be cleaned.
- for _, char := range gochars {
+ for _, char := range "56789" {
if isfile(pathf("%s%s%c%s", gobin, slash, char, "g")) {
for _, old := range oldtool {
xremove(pathf("%s/%s", gobin, old))
@@ -540,7 +529,7 @@ func install(dir string) {
if elem == "go" {
elem = "go_bootstrap"
}
- link = []string{fmt.Sprintf("%s/%sl", tooldir, gochar), "-o", pathf("%s/%s%s", tooldir, elem, exe)}
+ link = []string{pathf("%s/link", tooldir), "-o", pathf("%s/%s%s", tooldir, elem, exe)}
targ = len(link) - 1
}
ttarg := mtime(link[targ])
@@ -675,7 +664,7 @@ func install(dir string) {
} else {
archive = b
}
- compile := []string{pathf("%s/%sg", tooldir, gochar), "-pack", "-o", b, "-p", pkg}
+ compile := []string{pathf("%s/compile", tooldir), "-pack", "-o", b, "-p", pkg}
if dir == "runtime" {
compile = append(compile, "-+", "-asmhdr", pathf("%s/go_asm.h", workdir))
}
@@ -703,11 +692,7 @@ func install(dir string) {
b := pathf("%s/%s", workdir, filepath.Base(p))
// Change the last character of the output file (which was c or s).
- if gohostos == "plan9" {
- b = b[:len(b)-1] + gohostchar
- } else {
- b = b[:len(b)-1] + "o"
- }
+ b = b[:len(b)-1] + "o"
compile = append(compile, "-o", b, p)
bgrun(path, compile...)
@@ -897,17 +882,9 @@ var buildorder = []string{
// compilers but build only the $GOARCH ones.
var cleantab = []string{
// Commands and C libraries.
- "cmd/5g",
- "cmd/5l",
- "cmd/6g",
- "cmd/6l",
- "cmd/7g",
- "cmd/7l",
- "cmd/8g",
- "cmd/8l",
- "cmd/9g",
- "cmd/9l",
+ "cmd/compile",
"cmd/go",
+ "cmd/link",
"cmd/old5a",
"cmd/old6a",
"cmd/old8a",
@@ -1043,7 +1020,6 @@ func cmdenv() {
xprintf(format, "GOHOSTARCH", gohostarch)
xprintf(format, "GOHOSTOS", gohostos)
xprintf(format, "GOTOOLDIR", tooldir)
- xprintf(format, "GOCHAR", gochar)
if goarch == "arm" {
xprintf(format, "GOARM", goarm)
}
@@ -1088,10 +1064,8 @@ func cmdbootstrap() {
// For the main bootstrap, building for host os/arch.
oldgoos = goos
oldgoarch = goarch
- oldgochar = gochar
goos = gohostos
goarch = gohostarch
- gochar = gohostchar
os.Setenv("GOHOSTARCH", gohostarch)
os.Setenv("GOHOSTOS", gohostos)
os.Setenv("GOARCH", goarch)
@@ -1105,37 +1079,22 @@ func cmdbootstrap() {
// than in a standard release like Go 1.4, so don't do this rebuild by default.
if false {
xprintf("##### Building Go toolchain using itself.\n")
- for _, pattern := range buildorder {
- if pattern == "cmd/go" {
+ for _, dir := range buildorder {
+ if dir == "cmd/go" {
break
}
- dir := pattern
- if strings.Contains(pattern, "%s") {
- dir = fmt.Sprintf(pattern, gohostchar)
- }
install(dir)
- if oldgochar != gohostchar && strings.Contains(pattern, "%s") {
- install(fmt.Sprintf(pattern, oldgochar))
- }
}
xprintf("\n")
}
xprintf("##### Building compilers and go_bootstrap for host, %s/%s.\n", gohostos, gohostarch)
- for _, pattern := range buildorder {
- dir := pattern
- if strings.Contains(pattern, "%s") {
- dir = fmt.Sprintf(pattern, gohostchar)
- }
+ for _, dir := range buildorder {
install(dir)
- if oldgochar != gohostchar && strings.Contains(pattern, "%s") {
- install(fmt.Sprintf(pattern, oldgochar))
- }
}
goos = oldgoos
goarch = oldgoarch
- gochar = oldgochar
os.Setenv("GOARCH", goarch)
os.Setenv("GOOS", goos)
diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
index f5037fab88..7988129868 100644
--- a/src/cmd/dist/buildtool.go
+++ b/src/cmd/dist/buildtool.go
@@ -23,31 +23,34 @@ import (
// which are commands, and entries beginning with internal/, which are
// packages supporting the commands.
var bootstrapDirs = []string{
- "5g",
- "5l",
- "6g",
- "6l",
- "7g",
- "7l",
- "8g",
- "8l",
- "9g",
- "9l",
"asm",
"asm/internal/arch",
"asm/internal/asm",
"asm/internal/flags",
"asm/internal/lex",
+ "compile",
+ "compile/internal/amd64",
+ "compile/internal/arm",
+ "compile/internal/arm64",
+ "compile/internal/big",
+ "compile/internal/gc",
+ "compile/internal/ppc64",
+ "compile/internal/ssa",
+ "compile/internal/x86",
"internal/asm",
- "internal/gc/big",
- "internal/gc",
- "internal/ld",
+ "internal/gcprog",
"internal/obj",
"internal/obj/arm",
"internal/obj/arm64",
"internal/obj/ppc64",
"internal/obj/x86",
- "internal/ssa",
+ "link",
+ "link/internal/amd64",
+ "link/internal/arm",
+ "link/internal/arm64",
+ "link/internal/ld",
+ "link/internal/ppc64",
+ "link/internal/x86",
"old5a",
"old6a",
"old8a",
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
index 1ed099583e..f5a0dc50f1 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -14,6 +14,7 @@ import (
"os/exec"
"path/filepath"
"regexp"
+ "runtime"
"strconv"
"strings"
"time"
@@ -23,8 +24,11 @@ func cmdtest() {
var t tester
flag.BoolVar(&t.listMode, "list", false, "list available tests")
flag.BoolVar(&t.noRebuild, "no-rebuild", false, "don't rebuild std and cmd packages")
+ flag.BoolVar(&t.keepGoing, "k", false, "keep going even when error occurred")
flag.StringVar(&t.banner, "banner", "##### ", "banner prefix; blank means no section banners")
- flag.StringVar(&t.runRxStr, "run", "", "run only those tests matching the regular expression; empty means to run all")
+ flag.StringVar(&t.runRxStr, "run", os.Getenv("GOTESTONLY"),
+ "run only those tests matching the regular expression; empty means to run all. "+
+ "Special exception: if the string begins with '!', the match is inverted.")
xflagparse(0)
t.run()
}
@@ -33,8 +37,10 @@ func cmdtest() {
type tester struct {
listMode bool
noRebuild bool
+ keepGoing bool
runRxStr string
runRx *regexp.Regexp
+ runRxWant bool
banner string // prefix, or "" for none
goroot string
@@ -129,6 +135,19 @@ func (t *tester) run() {
}
if t.runRxStr != "" {
+ // Temporary (2015-05-14) special case for "std",
+ // which the plan9 builder was using for ages. Delete
+ // this once we update dashboard/builders.go to use a
+ // regexp instead.
+ if runtime.GOOS == "plan9" && t.runRxStr == "std" {
+ t.runRxStr = "^go_test:"
+ }
+ if t.runRxStr[0] == '!' {
+ t.runRxWant = false
+ t.runRxStr = t.runRxStr[1:]
+ } else {
+ t.runRxWant = true
+ }
t.runRx = regexp.MustCompile(t.runRxStr)
}
@@ -146,8 +165,9 @@ func (t *tester) run() {
os.Unsetenv("GOROOT_FINAL")
var lastHeading string
+ ok := true
for _, dt := range t.tests {
- if t.runRx != nil && !t.runRx.MatchString(dt.name) {
+ if t.runRx != nil && (t.runRx.MatchString(dt.name) != t.runRxWant) {
t.partial = true
continue
}
@@ -159,10 +179,18 @@ func (t *tester) run() {
fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
}
if err := dt.fn(); err != nil {
- log.Fatalf("Failed: %v", err)
+ ok = false
+ if t.keepGoing {
+ log.Printf("Failed: %v", err)
+ } else {
+ log.Fatalf("Failed: %v", err)
+ }
}
}
- if t.partial {
+ if !ok {
+ fmt.Println("\nFAILED")
+ os.Exit(1)
+ } else if t.partial {
fmt.Println("\nALL TESTS PASSED (some were excluded)")
} else {
fmt.Println("\nALL TESTS PASSED")
@@ -173,52 +201,71 @@ func (t *tester) timeout(sec int) string {
return "-timeout=" + fmt.Sprint(time.Duration(sec)*time.Second*time.Duration(t.timeoutScale))
}
-func (t *tester) registerTests() {
- // Register a separate logical test for each package in the standard library
- // but actually group them together at execution time to share the cost of
- // building packages shared between them.
- all, err := exec.Command("go", "list", "std", "cmd").Output()
- if err != nil {
- log.Fatalf("Error running go list std cmd: %v", err)
+// ranGoTest and stdMatches are state closed over by the stdlib
+// testing func in registerStdTest below. The tests are run
+// sequentially, so there's no need for locks.
+var (
+ ranGoTest bool
+ stdMatches []string
+)
+
+func (t *tester) registerStdTest(pkg string) {
+ testName := "go_test:" + pkg
+ if t.runRx == nil || t.runRx.MatchString(testName) {
+ stdMatches = append(stdMatches, pkg)
+ }
+ t.tests = append(t.tests, distTest{
+ name: testName,
+ heading: "Testing packages.",
+ fn: func() error {
+ if ranGoTest {
+ return nil
+ }
+ ranGoTest = true
+ cmd := exec.Command("go", append([]string{
+ "test",
+ "-short",
+ t.timeout(120),
+ "-gcflags=" + os.Getenv("GO_GCFLAGS"),
+ }, stdMatches...)...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+ },
+ })
+}
+
+// validStdPkg reports whether pkg looks like a standard library package name.
+// Notably, it's not blank and doesn't contain regexp characters.
+func validStdPkg(pkg string) bool {
+ if pkg == "" {
+ return false
}
- // ranGoTest and stdMatches are state closed over by the
- // stdlib testing func below. The tests are run sequentially,
- // so there's no need for locks.
- var (
- ranGoTest bool
- stdMatches []string
- )
- for _, pkg := range strings.Fields(string(all)) {
- testName := "go_test:" + pkg
- if t.runRx == nil || t.runRx.MatchString(testName) {
- stdMatches = append(stdMatches, pkg)
+ for _, r := range pkg {
+ switch {
+ case 'a' <= r && r <= 'z':
+ case 'A' <= r && r <= 'Z':
+ case '0' <= r && r <= '9':
+ case r == '_':
+ case r == '/':
+ default:
+ return false
}
- t.tests = append(t.tests, distTest{
- name: testName,
- heading: "Testing packages.",
- fn: func() error {
- if ranGoTest {
- return nil
- }
- ranGoTest = true
- cmd := exec.Command("go", append([]string{
- "test",
- "-short",
- t.timeout(120),
- "-gcflags=" + os.Getenv("GO_GCFLAGS"),
- }, stdMatches...)...)
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- return cmd.Run()
- },
- })
}
+ return true
+}
- // Old hack for when Plan 9 on GCE was too slow.
- // We're keeping this until test sharding (Issue 10029) is finished, though.
- if os.Getenv("GOTESTONLY") == "std" {
- t.partial = true
- return
+func (t *tester) registerTests() {
+ // Fast path to avoid the ~1 second of `go list std cmd` when
+ // the caller passed -run=^go_test:foo/bar$ (as the continuous
+ // build coordinator does).
+ if strings.HasPrefix(t.runRxStr, "^go_test:") && strings.HasSuffix(t.runRxStr, "$") {
+ pkg := strings.TrimPrefix(t.runRxStr, "^go_test:")
+ pkg = strings.TrimSuffix(pkg, "$")
+ if validStdPkg(pkg) {
+ t.registerStdTest(pkg)
+ return
+ }
}
// Runtime CPU tests.
@@ -244,9 +291,7 @@ func (t *tester) registerTests() {
},
})
- iOS := t.goos == "darwin" && (t.goarch == "arm" || t.goarch == "arm64")
-
- if t.cgoEnabled && t.goos != "android" && !iOS {
+ if t.cgoEnabled && t.goos != "android" && !t.iOS() {
// Disabled on android and iOS. golang.org/issue/8345
t.tests = append(t.tests, distTest{
name: "cgo_stdio",
@@ -265,7 +310,7 @@ func (t *tester) registerTests() {
},
})
}
- if t.cgoEnabled && t.goos != "android" && !iOS {
+ if t.cgoEnabled && t.goos != "android" && !t.iOS() {
// TODO(crawshaw): reenable on android and iOS
// golang.org/issue/8345
//
@@ -295,7 +340,7 @@ func (t *tester) registerTests() {
heading: "../misc/cgo/testso",
fn: t.cgoTestSOWindows,
})
- } else if t.hasBash() && t.goos != "android" && !iOS {
+ } else if t.hasBash() && t.goos != "android" && !t.iOS() {
t.registerTest("testso", "../misc/cgo/testso", "./test.bash")
}
if t.supportedBuildmode("c-archive") {
@@ -305,28 +350,28 @@ func (t *tester) registerTests() {
t.registerTest("testcshared", "../misc/cgo/testcshared", "./test.bash")
}
if t.supportedBuildmode("shared") {
- t.registerTest("testshared", "../misc/cgo/testshared", "./test.bash")
+ t.registerTest("testshared", "../misc/cgo/testshared", "go", "test")
}
if t.gohostos == "linux" && t.goarch == "amd64" {
t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", "main.go")
}
- if t.hasBash() && t.goos != "android" && !iOS && t.gohostos != "windows" {
+ if t.hasBash() && t.goos != "android" && !t.iOS() && t.gohostos != "windows" {
t.registerTest("cgo_errors", "../misc/cgo/errors", "./test.bash")
}
if t.gohostos == "linux" && t.extLink() {
t.registerTest("testsigfwd", "../misc/cgo/testsigfwd", "go", "run", "main.go")
}
}
- if t.hasBash() && t.goos != "nacl" && t.goos != "android" && !iOS {
+ if t.hasBash() && t.goos != "nacl" && t.goos != "android" && !t.iOS() {
t.registerTest("doc_progs", "../doc/progs", "time", "go", "run", "run.go")
t.registerTest("wiki", "../doc/articles/wiki", "./test.bash")
t.registerTest("codewalk", "../doc/codewalk", "time", "./run")
t.registerTest("shootout", "../test/bench/shootout", "time", "./timing.sh", "-test")
}
- if t.goos != "android" && !iOS {
+ if t.goos != "android" && !t.iOS() {
t.registerTest("bench_go1", "../test/bench/go1", "go", "test")
}
- if t.goos != "android" && !iOS {
+ if t.goos != "android" && !t.iOS() {
// TODO(bradfitz): shard down into these tests, as
// this is one of the slowest (and most shardable)
// tests.
@@ -336,7 +381,7 @@ func (t *tester) registerTests() {
fn: t.testDirTest,
})
}
- if t.goos != "nacl" && t.goos != "android" && !iOS {
+ if t.goos != "nacl" && t.goos != "android" && !t.iOS() {
t.tests = append(t.tests, distTest{
name: "api",
heading: "API check",
@@ -346,6 +391,44 @@ func (t *tester) registerTests() {
})
}
+ // Register the standard library tests lasts, to avoid the ~1 second latency
+ // of running `go list std cmd` if we're running a specific test.
+ // Now we know the names of all the other tests registered so far.
+ if !t.wantSpecificRegisteredTest() {
+ all, err := exec.Command("go", "list", "std", "cmd").Output()
+ if err != nil {
+ log.Fatalf("Error running go list std cmd: %v", err)
+ }
+ // Put the standard library tests first.
+ orig := t.tests
+ t.tests = nil
+ for _, pkg := range strings.Fields(string(all)) {
+ t.registerStdTest(pkg)
+ }
+ t.tests = append(t.tests, orig...)
+ }
+}
+
+// wantSpecificRegisteredTest reports whether the caller is requesting a
+// run of a specific test via the flag -run=^TESTNAME$ (as is done by the
+// continuous build coordinator).
+func (t *tester) wantSpecificRegisteredTest() bool {
+ if !strings.HasPrefix(t.runRxStr, "^") || !strings.HasSuffix(t.runRxStr, "$") {
+ return false
+ }
+ test := t.runRxStr[1 : len(t.runRxStr)-1]
+ return t.isRegisteredTestName(test)
+}
+
+// isRegisteredTestName reports whether a test named testName has already
+// been registered.
+func (t *tester) isRegisteredTestName(testName string) bool {
+ for _, tt := range t.tests {
+ if tt.name == testName {
+ return true
+ }
+ }
+ return false
}
func (t *tester) registerTest(name, dirBanner, bin string, args ...string) {
diff --git a/src/cmd/doc/main.go b/src/cmd/doc/main.go
index b3be2a975b..18dafc298c 100644
--- a/src/cmd/doc/main.go
+++ b/src/cmd/doc/main.go
@@ -132,11 +132,12 @@ func parseArgs() (*build.Package, string, string) {
// slash+1: if there's no slash, the value is -1 and start is 0; otherwise
// start is the byte after the slash.
for start := slash + 1; start < len(arg); start = period + 1 {
- period = start + strings.Index(arg[start:], ".")
+ period = strings.Index(arg[start:], ".")
symbol := ""
if period < 0 {
period = len(arg)
} else {
+ period += start
symbol = arg[period+1:]
}
// Have we identified a package already?
diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go
index 3a0aa7ff89..5c8976b663 100644
--- a/src/cmd/doc/pkg.go
+++ b/src/cmd/doc/pkg.go
@@ -115,7 +115,7 @@ func (pkg *Package) emit(comment string, node ast.Node) {
log.Fatal(err)
}
if comment != "" {
- pkg.newlines(1)
+ pkg.newlines(2) // Guarantee blank line before comment.
doc.ToText(&pkg.buf, comment, " ", "\t", 80)
}
pkg.newlines(1)
@@ -190,6 +190,7 @@ func (pkg *Package) packageDoc() {
pkg.valueSummary(pkg.doc.Vars)
pkg.funcSummary(pkg.doc.Funcs)
pkg.typeSummary()
+ pkg.bugs()
}
// packageClause prints the package clause.
@@ -253,6 +254,18 @@ func (pkg *Package) typeSummary() {
}
}
+// bugs prints the BUGS information for the package.
+// TODO: Provide access to TODOs and NOTEs as well (very noisy so off by default)?
+func (pkg *Package) bugs() {
+ if pkg.doc.Notes["BUG"] == nil {
+ return
+ }
+ pkg.Printf("\n")
+ for _, note := range pkg.doc.Notes["BUG"] {
+ pkg.Printf("%s: %v\n", "BUG", note.Body)
+ }
+}
+
// findValues finds the doc.Values that describe the symbol.
func (pkg *Package) findValues(symbol string, docValues []*doc.Value) (values []*doc.Value) {
for _, value := range docValues {
@@ -332,13 +345,16 @@ func (pkg *Package) symbolDoc(symbol string) {
}
decl := typ.Decl
spec := pkg.findTypeSpec(decl, typ.Name)
- trimUnexportedFields(spec)
+ trimUnexportedElems(spec)
// If there are multiple types defined, reduce to just this one.
if len(decl.Specs) > 1 {
decl.Specs = []ast.Spec{spec}
}
pkg.emit(typ.Doc, decl)
// Show associated methods, constants, etc.
+ if len(typ.Consts) > 0 || len(typ.Vars) > 0 || len(typ.Funcs) > 0 || len(typ.Methods) > 0 {
+ pkg.Printf("\n")
+ }
pkg.valueSummary(typ.Consts)
pkg.valueSummary(typ.Vars)
pkg.funcSummary(typ.Funcs)
@@ -353,22 +369,26 @@ func (pkg *Package) symbolDoc(symbol string) {
}
}
-// trimUnexportedFields modifies spec in place to elide unexported fields (unless
-// the unexported flag is set). If spec is not a structure declartion, nothing happens.
-func trimUnexportedFields(spec *ast.TypeSpec) {
+// trimUnexportedElems modifies spec in place to elide unexported fields from
+// structs and methods from interfaces (unless the unexported flag is set).
+func trimUnexportedElems(spec *ast.TypeSpec) {
if *unexported {
- // We're printing all fields.
return
}
- // It must be a struct for us to care. (We show unexported methods in interfaces.)
- structType, ok := spec.Type.(*ast.StructType)
- if !ok {
- return
+ switch typ := spec.Type.(type) {
+ case *ast.StructType:
+ typ.Fields = trimUnexportedFields(typ.Fields, "fields")
+ case *ast.InterfaceType:
+ typ.Methods = trimUnexportedFields(typ.Methods, "methods")
}
+}
+
+// trimUnexportedFields returns the field list trimmed of unexported fields.
+func trimUnexportedFields(fields *ast.FieldList, what string) *ast.FieldList {
trimmed := false
- list := make([]*ast.Field, 0, len(structType.Fields.List))
- for _, field := range structType.Fields.List {
- // Trims if any is unexported. Fine in practice.
+ list := make([]*ast.Field, 0, len(fields.List))
+ for _, field := range fields.List {
+ // Trims if any is unexported. Good enough in practice.
ok := true
for _, name := range field.Names {
if !isExported(name.Name) {
@@ -381,19 +401,23 @@ func trimUnexportedFields(spec *ast.TypeSpec) {
list = append(list, field)
}
}
- if trimmed {
- unexportedField := &ast.Field{
- Type: ast.NewIdent(""), // Hack: printer will treat this as a field with a named type.
- Comment: &ast.CommentGroup{
- List: []*ast.Comment{
- &ast.Comment{
- Text: "// Has unexported fields.\n",
- },
+ if !trimmed {
+ return fields
+ }
+ unexportedField := &ast.Field{
+ Type: ast.NewIdent(""), // Hack: printer will treat this as a field with a named type.
+ Comment: &ast.CommentGroup{
+ List: []*ast.Comment{
+ &ast.Comment{
+ Text: fmt.Sprintf("// Has unexported %s.\n", what),
},
},
- }
- list = append(list, unexportedField)
- structType.Fields.List = list
+ },
+ }
+ return &ast.FieldList{
+ Opening: fields.Opening,
+ List: append(list, unexportedField),
+ Closing: fields.Closing,
}
}
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index e0d4a6c0fe..2b1cbf98ec 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -503,6 +503,7 @@ syntax of package template. The default output is equivalent to -f
Name string // package name
Doc string // package documentation string
Target string // install path
+ Shlib string // the shared library that contains this package (only set when -linkshared)
Goroot bool // is this package in the Go root?
Standard bool // is this package part of the standard Go library?
Stale bool // would 'go install' do anything for this package?
@@ -1053,7 +1054,7 @@ environment variable (see 'go help gopath').
If no import paths are given, the action applies to the
package in the current directory.
-There are three reserved names for paths that should not be used
+There are four reserved names for paths that should not be used
for packages to be built with the go tool:
- "main" denotes the top-level package in a stand-alone executable.
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index fda126b008..17ff7e0cbb 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -547,9 +547,6 @@ var (
goarch string
goos string
exeSuffix string
-
- archCharVal string
- archCharErr error
)
func init() {
@@ -558,16 +555,6 @@ func init() {
if goos == "windows" {
exeSuffix = ".exe"
}
- archCharVal, archCharErr = build.ArchChar(goarch)
-}
-
-// archChar returns the architecture character. This is only needed
-// for the gc toolchain, so only fail if we actually need it.
-func archChar() string {
- if archCharErr != nil {
- fatalf("%s", archCharErr)
- }
- return archCharVal
}
// A builder holds global state about a build.
@@ -782,8 +769,8 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
b.actionCache[key] = a
return a
}
- pkgs := readpkglist(filepath.Join(p.build.PkgTargetRoot, shlib))
- a = b.libaction(shlib, pkgs, modeInstall, depMode)
+ pkgs := readpkglist(shlib)
+ a = b.libaction(filepath.Base(shlib), pkgs, modeInstall, depMode)
b.actionCache[key2] = a
b.actionCache[key] = a
return a
@@ -1208,7 +1195,7 @@ func (b *builder) build(a *action) (err error) {
fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
}
- if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" && archChar() != "" &&
+ if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" &&
(!hasString(a.p.GoFiles, "zgoos_"+buildContext.GOOS+".go") ||
!hasString(a.p.GoFiles, "zgoarch_"+buildContext.GOARCH+".go")) {
return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix())
@@ -1371,15 +1358,8 @@ func (b *builder) build(a *action) (err error) {
}
}
- var objExt string
- if _, ok := buildToolchain.(gccgoToolchain); ok {
- objExt = "o"
- } else {
- objExt = archChar()
- }
-
for _, file := range cfiles {
- out := file[:len(file)-len(".c")] + "." + objExt
+ out := file[:len(file)-len(".c")] + ".o"
if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil {
return err
}
@@ -1388,7 +1368,7 @@ func (b *builder) build(a *action) (err error) {
// Assemble .s files.
for _, file := range sfiles {
- out := file[:len(file)-len(".s")] + "." + objExt
+ out := file[:len(file)-len(".s")] + ".o"
if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil {
return err
}
@@ -1532,7 +1512,7 @@ func (b *builder) linkShared(a *action) (err error) {
}
ldflags = append(ldflags, d.p.ImportPath+"="+d.target)
}
- return b.run(".", a.target, nil, buildToolExec, tool(archChar()+"l"), "-o", a.target, importArgs, ldflags)
+ return b.run(".", a.target, nil, buildToolExec, tool("link"), "-o", a.target, importArgs, ldflags)
}
// install is the action for installing a single package or executable.
@@ -2109,18 +2089,18 @@ func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error
type gcToolchain struct{}
func (gcToolchain) compiler() string {
- return tool(archChar() + "g")
+ return tool("compile")
}
func (gcToolchain) linker() string {
- return tool(archChar() + "l")
+ return tool("link")
}
func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
if archive != "" {
ofile = archive
} else {
- out := "_go_." + archChar()
+ out := "_go_.o"
ofile = obj + out
}
@@ -2152,7 +2132,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix)
}
- args := []interface{}{buildToolExec, tool(archChar() + "g"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs}
+ args := []interface{}{buildToolExec, tool("compile"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs}
if ofile == archive {
args = append(args, "-pack")
}
@@ -2182,9 +2162,22 @@ func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
}
// Disable checks when additional flags are passed, as the old assemblers
// don't implement some of them (e.g., -shared).
- if verifyAsm && goarch != "arm64" && len(buildAsmflags) == 0 {
- if err := toolVerify(b, p, "old"+archChar()+"a", ofile, args); err != nil {
- return err
+ if verifyAsm && len(buildAsmflags) == 0 {
+ old := ""
+ switch goarch {
+ case "arm":
+ old = "old5a"
+ case "amd64", "amd64p32":
+ old = "old6a"
+ case "386":
+ old = "old8a"
+ case "ppc64", "ppc64le":
+ old = "old9a"
+ }
+ if old != "" {
+ if err := toolVerify(b, p, old, ofile, args); err != nil {
+ return err
+ }
}
}
return nil
@@ -2333,7 +2326,7 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action,
ldflags = setextld(ldflags, compiler)
ldflags = append(ldflags, "-buildmode="+ldBuildmode)
ldflags = append(ldflags, buildLdflags...)
- return b.run(".", p.ImportPath, nil, buildToolExec, tool(archChar()+"l"), "-o", out, importArgs, ldflags, mainpkg)
+ return b.run(".", p.ImportPath, nil, buildToolExec, tool("link"), "-o", out, importArgs, ldflags, mainpkg)
}
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
@@ -2785,13 +2778,6 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
cgoflags := []string{}
// TODO: make cgo not depend on $GOARCH?
- var objExt string
- if _, ok := buildToolchain.(gccgoToolchain); ok {
- objExt = "o"
- } else {
- objExt = archChar()
- }
-
if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = append(cgoflags, "-import_runtime_cgo=false")
}
@@ -2836,7 +2822,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
// cc _cgo_defun.c
_, gccgo := buildToolchain.(gccgoToolchain)
if gccgo {
- defunObj := obj + "_cgo_defun." + objExt
+ defunObj := obj + "_cgo_defun.o"
if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
return nil, nil, err
}
diff --git a/src/cmd/go/env.go b/src/cmd/go/env.go
index 863eb4d26e..8d427b37c2 100644
--- a/src/cmd/go/env.go
+++ b/src/cmd/go/env.go
@@ -49,10 +49,6 @@ func mkEnv() []envVar {
{"TERM", "dumb"},
}
- if archCharErr == nil {
- env = append(env, envVar{"GOCHAR", archChar()})
- }
-
if goos != "plan9" {
cmd := b.gccCmd(".")
env = append(env, envVar{"CC", cmd[0]})
diff --git a/src/cmd/go/fmt.go b/src/cmd/go/fmt.go
index 65dc3ca599..1722b9d568 100644
--- a/src/cmd/go/fmt.go
+++ b/src/cmd/go/fmt.go
@@ -4,6 +4,11 @@
package main
+import (
+ "os"
+ "path/filepath"
+)
+
func init() {
addBuildFlagsNX(cmdFmt)
}
@@ -29,10 +34,31 @@ See also: go fix, go vet.
}
func runFmt(cmd *Command, args []string) {
+ gofmt := gofmtPath()
for _, pkg := range packages(args) {
// Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package,
// not to packages in subdirectories.
- run(stringList("gofmt", "-l", "-w", relPaths(pkg.allgofiles)))
+ run(stringList(gofmt, "-l", "-w", relPaths(pkg.allgofiles)))
}
}
+
+func gofmtPath() string {
+ gofmt := "gofmt"
+ if toolIsWindows {
+ gofmt += toolWindowsExtension
+ }
+
+ gofmtPath := filepath.Join(gobin, gofmt)
+ if _, err := os.Stat(gofmtPath); err == nil {
+ return gofmtPath
+ }
+
+ gofmtPath = filepath.Join(goroot, "bin", gofmt)
+ if _, err := os.Stat(gofmtPath); err == nil {
+ return gofmtPath
+ }
+
+ // fallback to looking for gofmt in $PATH
+ return "gofmt"
+}
diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go
index 56e8493e1a..2062f0c4ee 100644
--- a/src/cmd/go/help.go
+++ b/src/cmd/go/help.go
@@ -47,7 +47,7 @@ environment variable (see 'go help gopath').
If no import paths are given, the action applies to the
package in the current directory.
-There are three reserved names for paths that should not be used
+There are four reserved names for paths that should not be used
for packages to be built with the go tool:
- "main" denotes the top-level package in a stand-alone executable.
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index 9466aad6a6..601c30362f 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -394,25 +394,17 @@ const (
// goTools is a map of Go program import path to install target directory.
var goTools = map[string]targetDir{
- "cmd/5g": toTool,
- "cmd/5l": toTool,
- "cmd/6g": toTool,
- "cmd/6l": toTool,
- "cmd/7g": toTool,
- "cmd/7l": toTool,
- "cmd/8g": toTool,
- "cmd/8l": toTool,
- "cmd/9g": toTool,
- "cmd/9l": toTool,
"cmd/addr2line": toTool,
"cmd/api": toTool,
"cmd/asm": toTool,
+ "cmd/compile": toTool,
"cmd/cgo": toTool,
"cmd/cover": toTool,
"cmd/dist": toTool,
"cmd/doc": toTool,
"cmd/fix": toTool,
"cmd/link": toTool,
+ "cmd/newlink": toTool,
"cmd/nm": toTool,
"cmd/objdump": toTool,
"cmd/old5a": toTool,
@@ -536,7 +528,8 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
shlibnamefile := p.target[:len(p.target)-2] + ".shlibname"
shlib, err := ioutil.ReadFile(shlibnamefile)
if err == nil {
- p.Shlib = strings.TrimSpace(string(shlib))
+ libname := strings.TrimSpace(string(shlib))
+ p.Shlib = filepath.Join(p.build.PkgTargetRoot, libname)
} else if !os.IsNotExist(err) {
fatalf("unexpected error reading %s: %v", shlibnamefile, err)
}
@@ -680,10 +673,10 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
p.Target = p.target
// The gc toolchain only permits C source files with cgo.
- if len(p.CFiles) > 0 && !p.usesCgo() && buildContext.Compiler == "gc" {
+ if len(p.CFiles) > 0 && !p.usesCgo() && !p.usesSwig() && buildContext.Compiler == "gc" {
p.Error = &PackageError{
ImportStack: stk.copy(),
- Err: fmt.Sprintf("C source files not allowed when not using cgo: %s", strings.Join(p.CFiles, " ")),
+ Err: fmt.Sprintf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " ")),
}
return p
}
diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
index 408104d776..2179000afd 100644
--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -115,8 +115,12 @@ var vcsGit = &vcsCmd{
tagLookupCmd: []tagCmd{
{"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`},
},
- tagSyncCmd: "checkout {tag}",
- tagSyncDefault: "checkout master",
+ tagSyncCmd: "checkout {tag}",
+ // both createCmd and downloadCmd update the working dir.
+ // No need to do more here. We used to 'checkout master'
+ // but that doesn't work if the default branch is not named master.
+ // See golang.org/issue/9032.
+ tagSyncDefault: "",
scheme: []string{"git", "https", "http", "git+ssh"},
pingCmd: "ls-remote {scheme}://{repo}",
diff --git a/src/cmd/internal/asm/lexbody.go b/src/cmd/internal/asm/lexbody.go
index b5e5d1eee2..a1519c8566 100644
--- a/src/cmd/internal/asm/lexbody.go
+++ b/src/cmd/internal/asm/lexbody.go
@@ -149,7 +149,7 @@ func newfile(s string, f *os.File) {
}
fi.P = nil
- obj.Linklinehist(Ctxt, int(Lineno), s, 0)
+ Ctxt.LineHist.Push(int(Lineno), s)
}
var thetext *obj.LSym
@@ -630,7 +630,7 @@ loop:
n, _ = i.F.Read(i.B[:])
if n == 0 {
i.F.Close()
- obj.Linklinehist(Ctxt, int(Lineno), "<pop>", 0)
+ Ctxt.LineHist.Pop(int(Lineno))
goto pop
}
fi.P = i.B[1:n]
diff --git a/src/cmd/internal/asm/macbody.go b/src/cmd/internal/asm/macbody.go
index c488ea1e56..4565d3a37f 100644
--- a/src/cmd/internal/asm/macbody.go
+++ b/src/cmd/internal/asm/macbody.go
@@ -32,7 +32,6 @@ package asm
import (
"bytes"
- "cmd/internal/obj"
"fmt"
"os"
"strings"
@@ -683,7 +682,7 @@ func maclin() {
}
nn:
- obj.Linklinehist(Ctxt, int(Lineno), symb, int(n))
+ Ctxt.LineHist.Update(int(Lineno), symb, int(n))
return
bad:
@@ -796,7 +795,7 @@ func macprag() {
/*
* put pragma-line in as a funny history
*/
- obj.Linklinehist(Ctxt, int(Lineno), symb, -1)
+ Ctxt.AddImport(symb)
return
}
if s != nil && s.Name == "pack" {
diff --git a/src/cmd/internal/gc/go.errors b/src/cmd/internal/gc/go.errors
deleted file mode 100644
index 8370a2007d..0000000000
--- a/src/cmd/internal/gc/go.errors
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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.
-
-// Example-based syntax error messages.
-// See yaccerrors.go.
-
-package gc
-
-var yymsg = []struct {
- yystate int
- yychar int
- msg string
-}{
- // Each line of the form % token list
- // is converted by yaccerrors.go into the yystate and yychar caused
- // by that token list.
-
- % loadsys package LIMPORT '(' LLITERAL import_package import_there ','
- "unexpected comma during import block"},
-
- % loadsys package LIMPORT LNAME ';'
- "missing import path; require quoted string"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header ';'
- "missing { after if clause"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' LSWITCH if_header ';'
- "missing { after switch clause"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' LFOR for_header ';'
- "missing { after for clause"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' LFOR ';' LBODY
- "missing { after for clause"},
-
- % loadsys package imports LFUNC LNAME '(' ')' ';' '{'
- "unexpected semicolon or newline before {"},
-
- % loadsys package imports LTYPE LNAME ';'
- "unexpected semicolon or newline in type declaration"},
-
- % loadsys package imports LCHAN '}'
- "unexpected } in channel type"},
-
- % loadsys package imports LCHAN ')'
- "unexpected ) in channel type"},
-
- % loadsys package imports LCHAN ','
- "unexpected comma in channel type"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' if_stmt ';' LELSE
- "unexpected semicolon or newline before else"},
-
- % loadsys package imports LTYPE LNAME LINTERFACE '{' LNAME ',' LNAME
- "name list not allowed in interface type"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' LFOR LVAR LNAME '=' LNAME
- "var declaration not allowed in for initializer"},
-
- % loadsys package imports LVAR LNAME '[' ']' LNAME '{'
- "unexpected { at end of statement"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' LVAR LNAME '[' ']' LNAME '{'
- "unexpected { at end of statement"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' LDEFER LNAME ';'
- "argument to go/defer must be function call"},
-
- % loadsys package imports LVAR LNAME '=' LNAME '{' LNAME ';'
- "need trailing comma before newline in composite literal"},
-
- % loadsys package imports LVAR LNAME '=' comptype '{' LNAME ';'
- "need trailing comma before newline in composite literal"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' LFUNC LNAME
- "nested func not allowed"},
-
- % loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header loop_body LELSE ';'
- "else must be followed by if or statement block"},
-}
diff --git a/src/cmd/internal/gc/yaccerrors.go b/src/cmd/internal/gc/yaccerrors.go
deleted file mode 100644
index 9dc54d9c8c..0000000000
--- a/src/cmd/internal/gc/yaccerrors.go
+++ /dev/null
@@ -1,194 +0,0 @@
-// 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.
-
-// +build ignore
-
-// This program implements the core idea from
-//
-// Clinton L. Jeffery, Generating LR syntax error messages from examples,
-// ACM TOPLAS 25(5) (September 2003). http://doi.acm.org/10.1145/937563.937566
-//
-// It reads Bison's summary of a grammar followed by a file
-// like go.errors, replacing lines beginning with % by the
-// yystate and yychar that will be active when an error happens
-// while parsing that line.
-//
-// Unlike the system described in the paper, the lines in go.errors
-// give grammar symbol name lists, not actual program fragments.
-// This is a little less programmer-friendly but doesn't require being
-// able to run the text through lex.c.
-
-package main
-
-import (
- "bufio"
- "fmt"
- "io"
- "log"
- "os"
- "strconv"
- "strings"
-)
-
-func xatoi(s string) int {
- n, err := strconv.Atoi(s)
- if err != nil {
- log.Fatal(err)
- }
- return n
-}
-
-func trimParen(s string) string {
- s = strings.TrimPrefix(s, "(")
- s = strings.TrimSuffix(s, ")")
- return s
-}
-
-type action struct {
- token string
- n int
-}
-
-var shift = map[int][]action{}
-var reduce = map[int][]action{}
-
-type rule struct {
- lhs string
- size int
-}
-
-var rules = map[int]rule{}
-
-func readYaccOutput() {
- r, err := os.Open("y.output")
- if err != nil {
- log.Fatal(err)
- }
- defer r.Close()
-
- var state int
-
- scanner := bufio.NewScanner(r)
- for scanner.Scan() {
- f := strings.Fields(scanner.Text())
- nf := len(f)
-
- if nf >= 4 && f[1] == "terminals," && f[3] == "nonterminals" {
- // We're done.
- break
- }
-
- if nf >= 2 && f[0] == "state" {
- state = xatoi(f[1])
- continue
- }
- if nf >= 3 && (f[1] == "shift" || f[1] == "goto") {
- shift[state] = append(shift[state], action{f[0], xatoi(f[2])})
- continue
- }
- if nf >= 3 && f[1] == "reduce" {
- reduce[state] = append(reduce[state], action{f[0], xatoi(f[2])})
- continue
- }
- if nf >= 3 && strings.HasSuffix(f[0], ":") && strings.HasPrefix(f[nf-1], "(") && strings.HasSuffix(f[nf-1], ")") {
- n := xatoi(trimParen(f[nf-1]))
-
- size := nf - 2
- if size == 1 && f[1] == "." {
- size = 0
- }
-
- rules[n] = rule{strings.TrimSuffix(f[0], ":"), size}
- continue
- }
- }
-}
-
-func runMachine(w io.Writer, s string) {
- f := strings.Fields(s)
-
- // Run it through the LR machine and print the induced "yystate, yychar,"
- // at the point where the error happens.
-
- var stack []int
- state := 0
- i := 1
- tok := ""
-
-Loop:
- if tok == "" && i < len(f) {
- tok = f[i]
- i++
- }
-
- for _, a := range shift[state] {
- if a.token == tok {
- if false {
- fmt.Println("SHIFT ", tok, " ", state, " -> ", a)
- }
- stack = append(stack, state)
- state = a.n
- tok = ""
- goto Loop
- }
- }
-
- for _, a := range reduce[state] {
- if a.token == tok || a.token == "." {
- stack = append(stack, state)
- rule, ok := rules[a.n]
- if !ok {
- log.Fatal("missing rule")
- }
- stack = stack[:len(stack)-rule.size]
- state = stack[len(stack)-1]
- stack = stack[:len(stack)-1]
- if tok != "" {
- i--
- }
- tok = rule.lhs
- if false {
- fmt.Println("REDUCE ", stack, " ", state, " ", tok, " rule ", rule)
- }
- goto Loop
- }
- }
-
- // No shift or reduce applied - found the error.
- fmt.Fprintf(w, "\t{%d, %s,\n", state, tok)
-}
-
-func processGoErrors() {
- r, err := os.Open("go.errors")
- if err != nil {
- log.Fatal(err)
- }
- defer r.Close()
-
- w, err := os.Create("yymsg.go")
- if err != nil {
- log.Fatal(err)
- }
- defer w.Close()
-
- fmt.Fprintf(w, "// DO NOT EDIT - generated with go generate\n\n")
-
- scanner := bufio.NewScanner(r)
- for scanner.Scan() {
- s := scanner.Text()
-
- // Treat % as first field on line as introducing a pattern (token sequence).
- if strings.HasPrefix(strings.TrimSpace(s), "%") {
- runMachine(w, s)
- continue
- }
-
- fmt.Fprintln(w, s)
- }
-}
-
-func main() {
- readYaccOutput()
- processGoErrors()
-}
diff --git a/src/cmd/internal/gc/yymsg.go b/src/cmd/internal/gc/yymsg.go
deleted file mode 100644
index cb45cb8d1b..0000000000
--- a/src/cmd/internal/gc/yymsg.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// DO NOT EDIT - generated with go generate
-
-// 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.
-
-// Example-based syntax error messages.
-// See yaccerrors.go.
-
-package gc
-
-var yymsg = []struct {
- yystate int
- yychar int
- msg string
-}{
- // Each line of the form % token list
- // is converted by yaccerrors.go into the yystate and yychar caused
- // by that token list.
-
- {332, ',',
- "unexpected comma during import block"},
-
- {89, ';',
- "missing import path; require quoted string"},
-
- {390, ';',
- "missing { after if clause"},
-
- {387, ';',
- "missing { after switch clause"},
-
- {279, ';',
- "missing { after for clause"},
-
- {498, LBODY,
- "missing { after for clause"},
-
- {17, '{',
- "unexpected semicolon or newline before {"},
-
- {111, ';',
- "unexpected semicolon or newline in type declaration"},
-
- {78, '}',
- "unexpected } in channel type"},
-
- {78, ')',
- "unexpected ) in channel type"},
-
- {78, ',',
- "unexpected comma in channel type"},
-
- {416, LELSE,
- "unexpected semicolon or newline before else"},
-
- {329, ',',
- "name list not allowed in interface type"},
-
- {279, LVAR,
- "var declaration not allowed in for initializer"},
-
- {25, '{',
- "unexpected { at end of statement"},
-
- {371, '{',
- "unexpected { at end of statement"},
-
- {122, ';',
- "argument to go/defer must be function call"},
-
- {398, ';',
- "need trailing comma before newline in composite literal"},
-
- {414, ';',
- "need trailing comma before newline in composite literal"},
-
- {124, LNAME,
- "nested func not allowed"},
-
- {650, ';',
- "else must be followed by if or statement block"},
-}
diff --git a/src/cmd/internal/gcprog/gcprog.go b/src/cmd/internal/gcprog/gcprog.go
new file mode 100644
index 0000000000..5845f7d65e
--- /dev/null
+++ b/src/cmd/internal/gcprog/gcprog.go
@@ -0,0 +1,298 @@
+// Copyright 2015 The Go 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 gcprog implements an encoder for packed GC pointer bitmaps,
+// known as GC programs.
+//
+// Program Format
+//
+// The GC program encodes a sequence of 0 and 1 bits indicating scalar or pointer words in an object.
+// The encoding is a simple Lempel-Ziv program, with codes to emit literal bits and to repeat the
+// last n bits c times.
+//
+// The possible codes are:
+//
+// 00000000: stop
+// 0nnnnnnn: emit n bits copied from the next (n+7)/8 bytes, least significant bit first
+// 10000000 n c: repeat the previous n bits c times; n, c are varints
+// 1nnnnnnn c: repeat the previous n bits c times; c is a varint
+//
+// The numbers n and c, when they follow a code, are encoded as varints
+// using the same encoding as encoding/binary's Uvarint.
+//
+package gcprog
+
+import (
+ "fmt"
+ "io"
+)
+
+const progMaxLiteral = 127 // maximum n for literal n bit code
+
+// A Writer is an encoder for GC programs.
+//
+// The typical use of a Writer is to call Init, maybe call Debug,
+// make a sequence of Ptr, Advance, Repeat, and Append calls
+// to describe the data type, and then finally call End.
+type Writer struct {
+ writeByte func(byte)
+ symoff int
+ index int64
+ b [progMaxLiteral]byte
+ nb int
+ debug io.Writer
+ debugBuf []byte
+}
+
+// Init initializes w to write a new GC program
+// by calling writeByte for each byte in the program.
+func (w *Writer) Init(writeByte func(byte)) {
+ w.writeByte = writeByte
+}
+
+// Debug causes the writer to print a debugging trace to out
+// during future calls to methods like Ptr, Advance, and End.
+// It also enables debugging checks during the encoding.
+func (w *Writer) Debug(out io.Writer) {
+ w.debug = out
+}
+
+// BitIndex returns the number of bits written to the bit stream so far.
+func (w *Writer) BitIndex() int64 {
+ return w.index
+}
+
+// byte writes the byte x to the output.
+func (w *Writer) byte(x byte) {
+ if w.debug != nil {
+ w.debugBuf = append(w.debugBuf, x)
+ }
+ w.writeByte(x)
+}
+
+// End marks the end of the program, writing any remaining bytes.
+func (w *Writer) End() {
+ w.flushlit()
+ w.byte(0)
+ if w.debug != nil {
+ index := progbits(w.debugBuf)
+ if index != w.index {
+ println("gcprog: End wrote program for", index, "bits, but current index is", w.index)
+ panic("gcprog: out of sync")
+ }
+ }
+}
+
+// Ptr emits a 1 into the bit stream at the given bit index.
+// that is, it records that the index'th word in the object memory is a pointer.
+// Any bits between the current index and the new index
+// are set to zero, meaning the corresponding words are scalars.
+func (w *Writer) Ptr(index int64) {
+ if index < w.index {
+ println("gcprog: Ptr at index", index, "but current index is", w.index)
+ panic("gcprog: invalid Ptr index")
+ }
+ w.ZeroUntil(index)
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, "gcprog: ptr at %d\n", index)
+ }
+ w.lit(1)
+}
+
+// ShouldRepeat reports whether it would be worthwhile to
+// use a Repeat to describe c elements of n bits each,
+// compared to just emitting c copies of the n-bit description.
+func (w *Writer) ShouldRepeat(n, c int64) bool {
+ // Should we lay out the bits directly instead of
+ // encoding them as a repetition? Certainly if count==1,
+ // since there's nothing to repeat, but also if the total
+ // size of the plain pointer bits for the type will fit in
+ // 4 or fewer bytes, since using a repetition will require
+ // flushing the current bits plus at least one byte for
+ // the repeat size and one for the repeat count.
+ return c > 1 && c*n > 4*8
+}
+
+// Repeat emits an instruction to repeat the description
+// of the last n words c times (including the initial description, c+1 times in total).
+func (w *Writer) Repeat(n, c int64) {
+ if n == 0 || c == 0 {
+ return
+ }
+ w.flushlit()
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, "gcprog: repeat %d × %d\n", n, c)
+ }
+ if n < 128 {
+ w.byte(0x80 | byte(n))
+ } else {
+ w.byte(0x80)
+ w.varint(n)
+ }
+ w.varint(c)
+ w.index += n * c
+}
+
+// ZeroUntil adds zeros to the bit stream until reaching the given index;
+// that is, it records that the words from the most recent pointer until
+// the index'th word are scalars.
+// ZeroUntil is usually called in preparation for a call to Repeat, Append, or End.
+func (w *Writer) ZeroUntil(index int64) {
+ if index < w.index {
+ println("gcprog: Advance", index, "but index is", w.index)
+ panic("gcprog: invalid Advance index")
+ }
+ skip := (index - w.index)
+ if skip == 0 {
+ return
+ }
+ if skip < 4*8 {
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, "gcprog: advance to %d by literals\n", index)
+ }
+ for i := int64(0); i < skip; i++ {
+ w.lit(0)
+ }
+ return
+ }
+
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, "gcprog: advance to %d by repeat\n", index)
+ }
+ w.lit(0)
+ w.flushlit()
+ w.Repeat(1, skip-1)
+}
+
+// Append emits the given GC program into the current output.
+// The caller asserts that the program emits n bits (describes n words),
+// and Append panics if that is not true.
+func (w *Writer) Append(prog []byte, n int64) {
+ w.flushlit()
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, "gcprog: append prog for %d ptrs\n", n)
+ fmt.Fprintf(w.debug, "\t")
+ }
+ n1 := progbits(prog)
+ if n1 != n {
+ panic("gcprog: wrong bit count in append")
+ }
+ // The last byte of the prog terminates the program.
+ // Don't emit that, or else our own program will end.
+ for i, x := range prog[:len(prog)-1] {
+ if w.debug != nil {
+ if i > 0 {
+ fmt.Fprintf(w.debug, " ")
+ }
+ fmt.Fprintf(w.debug, "%02x", x)
+ }
+ w.byte(x)
+ }
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, "\n")
+ }
+ w.index += n
+}
+
+// progbits returns the length of the bit stream encoded by the program p.
+func progbits(p []byte) int64 {
+ var n int64
+ for len(p) > 0 {
+ x := p[0]
+ p = p[1:]
+ if x == 0 {
+ break
+ }
+ if x&0x80 == 0 {
+ count := x &^ 0x80
+ n += int64(count)
+ p = p[(count+7)/8:]
+ continue
+ }
+ nbit := int64(x &^ 0x80)
+ if nbit == 0 {
+ nbit, p = readvarint(p)
+ }
+ var count int64
+ count, p = readvarint(p)
+ n += nbit * count
+ }
+ if len(p) > 0 {
+ println("gcprog: found end instruction after", n, "ptrs, with", len(p), "bytes remaining")
+ panic("gcprog: extra data at end of program")
+ }
+ return n
+}
+
+// readvarint reads a varint from p, returning the value and the remainder of p.
+func readvarint(p []byte) (int64, []byte) {
+ var v int64
+ var nb uint
+ for {
+ c := p[0]
+ p = p[1:]
+ v |= int64(c&^0x80) << nb
+ nb += 7
+ if c&0x80 == 0 {
+ break
+ }
+ }
+ return v, p
+}
+
+// lit adds a single literal bit to w.
+func (w *Writer) lit(x byte) {
+ if w.nb == progMaxLiteral {
+ w.flushlit()
+ }
+ w.b[w.nb] = x
+ w.nb++
+ w.index++
+}
+
+// varint emits the varint encoding of x.
+func (w *Writer) varint(x int64) {
+ if x < 0 {
+ panic("gcprog: negative varint")
+ }
+ for x >= 0x80 {
+ w.byte(byte(0x80 | x))
+ x >>= 7
+ }
+ w.byte(byte(x))
+}
+
+// flushlit flushes any pending literal bits.
+func (w *Writer) flushlit() {
+ if w.nb == 0 {
+ return
+ }
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, "gcprog: flush %d literals\n", w.nb)
+ fmt.Fprintf(w.debug, "\t%v\n", w.b[:w.nb])
+ fmt.Fprintf(w.debug, "\t%02x", byte(w.nb))
+ }
+ w.byte(byte(w.nb))
+ var bits uint8
+ for i := 0; i < w.nb; i++ {
+ bits |= w.b[i] << uint(i%8)
+ if (i+1)%8 == 0 {
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, " %02x", bits)
+ }
+ w.byte(bits)
+ bits = 0
+ }
+ }
+ if w.nb%8 != 0 {
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, " %02x", bits)
+ }
+ w.byte(bits)
+ }
+ if w.debug != nil {
+ fmt.Fprintf(w.debug, "\n")
+ }
+ w.nb = 0
+}
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index 6e00cb55ab..9e643932be 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -2677,8 +2677,8 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
case 59: /* stxr/stlxr */
o1 = opstore(ctxt, int(p.As))
- if p.To2.Type != obj.TYPE_NONE {
- o1 |= uint32(p.To2.Reg&31) << 16
+ if p.RegTo2 != obj.REG_NONE {
+ o1 |= uint32(p.RegTo2&31) << 16
} else {
o1 |= 0x1F << 16
}
diff --git a/src/cmd/internal/obj/line_test.go b/src/cmd/internal/obj/line_test.go
index dde5d64e17..5486f0d648 100644
--- a/src/cmd/internal/obj/line_test.go
+++ b/src/cmd/internal/obj/line_test.go
@@ -13,13 +13,13 @@ func TestLineHist(t *testing.T) {
ctxt := new(Link)
ctxt.Hash = make(map[SymVer]*LSym)
- Linklinehist(ctxt, 1, "a.c", 0)
- Linklinehist(ctxt, 3, "a.h", 0)
- Linklinehist(ctxt, 5, "<pop>", 0)
- Linklinehist(ctxt, 7, "linedir", 2)
- Linklinehist(ctxt, 9, "<pop>", 0)
- Linklinehist(ctxt, 11, "b.c", 0)
- Linklinehist(ctxt, 13, "<pop>", 0)
+ ctxt.LineHist.Push(1, "a.c")
+ ctxt.LineHist.Push(3, "a.h")
+ ctxt.LineHist.Pop(5)
+ ctxt.LineHist.Update(7, "linedir", 2)
+ ctxt.LineHist.Pop(9)
+ ctxt.LineHist.Push(11, "b.c")
+ ctxt.LineHist.Pop(13)
var expect = []string{
0: "??:0",
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index 9f5e87b4c3..2fc12c1eb1 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -206,7 +206,6 @@ type Prog struct {
From Addr
From3 Addr
To Addr
- To2 Addr
Opt interface{}
Forwd *Prog
Pcond *Prog
@@ -217,12 +216,12 @@ type Prog struct {
Spadj int32
As int16
Reg int16
+ RegTo2 int16 // 2nd register output operand
Mark uint16
Optab uint16
Scond uint8
Back uint8
Ft uint8
- F3t uint8
Tt uint8
Isize uint8
Printed uint8
diff --git a/src/cmd/internal/obj/mgc0.go b/src/cmd/internal/obj/mgc0.go
index 2407deaf32..a385d607bb 100644
--- a/src/cmd/internal/obj/mgc0.go
+++ b/src/cmd/internal/obj/mgc0.go
@@ -22,16 +22,6 @@ package obj
// Used by cmd/gc.
const (
- GcBits = 4
- BitsPerPointer = 2
- BitsDead = 0
- BitsScalar = 1
- BitsPointer = 2
- BitsMask = 3
- PointersPerByte = 8 / BitsPerPointer
-)
-
-const (
InsData = 1 + iota
InsArray
InsArrayEnd
diff --git a/src/cmd/internal/obj/obj.go b/src/cmd/internal/obj/obj.go
index 39db2396e7..af3290d3a5 100644
--- a/src/cmd/internal/obj/obj.go
+++ b/src/cmd/internal/obj/obj.go
@@ -241,12 +241,6 @@ func (h *LineHist) LineString(lineno int) string {
return text
}
-// TODO(rsc): Replace call sites with use of ctxt.LineHist.
-// Note that all call sites use showAll=false, showFullPath=false.
-func Linklinefmt(ctxt *Link, lineno int, showAll, showFullPath bool) string {
- return ctxt.LineHist.LineString(lineno)
-}
-
// FileLine returns the file name and line number
// at the top of the stack for the given lineno.
func (h *LineHist) FileLine(lineno int) (file string, line int) {
@@ -287,30 +281,3 @@ func linkgetline(ctxt *Link, lineno int32, f **LSym, l *int32) {
func Linkprfile(ctxt *Link, line int) {
fmt.Printf("%s ", ctxt.LineHist.LineString(line))
}
-
-// Linklinehist pushes, amends, or pops an entry on the line history stack.
-// If f != "<pop>" and n == 0, the call pushes the start of a new file named f at lineno.
-// If f != "<pop>" and n > 0, the call amends the top of the stack to record that lineno
-// now corresponds to f at line n.
-// If f == "<pop>", the call pops the topmost entry from the stack, picking up
-// the parent file at the line following the one where the corresponding push occurred.
-//
-// If n < 0, linklinehist records f as a package required by the current compilation
-// (nothing to do with line numbers).
-//
-// TODO(rsc): Replace uses with direct calls to ctxt.Hist methods.
-func Linklinehist(ctxt *Link, lineno int, f string, n int) {
- switch {
- case n < 0:
- ctxt.AddImport(f)
-
- case f == "<pop>":
- ctxt.LineHist.Pop(lineno)
-
- case n == 0:
- ctxt.LineHist.Push(lineno, f)
-
- default:
- ctxt.LineHist.Update(lineno, f, n)
- }
-}
diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go
index b0b209184f..efecae62ac 100644
--- a/src/cmd/internal/obj/util.go
+++ b/src/cmd/internal/obj/util.go
@@ -213,10 +213,17 @@ func Getgoos() string {
}
func Getgoarm() string {
- return envOr("GOARM", defaultGOARM)
+ switch v := envOr("GOARM", defaultGOARM); v {
+ case "5", "6", "7":
+ return v
+ }
+ // Fail here, rather than validate at multiple call sites.
+ log.Fatalf("Invalid GOARM value. Must be 5, 6, or 7.")
+ panic("unreachable")
}
func Getgo386() string {
+ // Validated by cmd/8g.
return envOr("GO386", defaultGO386)
}
@@ -234,7 +241,7 @@ func Atoi(s string) int {
}
func (p *Prog) Line() string {
- return Linklinefmt(p.Ctxt, int(p.Lineno), false, false)
+ return p.Ctxt.LineHist.LineString(int(p.Lineno))
}
var armCondCode = []string{
@@ -320,8 +327,8 @@ func (p *Prog) String() string {
if p.To.Type != TYPE_NONE {
fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.To))
}
- if p.To2.Type != TYPE_NONE {
- fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.To2))
+ if p.RegTo2 != REG_NONE {
+ fmt.Fprintf(&buf, "%s%v", sep, Rconv(int(p.RegTo2)))
}
return buf.String()
}
@@ -333,7 +340,7 @@ func (ctxt *Link) NewProg() *Prog {
}
func (ctxt *Link) Line(n int) string {
- return Linklinefmt(ctxt, n, false, false)
+ return ctxt.LineHist.LineString(n)
}
func Getcallerpc(interface{}) uintptr {
diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go
index 0c0cc04548..2b9c2670df 100644
--- a/src/cmd/internal/obj/x86/asm6.go
+++ b/src/cmd/internal/obj/x86/asm6.go
@@ -2974,15 +2974,12 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
if p.Ft == 0 {
p.Ft = uint8(oclass(ctxt, p, &p.From))
}
- if p.F3t == 0 {
- p.F3t = uint8(oclass(ctxt, p, &p.From3))
- }
if p.Tt == 0 {
p.Tt = uint8(oclass(ctxt, p, &p.To))
}
ft := int(p.Ft) * Ymax
- f3t := int(p.F3t) * Ymax
+ f3t := oclass(ctxt, p, &p.From3) * Ymax
tt := int(p.Tt) * Ymax
xo := obj.Bool2int(o.op[0] == 0x0f)
diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go
index 7a4fc128e6..4798c8f7fb 100644
--- a/src/cmd/internal/obj/x86/obj6.go
+++ b/src/cmd/internal/obj/x86/obj6.go
@@ -350,9 +350,6 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
if p.From3.Name == obj.NAME_EXTERN {
ctxt.Diag("don't know how to handle %v with -dynlink", p)
}
- if p.To2.Name == obj.NAME_EXTERN {
- ctxt.Diag("don't know how to handle %v with -dynlink", p)
- }
var source *obj.Addr
if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
diff --git a/src/cmd/internal/objfile/macho.go b/src/cmd/internal/objfile/macho.go
index a6cd02b930..7371c0d9d1 100644
--- a/src/cmd/internal/objfile/macho.go
+++ b/src/cmd/internal/objfile/macho.go
@@ -13,6 +13,8 @@ import (
"sort"
)
+const stabTypeMask = 0xe0
+
type machoFile struct {
macho *macho.File
}
@@ -34,12 +36,19 @@ func (f *machoFile) symbols() ([]Sym, error) {
// We infer the size of a symbol by looking at where the next symbol begins.
var addrs []uint64
for _, s := range f.macho.Symtab.Syms {
- addrs = append(addrs, s.Value)
+ // Skip stab debug info.
+ if s.Type&stabTypeMask == 0 {
+ addrs = append(addrs, s.Value)
+ }
}
sort.Sort(uint64s(addrs))
var syms []Sym
for _, s := range f.macho.Symtab.Syms {
+ if s.Type&stabTypeMask != 0 {
+ // Skip stab debug info.
+ continue
+ }
sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'}
i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
if i < len(addrs) {
diff --git a/src/cmd/6l/asm.go b/src/cmd/link/internal/amd64/asm.go
index a025ce6ea6..74ec9dd3ea 100644
--- a/src/cmd/6l/asm.go
+++ b/src/cmd/link/internal/amd64/asm.go
@@ -28,11 +28,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package amd64
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"debug/elf"
"fmt"
"log"
@@ -44,24 +44,6 @@ func PADDR(x uint32) uint32 {
var zeroes string
-func needlib(name string) int {
- if name[0] == '\x00' {
- return 0
- }
-
- /* reuse hash code in symbol table */
- p := fmt.Sprintf(".elfload.%s", name)
-
- s := ld.Linklookup(ld.Ctxt, p, 0)
-
- if s.Type == 0 {
- s.Type = 100 // avoid SDATA, etc.
- return 1
- }
-
- return 0
-}
-
func Addcall(ctxt *ld.Link, s *ld.LSym, t *ld.LSym) int64 {
s.Reachable = true
i := s.Size
@@ -292,7 +274,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
break
}
if ld.Iself {
- adddynsym(ld.Ctxt, targ)
+ ld.Adddynsym(ld.Ctxt, targ)
rela := ld.Linklookup(ld.Ctxt, ".rela", 0)
ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off))
if r.Siz == 8 {
@@ -316,7 +298,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
// just in case the C code assigns to the variable,
// and of course it only works for single pointers,
// but we only need to support cgo and that's all it needs.
- adddynsym(ld.Ctxt, targ)
+ ld.Adddynsym(ld.Ctxt, targ)
got := ld.Linklookup(ld.Ctxt, ".got", 0)
s.Type = got.Type | obj.SSUB
@@ -423,9 +405,9 @@ func machoreloc1(r *ld.Reloc, sectoff int64) int {
v = uint32(rs.Dynid)
v |= 1 << 27 // external relocation
} else {
- v = uint32((rs.Sect.(*ld.Section)).Extnum)
+ v = uint32(rs.Sect.Extnum)
if v == 0 {
- ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, (rs.Sect.(*ld.Section)).Name, rs.Type)
+ ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, rs.Sect.Name, rs.Type)
return -1
}
}
@@ -544,7 +526,7 @@ func addpltsym(s *ld.LSym) {
return
}
- adddynsym(ld.Ctxt, s)
+ ld.Adddynsym(ld.Ctxt, s)
if ld.Iself {
plt := ld.Linklookup(ld.Ctxt, ".plt", 0)
@@ -612,7 +594,7 @@ func addgotsym(s *ld.LSym) {
return
}
- adddynsym(ld.Ctxt, s)
+ ld.Adddynsym(ld.Ctxt, s)
got := ld.Linklookup(ld.Ctxt, ".got", 0)
s.Got = int32(got.Size)
ld.Adduint64(ld.Ctxt, got, 0)
@@ -629,80 +611,6 @@ func addgotsym(s *ld.LSym) {
}
}
-func adddynsym(ctxt *ld.Link, s *ld.LSym) {
- if s.Dynid >= 0 {
- return
- }
-
- if ld.Iself {
- s.Dynid = int32(ld.Nelfsym)
- ld.Nelfsym++
-
- d := ld.Linklookup(ctxt, ".dynsym", 0)
-
- name := s.Extname
- ld.Adduint32(ctxt, d, uint32(ld.Addstring(ld.Linklookup(ctxt, ".dynstr", 0), name)))
-
- /* type */
- t := ld.STB_GLOBAL << 4
-
- if s.Cgoexport != 0 && s.Type&obj.SMASK == obj.STEXT {
- t |= ld.STT_FUNC
- } else {
- t |= ld.STT_OBJECT
- }
- ld.Adduint8(ctxt, d, uint8(t))
-
- /* reserved */
- ld.Adduint8(ctxt, d, 0)
-
- /* section where symbol is defined */
- if s.Type == obj.SDYNIMPORT {
- ld.Adduint16(ctxt, d, ld.SHN_UNDEF)
- } else {
- ld.Adduint16(ctxt, d, 1)
- }
-
- /* value */
- if s.Type == obj.SDYNIMPORT {
- ld.Adduint64(ctxt, d, 0)
- } else {
- ld.Addaddr(ctxt, d, s)
- }
-
- /* size of object */
- ld.Adduint64(ctxt, d, uint64(s.Size))
-
- if s.Cgoexport&ld.CgoExportDynamic == 0 && s.Dynimplib != "" && needlib(s.Dynimplib) != 0 {
- ld.Elfwritedynent(ld.Linklookup(ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(ld.Linklookup(ctxt, ".dynstr", 0), s.Dynimplib)))
- }
- } else if ld.HEADTYPE == obj.Hdarwin {
- ld.Diag("adddynsym: missed symbol %s (%s)", s.Name, s.Extname)
- } else if ld.HEADTYPE == obj.Hwindows {
- } else // already taken care of
- {
- ld.Diag("adddynsym: unsupported binary format")
- }
-}
-
-func adddynlib(lib string) {
- if needlib(lib) == 0 {
- return
- }
-
- if ld.Iself {
- s := ld.Linklookup(ld.Ctxt, ".dynstr", 0)
- if s.Size == 0 {
- ld.Addstring(s, "")
- }
- ld.Elfwritedynent(ld.Linklookup(ld.Ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(s, lib)))
- } else if ld.HEADTYPE == obj.Hdarwin {
- ld.Machoadddynlib(lib)
- } else {
- ld.Diag("adddynlib: unsupported binary format")
- }
-}
-
func asmb() {
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
@@ -802,7 +710,7 @@ func asmb() {
symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin:
- symo = int64(ld.Segdata.Fileoff + uint64(ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))) + uint64(machlink))
+ symo = int64(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
case obj.Hlinux,
obj.Hfreebsd,
diff --git a/src/cmd/6l/l.go b/src/cmd/link/internal/amd64/l.go
index 6b42088de3..2537419eff 100644
--- a/src/cmd/6l/l.go
+++ b/src/cmd/link/internal/amd64/l.go
@@ -28,7 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package amd64
const (
thechar = '6'
@@ -40,7 +40,8 @@ const (
MINLC = 1
)
-/* Used by ../ld/dwarf.c */
+/* Used by ../internal/ld/dwarf.go */
const (
DWARFREGSP = 7
+ DWARFREGLR = 16
)
diff --git a/src/cmd/6l/obj.go b/src/cmd/link/internal/amd64/obj.go
index 9e6dc60e2d..1aa4422ed9 100644
--- a/src/cmd/6l/obj.go
+++ b/src/cmd/link/internal/amd64/obj.go
@@ -28,18 +28,18 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package amd64
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"fmt"
"log"
)
// Reading object files.
-func main() {
+func Main() {
linkarchinit()
ld.Ldmain()
}
@@ -59,10 +59,9 @@ func linkarchinit() {
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
+ ld.Thearch.Dwarfreglr = DWARFREGLR
- ld.Thearch.Adddynlib = adddynlib
ld.Thearch.Adddynrel = adddynrel
- ld.Thearch.Adddynsym = adddynsym
ld.Thearch.Archinit = archinit
ld.Thearch.Archreloc = archreloc
ld.Thearch.Archrelocvariant = archrelocvariant
@@ -91,7 +90,7 @@ func archinit() {
ld.Linkmode = ld.LinkInternal
}
- if ld.Buildmode == ld.BuildmodeCShared || ld.DynlinkingGo() {
+ if ld.Buildmode == ld.BuildmodeCArchive || ld.Buildmode == ld.BuildmodeCShared || ld.DynlinkingGo() {
ld.Linkmode = ld.LinkExternal
}
@@ -169,14 +168,6 @@ func archinit() {
ld.Elfinit()
ld.HEADR = ld.ELFRESERVE
- if ld.Buildmode == ld.BuildmodeShared {
- // When building a shared library we write a package list
- // note that can get quite large. The external linker will
- // re-layout all the sections anyway, so making this larger
- // just wastes a little space in the intermediate object
- // file, not the final shared library.
- ld.HEADR *= 3
- }
if ld.INITTEXT == -1 {
ld.INITTEXT = (1 << 22) + int64(ld.HEADR)
}
diff --git a/src/cmd/link/internal/amd64/z.go b/src/cmd/link/internal/amd64/z.go
new file mode 100644
index 0000000000..f70035b9e3
--- /dev/null
+++ b/src/cmd/link/internal/amd64/z.go
@@ -0,0 +1 @@
+package amd64
diff --git a/src/cmd/5l/asm.go b/src/cmd/link/internal/arm/asm.go
index 85ea684fc7..39d4550917 100644
--- a/src/cmd/5l/asm.go
+++ b/src/cmd/link/internal/arm/asm.go
@@ -28,33 +28,15 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"fmt"
"log"
)
-func needlib(name string) int {
- if name[0] == '\x00' {
- return 0
- }
-
- /* reuse hash code in symbol table */
- p := fmt.Sprintf(".dynlib.%s", name)
-
- s := ld.Linklookup(ld.Ctxt, p, 0)
-
- if s.Type == 0 {
- s.Type = 100 // avoid SDATA, etc.
- return 1
- }
-
- return 0
-}
-
func gentext() {
}
@@ -194,7 +176,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
break
}
if ld.Iself {
- adddynsym(ld.Ctxt, targ)
+ ld.Adddynsym(ld.Ctxt, targ)
rel := ld.Linklookup(ld.Ctxt, ".rel", 0)
ld.Addaddrplus(ld.Ctxt, rel, s, int64(r.Off))
ld.Adduint32(ld.Ctxt, rel, ld.ELF32_R_INFO(uint32(targ.Dynid), ld.R_ARM_GLOB_DAT)) // we need a nil + A dynmic reloc
@@ -297,9 +279,9 @@ func machoreloc1(r *ld.Reloc, sectoff int64) int {
v = uint32(rs.Dynid)
v |= 1 << 27 // external relocation
} else {
- v = uint32((rs.Sect.(*ld.Section)).Extnum)
+ v = uint32(rs.Sect.Extnum)
if v == 0 {
- ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, (rs.Sect.(*ld.Section)).Name, rs.Type)
+ ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, rs.Sect.Name, rs.Type)
return -1
}
}
@@ -440,7 +422,7 @@ func addpltsym(ctxt *ld.Link, s *ld.LSym) {
return
}
- adddynsym(ctxt, s)
+ ld.Adddynsym(ctxt, s)
if ld.Iself {
plt := ld.Linklookup(ctxt, ".plt", 0)
@@ -495,7 +477,7 @@ func addgotsym(ctxt *ld.Link, s *ld.LSym) {
return
}
- adddynsym(ctxt, s)
+ ld.Adddynsym(ctxt, s)
got := ld.Linklookup(ctxt, ".got", 0)
s.Got = int32(got.Size)
ld.Adduint32(ctxt, got, 0)
@@ -509,72 +491,6 @@ func addgotsym(ctxt *ld.Link, s *ld.LSym) {
}
}
-func adddynsym(ctxt *ld.Link, s *ld.LSym) {
- if s.Dynid >= 0 {
- return
- }
-
- if ld.Iself {
- s.Dynid = int32(ld.Nelfsym)
- ld.Nelfsym++
-
- d := ld.Linklookup(ctxt, ".dynsym", 0)
-
- /* name */
- name := s.Extname
-
- ld.Adduint32(ctxt, d, uint32(ld.Addstring(ld.Linklookup(ctxt, ".dynstr", 0), name)))
-
- /* value */
- if s.Type == obj.SDYNIMPORT {
- ld.Adduint32(ctxt, d, 0)
- } else {
- ld.Addaddr(ctxt, d, s)
- }
-
- /* size */
- ld.Adduint32(ctxt, d, 0)
-
- /* type */
- t := ld.STB_GLOBAL << 4
-
- if (s.Cgoexport&ld.CgoExportDynamic != 0) && s.Type&obj.SMASK == obj.STEXT {
- t |= ld.STT_FUNC
- } else {
- t |= ld.STT_OBJECT
- }
- ld.Adduint8(ctxt, d, uint8(t))
- ld.Adduint8(ctxt, d, 0)
-
- /* shndx */
- if s.Type == obj.SDYNIMPORT {
- ld.Adduint16(ctxt, d, ld.SHN_UNDEF)
- } else {
- ld.Adduint16(ctxt, d, 1)
- }
- } else {
- ld.Diag("adddynsym: unsupported binary format")
- }
-}
-
-func adddynlib(lib string) {
- if needlib(lib) == 0 {
- return
- }
-
- if ld.Iself {
- s := ld.Linklookup(ld.Ctxt, ".dynstr", 0)
- if s.Size == 0 {
- ld.Addstring(s, "")
- }
- ld.Elfwritedynent(ld.Linklookup(ld.Ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(s, lib)))
- } else if ld.HEADTYPE == obj.Hdarwin {
- ld.Machoadddynlib(lib)
- } else {
- ld.Diag("adddynlib: unsupported binary format")
- }
-}
-
func asmb() {
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
@@ -617,14 +533,12 @@ func asmb() {
fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
}
- if ld.Debug['w'] == 0 { // TODO(minux): enable DWARF Support
- dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
- ld.Cseek(int64(dwarfoff))
+ dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
+ ld.Cseek(int64(dwarfoff))
- ld.Segdwarf.Fileoff = uint64(ld.Cpos())
- ld.Dwarfemitdebugsections()
- ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
- }
+ ld.Segdwarf.Fileoff = uint64(ld.Cpos())
+ ld.Dwarfemitdebugsections()
+ ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
machlink = uint32(ld.Domacholink())
}
@@ -651,7 +565,7 @@ func asmb() {
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin:
- symo = uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Filelen), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)) + int64(machlink))
+ symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
}
ld.Cseek(int64(symo))
diff --git a/src/cmd/5l/l.go b/src/cmd/link/internal/arm/l.go
index a52154594d..4973772163 100644
--- a/src/cmd/5l/l.go
+++ b/src/cmd/link/internal/arm/l.go
@@ -28,7 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm
// Writing object files.
@@ -72,7 +72,8 @@ const (
MINLC = 4
)
-/* Used by ../ld/dwarf.c */
+/* Used by ../internal/ld/dwarf.go */
const (
DWARFREGSP = 13
+ DWARFREGLR = 14
)
diff --git a/src/cmd/5l/obj.go b/src/cmd/link/internal/arm/obj.go
index fa74908005..14fe7a64eb 100644
--- a/src/cmd/5l/obj.go
+++ b/src/cmd/link/internal/arm/obj.go
@@ -28,18 +28,18 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"fmt"
"log"
)
// Reading object files.
-func main() {
+func Main() {
linkarchinit()
ld.Ldmain()
}
@@ -56,10 +56,9 @@ func linkarchinit() {
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
+ ld.Thearch.Dwarfreglr = DWARFREGLR
- ld.Thearch.Adddynlib = adddynlib
ld.Thearch.Adddynrel = adddynrel
- ld.Thearch.Adddynsym = adddynsym
ld.Thearch.Archinit = archinit
ld.Thearch.Archreloc = archreloc
ld.Thearch.Archrelocvariant = archrelocvariant
diff --git a/src/cmd/7l/asm.go b/src/cmd/link/internal/arm64/asm.go
index a17899dcf0..3aebd8a223 100644
--- a/src/cmd/7l/asm.go
+++ b/src/cmd/link/internal/arm64/asm.go
@@ -28,11 +28,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm64
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"encoding/binary"
"fmt"
"log"
@@ -40,24 +40,6 @@ import (
func gentext() {}
-func needlib(name string) int {
- if name[0] == '\x00' {
- return 0
- }
-
- /* reuse hash code in symbol table */
- p := fmt.Sprintf(".dynlib.%s", name)
-
- s := ld.Linklookup(ld.Ctxt, p, 0)
-
- if s.Type == 0 {
- s.Type = 100 // avoid SDATA, etc.
- return 1
- }
-
- return 0
-}
-
func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
log.Fatalf("adddynrela not implemented")
}
@@ -125,9 +107,9 @@ func machoreloc1(r *ld.Reloc, sectoff int64) int {
v = uint32(rs.Dynid)
v |= 1 << 27 // external relocation
} else {
- v = uint32((rs.Sect.(*ld.Section)).Extnum)
+ v = uint32(rs.Sect.Extnum)
if v == 0 {
- ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, (rs.Sect.(*ld.Section)).Name, rs.Type)
+ ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, rs.Sect.Name, rs.Type)
return -1
}
}
@@ -293,28 +275,6 @@ func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 {
return -1
}
-func adddynsym(ctxt *ld.Link, s *ld.LSym) {
- // TODO(minux): implement when needed.
-}
-
-func adddynlib(lib string) {
- if needlib(lib) == 0 {
- return
- }
-
- if ld.Iself {
- s := ld.Linklookup(ld.Ctxt, ".dynstr", 0)
- if s.Size == 0 {
- ld.Addstring(s, "")
- }
- ld.Elfwritedynent(ld.Linklookup(ld.Ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(s, lib)))
- } else if ld.HEADTYPE == obj.Hdarwin {
- ld.Machoadddynlib(lib)
- } else {
- ld.Diag("adddynlib: unsupported binary format")
- }
-}
-
func asmb() {
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
@@ -357,14 +317,12 @@ func asmb() {
fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
}
- if ld.Debug['w'] == 0 { // TODO(minux): enable DWARF Support
- dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
- ld.Cseek(int64(dwarfoff))
+ dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
+ ld.Cseek(int64(dwarfoff))
- ld.Segdwarf.Fileoff = uint64(ld.Cpos())
- ld.Dwarfemitdebugsections()
- ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
- }
+ ld.Segdwarf.Fileoff = uint64(ld.Cpos())
+ ld.Dwarfemitdebugsections()
+ ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
machlink = uint32(ld.Domacholink())
}
@@ -391,7 +349,7 @@ func asmb() {
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin:
- symo = uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Filelen), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)) + int64(machlink))
+ symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
}
ld.Cseek(int64(symo))
diff --git a/src/cmd/7l/l.go b/src/cmd/link/internal/arm64/l.go
index 6f90acb107..8d0d57e72a 100644
--- a/src/cmd/7l/l.go
+++ b/src/cmd/link/internal/arm64/l.go
@@ -28,7 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm64
// Writing object files.
@@ -71,7 +71,8 @@ const (
MINLC = 4
)
-/* Used by ../ld/dwarf.c */
+/* Used by ../internal/ld/dwarf.go */
const (
DWARFREGSP = 31
+ DWARFREGLR = 30
)
diff --git a/src/cmd/7l/obj.go b/src/cmd/link/internal/arm64/obj.go
index f8ac7d33ea..56f5815903 100644
--- a/src/cmd/7l/obj.go
+++ b/src/cmd/link/internal/arm64/obj.go
@@ -28,18 +28,18 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package arm64
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"fmt"
"log"
)
// Reading object files.
-func main() {
+func Main() {
linkarchinit()
ld.Ldmain()
}
@@ -56,10 +56,9 @@ func linkarchinit() {
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
+ ld.Thearch.Dwarfreglr = DWARFREGLR
- ld.Thearch.Adddynlib = adddynlib
ld.Thearch.Adddynrel = adddynrel
- ld.Thearch.Adddynsym = adddynsym
ld.Thearch.Archinit = archinit
ld.Thearch.Archreloc = archreloc
ld.Thearch.Archrelocvariant = archrelocvariant
diff --git a/src/cmd/internal/ld/ar.go b/src/cmd/link/internal/ld/ar.go
index 0e59016edb..0e59016edb 100644
--- a/src/cmd/internal/ld/ar.go
+++ b/src/cmd/link/internal/ld/ar.go
diff --git a/src/cmd/internal/ld/arch.go b/src/cmd/link/internal/ld/arch.go
index 1b8e1b19ba..1b8e1b19ba 100644
--- a/src/cmd/internal/ld/arch.go
+++ b/src/cmd/link/internal/ld/arch.go
diff --git a/src/cmd/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index 3194bd568e..fd1cdd64bb 100644
--- a/src/cmd/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -32,9 +32,11 @@
package ld
import (
+ "cmd/internal/gcprog"
"cmd/internal/obj"
"fmt"
"log"
+ "os"
"strings"
)
@@ -520,7 +522,7 @@ func relocsym(s *LSym) {
} else if HEADTYPE == obj.Hdarwin {
if r.Type == obj.R_CALL {
if rs.Type != obj.SHOSTOBJ {
- o += int64(uint64(Symaddr(rs)) - (rs.Sect.(*Section)).Vaddr)
+ o += int64(uint64(Symaddr(rs)) - rs.Sect.Vaddr)
}
o -= int64(r.Off) // relative to section offset, not symbol
} else {
@@ -532,7 +534,7 @@ func relocsym(s *LSym) {
o += int64(r.Siz)
// GNU ld always add VirtualAddress of the .text section to the
// relocated address, compensate that.
- o -= int64(s.Sect.(*Section).Vaddr - PEBASE)
+ o -= int64(s.Sect.Vaddr - PEBASE)
} else {
Diag("unhandled pcrel relocation for %s", headstring)
}
@@ -963,6 +965,22 @@ func Addstring(s *LSym, str string) int64 {
return int64(r)
}
+// addgostring adds str, as a Go string value, to s. symname is the name of the
+// symbol used to define the string data and must be unique per linked object.
+func addgostring(s *LSym, symname, str string) {
+ sym := Linklookup(Ctxt, symname, 0)
+ if sym.Type != obj.Sxxx {
+ Diag("duplicate symname in addgostring: %s", symname)
+ }
+ sym.Reachable = true
+ sym.Local = true
+ sym.Type = obj.SRODATA
+ sym.Size = int64(len(str))
+ sym.P = []byte(str)
+ Addaddr(Ctxt, s, sym)
+ adduint(Ctxt, s, uint64(len(str)))
+}
+
func addinitarrdata(s *LSym) {
p := s.Name + ".ptr"
sp := Linklookup(Ctxt, p, 0)
@@ -1028,165 +1046,65 @@ func maxalign(s *LSym, type_ int) int32 {
return max
}
-// Helper object for building GC type programs.
-type ProgGen struct {
- s *LSym
- datasize int32
- data [256 / obj.PointersPerByte]uint8
- pos int64
-}
-
-func proggeninit(g *ProgGen, s *LSym) {
- g.s = s
- g.datasize = 0
- g.pos = 0
- g.data = [256 / obj.PointersPerByte]uint8{}
-}
+const debugGCProg = false
-func proggenemit(g *ProgGen, v uint8) {
- Adduint8(Ctxt, g.s, v)
+type GCProg struct {
+ sym *LSym
+ w gcprog.Writer
}
-// Writes insData block from g->data.
-func proggendataflush(g *ProgGen) {
- if g.datasize == 0 {
- return
- }
- proggenemit(g, obj.InsData)
- proggenemit(g, uint8(g.datasize))
- s := (g.datasize + obj.PointersPerByte - 1) / obj.PointersPerByte
- for i := int32(0); i < s; i++ {
- proggenemit(g, g.data[i])
+func (p *GCProg) Init(name string) {
+ p.sym = Linklookup(Ctxt, name, 0)
+ p.w.Init(p.writeByte)
+ if debugGCProg {
+ fmt.Fprintf(os.Stderr, "ld: start GCProg %s\n", name)
+ p.w.Debug(os.Stderr)
}
- g.datasize = 0
- g.data = [256 / obj.PointersPerByte]uint8{}
}
-func proggendata(g *ProgGen, d uint8) {
- g.data[g.datasize/obj.PointersPerByte] |= d << uint((g.datasize%obj.PointersPerByte)*obj.BitsPerPointer)
- g.datasize++
- if g.datasize == 255 {
- proggendataflush(g)
- }
+func (p *GCProg) writeByte(x byte) {
+ Adduint8(Ctxt, p.sym, x)
}
-// Skip v bytes due to alignment, etc.
-func proggenskip(g *ProgGen, off int64, v int64) {
- for i := off; i < off+v; i++ {
- if (i % int64(Thearch.Ptrsize)) == 0 {
- proggendata(g, obj.BitsScalar)
- }
+func (p *GCProg) End(size int64) {
+ p.w.ZeroUntil(size / int64(Thearch.Ptrsize))
+ p.w.End()
+ if debugGCProg {
+ fmt.Fprintf(os.Stderr, "ld: end GCProg\n")
}
}
-// Emit insArray instruction.
-func proggenarray(g *ProgGen, length int64) {
- var i int32
-
- proggendataflush(g)
- proggenemit(g, obj.InsArray)
- for i = 0; i < int32(Thearch.Ptrsize); i, length = i+1, length>>8 {
- proggenemit(g, uint8(length))
- }
-}
-
-func proggenarrayend(g *ProgGen) {
- proggendataflush(g)
- proggenemit(g, obj.InsArrayEnd)
-}
-
-func proggenfini(g *ProgGen, size int64) {
- proggenskip(g, g.pos, size-g.pos)
- proggendataflush(g)
- proggenemit(g, obj.InsEnd)
-}
-
-// This function generates GC pointer info for global variables.
-func proggenaddsym(g *ProgGen, s *LSym) {
- if s.Size == 0 {
+func (p *GCProg) AddSym(s *LSym) {
+ typ := s.Gotype
+ // Things without pointers should be in SNOPTRDATA or SNOPTRBSS;
+ // everything we see should have pointers and should therefore have a type.
+ if typ == nil {
+ Diag("missing Go type information for global symbol: %s size %d", s.Name, int(s.Size))
return
}
- // Skip alignment hole from the previous symbol.
- proggenskip(g, g.pos, s.Value-g.pos)
-
- g.pos += s.Value - g.pos
-
- // The test for names beginning with . here is meant
- // to keep .dynamic and .dynsym from turning up as
- // conservative symbols. They should be marked SELFSECT
- // and not SDATA, but sometimes that doesn't happen.
- // Leave debugging the SDATA issue for the Go rewrite.
+ ptrsize := int64(Thearch.Ptrsize)
+ nptr := decodetype_ptrdata(typ) / ptrsize
- if s.Gotype == nil && s.Size >= int64(Thearch.Ptrsize) && s.Name[0] != '.' {
- // conservative scan
- Diag("missing Go type information for global symbol: %s size %d", s.Name, int(s.Size))
-
- if (s.Size%int64(Thearch.Ptrsize) != 0) || (g.pos%int64(Thearch.Ptrsize) != 0) {
- Diag("proggenaddsym: unaligned conservative symbol %s: size=%d pos=%d", s.Name, s.Size, g.pos)
- }
- size := (s.Size + int64(Thearch.Ptrsize) - 1) / int64(Thearch.Ptrsize) * int64(Thearch.Ptrsize)
- if size < int64(32*Thearch.Ptrsize) {
- // Emit small symbols as data.
- for i := int64(0); i < size/int64(Thearch.Ptrsize); i++ {
- proggendata(g, obj.BitsPointer)
- }
- } else {
- // Emit large symbols as array.
- proggenarray(g, size/int64(Thearch.Ptrsize))
-
- proggendata(g, obj.BitsPointer)
- proggenarrayend(g)
- }
+ if debugGCProg {
+ fmt.Fprintf(os.Stderr, "gcprog sym: %s at %d (ptr=%d+%d)\n", s.Name, s.Value, s.Value/ptrsize, nptr)
+ }
- g.pos = s.Value + size
- } else if s.Gotype == nil || decodetype_noptr(s.Gotype) != 0 || s.Size < int64(Thearch.Ptrsize) || s.Name[0] == '.' {
- // no scan
- if s.Size < int64(32*Thearch.Ptrsize) {
- // Emit small symbols as data.
- // This case also handles unaligned and tiny symbols, so tread carefully.
- for i := s.Value; i < s.Value+s.Size; i++ {
- if (i % int64(Thearch.Ptrsize)) == 0 {
- proggendata(g, obj.BitsScalar)
- }
+ if decodetype_usegcprog(typ) == 0 {
+ // Copy pointers from mask into program.
+ mask := decodetype_gcmask(typ)
+ for i := int64(0); i < nptr; i++ {
+ if (mask[i/8]>>uint(i%8))&1 != 0 {
+ p.w.Ptr(s.Value/ptrsize + i)
}
- } else {
- // Emit large symbols as array.
- if (s.Size%int64(Thearch.Ptrsize) != 0) || (g.pos%int64(Thearch.Ptrsize) != 0) {
- Diag("proggenaddsym: unaligned noscan symbol %s: size=%d pos=%d", s.Name, s.Size, g.pos)
- }
- proggenarray(g, s.Size/int64(Thearch.Ptrsize))
- proggendata(g, obj.BitsScalar)
- proggenarrayend(g)
- }
-
- g.pos = s.Value + s.Size
- } else if decodetype_usegcprog(s.Gotype) != 0 {
- // gc program, copy directly
- proggendataflush(g)
-
- gcprog := decodetype_gcprog(s.Gotype)
- size := decodetype_size(s.Gotype)
- if (size%int64(Thearch.Ptrsize) != 0) || (g.pos%int64(Thearch.Ptrsize) != 0) {
- Diag("proggenaddsym: unaligned gcprog symbol %s: size=%d pos=%d", s.Name, s.Size, g.pos)
- }
- for i := int64(0); i < int64(len(gcprog.P)-1); i++ {
- proggenemit(g, uint8(gcprog.P[i]))
}
- g.pos = s.Value + size
- } else {
- // gc mask, it's small so emit as data
- mask := decodetype_gcmask(s.Gotype)
-
- size := decodetype_size(s.Gotype)
- if (size%int64(Thearch.Ptrsize) != 0) || (g.pos%int64(Thearch.Ptrsize) != 0) {
- Diag("proggenaddsym: unaligned gcmask symbol %s: size=%d pos=%d", s.Name, s.Size, g.pos)
- }
- for i := int64(0); i < size; i += int64(Thearch.Ptrsize) {
- proggendata(g, uint8((mask[i/int64(Thearch.Ptrsize)/2]>>uint64((i/int64(Thearch.Ptrsize)%2)*4+2))&obj.BitsMask))
- }
- g.pos = s.Value + size
+ return
}
+
+ // Copy program.
+ prog := decodetype_gcprog(typ)
+ p.w.ZeroUntil(s.Value / ptrsize)
+ p.w.Append(prog[4:], nptr)
}
func growdatsize(datsizep *int64, s *LSym) {
@@ -1394,15 +1312,13 @@ func dodata() {
/* data */
sect = addsection(&Segdata, ".data", 06)
-
sect.Align = maxalign(s, obj.SBSS-1)
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.data", 0).Sect = sect
Linklookup(Ctxt, "runtime.edata", 0).Sect = sect
- gcdata := Linklookup(Ctxt, "runtime.gcdata", 0)
- var gen ProgGen
- proggeninit(&gen, gcdata)
+ var gc GCProg
+ gc.Init("runtime.gcdata")
for ; s != nil && s.Type < obj.SBSS; s = s.Next {
if s.Type == obj.SINITARR {
Ctxt.Cursym = s
@@ -1413,33 +1329,30 @@ func dodata() {
s.Type = obj.SDATA
datsize = aligndatsize(datsize, s)
s.Value = int64(uint64(datsize) - sect.Vaddr)
- proggenaddsym(&gen, s) // gc
+ gc.AddSym(s)
growdatsize(&datsize, s)
}
-
sect.Length = uint64(datsize) - sect.Vaddr
- proggenfini(&gen, int64(sect.Length)) // gc
+ gc.End(int64(sect.Length))
/* bss */
sect = addsection(&Segdata, ".bss", 06)
-
sect.Align = maxalign(s, obj.SNOPTRBSS-1)
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.bss", 0).Sect = sect
Linklookup(Ctxt, "runtime.ebss", 0).Sect = sect
- gcbss := Linklookup(Ctxt, "runtime.gcbss", 0)
- proggeninit(&gen, gcbss)
+ gc = GCProg{}
+ gc.Init("runtime.gcbss")
for ; s != nil && s.Type < obj.SNOPTRBSS; s = s.Next {
s.Sect = sect
datsize = aligndatsize(datsize, s)
s.Value = int64(uint64(datsize) - sect.Vaddr)
- proggenaddsym(&gen, s) // gc
+ gc.AddSym(s)
growdatsize(&datsize, s)
}
-
sect.Length = uint64(datsize) - sect.Vaddr
- proggenfini(&gen, int64(sect.Length)) // gc
+ gc.End(int64(sect.Length))
/* pointer-free bss */
sect = addsection(&Segdata, ".noptrbss", 06)
@@ -1768,13 +1681,20 @@ func address() {
for sym := datap; sym != nil; sym = sym.Next {
Ctxt.Cursym = sym
if sym.Sect != nil {
- sym.Value += int64((sym.Sect.(*Section)).Vaddr)
+ sym.Value += int64(sym.Sect.Vaddr)
}
for sub = sym.Sub; sub != nil; sub = sub.Sub {
sub.Value += sym.Value
}
}
+ if Buildmode == BuildmodeShared {
+ s := Linklookup(Ctxt, "go.link.abihashbytes", 0)
+ sectSym := Linklookup(Ctxt, ".note.go.abihash", 0)
+ s.Sect = sectSym.Sect
+ s.Value = int64(sectSym.Sect.Vaddr + 16)
+ }
+
xdefine("runtime.text", obj.STEXT, int64(text.Vaddr))
xdefine("runtime.etext", obj.STEXT, int64(text.Vaddr+text.Length))
xdefine("runtime.rodata", obj.SRODATA, int64(rodata.Vaddr))
diff --git a/src/cmd/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go
index 754c89f12b..c1cf4d7181 100644
--- a/src/cmd/internal/ld/decodesym.go
+++ b/src/cmd/link/internal/ld/decodesym.go
@@ -4,7 +4,10 @@
package ld
-import "cmd/internal/obj"
+import (
+ "cmd/internal/obj"
+ "debug/elf"
+)
// Decoding the type.* symbols. This has to be in sync with
// ../../runtime/type.go, or more specifically, with what
@@ -44,7 +47,7 @@ func decode_inuxi(p []byte, sz int) uint64 {
// commonsize returns the size of the common prefix for all type
// structures (runtime._type).
func commonsize() int {
- return 9*Thearch.Ptrsize + 8
+ return 8*Thearch.Ptrsize + 8
}
// Type.commonType.kind
@@ -67,14 +70,43 @@ func decodetype_size(s *LSym) int64 {
return int64(decode_inuxi(s.P, Thearch.Ptrsize)) // 0x8 / 0x10
}
+// Type.commonType.ptrdata
+func decodetype_ptrdata(s *LSym) int64 {
+ return int64(decode_inuxi(s.P[Thearch.Ptrsize:], Thearch.Ptrsize)) // 0x8 / 0x10
+}
+
+// Find the elf.Section of a given shared library that contains a given address.
+func findShlibSection(path string, addr uint64) *elf.Section {
+ for _, shlib := range Ctxt.Shlibs {
+ if shlib.Path == path {
+ for _, sect := range shlib.File.Sections {
+ if sect.Addr <= addr && addr <= sect.Addr+sect.Size {
+ return sect
+ }
+ }
+ }
+ }
+ return nil
+}
+
// Type.commonType.gc
-func decodetype_gcprog(s *LSym) *LSym {
+func decodetype_gcprog(s *LSym) []byte {
if s.Type == obj.SDYNIMPORT {
- // The gcprog for "type.$name" is calle "type..gcprog.$name".
- x := "type..gcprog." + s.Name[5:]
- return Linklookup(Ctxt, x, 0)
+ addr := decodetype_gcprog_shlib(s)
+ sect := findShlibSection(s.File, addr)
+ if sect != nil {
+ // A gcprog is a 4-byte uint32 indicating length, followed by
+ // the actual program.
+ progsize := make([]byte, 4)
+ sect.ReadAt(progsize, int64(addr-sect.Addr))
+ progbytes := make([]byte, Ctxt.Arch.ByteOrder.Uint32(progsize))
+ sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
+ return append(progsize, progbytes...)
+ }
+ Exitf("cannot find gcprog for %s", s.Name)
+ return nil
}
- return decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+2*int32(Thearch.Ptrsize))
+ return decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize)).P
}
func decodetype_gcprog_shlib(s *LSym) uint64 {
@@ -83,9 +115,16 @@ func decodetype_gcprog_shlib(s *LSym) uint64 {
func decodetype_gcmask(s *LSym) []byte {
if s.Type == obj.SDYNIMPORT {
- // ldshlibsyms makes special efforts to read the value
- // of gcmask for types defined in that shared library.
- return s.gcmask
+ addr := decodetype_gcprog_shlib(s)
+ ptrdata := decodetype_ptrdata(s)
+ sect := findShlibSection(s.File, addr)
+ if sect != nil {
+ r := make([]byte, ptrdata/int64(Thearch.Ptrsize))
+ sect.ReadAt(r, int64(addr-sect.Addr))
+ return r
+ }
+ Exitf("cannot find gcmask for %s", s.Name)
+ return nil
}
mask := decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
return mask.P
diff --git a/src/cmd/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index 6d90404b13..b8fb2e6b55 100644
--- a/src/cmd/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -17,6 +17,7 @@ package ld
import (
"cmd/internal/obj"
"fmt"
+ "os"
"strings"
)
@@ -240,6 +241,7 @@ var abbrevs = [DW_NABRV]DWAbbrev{
{DW_AT_low_pc, DW_FORM_addr},
{DW_AT_high_pc, DW_FORM_addr},
{DW_AT_stmt_list, DW_FORM_data4},
+ {DW_AT_comp_dir, DW_FORM_string},
},
},
@@ -694,6 +696,9 @@ func adddwarfrel(sec *LSym, sym *LSym, offsetbase int64, siz int, addend int64)
if Iself && Thearch.Thechar == '6' {
addend = 0
}
+ if HEADTYPE == obj.Hdarwin {
+ addend += sym.Value
+ }
switch siz {
case 4:
Thearch.Lput(uint32(addend))
@@ -1547,6 +1552,13 @@ func flushunit(dwinfo *DWDie, pc int64, pcsym *LSym, unitstart int64, header_len
}
}
+func getCompilationDir() string {
+ if dir, err := os.Getwd(); err == nil {
+ return dir
+ }
+ return "/"
+}
+
func writelines() {
if linesec == nil {
linesec = Linklookup(Ctxt, ".dwarfline", 0)
@@ -1571,6 +1583,9 @@ func writelines() {
newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT, int64(lang), 0)
newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart-lineo, 0)
newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s.Value, s)
+ // OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
+ compDir := getCompilationDir()
+ newattr(dwinfo, DW_AT_comp_dir, DW_CLS_STRING, int64(len(compDir)), compDir)
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf
@@ -1692,11 +1707,17 @@ func writelines() {
switch a.Name {
case obj.A_AUTO:
dt = DW_ABRV_AUTO
- offs = int64(a.Aoffset) - int64(Thearch.Ptrsize)
+ offs = int64(a.Aoffset)
+ if !haslinkregister() {
+ offs -= int64(Thearch.Ptrsize)
+ }
case obj.A_PARAM:
dt = DW_ABRV_PARAM
offs = int64(a.Aoffset)
+ if haslinkregister() {
+ offs += int64(Thearch.Ptrsize)
+ }
default:
continue
@@ -1749,7 +1770,6 @@ func writelines() {
const (
CIERESERVE = 16
DATAALIGNMENTFACTOR = -4
- FAKERETURNCOLUMN = 16 // TODO gdb6 doesn't like > 15?
)
func putpccfadelta(deltapc int64, cfa int64) {
@@ -1778,21 +1798,30 @@ func writeframes() {
frameo = Cpos()
// Emit the CIE, Section 6.4.1
- Thearch.Lput(CIERESERVE) // initial length, must be multiple of thearch.ptrsize
- Thearch.Lput(0xffffffff) // cid.
- Cput(3) // dwarf version (appendix F)
- Cput(0) // augmentation ""
- uleb128put(1) // code_alignment_factor
- sleb128put(DATAALIGNMENTFACTOR) // guess
- uleb128put(FAKERETURNCOLUMN) // return_address_register
+ Thearch.Lput(CIERESERVE) // initial length, must be multiple of thearch.ptrsize
+ Thearch.Lput(0xffffffff) // cid.
+ Cput(3) // dwarf version (appendix F)
+ Cput(0) // augmentation ""
+ uleb128put(1) // code_alignment_factor
+ sleb128put(DATAALIGNMENTFACTOR) // guess
+ uleb128put(int64(Thearch.Dwarfreglr)) // return_address_register
Cput(DW_CFA_def_cfa)
uleb128put(int64(Thearch.Dwarfregsp)) // register SP (**ABI-dependent, defined in l.h)
- uleb128put(int64(Thearch.Ptrsize)) // offset
+ if haslinkregister() {
+ uleb128put(int64(0)) // offset
+ } else {
+ uleb128put(int64(Thearch.Ptrsize)) // offset
+ }
- Cput(DW_CFA_offset + FAKERETURNCOLUMN) // return address
- uleb128put(int64(-Thearch.Ptrsize) / DATAALIGNMENTFACTOR) // at cfa - x*4
+ Cput(DW_CFA_offset_extended)
+ uleb128put(int64(Thearch.Dwarfreglr)) // return address
+ if haslinkregister() {
+ uleb128put(int64(0) / DATAALIGNMENTFACTOR) // at cfa - 0
+ } else {
+ uleb128put(int64(-Thearch.Ptrsize) / DATAALIGNMENTFACTOR) // at cfa - x*4
+ }
// 4 is to exclude the length field.
pad := CIERESERVE + frameo + 4 - Cpos()
@@ -1834,7 +1863,11 @@ func writeframes() {
}
}
- putpccfadelta(int64(nextpc)-int64(pcsp.pc), int64(Thearch.Ptrsize)+int64(pcsp.value))
+ if haslinkregister() {
+ putpccfadelta(int64(nextpc)-int64(pcsp.pc), int64(pcsp.value))
+ } else {
+ putpccfadelta(int64(nextpc)-int64(pcsp.pc), int64(Thearch.Ptrsize)+int64(pcsp.value))
+ }
}
fdesize = Cpos() - fdeo - 4 // exclude the length field.
@@ -2065,6 +2098,14 @@ func writedwarfreloc(s *LSym) int64 {
return start
}
+func addmachodwarfsect(prev *Section, name string) *Section {
+ sect := addsection(&Segdwarf, name, 04)
+ sect.Extnum = prev.Extnum + 1
+ sym := Linklookup(Ctxt, name, 0)
+ sym.Sect = sect
+ return sect
+}
+
/*
* This is the main entry point for generating dwarf. After emitting
* the mandatory debug_abbrev section, it calls writelines() to set up
@@ -2079,8 +2120,33 @@ func Dwarfemitdebugsections() {
return
}
- if Linkmode == LinkExternal && !Iself {
- return
+ if Linkmode == LinkExternal {
+ if !Iself && HEADTYPE != obj.Hdarwin {
+ return
+ }
+ if HEADTYPE == obj.Hdarwin {
+ sect := Segdata.Sect
+ // find the last section.
+ for sect.Next != nil {
+ sect = sect.Next
+ }
+ sect = addmachodwarfsect(sect, ".debug_abbrev")
+ sect = addmachodwarfsect(sect, ".debug_line")
+ sect = addmachodwarfsect(sect, ".debug_frame")
+ sect = addmachodwarfsect(sect, ".debug_info")
+
+ infosym = Linklookup(Ctxt, ".debug_info", 0)
+ infosym.Hide = 1
+
+ abbrevsym = Linklookup(Ctxt, ".debug_abbrev", 0)
+ abbrevsym.Hide = 1
+
+ linesym = Linklookup(Ctxt, ".debug_line", 0)
+ linesym.Hide = 1
+
+ framesym = Linklookup(Ctxt, ".debug_frame", 0)
+ framesym.Hide = 1
+ }
}
// For diagnostic messages.
@@ -2173,6 +2239,15 @@ func Dwarfemitdebugsections() {
for Cpos()&7 != 0 {
Cput(0)
}
+ if HEADTYPE != obj.Hdarwin {
+ dwarfemitreloc()
+ }
+}
+
+func dwarfemitreloc() {
+ if Debug['w'] != 0 { // disable dwarf
+ return
+ }
inforeloco = writedwarfreloc(infosec)
inforelocsize = Cpos() - inforeloco
align(inforelocsize)
@@ -2402,14 +2477,15 @@ func dwarfaddelfheaders() {
/*
* Macho
*/
-func dwarfaddmachoheaders() {
+func dwarfaddmachoheaders(ms *MachoSeg) {
if Debug['w'] != 0 { // disable dwarf
return
}
// Zero vsize segments won't be loaded in memory, even so they
// have to be page aligned in the file.
- fakestart := abbrevo &^ 0xfff
+ fakestart := Rnd(int64(Segdwarf.Fileoff), 0x1000)
+ addr := Segdata.Vaddr + Segdata.Length
nsect := 4
if pubnamessize > 0 {
@@ -2425,57 +2501,94 @@ func dwarfaddmachoheaders() {
nsect++
}
- ms := newMachoSeg("__DWARF", nsect)
- ms.fileoffset = uint64(fakestart)
- ms.filesize = uint64(abbrevo) - uint64(fakestart)
- ms.vaddr = ms.fileoffset + Segdata.Vaddr - Segdata.Fileoff
+ if Linkmode != LinkExternal {
+ ms = newMachoSeg("__DWARF", nsect)
+ ms.fileoffset = uint64(fakestart)
+ ms.filesize = Segdwarf.Filelen
+ ms.vaddr = addr
+ }
msect := newMachoSect(ms, "__debug_abbrev", "__DWARF")
msect.off = uint32(abbrevo)
msect.size = uint64(abbrevsize)
- msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff
- ms.filesize += msect.size
+ msect.addr = addr
+ addr += msect.size
+ msect.flag = 0x02000000
+ if abbrevsym != nil {
+ abbrevsym.Value = int64(msect.addr)
+ }
msect = newMachoSect(ms, "__debug_line", "__DWARF")
msect.off = uint32(lineo)
msect.size = uint64(linesize)
- msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff
- ms.filesize += msect.size
+ msect.addr = addr
+ addr += msect.size
+ msect.flag = 0x02000000
+ if linesym != nil {
+ linesym.Value = int64(msect.addr)
+ }
+ if linerelocsize > 0 {
+ msect.nreloc = uint32(len(linesec.R))
+ msect.reloc = uint32(linereloco)
+ }
msect = newMachoSect(ms, "__debug_frame", "__DWARF")
msect.off = uint32(frameo)
msect.size = uint64(framesize)
- msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff
- ms.filesize += msect.size
+ msect.addr = addr
+ addr += msect.size
+ msect.flag = 0x02000000
+ if framesym != nil {
+ framesym.Value = int64(msect.addr)
+ }
+ if framerelocsize > 0 {
+ msect.nreloc = uint32(len(framesec.R))
+ msect.reloc = uint32(framereloco)
+ }
msect = newMachoSect(ms, "__debug_info", "__DWARF")
msect.off = uint32(infoo)
msect.size = uint64(infosize)
- msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff
- ms.filesize += msect.size
+ msect.addr = addr
+ addr += msect.size
+ msect.flag = 0x02000000
+ if infosym != nil {
+ infosym.Value = int64(msect.addr)
+ }
+ if inforelocsize > 0 {
+ msect.nreloc = uint32(len(infosec.R))
+ msect.reloc = uint32(inforeloco)
+ }
if pubnamessize > 0 {
msect := newMachoSect(ms, "__debug_pubnames", "__DWARF")
msect.off = uint32(pubnameso)
msect.size = uint64(pubnamessize)
- msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff
- ms.filesize += msect.size
+ msect.addr = addr
+ addr += msect.size
+ msect.flag = 0x02000000
}
if pubtypessize > 0 {
msect := newMachoSect(ms, "__debug_pubtypes", "__DWARF")
msect.off = uint32(pubtypeso)
msect.size = uint64(pubtypessize)
- msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff
- ms.filesize += msect.size
+ msect.addr = addr
+ addr += msect.size
+ msect.flag = 0x02000000
}
if arangessize > 0 {
msect := newMachoSect(ms, "__debug_aranges", "__DWARF")
msect.off = uint32(arangeso)
msect.size = uint64(arangessize)
- msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff
- ms.filesize += msect.size
+ msect.addr = addr
+ addr += msect.size
+ msect.flag = 0x02000000
+ if arangesrelocsize > 0 {
+ msect.nreloc = uint32(len(arangessec.R))
+ msect.reloc = uint32(arangesreloco)
+ }
}
// TODO(lvd) fix gdb/python to load MachO (16 char section name limit)
@@ -2483,8 +2596,9 @@ func dwarfaddmachoheaders() {
msect := newMachoSect(ms, "__debug_gdb_scripts", "__DWARF")
msect.off = uint32(gdbscripto)
msect.size = uint64(gdbscriptsize)
- msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff
- ms.filesize += msect.size
+ msect.addr = addr
+ addr += msect.size
+ msect.flag = 0x02000000
}
}
diff --git a/src/cmd/internal/ld/dwarf_defs.go b/src/cmd/link/internal/ld/dwarf_defs.go
index 61389d9218..61389d9218 100644
--- a/src/cmd/internal/ld/dwarf_defs.go
+++ b/src/cmd/link/internal/ld/dwarf_defs.go
diff --git a/src/cmd/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index 5c17b2da6f..68d21f415c 100644
--- a/src/cmd/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -6,8 +6,12 @@ package ld
import (
"cmd/internal/obj"
+ "crypto/sha1"
"encoding/binary"
"fmt"
+ "path/filepath"
+ "sort"
+ "strings"
)
/*
@@ -1199,32 +1203,15 @@ func elfwritebuildinfo() int {
return int(sh.size)
}
-// Go package list note
+// Go specific notes
const (
ELF_NOTE_GOPKGLIST_TAG = 1
+ ELF_NOTE_GOABIHASH_TAG = 2
+ ELF_NOTE_GODEPS_TAG = 3
)
var ELF_NOTE_GO_NAME = []byte("GO\x00\x00")
-func elfgopkgnote(sh *ElfShdr, startva uint64, resoff uint64) int {
- n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(pkglistfornote)), 4))
- return elfnote(sh, startva, resoff, n, false)
-}
-
-func elfwritegopkgnote() int {
- sh := elfwritenotehdr(".note.go.pkg-list", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(pkglistfornote)), ELF_NOTE_GOPKGLIST_TAG)
- if sh == nil {
- return 0
- }
-
- Cwrite(ELF_NOTE_GO_NAME)
- Cwrite(pkglistfornote)
- var zero = make([]byte, 4)
- Cwrite(zero[:int(Rnd(int64(len(pkglistfornote)), 4)-int64(len(pkglistfornote)))])
-
- return int(sh.size)
-}
-
var elfverneed int
type Elfaux struct {
@@ -1455,6 +1442,24 @@ func elfshalloc(sect *Section) *ElfShdr {
func elfshbits(sect *Section) *ElfShdr {
sh := elfshalloc(sect)
+ // If this section has already been set up as a note, we assume type_ and
+ // flags are already correct, but the other fields still need filling in.
+ if sh.type_ == SHT_NOTE {
+ if Linkmode != LinkExternal {
+ // TODO(mwhudson): the approach here will work OK when
+ // linking internally for notes that we want to be included
+ // in a loadable segment (e.g. the abihash note) but not for
+ // notes that we do not want to be mapped (e.g. the package
+ // list note). The real fix is probably to define new values
+ // for LSym.Type corresponding to mapped and unmapped notes
+ // and handle them in dodata().
+ Diag("sh.type_ == SHT_NOTE in elfshbits when linking internally")
+ }
+ sh.addralign = uint64(sect.Align)
+ sh.size = sect.Length
+ sh.off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
+ return sh
+ }
if sh.type_ > 0 {
return sh
}
@@ -1490,13 +1495,16 @@ func elfshbits(sect *Section) *ElfShdr {
func elfshreloc(sect *Section) *ElfShdr {
// If main section is SHT_NOBITS, nothing to relocate.
- // Also nothing to relocate in .shstrtab.
+ // Also nothing to relocate in .shstrtab or notes.
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
return nil
}
if sect.Name == ".shstrtab" || sect.Name == ".tbss" {
return nil
}
+ if sect.Elfsect.type_ == SHT_NOTE {
+ return nil
+ }
var prefix string
var typ int
@@ -1517,7 +1525,7 @@ func elfshreloc(sect *Section) *ElfShdr {
sh.entsize += uint64(Thearch.Regsize)
}
sh.link = uint32(elfshname(".symtab").shnum)
- sh.info = uint32((sect.Elfsect.(*ElfShdr)).shnum)
+ sh.info = uint32(sect.Elfsect.shnum)
sh.off = sect.Reloff
sh.size = sect.Rellen
sh.addralign = uint64(Thearch.Regsize)
@@ -1596,6 +1604,29 @@ func Elfemitreloc() {
}
}
+func addgonote(sectionName string, tag uint32, desc []byte) {
+ s := Linklookup(Ctxt, sectionName, 0)
+ s.Reachable = true
+ s.Type = obj.SELFROSECT
+ // namesz
+ Adduint32(Ctxt, s, uint32(len(ELF_NOTE_GO_NAME)))
+ // descsz
+ Adduint32(Ctxt, s, uint32(len(desc)))
+ // tag
+ Adduint32(Ctxt, s, tag)
+ // name + padding
+ s.P = append(s.P, ELF_NOTE_GO_NAME...)
+ for len(s.P)%4 != 0 {
+ s.P = append(s.P, 0)
+ }
+ // desc + padding
+ s.P = append(s.P, desc...)
+ for len(s.P)%4 != 0 {
+ s.P = append(s.P, 0)
+ }
+ s.Size = int64(len(s.P))
+}
+
func doelf() {
if !Iself {
return
@@ -1632,9 +1663,6 @@ func doelf() {
if len(buildinfo) > 0 {
Addstring(shstrtab, ".note.gnu.build-id")
}
- if Buildmode == BuildmodeShared {
- Addstring(shstrtab, ".note.go.pkg-list")
- }
Addstring(shstrtab, ".elfdata")
Addstring(shstrtab, ".rodata")
Addstring(shstrtab, ".typelink")
@@ -1668,6 +1696,12 @@ func doelf() {
// add a .note.GNU-stack section to mark the stack as non-executable
Addstring(shstrtab, ".note.GNU-stack")
+
+ if Buildmode == BuildmodeShared {
+ Addstring(shstrtab, ".note.go.abihash")
+ Addstring(shstrtab, ".note.go.pkg-list")
+ Addstring(shstrtab, ".note.go.deps")
+ }
}
hasinitarr := Linkshared
@@ -1856,6 +1890,30 @@ func doelf() {
// size of .rel(a).plt section.
Elfwritedynent(s, DT_DEBUG, 0)
}
+
+ if Buildmode == BuildmodeShared {
+ // The go.link.abihashbytes symbol will be pointed at the appropriate
+ // part of the .note.go.abihash section in data.go:func address().
+ s := Linklookup(Ctxt, "go.link.abihashbytes", 0)
+ s.Local = true
+ s.Type = obj.SRODATA
+ s.Special = 1
+ s.Reachable = true
+ s.Size = int64(sha1.Size)
+
+ sort.Sort(byPkg(Ctxt.Library))
+ h := sha1.New()
+ for _, l := range Ctxt.Library {
+ h.Write(l.hash)
+ }
+ addgonote(".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
+ addgonote(".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, []byte(pkglistfornote))
+ var deplist []string
+ for _, shlib := range Ctxt.Shlibs {
+ deplist = append(deplist, filepath.Base(shlib.Path))
+ }
+ addgonote(".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n")))
+ }
}
// Do not write DT_NULL. elfdynhash will finish it.
@@ -1922,15 +1980,13 @@ func Asmbelf(symo int64) {
eh.phentsize = 0
if Buildmode == BuildmodeShared {
- // The package list note we make space for here can get quite
- // large. The external linker will re-layout all the sections
- // anyway, so making this larger just wastes a little space
- // in the intermediate object file, not the final shared
- // library.
- elfreserve *= 3
- resoff = elfreserve
sh := elfshname(".note.go.pkg-list")
- resoff -= int64(elfgopkgnote(sh, uint64(startva), uint64(resoff)))
+ sh.type_ = SHT_NOTE
+ sh = elfshname(".note.go.abihash")
+ sh.type_ = SHT_NOTE
+ sh.flags = SHF_ALLOC
+ sh = elfshname(".note.go.deps")
+ sh.type_ = SHT_NOTE
}
goto elfobj
}
@@ -2340,15 +2396,99 @@ elfobj:
a += int64(elfwritebuildinfo())
}
}
- if Buildmode == BuildmodeShared {
- a += int64(elfwritegopkgnote())
- }
if a > elfreserve {
Diag("ELFRESERVE too small: %d > %d", a, elfreserve)
}
}
+func Elfadddynsym(ctxt *Link, s *LSym) {
+ if elf64 {
+ s.Dynid = int32(Nelfsym)
+ Nelfsym++
+
+ d := Linklookup(ctxt, ".dynsym", 0)
+
+ name := s.Extname
+ Adduint32(ctxt, d, uint32(Addstring(Linklookup(ctxt, ".dynstr", 0), name)))
+
+ /* type */
+ t := STB_GLOBAL << 4
+
+ if s.Cgoexport != 0 && s.Type&obj.SMASK == obj.STEXT {
+ t |= STT_FUNC
+ } else {
+ t |= STT_OBJECT
+ }
+ Adduint8(ctxt, d, uint8(t))
+
+ /* reserved */
+ Adduint8(ctxt, d, 0)
+
+ /* section where symbol is defined */
+ if s.Type == obj.SDYNIMPORT {
+ Adduint16(ctxt, d, SHN_UNDEF)
+ } else {
+ Adduint16(ctxt, d, 1)
+ }
+
+ /* value */
+ if s.Type == obj.SDYNIMPORT {
+ Adduint64(ctxt, d, 0)
+ } else {
+ Addaddr(ctxt, d, s)
+ }
+
+ /* size of object */
+ Adduint64(ctxt, d, uint64(s.Size))
+
+ if Thearch.Thechar == '6' && s.Cgoexport&CgoExportDynamic == 0 && s.Dynimplib != "" && !seenlib[s.Dynimplib] {
+ Elfwritedynent(Linklookup(ctxt, ".dynamic", 0), DT_NEEDED, uint64(Addstring(Linklookup(ctxt, ".dynstr", 0), s.Dynimplib)))
+ }
+ } else {
+ s.Dynid = int32(Nelfsym)
+ Nelfsym++
+
+ d := Linklookup(ctxt, ".dynsym", 0)
+
+ /* name */
+ name := s.Extname
+
+ Adduint32(ctxt, d, uint32(Addstring(Linklookup(ctxt, ".dynstr", 0), name)))
+
+ /* value */
+ if s.Type == obj.SDYNIMPORT {
+ Adduint32(ctxt, d, 0)
+ } else {
+ Addaddr(ctxt, d, s)
+ }
+
+ /* size */
+ Adduint32(ctxt, d, 0)
+
+ /* type */
+ t := STB_GLOBAL << 4
+
+ // TODO(mwhudson): presumably the behaviour should actually be the same on both arm and 386.
+ if Thearch.Thechar == '8' && s.Cgoexport != 0 && s.Type&obj.SMASK == obj.STEXT {
+ t |= STT_FUNC
+ } else if Thearch.Thechar == '5' && s.Cgoexport&CgoExportDynamic != 0 && s.Type&obj.SMASK == obj.STEXT {
+ t |= STT_FUNC
+ } else {
+ t |= STT_OBJECT
+ }
+ Adduint8(ctxt, d, uint8(t))
+ Adduint8(ctxt, d, 0)
+
+ /* shndx */
+ if s.Type == obj.SDYNIMPORT {
+ Adduint16(ctxt, d, SHN_UNDEF)
+ } else {
+ Adduint16(ctxt, d, 1)
+ }
+ }
+}
+
func ELF32_R_SYM(info uint32) uint32 {
return info >> 8
}
diff --git a/src/cmd/internal/ld/go.go b/src/cmd/link/internal/ld/go.go
index 0223bfae9d..80a6c6ed7d 100644
--- a/src/cmd/internal/ld/go.go
+++ b/src/cmd/link/internal/ld/go.go
@@ -416,7 +416,11 @@ func loadcgo(file string, pkg string, p string) {
// to force a link of foo.so.
havedynamic = 1
- Thearch.Adddynlib(lib)
+ if HEADTYPE == obj.Hdarwin {
+ Machoadddynlib(lib)
+ } else {
+ dynlib = append(dynlib, lib)
+ }
continue
}
@@ -534,6 +538,41 @@ err:
nerrors++
}
+var seenlib = make(map[string]bool)
+
+func adddynlib(lib string) {
+ if seenlib[lib] || Linkmode == LinkExternal {
+ return
+ }
+ seenlib[lib] = true
+
+ if Iself {
+ s := Linklookup(Ctxt, ".dynstr", 0)
+ if s.Size == 0 {
+ Addstring(s, "")
+ }
+ Elfwritedynent(Linklookup(Ctxt, ".dynamic", 0), DT_NEEDED, uint64(Addstring(s, lib)))
+ } else {
+ Diag("adddynlib: unsupported binary format")
+ }
+}
+
+func Adddynsym(ctxt *Link, s *LSym) {
+ if s.Dynid >= 0 || Linkmode == LinkExternal {
+ return
+ }
+
+ if Iself {
+ Elfadddynsym(ctxt, s)
+ } else if HEADTYPE == obj.Hdarwin {
+ Diag("adddynsym: missed symbol %s (%s)", s.Name, s.Extname)
+ } else if HEADTYPE == obj.Hwindows {
+ // already taken care of
+ } else {
+ Diag("adddynsym: unsupported binary format")
+ }
+}
+
var markq *LSym
var emarkq *LSym
@@ -614,15 +653,14 @@ func deadcode() {
}
if Buildmode == BuildmodeShared {
- // Mark all symbols as reachable when building a
- // shared library.
+ // Mark all symbols defined in this library as reachable when
+ // building a shared library.
for s := Ctxt.Allsym; s != nil; s = s.Allsym {
- if s.Type != 0 {
+ if s.Type != 0 && s.Type != obj.SDYNIMPORT {
mark(s)
}
}
- mark(Linkrlookup(Ctxt, "main.main", 0))
- mark(Linkrlookup(Ctxt, "main.init", 0))
+ markflood()
} else {
mark(Linklookup(Ctxt, INITENTRY, 0))
if Linkshared && Buildmode == BuildmodeExe {
@@ -737,8 +775,11 @@ func addexport() {
return
}
- for i := 0; i < len(dynexp); i++ {
- Thearch.Adddynsym(Ctxt, dynexp[i])
+ for _, exp := range dynexp {
+ Adddynsym(Ctxt, exp)
+ }
+ for _, lib := range dynlib {
+ adddynlib(lib)
}
}
diff --git a/src/cmd/internal/ld/ld.go b/src/cmd/link/internal/ld/ld.go
index 7242301d0f..1068bdd767 100644
--- a/src/cmd/internal/ld/ld.go
+++ b/src/cmd/link/internal/ld/ld.go
@@ -109,8 +109,8 @@ func addlibpath(ctxt *Link, srcref string, objref string, file string, pkg strin
fmt.Fprintf(ctxt.Bso, "%5.2f addlibpath: srcref: %s objref: %s file: %s pkg: %s shlibnamefile: %s\n", obj.Cputime(), srcref, objref, file, pkg, shlibnamefile)
}
- ctxt.Library = append(ctxt.Library, Library{})
- l := &ctxt.Library[len(ctxt.Library)-1]
+ ctxt.Library = append(ctxt.Library, &Library{})
+ l := ctxt.Library[len(ctxt.Library)-1]
l.Objref = objref
l.Srcref = srcref
l.File = file
diff --git a/src/cmd/internal/ld/ldelf.go b/src/cmd/link/internal/ld/ldelf.go
index 3efdb75b89..3efdb75b89 100644
--- a/src/cmd/internal/ld/ldelf.go
+++ b/src/cmd/link/internal/ld/ldelf.go
diff --git a/src/cmd/internal/ld/ldmacho.go b/src/cmd/link/internal/ld/ldmacho.go
index 2abfa3336f..2abfa3336f 100644
--- a/src/cmd/internal/ld/ldmacho.go
+++ b/src/cmd/link/internal/ld/ldmacho.go
diff --git a/src/cmd/internal/ld/ldpe.go b/src/cmd/link/internal/ld/ldpe.go
index b98cf0206b..b98cf0206b 100644
--- a/src/cmd/internal/ld/ldpe.go
+++ b/src/cmd/link/internal/ld/ldpe.go
diff --git a/src/cmd/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 184175e026..d87f1801f0 100644
--- a/src/cmd/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -34,7 +34,9 @@ import (
"bufio"
"bytes"
"cmd/internal/obj"
+ "crypto/sha1"
"debug/elf"
+ "encoding/binary"
"fmt"
"io"
"io/ioutil"
@@ -86,15 +88,14 @@ type Arch struct {
Maxalign int
Minlc int
Dwarfregsp int
+ Dwarfreglr int
Linuxdynld string
Freebsddynld string
Netbsddynld string
Openbsddynld string
Dragonflydynld string
Solarisdynld string
- Adddynlib func(string)
Adddynrel func(*LSym, *Reloc)
- Adddynsym func(*Link, *LSym)
Archinit func()
Archreloc func(*Reloc, *LSym, *int64) int
Archrelocvariant func(*Reloc, *LSym, int64) int64
@@ -162,7 +163,7 @@ type Section struct {
Length uint64
Next *Section
Seg *Segment
- Elfsect interface{}
+ Elfsect *ElfShdr
Reloff uint64
Rellen uint64
}
@@ -178,6 +179,7 @@ var (
Thelinkarch *LinkArch
outfile string
dynexp []*LSym
+ dynlib []string
ldflag []string
havedynamic int
Funcalign int
@@ -473,7 +475,7 @@ func loadlib() {
if Ctxt.Library[i].Shlib != "" {
ldshlibsyms(Ctxt.Library[i].Shlib)
} else {
- objfile(Ctxt.Library[i].File, Ctxt.Library[i].Pkg)
+ objfile(Ctxt.Library[i])
}
}
@@ -519,7 +521,7 @@ func loadlib() {
if DynlinkingGo() {
Exitf("cannot implicitly include runtime/cgo in a shared library")
}
- objfile(Ctxt.Library[i].File, Ctxt.Library[i].Pkg)
+ objfile(Ctxt.Library[i])
}
}
}
@@ -630,18 +632,18 @@ func nextar(bp *obj.Biobuf, off int64, a *ArHdr) int64 {
return int64(arsize) + SAR_HDR
}
-func objfile(file string, pkg string) {
- pkg = pathtoprefix(pkg)
+func objfile(lib *Library) {
+ pkg := pathtoprefix(lib.Pkg)
if Debug['v'] > 1 {
- fmt.Fprintf(&Bso, "%5.2f ldobj: %s (%s)\n", obj.Cputime(), file, pkg)
+ fmt.Fprintf(&Bso, "%5.2f ldobj: %s (%s)\n", obj.Cputime(), lib.File, pkg)
}
Bso.Flush()
var err error
var f *obj.Biobuf
- f, err = obj.Bopenr(file)
+ f, err = obj.Bopenr(lib.File)
if err != nil {
- Exitf("cannot open file %s: %v", file, err)
+ Exitf("cannot open file %s: %v", lib.File, err)
}
magbuf := make([]byte, len(ARMAG))
@@ -650,7 +652,7 @@ func objfile(file string, pkg string) {
l := obj.Bseek(f, 0, 2)
obj.Bseek(f, 0, 0)
- ldobj(f, pkg, l, file, file, FileObj)
+ ldobj(f, pkg, l, lib.File, lib.File, FileObj)
obj.Bterm(f)
return
@@ -663,7 +665,7 @@ func objfile(file string, pkg string) {
l := nextar(f, off, &arhdr)
var pname string
if l <= 0 {
- Diag("%s: short read on archive file symbol header", file)
+ Diag("%s: short read on archive file symbol header", lib.File)
goto out
}
@@ -671,20 +673,29 @@ func objfile(file string, pkg string) {
off += l
l = nextar(f, off, &arhdr)
if l <= 0 {
- Diag("%s: short read on archive file symbol header", file)
+ Diag("%s: short read on archive file symbol header", lib.File)
goto out
}
}
if !strings.HasPrefix(arhdr.name, pkgname) {
- Diag("%s: cannot find package header", file)
+ Diag("%s: cannot find package header", lib.File)
goto out
}
+ if Buildmode == BuildmodeShared {
+ before := obj.Boffset(f)
+ pkgdefBytes := make([]byte, atolwhex(arhdr.size))
+ obj.Bread(f, pkgdefBytes)
+ hash := sha1.Sum(pkgdefBytes)
+ lib.hash = hash[:]
+ obj.Bseek(f, before, 0)
+ }
+
off += l
if Debug['u'] != 0 {
- ldpkg(f, pkg, atolwhex(arhdr.size), file, Pkgdef)
+ ldpkg(f, pkg, atolwhex(arhdr.size), lib.File, Pkgdef)
}
/*
@@ -705,14 +716,14 @@ func objfile(file string, pkg string) {
break
}
if l < 0 {
- Exitf("%s: malformed archive", file)
+ Exitf("%s: malformed archive", lib.File)
}
off += l
- pname = fmt.Sprintf("%s(%s)", file, arhdr.name)
+ pname = fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
l = atolwhex(arhdr.size)
- ldobj(f, pkg, l, pname, file, ArchiveObj)
+ ldobj(f, pkg, l, pname, lib.File, ArchiveObj)
}
out:
@@ -912,7 +923,7 @@ func hostlink() {
}
if HEADTYPE == obj.Hdarwin {
- argv = append(argv, "-Wl,-no_pie,-pagezero_size,4000000")
+ argv = append(argv, "-Wl,-no_pie,-pagezero_size,4000000,-headerpad,1144")
}
if HEADTYPE == obj.Hopenbsd {
argv = append(argv, "-Wl,-nopie")
@@ -972,15 +983,35 @@ func hostlink() {
argv = append(argv, fmt.Sprintf("%s/go.o", tmpdir))
if Linkshared {
- for _, shlib := range Ctxt.Shlibs {
- dir, base := filepath.Split(shlib)
- argv = append(argv, "-L"+dir)
- if !rpath.set {
- argv = append(argv, "-Wl,-rpath="+dir)
+ seenDirs := make(map[string]bool)
+ seenLibs := make(map[string]bool)
+ addshlib := func(path string) {
+ dir, base := filepath.Split(path)
+ if !seenDirs[dir] {
+ argv = append(argv, "-L"+dir)
+ if !rpath.set {
+ argv = append(argv, "-Wl,-rpath="+dir)
+ }
+ seenDirs[dir] = true
}
base = strings.TrimSuffix(base, ".so")
base = strings.TrimPrefix(base, "lib")
- argv = append(argv, "-l"+base)
+ if !seenLibs[base] {
+ argv = append(argv, "-l"+base)
+ seenLibs[base] = true
+ }
+ }
+ for _, shlib := range Ctxt.Shlibs {
+ addshlib(shlib.Path)
+ for _, dep := range shlib.Deps {
+ if dep == "" {
+ continue
+ }
+ libpath := findshlib(dep)
+ if libpath != "" {
+ addshlib(libpath)
+ }
+ }
}
}
@@ -1018,6 +1049,31 @@ func hostlink() {
if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
Exitf("running %s failed: %v\n%s", argv[0], err, out)
+ } else if Debug['v'] != 0 && len(out) > 0 {
+ fmt.Fprintf(&Bso, "%s", out)
+ Bso.Flush()
+ }
+
+ if Debug['s'] == 0 && debug_s == 0 && HEADTYPE == obj.Hdarwin {
+ // Skip combining dwarf on arm.
+ if Thearch.Thechar != '5' && Thearch.Thechar != '7' {
+ dsym := fmt.Sprintf("%s/go.dwarf", tmpdir)
+ if out, err := exec.Command("dsymutil", "-f", outfile, "-o", dsym).CombinedOutput(); err != nil {
+ Ctxt.Cursym = nil
+ Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
+ }
+ combinedOutput := fmt.Sprintf("%s/go.combined", tmpdir)
+ if err := machoCombineDwarf(outfile, dsym, combinedOutput); err != nil {
+ Ctxt.Cursym = nil
+ Exitf("%s: combining dwarf failed: %v", os.Args[0], err)
+ }
+ origOutput := fmt.Sprintf("%s/go.orig", tmpdir)
+ os.Rename(outfile, origOutput)
+ if err := os.Rename(combinedOutput, outfile); err != nil {
+ Ctxt.Cursym = nil
+ Exitf("%s: rename(%s, %s) failed: %v", os.Args[0], combinedOutput, outfile, err)
+ }
+ }
}
}
@@ -1119,22 +1175,86 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
ldobjfile(Ctxt, f, pkg, eof-obj.Boffset(f), pn)
}
-func ldshlibsyms(shlib string) {
- found := false
- libpath := ""
+func readelfsymboldata(f *elf.File, sym *elf.Symbol) []byte {
+ data := make([]byte, sym.Size)
+ sect := f.Sections[sym.Section]
+ if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
+ Diag("reading %s from non-data section", sym.Name)
+ }
+ n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
+ if uint64(n) != sym.Size {
+ Diag("reading contents of %s: %v", sym.Name, err)
+ }
+ return data
+}
+
+func readwithpad(r io.Reader, sz int32) ([]byte, error) {
+ data := make([]byte, Rnd(int64(sz), 4))
+ _, err := io.ReadFull(r, data)
+ if err != nil {
+ return nil, err
+ }
+ data = data[:sz]
+ return data, nil
+}
+
+func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
+ for _, sect := range f.Sections {
+ if sect.Type != elf.SHT_NOTE {
+ continue
+ }
+ r := sect.Open()
+ for {
+ var namesize, descsize, noteType int32
+ err := binary.Read(r, f.ByteOrder, &namesize)
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return nil, fmt.Errorf("read namesize failed:", err)
+ }
+ err = binary.Read(r, f.ByteOrder, &descsize)
+ if err != nil {
+ return nil, fmt.Errorf("read descsize failed:", err)
+ }
+ err = binary.Read(r, f.ByteOrder, &noteType)
+ if err != nil {
+ return nil, fmt.Errorf("read type failed:", err)
+ }
+ noteName, err := readwithpad(r, namesize)
+ if err != nil {
+ return nil, fmt.Errorf("read name failed:", err)
+ }
+ desc, err := readwithpad(r, descsize)
+ if err != nil {
+ return nil, fmt.Errorf("read desc failed:", err)
+ }
+ if string(name) == string(noteName) && typ == noteType {
+ return desc, nil
+ }
+ }
+ }
+ return nil, nil
+}
+
+func findshlib(shlib string) string {
for _, libdir := range Ctxt.Libdir {
- libpath = filepath.Join(libdir, shlib)
+ libpath := filepath.Join(libdir, shlib)
if _, err := os.Stat(libpath); err == nil {
- found = true
- break
+ return libpath
}
}
- if !found {
- Diag("cannot find shared library: %s", shlib)
+ Diag("cannot find shared library: %s", shlib)
+ return ""
+}
+
+func ldshlibsyms(shlib string) {
+ libpath := findshlib(shlib)
+ if libpath == "" {
return
}
- for _, processedname := range Ctxt.Shlibs {
- if processedname == libpath {
+ for _, processedlib := range Ctxt.Shlibs {
+ if processedlib.Path == libpath {
return
}
}
@@ -1148,85 +1268,48 @@ func ldshlibsyms(shlib string) {
Diag("cannot open shared library: %s", libpath)
return
}
- defer f.Close()
- syms, err := f.Symbols()
+
+ hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
+ if err != nil {
+ Diag("cannot read ABI hash from shared library %s: %v", libpath, err)
+ return
+ }
+
+ depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
+ if err != nil {
+ Diag("cannot read dep list from shared library %s: %v", libpath, err)
+ return
+ }
+ deps := strings.Split(string(depsbytes), "\n")
+
+ syms, err := f.DynamicSymbols()
if err != nil {
Diag("cannot read symbols from shared library: %s", libpath)
return
}
- // If a package has a global variable of a type defined in another shared
- // library, we need to know the gcmask used by the type, if any. To support
- // this, we read all the runtime.gcbits.* symbols, keep a map of address to
- // gcmask, and after we're read all the symbols, read the addresses of the
- // gcmasks symbols out of the type data to look up the gcmask for each type.
- // This depends on the fact that the runtime.gcbits.* symbols are local (so
- // the address is actually present in the type data and we don't have to
- // search all relocations to find the ones which correspond to gcmasks) and
- // also that the shared library we are linking against has not had the symbol
- // table removed.
- gcmasks := make(map[uint64][]byte)
- types := []*LSym{}
for _, s := range syms {
if elf.ST_TYPE(s.Info) == elf.STT_NOTYPE || elf.ST_TYPE(s.Info) == elf.STT_SECTION {
continue
}
- if s.Section == elf.SHN_UNDEF {
- continue
- }
- if strings.HasPrefix(s.Name, "_") {
- continue
- }
- if strings.HasPrefix(s.Name, "runtime.gcbits.0x") {
- data := make([]byte, s.Size)
- sect := f.Sections[s.Section]
- if sect.Type == elf.SHT_PROGBITS {
- n, err := sect.ReadAt(data, int64(s.Value-sect.Offset))
- if uint64(n) != s.Size {
- Diag("Error reading contents of %s: %v", s.Name, err)
- }
- }
- gcmasks[s.Value] = data
- }
- if elf.ST_BIND(s.Info) != elf.STB_GLOBAL {
- continue
- }
lsym := Linklookup(Ctxt, s.Name, 0)
- if lsym.Type != 0 && lsym.Dupok == 0 {
+ if lsym.Type != 0 && lsym.Type != obj.SDYNIMPORT && lsym.Dupok == 0 {
Diag(
"Found duplicate symbol %s reading from %s, first found in %s",
s.Name, shlib, lsym.File)
}
lsym.Type = obj.SDYNIMPORT
lsym.ElfType = elf.ST_TYPE(s.Info)
- lsym.File = libpath
- if strings.HasPrefix(lsym.Name, "type.") {
- data := make([]byte, s.Size)
- sect := f.Sections[s.Section]
- if sect.Type == elf.SHT_PROGBITS {
- n, err := sect.ReadAt(data, int64(s.Value-sect.Offset))
- if uint64(n) != s.Size {
- Diag("Error reading contents of %s: %v", s.Name, err)
- }
- lsym.P = data
- }
- if !strings.HasPrefix(lsym.Name, "type..") {
- types = append(types, lsym)
+ if s.Section != elf.SHN_UNDEF {
+ // Set .File for the library that actually defines the symbol.
+ lsym.File = libpath
+ // The decodetype_* functions in decodetype.go need access to
+ // the type data.
+ if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
+ lsym.P = readelfsymboldata(f, &s)
}
}
}
- for _, t := range types {
- if decodetype_noptr(t) != 0 || decodetype_usegcprog(t) != 0 {
- continue
- }
- addr := decodetype_gcprog_shlib(t)
- tgcmask, ok := gcmasks[addr]
- if !ok {
- Diag("bits not found for %s at %d", t.Name, addr)
- }
- t.gcmask = tgcmask
- }
-
// We might have overwritten some functions above (this tends to happen for the
// autogenerated type equality/hashing functions) and we don't want to generated
// pcln table entries for these any more so unstitch them from the Textp linked
@@ -1254,7 +1337,7 @@ func ldshlibsyms(shlib string) {
Ctxt.Etextp = last
}
- Ctxt.Shlibs = append(Ctxt.Shlibs, libpath)
+ Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f})
}
func mywhatsys() {
@@ -1572,12 +1655,11 @@ func Cflush() {
}
func Cpos() int64 {
- Cflush()
off, err := coutbuf.f.Seek(0, 1)
if err != nil {
Exitf("seeking in output [0, 1]: %v", err)
}
- return off
+ return off + int64(coutbuf.Buffered())
}
func Cseek(p int64) {
@@ -1596,7 +1678,7 @@ func Cput(c uint8) {
}
func usage() {
- fmt.Fprintf(os.Stderr, "usage: %cl [options] obj.%c\n", Thearch.Thechar, Thearch.Thechar)
+ fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n")
obj.Flagprint(2)
Exit(2)
}
diff --git a/src/cmd/internal/ld/link.go b/src/cmd/link/internal/ld/link.go
index 03da52a981..33b17c5985 100644
--- a/src/cmd/internal/ld/link.go
+++ b/src/cmd/link/internal/ld/link.go
@@ -34,6 +34,7 @@ import (
"cmd/internal/obj"
"debug/elf"
"encoding/binary"
+ "fmt"
)
type LSym struct {
@@ -77,13 +78,19 @@ type LSym struct {
File string
Dynimplib string
Dynimpvers string
- Sect interface{}
+ Sect *Section
Autom *Auto
Pcln *Pcln
P []byte
R []Reloc
Local bool
- gcmask []byte
+}
+
+func (s *LSym) String() string {
+ if s.Version == 0 {
+ return s.Name
+ }
+ return fmt.Sprintf("%s<%d>", s.Name, s.Version)
}
type Reloc struct {
@@ -106,6 +113,13 @@ type Auto struct {
Gotype *LSym
}
+type Shlib struct {
+ Path string
+ Hash []byte
+ Deps []string
+ File *elf.File
+}
+
type Link struct {
Thechar int32
Thestring string
@@ -122,8 +136,8 @@ type Link struct {
Nsymbol int32
Tlsg *LSym
Libdir []string
- Library []Library
- Shlibs []string
+ Library []*Library
+ Shlibs []Shlib
Tlsoffset int
Diag func(string, ...interface{})
Cursym *LSym
@@ -149,6 +163,7 @@ type Library struct {
File string
Pkg string
Shlib string
+ hash []byte
}
type Pcln struct {
diff --git a/src/cmd/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index ceeb7b0f5d..3a8a881d97 100644
--- a/src/cmd/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -443,7 +443,8 @@ func Asmbmacho() {
ms = newMachoSeg("", 40)
ms.fileoffset = Segtext.Fileoff
- ms.filesize = Segdata.Fileoff + Segdata.Filelen - Segtext.Fileoff
+ ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff
+ ms.vsize = ms.filesize
}
/* segment for zero page */
@@ -561,8 +562,8 @@ func Asmbmacho() {
}
// TODO: dwarf headers go in ms too
- if Debug['s'] == 0 && Linkmode != LinkExternal {
- dwarfaddmachoheaders()
+ if Debug['s'] == 0 {
+ dwarfaddmachoheaders(ms)
}
a := machowrite()
@@ -705,7 +706,7 @@ func machosymtab() {
Diag("missing section for %s", s.Name)
Adduint8(Ctxt, symtab, 0)
} else {
- Adduint8(Ctxt, symtab, uint8((o.Sect.(*Section)).Extnum))
+ Adduint8(Ctxt, symtab, uint8(o.Sect.Extnum))
}
Adduint16(Ctxt, symtab, 0) // desc
adduintxx(Ctxt, symtab, uint64(Symaddr(s)), Thearch.Ptrsize)
@@ -850,4 +851,5 @@ func Machoemitreloc() {
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
machorelocsect(sect, datap)
}
+ dwarfemitreloc()
}
diff --git a/src/cmd/link/internal/ld/macho_combine_dwarf.go b/src/cmd/link/internal/ld/macho_combine_dwarf.go
new file mode 100644
index 0000000000..9134373a52
--- /dev/null
+++ b/src/cmd/link/internal/ld/macho_combine_dwarf.go
@@ -0,0 +1,369 @@
+// Copyright 2015 The Go 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 ld
+
+import (
+ "bytes"
+ "debug/macho"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+ "unsafe"
+)
+
+var fakedwarf, realdwarf, linkseg *macho.Segment
+var dwarfstart, linkstart int64
+var linkoffset uint32
+var machHeader *macho.FileHeader
+var mappedHeader []byte
+
+const (
+ LC_LOAD_DYLINKER = 0xe
+ LC_PREBOUND_DYLIB = 0x10
+ LC_LOAD_WEAK_DYLIB = 0x18
+ LC_UUID = 0x1b
+ LC_RPATH = 0x8000001c
+ LC_CODE_SIGNATURE = 0x1d
+ LC_SEGMENT_SPLIT_INFO = 0x1e
+ LC_REEXPORT_DYLIB = 0x8000001f
+ LC_ENCRYPTION_INFO = 0x21
+ LC_DYLD_INFO = 0x22
+ LC_DYLD_INFO_ONLY = 0x80000022
+ LC_VERSION_MIN_MACOSX = 0x24
+ LC_VERSION_MIN_IPHONEOS = 0x25
+ LC_FUNCTION_STARTS = 0x26
+ LC_MAIN = 0x80000028
+ LC_DATA_IN_CODE = 0x29
+ LC_SOURCE_VERSION = 0x2A
+ LC_DYLIB_CODE_SIGN_DRS = 0x2B
+ LC_ENCRYPTION_INFO_64 = 0x2C
+
+ dwarfMinAlign = 6 // 64 = 1 << 6
+ pageAlign = 12 // 4096 = 1 << 12
+)
+
+type loadCmd struct {
+ Cmd macho.LoadCmd
+ Len uint32
+}
+
+type dyldInfoCmd struct {
+ Cmd macho.LoadCmd
+ Len uint32
+ RebaseOff, RebaseLen uint32
+ BindOff, BindLen uint32
+ WeakBindOff, WeakBindLen uint32
+ LazyBindOff, LazyBindLen uint32
+ ExportOff, ExportLen uint32
+}
+
+type linkEditDataCmd struct {
+ Cmd macho.LoadCmd
+ Len uint32
+ DataOff, DataLen uint32
+}
+
+type encryptionInfoCmd struct {
+ Cmd macho.LoadCmd
+ Len uint32
+ CryptOff, CryptLen uint32
+ CryptId uint32
+}
+
+type loadCmdReader struct {
+ offset, next int64
+ f *os.File
+ order binary.ByteOrder
+}
+
+func (r *loadCmdReader) Next() (cmd loadCmd, err error) {
+ r.offset = r.next
+ if _, err = r.f.Seek(r.offset, 0); err != nil {
+ return
+ }
+ if err = binary.Read(r.f, r.order, &cmd); err != nil {
+ return
+ }
+ r.next = r.offset + int64(cmd.Len)
+ return
+}
+
+func (r loadCmdReader) ReadAt(offset int64, data interface{}) error {
+ if _, err := r.f.Seek(r.offset+offset, 0); err != nil {
+ return err
+ }
+ return binary.Read(r.f, r.order, data)
+}
+
+func (r loadCmdReader) WriteAt(offset int64, data interface{}) error {
+ if _, err := r.f.Seek(r.offset+offset, 0); err != nil {
+ return err
+ }
+ return binary.Write(r.f, r.order, data)
+}
+
+// machoCombineDwarf merges dwarf info generated by dsymutil into a macho executable.
+// With internal linking, DWARF is embedded into the executable, this lets us do the
+// same for external linking.
+// inexe is the path to the executable with no DWARF. It must have enough room in the macho
+// header to add the DWARF sections. (Use ld's -headerpad option)
+// dsym is the path to the macho file containing DWARF from dsymutil.
+// outexe is the path where the combined executable should be saved.
+func machoCombineDwarf(inexe, dsym, outexe string) error {
+ exef, err := os.Open(inexe)
+ if err != nil {
+ return err
+ }
+ dwarff, err := os.Open(dsym)
+ if err != nil {
+ return err
+ }
+ outf, err := os.Create(outexe)
+ if err != nil {
+ return err
+ }
+ outf.Chmod(0755)
+
+ exem, err := macho.NewFile(exef)
+ if err != nil {
+ return err
+ }
+ dwarfm, err := macho.NewFile(dwarff)
+ if err != nil {
+ return err
+ }
+
+ // The string table needs to be the last thing in the file
+ // for code signing to work. So we'll need to move the
+ // linkedit section, but all the others can be copied directly.
+ linkseg = exem.Segment("__LINKEDIT")
+ if linkseg == nil {
+ return fmt.Errorf("missing __LINKEDIT segment")
+ }
+
+ if _, err = exef.Seek(0, 0); err != nil {
+ return err
+ }
+ if _, err := io.CopyN(outf, exef, int64(linkseg.Offset)); err != nil {
+ return err
+ }
+
+ realdwarf = dwarfm.Segment("__DWARF")
+ if realdwarf == nil {
+ return fmt.Errorf("missing __DWARF segment")
+ }
+
+ // Now copy the dwarf data into the output.
+ maxalign := uint32(dwarfMinAlign) //
+ for _, sect := range dwarfm.Sections {
+ if sect.Align > maxalign {
+ maxalign = sect.Align
+ }
+ }
+ dwarfstart = machoCalcStart(realdwarf.Offset, linkseg.Offset, maxalign)
+ if _, err = outf.Seek(dwarfstart, 0); err != nil {
+ return err
+ }
+
+ if _, err = dwarff.Seek(int64(realdwarf.Offset), 0); err != nil {
+ return err
+ }
+ if _, err := io.CopyN(outf, dwarff, int64(realdwarf.Filesz)); err != nil {
+ return err
+ }
+
+ // And finally the linkedit section.
+ if _, err = exef.Seek(int64(linkseg.Offset), 0); err != nil {
+ return err
+ }
+ linkstart = machoCalcStart(linkseg.Offset, uint64(dwarfstart)+realdwarf.Filesz, pageAlign)
+ linkoffset = uint32(linkstart - int64(linkseg.Offset))
+ if _, err = outf.Seek(linkstart, 0); err != nil {
+ return err
+ }
+ if _, err := io.Copy(outf, exef); err != nil {
+ return err
+ }
+
+ // Now we need to update the headers.
+ cmdOffset := unsafe.Sizeof(exem.FileHeader)
+ is64bit := exem.Magic == macho.Magic64
+ if is64bit {
+ // mach_header_64 has one extra uint32.
+ cmdOffset += unsafe.Sizeof(exem.Magic)
+ }
+
+ textsect := exem.Section("__text")
+ if linkseg == nil {
+ return fmt.Errorf("missing __text section")
+ }
+
+ dwarfCmdOffset := int64(cmdOffset) + int64(exem.FileHeader.Cmdsz)
+ availablePadding := int64(textsect.Offset) - dwarfCmdOffset
+ if availablePadding < int64(realdwarf.Len) {
+ return fmt.Errorf("No room to add dwarf info. Need at least %d padding bytes, found %d", realdwarf.Len, availablePadding)
+ }
+ // First, copy the dwarf load command into the header
+ if _, err = outf.Seek(dwarfCmdOffset, 0); err != nil {
+ return err
+ }
+ if _, err := io.CopyN(outf, bytes.NewReader(realdwarf.Raw()), int64(realdwarf.Len)); err != nil {
+ return err
+ }
+
+ if _, err = outf.Seek(int64(unsafe.Offsetof(exem.FileHeader.Ncmd)), 0); err != nil {
+ return err
+ }
+ if err = binary.Write(outf, exem.ByteOrder, exem.Ncmd+1); err != nil {
+ return err
+ }
+ if err = binary.Write(outf, exem.ByteOrder, exem.Cmdsz+realdwarf.Len); err != nil {
+ return err
+ }
+
+ reader := loadCmdReader{next: int64(cmdOffset), f: outf, order: exem.ByteOrder}
+ for i := uint32(0); i < exem.Ncmd; i++ {
+ cmd, err := reader.Next()
+ if err != nil {
+ return err
+ }
+ switch cmd.Cmd {
+ case macho.LoadCmdSegment64:
+ err = machoUpdateSegment(reader, &macho.Segment64{}, &macho.Section64{})
+ case macho.LoadCmdSegment:
+ err = machoUpdateSegment(reader, &macho.Segment32{}, &macho.Section32{})
+ case LC_DYLD_INFO, LC_DYLD_INFO_ONLY:
+ err = machoUpdateLoadCommand(reader, &dyldInfoCmd{}, "RebaseOff", "BindOff", "WeakBindOff", "LazyBindOff", "ExportOff")
+ case macho.LoadCmdSymtab:
+ err = machoUpdateLoadCommand(reader, &macho.SymtabCmd{}, "Symoff", "Stroff")
+ case macho.LoadCmdDysymtab:
+ err = machoUpdateLoadCommand(reader, &macho.DysymtabCmd{}, "Tocoffset", "Modtaboff", "Extrefsymoff", "Indirectsymoff", "Extreloff", "Locreloff")
+ case LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS:
+ err = machoUpdateLoadCommand(reader, &linkEditDataCmd{}, "DataOff")
+ case LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64:
+ err = machoUpdateLoadCommand(reader, &encryptionInfoCmd{}, "CryptOff")
+ case macho.LoadCmdDylib, macho.LoadCmdThread, macho.LoadCmdUnixThread, LC_PREBOUND_DYLIB, LC_UUID, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_SOURCE_VERSION, LC_MAIN, LC_LOAD_DYLINKER, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_RPATH:
+ // Nothing to update
+ default:
+ err = fmt.Errorf("Unknown load command 0x%x (%s)\n", int(cmd.Cmd), cmd.Cmd)
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return machoUpdateDwarfHeader(&reader)
+}
+
+// machoUpdateSegment updates the load command for a moved segment.
+// Only the linkedit segment should move, and it should have 0 sections.
+// seg should be a macho.Segment32 or macho.Segment64 as appropriate.
+// sect should be a macho.Section32 or macho.Section64 as appropriate.
+func machoUpdateSegment(r loadCmdReader, seg, sect interface{}) error {
+ if err := r.ReadAt(0, seg); err != nil {
+ return err
+ }
+ segValue := reflect.ValueOf(seg)
+ offset := reflect.Indirect(segValue).FieldByName("Offset")
+
+ // Only the linkedit segment moved, any thing before that is fine.
+ if offset.Uint() < linkseg.Offset {
+ return nil
+ }
+ offset.SetUint(offset.Uint() + uint64(linkoffset))
+ if err := r.WriteAt(0, seg); err != nil {
+ return err
+ }
+ // There shouldn't be any sections, but just to make sure...
+ return machoUpdateSections(r, segValue, reflect.ValueOf(sect), uint64(linkoffset))
+}
+
+func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, delta uint64) error {
+ iseg := reflect.Indirect(seg)
+ nsect := iseg.FieldByName("Nsect").Uint()
+ if nsect == 0 {
+ return nil
+ }
+ sectOffset := int64(iseg.Type().Size())
+
+ isect := reflect.Indirect(sect)
+ offsetField := isect.FieldByName("Offset")
+ reloffField := isect.FieldByName("Reloff")
+ sectSize := int64(isect.Type().Size())
+ for i := uint64(0); i < nsect; i++ {
+ if err := r.ReadAt(sectOffset, sect.Interface()); err != nil {
+ return err
+ }
+ if offsetField.Uint() != 0 {
+ offsetField.SetUint(offsetField.Uint() + delta)
+ }
+ if reloffField.Uint() != 0 {
+ reloffField.SetUint(reloffField.Uint() + delta)
+ }
+ if err := r.WriteAt(sectOffset, sect.Interface()); err != nil {
+ return err
+ }
+ sectOffset += sectSize
+ }
+ return nil
+}
+
+// machoUpdateDwarfHeader updates the DWARF segment load command.
+func machoUpdateDwarfHeader(r *loadCmdReader) error {
+ var seg, sect interface{}
+ cmd, err := r.Next()
+ if err != nil {
+ return err
+ }
+ if cmd.Cmd == macho.LoadCmdSegment64 {
+ seg = new(macho.Segment64)
+ sect = new(macho.Section64)
+ } else {
+ seg = new(macho.Segment32)
+ sect = new(macho.Section32)
+ }
+ if err := r.ReadAt(0, seg); err != nil {
+ return err
+ }
+ segValue := reflect.ValueOf(seg)
+ offset := reflect.Indirect(segValue).FieldByName("Offset")
+
+ delta := uint64(dwarfstart) - realdwarf.Offset
+ offset.SetUint(offset.Uint() + delta)
+ if err := r.WriteAt(0, seg); err != nil {
+ return err
+ }
+ return machoUpdateSections(*r, segValue, reflect.ValueOf(sect), delta)
+}
+
+func machoUpdateLoadCommand(r loadCmdReader, cmd interface{}, fields ...string) error {
+ if err := r.ReadAt(0, cmd); err != nil {
+ return err
+ }
+ value := reflect.Indirect(reflect.ValueOf(cmd))
+
+ for _, name := range fields {
+ field := value.FieldByName(name)
+ fieldval := field.Uint()
+ if fieldval >= linkseg.Offset {
+ field.SetUint(fieldval + uint64(linkoffset))
+ }
+ }
+ if err := r.WriteAt(0, cmd); err != nil {
+ return err
+ }
+ return nil
+}
+
+func machoCalcStart(origAddr, newAddr uint64, alignExp uint32) int64 {
+ align := uint64(1 << alignExp)
+ if (origAddr % align) == (newAddr % align) {
+ return int64(newAddr)
+ }
+ padding := (align - (newAddr % align))
+ padding += origAddr % align
+ return int64(padding + newAddr)
+}
diff --git a/src/cmd/internal/ld/objfile.go b/src/cmd/link/internal/ld/objfile.go
index 3d59323dba..613fcb2a40 100644
--- a/src/cmd/internal/ld/objfile.go
+++ b/src/cmd/link/internal/ld/objfile.go
@@ -347,7 +347,7 @@ func rdsym(ctxt *Link, f *obj.Biobuf, pkg string) *LSym {
s.Reachable = false
}
}
- if v == 0 && strings.HasPrefix(s.Name, "runtime.gcbits.0x") {
+ if v == 0 && strings.HasPrefix(s.Name, "runtime.gcbits.") {
s.Local = true
}
return s
diff --git a/src/cmd/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go
index be2568d3b9..be2568d3b9 100644
--- a/src/cmd/internal/ld/pcln.go
+++ b/src/cmd/link/internal/ld/pcln.go
diff --git a/src/cmd/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index cb82c053d8..cb82c053d8 100644
--- a/src/cmd/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
diff --git a/src/cmd/internal/ld/pobj.go b/src/cmd/link/internal/ld/pobj.go
index 8568744c3d..5b24428059 100644
--- a/src/cmd/internal/ld/pobj.go
+++ b/src/cmd/link/internal/ld/pobj.go
@@ -160,10 +160,9 @@ func Ldmain() {
}
if outfile == "" {
+ outfile = "a.out"
if HEADTYPE == obj.Hwindows {
- outfile = fmt.Sprintf("%c.out.exe", Thearch.Thechar)
- } else {
- outfile = fmt.Sprintf("%c.out", Thearch.Thechar)
+ outfile += ".exe"
}
}
diff --git a/src/cmd/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go
index 652109d3e3..652109d3e3 100644
--- a/src/cmd/internal/ld/sym.go
+++ b/src/cmd/link/internal/ld/sym.go
diff --git a/src/cmd/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index d6e79dc00f..7ceb64f941 100644
--- a/src/cmd/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -32,6 +32,8 @@ package ld
import (
"cmd/internal/obj"
+ "fmt"
+ "path/filepath"
"strings"
)
@@ -128,12 +130,12 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
Diag("missing section in putelfsym")
return
}
- if xo.Sect.(*Section).Elfsect == nil {
+ if xo.Sect.Elfsect == nil {
Ctxt.Cursym = x
Diag("missing ELF section in putelfsym")
return
}
- elfshnum = xo.Sect.(*Section).Elfsect.(*ElfShdr).shnum
+ elfshnum = xo.Sect.Elfsect.shnum
}
// One pass for each binding: STB_LOCAL, STB_GLOBAL,
@@ -159,7 +161,7 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
off := putelfstr(s)
if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
- addr -= int64(xo.Sect.(*Section).Vaddr)
+ addr -= int64(xo.Sect.Vaddr)
}
other := STV_DEFAULT
if x.Type&obj.SHIDDEN != 0 {
@@ -294,6 +296,20 @@ func Vputl(v uint64) {
Lputl(uint32(v >> 32))
}
+type byPkg []*Library
+
+func (libs byPkg) Len() int {
+ return len(libs)
+}
+
+func (libs byPkg) Less(a, b int) bool {
+ return libs[a].Pkg < libs[b].Pkg
+}
+
+func (libs byPkg) Swap(a, b int) {
+ libs[a], libs[b] = libs[b], libs[a]
+}
+
func symtab() {
dosymtype()
@@ -410,6 +426,15 @@ func symtab() {
}
}
+ if Buildmode == BuildmodeShared {
+ abihashgostr := Linklookup(Ctxt, "go.link.abihash."+filepath.Base(outfile), 0)
+ abihashgostr.Reachable = true
+ abihashgostr.Type = obj.SRODATA
+ hashsym := Linklookup(Ctxt, "go.link.abihashbytes", 0)
+ Addaddr(Ctxt, abihashgostr, hashsym)
+ adduint(Ctxt, abihashgostr, uint64(hashsym.Size))
+ }
+
// Information about the layout of the executable image for the
// runtime to use. Any changes here must be matched by changes to
// the definition of moduledata in runtime/symtab.go.
@@ -454,6 +479,38 @@ func symtab() {
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0))
adduint(Ctxt, moduledata, uint64(ntypelinks))
adduint(Ctxt, moduledata, uint64(ntypelinks))
+ if len(Ctxt.Shlibs) > 0 {
+ thismodulename := filepath.Base(outfile)
+ if Buildmode == BuildmodeExe {
+ // When linking an executable, outfile is just "a.out". Make
+ // it something slightly more comprehensible.
+ thismodulename = "the executable"
+ }
+ addgostring(moduledata, "go.link.thismodulename", thismodulename)
+
+ modulehashes := Linklookup(Ctxt, "go.link.abihashes", 0)
+ modulehashes.Reachable = true
+ modulehashes.Local = true
+ modulehashes.Type = obj.SRODATA
+
+ for i, shlib := range Ctxt.Shlibs {
+ // modulehashes[i].modulename
+ modulename := filepath.Base(shlib.Path)
+ addgostring(modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
+
+ // modulehashes[i].linktimehash
+ addgostring(modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
+
+ // modulehashes[i].runtimehash
+ abihash := Linklookup(Ctxt, "go.link.abihash."+modulename, 0)
+ abihash.Reachable = true
+ Addaddr(Ctxt, modulehashes, abihash)
+ }
+
+ Addaddr(Ctxt, moduledata, modulehashes)
+ adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
+ adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
+ }
// The rest of moduledata is zero initialized.
// When linking an object that does not contain the runtime we are
// creating the moduledata from scratch and it does not have a
diff --git a/src/cmd/internal/ld/textflag.go b/src/cmd/link/internal/ld/textflag.go
index 335f20d21d..335f20d21d 100644
--- a/src/cmd/internal/ld/textflag.go
+++ b/src/cmd/link/internal/ld/textflag.go
diff --git a/src/cmd/internal/ld/util.go b/src/cmd/link/internal/ld/util.go
index f38f05ce9d..f38f05ce9d 100644
--- a/src/cmd/internal/ld/util.go
+++ b/src/cmd/link/internal/ld/util.go
diff --git a/src/cmd/9l/asm.go b/src/cmd/link/internal/ppc64/asm.go
index 257f23e2ab..f070921ecf 100644
--- a/src/cmd/9l/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -28,34 +28,16 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package ppc64
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"encoding/binary"
"fmt"
"log"
)
-func needlib(name string) int {
- if name[0] == '\x00' {
- return 0
- }
-
- /* reuse hash code in symbol table */
- p := fmt.Sprintf(".dynlib.%s", name)
-
- s := ld.Linklookup(ld.Ctxt, p, 0)
-
- if s.Type == 0 {
- s.Type = 100 // avoid SDATA, etc.
- return 1
- }
-
- return 0
-}
-
func gentext() {
var s *ld.LSym
var stub *ld.LSym
@@ -240,7 +222,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
r.Type = obj.R_ADDR
if targ.Type == obj.SDYNIMPORT {
// These happen in .toc sections
- adddynsym(ld.Ctxt, targ)
+ ld.Adddynsym(ld.Ctxt, targ)
rela := ld.Linklookup(ld.Ctxt, ".rela", 0)
ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off))
@@ -520,7 +502,7 @@ func addpltsym(ctxt *ld.Link, s *ld.LSym) {
return
}
- adddynsym(ctxt, s)
+ ld.Adddynsym(ctxt, s)
if ld.Iself {
plt := ld.Linklookup(ctxt, ".plt", 0)
@@ -622,70 +604,6 @@ func ensureglinkresolver() *ld.LSym {
return glink
}
-func adddynsym(ctxt *ld.Link, s *ld.LSym) {
- if s.Dynid >= 0 {
- return
- }
-
- if ld.Iself {
- s.Dynid = int32(ld.Nelfsym)
- ld.Nelfsym++
-
- d := ld.Linklookup(ctxt, ".dynsym", 0)
-
- name := s.Extname
- ld.Adduint32(ctxt, d, uint32(ld.Addstring(ld.Linklookup(ctxt, ".dynstr", 0), name)))
-
- /* type */
- t := ld.STB_GLOBAL << 4
-
- if s.Cgoexport != 0 && s.Type&obj.SMASK == obj.STEXT {
- t |= ld.STT_FUNC
- } else {
- t |= ld.STT_OBJECT
- }
- ld.Adduint8(ctxt, d, uint8(t))
-
- /* reserved */
- ld.Adduint8(ctxt, d, 0)
-
- /* section where symbol is defined */
- if s.Type == obj.SDYNIMPORT {
- ld.Adduint16(ctxt, d, ld.SHN_UNDEF)
- } else {
- ld.Adduint16(ctxt, d, 1)
- }
-
- /* value */
- if s.Type == obj.SDYNIMPORT {
- ld.Adduint64(ctxt, d, 0)
- } else {
- ld.Addaddr(ctxt, d, s)
- }
-
- /* size of object */
- ld.Adduint64(ctxt, d, uint64(s.Size))
- } else {
- ld.Diag("adddynsym: unsupported binary format")
- }
-}
-
-func adddynlib(lib string) {
- if needlib(lib) == 0 {
- return
- }
-
- if ld.Iself {
- s := ld.Linklookup(ld.Ctxt, ".dynstr", 0)
- if s.Size == 0 {
- ld.Addstring(s, "")
- }
- ld.Elfwritedynent(ld.Linklookup(ld.Ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(s, lib)))
- } else {
- ld.Diag("adddynlib: unsupported binary format")
- }
-}
-
func asmb() {
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
diff --git a/src/cmd/9l/l.go b/src/cmd/link/internal/ppc64/l.go
index e7dc102af2..1275a34dbb 100644
--- a/src/cmd/9l/l.go
+++ b/src/cmd/link/internal/ppc64/l.go
@@ -28,7 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package ppc64
// Writing object files.
@@ -71,7 +71,8 @@ const (
MINLC = 4
)
-/* Used by ../ld/dwarf.c */
+/* Used by ../internal/ld/dwarf.go */
const (
DWARFREGSP = 1
+ DWARFREGLR = 65
)
diff --git a/src/cmd/9l/obj.go b/src/cmd/link/internal/ppc64/obj.go
index 46a92396e4..d663b6ebae 100644
--- a/src/cmd/9l/obj.go
+++ b/src/cmd/link/internal/ppc64/obj.go
@@ -28,18 +28,18 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package ppc64
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"fmt"
"log"
)
// Reading object files.
-func main() {
+func Main() {
linkarchinit()
ld.Ldmain()
}
@@ -60,10 +60,9 @@ func linkarchinit() {
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
+ ld.Thearch.Dwarfreglr = DWARFREGLR
- ld.Thearch.Adddynlib = adddynlib
ld.Thearch.Adddynrel = adddynrel
- ld.Thearch.Adddynsym = adddynsym
ld.Thearch.Archinit = archinit
ld.Thearch.Archreloc = archreloc
ld.Thearch.Archrelocvariant = archrelocvariant
diff --git a/src/cmd/8l/asm.go b/src/cmd/link/internal/x86/asm.go
index 7231379108..d30bd48b4e 100644
--- a/src/cmd/8l/asm.go
+++ b/src/cmd/link/internal/x86/asm.go
@@ -28,33 +28,15 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package x86
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"fmt"
"log"
)
-func needlib(name string) int {
- if name[0] == '\x00' {
- return 0
- }
-
- /* reuse hash code in symbol table */
- p := fmt.Sprintf(".dynlib.%s", name)
-
- s := ld.Linklookup(ld.Ctxt, p, 0)
-
- if s.Type == 0 {
- s.Type = 100 // avoid SDATA, etc.
- return 1
- }
-
- return 0
-}
-
func gentext() {
}
@@ -202,7 +184,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
break
}
if ld.Iself {
- adddynsym(ld.Ctxt, targ)
+ ld.Adddynsym(ld.Ctxt, targ)
rel := ld.Linklookup(ld.Ctxt, ".rel", 0)
ld.Addaddrplus(ld.Ctxt, rel, s, int64(r.Off))
ld.Adduint32(ld.Ctxt, rel, ld.ELF32_R_INFO(uint32(targ.Dynid), ld.R_386_32))
@@ -222,7 +204,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
// just in case the C code assigns to the variable,
// and of course it only works for single pointers,
// but we only need to support cgo and that's all it needs.
- adddynsym(ld.Ctxt, targ)
+ ld.Adddynsym(ld.Ctxt, targ)
got := ld.Linklookup(ld.Ctxt, ".got", 0)
s.Type = got.Type | obj.SSUB
@@ -294,9 +276,9 @@ func machoreloc1(r *ld.Reloc, sectoff int64) int {
v = uint32(rs.Dynid)
v |= 1 << 27 // external relocation
} else {
- v = uint32((rs.Sect.(*ld.Section)).Extnum)
+ v = uint32(rs.Sect.Extnum)
if v == 0 {
- ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, (rs.Sect.(*ld.Section)).Name, rs.Type)
+ ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, rs.Sect.Name, rs.Type)
return -1
}
}
@@ -420,7 +402,7 @@ func addpltsym(ctxt *ld.Link, s *ld.LSym) {
return
}
- adddynsym(ctxt, s)
+ ld.Adddynsym(ctxt, s)
if ld.Iself {
plt := ld.Linklookup(ctxt, ".plt", 0)
@@ -480,7 +462,7 @@ func addgotsym(ctxt *ld.Link, s *ld.LSym) {
return
}
- adddynsym(ctxt, s)
+ ld.Adddynsym(ctxt, s)
got := ld.Linklookup(ctxt, ".got", 0)
s.Got = int32(got.Size)
ld.Adduint32(ctxt, got, 0)
@@ -496,76 +478,6 @@ func addgotsym(ctxt *ld.Link, s *ld.LSym) {
}
}
-func adddynsym(ctxt *ld.Link, s *ld.LSym) {
- if s.Dynid >= 0 {
- return
- }
-
- if ld.Iself {
- s.Dynid = int32(ld.Nelfsym)
- ld.Nelfsym++
-
- d := ld.Linklookup(ctxt, ".dynsym", 0)
-
- /* name */
- name := s.Extname
-
- ld.Adduint32(ctxt, d, uint32(ld.Addstring(ld.Linklookup(ctxt, ".dynstr", 0), name)))
-
- /* value */
- if s.Type == obj.SDYNIMPORT {
- ld.Adduint32(ctxt, d, 0)
- } else {
- ld.Addaddr(ctxt, d, s)
- }
-
- /* size */
- ld.Adduint32(ctxt, d, 0)
-
- /* type */
- t := ld.STB_GLOBAL << 4
-
- if s.Cgoexport != 0 && s.Type&obj.SMASK == obj.STEXT {
- t |= ld.STT_FUNC
- } else {
- t |= ld.STT_OBJECT
- }
- ld.Adduint8(ctxt, d, uint8(t))
- ld.Adduint8(ctxt, d, 0)
-
- /* shndx */
- if s.Type == obj.SDYNIMPORT {
- ld.Adduint16(ctxt, d, ld.SHN_UNDEF)
- } else {
- ld.Adduint16(ctxt, d, 1)
- }
- } else if ld.HEADTYPE == obj.Hdarwin {
- ld.Diag("adddynsym: missed symbol %s (%s)", s.Name, s.Extname)
- } else if ld.HEADTYPE == obj.Hwindows {
- } else // already taken care of
- {
- ld.Diag("adddynsym: unsupported binary format")
- }
-}
-
-func adddynlib(lib string) {
- if needlib(lib) == 0 {
- return
- }
-
- if ld.Iself {
- s := ld.Linklookup(ld.Ctxt, ".dynstr", 0)
- if s.Size == 0 {
- ld.Addstring(s, "")
- }
- ld.Elfwritedynent(ld.Linklookup(ld.Ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(s, lib)))
- } else if ld.HEADTYPE == obj.Hdarwin {
- ld.Machoadddynlib(lib)
- } else if ld.HEADTYPE != obj.Hwindows {
- ld.Diag("adddynlib: unsupported binary format")
- }
-}
-
func asmb() {
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
@@ -639,7 +551,7 @@ func asmb() {
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin:
- symo = uint32(ld.Segdata.Fileoff + uint64(ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))) + uint64(machlink))
+ symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
case obj.Hwindows:
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
diff --git a/src/cmd/8l/l.go b/src/cmd/link/internal/x86/l.go
index 60050857c4..8a811ff0a2 100644
--- a/src/cmd/8l/l.go
+++ b/src/cmd/link/internal/x86/l.go
@@ -28,7 +28,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package x86
const (
thechar = '8'
@@ -40,7 +40,8 @@ const (
MINLC = 1
)
-/* Used by ../ld/dwarf.c */
+/* Used by ../internal/ld/dwarf.go */
const (
DWARFREGSP = 4
+ DWARFREGLR = 8
)
diff --git a/src/cmd/8l/obj.go b/src/cmd/link/internal/x86/obj.go
index 7b490ae87c..ee408f70c6 100644
--- a/src/cmd/8l/obj.go
+++ b/src/cmd/link/internal/x86/obj.go
@@ -28,18 +28,18 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-package main
+package x86
import (
- "cmd/internal/ld"
"cmd/internal/obj"
+ "cmd/link/internal/ld"
"fmt"
"log"
)
// Reading object files.
-func main() {
+func Main() {
linkarchinit()
ld.Ldmain()
}
@@ -56,10 +56,9 @@ func linkarchinit() {
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
+ ld.Thearch.Dwarfreglr = DWARFREGLR
- ld.Thearch.Adddynlib = adddynlib
ld.Thearch.Adddynrel = adddynrel
- ld.Thearch.Adddynsym = adddynsym
ld.Thearch.Archinit = archinit
ld.Thearch.Archreloc = archreloc
ld.Thearch.Archrelocvariant = archrelocvariant
diff --git a/src/cmd/link/main.go b/src/cmd/link/main.go
index b23f3f87b0..0e6c34ee0a 100644
--- a/src/cmd/link/main.go
+++ b/src/cmd/link/main.go
@@ -1,9 +1,34 @@
-// Copyright 2014 The Go Authors. All rights reserved.
+// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Placeholder to keep build building.
-
package main
-func main() {}
+import (
+ "cmd/internal/obj"
+ "cmd/link/internal/amd64"
+ "cmd/link/internal/arm"
+ "cmd/link/internal/arm64"
+ "cmd/link/internal/ppc64"
+ "cmd/link/internal/x86"
+ "fmt"
+ "os"
+)
+
+func main() {
+ switch obj.Getgoarch() {
+ default:
+ fmt.Fprintf(os.Stderr, "link: unknown architecture %q\n", obj.Getgoarch())
+ os.Exit(2)
+ case "386":
+ x86.Main()
+ case "amd64", "amd64p32":
+ amd64.Main()
+ case "arm":
+ arm.Main()
+ case "arm64":
+ arm64.Main()
+ case "ppc64", "ppc64le":
+ ppc64.Main()
+ }
+}
diff --git a/src/cmd/link/auto.go b/src/cmd/newlink/auto.go
index 21f6d60827..21f6d60827 100644
--- a/src/cmd/link/auto.go
+++ b/src/cmd/newlink/auto.go
diff --git a/src/cmd/link/auto_test.go b/src/cmd/newlink/auto_test.go
index f99e097a9c..f99e097a9c 100644
--- a/src/cmd/link/auto_test.go
+++ b/src/cmd/newlink/auto_test.go
diff --git a/src/cmd/link/dead.go b/src/cmd/newlink/dead.go
index ee23a61f81..ee23a61f81 100644
--- a/src/cmd/link/dead.go
+++ b/src/cmd/newlink/dead.go
diff --git a/src/cmd/link/dead_test.go b/src/cmd/newlink/dead_test.go
index eb34d0580d..eb34d0580d 100644
--- a/src/cmd/link/dead_test.go
+++ b/src/cmd/newlink/dead_test.go
diff --git a/src/cmd/link/debug.go b/src/cmd/newlink/debug.go
index ee20644fd0..ee20644fd0 100644
--- a/src/cmd/link/debug.go
+++ b/src/cmd/newlink/debug.go
diff --git a/src/cmd/link/hex_test.go b/src/cmd/newlink/hex_test.go
index b76b266558..b76b266558 100644
--- a/src/cmd/link/hex_test.go
+++ b/src/cmd/newlink/hex_test.go
diff --git a/src/cmd/link/layout.go b/src/cmd/newlink/layout.go
index d5c291e255..d5c291e255 100644
--- a/src/cmd/link/layout.go
+++ b/src/cmd/newlink/layout.go
diff --git a/src/cmd/link/layout_test.go b/src/cmd/newlink/layout_test.go
index e5513af35e..e5513af35e 100644
--- a/src/cmd/link/layout_test.go
+++ b/src/cmd/newlink/layout_test.go
diff --git a/src/cmd/link/link_test.go b/src/cmd/newlink/link_test.go
index b5ae15fc71..b5ae15fc71 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/newlink/link_test.go
diff --git a/src/cmd/link/load.go b/src/cmd/newlink/load.go
index 50602b82a1..50602b82a1 100644
--- a/src/cmd/link/load.go
+++ b/src/cmd/newlink/load.go
diff --git a/src/cmd/link/macho.go b/src/cmd/newlink/macho.go
index 4e5524be9b..4e5524be9b 100644
--- a/src/cmd/link/macho.go
+++ b/src/cmd/newlink/macho.go
diff --git a/src/cmd/link/macho_test.go b/src/cmd/newlink/macho_test.go
index 37c4418b77..37c4418b77 100644
--- a/src/cmd/link/macho_test.go
+++ b/src/cmd/newlink/macho_test.go
diff --git a/src/cmd/newlink/main.go b/src/cmd/newlink/main.go
new file mode 100644
index 0000000000..b23f3f87b0
--- /dev/null
+++ b/src/cmd/newlink/main.go
@@ -0,0 +1,9 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Placeholder to keep build building.
+
+package main
+
+func main() {}
diff --git a/src/cmd/link/pclntab.go b/src/cmd/newlink/pclntab.go
index 7f8bf52a9b..7f8bf52a9b 100644
--- a/src/cmd/link/pclntab.go
+++ b/src/cmd/newlink/pclntab.go
diff --git a/src/cmd/link/pclntab_test.go b/src/cmd/newlink/pclntab_test.go
index ea80806742..ea80806742 100644
--- a/src/cmd/link/pclntab_test.go
+++ b/src/cmd/newlink/pclntab_test.go
diff --git a/src/cmd/link/prog.go b/src/cmd/newlink/prog.go
index 77fb1ece5b..77fb1ece5b 100644
--- a/src/cmd/link/prog.go
+++ b/src/cmd/newlink/prog.go
diff --git a/src/cmd/link/prog_test.go b/src/cmd/newlink/prog_test.go
index 0853506957..0853506957 100644
--- a/src/cmd/link/prog_test.go
+++ b/src/cmd/newlink/prog_test.go
diff --git a/src/cmd/link/runtime.go b/src/cmd/newlink/runtime.go
index acda2d24d6..acda2d24d6 100644
--- a/src/cmd/link/runtime.go
+++ b/src/cmd/newlink/runtime.go
diff --git a/src/cmd/link/scan.go b/src/cmd/newlink/scan.go
index 7feb0d8900..7feb0d8900 100644
--- a/src/cmd/link/scan.go
+++ b/src/cmd/newlink/scan.go
diff --git a/src/cmd/link/testdata/Makefile b/src/cmd/newlink/testdata/Makefile
index 83e8a05195..83e8a05195 100644
--- a/src/cmd/link/testdata/Makefile
+++ b/src/cmd/newlink/testdata/Makefile
diff --git a/src/cmd/link/testdata/autosection.6 b/src/cmd/newlink/testdata/autosection.6
index 34aa5d3dbb..34aa5d3dbb 100644
--- a/src/cmd/link/testdata/autosection.6
+++ b/src/cmd/newlink/testdata/autosection.6
Binary files differ
diff --git a/src/cmd/link/testdata/autosection.s b/src/cmd/newlink/testdata/autosection.s
index e0cb21723e..e0cb21723e 100644
--- a/src/cmd/link/testdata/autosection.s
+++ b/src/cmd/newlink/testdata/autosection.s
diff --git a/src/cmd/link/testdata/autoweak.6 b/src/cmd/newlink/testdata/autoweak.6
index a86b841171..a86b841171 100644
--- a/src/cmd/link/testdata/autoweak.6
+++ b/src/cmd/newlink/testdata/autoweak.6
Binary files differ
diff --git a/src/cmd/link/testdata/autoweak.s b/src/cmd/newlink/testdata/autoweak.s
index 2d11330db2..2d11330db2 100644
--- a/src/cmd/link/testdata/autoweak.s
+++ b/src/cmd/newlink/testdata/autoweak.s
diff --git a/src/cmd/link/testdata/dead.6 b/src/cmd/newlink/testdata/dead.6
index 5e9b09c03e..5e9b09c03e 100644
--- a/src/cmd/link/testdata/dead.6
+++ b/src/cmd/newlink/testdata/dead.6
Binary files differ
diff --git a/src/cmd/link/testdata/dead.s b/src/cmd/newlink/testdata/dead.s
index 86f31360fa..86f31360fa 100644
--- a/src/cmd/link/testdata/dead.s
+++ b/src/cmd/newlink/testdata/dead.s
diff --git a/src/cmd/link/testdata/genpcln.go b/src/cmd/newlink/testdata/genpcln.go
index c10eaeae91..c10eaeae91 100644
--- a/src/cmd/link/testdata/genpcln.go
+++ b/src/cmd/newlink/testdata/genpcln.go
diff --git a/src/cmd/link/testdata/hello.6 b/src/cmd/newlink/testdata/hello.6
index 890cbbd016..890cbbd016 100644
--- a/src/cmd/link/testdata/hello.6
+++ b/src/cmd/newlink/testdata/hello.6
Binary files differ
diff --git a/src/cmd/link/testdata/hello.s b/src/cmd/newlink/testdata/hello.s
index 32ed675033..32ed675033 100644
--- a/src/cmd/link/testdata/hello.s
+++ b/src/cmd/newlink/testdata/hello.s
diff --git a/src/cmd/link/testdata/layout.6 b/src/cmd/newlink/testdata/layout.6
index 748c836255..748c836255 100644
--- a/src/cmd/link/testdata/layout.6
+++ b/src/cmd/newlink/testdata/layout.6
Binary files differ
diff --git a/src/cmd/link/testdata/layout.s b/src/cmd/newlink/testdata/layout.s
index c3e55ef49a..c3e55ef49a 100644
--- a/src/cmd/link/testdata/layout.s
+++ b/src/cmd/newlink/testdata/layout.s
diff --git a/src/cmd/link/testdata/link.hello.darwin.amd64 b/src/cmd/newlink/testdata/link.hello.darwin.amd64
index 4c62eb19b4..4c62eb19b4 100644
--- a/src/cmd/link/testdata/link.hello.darwin.amd64
+++ b/src/cmd/newlink/testdata/link.hello.darwin.amd64
diff --git a/src/cmd/link/testdata/macho.amd64.exit9 b/src/cmd/newlink/testdata/macho.amd64.exit9
index 1adc814c33..1adc814c33 100644
--- a/src/cmd/link/testdata/macho.amd64.exit9
+++ b/src/cmd/newlink/testdata/macho.amd64.exit9
diff --git a/src/cmd/link/testdata/macho.amd64.hello b/src/cmd/newlink/testdata/macho.amd64.hello
index 45e70d0ac5..45e70d0ac5 100644
--- a/src/cmd/link/testdata/macho.amd64.hello
+++ b/src/cmd/newlink/testdata/macho.amd64.hello
diff --git a/src/cmd/link/testdata/macho.amd64.helloro b/src/cmd/newlink/testdata/macho.amd64.helloro
index 4b70fbd0fa..4b70fbd0fa 100644
--- a/src/cmd/link/testdata/macho.amd64.helloro
+++ b/src/cmd/newlink/testdata/macho.amd64.helloro
diff --git a/src/cmd/link/testdata/pclntab.6 b/src/cmd/newlink/testdata/pclntab.6
index 8156698265..8156698265 100644
--- a/src/cmd/link/testdata/pclntab.6
+++ b/src/cmd/newlink/testdata/pclntab.6
Binary files differ
diff --git a/src/cmd/link/testdata/pclntab.s b/src/cmd/newlink/testdata/pclntab.s
index 12dac70b0c..12dac70b0c 100644
--- a/src/cmd/link/testdata/pclntab.s
+++ b/src/cmd/newlink/testdata/pclntab.s
diff --git a/src/cmd/link/util.go b/src/cmd/newlink/util.go
index b8a6b2cb30..b8a6b2cb30 100644
--- a/src/cmd/link/util.go
+++ b/src/cmd/newlink/util.go
diff --git a/src/cmd/link/write.go b/src/cmd/newlink/write.go
index 7e11b2fe71..7e11b2fe71 100644
--- a/src/cmd/link/write.go
+++ b/src/cmd/newlink/write.go
diff --git a/src/cmd/pack/pack_test.go b/src/cmd/pack/pack_test.go
index 9c33f4f98b..cd32020501 100644
--- a/src/cmd/pack/pack_test.go
+++ b/src/cmd/pack/pack_test.go
@@ -13,7 +13,6 @@ import (
"os"
"os/exec"
"path/filepath"
- "regexp"
"runtime"
"testing"
"time"
@@ -223,16 +222,14 @@ func TestHello(t *testing.T) {
t.Fatal(err)
}
- char := findChar(t, dir)
-
run := func(args ...string) string {
return doRun(t, dir, args...)
}
run("go", "build", "cmd/pack") // writes pack binary to dir
- run("go", "tool", char+"g", "hello.go")
- run("./pack", "grc", "hello.a", "hello."+char)
- run("go", "tool", char+"l", "-o", "a.out", "hello.a")
+ run("go", "tool", "compile", "hello.go")
+ run("./pack", "grc", "hello.a", "hello.o")
+ run("go", "tool", "link", "-o", "a.out", "hello.a")
out := run("./a.out")
if out != "hello world\n" {
t.Fatalf("incorrect output: %q, want %q", out, "hello world\n")
@@ -297,17 +294,15 @@ func TestLargeDefs(t *testing.T) {
t.Fatal(err)
}
- char := findChar(t, dir)
-
run := func(args ...string) string {
return doRun(t, dir, args...)
}
run("go", "build", "cmd/pack") // writes pack binary to dir
- run("go", "tool", char+"g", "large.go")
- run("./pack", "grc", "large.a", "large."+char)
- run("go", "tool", char+"g", "-I", ".", "main.go")
- run("go", "tool", char+"l", "-L", ".", "-o", "a.out", "main."+char)
+ run("go", "tool", "compile", "large.go")
+ run("./pack", "grc", "large.a", "large.o")
+ run("go", "tool", "compile", "-I", ".", "main.go")
+ run("go", "tool", "link", "-L", ".", "-o", "a.out", "main.o")
out := run("./a.out")
if out != "ok\n" {
t.Fatalf("incorrect output: %q, want %q", out, "ok\n")
@@ -325,20 +320,6 @@ func doRun(t *testing.T, dir string, args ...string) string {
return string(out)
}
-// findChar returns the architecture character for the go command.
-func findChar(t *testing.T, dir string) string {
- out := doRun(t, dir, "go", "env")
- re, err := regexp.Compile(`\s*GOCHAR=['"]?(\w)['"]?`)
- if err != nil {
- t.Fatal(err)
- }
- fields := re.FindStringSubmatch(out)
- if fields == nil {
- t.Fatal("cannot find GOCHAR in 'go env' output:\n", out)
- }
- return fields[1]
-}
-
// Fake implementation of files.
var helloFile = &FakeFile{
diff --git a/src/cmd/pprof/internal/profile/legacy_profile.go b/src/cmd/pprof/internal/profile/legacy_profile.go
index bfc8110e45..e4c92cdd19 100644
--- a/src/cmd/pprof/internal/profile/legacy_profile.go
+++ b/src/cmd/pprof/internal/profile/legacy_profile.go
@@ -554,9 +554,10 @@ func parseHeap(b []byte) (p *Profile, err error) {
}
}
- if l = strings.TrimSpace(l); l == "" {
+ if isSpaceOrComment(l) {
continue
}
+ l = strings.TrimSpace(l)
if sectionTrigger(l) != unrecognizedSection {
break
diff --git a/src/cmd/yacc/yacc.go b/src/cmd/yacc/yacc.go
index 5c7b0b71b1..53c0fab174 100644
--- a/src/cmd/yacc/yacc.go
+++ b/src/cmd/yacc/yacc.go
@@ -128,6 +128,7 @@ const (
TYPEDEF
TYPENAME
UNION
+ ERROR
)
const ENDFILE = 0
@@ -325,8 +326,24 @@ var resrv = []Resrv{
{"type", TYPEDEF},
{"union", UNION},
{"struct", UNION},
+ {"error", ERROR},
}
+type Error struct {
+ lineno int
+ tokens []string
+ msg string
+}
+
+var errors []Error
+
+type Row struct {
+ actions []int
+ defaultAction int
+}
+
+var stateTable []Row
+
var zznewstate = 0
const EOF = -1
@@ -402,6 +419,27 @@ outer:
}
start = chfind(1, tokname)
+ case ERROR:
+ lno := lineno
+ var tokens []string
+ for {
+ t := gettok()
+ if t == ':' {
+ break
+ }
+ if t != IDENTIFIER && t != IDENTCOLON {
+ errorf("bad syntax in %%error")
+ }
+ tokens = append(tokens, tokname)
+ if t == IDENTCOLON {
+ break
+ }
+ }
+ if gettok() != IDENTIFIER {
+ errorf("bad syntax in %%error")
+ }
+ errors = append(errors, Error{lno, tokens, tokname})
+
case TYPEDEF:
t = gettok()
if t != TYPENAME {
@@ -2155,6 +2193,10 @@ func output() {
}
fmt.Fprintf(ftable, "\nvar %sExca = [...]int{\n", prefix)
+ if len(errors) > 0 {
+ stateTable = make([]Row, nstate)
+ }
+
noset := mkset()
// output the stuff for state i
@@ -2368,6 +2410,15 @@ func wrstate(i int) {
var j0, j1, u int
var pp, qq int
+ if len(errors) > 0 {
+ actions := append([]int(nil), temp1...)
+ defaultAction := ERRCODE
+ if lastred != 0 {
+ defaultAction = -lastred
+ }
+ stateTable[i] = Row{actions, defaultAction}
+ }
+
if foutput == nil {
return
}
@@ -2914,6 +2965,20 @@ func others() {
}
fmt.Fprintf(ftable, "%d,\n}\n", 0)
+ // Custom error messages.
+ fmt.Fprintf(ftable, "\n")
+ fmt.Fprintf(ftable, "var %sErrorMessages = [...]struct {\n", prefix)
+ fmt.Fprintf(ftable, "\tstate int\n")
+ fmt.Fprintf(ftable, "\ttoken int\n")
+ fmt.Fprintf(ftable, "\tmsg string\n")
+ fmt.Fprintf(ftable, "}{\n")
+ for _, error := range errors {
+ lineno = error.lineno
+ state, token := runMachine(error.tokens)
+ fmt.Fprintf(ftable, "\t{%v, %v, %s},\n", state, token, error.msg)
+ }
+ fmt.Fprintf(ftable, "}\n")
+
// copy parser text
ch := getrune(finput)
for ch != EOF {
@@ -2932,6 +2997,59 @@ func others() {
fmt.Fprintf(ftable, "%v", parts[1])
}
+func runMachine(tokens []string) (state, token int) {
+ var stack []int
+ i := 0
+ token = -1
+
+Loop:
+ if token < 0 {
+ token = chfind(2, tokens[i])
+ i++
+ }
+
+ row := stateTable[state]
+
+ c := token
+ if token >= NTBASE {
+ c = token - NTBASE + ntokens
+ }
+ action := row.actions[c]
+ if action == 0 {
+ action = row.defaultAction
+ }
+
+ switch {
+ case action == ACCEPTCODE:
+ errorf("tokens are accepted")
+ return
+ case action == ERRCODE:
+ if token >= NTBASE {
+ errorf("error at non-terminal token %s", symnam(token))
+ }
+ return
+ case action > 0:
+ // Shift to state action.
+ stack = append(stack, state)
+ state = action
+ token = -1
+ goto Loop
+ default:
+ // Reduce by production -action.
+ prod := prdptr[-action]
+ if rhsLen := len(prod) - 2; rhsLen > 0 {
+ n := len(stack) - rhsLen
+ state = stack[n]
+ stack = stack[:n]
+ }
+ if token >= 0 {
+ i--
+ }
+ token = prod[0]
+ goto Loop
+ }
+}
+
func arout(s string, v []int, n int) {
s = prefix + s
fmt.Fprintf(ftable, "var %v = [...]int{\n", s)
@@ -3212,7 +3330,6 @@ type $$Parser interface {
type $$ParserImpl struct {
lookahead func() int
- state func() int
}
func (p *$$ParserImpl) Lookahead() int {
@@ -3222,7 +3339,6 @@ func (p *$$ParserImpl) Lookahead() int {
func $$NewParser() $$Parser {
p := &$$ParserImpl{
lookahead: func() int { return -1 },
- state: func() int { return -1 },
}
return p
}
@@ -3253,6 +3369,13 @@ func $$ErrorMessage(state, lookAhead int) string {
if !$$ErrorVerbose {
return "syntax error"
}
+
+ for _, e := range $$ErrorMessages {
+ if e.state == state && e.token == lookAhead {
+ return "syntax error: " + e.msg
+ }
+ }
+
res := "syntax error: unexpected " + $$Tokname(lookAhead)
// To match Bison, suggest at most four expected tokens.
@@ -3355,7 +3478,6 @@ func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int {
$$state := 0
$$char := -1
$$token := -1 // $$char translated into internal numbering
- $$rcvr.state = func() int { return $$state }
$$rcvr.lookahead = func() int { return $$char }
defer func() {
// Make sure we report no lookahead when not parsing.