aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2020-12-28 00:39:13 -0800
committerMatthew Dempsky <mdempsky@google.com>2020-12-28 00:39:17 -0800
commita800acaae140318896e319edc25845d643d8e273 (patch)
tree0f7c703133787305911b4deb1150702c68f8b739 /src/cmd/compile
parentdd40bbc57bc94be17a553964649696120b9fa180 (diff)
parent07569dac4e7e03715b4171a46c220cd5d4d6295b (diff)
downloadgo-a800acaae140318896e319edc25845d643d8e273.tar.gz
go-a800acaae140318896e319edc25845d643d8e273.zip
[dev.typeparams] all: merge dev.regabi (07569da) into dev.typeparams
Conflicts: - test/fixedbugs/issue27595.go - test/fixedbugs/issue30087.go - test/used.go Merge List: + 2020-12-28 07569dac4e [dev.regabi] all: merge master (1d78139) into dev.regabi + 2020-12-28 76136be027 [dev.regabi] cmd/compile: check for recursive import in ImportBody + 2020-12-28 fda7ec3a3f [dev.regabi] cmd/compile: remove Name.IsDDD, etc + 2020-12-28 098a6490b9 [dev.regabi] cmd/compile: remove Declare in makepartialcall + 2020-12-28 137f0d2e06 [dev.regabi] cmd/compile: remove unnecessary Name.Sym call + 2020-12-28 3383b5c74a [dev.regabi] cmd/compile: flatten dependency graph [generated] + 2020-12-28 f8afb8216a [dev.regabi] cmd/compile: rename CommStmt and CaseStmt [generated] + 2020-12-28 5f3bd59a0d [dev.regabi] cmd/compile: remove some unneeded code in package ir + 2020-12-28 3bdafb0d82 [dev.regabi] cmd/compile: remove CommStmt.List + 2020-12-28 2ecf52b841 [dev.regabi] cmd/compile: separate CommStmt from CaseStmt + 2020-12-28 ed9772e130 [dev.regabi] cmd/compile: add explicit file name in types generation + 2020-12-28 a59d26603f [dev.regabi] cmd/compile: use []*CaseStmt in {Select,Switch}Stmt + 2020-12-28 fbc4458c06 [dev.regabi] cmd/compile: simplify some tree traversal code + 2020-12-28 6c67677541 [dev.regabi] cmd/compile: simplify FuncName and PkgFuncName + 2020-12-28 676d794b81 [dev.regabi] cmd/compile: remove refersToCommonName + 2020-12-28 c98548e110 [dev.regabi] cmd/compile: merge ascompatee, ascompatee1, and reorder3 + 2020-12-28 4c215c4fa9 [dev.regabi] cmd/compile: simplify and optimize reorder3 + 2020-12-28 e6c973198d [dev.regabi] cmd/compile: stop mangling SelectorExpr.Sel for ODOTMETH + 2020-12-28 135ce1c485 [dev.regabi] cmd/compile: desugar OMETHEXPR into ONAME during walk + 2020-12-28 0f732f8c91 [dev.regabi] cmd/compile: minor walkExpr cleanups + 2020-12-28 0de8eafd98 [dev.regabi] cmd/compile: remove SelectorExpr.Offset field + 2020-12-28 a4f335f420 [dev.regabi] cmd/compile: always use a Field for ODOTPTR expressions + 2020-12-26 1d78139128 runtime/cgo: fix Android build with NDK 22 + 2020-12-25 2018b68a65 net/mail: don't use MDT in test + 2020-12-25 e4f293d853 [dev.regabi] cmd/compile: fix OCALLMETH desugaring + 2020-12-25 1d9a1f67d5 [dev.regabi] cmd/compile: don't emit reflect data for method types + 2020-12-25 396b6c2e7c [dev.regabi] cmd/compile: cleanup assignment typechecking + 2020-12-25 e24d2f3d05 [dev.regabi] cmd/compile: remove typ from RangeStmt + 2020-12-25 2785c691c2 [dev.regabi] cmd/compile: cleanup devirtualization docs + 2020-12-25 4b1d0fe66f [dev.regabi] cmd/compile: new devirtualization pkg [generated] + 2020-12-24 082cc8b7d9 [dev.regabi] cmd/compile: change ir.IsAssignable -> ir.IsAddressable + 2020-12-24 27b248b307 [dev.regabi] cmd/compile: separate range stmt Vars to Key, Value nodes + 2020-12-23 40818038bf [dev.regabi] cmd/compile: change CaseStmt.Vars to Var + 2020-12-23 b116404444 runtime: shift timeHistogram buckets and allow negative durations + 2020-12-23 8db7e2fecd runtime: fix allocs-by-size and frees-by-size buckets + 2020-12-23 fb96f07e1a runtime: fix nStackRoots comment about stack roots + 2020-12-23 d1502b3c72 lib/time, time/tzdata: update tzdata to 2020e + 2020-12-23 30c99cbb7a cmd/go: add the Retract field to 'go help mod edit' definition of the GoMod struct + 2020-12-23 49d0b239cb doc: fix a typo in contribute.html + 2020-12-23 9eeed291bc [dev.regabi] cmd/compile: eliminate usage of ir.Node in liveness + 2020-12-23 d1d64e4cea [dev.regabi] cmd/compile: split SliceExpr.List into separate fields + 2020-12-23 98a73030b0 cmd/go: in 'go get', promote named implicit dependencies to explicit + 2020-12-23 d19018e8f1 [dev.regabi] cmd/compile: split SliceHeaderExpr.LenCap into separate fields + 2020-12-23 53f082b0ee [dev.regabi] cmd/compile: cleanup export code further + 2020-12-23 31267f82e1 [dev.regabi] cmd/compile: simplify function/interface/struct typechecking + 2020-12-23 addade2cce [dev.regabi] cmd/compile: prefer types constructors over typecheck + 2020-12-23 18ebfb49e9 [dev.regabi] cmd/compile: cleanup noder + 2020-12-23 87a592b356 [dev.regabi] cmd/compile: cleanup import/export code + 2020-12-23 5898025026 [dev.regabi] cmd/compile: update mkbuiltin.go to use new type constructors + 2020-12-23 63c96c2ee7 [dev.regabi] cmd/compile: update mkbuiltin.go and re-enable TestBuiltin + 2020-12-23 fd6ba1c8a2 os/signal: fix a deadlock with syscall.AllThreadsSyscall() use + 2020-12-23 b0b0d98283 runtime: linux iscgo support for not blocking nptl signals + 2020-12-22 223331fc0c cmd/go/internal/modload: add hint for missing implicit dependency Change-Id: Iecb8a7dfb401b6ab383e97101cd81bfc201683f6
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/devirtualize/devirtualize.go85
-rw-r--r--src/cmd/compile/internal/escape/escape.go29
-rw-r--r--src/cmd/compile/internal/gc/main.go3
-rw-r--r--src/cmd/compile/internal/inline/inl.go91
-rw-r--r--src/cmd/compile/internal/ir/expr.go80
-rw-r--r--src/cmd/compile/internal/ir/fmt.go37
-rw-r--r--src/cmd/compile/internal/ir/func.go38
-rw-r--r--src/cmd/compile/internal/ir/mknode.go18
-rw-r--r--src/cmd/compile/internal/ir/name.go3
-rw-r--r--src/cmd/compile/internal/ir/node_gen.go70
-rw-r--r--src/cmd/compile/internal/ir/scc.go49
-rw-r--r--src/cmd/compile/internal/ir/stmt.go121
-rw-r--r--src/cmd/compile/internal/ir/type.go28
-rw-r--r--src/cmd/compile/internal/ir/visit.go3
-rw-r--r--src/cmd/compile/internal/liveness/plive.go107
-rw-r--r--src/cmd/compile/internal/noder/noder.go119
-rw-r--r--src/cmd/compile/internal/objw/prog.go12
-rw-r--r--src/cmd/compile/internal/pkginit/initorder.go6
-rw-r--r--src/cmd/compile/internal/reflectdata/alg.go22
-rw-r--r--src/cmd/compile/internal/reflectdata/reflect.go15
-rw-r--r--src/cmd/compile/internal/ssa/numberlines.go10
-rw-r--r--src/cmd/compile/internal/ssagen/ssa.go119
-rw-r--r--src/cmd/compile/internal/staticinit/sched.go2
-rw-r--r--src/cmd/compile/internal/typebits/typebits.go87
-rw-r--r--src/cmd/compile/internal/typecheck/builtin.go189
-rw-r--r--src/cmd/compile/internal/typecheck/builtin_test.go1
-rw-r--r--src/cmd/compile/internal/typecheck/const.go2
-rw-r--r--src/cmd/compile/internal/typecheck/dcl.go126
-rw-r--r--src/cmd/compile/internal/typecheck/expr.go50
-rw-r--r--src/cmd/compile/internal/typecheck/func.go55
-rw-r--r--src/cmd/compile/internal/typecheck/iexport.go82
-rw-r--r--src/cmd/compile/internal/typecheck/iimport.go142
-rw-r--r--src/cmd/compile/internal/typecheck/mkbuiltin.go14
-rw-r--r--src/cmd/compile/internal/typecheck/stmt.go369
-rw-r--r--src/cmd/compile/internal/typecheck/type.go72
-rw-r--r--src/cmd/compile/internal/typecheck/typecheck.go37
-rw-r--r--src/cmd/compile/internal/types/alg.go2
-rw-r--r--src/cmd/compile/internal/types/algkind_string.go2
-rw-r--r--src/cmd/compile/internal/types/fmt.go14
-rw-r--r--src/cmd/compile/internal/types/goversion.go2
-rw-r--r--src/cmd/compile/internal/types/kind_string.go (renamed from src/cmd/compile/internal/types/etype_string.go)12
-rw-r--r--src/cmd/compile/internal/types/type.go4
-rw-r--r--src/cmd/compile/internal/walk/assign.go390
-rw-r--r--src/cmd/compile/internal/walk/builtin.go17
-rw-r--r--src/cmd/compile/internal/walk/compare.go12
-rw-r--r--src/cmd/compile/internal/walk/complit.go5
-rw-r--r--src/cmd/compile/internal/walk/convert.go4
-rw-r--r--src/cmd/compile/internal/walk/expr.go119
-rw-r--r--src/cmd/compile/internal/walk/order.go29
-rw-r--r--src/cmd/compile/internal/walk/range.go30
-rw-r--r--src/cmd/compile/internal/walk/select.go24
-rw-r--r--src/cmd/compile/internal/walk/switch.go48
-rw-r--r--src/cmd/compile/internal/walk/walk.go30
53 files changed, 1281 insertions, 1756 deletions
diff --git a/src/cmd/compile/internal/devirtualize/devirtualize.go b/src/cmd/compile/internal/devirtualize/devirtualize.go
new file mode 100644
index 0000000000..60ba208d08
--- /dev/null
+++ b/src/cmd/compile/internal/devirtualize/devirtualize.go
@@ -0,0 +1,85 @@
+// Copyright 2020 The Go 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 devirtualize implements a simple "devirtualization"
+// optimization pass, which replaces interface method calls with
+// direct concrete-type method calls where possible.
+package devirtualize
+
+import (
+ "cmd/compile/internal/base"
+ "cmd/compile/internal/ir"
+ "cmd/compile/internal/typecheck"
+ "cmd/compile/internal/types"
+)
+
+// Func devirtualizes calls within fn where possible.
+func Func(fn *ir.Func) {
+ ir.CurFunc = fn
+ ir.VisitList(fn.Body, func(n ir.Node) {
+ if call, ok := n.(*ir.CallExpr); ok {
+ Call(call)
+ }
+ })
+}
+
+// Call devirtualizes the given call if possible.
+func Call(call *ir.CallExpr) {
+ if call.Op() != ir.OCALLINTER {
+ return
+ }
+ sel := call.X.(*ir.SelectorExpr)
+ r := ir.StaticValue(sel.X)
+ if r.Op() != ir.OCONVIFACE {
+ return
+ }
+ recv := r.(*ir.ConvExpr)
+
+ typ := recv.X.Type()
+ if typ.IsInterface() {
+ return
+ }
+
+ dt := ir.NewTypeAssertExpr(sel.Pos(), sel.X, nil)
+ dt.SetType(typ)
+ x := typecheck.Callee(ir.NewSelectorExpr(sel.Pos(), ir.OXDOT, dt, sel.Sel))
+ switch x.Op() {
+ case ir.ODOTMETH:
+ x := x.(*ir.SelectorExpr)
+ if base.Flag.LowerM != 0 {
+ base.WarnfAt(call.Pos(), "devirtualizing %v to %v", sel, typ)
+ }
+ call.SetOp(ir.OCALLMETH)
+ call.X = x
+ case ir.ODOTINTER:
+ // Promoted method from embedded interface-typed field (#42279).
+ x := x.(*ir.SelectorExpr)
+ if base.Flag.LowerM != 0 {
+ base.WarnfAt(call.Pos(), "partially devirtualizing %v to %v", sel, typ)
+ }
+ call.SetOp(ir.OCALLINTER)
+ call.X = x
+ default:
+ // TODO(mdempsky): Turn back into Fatalf after more testing.
+ if base.Flag.LowerM != 0 {
+ base.WarnfAt(call.Pos(), "failed to devirtualize %v (%v)", x, x.Op())
+ }
+ return
+ }
+
+ // Duplicated logic from typecheck for function call return
+ // value types.
+ //
+ // Receiver parameter size may have changed; need to update
+ // call.Type to get correct stack offsets for result
+ // parameters.
+ types.CheckSize(x.Type())
+ switch ft := x.Type(); ft.NumResults() {
+ case 0:
+ case 1:
+ call.SetType(ft.Results().Field(0).Type)
+ default:
+ call.SetType(ft.Results())
+ }
+}
diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go
index b7cb56b997..d8f0111d2d 100644
--- a/src/cmd/compile/internal/escape/escape.go
+++ b/src/cmd/compile/internal/escape/escape.go
@@ -347,21 +347,19 @@ func (e *escape) stmt(n ir.Node) {
e.loopDepth--
case ir.ORANGE:
- // for List = range Right { Nbody }
+ // for Key, Value = range X { Body }
n := n.(*ir.RangeStmt)
e.loopDepth++
- ks := e.addrs(n.Vars)
+ e.addr(n.Key)
+ k := e.addr(n.Value)
e.block(n.Body)
e.loopDepth--
- // Right is evaluated outside the loop.
- k := e.discardHole()
- if len(ks) >= 2 {
- if n.X.Type().IsArray() {
- k = ks[1].note(n, "range")
- } else {
- k = ks[1].deref(n, "range-deref")
- }
+ // X is evaluated outside the loop.
+ if n.X.Type().IsArray() {
+ k = k.note(n, "range")
+ } else {
+ k = k.deref(n, "range-deref")
}
e.expr(e.later(k), n.X)
@@ -371,9 +369,8 @@ func (e *escape) stmt(n ir.Node) {
var ks []hole
for _, cas := range n.Cases { // cases
- cas := cas.(*ir.CaseStmt)
if typesw && n.Tag.(*ir.TypeSwitchGuard).Tag != nil {
- cv := cas.Vars[0]
+ cv := cas.Var
k := e.dcl(cv) // type switch variables have no ODCL.
if cv.Type().HasPointers() {
ks = append(ks, k.dotType(cv.Type(), cas, "switch case"))
@@ -393,7 +390,6 @@ func (e *escape) stmt(n ir.Node) {
case ir.OSELECT:
n := n.(*ir.SelectStmt)
for _, cas := range n.Cases {
- cas := cas.(*ir.CaseStmt)
e.stmt(cas.Comm)
e.block(cas.Body)
}
@@ -559,10 +555,9 @@ func (e *escape) exprSkipInit(k hole, n ir.Node) {
case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR:
n := n.(*ir.SliceExpr)
e.expr(k.note(n, "slice"), n.X)
- low, high, max := n.SliceBounds()
- e.discard(low)
- e.discard(high)
- e.discard(max)
+ e.discard(n.Low)
+ e.discard(n.High)
+ e.discard(n.Max)
case ir.OCONV, ir.OCONVNOP:
n := n.(*ir.ConvExpr)
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index c5870c650a..6fc9695d41 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -10,6 +10,7 @@ import (
"bufio"
"bytes"
"cmd/compile/internal/base"
+ "cmd/compile/internal/devirtualize"
"cmd/compile/internal/dwarfgen"
"cmd/compile/internal/escape"
"cmd/compile/internal/inline"
@@ -243,7 +244,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
// Devirtualize.
for _, n := range typecheck.Target.Decls {
if n.Op() == ir.ODCLFUNC {
- inline.Devirtualize(n.(*ir.Func))
+ devirtualize.Func(n.(*ir.Func))
}
}
ir.CurFunc = nil
diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go
index 222e62d0cc..67162771e9 100644
--- a/src/cmd/compile/internal/inline/inl.go
+++ b/src/cmd/compile/internal/inline/inl.go
@@ -324,19 +324,17 @@ func (v *hairyVisitor) doNode(n ir.Node) error {
if t == nil {
base.Fatalf("no function type for [%p] %+v\n", n.X, n.X)
}
- if types.IsRuntimePkg(n.X.Sym().Pkg) {
- fn := n.X.Sym().Name
- if fn == "heapBits.nextArena" {
- // Special case: explicitly allow
- // mid-stack inlining of
- // runtime.heapBits.next even though
- // it calls slow-path
- // runtime.heapBits.nextArena.
- break
- }
+ fn := ir.MethodExprName(n.X).Func
+ if types.IsRuntimePkg(fn.Sym().Pkg) && fn.Sym().Name == "heapBits.nextArena" {
+ // Special case: explicitly allow
+ // mid-stack inlining of
+ // runtime.heapBits.next even though
+ // it calls slow-path
+ // runtime.heapBits.nextArena.
+ break
}
- if inlfn := ir.MethodExprName(n.X).Func; inlfn.Inl != nil {
- v.budget -= inlfn.Inl.Cost
+ if fn.Inl != nil {
+ v.budget -= fn.Inl.Cost
break
}
// Call cost for non-leaf inlining.
@@ -531,7 +529,7 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
// Prevent inlining some reflect.Value methods when using checkptr,
// even when package reflect was compiled without it (#35073).
n := n.(*ir.CallExpr)
- if s := n.X.Sym(); base.Debug.Checkptr != 0 && types.IsReflectPkg(s.Pkg) && (s.Name == "Value.UnsafeAddr" || s.Name == "Value.Pointer") {
+ if s := ir.MethodExprName(n.X).Sym(); base.Debug.Checkptr != 0 && types.IsReflectPkg(s.Pkg) && (s.Name == "Value.UnsafeAddr" || s.Name == "Value.Pointer") {
return n
}
}
@@ -1203,73 +1201,6 @@ func pruneUnusedAutos(ll []*ir.Name, vis *hairyVisitor) []*ir.Name {
return s
}
-// Devirtualize replaces interface method calls within fn with direct
-// concrete-type method calls where applicable.
-func Devirtualize(fn *ir.Func) {
- ir.CurFunc = fn
- ir.VisitList(fn.Body, func(n ir.Node) {
- if n.Op() == ir.OCALLINTER {
- devirtualizeCall(n.(*ir.CallExpr))
- }
- })
-}
-
-func devirtualizeCall(call *ir.CallExpr) {
- sel := call.X.(*ir.SelectorExpr)
- r := ir.StaticValue(sel.X)
- if r.Op() != ir.OCONVIFACE {
- return
- }
- recv := r.(*ir.ConvExpr)
-
- typ := recv.X.Type()
- if typ.IsInterface() {
- return
- }
-
- dt := ir.NewTypeAssertExpr(sel.Pos(), sel.X, nil)
- dt.SetType(typ)
- x := typecheck.Callee(ir.NewSelectorExpr(sel.Pos(), ir.OXDOT, dt, sel.Sel))
- switch x.Op() {
- case ir.ODOTMETH:
- x := x.(*ir.SelectorExpr)
- if base.Flag.LowerM != 0 {
- base.WarnfAt(call.Pos(), "devirtualizing %v to %v", sel, typ)
- }
- call.SetOp(ir.OCALLMETH)
- call.X = x
- case ir.ODOTINTER:
- // Promoted method from embedded interface-typed field (#42279).
- x := x.(*ir.SelectorExpr)
- if base.Flag.LowerM != 0 {
- base.WarnfAt(call.Pos(), "partially devirtualizing %v to %v", sel, typ)
- }
- call.SetOp(ir.OCALLINTER)
- call.X = x
- default:
- // TODO(mdempsky): Turn back into Fatalf after more testing.
- if base.Flag.LowerM != 0 {
- base.WarnfAt(call.Pos(), "failed to devirtualize %v (%v)", x, x.Op())
- }
- return
- }
-
- // Duplicated logic from typecheck for function call return
- // value types.
- //
- // Receiver parameter size may have changed; need to update
- // call.Type to get correct stack offsets for result
- // parameters.
- types.CheckSize(x.Type())
- switch ft := x.Type(); ft.NumResults() {
- case 0:
- case 1:
- call.SetType(ft.Results().Field(0).Type)
- default:
- call.SetType(ft.Results())
- }
-}
-
// numNonClosures returns the number of functions in list which are not closures.
func numNonClosures(list []*ir.Func) int {
count := 0
diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go
index 640cc03954..1337d356a1 100644
--- a/src/cmd/compile/internal/ir/expr.go
+++ b/src/cmd/compile/internal/ir/expr.go
@@ -572,14 +572,12 @@ type SelectorExpr struct {
miniExpr
X Node
Sel *types.Sym
- Offset int64
Selection *types.Field
}
func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr {
n := &SelectorExpr{X: x, Sel: sel}
n.pos = pos
- n.Offset = types.BADWIDTH
n.SetOp(op)
return n
}
@@ -596,6 +594,7 @@ func (n *SelectorExpr) SetOp(op Op) {
func (n *SelectorExpr) Sym() *types.Sym { return n.Sel }
func (n *SelectorExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
func (n *SelectorExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
+func (n *SelectorExpr) Offset() int64 { return n.Selection.Offset }
// Before type-checking, bytes.Buffer is a SelectorExpr.
// After type-checking it becomes a Name.
@@ -605,11 +604,13 @@ func (*SelectorExpr) CanBeNtype() {}
type SliceExpr struct {
miniExpr
X Node
- List Nodes // TODO(rsc): Use separate Nodes
+ Low Node
+ High Node
+ Max Node
}
-func NewSliceExpr(pos src.XPos, op Op, x Node) *SliceExpr {
- n := &SliceExpr{X: x}
+func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr {
+ n := &SliceExpr{X: x, Low: low, High: high, Max: max}
n.pos = pos
n.op = op
return n
@@ -624,61 +625,6 @@ func (n *SliceExpr) SetOp(op Op) {
}
}
-// SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max].
-// n must be a slice expression. max is nil if n is a simple slice expression.
-func (n *SliceExpr) SliceBounds() (low, high, max Node) {
- if len(n.List) == 0 {
- return nil, nil, nil
- }
-
- switch n.Op() {
- case OSLICE, OSLICEARR, OSLICESTR:
- s := n.List
- return s[0], s[1], nil
- case OSLICE3, OSLICE3ARR:
- s := n.List
- return s[0], s[1], s[2]
- }
- base.Fatalf("SliceBounds op %v: %v", n.Op(), n)
- return nil, nil, nil
-}
-
-// SetSliceBounds sets n's slice bounds, where n is a slice expression.
-// n must be a slice expression. If max is non-nil, n must be a full slice expression.
-func (n *SliceExpr) SetSliceBounds(low, high, max Node) {
- switch n.Op() {
- case OSLICE, OSLICEARR, OSLICESTR:
- if max != nil {
- base.Fatalf("SetSliceBounds %v given three bounds", n.Op())
- }
- s := n.List
- if s == nil {
- if low == nil && high == nil {
- return
- }
- n.List = []Node{low, high}
- return
- }
- s[0] = low
- s[1] = high
- return
- case OSLICE3, OSLICE3ARR:
- s := n.List
- if s == nil {
- if low == nil && high == nil && max == nil {
- return
- }
- n.List = []Node{low, high, max}
- return
- }
- s[0] = low
- s[1] = high
- s[2] = max
- return
- }
- base.Fatalf("SetSliceBounds op %v: %v", n.Op(), n)
-}
-
// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR).
// o must be a slicing op.
func (o Op) IsSlice3() bool {
@@ -695,16 +641,16 @@ func (o Op) IsSlice3() bool {
// A SliceHeader expression constructs a slice header from its parts.
type SliceHeaderExpr struct {
miniExpr
- Ptr Node
- LenCap Nodes // TODO(rsc): Split into two Node fields
+ Ptr Node
+ Len Node
+ Cap Node
}
func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr {
- n := &SliceHeaderExpr{Ptr: ptr}
+ n := &SliceHeaderExpr{Ptr: ptr, Len: len, Cap: cap}
n.pos = pos
n.op = OSLICEHEADER
n.typ = typ
- n.LenCap = []Node{len, cap}
return n
}
@@ -829,12 +775,12 @@ func IsZero(n Node) bool {
}
// lvalue etc
-func IsAssignable(n Node) bool {
+func IsAddressable(n Node) bool {
switch n.Op() {
case OINDEX:
n := n.(*IndexExpr)
if n.X.Type() != nil && n.X.Type().IsArray() {
- return IsAssignable(n.X)
+ return IsAddressable(n.X)
}
if n.X.Type() != nil && n.X.Type().IsString() {
return false
@@ -845,7 +791,7 @@ func IsAssignable(n Node) bool {
case ODOT:
n := n.(*SelectorExpr)
- return IsAssignable(n.X)
+ return IsAddressable(n.X)
case ONAME:
n := n.(*Name)
diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go
index 2682908539..49f451a5d8 100644
--- a/src/cmd/compile/internal/ir/fmt.go
+++ b/src/cmd/compile/internal/ir/fmt.go
@@ -444,12 +444,15 @@ func stmtFmt(n Node, s fmt.State) {
break
}
- if len(n.Vars) == 0 {
- fmt.Fprintf(s, "for range %v { %v }", n.X, n.Body)
- break
+ fmt.Fprint(s, "for")
+ if n.Key != nil {
+ fmt.Fprintf(s, " %v", n.Key)
+ if n.Value != nil {
+ fmt.Fprintf(s, ", %v", n.Value)
+ }
+ fmt.Fprint(s, " =")
}
-
- fmt.Fprintf(s, "for %.v = range %v { %v }", n.Vars, n.X, n.Body)
+ fmt.Fprintf(s, " range %v { %v }", n.X, n.Body)
case OSELECT:
n := n.(*SelectStmt)
@@ -475,7 +478,7 @@ func stmtFmt(n Node, s fmt.State) {
fmt.Fprintf(s, " { %v }", n.Cases)
case OCASE:
- n := n.(*CaseStmt)
+ n := n.(*CaseClause)
if len(n.List) != 0 {
fmt.Fprintf(s, "case %.v", n.List)
} else {
@@ -753,7 +756,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
fmt.Fprint(s, ".<nil>")
return
}
- fmt.Fprintf(s, ".%s", types.SymMethodName(n.Method.Sym))
+ fmt.Fprintf(s, ".%s", n.Method.Sym.Name)
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
n := n.(*SelectorExpr)
@@ -762,7 +765,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
fmt.Fprint(s, ".<nil>")
return
}
- fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sel))
+ fmt.Fprintf(s, ".%s", n.Sel.Name)
case ODOTTYPE, ODOTTYPE2:
n := n.(*TypeAssertExpr)
@@ -782,28 +785,24 @@ func exprFmt(n Node, s fmt.State, prec int) {
n := n.(*SliceExpr)
exprFmt(n.X, s, nprec)
fmt.Fprint(s, "[")
- low, high, max := n.SliceBounds()
- if low != nil {
- fmt.Fprint(s, low)
+ if n.Low != nil {
+ fmt.Fprint(s, n.Low)
}
fmt.Fprint(s, ":")
- if high != nil {
- fmt.Fprint(s, high)
+ if n.High != nil {
+ fmt.Fprint(s, n.High)
}
if n.Op().IsSlice3() {
fmt.Fprint(s, ":")
- if max != nil {
- fmt.Fprint(s, max)
+ if n.Max != nil {
+ fmt.Fprint(s, n.Max)
}
}
fmt.Fprint(s, "]")
case OSLICEHEADER:
n := n.(*SliceHeaderExpr)
- if len(n.LenCap) != 2 {
- base.Fatalf("bad OSLICEHEADER list length %d", len(n.LenCap))
- }
- fmt.Fprintf(s, "sliceheader{%v,%v,%v}", n.Ptr, n.LenCap[0], n.LenCap[1])
+ fmt.Fprintf(s, "sliceheader{%v,%v,%v}", n.Ptr, n.Len, n.Cap)
case OCOMPLEX, OCOPY:
n := n.(*BinaryExpr)
diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go
index 6bc8cd574c..16d67f6ae0 100644
--- a/src/cmd/compile/internal/ir/func.go
+++ b/src/cmd/compile/internal/ir/func.go
@@ -206,50 +206,22 @@ func (f *Func) SetWBPos(pos src.XPos) {
}
// funcname returns the name (without the package) of the function n.
-func FuncName(n Node) string {
- var f *Func
- switch n := n.(type) {
- case *Func:
- f = n
- case *Name:
- f = n.Func
- case *CallPartExpr:
- f = n.Func
- case *ClosureExpr:
- f = n.Func
- }
+func FuncName(f *Func) string {
if f == nil || f.Nname == nil {
return "<nil>"
}
- return f.Nname.Sym().Name
+ return f.Sym().Name
}
// pkgFuncName returns the name of the function referenced by n, with package prepended.
// This differs from the compiler's internal convention where local functions lack a package
// because the ultimate consumer of this is a human looking at an IDE; package is only empty
// if the compilation package is actually the empty string.
-func PkgFuncName(n Node) string {
- var s *types.Sym
- if n == nil {
+func PkgFuncName(f *Func) string {
+ if f == nil || f.Nname == nil {
return "<nil>"
}
- if n.Op() == ONAME {
- s = n.Sym()
- } else {
- var f *Func
- switch n := n.(type) {
- case *CallPartExpr:
- f = n.Func
- case *ClosureExpr:
- f = n.Func
- case *Func:
- f = n
- }
- if f == nil || f.Nname == nil {
- return "<nil>"
- }
- s = f.Nname.Sym()
- }
+ s := f.Sym()
pkg := s.Pkg
p := base.Ctxt.Pkgpath
diff --git a/src/cmd/compile/internal/ir/mknode.go b/src/cmd/compile/internal/ir/mknode.go
index f5dacee622..3b5da32d8c 100644
--- a/src/cmd/compile/internal/ir/mknode.go
+++ b/src/cmd/compile/internal/ir/mknode.go
@@ -37,6 +37,8 @@ func main() {
nodeType := lookup("Node")
ntypeType := lookup("Ntype")
nodesType := lookup("Nodes")
+ slicePtrCaseClauseType := types.NewSlice(types.NewPointer(lookup("CaseClause")))
+ slicePtrCommClauseType := types.NewSlice(types.NewPointer(lookup("CommClause")))
ptrFieldType := types.NewPointer(lookup("Field"))
slicePtrFieldType := types.NewSlice(ptrFieldType)
ptrIdentType := types.NewPointer(lookup("Ident"))
@@ -76,6 +78,10 @@ func main() {
switch {
case is(nodesType):
fmt.Fprintf(&buf, "c.%s = c.%s.Copy()\n", name, name)
+ case is(slicePtrCaseClauseType):
+ fmt.Fprintf(&buf, "c.%s = copyCases(c.%s)\n", name, name)
+ case is(slicePtrCommClauseType):
+ fmt.Fprintf(&buf, "c.%s = copyComms(c.%s)\n", name, name)
case is(ptrFieldType):
fmt.Fprintf(&buf, "if c.%s != nil { c.%s = c.%s.copy() }\n", name, name, name)
case is(slicePtrFieldType):
@@ -94,6 +100,10 @@ func main() {
fmt.Fprintf(&buf, "err = maybeDo(n.%s, err, do)\n", name)
case is(nodesType):
fmt.Fprintf(&buf, "err = maybeDoList(n.%s, err, do)\n", name)
+ case is(slicePtrCaseClauseType):
+ fmt.Fprintf(&buf, "err = maybeDoCases(n.%s, err, do)\n", name)
+ case is(slicePtrCommClauseType):
+ fmt.Fprintf(&buf, "err = maybeDoComms(n.%s, err, do)\n", name)
case is(ptrFieldType):
fmt.Fprintf(&buf, "err = maybeDoField(n.%s, err, do)\n", name)
case is(slicePtrFieldType):
@@ -113,6 +123,10 @@ func main() {
fmt.Fprintf(&buf, "n.%s = toNtype(maybeEdit(n.%s, edit))\n", name, name)
case is(nodesType):
fmt.Fprintf(&buf, "editList(n.%s, edit)\n", name)
+ case is(slicePtrCaseClauseType):
+ fmt.Fprintf(&buf, "editCases(n.%s, edit)\n", name)
+ case is(slicePtrCommClauseType):
+ fmt.Fprintf(&buf, "editComms(n.%s, edit)\n", name)
case is(ptrFieldType):
fmt.Fprintf(&buf, "editField(n.%s, edit)\n", name)
case is(slicePtrFieldType):
@@ -155,10 +169,6 @@ func forNodeFields(typName string, typ *types.Struct, f func(name string, is fun
case "orig":
continue
}
- switch typName + "." + v.Name() {
- case "AddStringExpr.Alloc":
- continue
- }
f(v.Name(), func(t types.Type) bool { return types.Identical(t, v.Type()) })
}
}
diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go
index 93535f4cee..cc8e1b4cd1 100644
--- a/src/cmd/compile/internal/ir/name.go
+++ b/src/cmd/compile/internal/ir/name.go
@@ -268,7 +268,6 @@ const (
nameInlLocal // PAUTO created by inliner, derived from callee local
nameOpenDeferSlot // if temporary var storing info for open-coded defers
nameLibfuzzerExtraCounter // if PEXTERN should be assigned to __libfuzzer_extra_counters section
- nameIsDDD // is function argument a ...
nameAlias // is type name an alias
)
@@ -286,7 +285,6 @@ func (n *Name) InlFormal() bool { return n.flags&nameInlFormal != 0
func (n *Name) InlLocal() bool { return n.flags&nameInlLocal != 0 }
func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 }
func (n *Name) LibfuzzerExtraCounter() bool { return n.flags&nameLibfuzzerExtraCounter != 0 }
-func (n *Name) IsDDD() bool { return n.flags&nameIsDDD != 0 }
func (n *Name) SetCaptured(b bool) { n.flags.set(nameCaptured, b) }
func (n *Name) setReadonly(b bool) { n.flags.set(nameReadonly, b) }
@@ -302,7 +300,6 @@ func (n *Name) SetInlFormal(b bool) { n.flags.set(nameInlFormal, b)
func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b) }
func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) }
func (n *Name) SetLibfuzzerExtraCounter(b bool) { n.flags.set(nameLibfuzzerExtraCounter, b) }
-func (n *Name) SetIsDDD(b bool) { n.flags.set(nameIsDDD, b) }
// MarkReadonly indicates that n is an ONAME with readonly contents.
func (n *Name) MarkReadonly() {
diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go
index 89b1c0ba23..27a5311748 100644
--- a/src/cmd/compile/internal/ir/node_gen.go
+++ b/src/cmd/compile/internal/ir/node_gen.go
@@ -226,29 +226,26 @@ func (n *CallPartExpr) editChildren(edit func(Node) Node) {
n.X = maybeEdit(n.X, edit)
}
-func (n *CaseStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
-func (n *CaseStmt) copy() Node {
+func (n *CaseClause) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *CaseClause) copy() Node {
c := *n
c.init = c.init.Copy()
- c.Vars = c.Vars.Copy()
c.List = c.List.Copy()
c.Body = c.Body.Copy()
return &c
}
-func (n *CaseStmt) doChildren(do func(Node) error) error {
+func (n *CaseClause) doChildren(do func(Node) error) error {
var err error
err = maybeDoList(n.init, err, do)
- err = maybeDoList(n.Vars, err, do)
+ err = maybeDo(n.Var, err, do)
err = maybeDoList(n.List, err, do)
- err = maybeDo(n.Comm, err, do)
err = maybeDoList(n.Body, err, do)
return err
}
-func (n *CaseStmt) editChildren(edit func(Node) Node) {
+func (n *CaseClause) editChildren(edit func(Node) Node) {
editList(n.init, edit)
- editList(n.Vars, edit)
+ n.Var = maybeEdit(n.Var, edit)
editList(n.List, edit)
- n.Comm = maybeEdit(n.Comm, edit)
editList(n.Body, edit)
}
@@ -296,6 +293,26 @@ func (n *ClosureReadExpr) editChildren(edit func(Node) Node) {
editList(n.init, edit)
}
+func (n *CommClause) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *CommClause) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ c.Body = c.Body.Copy()
+ return &c
+}
+func (n *CommClause) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ err = maybeDo(n.Comm, err, do)
+ err = maybeDoList(n.Body, err, do)
+ return err
+}
+func (n *CommClause) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+ n.Comm = maybeEdit(n.Comm, edit)
+ editList(n.Body, edit)
+}
+
func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *CompLitExpr) copy() Node {
c := *n
@@ -725,22 +742,23 @@ func (n *RangeStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *RangeStmt) copy() Node {
c := *n
c.init = c.init.Copy()
- c.Vars = c.Vars.Copy()
c.Body = c.Body.Copy()
return &c
}
func (n *RangeStmt) doChildren(do func(Node) error) error {
var err error
err = maybeDoList(n.init, err, do)
- err = maybeDoList(n.Vars, err, do)
err = maybeDo(n.X, err, do)
+ err = maybeDo(n.Key, err, do)
+ err = maybeDo(n.Value, err, do)
err = maybeDoList(n.Body, err, do)
return err
}
func (n *RangeStmt) editChildren(edit func(Node) Node) {
editList(n.init, edit)
- editList(n.Vars, edit)
n.X = maybeEdit(n.X, edit)
+ n.Key = maybeEdit(n.Key, edit)
+ n.Value = maybeEdit(n.Value, edit)
editList(n.Body, edit)
}
@@ -781,20 +799,20 @@ func (n *SelectStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *SelectStmt) copy() Node {
c := *n
c.init = c.init.Copy()
- c.Cases = c.Cases.Copy()
+ c.Cases = copyComms(c.Cases)
c.Compiled = c.Compiled.Copy()
return &c
}
func (n *SelectStmt) doChildren(do func(Node) error) error {
var err error
err = maybeDoList(n.init, err, do)
- err = maybeDoList(n.Cases, err, do)
+ err = maybeDoComms(n.Cases, err, do)
err = maybeDoList(n.Compiled, err, do)
return err
}
func (n *SelectStmt) editChildren(edit func(Node) Node) {
editList(n.init, edit)
- editList(n.Cases, edit)
+ editComms(n.Cases, edit)
editList(n.Compiled, edit)
}
@@ -838,40 +856,44 @@ func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *SliceExpr) copy() Node {
c := *n
c.init = c.init.Copy()
- c.List = c.List.Copy()
return &c
}
func (n *SliceExpr) doChildren(do func(Node) error) error {
var err error
err = maybeDoList(n.init, err, do)
err = maybeDo(n.X, err, do)
- err = maybeDoList(n.List, err, do)
+ err = maybeDo(n.Low, err, do)
+ err = maybeDo(n.High, err, do)
+ err = maybeDo(n.Max, err, do)
return err
}
func (n *SliceExpr) editChildren(edit func(Node) Node) {
editList(n.init, edit)
n.X = maybeEdit(n.X, edit)
- editList(n.List, edit)
+ n.Low = maybeEdit(n.Low, edit)
+ n.High = maybeEdit(n.High, edit)
+ n.Max = maybeEdit(n.Max, edit)
}
func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *SliceHeaderExpr) copy() Node {
c := *n
c.init = c.init.Copy()
- c.LenCap = c.LenCap.Copy()
return &c
}
func (n *SliceHeaderExpr) doChildren(do func(Node) error) error {
var err error
err = maybeDoList(n.init, err, do)
err = maybeDo(n.Ptr, err, do)
- err = maybeDoList(n.LenCap, err, do)
+ err = maybeDo(n.Len, err, do)
+ err = maybeDo(n.Cap, err, do)
return err
}
func (n *SliceHeaderExpr) editChildren(edit func(Node) Node) {
editList(n.init, edit)
n.Ptr = maybeEdit(n.Ptr, edit)
- editList(n.LenCap, edit)
+ n.Len = maybeEdit(n.Len, edit)
+ n.Cap = maybeEdit(n.Cap, edit)
}
func (n *SliceType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
@@ -941,7 +963,7 @@ func (n *SwitchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *SwitchStmt) copy() Node {
c := *n
c.init = c.init.Copy()
- c.Cases = c.Cases.Copy()
+ c.Cases = copyCases(c.Cases)
c.Compiled = c.Compiled.Copy()
return &c
}
@@ -949,14 +971,14 @@ func (n *SwitchStmt) doChildren(do func(Node) error) error {
var err error
err = maybeDoList(n.init, err, do)
err = maybeDo(n.Tag, err, do)
- err = maybeDoList(n.Cases, err, do)
+ err = maybeDoCases(n.Cases, err, do)
err = maybeDoList(n.Compiled, err, do)
return err
}
func (n *SwitchStmt) editChildren(edit func(Node) Node) {
editList(n.init, edit)
n.Tag = maybeEdit(n.Tag, edit)
- editList(n.Cases, edit)
+ editCases(n.Cases, edit)
editList(n.Compiled, edit)
}
diff --git a/src/cmd/compile/internal/ir/scc.go b/src/cmd/compile/internal/ir/scc.go
index 4f646e22b5..f35c4d44e9 100644
--- a/src/cmd/compile/internal/ir/scc.go
+++ b/src/cmd/compile/internal/ir/scc.go
@@ -76,48 +76,27 @@ func (v *bottomUpVisitor) visit(n *Func) uint32 {
min := v.visitgen
v.stack = append(v.stack, n)
+ do := func(defn Node) {
+ if defn != nil {
+ if m := v.visit(defn.(*Func)); m < min {
+ min = m
+ }
+ }
+ }
+
Visit(n, func(n Node) {
switch n.Op() {
case ONAME:
- n := n.(*Name)
- if n.Class_ == PFUNC {
- if n != nil && n.Name().Defn != nil {
- if m := v.visit(n.Name().Defn.(*Func)); m < min {
- min = m
- }
- }
+ if n := n.(*Name); n.Class_ == PFUNC {
+ do(n.Defn)
}
- case OMETHEXPR:
- n := n.(*MethodExpr)
- fn := MethodExprName(n)
- if fn != nil && fn.Defn != nil {
- if m := v.visit(fn.Defn.(*Func)); m < min {
- min = m
- }
- }
- case ODOTMETH:
- n := n.(*SelectorExpr)
- fn := MethodExprName(n)
- if fn != nil && fn.Op() == ONAME && fn.Class_ == PFUNC && fn.Defn != nil {
- if m := v.visit(fn.Defn.(*Func)); m < min {
- min = m
- }
- }
- case OCALLPART:
- n := n.(*CallPartExpr)
- fn := AsNode(n.Method.Nname)
- if fn != nil && fn.Op() == ONAME {
- if fn := fn.(*Name); fn.Class_ == PFUNC && fn.Name().Defn != nil {
- if m := v.visit(fn.Name().Defn.(*Func)); m < min {
- min = m
- }
- }
+ case ODOTMETH, OCALLPART, OMETHEXPR:
+ if fn := MethodExprName(n); fn != nil {
+ do(fn.Defn)
}
case OCLOSURE:
n := n.(*ClosureExpr)
- if m := v.visit(n.Func); m < min {
- min = m
- }
+ do(n.Func)
}
})
diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go
index ad6db436a7..de152fec72 100644
--- a/src/cmd/compile/internal/ir/stmt.go
+++ b/src/cmd/compile/internal/ir/stmt.go
@@ -173,24 +173,94 @@ func NewBranchStmt(pos src.XPos, op Op, label *types.Sym) *BranchStmt {
func (n *BranchStmt) Sym() *types.Sym { return n.Label }
-// A CaseStmt is a case statement in a switch or select: case List: Body.
-type CaseStmt struct {
+// A CaseClause is a case statement in a switch or select: case List: Body.
+type CaseClause struct {
miniStmt
- Vars Nodes // declared variable for this case in type switch
+ Var Node // declared variable for this case in type switch
List Nodes // list of expressions for switch, early select
- Comm Node // communication case (Exprs[0]) after select is type-checked
Body Nodes
}
-func NewCaseStmt(pos src.XPos, list, body []Node) *CaseStmt {
- n := &CaseStmt{}
+func NewCaseStmt(pos src.XPos, list, body []Node) *CaseClause {
+ n := &CaseClause{List: list, Body: body}
+ n.pos = pos
+ n.op = OCASE
+ return n
+}
+
+// TODO(mdempsky): Generate these with mknode.go.
+func copyCases(list []*CaseClause) []*CaseClause {
+ if list == nil {
+ return nil
+ }
+ c := make([]*CaseClause, len(list))
+ copy(c, list)
+ return c
+}
+func maybeDoCases(list []*CaseClause, err error, do func(Node) error) error {
+ if err != nil {
+ return err
+ }
+ for _, x := range list {
+ if x != nil {
+ if err := do(x); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+func editCases(list []*CaseClause, edit func(Node) Node) {
+ for i, x := range list {
+ if x != nil {
+ list[i] = edit(x).(*CaseClause)
+ }
+ }
+}
+
+type CommClause struct {
+ miniStmt
+ Comm Node // communication case
+ Body Nodes
+}
+
+func NewCommStmt(pos src.XPos, comm Node, body []Node) *CommClause {
+ n := &CommClause{Comm: comm, Body: body}
n.pos = pos
n.op = OCASE
- n.List.Set(list)
- n.Body.Set(body)
return n
}
+// TODO(mdempsky): Generate these with mknode.go.
+func copyComms(list []*CommClause) []*CommClause {
+ if list == nil {
+ return nil
+ }
+ c := make([]*CommClause, len(list))
+ copy(c, list)
+ return c
+}
+func maybeDoComms(list []*CommClause, err error, do func(Node) error) error {
+ if err != nil {
+ return err
+ }
+ for _, x := range list {
+ if x != nil {
+ if err := do(x); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+func editComms(list []*CommClause, edit func(Node) Node) {
+ for i, x := range list {
+ if x != nil {
+ list[i] = edit(x).(*CommClause)
+ }
+ }
+}
+
// A ForStmt is a non-range for loop: for Init; Cond; Post { Body }
// Op can be OFOR or OFORUNTIL (!Cond).
type ForStmt struct {
@@ -203,11 +273,13 @@ type ForStmt struct {
HasBreak bool
}
-func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStmt {
+func NewForStmt(pos src.XPos, init Node, cond, post Node, body []Node) *ForStmt {
n := &ForStmt{Cond: cond, Post: post}
n.pos = pos
n.op = OFOR
- n.init.Set(init)
+ if init != nil {
+ n.init = []Node{init}
+ }
n.Body.Set(body)
return n
}
@@ -290,32 +362,27 @@ func NewLabelStmt(pos src.XPos, label *types.Sym) *LabelStmt {
func (n *LabelStmt) Sym() *types.Sym { return n.Label }
-// A RangeStmt is a range loop: for Vars = range X { Stmts }
-// Op can be OFOR or OFORUNTIL (!Cond).
+// A RangeStmt is a range loop: for Key, Value = range X { Body }
type RangeStmt struct {
miniStmt
Label *types.Sym
- Vars Nodes // TODO(rsc): Replace with Key, Value Node
Def bool
X Node
+ Key Node
+ Value Node
Body Nodes
HasBreak bool
- typ *types.Type // TODO(rsc): Remove - use X.Type() instead
Prealloc *Name
}
-func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt {
- n := &RangeStmt{X: x}
+func NewRangeStmt(pos src.XPos, key, value, x Node, body []Node) *RangeStmt {
+ n := &RangeStmt{X: x, Key: key, Value: value}
n.pos = pos
n.op = ORANGE
- n.Vars.Set(vars)
n.Body.Set(body)
return n
}
-func (n *RangeStmt) Type() *types.Type { return n.typ }
-func (n *RangeStmt) SetType(x *types.Type) { n.typ = x }
-
// A ReturnStmt is a return statement.
type ReturnStmt struct {
miniStmt
@@ -339,18 +406,17 @@ func (n *ReturnStmt) SetOrig(x Node) { n.orig = x }
type SelectStmt struct {
miniStmt
Label *types.Sym
- Cases Nodes
+ Cases []*CommClause
HasBreak bool
// TODO(rsc): Instead of recording here, replace with a block?
Compiled Nodes // compiled form, after walkswitch
}
-func NewSelectStmt(pos src.XPos, cases []Node) *SelectStmt {
- n := &SelectStmt{}
+func NewSelectStmt(pos src.XPos, cases []*CommClause) *SelectStmt {
+ n := &SelectStmt{Cases: cases}
n.pos = pos
n.op = OSELECT
- n.Cases.Set(cases)
return n
}
@@ -372,7 +438,7 @@ func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt {
type SwitchStmt struct {
miniStmt
Tag Node
- Cases Nodes // list of *CaseStmt
+ Cases []*CaseClause
Label *types.Sym
HasBreak bool
@@ -380,11 +446,10 @@ type SwitchStmt struct {
Compiled Nodes // compiled form, after walkswitch
}
-func NewSwitchStmt(pos src.XPos, tag Node, cases []Node) *SwitchStmt {
- n := &SwitchStmt{Tag: tag}
+func NewSwitchStmt(pos src.XPos, tag Node, cases []*CaseClause) *SwitchStmt {
+ n := &SwitchStmt{Tag: tag, Cases: cases}
n.pos = pos
n.op = OSWITCH
- n.Cases.Set(cases)
return n
}
diff --git a/src/cmd/compile/internal/ir/type.go b/src/cmd/compile/internal/ir/type.go
index 5e6d76229d..bd3a05d06e 100644
--- a/src/cmd/compile/internal/ir/type.go
+++ b/src/cmd/compile/internal/ir/type.go
@@ -115,14 +115,6 @@ func (n *StructType) SetOTYPE(t *types.Type) {
n.Fields = nil
}
-func deepCopyFields(pos src.XPos, fields []*Field) []*Field {
- var out []*Field
- for _, f := range fields {
- out = append(out, f.deepCopy(pos))
- }
- return out
-}
-
// An InterfaceType represents a struct { ... } type syntax.
type InterfaceType struct {
miniType
@@ -250,26 +242,6 @@ func editFields(list []*Field, edit func(Node) Node) {
}
}
-func (f *Field) deepCopy(pos src.XPos) *Field {
- if f == nil {
- return nil
- }
- fpos := pos
- if !pos.IsKnown() {
- fpos = f.Pos
- }
- decl := f.Decl
- if decl != nil {
- decl = DeepCopy(pos, decl).(*Name)
- }
- ntype := f.Ntype
- if ntype != nil {
- ntype = DeepCopy(pos, ntype).(Ntype)
- }
- // No keyed literal here: if a new struct field is added, we want this to stop compiling.
- return &Field{fpos, f.Sym, ntype, f.Type, f.Embedded, f.IsDDD, f.Note, decl}
-}
-
// A SliceType represents a []Elem type syntax.
// If DDD is true, it's the ...Elem at the end of a function list.
type SliceType struct {
diff --git a/src/cmd/compile/internal/ir/visit.go b/src/cmd/compile/internal/ir/visit.go
index a1c345968f..8839e1664d 100644
--- a/src/cmd/compile/internal/ir/visit.go
+++ b/src/cmd/compile/internal/ir/visit.go
@@ -217,10 +217,9 @@ func EditChildren(n Node, edit func(Node) Node) {
// Note that editList only calls edit on the nodes in the list, not their children.
// If x's children should be processed, edit(x) must call EditChildren(x, edit) itself.
func editList(list Nodes, edit func(Node) Node) {
- s := list
for i, x := range list {
if x != nil {
- s[i] = edit(x)
+ list[i] = edit(x)
}
}
}
diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go
index 785a3a29de..89c70df65a 100644
--- a/src/cmd/compile/internal/liveness/plive.go
+++ b/src/cmd/compile/internal/liveness/plive.go
@@ -24,6 +24,7 @@ import (
"cmd/compile/internal/ir"
"cmd/compile/internal/objw"
"cmd/compile/internal/ssa"
+ "cmd/compile/internal/typebits"
"cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/objabi"
@@ -179,11 +180,7 @@ type progeffectscache struct {
// nor do we care about non-local variables,
// nor do we care about empty structs (handled by the pointer check),
// nor do we care about the fake PAUTOHEAP variables.
-func ShouldTrack(nn ir.Node) bool {
- if nn.Op() != ir.ONAME {
- return false
- }
- n := nn.(*ir.Name)
+func ShouldTrack(n *ir.Name) bool {
return (n.Class_ == ir.PAUTO || n.Class_ == ir.PPARAM || n.Class_ == ir.PPARAMOUT) && n.Type().HasPointers()
}
@@ -248,19 +245,17 @@ const (
// liveness effects v has on that variable.
// If v does not affect any tracked variables, it returns -1, 0.
func (lv *liveness) valueEffects(v *ssa.Value) (int32, liveEffect) {
- n, e := affectedNode(v)
- if e == 0 || n == nil || n.Op() != ir.ONAME { // cheapest checks first
+ n, e := affectedVar(v)
+ if e == 0 || n == nil { // cheapest checks first
return -1, 0
}
-
- nn := n.(*ir.Name)
// AllocFrame has dropped unused variables from
// lv.fn.Func.Dcl, but they might still be referenced by
// OpVarFoo pseudo-ops. Ignore them to prevent "lost track of
// variable" ICEs (issue 19632).
switch v.Op {
case ssa.OpVarDef, ssa.OpVarKill, ssa.OpVarLive, ssa.OpKeepAlive:
- if !nn.Name().Used() {
+ if !n.Name().Used() {
return -1, 0
}
}
@@ -283,14 +278,14 @@ func (lv *liveness) valueEffects(v *ssa.Value) (int32, liveEffect) {
return -1, 0
}
- if pos, ok := lv.idx[nn]; ok {
+ if pos, ok := lv.idx[n]; ok {
return pos, effect
}
return -1, 0
}
-// affectedNode returns the *Node affected by v
-func affectedNode(v *ssa.Value) (ir.Node, ssa.SymEffect) {
+// affectedVar returns the *ir.Name node affected by v
+func affectedVar(v *ssa.Value) (*ir.Name, ssa.SymEffect) {
// Special cases.
switch v.Op {
case ssa.OpLoadReg:
@@ -381,82 +376,6 @@ func (lv *liveness) blockEffects(b *ssa.Block) *blockEffects {
return &lv.be[b.ID]
}
-// NOTE: The bitmap for a specific type t could be cached in t after
-// the first run and then simply copied into bv at the correct offset
-// on future calls with the same type t.
-func SetTypeBits(t *types.Type, off int64, bv bitvec.BitVec) {
- if t.Align > 0 && off&int64(t.Align-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid initial alignment: type %v has alignment %d, but offset is %v", t, t.Align, off)
- }
- if !t.HasPointers() {
- // Note: this case ensures that pointers to go:notinheap types
- // are not considered pointers by garbage collection and stack copying.
- return
- }
-
- switch t.Kind() {
- case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP:
- if off&int64(types.PtrSize-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
- }
- bv.Set(int32(off / int64(types.PtrSize))) // pointer
-
- case types.TSTRING:
- // struct { byte *str; intgo len; }
- if off&int64(types.PtrSize-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
- }
- bv.Set(int32(off / int64(types.PtrSize))) //pointer in first slot
-
- case types.TINTER:
- // struct { Itab *tab; void *data; }
- // or, when isnilinter(t)==true:
- // struct { Type *type; void *data; }
- if off&int64(types.PtrSize-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
- }
- // The first word of an interface is a pointer, but we don't
- // treat it as such.
- // 1. If it is a non-empty interface, the pointer points to an itab
- // which is always in persistentalloc space.
- // 2. If it is an empty interface, the pointer points to a _type.
- // a. If it is a compile-time-allocated type, it points into
- // the read-only data section.
- // b. If it is a reflect-allocated type, it points into the Go heap.
- // Reflect is responsible for keeping a reference to
- // the underlying type so it won't be GCd.
- // If we ever have a moving GC, we need to change this for 2b (as
- // well as scan itabs to update their itab._type fields).
- bv.Set(int32(off/int64(types.PtrSize) + 1)) // pointer in second slot
-
- case types.TSLICE:
- // struct { byte *array; uintgo len; uintgo cap; }
- if off&int64(types.PtrSize-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid TARRAY alignment, %v", t)
- }
- bv.Set(int32(off / int64(types.PtrSize))) // pointer in first slot (BitsPointer)
-
- case types.TARRAY:
- elt := t.Elem()
- if elt.Width == 0 {
- // Short-circuit for #20739.
- break
- }
- for i := int64(0); i < t.NumElem(); i++ {
- SetTypeBits(elt, off, bv)
- off += elt.Width
- }
-
- case types.TSTRUCT:
- for _, f := range t.Fields().Slice() {
- SetTypeBits(f.Type, off+f.Offset, bv)
- }
-
- default:
- base.Fatalf("onebitwalktype1: unexpected type, %v", t)
- }
-}
-
// Generates live pointer value maps for arguments and local variables. The
// this argument and the in arguments are always assumed live. The vars
// argument is a slice of *Nodes.
@@ -469,10 +388,10 @@ func (lv *liveness) pointerMap(liveout bitvec.BitVec, vars []*ir.Name, args, loc
node := vars[i]
switch node.Class_ {
case ir.PAUTO:
- SetTypeBits(node.Type(), node.FrameOffset()+lv.stkptrsize, locals)
+ typebits.Set(node.Type(), node.FrameOffset()+lv.stkptrsize, locals)
case ir.PPARAM, ir.PPARAMOUT:
- SetTypeBits(node.Type(), node.FrameOffset(), args)
+ typebits.Set(node.Type(), node.FrameOffset(), args)
}
}
}
@@ -1315,15 +1234,15 @@ func WriteFuncMap(fn *ir.Func) {
off = objw.Uint32(lsym, off, uint32(bv.N))
if ir.IsMethod(fn) {
- SetTypeBits(fn.Type().Recvs(), 0, bv)
+ typebits.Set(fn.Type().Recvs(), 0, bv)
}
if fn.Type().NumParams() > 0 {
- SetTypeBits(fn.Type().Params(), 0, bv)
+ typebits.Set(fn.Type().Params(), 0, bv)
}
off = objw.BitVec(lsym, off, bv)
if fn.Type().NumResults() > 0 {
- SetTypeBits(fn.Type().Results(), 0, bv)
+ typebits.Set(fn.Type().Results(), 0, bv)
off = objw.BitVec(lsym, off, bv)
}
diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go
index 1bebb44e6c..c1356be52f 100644
--- a/src/cmd/compile/internal/noder/noder.go
+++ b/src/cmd/compile/internal/noder/noder.go
@@ -510,11 +510,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
names := p.declNames(ir.ONAME, decl.NameList)
typ := p.typeExprOrNil(decl.Type)
-
- var exprs []ir.Node
- if decl.Values != nil {
- exprs = p.exprList(decl.Values)
- }
+ exprs := p.exprList(decl.Values)
if pragma, ok := decl.Pragma.(*pragmas); ok {
if len(pragma.Embeds) > 0 {
@@ -753,10 +749,14 @@ func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Field {
}
func (p *noder) exprList(expr syntax.Expr) []ir.Node {
- if list, ok := expr.(*syntax.ListExpr); ok {
- return p.exprs(list.ElemList)
+ switch expr := expr.(type) {
+ case nil:
+ return nil
+ case *syntax.ListExpr:
+ return p.exprs(expr.ElemList)
+ default:
+ return []ir.Node{p.expr(expr)}
}
- return []ir.Node{p.expr(expr)}
}
func (p *noder) exprs(exprs []syntax.Expr) []ir.Node {
@@ -775,17 +775,14 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
case *syntax.Name:
return p.mkname(expr)
case *syntax.BasicLit:
- n := ir.NewLiteral(p.basicLit(expr))
+ n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
if expr.Kind == syntax.RuneLit {
n.SetType(types.UntypedRune)
}
n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error
return n
case *syntax.CompositeLit:
- n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, nil, nil)
- if expr.Type != nil {
- n.Ntype = ir.Node(p.expr(expr.Type)).(ir.Ntype)
- }
+ n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, p.typeExpr(expr.Type), nil)
l := p.exprs(expr.ElemList)
for i, e := range l {
l[i] = p.wrapname(expr.ElemList[i], e)
@@ -818,17 +815,16 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
if expr.Full {
op = ir.OSLICE3
}
- n := ir.NewSliceExpr(p.pos(expr), op, p.expr(expr.X))
+ x := p.expr(expr.X)
var index [3]ir.Node
- for i, x := range &expr.Index {
- if x != nil {
- index[i] = p.expr(x)
+ for i, n := range &expr.Index {
+ if n != nil {
+ index[i] = p.expr(n)
}
}
- n.SetSliceBounds(index[0], index[1], index[2])
- return n
+ return ir.NewSliceExpr(p.pos(expr), op, x, index[0], index[1], index[2])
case *syntax.AssertExpr:
- return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type).(ir.Ntype))
+ return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type))
case *syntax.Operation:
if expr.Op == syntax.Add && expr.Y != nil {
return p.sum(expr)
@@ -852,8 +848,7 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
}
return ir.NewBinaryExpr(pos, op, x, y)
case *syntax.CallExpr:
- n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), nil)
- n.Args.Set(p.exprs(expr.ArgList))
+ n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), p.exprs(expr.ArgList))
n.IsDDD = expr.HasDots
return n
@@ -1120,7 +1115,7 @@ func (p *noder) stmt(stmt syntax.Stmt) ir.Node {
func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
p.setlineno(stmt)
switch stmt := stmt.(type) {
- case *syntax.EmptyStmt:
+ case nil, *syntax.EmptyStmt:
return nil
case *syntax.LabeledStmt:
return p.labeledStmt(stmt, fallOK)
@@ -1193,12 +1188,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
}
return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
case *syntax.ReturnStmt:
- var results []ir.Node
- if stmt.Results != nil {
- results = p.exprList(stmt.Results)
- }
- n := ir.NewReturnStmt(p.pos(stmt), nil)
- n.Results.Set(results)
+ n := ir.NewReturnStmt(p.pos(stmt), p.exprList(stmt.Results))
if len(n.Results) == 0 && ir.CurFunc != nil {
for _, ln := range ir.CurFunc.Dcl {
if ln.Class_ == ir.PPARAM {
@@ -1292,14 +1282,11 @@ func (p *noder) blockStmt(stmt *syntax.BlockStmt) []ir.Node {
func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
p.openScope(stmt.Pos())
- n := ir.NewIfStmt(p.pos(stmt), nil, nil, nil)
- if stmt.Init != nil {
- *n.PtrInit() = []ir.Node{p.stmt(stmt.Init)}
+ init := p.stmt(stmt.Init)
+ n := ir.NewIfStmt(p.pos(stmt), p.expr(stmt.Cond), p.blockStmt(stmt.Then), nil)
+ if init != nil {
+ *n.PtrInit() = []ir.Node{init}
}
- if stmt.Cond != nil {
- n.Cond = p.expr(stmt.Cond)
- }
- n.Body.Set(p.blockStmt(stmt.Then))
if stmt.Else != nil {
e := p.stmt(stmt.Else)
if e.Op() == ir.OBLOCK {
@@ -1320,53 +1307,46 @@ func (p *noder) forStmt(stmt *syntax.ForStmt) ir.Node {
panic("unexpected RangeClause")
}
- n := ir.NewRangeStmt(p.pos(r), nil, p.expr(r.X), nil)
+ n := ir.NewRangeStmt(p.pos(r), nil, nil, p.expr(r.X), nil)
if r.Lhs != nil {
n.Def = r.Def
- n.Vars.Set(p.assignList(r.Lhs, n, n.Def))
+ lhs := p.assignList(r.Lhs, n, n.Def)
+ n.Key = lhs[0]
+ if len(lhs) > 1 {
+ n.Value = lhs[1]
+ }
}
n.Body.Set(p.blockStmt(stmt.Body))
p.closeAnotherScope()
return n
}
- n := ir.NewForStmt(p.pos(stmt), nil, nil, nil, nil)
- if stmt.Init != nil {
- *n.PtrInit() = []ir.Node{p.stmt(stmt.Init)}
- }
- if stmt.Cond != nil {
- n.Cond = p.expr(stmt.Cond)
- }
- if stmt.Post != nil {
- n.Post = p.stmt(stmt.Post)
- }
- n.Body.Set(p.blockStmt(stmt.Body))
+ n := ir.NewForStmt(p.pos(stmt), p.stmt(stmt.Init), p.expr(stmt.Cond), p.stmt(stmt.Post), p.blockStmt(stmt.Body))
p.closeAnotherScope()
return n
}
func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
p.openScope(stmt.Pos())
- n := ir.NewSwitchStmt(p.pos(stmt), nil, nil)
- if stmt.Init != nil {
- *n.PtrInit() = []ir.Node{p.stmt(stmt.Init)}
- }
- if stmt.Tag != nil {
- n.Tag = p.expr(stmt.Tag)
+
+ init := p.stmt(stmt.Init)
+ n := ir.NewSwitchStmt(p.pos(stmt), p.expr(stmt.Tag), nil)
+ if init != nil {
+ *n.PtrInit() = []ir.Node{init}
}
var tswitch *ir.TypeSwitchGuard
if l := n.Tag; l != nil && l.Op() == ir.OTYPESW {
tswitch = l.(*ir.TypeSwitchGuard)
}
- n.Cases.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace))
+ n.Cases = p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)
p.closeScope(stmt.Rbrace)
return n
}
-func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []ir.Node {
- nodes := make([]ir.Node, 0, len(clauses))
+func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []*ir.CaseClause {
+ nodes := make([]*ir.CaseClause, 0, len(clauses))
for i, clause := range clauses {
p.setlineno(clause)
if i > 0 {
@@ -1374,14 +1354,11 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitch
}
p.openScope(clause.Pos())
- n := ir.NewCaseStmt(p.pos(clause), nil, nil)
- if clause.Cases != nil {
- n.List.Set(p.exprList(clause.Cases))
- }
+ n := ir.NewCaseStmt(p.pos(clause), p.exprList(clause.Cases), nil)
if tswitch != nil && tswitch.Tag != nil {
nn := typecheck.NewName(tswitch.Tag.Sym())
typecheck.Declare(nn, typecheck.DeclContext)
- n.Vars = []ir.Node{nn}
+ n.Var = nn
// keep track of the instances for reporting unused
nn.Defn = tswitch
}
@@ -1416,13 +1393,11 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitch
}
func (p *noder) selectStmt(stmt *syntax.SelectStmt) ir.Node {
- n := ir.NewSelectStmt(p.pos(stmt), nil)
- n.Cases.Set(p.commClauses(stmt.Body, stmt.Rbrace))
- return n
+ return ir.NewSelectStmt(p.pos(stmt), p.commClauses(stmt.Body, stmt.Rbrace))
}
-func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []ir.Node {
- nodes := make([]ir.Node, 0, len(clauses))
+func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.CommClause {
+ nodes := make([]*ir.CommClause, len(clauses))
for i, clause := range clauses {
p.setlineno(clause)
if i > 0 {
@@ -1430,12 +1405,7 @@ func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []i
}
p.openScope(clause.Pos())
- n := ir.NewCaseStmt(p.pos(clause), nil, nil)
- if clause.Comm != nil {
- n.List = []ir.Node{p.stmt(clause.Comm)}
- }
- n.Body.Set(p.stmts(clause.Body))
- nodes = append(nodes, n)
+ nodes[i] = ir.NewCommStmt(p.pos(clause), p.stmt(clause.Comm), p.stmts(clause.Body))
}
if len(clauses) > 0 {
p.closeScope(rbrace)
@@ -2001,7 +1971,6 @@ func oldname(s *types.Sym) ir.Node {
c = typecheck.NewName(s)
c.Class_ = ir.PAUTOHEAP
c.SetIsClosureVar(true)
- c.SetIsDDD(n.IsDDD())
c.Defn = n
// Link into list of active closure variables.
diff --git a/src/cmd/compile/internal/objw/prog.go b/src/cmd/compile/internal/objw/prog.go
index 54028e47fd..8d24f94aa5 100644
--- a/src/cmd/compile/internal/objw/prog.go
+++ b/src/cmd/compile/internal/objw/prog.go
@@ -33,7 +33,6 @@ package objw
import (
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
- "cmd/compile/internal/ssa"
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/src"
@@ -173,7 +172,7 @@ func (pp *Progs) Prog(as obj.As) *obj.Prog {
p.Pos = pp.Pos
if pp.Pos.IsStmt() == src.PosIsStmt {
// Clear IsStmt for later Progs at this pos provided that as can be marked as a stmt
- if ssa.LosesStmtMark(as) {
+ if LosesStmtMark(as) {
return p
}
pp.Pos = pp.Pos.WithNotStmt()
@@ -216,3 +215,12 @@ func (pp *Progs) SetText(fn *ir.Func) {
ptxt.From.Name = obj.NAME_EXTERN
ptxt.From.Sym = fn.LSym
}
+
+// LosesStmtMark reports whether a prog with op as loses its statement mark on the way to DWARF.
+// The attributes from some opcodes are lost in translation.
+// TODO: this is an artifact of how funcpctab combines information for instructions at a single PC.
+// Should try to fix it there.
+func LosesStmtMark(as obj.As) bool {
+ // is_stmt does not work for these; it DOES for ANOP even though that generates no code.
+ return as == obj.APCDATA || as == obj.AFUNCDATA
+}
diff --git a/src/cmd/compile/internal/pkginit/initorder.go b/src/cmd/compile/internal/pkginit/initorder.go
index d63c5a4717..c6e223954d 100644
--- a/src/cmd/compile/internal/pkginit/initorder.go
+++ b/src/cmd/compile/internal/pkginit/initorder.go
@@ -289,10 +289,6 @@ func (d *initDeps) inspectList(l ir.Nodes) { ir.VisitList(l, d.cachedVisit()) }
// referenced by n, if any.
func (d *initDeps) visit(n ir.Node) {
switch n.Op() {
- case ir.OMETHEXPR:
- n := n.(*ir.MethodExpr)
- d.foundDep(ir.MethodExprName(n))
-
case ir.ONAME:
n := n.(*ir.Name)
switch n.Class_ {
@@ -304,7 +300,7 @@ func (d *initDeps) visit(n ir.Node) {
n := n.(*ir.ClosureExpr)
d.inspectList(n.Func.Body)
- case ir.ODOTMETH, ir.OCALLPART:
+ case ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR:
d.foundDep(ir.MethodExprName(n))
}
}
diff --git a/src/cmd/compile/internal/reflectdata/alg.go b/src/cmd/compile/internal/reflectdata/alg.go
index 8391486e50..1f943f5795 100644
--- a/src/cmd/compile/internal/reflectdata/alg.go
+++ b/src/cmd/compile/internal/reflectdata/alg.go
@@ -289,11 +289,11 @@ func hashfor(t *types.Type) ir.Node {
n := typecheck.NewName(sym)
ir.MarkFunc(n)
- n.SetType(typecheck.NewFuncType(nil, []*ir.Field{
- ir.NewField(base.Pos, nil, nil, types.NewPtr(t)),
- ir.NewField(base.Pos, nil, nil, types.Types[types.TUINTPTR]),
- }, []*ir.Field{
- ir.NewField(base.Pos, nil, nil, types.Types[types.TUINTPTR]),
+ n.SetType(types.NewSignature(types.NoPkg, nil, []*types.Field{
+ types.NewField(base.Pos, nil, types.NewPtr(t)),
+ types.NewField(base.Pos, nil, types.Types[types.TUINTPTR]),
+ }, []*types.Field{
+ types.NewField(base.Pos, nil, types.Types[types.TUINTPTR]),
}))
return n
}
@@ -777,12 +777,12 @@ func hashmem(t *types.Type) ir.Node {
n := typecheck.NewName(sym)
ir.MarkFunc(n)
- n.SetType(typecheck.NewFuncType(nil, []*ir.Field{
- ir.NewField(base.Pos, nil, nil, types.NewPtr(t)),
- ir.NewField(base.Pos, nil, nil, types.Types[types.TUINTPTR]),
- ir.NewField(base.Pos, nil, nil, types.Types[types.TUINTPTR]),
- }, []*ir.Field{
- ir.NewField(base.Pos, nil, nil, types.Types[types.TUINTPTR]),
+ n.SetType(types.NewSignature(types.NoPkg, nil, []*types.Field{
+ types.NewField(base.Pos, nil, types.NewPtr(t)),
+ types.NewField(base.Pos, nil, types.Types[types.TUINTPTR]),
+ types.NewField(base.Pos, nil, types.Types[types.TUINTPTR]),
+ }, []*types.Field{
+ types.NewField(base.Pos, nil, types.Types[types.TUINTPTR]),
}))
return n
}
diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index ba3e0fa75e..df80380fc1 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -16,8 +16,8 @@ import (
"cmd/compile/internal/escape"
"cmd/compile/internal/inline"
"cmd/compile/internal/ir"
- "cmd/compile/internal/liveness"
"cmd/compile/internal/objw"
+ "cmd/compile/internal/typebits"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/gcprog"
@@ -835,6 +835,9 @@ func TypeSym(t *types.Type) *types.Sym {
if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
base.Fatalf("typenamesym %v", t)
}
+ if t.Kind() == types.TFUNC && t.Recv() != nil {
+ base.Fatalf("misuse of method type: %v", t)
+ }
s := types.TypeSym(t)
signatmu.Lock()
NeedRuntimeType(t)
@@ -1419,7 +1422,11 @@ func WriteBasicTypes() {
// The latter is the type of an auto-generated wrapper.
WriteType(types.NewPtr(types.ErrorType))
- WriteType(typecheck.NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, types.ErrorType)}, []*ir.Field{ir.NewField(base.Pos, nil, nil, types.Types[types.TSTRING])}))
+ WriteType(types.NewSignature(types.NoPkg, nil, []*types.Field{
+ types.NewField(base.Pos, nil, types.ErrorType),
+ }, []*types.Field{
+ types.NewField(base.Pos, nil, types.Types[types.TSTRING]),
+ }))
// add paths for runtime and main, which 6l imports implicitly.
dimportpath(ir.Pkgs.Runtime)
@@ -1545,7 +1552,7 @@ func fillptrmask(t *types.Type, ptrmask []byte) {
}
vec := bitvec.New(8 * int32(len(ptrmask)))
- liveness.SetTypeBits(t, 0, vec)
+ typebits.Set(t, 0, vec)
nptr := types.PtrDataSize(t) / int64(types.PtrSize)
for i := int64(0); i < nptr; i++ {
@@ -1856,7 +1863,7 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) {
r.Sym = tsym
// dot.Xoffset is the method index * Widthptr (the offset of code pointer
// in itab).
- midx := dot.Offset / int64(types.PtrSize)
+ midx := dot.Offset() / int64(types.PtrSize)
r.Add = InterfaceMethodOffset(ityp, midx)
r.Type = objabi.R_USEIFACEMETHOD
}
diff --git a/src/cmd/compile/internal/ssa/numberlines.go b/src/cmd/compile/internal/ssa/numberlines.go
index f4e62b88c4..2a9c8e4f32 100644
--- a/src/cmd/compile/internal/ssa/numberlines.go
+++ b/src/cmd/compile/internal/ssa/numberlines.go
@@ -5,7 +5,6 @@
package ssa
import (
- "cmd/internal/obj"
"cmd/internal/src"
"fmt"
"sort"
@@ -23,15 +22,6 @@ func isPoorStatementOp(op Op) bool {
return false
}
-// LosesStmtMark reports whether a prog with op as loses its statement mark on the way to DWARF.
-// The attributes from some opcodes are lost in translation.
-// TODO: this is an artifact of how funcpctab combines information for instructions at a single PC.
-// Should try to fix it there.
-func LosesStmtMark(as obj.As) bool {
- // is_stmt does not work for these; it DOES for ANOP even though that generates no code.
- return as == obj.APCDATA || as == obj.AFUNCDATA
-}
-
// nextGoodStatementIndex returns an index at i or later that is believed
// to be a good place to start the statement for b. This decision is
// based on v's Op, the possibility of a better later operation, and
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go
index a77e57a5b6..0da6ab3272 100644
--- a/src/cmd/compile/internal/ssagen/ssa.go
+++ b/src/cmd/compile/internal/ssagen/ssa.go
@@ -214,10 +214,7 @@ func InitConfig() {
func getParam(n *ir.CallExpr, i int) *types.Field {
t := n.X.Type()
if n.Op() == ir.OCALLMETH {
- if i == 0 {
- return t.Recv()
- }
- return t.Params().Field(i - 1)
+ base.Fatalf("OCALLMETH missed by walkCall")
}
return t.Params().Field(i)
}
@@ -1166,7 +1163,7 @@ func (s *state) stmt(n ir.Node) {
}
fallthrough
- case ir.OCALLMETH, ir.OCALLINTER:
+ case ir.OCALLINTER:
n := n.(*ir.CallExpr)
s.callResult(n, callNormal)
if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME && n.X.(*ir.Name).Class_ == ir.PFUNC {
@@ -1367,7 +1364,7 @@ func (s *state) stmt(n ir.Node) {
// We're assigning a slicing operation back to its source.
// Don't write back fields we aren't changing. See issue #14855.
rhs := rhs.(*ir.SliceExpr)
- i, j, k := rhs.SliceBounds()
+ i, j, k := rhs.Low, rhs.High, rhs.Max
if i != nil && (i.Op() == ir.OLITERAL && i.Val().Kind() == constant.Int && ir.Int64Val(i) == 0) {
// [0:...] is the same as [:...]
i = nil
@@ -2111,10 +2108,6 @@ func (s *state) expr(n ir.Node) *ssa.Value {
n := n.(*ir.UnaryExpr)
aux := n.X.Sym().Linksym()
return s.entryNewValue1A(ssa.OpAddr, n.Type(), aux, s.sb)
- case ir.OMETHEXPR:
- n := n.(*ir.MethodExpr)
- sym := staticdata.FuncSym(n.FuncName().Sym()).Linksym()
- return s.entryNewValue1A(ssa.OpAddr, types.NewPtr(n.Type()), sym, s.sb)
case ir.ONAME:
n := n.(*ir.Name)
if n.Class_ == ir.PFUNC {
@@ -2736,7 +2729,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
// SSA, then load just the selected field. This
// prevents false memory dependencies in race/msan
// instrumentation.
- if ir.IsAssignable(n) && !s.canSSA(n) {
+ if ir.IsAddressable(n) && !s.canSSA(n) {
p := s.addr(n)
return s.load(n.Type(), p)
}
@@ -2746,7 +2739,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
case ir.ODOTPTR:
n := n.(*ir.SelectorExpr)
p := s.exprPtr(n.X, n.Bounded(), n.Pos())
- p = s.newValue1I(ssa.OpOffPtr, types.NewPtr(n.Type()), n.Offset, p)
+ p = s.newValue1I(ssa.OpOffPtr, types.NewPtr(n.Type()), n.Offset(), p)
return s.load(n.Type(), p)
case ir.OINDEX:
@@ -2844,23 +2837,22 @@ func (s *state) expr(n ir.Node) *ssa.Value {
case ir.OSLICEHEADER:
n := n.(*ir.SliceHeaderExpr)
p := s.expr(n.Ptr)
- l := s.expr(n.LenCap[0])
- c := s.expr(n.LenCap[1])
+ l := s.expr(n.Len)
+ c := s.expr(n.Cap)
return s.newValue3(ssa.OpSliceMake, n.Type(), p, l, c)
case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR:
n := n.(*ir.SliceExpr)
v := s.expr(n.X)
var i, j, k *ssa.Value
- low, high, max := n.SliceBounds()
- if low != nil {
- i = s.expr(low)
+ if n.Low != nil {
+ i = s.expr(n.Low)
}
- if high != nil {
- j = s.expr(high)
+ if n.High != nil {
+ j = s.expr(n.High)
}
- if max != nil {
- k = s.expr(max)
+ if n.Max != nil {
+ k = s.expr(n.Max)
}
p, l, c := s.slice(v, i, j, k, n.Bounded())
return s.newValue3(ssa.OpSliceMake, n.Type(), p, l, c)
@@ -2869,12 +2861,11 @@ func (s *state) expr(n ir.Node) *ssa.Value {
n := n.(*ir.SliceExpr)
v := s.expr(n.X)
var i, j *ssa.Value
- low, high, _ := n.SliceBounds()
- if low != nil {
- i = s.expr(low)
+ if n.Low != nil {
+ i = s.expr(n.Low)
}
- if high != nil {
- j = s.expr(high)
+ if n.High != nil {
+ j = s.expr(n.High)
}
p, l, _ := s.slice(v, i, j, nil, n.Bounded())
return s.newValue2(ssa.OpStringMake, n.Type(), p, l)
@@ -4398,16 +4389,7 @@ func (s *state) openDeferRecord(n *ir.CallExpr) {
opendefer.closure = closure
}
} else if n.Op() == ir.OCALLMETH {
- if fn.Op() != ir.ODOTMETH {
- base.Fatalf("OCALLMETH: n.Left not an ODOTMETH: %v", fn)
- }
- fn := fn.(*ir.SelectorExpr)
- closureVal := s.getMethodClosure(fn)
- // We must always store the function value in a stack slot for the
- // runtime panic code to use. But in the defer exit code, we will
- // call the method directly.
- closure := s.openDeferSave(nil, fn.Type(), closureVal)
- opendefer.closureNode = closure.Aux.(*ir.Name)
+ base.Fatalf("OCALLMETH missed by walkCall")
} else {
if fn.Op() != ir.ODOTINTER {
base.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op())
@@ -4681,18 +4663,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
s.maybeNilCheckClosure(closure, k)
}
case ir.OCALLMETH:
- if fn.Op() != ir.ODOTMETH {
- s.Fatalf("OCALLMETH: n.Left not an ODOTMETH: %v", fn)
- }
- fn := fn.(*ir.SelectorExpr)
- testLateExpansion = k != callDeferStack && ssa.LateCallExpansionEnabledWithin(s.f)
- if k == callNormal {
- sym = fn.Sel
- break
- }
- closure = s.getMethodClosure(fn)
- // Note: receiver is already present in n.Rlist, so we don't
- // want to set it here.
+ base.Fatalf("OCALLMETH missed by walkCall")
case ir.OCALLINTER:
if fn.Op() != ir.ODOTINTER {
s.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op())
@@ -4757,9 +4728,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
}
// Set receiver (for method calls).
if n.Op() == ir.OCALLMETH {
- f := ft.Recv()
- s.storeArgWithBase(args[0], f.Type, addr, off+f.Offset)
- args = args[1:]
+ base.Fatalf("OCALLMETH missed by walkCall")
}
// Set other args.
for _, f := range ft.Params().Fields().Slice() {
@@ -4827,11 +4796,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
t := n.X.Type()
args := n.Rargs
if n.Op() == ir.OCALLMETH {
- f := t.Recv()
- ACArg, arg := s.putArg(args[0], f.Type, argStart+f.Offset, testLateExpansion)
- ACArgs = append(ACArgs, ACArg)
- callArgs = append(callArgs, arg)
- args = args[1:]
+ base.Fatalf("OCALLMETH missed by walkCall")
}
for i, n := range args {
f := t.Params().Field(i)
@@ -4949,29 +4914,13 @@ func (s *state) maybeNilCheckClosure(closure *ssa.Value, k callKind) {
}
}
-// getMethodClosure returns a value representing the closure for a method call
-func (s *state) getMethodClosure(fn *ir.SelectorExpr) *ssa.Value {
- // Make a name n2 for the function.
- // fn.Sym might be sync.(*Mutex).Unlock.
- // Make a PFUNC node out of that, then evaluate it.
- // We get back an SSA value representing &sync.(*Mutex).Unlock·f.
- // We can then pass that to defer or go.
- n2 := ir.NewNameAt(fn.Pos(), fn.Sel)
- n2.Curfn = s.curfn
- n2.Class_ = ir.PFUNC
- // n2.Sym already existed, so it's already marked as a function.
- n2.SetPos(fn.Pos())
- n2.SetType(types.Types[types.TUINT8]) // fake type for a static closure. Could use runtime.funcval if we had it.
- return s.expr(n2)
-}
-
// getClosureAndRcvr returns values for the appropriate closure and receiver of an
// interface call
func (s *state) getClosureAndRcvr(fn *ir.SelectorExpr) (*ssa.Value, *ssa.Value) {
i := s.expr(fn.X)
itab := s.newValue1(ssa.OpITab, types.Types[types.TUINTPTR], i)
s.nilCheck(itab)
- itabidx := fn.Offset + 2*int64(types.PtrSize) + 8 // offset of fun field in runtime.itab
+ itabidx := fn.Offset() + 2*int64(types.PtrSize) + 8 // offset of fun field in runtime.itab
closure := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.UintptrPtr, itabidx, itab)
rcvr := s.newValue1(ssa.OpIData, s.f.Config.Types.BytePtr, i)
return closure, rcvr
@@ -5075,11 +5024,11 @@ func (s *state) addr(n ir.Node) *ssa.Value {
case ir.ODOT:
n := n.(*ir.SelectorExpr)
p := s.addr(n.X)
- return s.newValue1I(ssa.OpOffPtr, t, n.Offset, p)
+ return s.newValue1I(ssa.OpOffPtr, t, n.Offset(), p)
case ir.ODOTPTR:
n := n.(*ir.SelectorExpr)
p := s.exprPtr(n.X, n.Bounded(), n.Pos())
- return s.newValue1I(ssa.OpOffPtr, t, n.Offset, p)
+ return s.newValue1I(ssa.OpOffPtr, t, n.Offset(), p)
case ir.OCLOSUREREAD:
n := n.(*ir.ClosureReadExpr)
return s.newValue1I(ssa.OpOffPtr, t, n.Offset,
@@ -5091,7 +5040,7 @@ func (s *state) addr(n ir.Node) *ssa.Value {
}
addr := s.addr(n.X)
return s.newValue1(ssa.OpCopy, t, addr) // ensure that addr has the right type
- case ir.OCALLFUNC, ir.OCALLINTER, ir.OCALLMETH:
+ case ir.OCALLFUNC, ir.OCALLINTER:
n := n.(*ir.CallExpr)
return s.callAddr(n, callNormal)
case ir.ODOTTYPE:
@@ -6328,7 +6277,7 @@ type State struct {
// Prog appends a new Prog.
func (s *State) Prog(as obj.As) *obj.Prog {
p := s.pp.Prog(as)
- if ssa.LosesStmtMark(as) {
+ if objw.LosesStmtMark(as) {
return p
}
// Float a statement start to the beginning of any same-line run.
@@ -7116,21 +7065,17 @@ func (s *State) UseArgs(n int64) {
// fieldIdx finds the index of the field referred to by the ODOT node n.
func fieldIdx(n *ir.SelectorExpr) int {
t := n.X.Type()
- f := n.Sel
if !t.IsStruct() {
panic("ODOT's LHS is not a struct")
}
- var i int
- for _, t1 := range t.Fields().Slice() {
- if t1.Sym != f {
- i++
- continue
- }
- if t1.Offset != n.Offset {
- panic("field offset doesn't match")
+ for i, f := range t.Fields().Slice() {
+ if f.Sym == n.Sel {
+ if f.Offset != n.Offset() {
+ panic("field offset doesn't match")
+ }
+ return i
}
- return i
}
panic(fmt.Sprintf("can't find field in expr %v\n", n))
diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go
index 2a499d6eed..2711f6cec0 100644
--- a/src/cmd/compile/internal/staticinit/sched.go
+++ b/src/cmd/compile/internal/staticinit/sched.go
@@ -469,7 +469,7 @@ func StaticLoc(n ir.Node) (name *ir.Name, offset int64, ok bool) {
if name, offset, ok = StaticLoc(n.X); !ok {
break
}
- offset += n.Offset
+ offset += n.Offset()
return name, offset, true
case ir.OINDEX:
diff --git a/src/cmd/compile/internal/typebits/typebits.go b/src/cmd/compile/internal/typebits/typebits.go
new file mode 100644
index 0000000000..63a2bb3ffa
--- /dev/null
+++ b/src/cmd/compile/internal/typebits/typebits.go
@@ -0,0 +1,87 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typebits
+
+import (
+ "cmd/compile/internal/base"
+ "cmd/compile/internal/bitvec"
+ "cmd/compile/internal/types"
+)
+
+// NOTE: The bitmap for a specific type t could be cached in t after
+// the first run and then simply copied into bv at the correct offset
+// on future calls with the same type t.
+func Set(t *types.Type, off int64, bv bitvec.BitVec) {
+ if t.Align > 0 && off&int64(t.Align-1) != 0 {
+ base.Fatalf("onebitwalktype1: invalid initial alignment: type %v has alignment %d, but offset is %v", t, t.Align, off)
+ }
+ if !t.HasPointers() {
+ // Note: this case ensures that pointers to go:notinheap types
+ // are not considered pointers by garbage collection and stack copying.
+ return
+ }
+
+ switch t.Kind() {
+ case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP:
+ if off&int64(types.PtrSize-1) != 0 {
+ base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
+ }
+ bv.Set(int32(off / int64(types.PtrSize))) // pointer
+
+ case types.TSTRING:
+ // struct { byte *str; intgo len; }
+ if off&int64(types.PtrSize-1) != 0 {
+ base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
+ }
+ bv.Set(int32(off / int64(types.PtrSize))) //pointer in first slot
+
+ case types.TINTER:
+ // struct { Itab *tab; void *data; }
+ // or, when isnilinter(t)==true:
+ // struct { Type *type; void *data; }
+ if off&int64(types.PtrSize-1) != 0 {
+ base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
+ }
+ // The first word of an interface is a pointer, but we don't
+ // treat it as such.
+ // 1. If it is a non-empty interface, the pointer points to an itab
+ // which is always in persistentalloc space.
+ // 2. If it is an empty interface, the pointer points to a _type.
+ // a. If it is a compile-time-allocated type, it points into
+ // the read-only data section.
+ // b. If it is a reflect-allocated type, it points into the Go heap.
+ // Reflect is responsible for keeping a reference to
+ // the underlying type so it won't be GCd.
+ // If we ever have a moving GC, we need to change this for 2b (as
+ // well as scan itabs to update their itab._type fields).
+ bv.Set(int32(off/int64(types.PtrSize) + 1)) // pointer in second slot
+
+ case types.TSLICE:
+ // struct { byte *array; uintgo len; uintgo cap; }
+ if off&int64(types.PtrSize-1) != 0 {
+ base.Fatalf("onebitwalktype1: invalid TARRAY alignment, %v", t)
+ }
+ bv.Set(int32(off / int64(types.PtrSize))) // pointer in first slot (BitsPointer)
+
+ case types.TARRAY:
+ elt := t.Elem()
+ if elt.Width == 0 {
+ // Short-circuit for #20739.
+ break
+ }
+ for i := int64(0); i < t.NumElem(); i++ {
+ Set(elt, off, bv)
+ off += elt.Width
+ }
+
+ case types.TSTRUCT:
+ for _, f := range t.Fields().Slice() {
+ Set(f.Type, off+f.Offset, bv)
+ }
+
+ default:
+ base.Fatalf("onebitwalktype1: unexpected type, %v", t)
+ }
+}
diff --git a/src/cmd/compile/internal/typecheck/builtin.go b/src/cmd/compile/internal/typecheck/builtin.go
index d3c30fbf50..0dee852529 100644
--- a/src/cmd/compile/internal/typecheck/builtin.go
+++ b/src/cmd/compile/internal/typecheck/builtin.go
@@ -3,9 +3,8 @@
package typecheck
import (
- "cmd/compile/internal/base"
- "cmd/compile/internal/ir"
"cmd/compile/internal/types"
+ "cmd/internal/src"
)
var runtimeDecls = [...]struct {
@@ -212,133 +211,133 @@ func runtimeTypes() []*types.Type {
typs[1] = types.NewPtr(typs[0])
typs[2] = types.Types[types.TANY]
typs[3] = types.NewPtr(typs[2])
- typs[4] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3])})
+ typs[4] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[3])})
typs[5] = types.Types[types.TUINTPTR]
typs[6] = types.Types[types.TBOOL]
typs[7] = types.Types[types.TUNSAFEPTR]
- typs[8] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[5]), ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[6])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7])})
- typs[9] = NewFuncType(nil, nil, nil)
+ typs[8] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[5]), types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[6])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[7])})
+ typs[9] = types.NewSignature(types.NoPkg, nil, nil, nil)
typs[10] = types.Types[types.TINTER]
- typs[11] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[10])}, nil)
+ typs[11] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[10])}, nil)
typs[12] = types.Types[types.TINT32]
typs[13] = types.NewPtr(typs[12])
- typs[14] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[13])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[10])})
+ typs[14] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[13])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[10])})
typs[15] = types.Types[types.TINT]
- typs[16] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[15])}, nil)
+ typs[16] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[15])}, nil)
typs[17] = types.Types[types.TUINT]
- typs[18] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[17]), ir.NewField(base.Pos, nil, nil, typs[15])}, nil)
- typs[19] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[6])}, nil)
+ typs[18] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[17]), types.NewField(src.NoXPos, nil, typs[15])}, nil)
+ typs[19] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[6])}, nil)
typs[20] = types.Types[types.TFLOAT64]
- typs[21] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[20])}, nil)
+ typs[21] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[20])}, nil)
typs[22] = types.Types[types.TINT64]
- typs[23] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[22])}, nil)
+ typs[23] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[22])}, nil)
typs[24] = types.Types[types.TUINT64]
- typs[25] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[24])}, nil)
+ typs[25] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[24])}, nil)
typs[26] = types.Types[types.TCOMPLEX128]
- typs[27] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[26])}, nil)
+ typs[27] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[26])}, nil)
typs[28] = types.Types[types.TSTRING]
- typs[29] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])}, nil)
- typs[30] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[2])}, nil)
- typs[31] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[5])}, nil)
+ typs[29] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])}, nil)
+ typs[30] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[2])}, nil)
+ typs[31] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[5])}, nil)
typs[32] = types.NewArray(typs[0], 32)
typs[33] = types.NewPtr(typs[32])
- typs[34] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[33]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])})
- typs[35] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[33]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])})
- typs[36] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[33]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])})
- typs[37] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[33]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])})
+ typs[34] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[33]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])})
+ typs[35] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[33]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])})
+ typs[36] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[33]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])})
+ typs[37] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[33]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])})
typs[38] = types.NewSlice(typs[28])
- typs[39] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[33]), ir.NewField(base.Pos, nil, nil, typs[38])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])})
- typs[40] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[28])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[15])})
+ typs[39] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[33]), types.NewField(src.NoXPos, nil, typs[38])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])})
+ typs[40] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[28])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[15])})
typs[41] = types.NewArray(typs[0], 4)
typs[42] = types.NewPtr(typs[41])
- typs[43] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[42]), ir.NewField(base.Pos, nil, nil, typs[22])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])})
- typs[44] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[33]), ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[15])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])})
- typs[45] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[15])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])})
+ typs[43] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[42]), types.NewField(src.NoXPos, nil, typs[22])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])})
+ typs[44] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[33]), types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[15])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])})
+ typs[45] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[15])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])})
typs[46] = types.RuneType
typs[47] = types.NewSlice(typs[46])
- typs[48] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[33]), ir.NewField(base.Pos, nil, nil, typs[47])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])})
+ typs[48] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[33]), types.NewField(src.NoXPos, nil, typs[47])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])})
typs[49] = types.NewSlice(typs[0])
- typs[50] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[33]), ir.NewField(base.Pos, nil, nil, typs[28])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[49])})
+ typs[50] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[33]), types.NewField(src.NoXPos, nil, typs[28])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[49])})
typs[51] = types.NewArray(typs[46], 32)
typs[52] = types.NewPtr(typs[51])
- typs[53] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[52]), ir.NewField(base.Pos, nil, nil, typs[28])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[47])})
- typs[54] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[5])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[15])})
- typs[55] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28]), ir.NewField(base.Pos, nil, nil, typs[15])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[46]), ir.NewField(base.Pos, nil, nil, typs[15])})
- typs[56] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[28])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[15])})
- typs[57] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[2])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[2])})
- typs[58] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[2])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7])})
- typs[59] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[3])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[2])})
- typs[60] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[2])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[2]), ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[61] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[1])}, nil)
- typs[62] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1])}, nil)
+ typs[53] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[52]), types.NewField(src.NoXPos, nil, typs[28])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[47])})
+ typs[54] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[5])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[15])})
+ typs[55] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[28]), types.NewField(src.NoXPos, nil, typs[15])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[46]), types.NewField(src.NoXPos, nil, typs[15])})
+ typs[56] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[28])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[15])})
+ typs[57] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[2])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[2])})
+ typs[58] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[2])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[7])})
+ typs[59] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[3])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[2])})
+ typs[60] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[2])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[2]), types.NewField(src.NoXPos, nil, typs[6])})
+ typs[61] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[1])}, nil)
+ typs[62] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1])}, nil)
typs[63] = types.NewPtr(typs[5])
- typs[64] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[63]), ir.NewField(base.Pos, nil, nil, typs[7]), ir.NewField(base.Pos, nil, nil, typs[7])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[6])})
+ typs[64] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[63]), types.NewField(src.NoXPos, nil, typs[7]), types.NewField(src.NoXPos, nil, typs[7])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[6])})
typs[65] = types.Types[types.TUINT32]
- typs[66] = NewFuncType(nil, nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[65])})
+ typs[66] = types.NewSignature(types.NoPkg, nil, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[65])})
typs[67] = types.NewMap(typs[2], typs[2])
- typs[68] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[22]), ir.NewField(base.Pos, nil, nil, typs[3])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[67])})
- typs[69] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[3])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[67])})
- typs[70] = NewFuncType(nil, nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[67])})
- typs[71] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[67]), ir.NewField(base.Pos, nil, nil, typs[3])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3])})
- typs[72] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[67]), ir.NewField(base.Pos, nil, nil, typs[2])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3])})
- typs[73] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[67]), ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[1])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3])})
- typs[74] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[67]), ir.NewField(base.Pos, nil, nil, typs[3])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[75] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[67]), ir.NewField(base.Pos, nil, nil, typs[2])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[76] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[67]), ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[1])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[77] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[67]), ir.NewField(base.Pos, nil, nil, typs[3])}, nil)
- typs[78] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[67]), ir.NewField(base.Pos, nil, nil, typs[2])}, nil)
- typs[79] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3])}, nil)
- typs[80] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[67])}, nil)
+ typs[68] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[22]), types.NewField(src.NoXPos, nil, typs[3])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[67])})
+ typs[69] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[3])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[67])})
+ typs[70] = types.NewSignature(types.NoPkg, nil, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[67])})
+ typs[71] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[67]), types.NewField(src.NoXPos, nil, typs[3])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[3])})
+ typs[72] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[67]), types.NewField(src.NoXPos, nil, typs[2])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[3])})
+ typs[73] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[67]), types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[1])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[3])})
+ typs[74] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[67]), types.NewField(src.NoXPos, nil, typs[3])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[6])})
+ typs[75] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[67]), types.NewField(src.NoXPos, nil, typs[2])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[6])})
+ typs[76] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[67]), types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[1])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[6])})
+ typs[77] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[67]), types.NewField(src.NoXPos, nil, typs[3])}, nil)
+ typs[78] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[67]), types.NewField(src.NoXPos, nil, typs[2])}, nil)
+ typs[79] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[3])}, nil)
+ typs[80] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[67])}, nil)
typs[81] = types.NewChan(typs[2], types.Cboth)
- typs[82] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[22])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[81])})
- typs[83] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[15])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[81])})
+ typs[82] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[22])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[81])})
+ typs[83] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[15])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[81])})
typs[84] = types.NewChan(typs[2], types.Crecv)
- typs[85] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[84]), ir.NewField(base.Pos, nil, nil, typs[3])}, nil)
- typs[86] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[84]), ir.NewField(base.Pos, nil, nil, typs[3])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[6])})
+ typs[85] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[84]), types.NewField(src.NoXPos, nil, typs[3])}, nil)
+ typs[86] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[84]), types.NewField(src.NoXPos, nil, typs[3])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[6])})
typs[87] = types.NewChan(typs[2], types.Csend)
- typs[88] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[87]), ir.NewField(base.Pos, nil, nil, typs[3])}, nil)
+ typs[88] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[87]), types.NewField(src.NoXPos, nil, typs[3])}, nil)
typs[89] = types.NewArray(typs[0], 3)
- typs[90] = NewStructType([]*ir.Field{ir.NewField(base.Pos, Lookup("enabled"), nil, typs[6]), ir.NewField(base.Pos, Lookup("pad"), nil, typs[89]), ir.NewField(base.Pos, Lookup("needed"), nil, typs[6]), ir.NewField(base.Pos, Lookup("cgo"), nil, typs[6]), ir.NewField(base.Pos, Lookup("alignme"), nil, typs[24])})
- typs[91] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[3])}, nil)
- typs[92] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[3])}, nil)
- typs[93] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[15])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[15])})
- typs[94] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[87]), ir.NewField(base.Pos, nil, nil, typs[3])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[95] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[84])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[6])})
+ typs[90] = types.NewStruct(types.NoPkg, []*types.Field{types.NewField(src.NoXPos, Lookup("enabled"), typs[6]), types.NewField(src.NoXPos, Lookup("pad"), typs[89]), types.NewField(src.NoXPos, Lookup("needed"), typs[6]), types.NewField(src.NoXPos, Lookup("cgo"), typs[6]), types.NewField(src.NoXPos, Lookup("alignme"), typs[24])})
+ typs[91] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[3])}, nil)
+ typs[92] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[3])}, nil)
+ typs[93] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[15])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[15])})
+ typs[94] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[87]), types.NewField(src.NoXPos, nil, typs[3])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[6])})
+ typs[95] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[84])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[6])})
typs[96] = types.NewPtr(typs[6])
- typs[97] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[96]), ir.NewField(base.Pos, nil, nil, typs[84])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[98] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[63])}, nil)
- typs[99] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[63]), ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[6])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[100] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[15])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7])})
- typs[101] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[22]), ir.NewField(base.Pos, nil, nil, typs[22])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7])})
- typs[102] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[15]), ir.NewField(base.Pos, nil, nil, typs[7])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7])})
+ typs[97] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[96]), types.NewField(src.NoXPos, nil, typs[84])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[6])})
+ typs[98] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[63])}, nil)
+ typs[99] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[63]), types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[6])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[6])})
+ typs[100] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[15])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[7])})
+ typs[101] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[22]), types.NewField(src.NoXPos, nil, typs[22])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[7])})
+ typs[102] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[15]), types.NewField(src.NoXPos, nil, typs[7])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[7])})
typs[103] = types.NewSlice(typs[2])
- typs[104] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[103]), ir.NewField(base.Pos, nil, nil, typs[15])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[103])})
- typs[105] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[5])}, nil)
- typs[106] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7]), ir.NewField(base.Pos, nil, nil, typs[5])}, nil)
- typs[107] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[5])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[108] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[3]), ir.NewField(base.Pos, nil, nil, typs[3])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[109] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7]), ir.NewField(base.Pos, nil, nil, typs[7])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[6])})
- typs[110] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7]), ir.NewField(base.Pos, nil, nil, typs[5]), ir.NewField(base.Pos, nil, nil, typs[5])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[5])})
- typs[111] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7]), ir.NewField(base.Pos, nil, nil, typs[5])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[5])})
- typs[112] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[22]), ir.NewField(base.Pos, nil, nil, typs[22])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[22])})
- typs[113] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[24]), ir.NewField(base.Pos, nil, nil, typs[24])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[24])})
- typs[114] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[20])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[22])})
- typs[115] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[20])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[24])})
- typs[116] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[20])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[65])})
- typs[117] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[22])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[20])})
- typs[118] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[24])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[20])})
- typs[119] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[65])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[20])})
- typs[120] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[26]), ir.NewField(base.Pos, nil, nil, typs[26])}, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[26])})
- typs[121] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[5]), ir.NewField(base.Pos, nil, nil, typs[5])}, nil)
- typs[122] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[5]), ir.NewField(base.Pos, nil, nil, typs[5]), ir.NewField(base.Pos, nil, nil, typs[5])}, nil)
- typs[123] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7]), ir.NewField(base.Pos, nil, nil, typs[1]), ir.NewField(base.Pos, nil, nil, typs[5])}, nil)
+ typs[104] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[103]), types.NewField(src.NoXPos, nil, typs[15])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[103])})
+ typs[105] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[5])}, nil)
+ typs[106] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[7]), types.NewField(src.NoXPos, nil, typs[5])}, nil)
+ typs[107] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[5])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[6])})
+ typs[108] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[3]), types.NewField(src.NoXPos, nil, typs[3])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[6])})
+ typs[109] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[7]), types.NewField(src.NoXPos, nil, typs[7])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[6])})
+ typs[110] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[7]), types.NewField(src.NoXPos, nil, typs[5]), types.NewField(src.NoXPos, nil, typs[5])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[5])})
+ typs[111] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[7]), types.NewField(src.NoXPos, nil, typs[5])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[5])})
+ typs[112] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[22]), types.NewField(src.NoXPos, nil, typs[22])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[22])})
+ typs[113] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[24]), types.NewField(src.NoXPos, nil, typs[24])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[24])})
+ typs[114] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[20])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[22])})
+ typs[115] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[20])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[24])})
+ typs[116] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[20])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[65])})
+ typs[117] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[22])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[20])})
+ typs[118] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[24])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[20])})
+ typs[119] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[65])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[20])})
+ typs[120] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[26]), types.NewField(src.NoXPos, nil, typs[26])}, []*types.Field{types.NewField(src.NoXPos, nil, typs[26])})
+ typs[121] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[5]), types.NewField(src.NoXPos, nil, typs[5])}, nil)
+ typs[122] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[5]), types.NewField(src.NoXPos, nil, typs[5]), types.NewField(src.NoXPos, nil, typs[5])}, nil)
+ typs[123] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[7]), types.NewField(src.NoXPos, nil, typs[1]), types.NewField(src.NoXPos, nil, typs[5])}, nil)
typs[124] = types.NewSlice(typs[7])
- typs[125] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[7]), ir.NewField(base.Pos, nil, nil, typs[124])}, nil)
+ typs[125] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[7]), types.NewField(src.NoXPos, nil, typs[124])}, nil)
typs[126] = types.Types[types.TUINT8]
- typs[127] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[126]), ir.NewField(base.Pos, nil, nil, typs[126])}, nil)
+ typs[127] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[126]), types.NewField(src.NoXPos, nil, typs[126])}, nil)
typs[128] = types.Types[types.TUINT16]
- typs[129] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[128]), ir.NewField(base.Pos, nil, nil, typs[128])}, nil)
- typs[130] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[65]), ir.NewField(base.Pos, nil, nil, typs[65])}, nil)
- typs[131] = NewFuncType(nil, []*ir.Field{ir.NewField(base.Pos, nil, nil, typs[24]), ir.NewField(base.Pos, nil, nil, typs[24])}, nil)
+ typs[129] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[128]), types.NewField(src.NoXPos, nil, typs[128])}, nil)
+ typs[130] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[65]), types.NewField(src.NoXPos, nil, typs[65])}, nil)
+ typs[131] = types.NewSignature(types.NoPkg, nil, []*types.Field{types.NewField(src.NoXPos, nil, typs[24]), types.NewField(src.NoXPos, nil, typs[24])}, nil)
return typs[:]
}
diff --git a/src/cmd/compile/internal/typecheck/builtin_test.go b/src/cmd/compile/internal/typecheck/builtin_test.go
index cc8d49730a..fb9d3e393f 100644
--- a/src/cmd/compile/internal/typecheck/builtin_test.go
+++ b/src/cmd/compile/internal/typecheck/builtin_test.go
@@ -13,7 +13,6 @@ import (
)
func TestBuiltin(t *testing.T) {
- t.Skip("mkbuiltin needs fixing")
testenv.MustHaveGoRun(t)
t.Parallel()
diff --git a/src/cmd/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go
index 54d70cb835..e22b284e82 100644
--- a/src/cmd/compile/internal/typecheck/const.go
+++ b/src/cmd/compile/internal/typecheck/const.go
@@ -929,7 +929,7 @@ func evalunsafe(n ir.Node) int64 {
fallthrough
case ir.ODOT:
r := r.(*ir.SelectorExpr)
- v += r.Offset
+ v += r.Offset()
next = r.X
default:
ir.Dump("unsafenmagic", tsel)
diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go
index 9f66d0fa17..36057ba2d1 100644
--- a/src/cmd/compile/internal/typecheck/dcl.go
+++ b/src/cmd/compile/internal/typecheck/dcl.go
@@ -281,72 +281,6 @@ func CheckFuncStack() {
}
}
-// turn a parsed function declaration into a type
-func NewFuncType(nrecv *ir.Field, nparams, nresults []*ir.Field) *types.Type {
- funarg := func(n *ir.Field) *types.Field {
- lno := base.Pos
- base.Pos = n.Pos
-
- if n.Ntype != nil {
- n.Type = typecheckNtype(n.Ntype).Type()
- n.Ntype = nil
- }
-
- f := types.NewField(n.Pos, n.Sym, n.Type)
- f.SetIsDDD(n.IsDDD)
- if n.Decl != nil {
- n.Decl.SetType(f.Type)
- f.Nname = n.Decl
- }
-
- base.Pos = lno
- return f
- }
- funargs := func(nn []*ir.Field) []*types.Field {
- res := make([]*types.Field, len(nn))
- for i, n := range nn {
- res[i] = funarg(n)
- }
- return res
- }
-
- var recv *types.Field
- if nrecv != nil {
- recv = funarg(nrecv)
- }
-
- t := types.NewSignature(types.LocalPkg, recv, funargs(nparams), funargs(nresults))
- checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
- return t
-}
-
-// convert a parsed id/type list into
-// a type for struct/interface/arglist
-func NewStructType(l []*ir.Field) *types.Type {
- lno := base.Pos
-
- fields := make([]*types.Field, len(l))
- for i, n := range l {
- base.Pos = n.Pos
-
- if n.Ntype != nil {
- n.Type = typecheckNtype(n.Ntype).Type()
- n.Ntype = nil
- }
- f := types.NewField(n.Pos, n.Sym, n.Type)
- if n.Embedded {
- checkembeddedtype(n.Type)
- f.Embedded = 1
- }
- f.Note = n.Note
- fields[i] = f
- }
- checkdupfields("field", fields)
-
- base.Pos = lno
- return types.NewStruct(types.LocalPkg, fields)
-}
-
// Add a method, declared as a function.
// - msym is the method symbol
// - t is function type (with receiver)
@@ -513,7 +447,6 @@ func funcarg(n *ir.Field, ctxt ir.Class) {
name := ir.NewNameAt(n.Pos, n.Sym)
n.Decl = name
name.Ntype = n.Ntype
- name.SetIsDDD(n.IsDDD)
Declare(name, ctxt)
vargen++
@@ -527,7 +460,6 @@ func funcarg2(f *types.Field, ctxt ir.Class) {
n := ir.NewNameAt(f.Pos, f.Sym)
f.Nname = n
n.SetType(f.Type)
- n.SetIsDDD(f.IsDDD())
Declare(n, ctxt)
}
@@ -604,27 +536,6 @@ func initname(s string) bool {
return s == "init"
}
-func tointerface(nmethods []*ir.Field) *types.Type {
- if len(nmethods) == 0 {
- return types.Types[types.TINTER]
- }
-
- lno := base.Pos
-
- methods := make([]*types.Field, len(nmethods))
- for i, n := range nmethods {
- base.Pos = n.Pos
- if n.Ntype != nil {
- n.Type = typecheckNtype(n.Ntype).Type()
- n.Ntype = nil
- }
- methods[i] = types.NewField(n.Pos, n.Sym, n.Type)
- }
-
- base.Pos = lno
- return types.NewInterface(types.LocalPkg, methods)
-}
-
var vargen int
func Temp(t *types.Type) *ir.Name {
@@ -643,6 +554,9 @@ func TempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name {
if t == nil {
base.Fatalf("tempAt called with nil type")
}
+ if t.Kind() == types.TFUNC && t.Recv() != nil {
+ base.Fatalf("misuse of method type: %v", t)
+ }
s := &types.Sym{
Name: autotmpname(len(curfn.Dcl)),
@@ -676,30 +590,26 @@ func autotmpname(n int) string {
// f is method type, with receiver.
// return function type, receiver as first argument (or not).
-func NewMethodType(f *types.Type, receiver *types.Type) *types.Type {
- inLen := f.Params().Fields().Len()
- if receiver != nil {
- inLen++
+func NewMethodType(sig *types.Type, recv *types.Type) *types.Type {
+ nrecvs := 0
+ if recv != nil {
+ nrecvs++
}
- in := make([]*ir.Field, 0, inLen)
- if receiver != nil {
- d := ir.NewField(base.Pos, nil, nil, receiver)
- in = append(in, d)
+ params := make([]*types.Field, nrecvs+sig.Params().Fields().Len())
+ if recv != nil {
+ params[0] = types.NewField(base.Pos, nil, recv)
}
-
- for _, t := range f.Params().Fields().Slice() {
- d := ir.NewField(base.Pos, nil, nil, t.Type)
- d.IsDDD = t.IsDDD()
- in = append(in, d)
+ for i, param := range sig.Params().Fields().Slice() {
+ d := types.NewField(base.Pos, nil, param.Type)
+ d.SetIsDDD(param.IsDDD())
+ params[nrecvs+i] = d
}
- outLen := f.Results().Fields().Len()
- out := make([]*ir.Field, 0, outLen)
- for _, t := range f.Results().Fields().Slice() {
- d := ir.NewField(base.Pos, nil, nil, t.Type)
- out = append(out, d)
+ results := make([]*types.Field, sig.Results().Fields().Len())
+ for i, t := range sig.Results().Fields().Slice() {
+ results[i] = types.NewField(base.Pos, nil, t.Type)
}
- return NewFuncType(nil, in, out)
+ return types.NewSignature(types.LocalPkg, nil, params, results)
}
diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go
index f940a2e73d..3e7a880c2a 100644
--- a/src/cmd/compile/internal/typecheck/expr.go
+++ b/src/cmd/compile/internal/typecheck/expr.go
@@ -571,7 +571,6 @@ func tcDot(n *ir.SelectorExpr, top int) ir.Node {
}
n.X = typecheck(n.X, ctxExpr|ctxType)
-
n.X = DefaultLit(n.X, nil)
t := n.X.Type()
@@ -581,8 +580,6 @@ func tcDot(n *ir.SelectorExpr, top int) ir.Node {
return n
}
- s := n.Sel
-
if n.X.Op() == ir.OTYPE {
return typecheckMethodExpr(n)
}
@@ -629,7 +626,10 @@ func tcDot(n *ir.SelectorExpr, top int) ir.Node {
}
if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && top&ctxCallee == 0 {
- return tcCallPart(n, s)
+ // Create top-level function.
+ fn := makepartialcall(n)
+
+ return ir.NewCallPartExpr(n.Pos(), n.X, n.Selection, fn)
}
return n
}
@@ -831,24 +831,18 @@ func tcSPtr(n *ir.UnaryExpr) ir.Node {
// tcSlice typechecks an OSLICE or OSLICE3 node.
func tcSlice(n *ir.SliceExpr) ir.Node {
- n.X = Expr(n.X)
- low, high, max := n.SliceBounds()
+ n.X = DefaultLit(Expr(n.X), nil)
+ n.Low = indexlit(Expr(n.Low))
+ n.High = indexlit(Expr(n.High))
+ n.Max = indexlit(Expr(n.Max))
hasmax := n.Op().IsSlice3()
- low = Expr(low)
- high = Expr(high)
- max = Expr(max)
- n.X = DefaultLit(n.X, nil)
- low = indexlit(low)
- high = indexlit(high)
- max = indexlit(max)
- n.SetSliceBounds(low, high, max)
l := n.X
if l.Type() == nil {
n.SetType(nil)
return n
}
if l.Type().IsArray() {
- if !ir.IsAssignable(n.X) {
+ if !ir.IsAddressable(n.X) {
base.Errorf("invalid operation %v (slice of unaddressable value)", n)
n.SetType(nil)
return n
@@ -886,19 +880,19 @@ func tcSlice(n *ir.SliceExpr) ir.Node {
return n
}
- if low != nil && !checksliceindex(l, low, tp) {
+ if n.Low != nil && !checksliceindex(l, n.Low, tp) {
n.SetType(nil)
return n
}
- if high != nil && !checksliceindex(l, high, tp) {
+ if n.High != nil && !checksliceindex(l, n.High, tp) {
n.SetType(nil)
return n
}
- if max != nil && !checksliceindex(l, max, tp) {
+ if n.Max != nil && !checksliceindex(l, n.Max, tp) {
n.SetType(nil)
return n
}
- if !checksliceconst(low, high) || !checksliceconst(low, max) || !checksliceconst(high, max) {
+ if !checksliceconst(n.Low, n.High) || !checksliceconst(n.Low, n.Max) || !checksliceconst(n.High, n.Max) {
n.SetType(nil)
return n
}
@@ -924,30 +918,22 @@ func tcSliceHeader(n *ir.SliceHeaderExpr) ir.Node {
base.Fatalf("need unsafe.Pointer for OSLICEHEADER")
}
- if x := len(n.LenCap); x != 2 {
- base.Fatalf("expected 2 params (len, cap) for OSLICEHEADER, got %d", x)
- }
-
n.Ptr = Expr(n.Ptr)
- l := Expr(n.LenCap[0])
- c := Expr(n.LenCap[1])
- l = DefaultLit(l, types.Types[types.TINT])
- c = DefaultLit(c, types.Types[types.TINT])
+ n.Len = DefaultLit(Expr(n.Len), types.Types[types.TINT])
+ n.Cap = DefaultLit(Expr(n.Cap), types.Types[types.TINT])
- if ir.IsConst(l, constant.Int) && ir.Int64Val(l) < 0 {
+ if ir.IsConst(n.Len, constant.Int) && ir.Int64Val(n.Len) < 0 {
base.Fatalf("len for OSLICEHEADER must be non-negative")
}
- if ir.IsConst(c, constant.Int) && ir.Int64Val(c) < 0 {
+ if ir.IsConst(n.Cap, constant.Int) && ir.Int64Val(n.Cap) < 0 {
base.Fatalf("cap for OSLICEHEADER must be non-negative")
}
- if ir.IsConst(l, constant.Int) && ir.IsConst(c, constant.Int) && constant.Compare(l.Val(), token.GTR, c.Val()) {
+ if ir.IsConst(n.Len, constant.Int) && ir.IsConst(n.Cap, constant.Int) && constant.Compare(n.Len.Val(), token.GTR, n.Cap.Val()) {
base.Fatalf("len larger than cap for OSLICEHEADER")
}
- n.LenCap[0] = l
- n.LenCap[1] = c
return n
}
diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go
index 99d81dcede..ed4f3ad4fe 100644
--- a/src/cmd/compile/internal/typecheck/func.go
+++ b/src/cmd/compile/internal/typecheck/func.go
@@ -73,17 +73,17 @@ func ClosureType(clo *ir.ClosureExpr) *types.Type {
// The information appears in the binary in the form of type descriptors;
// the struct is unnamed so that closures in multiple packages with the
// same struct type can share the descriptor.
- fields := []*ir.Field{
- ir.NewField(base.Pos, Lookup(".F"), nil, types.Types[types.TUINTPTR]),
+ fields := []*types.Field{
+ types.NewField(base.Pos, Lookup(".F"), types.Types[types.TUINTPTR]),
}
for _, v := range clo.Func.ClosureVars {
typ := v.Type()
if !v.Byval() {
typ = types.NewPtr(typ)
}
- fields = append(fields, ir.NewField(base.Pos, v.Sym(), nil, typ))
+ fields = append(fields, types.NewField(base.Pos, v.Sym(), typ))
}
- typ := NewStructType(fields)
+ typ := types.NewStruct(types.NoPkg, fields)
typ.SetNoalg(true)
return typ
}
@@ -92,9 +92,9 @@ func ClosureType(clo *ir.ClosureExpr) *types.Type {
// needed in the closure for n (n must be a OCALLPART node).
// The address of a variable of the returned type can be cast to a func.
func PartialCallType(n *ir.CallPartExpr) *types.Type {
- t := NewStructType([]*ir.Field{
- ir.NewField(base.Pos, Lookup("F"), nil, types.Types[types.TUINTPTR]),
- ir.NewField(base.Pos, Lookup("R"), nil, n.X.Type()),
+ t := types.NewStruct(types.NoPkg, []*types.Field{
+ types.NewField(base.Pos, Lookup("F"), types.Types[types.TUINTPTR]),
+ types.NewField(base.Pos, Lookup("R"), n.X.Type()),
})
t.SetNoalg(true)
return t
@@ -249,7 +249,9 @@ var globClosgen int32
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
// for partial calls.
-func makepartialcall(dot *ir.SelectorExpr, t0 *types.Type, meth *types.Sym) *ir.Func {
+func makepartialcall(dot *ir.SelectorExpr) *ir.Func {
+ t0 := dot.Type()
+ meth := dot.Sel
rcvrtype := dot.X.Type()
sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm")
@@ -263,11 +265,10 @@ func makepartialcall(dot *ir.SelectorExpr, t0 *types.Type, meth *types.Sym) *ir.
ir.CurFunc = nil
// Set line number equal to the line number where the method is declared.
- var m *types.Field
- if lookdot0(meth, rcvrtype, &m, false) == 1 && m.Pos.IsKnown() {
- base.Pos = m.Pos
+ if pos := dot.Selection.Pos; pos.IsKnown() {
+ base.Pos = pos
}
- // Note: !m.Pos.IsKnown() happens for method expressions where
+ // Note: !dot.Selection.Pos.IsKnown() happens for method expressions where
// the method is implicitly declared. The Error method of the
// built-in error type is one such method. We leave the line
// number at the use of the method expression in this
@@ -280,18 +281,17 @@ func makepartialcall(dot *ir.SelectorExpr, t0 *types.Type, meth *types.Sym) *ir.
fn := DeclFunc(sym, tfn)
fn.SetDupok(true)
fn.SetNeedctxt(true)
+ fn.SetWrapper(true)
// Declare and initialize variable holding receiver.
cr := ir.NewClosureRead(rcvrtype, types.Rnd(int64(types.PtrSize), int64(rcvrtype.Align)))
- ptr := NewName(Lookup(".this"))
- Declare(ptr, ir.PAUTO)
- ptr.SetUsed(true)
+ var ptr *ir.Name
var body []ir.Node
if rcvrtype.IsPtr() || rcvrtype.IsInterface() {
- ptr.SetType(rcvrtype)
+ ptr = Temp(rcvrtype)
body = append(body, ir.NewAssignStmt(base.Pos, ptr, cr))
} else {
- ptr.SetType(types.NewPtr(rcvrtype))
+ ptr = Temp(types.NewPtr(rcvrtype))
body = append(body, ir.NewAssignStmt(base.Pos, ptr, NodAddr(cr)))
}
@@ -382,23 +382,6 @@ func tcClosure(clo *ir.ClosureExpr, top int) {
Target.Decls = append(Target.Decls, fn)
}
-func tcCallPart(n ir.Node, sym *types.Sym) *ir.CallPartExpr {
- switch n.Op() {
- case ir.ODOTINTER, ir.ODOTMETH:
- break
-
- default:
- base.Fatalf("invalid typecheckpartialcall")
- }
- dot := n.(*ir.SelectorExpr)
-
- // Create top-level function.
- fn := makepartialcall(dot, dot.Type(), sym)
- fn.SetWrapper(true)
-
- return ir.NewCallPartExpr(dot.Pos(), dot.X, dot.Selection, fn)
-}
-
// type check function definition
// To be called by typecheck, not directly.
// (Call typecheckFunc instead.)
@@ -542,9 +525,7 @@ func tcCall(n *ir.CallExpr, top int) ir.Node {
default:
n.SetOp(ir.OCALLFUNC)
if t.Kind() != types.TFUNC {
- // TODO(mdempsky): Remove "o.Sym() != nil" once we stop
- // using ir.Name for numeric literals.
- if o := ir.Orig(l); o.Name() != nil && o.Sym() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil {
+ if o := ir.Orig(l); o.Name() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil {
// be more specific when the non-function
// name matches a predeclared function
base.Errorf("cannot call non-function %L, declared at %s",
diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go
index 4ddee01b5a..3b071a61ab 100644
--- a/src/cmd/compile/internal/typecheck/iexport.go
+++ b/src/cmd/compile/internal/typecheck/iexport.go
@@ -594,23 +594,15 @@ func (w *exportWriter) selector(s *types.Sym) {
base.Fatalf("missing currPkg")
}
- // Method selectors are rewritten into method symbols (of the
- // form T.M) during typechecking, but we want to write out
- // just the bare method name.
- name := s.Name
- if i := strings.LastIndex(name, "."); i >= 0 {
- name = name[i+1:]
- } else {
- pkg := w.currPkg
- if types.IsExported(name) {
- pkg = types.LocalPkg
- }
- if s.Pkg != pkg {
- base.Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path)
- }
+ pkg := w.currPkg
+ if types.IsExported(s.Name) {
+ pkg = types.LocalPkg
+ }
+ if s.Pkg != pkg {
+ base.Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path)
}
- w.string(name)
+ w.string(s.Name)
}
func (w *exportWriter) typ(t *types.Type) {
@@ -858,8 +850,6 @@ func intSize(typ *types.Type) (signed bool, maxBytes uint) {
// according to the maximum number of bytes needed to encode a value
// of type typ. As a special case, 8-bit types are always encoded as a
// single byte.
-//
-// TODO(mdempsky): Is this level of complexity really worthwhile?
func (w *exportWriter) mpint(x constant.Value, typ *types.Type) {
signed, maxBytes := intSize(typ)
@@ -1145,7 +1135,7 @@ func (w *exportWriter) stmt(n ir.Node) {
n := n.(*ir.RangeStmt)
w.op(ir.ORANGE)
w.pos(n.Pos())
- w.stmtList(n.Vars)
+ w.exprsOrNil(n.Key, n.Value)
w.expr(n.X)
w.stmtList(n.Body)
@@ -1154,8 +1144,7 @@ func (w *exportWriter) stmt(n ir.Node) {
w.op(n.Op())
w.pos(n.Pos())
w.stmtList(n.Init())
- w.exprsOrNil(nil, nil) // TODO(rsc): Delete (and fix importer).
- w.caseList(n)
+ w.commList(n.Cases)
case ir.OSWITCH:
n := n.(*ir.SwitchStmt)
@@ -1163,7 +1152,7 @@ func (w *exportWriter) stmt(n ir.Node) {
w.pos(n.Pos())
w.stmtList(n.Init())
w.exprsOrNil(n.Tag, nil)
- w.caseList(n)
+ w.caseList(n.Cases, isNamedTypeSwitch(n.Tag))
// case OCASE:
// handled by caseList
@@ -1187,39 +1176,32 @@ func (w *exportWriter) stmt(n ir.Node) {
}
}
-func isNamedTypeSwitch(n ir.Node) bool {
- if n.Op() != ir.OSWITCH {
- return false
- }
- sw := n.(*ir.SwitchStmt)
- if sw.Tag == nil || sw.Tag.Op() != ir.OTYPESW {
- return false
- }
- guard := sw.Tag.(*ir.TypeSwitchGuard)
- return guard.Tag != nil
+func isNamedTypeSwitch(x ir.Node) bool {
+ guard, ok := x.(*ir.TypeSwitchGuard)
+ return ok && guard.Tag != nil
}
-func (w *exportWriter) caseList(sw ir.Node) {
- namedTypeSwitch := isNamedTypeSwitch(sw)
-
- var cases []ir.Node
- if sw.Op() == ir.OSWITCH {
- cases = sw.(*ir.SwitchStmt).Cases
- } else {
- cases = sw.(*ir.SelectStmt).Cases
- }
+func (w *exportWriter) caseList(cases []*ir.CaseClause, namedTypeSwitch bool) {
w.uint64(uint64(len(cases)))
for _, cas := range cases {
- cas := cas.(*ir.CaseStmt)
w.pos(cas.Pos())
w.stmtList(cas.List)
if namedTypeSwitch {
- w.localName(cas.Vars[0].(*ir.Name))
+ w.localName(cas.Var.(*ir.Name))
}
w.stmtList(cas.Body)
}
}
+func (w *exportWriter) commList(cases []*ir.CommClause) {
+ w.uint64(uint64(len(cases)))
+ for _, cas := range cases {
+ w.pos(cas.Pos())
+ w.node(cas.Comm)
+ w.stmtList(cas.Body)
+ }
+}
+
func (w *exportWriter) exprList(list ir.Nodes) {
for _, n := range list {
w.expr(n)
@@ -1313,7 +1295,7 @@ func (w *exportWriter) expr(n ir.Node) {
s = n.Tag.Sym()
}
w.localIdent(s, 0) // declared pseudo-variable, if any
- w.exprsOrNil(n.X, nil)
+ w.expr(n.X)
// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
// should have been resolved by typechecking - handled by default case
@@ -1348,7 +1330,8 @@ func (w *exportWriter) expr(n ir.Node) {
n := n.(*ir.KeyExpr)
w.op(ir.OKEY)
w.pos(n.Pos())
- w.exprsOrNil(n.Key, n.Value)
+ w.expr(n.Key)
+ w.expr(n.Value)
// case OSTRUCTKEY:
// unreachable - handled in case OSTRUCTLIT by elemList
@@ -1387,17 +1370,15 @@ func (w *exportWriter) expr(n ir.Node) {
w.op(ir.OSLICE)
w.pos(n.Pos())
w.expr(n.X)
- low, high, _ := n.SliceBounds()
- w.exprsOrNil(low, high)
+ w.exprsOrNil(n.Low, n.High)
case ir.OSLICE3, ir.OSLICE3ARR:
n := n.(*ir.SliceExpr)
w.op(ir.OSLICE3)
w.pos(n.Pos())
w.expr(n.X)
- low, high, max := n.SliceBounds()
- w.exprsOrNil(low, high)
- w.expr(max)
+ w.exprsOrNil(n.Low, n.High)
+ w.expr(n.Max)
case ir.OCOPY, ir.OCOMPLEX:
// treated like other builtin calls (see e.g., OREAL)
@@ -1412,8 +1393,8 @@ func (w *exportWriter) expr(n ir.Node) {
n := n.(*ir.ConvExpr)
w.op(ir.OCONV)
w.pos(n.Pos())
- w.expr(n.X)
w.typ(n.Type())
+ w.expr(n.X)
case ir.OREAL, ir.OIMAG, ir.OCAP, ir.OCLOSE, ir.OLEN, ir.ONEW, ir.OPANIC:
n := n.(*ir.UnaryExpr)
@@ -1544,6 +1525,7 @@ func (w *exportWriter) fieldList(list ir.Nodes) {
w.uint64(uint64(len(list)))
for _, n := range list {
n := n.(*ir.StructKeyExpr)
+ w.pos(n.Pos())
w.selector(n.Field)
w.expr(n.Value)
}
diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go
index ab43d4f71b..546ddcba79 100644
--- a/src/cmd/compile/internal/typecheck/iimport.go
+++ b/src/cmd/compile/internal/typecheck/iimport.go
@@ -71,7 +71,12 @@ func ImportBody(fn *ir.Func) {
base.Fatalf("missing import reader for %v", fn)
}
+ if inimport {
+ base.Fatalf("recursive inimport")
+ }
+ inimport = true
r.doInline(fn)
+ inimport = false
}
func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset) *importReader {
@@ -767,10 +772,10 @@ func (r *importReader) stmtList() []ir.Node {
return list
}
-func (r *importReader) caseList(sw ir.Node) []ir.Node {
- namedTypeSwitch := isNamedTypeSwitch(sw)
+func (r *importReader) caseList(switchExpr ir.Node) []*ir.CaseClause {
+ namedTypeSwitch := isNamedTypeSwitch(switchExpr)
- cases := make([]ir.Node, r.uint64())
+ cases := make([]*ir.CaseClause, r.uint64())
for i := range cases {
cas := ir.NewCaseStmt(r.pos(), nil, nil)
cas.List.Set(r.stmtList())
@@ -780,8 +785,8 @@ func (r *importReader) caseList(sw ir.Node) []ir.Node {
// Sym for diagnostics anyway.
caseVar := ir.NewNameAt(cas.Pos(), r.ident())
Declare(caseVar, DeclContext)
- cas.Vars = []ir.Node{caseVar}
- caseVar.Defn = sw.(*ir.SwitchStmt).Tag
+ cas.Var = caseVar
+ caseVar.Defn = switchExpr
}
cas.Body.Set(r.stmtList())
cases[i] = cas
@@ -789,6 +794,14 @@ func (r *importReader) caseList(sw ir.Node) []ir.Node {
return cases
}
+func (r *importReader) commList() []*ir.CommClause {
+ cases := make([]*ir.CommClause, r.uint64())
+ for i := range cases {
+ cases[i] = ir.NewCommStmt(r.pos(), r.node(), r.stmtList())
+ }
+ return cases
+}
+
func (r *importReader) exprList() []ir.Node {
var list []ir.Node
for {
@@ -821,7 +834,7 @@ func (r *importReader) node() ir.Node {
pos := r.pos()
typ := r.typ()
- n := npos(pos, NodNil())
+ n := ir.NewNilExpr(pos)
n.SetType(typ)
return n
@@ -829,7 +842,7 @@ func (r *importReader) node() ir.Node {
pos := r.pos()
typ := r.typ()
- n := npos(pos, ir.NewLiteral(r.value(typ)))
+ n := ir.NewBasicLit(pos, r.value(typ))
n.SetType(typ)
return n
@@ -851,8 +864,7 @@ func (r *importReader) node() ir.Node {
if s := r.ident(); s != nil {
tag = ir.NewIdent(pos, s)
}
- expr, _ := r.exprsOrNil()
- return ir.NewTypeSwitchGuard(pos, tag, expr)
+ return ir.NewTypeSwitchGuard(pos, tag, r.expr())
// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
// unreachable - should have been resolved by typechecking
@@ -864,26 +876,16 @@ func (r *importReader) node() ir.Node {
// unreachable - mapped to case OADDR below by exporter
case ir.OSTRUCTLIT:
- // TODO(mdempsky): Export position information for OSTRUCTKEY nodes.
- savedlineno := base.Pos
- base.Pos = r.pos()
- n := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(r.typ()).(ir.Ntype), nil)
- n.List.Set(r.elemList()) // special handling of field names
- base.Pos = savedlineno
- return n
+ return ir.NewCompLitExpr(r.pos(), ir.OCOMPLIT, ir.TypeNode(r.typ()), r.fieldList())
// case OARRAYLIT, OSLICELIT, OMAPLIT:
// unreachable - mapped to case OCOMPLIT below by exporter
case ir.OCOMPLIT:
- n := ir.NewCompLitExpr(r.pos(), ir.OCOMPLIT, ir.TypeNode(r.typ()).(ir.Ntype), nil)
- n.List.Set(r.exprList())
- return n
+ return ir.NewCompLitExpr(r.pos(), ir.OCOMPLIT, ir.TypeNode(r.typ()), r.exprList())
case ir.OKEY:
- pos := r.pos()
- left, right := r.exprsOrNil()
- return ir.NewKeyExpr(pos, left, right)
+ return ir.NewKeyExpr(r.pos(), r.expr(), r.expr())
// case OSTRUCTKEY:
// unreachable - handled in case OSTRUCTLIT by elemList
@@ -913,22 +915,19 @@ func (r *importReader) node() ir.Node {
return ir.NewIndexExpr(r.pos(), r.expr(), r.expr())
case ir.OSLICE, ir.OSLICE3:
- n := ir.NewSliceExpr(r.pos(), op, r.expr())
+ pos, x := r.pos(), r.expr()
low, high := r.exprsOrNil()
var max ir.Node
- if n.Op().IsSlice3() {
+ if op.IsSlice3() {
max = r.expr()
}
- n.SetSliceBounds(low, high, max)
- return n
+ return ir.NewSliceExpr(pos, op, x, low, high, max)
// case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR:
// unreachable - mapped to OCONV case below by exporter
case ir.OCONV:
- n := ir.NewConvExpr(r.pos(), ir.OCONV, nil, r.expr())
- n.SetType(r.typ())
- return n
+ return ir.NewConvExpr(r.pos(), ir.OCONV, r.typ(), r.expr())
case ir.OCOPY, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCAP, ir.OCLOSE, ir.ODELETE, ir.OLEN, ir.OMAKE, ir.ONEW, ir.OPANIC, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
n := builtinCall(r.pos(), op)
@@ -942,10 +941,10 @@ func (r *importReader) node() ir.Node {
// unreachable - mapped to OCALL case below by exporter
case ir.OCALL:
- n := ir.NewCallExpr(r.pos(), ir.OCALL, nil, nil)
- n.PtrInit().Set(r.stmtList())
- n.X = r.expr()
- n.Args.Set(r.exprList())
+ pos := r.pos()
+ init := r.stmtList()
+ n := ir.NewCallExpr(pos, ir.OCALL, r.expr(), r.exprList())
+ n.PtrInit().Set(init)
n.IsDDD = r.bool()
return n
@@ -979,7 +978,7 @@ func (r *importReader) node() ir.Node {
case ir.OADDSTR:
pos := r.pos()
list := r.exprList()
- x := npos(pos, list[0])
+ x := list[0]
for _, y := range list[1:] {
x = ir.NewBinaryExpr(pos, ir.OADD, x, y)
}
@@ -1006,9 +1005,7 @@ func (r *importReader) node() ir.Node {
return ir.NewAssignStmt(r.pos(), r.expr(), r.expr())
case ir.OASOP:
- n := ir.NewAssignOpStmt(r.pos(), ir.OXXX, nil, nil)
- n.AsOp = r.op()
- n.X = r.expr()
+ n := ir.NewAssignOpStmt(r.pos(), r.op(), r.expr(), nil)
if !r.bool() {
n.Y = ir.NewInt(1)
n.IncDec = true
@@ -1021,15 +1018,10 @@ func (r *importReader) node() ir.Node {
// unreachable - mapped to OAS2 case below by exporter
case ir.OAS2:
- n := ir.NewAssignListStmt(r.pos(), ir.OAS2, nil, nil)
- n.Lhs.Set(r.exprList())
- n.Rhs.Set(r.exprList())
- return n
+ return ir.NewAssignListStmt(r.pos(), ir.OAS2, r.exprList(), r.exprList())
case ir.ORETURN:
- n := ir.NewReturnStmt(r.pos(), nil)
- n.Results.Set(r.exprList())
- return n
+ return ir.NewReturnStmt(r.pos(), r.exprList())
// case ORETJMP:
// unreachable - generated by compiler for trampolin routines (not exported)
@@ -1038,57 +1030,50 @@ func (r *importReader) node() ir.Node {
return ir.NewGoDeferStmt(r.pos(), op, r.expr())
case ir.OIF:
- n := ir.NewIfStmt(r.pos(), nil, nil, nil)
- n.PtrInit().Set(r.stmtList())
- n.Cond = r.expr()
- n.Body.Set(r.stmtList())
- n.Else.Set(r.stmtList())
+ pos, init := r.pos(), r.stmtList()
+ n := ir.NewIfStmt(pos, r.expr(), r.stmtList(), r.stmtList())
+ n.PtrInit().Set(init)
return n
case ir.OFOR:
- n := ir.NewForStmt(r.pos(), nil, nil, nil, nil)
- n.PtrInit().Set(r.stmtList())
- left, right := r.exprsOrNil()
- n.Cond = left
- n.Post = right
- n.Body.Set(r.stmtList())
+ pos, init := r.pos(), r.stmtList()
+ cond, post := r.exprsOrNil()
+ n := ir.NewForStmt(pos, nil, cond, post, r.stmtList())
+ n.PtrInit().Set(init)
return n
case ir.ORANGE:
- n := ir.NewRangeStmt(r.pos(), nil, nil, nil)
- n.Vars.Set(r.stmtList())
- n.X = r.expr()
- n.Body.Set(r.stmtList())
- return n
+ pos := r.pos()
+ k, v := r.exprsOrNil()
+ return ir.NewRangeStmt(pos, k, v, r.expr(), r.stmtList())
case ir.OSELECT:
- n := ir.NewSelectStmt(r.pos(), nil)
- n.PtrInit().Set(r.stmtList())
- r.exprsOrNil() // TODO(rsc): Delete (and fix exporter). These are always nil.
- n.Cases.Set(r.caseList(n))
+ pos := r.pos()
+ init := r.stmtList()
+ n := ir.NewSelectStmt(pos, r.commList())
+ n.PtrInit().Set(init)
return n
case ir.OSWITCH:
- n := ir.NewSwitchStmt(r.pos(), nil, nil)
- n.PtrInit().Set(r.stmtList())
- left, _ := r.exprsOrNil()
- n.Tag = left
- n.Cases.Set(r.caseList(n))
+ pos := r.pos()
+ init := r.stmtList()
+ x, _ := r.exprsOrNil()
+ n := ir.NewSwitchStmt(pos, x, r.caseList(x))
+ n.PtrInit().Set(init)
return n
// case OCASE:
// handled by caseList
case ir.OFALL:
- n := ir.NewBranchStmt(r.pos(), ir.OFALL, nil)
- return n
+ return ir.NewBranchStmt(r.pos(), ir.OFALL, nil)
// case OEMPTY:
// unreachable - not emitted by exporter
case ir.OBREAK, ir.OCONTINUE, ir.OGOTO:
- var sym *types.Sym
pos := r.pos()
+ var sym *types.Sym
if label := r.string(); label != "" {
sym = Lookup(label)
}
@@ -1111,12 +1096,10 @@ func (r *importReader) op() ir.Op {
return ir.Op(r.uint64())
}
-func (r *importReader) elemList() []ir.Node {
- c := r.uint64()
- list := make([]ir.Node, c)
+func (r *importReader) fieldList() []ir.Node {
+ list := make([]ir.Node, r.uint64())
for i := range list {
- s := r.ident()
- list[i] = ir.NewStructKeyExpr(base.Pos, s, r.expr())
+ list[i] = ir.NewStructKeyExpr(r.pos(), r.ident(), r.expr())
}
return list
}
@@ -1135,8 +1118,3 @@ func (r *importReader) exprsOrNil() (a, b ir.Node) {
func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr {
return ir.NewCallExpr(pos, ir.OCALL, ir.NewIdent(base.Pos, types.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
}
-
-func npos(pos src.XPos, n ir.Node) ir.Node {
- n.SetPos(pos)
- return n
-}
diff --git a/src/cmd/compile/internal/typecheck/mkbuiltin.go b/src/cmd/compile/internal/typecheck/mkbuiltin.go
index 2a208d960f..07f4b767e8 100644
--- a/src/cmd/compile/internal/typecheck/mkbuiltin.go
+++ b/src/cmd/compile/internal/typecheck/mkbuiltin.go
@@ -36,8 +36,8 @@ func main() {
fmt.Fprintln(&b, "package typecheck")
fmt.Fprintln(&b)
fmt.Fprintln(&b, `import (`)
- fmt.Fprintln(&b, ` "cmd/compile/internal/ir"`)
fmt.Fprintln(&b, ` "cmd/compile/internal/types"`)
+ fmt.Fprintln(&b, ` "cmd/internal/src"`)
fmt.Fprintln(&b, `)`)
mkbuiltin(&b, "runtime")
@@ -169,7 +169,7 @@ func (i *typeInterner) mktype(t ast.Expr) string {
}
return fmt.Sprintf("types.NewChan(%s, %s)", i.subtype(t.Value), dir)
case *ast.FuncType:
- return fmt.Sprintf("functype(nil, %s, %s)", i.fields(t.Params, false), i.fields(t.Results, false))
+ return fmt.Sprintf("types.NewSignature(types.NoPkg, nil, %s, %s)", i.fields(t.Params, false), i.fields(t.Results, false))
case *ast.InterfaceType:
if len(t.Methods.List) != 0 {
log.Fatal("non-empty interfaces unsupported")
@@ -180,7 +180,7 @@ func (i *typeInterner) mktype(t ast.Expr) string {
case *ast.StarExpr:
return fmt.Sprintf("types.NewPtr(%s)", i.subtype(t.X))
case *ast.StructType:
- return fmt.Sprintf("tostruct(%s)", i.fields(t.Fields, true))
+ return fmt.Sprintf("types.NewStruct(types.NoPkg, %s)", i.fields(t.Fields, true))
default:
log.Fatalf("unhandled type: %#v", t)
@@ -196,18 +196,18 @@ func (i *typeInterner) fields(fl *ast.FieldList, keepNames bool) string {
for _, f := range fl.List {
typ := i.subtype(f.Type)
if len(f.Names) == 0 {
- res = append(res, fmt.Sprintf("anonfield(%s)", typ))
+ res = append(res, fmt.Sprintf("types.NewField(src.NoXPos, nil, %s)", typ))
} else {
for _, name := range f.Names {
if keepNames {
- res = append(res, fmt.Sprintf("namedfield(%q, %s)", name.Name, typ))
+ res = append(res, fmt.Sprintf("types.NewField(src.NoXPos, Lookup(%q), %s)", name.Name, typ))
} else {
- res = append(res, fmt.Sprintf("anonfield(%s)", typ))
+ res = append(res, fmt.Sprintf("types.NewField(src.NoXPos, nil, %s)", typ))
}
}
}
}
- return fmt.Sprintf("[]*ir.Field{%s}", strings.Join(res, ", "))
+ return fmt.Sprintf("[]*types.Field{%s}", strings.Join(res, ", "))
}
func intconst(e ast.Expr) int64 {
diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go
index bf3801eea2..f5d36a663d 100644
--- a/src/cmd/compile/internal/typecheck/stmt.go
+++ b/src/cmd/compile/internal/typecheck/stmt.go
@@ -11,27 +11,29 @@ import (
"cmd/internal/src"
)
+func RangeExprType(t *types.Type) *types.Type {
+ if t.IsPtr() && t.Elem().IsArray() {
+ return t.Elem()
+ }
+ return t
+}
+
func typecheckrangeExpr(n *ir.RangeStmt) {
n.X = Expr(n.X)
-
- t := n.X.Type()
- if t == nil {
+ if n.X.Type() == nil {
return
}
+
+ t := RangeExprType(n.X.Type())
// delicate little dance. see typecheckas2
- ls := n.Vars
- for i1, n1 := range ls {
- if !ir.DeclaredBy(n1, n) {
- ls[i1] = AssignExpr(ls[i1])
- }
+ if n.Key != nil && !ir.DeclaredBy(n.Key, n) {
+ n.Key = AssignExpr(n.Key)
}
-
- if t.IsPtr() && t.Elem().IsArray() {
- t = t.Elem()
+ if n.Value != nil && !ir.DeclaredBy(n.Value, n) {
+ n.Value = AssignExpr(n.Value)
}
- n.SetType(t)
- var t1, t2 *types.Type
+ var tk, tv *types.Type
toomany := false
switch t.Kind() {
default:
@@ -39,12 +41,12 @@ func typecheckrangeExpr(n *ir.RangeStmt) {
return
case types.TARRAY, types.TSLICE:
- t1 = types.Types[types.TINT]
- t2 = t.Elem()
+ tk = types.Types[types.TINT]
+ tv = t.Elem()
case types.TMAP:
- t1 = t.Key()
- t2 = t.Elem()
+ tk = t.Key()
+ tv = t.Elem()
case types.TCHAN:
if !t.ChanDir().CanRecv() {
@@ -52,61 +54,35 @@ func typecheckrangeExpr(n *ir.RangeStmt) {
return
}
- t1 = t.Elem()
- t2 = nil
- if len(n.Vars) == 2 {
+ tk = t.Elem()
+ tv = nil
+ if n.Value != nil {
toomany = true
}
case types.TSTRING:
- t1 = types.Types[types.TINT]
- t2 = types.RuneType
+ tk = types.Types[types.TINT]
+ tv = types.RuneType
}
- if len(n.Vars) > 2 || toomany {
+ if toomany {
base.ErrorfAt(n.Pos(), "too many variables in range")
}
- var v1, v2 ir.Node
- if len(n.Vars) != 0 {
- v1 = n.Vars[0]
- }
- if len(n.Vars) > 1 {
- v2 = n.Vars[1]
- }
-
- // this is not only an optimization but also a requirement in the spec.
- // "if the second iteration variable is the blank identifier, the range
- // clause is equivalent to the same clause with only the first variable
- // present."
- if ir.IsBlank(v2) {
- if v1 != nil {
- n.Vars = []ir.Node{v1}
- }
- v2 = nil
- }
-
- if v1 != nil {
- if ir.DeclaredBy(v1, n) {
- v1.SetType(t1)
- } else if v1.Type() != nil {
- if op, why := assignop(t1, v1.Type()); op == ir.OXXX {
- base.ErrorfAt(n.Pos(), "cannot assign type %v to %L in range%s", t1, v1, why)
- }
- }
- checkassign(n, v1)
- }
-
- if v2 != nil {
- if ir.DeclaredBy(v2, n) {
- v2.SetType(t2)
- } else if v2.Type() != nil {
- if op, why := assignop(t2, v2.Type()); op == ir.OXXX {
- base.ErrorfAt(n.Pos(), "cannot assign type %v to %L in range%s", t2, v2, why)
+ do := func(nn ir.Node, t *types.Type) {
+ if nn != nil {
+ if ir.DeclaredBy(nn, n) {
+ nn.SetType(t)
+ } else if nn.Type() != nil {
+ if op, why := assignop(t, nn.Type()); op == ir.OXXX {
+ base.ErrorfAt(n.Pos(), "cannot assign type %v to %L in range%s", t, nn, why)
+ }
}
+ checkassign(n, nn)
}
- checkassign(n, v2)
}
+ do(n.Key, tk)
+ do(n.Value, tv)
}
// type check assignment.
@@ -117,47 +93,16 @@ func tcAssign(n *ir.AssignStmt) {
defer tracePrint("typecheckas", n)(nil)
}
- // delicate little dance.
- // the definition of n may refer to this assignment
- // as its definition, in which case it will call typecheckas.
- // in that case, do not call typecheck back, or it will cycle.
- // if the variable has a type (ntype) then typechecking
- // will not look at defn, so it is okay (and desirable,
- // so that the conversion below happens).
- n.X = Resolve(n.X)
-
- if !ir.DeclaredBy(n.X, n) || n.X.Name().Ntype != nil {
+ if n.Y == nil {
n.X = AssignExpr(n.X)
+ return
}
- // Use ctxMultiOK so we can emit an "N variables but M values" error
- // to be consistent with typecheckas2 (#26616).
- n.Y = typecheck(n.Y, ctxExpr|ctxMultiOK)
- checkassign(n, n.X)
- if n.Y != nil && n.Y.Type() != nil {
- if n.Y.Type().IsFuncArgStruct() {
- base.Errorf("assignment mismatch: 1 variable but %v returns %d values", n.Y.(*ir.CallExpr).X, n.Y.Type().NumFields())
- // Multi-value RHS isn't actually valid for OAS; nil out
- // to indicate failed typechecking.
- n.Y.SetType(nil)
- } else if n.X.Type() != nil {
- n.Y = AssignConv(n.Y, n.X.Type(), "assignment")
- }
- }
-
- if ir.DeclaredBy(n.X, n) && n.X.Name().Ntype == nil {
- n.Y = DefaultLit(n.Y, nil)
- n.X.SetType(n.Y.Type())
- }
-
- // second half of dance.
- // now that right is done, typecheck the left
- // just to get it over with. see dance above.
- n.SetTypecheck(1)
+ lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y}
+ assign(n, lhs, rhs)
+ n.X, n.Y = lhs[0], rhs[0]
- if n.X.Typecheck() == 0 {
- n.X = AssignExpr(n.X)
- }
+ // TODO(mdempsky): This seems out of place.
if !ir.IsBlank(n.X) {
types.CheckSize(n.X.Type()) // ensure width is calculated for backend
}
@@ -168,132 +113,118 @@ func tcAssignList(n *ir.AssignListStmt) {
defer tracePrint("typecheckas2", n)(nil)
}
- ls := n.Lhs
- for i1, n1 := range ls {
- // delicate little dance.
- n1 = Resolve(n1)
- ls[i1] = n1
+ assign(n, n.Lhs, n.Rhs)
+}
+
+func assign(stmt ir.Node, lhs, rhs []ir.Node) {
+ // delicate little dance.
+ // the definition of lhs may refer to this assignment
+ // as its definition, in which case it will call typecheckas.
+ // in that case, do not call typecheck back, or it will cycle.
+ // if the variable has a type (ntype) then typechecking
+ // will not look at defn, so it is okay (and desirable,
+ // so that the conversion below happens).
- if !ir.DeclaredBy(n1, n) || n1.Name().Ntype != nil {
- ls[i1] = AssignExpr(ls[i1])
+ checkLHS := func(i int, typ *types.Type) {
+ lhs[i] = Resolve(lhs[i])
+ if n := lhs[i]; typ != nil && ir.DeclaredBy(n, stmt) && n.Name().Ntype == nil {
+ if typ.Kind() != types.TNIL {
+ n.SetType(defaultType(typ))
+ } else {
+ base.Errorf("use of untyped nil")
+ }
}
+ if lhs[i].Typecheck() == 0 {
+ lhs[i] = AssignExpr(lhs[i])
+ }
+ checkassign(stmt, lhs[i])
}
- cl := len(n.Lhs)
- cr := len(n.Rhs)
- if cl > 1 && cr == 1 {
- n.Rhs[0] = typecheck(n.Rhs[0], ctxExpr|ctxMultiOK)
- } else {
- Exprs(n.Rhs)
- }
- checkassignlist(n, n.Lhs)
-
- var l ir.Node
- var r ir.Node
- if cl == cr {
- // easy
- ls := n.Lhs
- rs := n.Rhs
- for il, nl := range ls {
- nr := rs[il]
- if nl.Type() != nil && nr.Type() != nil {
- rs[il] = AssignConv(nr, nl.Type(), "assignment")
- }
- if ir.DeclaredBy(nl, n) && nl.Name().Ntype == nil {
- rs[il] = DefaultLit(rs[il], nil)
- nl.SetType(rs[il].Type())
- }
+ assignType := func(i int, typ *types.Type) {
+ checkLHS(i, typ)
+ if typ != nil {
+ checkassignto(typ, lhs[i])
}
+ }
- goto out
+ cr := len(rhs)
+ if len(rhs) == 1 {
+ rhs[0] = typecheck(rhs[0], ctxExpr|ctxMultiOK)
+ if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() {
+ cr = rtyp.NumFields()
+ }
+ } else {
+ Exprs(rhs)
}
- l = n.Lhs[0]
- r = n.Rhs[0]
+ // x, ok = y
+assignOK:
+ for len(lhs) == 2 && cr == 1 {
+ stmt := stmt.(*ir.AssignListStmt)
+ r := rhs[0]
- // x,y,z = f()
- if cr == 1 {
- if r.Type() == nil {
- goto out
- }
switch r.Op() {
- case ir.OCALLMETH, ir.OCALLINTER, ir.OCALLFUNC:
- if !r.Type().IsFuncArgStruct() {
- break
- }
- cr = r.Type().NumFields()
- if cr != cl {
- goto mismatch
- }
- r.(*ir.CallExpr).Use = ir.CallUseList
- n.SetOp(ir.OAS2FUNC)
- for i, l := range n.Lhs {
- f := r.Type().Field(i)
- if f.Type != nil && l.Type() != nil {
- checkassignto(f.Type, l)
- }
- if ir.DeclaredBy(l, n) && l.Name().Ntype == nil {
- l.SetType(f.Type)
- }
- }
- goto out
+ case ir.OINDEXMAP:
+ stmt.SetOp(ir.OAS2MAPR)
+ case ir.ORECV:
+ stmt.SetOp(ir.OAS2RECV)
+ case ir.ODOTTYPE:
+ r := r.(*ir.TypeAssertExpr)
+ stmt.SetOp(ir.OAS2DOTTYPE)
+ r.SetOp(ir.ODOTTYPE2)
+ default:
+ break assignOK
}
+
+ assignType(0, r.Type())
+ assignType(1, types.UntypedBool)
+ return
}
- // x, ok = y
- if cl == 2 && cr == 1 {
- if r.Type() == nil {
- goto out
- }
- switch r.Op() {
- case ir.OINDEXMAP, ir.ORECV, ir.ODOTTYPE:
- switch r.Op() {
- case ir.OINDEXMAP:
- n.SetOp(ir.OAS2MAPR)
- case ir.ORECV:
- n.SetOp(ir.OAS2RECV)
- case ir.ODOTTYPE:
- r := r.(*ir.TypeAssertExpr)
- n.SetOp(ir.OAS2DOTTYPE)
- r.SetOp(ir.ODOTTYPE2)
- }
- if l.Type() != nil {
- checkassignto(r.Type(), l)
- }
- if ir.DeclaredBy(l, n) {
- l.SetType(r.Type())
- }
- l := n.Lhs[1]
- if l.Type() != nil && !l.Type().IsBoolean() {
- checkassignto(types.Types[types.TBOOL], l)
+ if len(lhs) != cr {
+ if r, ok := rhs[0].(*ir.CallExpr); ok && len(rhs) == 1 {
+ if r.Type() != nil {
+ base.ErrorfAt(stmt.Pos(), "assignment mismatch: %d variable%s but %v returns %d value%s", len(lhs), plural(len(lhs)), r.X, cr, plural(cr))
}
- if ir.DeclaredBy(l, n) && l.Name().Ntype == nil {
- l.SetType(types.Types[types.TBOOL])
- }
- goto out
+ } else {
+ base.ErrorfAt(stmt.Pos(), "assignment mismatch: %d variable%s but %v value%s", len(lhs), plural(len(lhs)), len(rhs), plural(len(rhs)))
}
+
+ for i := range lhs {
+ checkLHS(i, nil)
+ }
+ return
}
-mismatch:
- switch r.Op() {
- default:
- base.Errorf("assignment mismatch: %d variables but %d values", cl, cr)
- case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER:
- r := r.(*ir.CallExpr)
- base.Errorf("assignment mismatch: %d variables but %v returns %d values", cl, r.X, cr)
+ // x,y,z = f()
+ if cr > len(rhs) {
+ stmt := stmt.(*ir.AssignListStmt)
+ stmt.SetOp(ir.OAS2FUNC)
+ r := rhs[0].(*ir.CallExpr)
+ r.Use = ir.CallUseList
+ rtyp := r.Type()
+
+ for i := range lhs {
+ assignType(i, rtyp.Field(i).Type)
+ }
+ return
}
- // second half of dance
-out:
- n.SetTypecheck(1)
- ls = n.Lhs
- for i1, n1 := range ls {
- if n1.Typecheck() == 0 {
- ls[i1] = AssignExpr(ls[i1])
+ for i, r := range rhs {
+ checkLHS(i, r.Type())
+ if lhs[i].Type() != nil {
+ rhs[i] = AssignConv(r, lhs[i].Type(), "assignment")
}
}
}
+func plural(n int) string {
+ if n == 1 {
+ return ""
+ }
+ return "s"
+}
+
// tcFor typechecks an OFOR node.
func tcFor(n *ir.ForStmt) ir.Node {
Stmts(n.Init())
@@ -399,11 +330,11 @@ func tcRange(n *ir.RangeStmt) {
// second half of dance, the first half being typecheckrangeExpr
n.SetTypecheck(1)
- ls := n.Vars
- for i1, n1 := range ls {
- if n1.Typecheck() == 0 {
- ls[i1] = AssignExpr(ls[i1])
- }
+ if n.Key != nil && n.Key.Typecheck() == 0 {
+ n.Key = AssignExpr(n.Key)
+ }
+ if n.Value != nil && n.Value.Typecheck() == 0 {
+ n.Value = AssignExpr(n.Value)
}
decldepth++
@@ -429,31 +360,23 @@ func tcReturn(n *ir.ReturnStmt) ir.Node {
// select
func tcSelect(sel *ir.SelectStmt) {
- var def ir.Node
+ var def *ir.CommClause
lno := ir.SetPos(sel)
Stmts(sel.Init())
for _, ncase := range sel.Cases {
- ncase := ncase.(*ir.CaseStmt)
-
- if len(ncase.List) == 0 {
+ if ncase.Comm == nil {
// default
if def != nil {
base.ErrorfAt(ncase.Pos(), "multiple defaults in select (first at %v)", ir.Line(def))
} else {
def = ncase
}
- } else if len(ncase.List) > 1 {
- base.ErrorfAt(ncase.Pos(), "select cases cannot be lists")
} else {
- ncase.List[0] = Stmt(ncase.List[0])
- n := ncase.List[0]
+ n := Stmt(ncase.Comm)
ncase.Comm = n
- ncase.List.Set(nil)
- oselrecv2 := func(dst, recv ir.Node, colas bool) {
- n := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, nil, nil)
- n.Lhs = []ir.Node{dst, ir.BlankNode}
- n.Rhs = []ir.Node{recv}
- n.Def = colas
+ oselrecv2 := func(dst, recv ir.Node, def bool) {
+ n := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv})
+ n.Def = def
n.SetTypecheck(1)
ncase.Comm = n
}
@@ -577,7 +500,6 @@ func tcSwitchExpr(n *ir.SwitchStmt) {
var defCase ir.Node
var cs constSet
for _, ncase := range n.Cases {
- ncase := ncase.(*ir.CaseStmt)
ls := ncase.List
if len(ls) == 0 { // default:
if defCase != nil {
@@ -646,7 +568,6 @@ func tcSwitchType(n *ir.SwitchStmt) {
var defCase, nilCase ir.Node
var ts typeSet
for _, ncase := range n.Cases {
- ncase := ncase.(*ir.CaseStmt)
ls := ncase.List
if len(ls) == 0 { // default:
if defCase != nil {
@@ -694,7 +615,7 @@ func tcSwitchType(n *ir.SwitchStmt) {
ts.add(ncase.Pos(), n1.Type())
}
- if len(ncase.Vars) != 0 {
+ if ncase.Var != nil {
// Assign the clause variable's type.
vt := t
if len(ls) == 1 {
@@ -707,7 +628,7 @@ func tcSwitchType(n *ir.SwitchStmt) {
}
}
- nvar := ncase.Vars[0]
+ nvar := ncase.Var
nvar.SetType(vt)
if vt != nil {
nvar = AssignExpr(nvar)
@@ -716,7 +637,7 @@ func tcSwitchType(n *ir.SwitchStmt) {
nvar.SetTypecheck(1)
nvar.SetWalkdef(1)
}
- ncase.Vars[0] = nvar
+ ncase.Var = nvar
}
Stmts(ncase.Body)
diff --git a/src/cmd/compile/internal/typecheck/type.go b/src/cmd/compile/internal/typecheck/type.go
index 4782bb9c31..0c2ebb8b26 100644
--- a/src/cmd/compile/internal/typecheck/type.go
+++ b/src/cmd/compile/internal/typecheck/type.go
@@ -73,13 +73,42 @@ func tcChanType(n *ir.ChanType) ir.Node {
// tcFuncType typechecks an OTFUNC node.
func tcFuncType(n *ir.FuncType) ir.Node {
- n.SetOTYPE(NewFuncType(n.Recv, n.Params, n.Results))
+ misc := func(f *types.Field, nf *ir.Field) {
+ f.SetIsDDD(nf.IsDDD)
+ if nf.Decl != nil {
+ nf.Decl.SetType(f.Type)
+ f.Nname = nf.Decl
+ }
+ }
+
+ lno := base.Pos
+
+ var recv *types.Field
+ if n.Recv != nil {
+ recv = tcField(n.Recv, misc)
+ }
+
+ t := types.NewSignature(types.LocalPkg, recv, tcFields(n.Params, misc), tcFields(n.Results, misc))
+ checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
+
+ base.Pos = lno
+
+ n.SetOTYPE(t)
return n
}
// tcInterfaceType typechecks an OTINTER node.
func tcInterfaceType(n *ir.InterfaceType) ir.Node {
- n.SetOTYPE(tointerface(n.Methods))
+ if len(n.Methods) == 0 {
+ n.SetOTYPE(types.Types[types.TINTER])
+ return n
+ }
+
+ lno := base.Pos
+ methods := tcFields(n.Methods, nil)
+ base.Pos = lno
+
+ n.SetOTYPE(types.NewInterface(types.LocalPkg, methods))
return n
}
@@ -117,6 +146,43 @@ func tcSliceType(n *ir.SliceType) ir.Node {
// tcStructType typechecks an OTSTRUCT node.
func tcStructType(n *ir.StructType) ir.Node {
- n.SetOTYPE(NewStructType(n.Fields))
+ lno := base.Pos
+
+ fields := tcFields(n.Fields, func(f *types.Field, nf *ir.Field) {
+ if nf.Embedded {
+ checkembeddedtype(f.Type)
+ f.Embedded = 1
+ }
+ f.Note = nf.Note
+ })
+ checkdupfields("field", fields)
+
+ base.Pos = lno
+ n.SetOTYPE(types.NewStruct(types.LocalPkg, fields))
return n
}
+
+// tcField typechecks a generic Field.
+// misc can be provided to handle specialized typechecking.
+func tcField(n *ir.Field, misc func(*types.Field, *ir.Field)) *types.Field {
+ base.Pos = n.Pos
+ if n.Ntype != nil {
+ n.Type = typecheckNtype(n.Ntype).Type()
+ n.Ntype = nil
+ }
+ f := types.NewField(n.Pos, n.Sym, n.Type)
+ if misc != nil {
+ misc(f, n)
+ }
+ return f
+}
+
+// tcFields typechecks a slice of generic Fields.
+// misc can be provided to handle specialized typechecking.
+func tcFields(l []*ir.Field, misc func(*types.Field, *ir.Field)) []*types.Field {
+ fields := make([]*types.Field, len(l))
+ for i, n := range l {
+ fields[i] = tcField(n, misc)
+ }
+ return fields
+}
diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go
index bf43402d3d..e23c249ff2 100644
--- a/src/cmd/compile/internal/typecheck/typecheck.go
+++ b/src/cmd/compile/internal/typecheck/typecheck.go
@@ -251,13 +251,7 @@ func Resolve(n ir.Node) (res ir.Node) {
}
}
- if inimport {
- base.Fatalf("recursive inimport")
- }
- inimport = true
- n = expandDecl(n)
- inimport = false
- return n
+ return expandDecl(n)
}
r := ir.AsNode(n.Sym().Def)
@@ -1232,7 +1226,7 @@ func lookdot(n *ir.SelectorExpr, t *types.Type, dostrcmp int) *types.Field {
if f1.Offset == types.BADWIDTH {
base.Fatalf("lookdot badwidth %v %p", f1, f1)
}
- n.Offset = f1.Offset
+ n.Selection = f1
n.SetType(f1.Type)
if t.IsInterface() {
if n.X.Type().IsPtr() {
@@ -1243,7 +1237,6 @@ func lookdot(n *ir.SelectorExpr, t *types.Type, dostrcmp int) *types.Field {
n.SetOp(ir.ODOTINTER)
}
- n.Selection = f1
return f1
}
@@ -1298,11 +1291,9 @@ func lookdot(n *ir.SelectorExpr, t *types.Type, dostrcmp int) *types.Field {
return nil
}
- n.Sel = ir.MethodSym(n.X.Type(), f2.Sym)
- n.Offset = f2.Offset
+ n.Selection = f2
n.SetType(f2.Type)
n.SetOp(ir.ODOTMETH)
- n.Selection = f2
return f2
}
@@ -1638,7 +1629,7 @@ func nonexported(sym *types.Sym) bool {
}
func checklvalue(n ir.Node, verb string) {
- if !ir.IsAssignable(n) {
+ if !ir.IsAddressable(n) {
base.Errorf("cannot %s %v", verb, n)
}
}
@@ -1656,7 +1647,7 @@ func checkassign(stmt ir.Node, n ir.Node) {
}
}
- if ir.IsAssignable(n) {
+ if ir.IsAddressable(n) {
return
}
if n.Op() == ir.OINDEXMAP {
@@ -1690,6 +1681,11 @@ func checkassignlist(stmt ir.Node, l ir.Nodes) {
}
func checkassignto(src *types.Type, dst ir.Node) {
+ // TODO(mdempsky): Handle all untyped types correctly.
+ if src == types.UntypedBool && dst.Type().IsBoolean() {
+ return
+ }
+
if op, why := assignop(src, dst.Type()); op == ir.OXXX {
base.Errorf("cannot assign %v to %L in multiple assignment%s", src, dst, why)
return
@@ -2101,7 +2097,6 @@ func isTermNode(n ir.Node) bool {
}
def := false
for _, cas := range n.Cases {
- cas := cas.(*ir.CaseStmt)
if !isTermNodes(cas.Body) {
return false
}
@@ -2117,7 +2112,6 @@ func isTermNode(n ir.Node) bool {
return false
}
for _, cas := range n.Cases {
- cas := cas.(*ir.CaseStmt)
if !isTermNodes(cas.Body) {
return false
}
@@ -2216,9 +2210,6 @@ func deadcodeslice(nn *ir.Nodes) {
case ir.OBLOCK:
n := n.(*ir.BlockStmt)
deadcodeslice(&n.List)
- case ir.OCASE:
- n := n.(*ir.CaseStmt)
- deadcodeslice(&n.Body)
case ir.OFOR:
n := n.(*ir.ForStmt)
deadcodeslice(&n.Body)
@@ -2231,10 +2222,14 @@ func deadcodeslice(nn *ir.Nodes) {
deadcodeslice(&n.Body)
case ir.OSELECT:
n := n.(*ir.SelectStmt)
- deadcodeslice(&n.Cases)
+ for _, cas := range n.Cases {
+ deadcodeslice(&cas.Body)
+ }
case ir.OSWITCH:
n := n.(*ir.SwitchStmt)
- deadcodeslice(&n.Cases)
+ for _, cas := range n.Cases {
+ deadcodeslice(&cas.Body)
+ }
}
if cut {
diff --git a/src/cmd/compile/internal/types/alg.go b/src/cmd/compile/internal/types/alg.go
index 14200e0d16..f1a472cca5 100644
--- a/src/cmd/compile/internal/types/alg.go
+++ b/src/cmd/compile/internal/types/alg.go
@@ -10,7 +10,7 @@ import "cmd/compile/internal/base"
// hashing a Type.
type AlgKind int
-//go:generate stringer -type AlgKind -trimprefix A
+//go:generate stringer -type AlgKind -trimprefix A alg.go
const (
// These values are known by runtime.
diff --git a/src/cmd/compile/internal/types/algkind_string.go b/src/cmd/compile/internal/types/algkind_string.go
index 8c5a0bc287..a1b518e4dd 100644
--- a/src/cmd/compile/internal/types/algkind_string.go
+++ b/src/cmd/compile/internal/types/algkind_string.go
@@ -1,4 +1,4 @@
-// Code generated by "stringer -type AlgKind -trimprefix A"; DO NOT EDIT.
+// Code generated by "stringer -type AlgKind -trimprefix A alg.go"; DO NOT EDIT.
package types
diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go
index bf37f01922..cd0679f6b9 100644
--- a/src/cmd/compile/internal/types/fmt.go
+++ b/src/cmd/compile/internal/types/fmt.go
@@ -180,15 +180,6 @@ func symfmt(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
b.WriteString(s.Name)
}
-func SymMethodName(s *Sym) string {
- // Skip leading "type." in method name
- name := s.Name
- if i := strings.LastIndex(name, "."); i >= 0 {
- name = name[i+1:]
- }
- return name
-}
-
// Type
var BasicTypeNames = []string{
@@ -595,7 +586,10 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
if funarg != FunargNone {
name = fmt.Sprint(f.Nname)
} else if verb == 'L' {
- name = SymMethodName(s)
+ name = s.Name
+ if name == ".F" {
+ name = "F" // Hack for toolstash -cmp.
+ }
if !IsExported(name) && mode != fmtTypeIDName {
name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg)
}
diff --git a/src/cmd/compile/internal/types/goversion.go b/src/cmd/compile/internal/types/goversion.go
index 2265f472cf..1a324aa42f 100644
--- a/src/cmd/compile/internal/types/goversion.go
+++ b/src/cmd/compile/internal/types/goversion.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:generate go run mkbuiltin.go
-
package types
import (
diff --git a/src/cmd/compile/internal/types/etype_string.go b/src/cmd/compile/internal/types/kind_string.go
index e7698296ab..1e1e846240 100644
--- a/src/cmd/compile/internal/types/etype_string.go
+++ b/src/cmd/compile/internal/types/kind_string.go
@@ -1,4 +1,4 @@
-// Code generated by "stringer -type EType -trimprefix T"; DO NOT EDIT.
+// Code generated by "stringer -type Kind -trimprefix T type.go"; DO NOT EDIT.
package types
@@ -48,13 +48,13 @@ func _() {
_ = x[NTYPE-37]
}
-const _EType_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTRCOMPLEX64COMPLEX128FLOAT32FLOAT64BOOLPTRFUNCSLICEARRAYSTRUCTCHANMAPINTERFORWANYSTRINGUNSAFEPTRIDEALNILBLANKFUNCARGSCHANARGSSSATUPLERESULTSNTYPE"
+const _Kind_name = "xxxINT8UINT8INT16UINT16INT32UINT32INT64UINT64INTUINTUINTPTRCOMPLEX64COMPLEX128FLOAT32FLOAT64BOOLPTRFUNCSLICEARRAYSTRUCTCHANMAPINTERFORWANYSTRINGUNSAFEPTRIDEALNILBLANKFUNCARGSCHANARGSSSATUPLERESULTSNTYPE"
-var _EType_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 158, 161, 166, 174, 182, 185, 190, 197, 202}
+var _Kind_index = [...]uint8{0, 3, 7, 12, 17, 23, 28, 34, 39, 45, 48, 52, 59, 68, 78, 85, 92, 96, 99, 103, 108, 113, 119, 123, 126, 131, 135, 138, 144, 153, 158, 161, 166, 174, 182, 185, 190, 197, 202}
func (i Kind) String() string {
- if i >= Kind(len(_EType_index)-1) {
- return "EType(" + strconv.FormatInt(int64(i), 10) + ")"
+ if i >= Kind(len(_Kind_index)-1) {
+ return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _EType_name[_EType_index[i]:_EType_index[i+1]]
+ return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
}
diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go
index b5557b492e..6feedbfabc 100644
--- a/src/cmd/compile/internal/types/type.go
+++ b/src/cmd/compile/internal/types/type.go
@@ -33,9 +33,9 @@ type VarObject interface {
RecordFrameOffset(int64) // save frame offset
}
-//go:generate stringer -type EType -trimprefix T
+//go:generate stringer -type Kind -trimprefix T type.go
-// EType describes a kind of type.
+// Kind describes a kind of type.
type Kind uint8
const (
diff --git a/src/cmd/compile/internal/walk/assign.go b/src/cmd/compile/internal/walk/assign.go
index 6b0e2b272c..c01079d236 100644
--- a/src/cmd/compile/internal/walk/assign.go
+++ b/src/cmd/compile/internal/walk/assign.go
@@ -297,54 +297,6 @@ func fncall(l ir.Node, rt *types.Type) bool {
return true
}
-func ascompatee(op ir.Op, nl, nr []ir.Node, init *ir.Nodes) []ir.Node {
- // check assign expression list to
- // an expression list. called in
- // expr-list = expr-list
-
- // ensure order of evaluation for function calls
- for i := range nl {
- nl[i] = safeExpr(nl[i], init)
- }
- for i1 := range nr {
- nr[i1] = safeExpr(nr[i1], init)
- }
-
- var nn []*ir.AssignStmt
- i := 0
- for ; i < len(nl); i++ {
- if i >= len(nr) {
- break
- }
- // Do not generate 'x = x' during return. See issue 4014.
- if op == ir.ORETURN && ir.SameSafeExpr(nl[i], nr[i]) {
- continue
- }
- nn = append(nn, ascompatee1(nl[i], nr[i], init))
- }
-
- // cannot happen: caller checked that lists had same length
- if i < len(nl) || i < len(nr) {
- var nln, nrn ir.Nodes
- nln.Set(nl)
- nrn.Set(nr)
- base.Fatalf("error in shape across %+v %v %+v / %d %d [%s]", nln, op, nrn, len(nl), len(nr), ir.FuncName(ir.CurFunc))
- }
- return reorder3(nn)
-}
-
-func ascompatee1(l ir.Node, r ir.Node, init *ir.Nodes) *ir.AssignStmt {
- // convas will turn map assigns into function calls,
- // making it impossible for reorder3 to work.
- n := ir.NewAssignStmt(base.Pos, l, r)
-
- if l.Op() == ir.OINDEXMAP {
- return n
- }
-
- return convas(n, init)
-}
-
// check assign type list to
// an expression list. called in
// expr-list = func()
@@ -387,39 +339,79 @@ func ascompatet(nl ir.Nodes, nr *types.Type) []ir.Node {
return append(nn, mm...)
}
-// reorder3
-// from ascompatee
-// a,b = c,d
-// simultaneous assignment. there cannot
-// be later use of an earlier lvalue.
-//
-// function calls have been removed.
-func reorder3(all []*ir.AssignStmt) []ir.Node {
+// check assign expression list to
+// an expression list. called in
+// expr-list = expr-list
+func ascompatee(op ir.Op, nl, nr []ir.Node, init *ir.Nodes) []ir.Node {
+ // cannot happen: should have been rejected during type checking
+ if len(nl) != len(nr) {
+ base.Fatalf("assignment operands mismatch: %+v / %+v", ir.Nodes(nl), ir.Nodes(nr))
+ }
+
+ // ensure order of evaluation for function calls
+ for i := range nl {
+ nl[i] = safeExpr(nl[i], init)
+ }
+ for i := range nr {
+ nr[i] = safeExpr(nr[i], init)
+ }
+
+ var assigned ir.NameSet
+ var memWrite bool
+
+ // affected reports whether expression n could be affected by
+ // the assignments applied so far.
+ affected := func(n ir.Node) bool {
+ return ir.Any(n, func(n ir.Node) bool {
+ if n.Op() == ir.ONAME && assigned.Has(n.(*ir.Name)) {
+ return true
+ }
+ if memWrite && readsMemory(n) {
+ return true
+ }
+ return false
+ })
+ }
+
// If a needed expression may be affected by an
// earlier assignment, make an early copy of that
// expression and use the copy instead.
var early []ir.Node
+ save := func(np *ir.Node) {
+ if n := *np; affected(n) {
+ tmp := ir.Node(typecheck.Temp(n.Type()))
+ as := typecheck.Stmt(ir.NewAssignStmt(base.Pos, tmp, n))
+ early = append(early, as)
+ *np = tmp
+ }
+ }
- var mapinit ir.Nodes
- for i, n := range all {
- l := n.X
+ var late []ir.Node
+ for i, l := range nl {
+ r := nr[i]
+
+ // Do not generate 'x = x' during return. See issue 4014.
+ if op == ir.ORETURN && ir.SameSafeExpr(l, r) {
+ continue
+ }
+
+ as := ir.NewAssignStmt(base.Pos, l, r)
// Save subexpressions needed on left side.
// Drill through non-dereferences.
for {
- switch ll := l; ll.Op() {
- case ir.ODOT:
- ll := ll.(*ir.SelectorExpr)
- l = ll.X
- continue
- case ir.OPAREN:
- ll := ll.(*ir.ParenExpr)
+ switch ll := l.(type) {
+ case *ir.IndexExpr:
+ if ll.X.Type().IsArray() {
+ save(&ll.Index)
+ l = ll.X
+ continue
+ }
+ case *ir.ParenExpr:
l = ll.X
continue
- case ir.OINDEX:
- ll := ll.(*ir.IndexExpr)
- if ll.X.Type().IsArray() {
- ll.Index = reorder3save(ll.Index, all, i, &early)
+ case *ir.SelectorExpr:
+ if ll.Op() == ir.ODOT {
l = ll.X
continue
}
@@ -427,228 +419,80 @@ func reorder3(all []*ir.AssignStmt) []ir.Node {
break
}
+ var name *ir.Name
switch l.Op() {
default:
- base.Fatalf("reorder3 unexpected lvalue %v", l.Op())
-
+ base.Fatalf("unexpected lvalue %v", l.Op())
case ir.ONAME:
- break
-
+ name = l.(*ir.Name)
case ir.OINDEX, ir.OINDEXMAP:
l := l.(*ir.IndexExpr)
- l.X = reorder3save(l.X, all, i, &early)
- l.Index = reorder3save(l.Index, all, i, &early)
- if l.Op() == ir.OINDEXMAP {
- all[i] = convas(all[i], &mapinit)
- }
-
+ save(&l.X)
+ save(&l.Index)
case ir.ODEREF:
l := l.(*ir.StarExpr)
- l.X = reorder3save(l.X, all, i, &early)
+ save(&l.X)
case ir.ODOTPTR:
l := l.(*ir.SelectorExpr)
- l.X = reorder3save(l.X, all, i, &early)
+ save(&l.X)
}
// Save expression on right side.
- all[i].Y = reorder3save(all[i].Y, all, i, &early)
- }
-
- early = append(mapinit, early...)
- for _, as := range all {
- early = append(early, as)
- }
- return early
-}
-
-// if the evaluation of *np would be affected by the
-// assignments in all up to but not including the ith assignment,
-// copy into a temporary during *early and
-// replace *np with that temp.
-// The result of reorder3save MUST be assigned back to n, e.g.
-// n.Left = reorder3save(n.Left, all, i, early)
-func reorder3save(n ir.Node, all []*ir.AssignStmt, i int, early *[]ir.Node) ir.Node {
- if !aliased(n, all[:i]) {
- return n
- }
-
- q := ir.Node(typecheck.Temp(n.Type()))
- as := typecheck.Stmt(ir.NewAssignStmt(base.Pos, q, n))
- *early = append(*early, as)
- return q
-}
+ save(&as.Y)
-// Is it possible that the computation of r might be
-// affected by assignments in all?
-func aliased(r ir.Node, all []*ir.AssignStmt) bool {
- if r == nil {
- return false
- }
-
- // Treat all fields of a struct as referring to the whole struct.
- // We could do better but we would have to keep track of the fields.
- for r.Op() == ir.ODOT {
- r = r.(*ir.SelectorExpr).X
- }
+ late = append(late, convas(as, init))
- // Look for obvious aliasing: a variable being assigned
- // during the all list and appearing in n.
- // Also record whether there are any writes to addressable
- // memory (either main memory or variables whose addresses
- // have been taken).
- memwrite := false
- for _, as := range all {
- // We can ignore assignments to blank.
- if ir.IsBlank(as.X) {
+ if name == nil || name.Addrtaken() || name.Class_ == ir.PEXTERN || name.Class_ == ir.PAUTOHEAP {
+ memWrite = true
continue
}
-
- lv := ir.OuterValue(as.X)
- if lv.Op() != ir.ONAME {
- memwrite = true
+ if ir.IsBlank(name) {
+ // We can ignore assignments to blank.
continue
}
- l := lv.(*ir.Name)
-
- switch l.Class_ {
- default:
- base.Fatalf("unexpected class: %v, %v", l, l.Class_)
-
- case ir.PAUTOHEAP, ir.PEXTERN:
- memwrite = true
- continue
-
- case ir.PAUTO, ir.PPARAM, ir.PPARAMOUT:
- if l.Name().Addrtaken() {
- memwrite = true
- continue
- }
-
- if refersToName(l, r) {
- // Direct hit: l appears in r.
- return true
- }
- }
- }
-
- // The variables being written do not appear in r.
- // However, r might refer to computed addresses
- // that are being written.
-
- // If no computed addresses are affected by the writes, no aliasing.
- if !memwrite {
- return false
+ assigned.Add(name)
}
- // If r does not refer to any variables whose addresses have been taken,
- // then the only possible writes to r would be directly to the variables,
- // and we checked those above, so no aliasing problems.
- if !anyAddrTaken(r) {
- return false
- }
-
- // Otherwise, both the writes and r refer to computed memory addresses.
- // Assume that they might conflict.
- return true
+ return append(early, late...)
}
-// anyAddrTaken reports whether the evaluation n,
-// which appears on the left side of an assignment,
-// may refer to variables whose addresses have been taken.
-func anyAddrTaken(n ir.Node) bool {
- return ir.Any(n, func(n ir.Node) bool {
- switch n.Op() {
- case ir.ONAME:
- n := n.(*ir.Name)
- return n.Class_ == ir.PEXTERN || n.Class_ == ir.PAUTOHEAP || n.Name().Addrtaken()
-
- case ir.ODOT: // but not ODOTPTR - should have been handled in aliased.
- base.Fatalf("anyAddrTaken unexpected ODOT")
-
- case ir.OADD,
- ir.OAND,
- ir.OANDAND,
- ir.OANDNOT,
- ir.OBITNOT,
- ir.OCONV,
- ir.OCONVIFACE,
- ir.OCONVNOP,
- ir.ODIV,
- ir.ODOTTYPE,
- ir.OLITERAL,
- ir.OLSH,
- ir.OMOD,
- ir.OMUL,
- ir.ONEG,
- ir.ONIL,
- ir.OOR,
- ir.OOROR,
- ir.OPAREN,
- ir.OPLUS,
- ir.ORSH,
- ir.OSUB,
- ir.OXOR:
- return false
- }
- // Be conservative.
- return true
- })
-}
-
-// refersToName reports whether r refers to name.
-func refersToName(name *ir.Name, r ir.Node) bool {
- return ir.Any(r, func(r ir.Node) bool {
- return r.Op() == ir.ONAME && r == name
- })
-}
-
-// refersToCommonName reports whether any name
-// appears in common between l and r.
-// This is called from sinit.go.
-func refersToCommonName(l ir.Node, r ir.Node) bool {
- if l == nil || r == nil {
+// readsMemory reports whether the evaluation n directly reads from
+// memory that might be written to indirectly.
+func readsMemory(n ir.Node) bool {
+ switch n.Op() {
+ case ir.ONAME:
+ n := n.(*ir.Name)
+ return n.Class_ == ir.PEXTERN || n.Class_ == ir.PAUTOHEAP || n.Addrtaken()
+
+ case ir.OADD,
+ ir.OAND,
+ ir.OANDAND,
+ ir.OANDNOT,
+ ir.OBITNOT,
+ ir.OCONV,
+ ir.OCONVIFACE,
+ ir.OCONVNOP,
+ ir.ODIV,
+ ir.ODOT,
+ ir.ODOTTYPE,
+ ir.OLITERAL,
+ ir.OLSH,
+ ir.OMOD,
+ ir.OMUL,
+ ir.ONEG,
+ ir.ONIL,
+ ir.OOR,
+ ir.OOROR,
+ ir.OPAREN,
+ ir.OPLUS,
+ ir.ORSH,
+ ir.OSUB,
+ ir.OXOR:
return false
}
- // This could be written elegantly as a Find nested inside a Find:
- //
- // found := ir.Find(l, func(l ir.Node) interface{} {
- // if l.Op() == ir.ONAME {
- // return ir.Find(r, func(r ir.Node) interface{} {
- // if r.Op() == ir.ONAME && l.Name() == r.Name() {
- // return r
- // }
- // return nil
- // })
- // }
- // return nil
- // })
- // return found != nil
- //
- // But that would allocate a new closure for the inner Find
- // for each name found on the left side.
- // It may not matter at all, but the below way of writing it
- // only allocates two closures, not O(|L|) closures.
-
- var doL, doR func(ir.Node) error
- var targetL *ir.Name
- doR = func(r ir.Node) error {
- if r.Op() == ir.ONAME && r.Name() == targetL {
- return stop
- }
- return ir.DoChildren(r, doR)
- }
- doL = func(l ir.Node) error {
- if l.Op() == ir.ONAME {
- l := l.(*ir.Name)
- targetL = l.Name()
- if doR(r) == stop {
- return stop
- }
- }
- return ir.DoChildren(l, doL)
- }
- return doL(l) == stop
+ // Be conservative.
+ return true
}
// expand append(l1, l2...) to
@@ -700,17 +544,15 @@ func appendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node {
nodes.Append(nif)
// s = s[:n]
- nt := ir.NewSliceExpr(base.Pos, ir.OSLICE, s)
- nt.SetSliceBounds(nil, nn, nil)
+ nt := ir.NewSliceExpr(base.Pos, ir.OSLICE, s, nil, nn, nil)
nt.SetBounded(true)
nodes.Append(ir.NewAssignStmt(base.Pos, s, nt))
var ncopy ir.Node
if elemtype.HasPointers() {
// copy(s[len(l1):], l2)
- slice := ir.NewSliceExpr(base.Pos, ir.OSLICE, s)
+ slice := ir.NewSliceExpr(base.Pos, ir.OSLICE, s, ir.NewUnaryExpr(base.Pos, ir.OLEN, l1), nil, nil)
slice.SetType(s.Type())
- slice.SetSliceBounds(ir.NewUnaryExpr(base.Pos, ir.OLEN, l1), nil, nil)
ir.CurFunc.SetWBPos(n.Pos())
@@ -724,9 +566,8 @@ func appendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node {
// rely on runtime to instrument:
// copy(s[len(l1):], l2)
// l2 can be a slice or string.
- slice := ir.NewSliceExpr(base.Pos, ir.OSLICE, s)
+ slice := ir.NewSliceExpr(base.Pos, ir.OSLICE, s, ir.NewUnaryExpr(base.Pos, ir.OLEN, l1), nil, nil)
slice.SetType(s.Type())
- slice.SetSliceBounds(ir.NewUnaryExpr(base.Pos, ir.OLEN, l1), nil, nil)
ptr1, len1 := backingArrayPtrLen(cheapExpr(slice, &nodes))
ptr2, len2 := backingArrayPtrLen(l2)
@@ -870,8 +711,7 @@ func extendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node {
nodes = append(nodes, nif)
// s = s[:n]
- nt := ir.NewSliceExpr(base.Pos, ir.OSLICE, s)
- nt.SetSliceBounds(nil, nn, nil)
+ nt := ir.NewSliceExpr(base.Pos, ir.OSLICE, s, nil, nn, nil)
nt.SetBounded(true)
nodes = append(nodes, ir.NewAssignStmt(base.Pos, s, nt))
diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go
index 61a555b773..fe6045cbbd 100644
--- a/src/cmd/compile/internal/walk/builtin.go
+++ b/src/cmd/compile/internal/walk/builtin.go
@@ -95,8 +95,7 @@ func walkAppend(n *ir.CallExpr, init *ir.Nodes, dst ir.Node) ir.Node {
nn := typecheck.Temp(types.Types[types.TINT])
l = append(l, ir.NewAssignStmt(base.Pos, nn, ir.NewUnaryExpr(base.Pos, ir.OLEN, ns))) // n = len(s)
- slice := ir.NewSliceExpr(base.Pos, ir.OSLICE, ns) // ...s[:n+argc]
- slice.SetSliceBounds(nil, ir.NewBinaryExpr(base.Pos, ir.OADD, nn, na), nil)
+ slice := ir.NewSliceExpr(base.Pos, ir.OSLICE, ns, nil, ir.NewBinaryExpr(base.Pos, ir.OADD, nn, na), nil) // ...s[:n+argc]
slice.SetBounded(true)
l = append(l, ir.NewAssignStmt(base.Pos, ns, slice)) // s = s[:n+argc]
@@ -407,9 +406,8 @@ func walkMakeSlice(n *ir.MakeExpr, init *ir.Nodes) ir.Node {
t = types.NewArray(t.Elem(), i) // [r]T
var_ := typecheck.Temp(t)
- appendWalkStmt(init, ir.NewAssignStmt(base.Pos, var_, nil)) // zero temp
- r := ir.NewSliceExpr(base.Pos, ir.OSLICE, var_) // arr[:l]
- r.SetSliceBounds(nil, l, nil)
+ appendWalkStmt(init, ir.NewAssignStmt(base.Pos, var_, nil)) // zero temp
+ r := ir.NewSliceExpr(base.Pos, ir.OSLICE, var_, nil, l, nil) // arr[:l]
// The conv is necessary in case n.Type is named.
return walkExpr(typecheck.Expr(typecheck.Conv(r, n.Type())), init)
}
@@ -438,7 +436,8 @@ func walkMakeSlice(n *ir.MakeExpr, init *ir.Nodes) ir.Node {
fn := typecheck.LookupRuntime(fnname)
m.Ptr = mkcall1(fn, types.Types[types.TUNSAFEPTR], init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(len, argtype), typecheck.Conv(cap, argtype))
m.Ptr.MarkNonNil()
- m.LenCap = []ir.Node{typecheck.Conv(len, types.Types[types.TINT]), typecheck.Conv(cap, types.Types[types.TINT])}
+ m.Len = typecheck.Conv(len, types.Types[types.TINT])
+ m.Cap = typecheck.Conv(cap, types.Types[types.TINT])
return walkExpr(typecheck.Expr(m), init)
}
@@ -471,7 +470,8 @@ func walkMakeSliceCopy(n *ir.MakeExpr, init *ir.Nodes) ir.Node {
sh := ir.NewSliceHeaderExpr(base.Pos, nil, nil, nil, nil)
sh.Ptr = mkcall1(fn, types.Types[types.TUNSAFEPTR], init, size, typecheck.NodNil(), ir.NewBool(false))
sh.Ptr.MarkNonNil()
- sh.LenCap = []ir.Node{length, length}
+ sh.Len = length
+ sh.Cap = length
sh.SetType(t)
s := typecheck.Temp(t)
@@ -493,7 +493,8 @@ func walkMakeSliceCopy(n *ir.MakeExpr, init *ir.Nodes) ir.Node {
s := ir.NewSliceHeaderExpr(base.Pos, nil, nil, nil, nil)
s.Ptr = mkcall1(fn, types.Types[types.TUNSAFEPTR], init, reflectdata.TypePtr(t.Elem()), length, copylen, typecheck.Conv(copyptr, types.Types[types.TUNSAFEPTR]))
s.Ptr.MarkNonNil()
- s.LenCap = []ir.Node{length, length}
+ s.Len = length
+ s.Cap = length
s.SetType(t)
return walkExpr(typecheck.Expr(s), init)
}
diff --git a/src/cmd/compile/internal/walk/compare.go b/src/cmd/compile/internal/walk/compare.go
index b1ab42782b..a4ea31bf55 100644
--- a/src/cmd/compile/internal/walk/compare.go
+++ b/src/cmd/compile/internal/walk/compare.go
@@ -155,7 +155,7 @@ func walkCompare(n *ir.BinaryExpr, init *ir.Nodes) ir.Node {
// Chose not to inline. Call equality function directly.
if !inline {
// eq algs take pointers; cmpl and cmpr must be addressable
- if !ir.IsAssignable(cmpl) || !ir.IsAssignable(cmpr) {
+ if !ir.IsAddressable(cmpl) || !ir.IsAddressable(cmpr) {
base.Fatalf("arguments of comparison must be lvalues - %v %v", cmpl, cmpr)
}
@@ -428,11 +428,11 @@ func eqFor(t *types.Type) (n ir.Node, needsize bool) {
sym := reflectdata.TypeSymPrefix(".eq", t)
n := typecheck.NewName(sym)
ir.MarkFunc(n)
- n.SetType(typecheck.NewFuncType(nil, []*ir.Field{
- ir.NewField(base.Pos, nil, nil, types.NewPtr(t)),
- ir.NewField(base.Pos, nil, nil, types.NewPtr(t)),
- }, []*ir.Field{
- ir.NewField(base.Pos, nil, nil, types.Types[types.TBOOL]),
+ n.SetType(types.NewSignature(types.NoPkg, nil, []*types.Field{
+ types.NewField(base.Pos, nil, types.NewPtr(t)),
+ types.NewField(base.Pos, nil, types.NewPtr(t)),
+ }, []*types.Field{
+ types.NewField(base.Pos, nil, types.Types[types.TBOOL]),
}))
return n, false
}
diff --git a/src/cmd/compile/internal/walk/complit.go b/src/cmd/compile/internal/walk/complit.go
index 6fbbee9284..8c4f9583ef 100644
--- a/src/cmd/compile/internal/walk/complit.go
+++ b/src/cmd/compile/internal/walk/complit.go
@@ -425,7 +425,7 @@ func slicelit(ctxt initContext, n *ir.CompLitExpr, var_ ir.Node, init *ir.Nodes)
}
// make slice out of heap (6)
- a = ir.NewAssignStmt(base.Pos, var_, ir.NewSliceExpr(base.Pos, ir.OSLICE, vauto))
+ a = ir.NewAssignStmt(base.Pos, var_, ir.NewSliceExpr(base.Pos, ir.OSLICE, vauto, nil, nil, nil))
a = typecheck.Stmt(a)
a = orderStmtInPlace(a, map[string][]*ir.Name{})
@@ -629,6 +629,7 @@ func oaslit(n *ir.AssignStmt, init *ir.Nodes) bool {
// not a special composite literal assignment
return false
}
+ x := n.X.(*ir.Name)
if !types.Identical(n.X.Type(), n.Y.Type()) {
// not a special composite literal assignment
return false
@@ -640,7 +641,7 @@ func oaslit(n *ir.AssignStmt, init *ir.Nodes) bool {
return false
case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT:
- if refersToCommonName(n.X, n.Y) {
+ if ir.Any(n.Y, func(y ir.Node) bool { return ir.Uses(y, x) }) {
// not a special composite literal assignment
return false
}
diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go
index 21426c9817..99abf30668 100644
--- a/src/cmd/compile/internal/walk/convert.go
+++ b/src/cmd/compile/internal/walk/convert.go
@@ -178,7 +178,7 @@ func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
// with a non-interface, especially in a switch on interface value
// with non-interface cases, is not visible to order.stmt, so we
// have to fall back on allocating a temp here.
- if !ir.IsAssignable(v) {
+ if !ir.IsAddressable(v) {
v = copyExpr(v, v.Type(), init)
}
v = typecheck.NodAddr(v)
@@ -260,7 +260,7 @@ func walkStringToBytes(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
}
// Slice the [n]byte to a []byte.
- slice := ir.NewSliceExpr(n.Pos(), ir.OSLICEARR, p)
+ slice := ir.NewSliceExpr(n.Pos(), ir.OSLICEARR, p, nil, nil, nil)
slice.SetType(n.Type())
slice.SetTypecheck(1)
return walkExpr(slice, init)
diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go
index 2029a6aef6..fd0dd5b062 100644
--- a/src/cmd/compile/internal/walk/expr.go
+++ b/src/cmd/compile/internal/walk/expr.go
@@ -26,15 +26,6 @@ func walkExpr(n ir.Node, init *ir.Nodes) ir.Node {
return n
}
- // Eagerly checkwidth all expressions for the back end.
- if n.Type() != nil && !n.Type().WidthCalculated() {
- switch n.Type().Kind() {
- case types.TBLANK, types.TNIL, types.TIDEAL:
- default:
- types.CheckSize(n.Type())
- }
- }
-
if init == n.PtrInit() {
// not okay to use n->ninit when walking n,
// because we might replace n with some other node
@@ -70,23 +61,14 @@ func walkExpr(n ir.Node, init *ir.Nodes) ir.Node {
n = walkExpr1(n, init)
- // Expressions that are constant at run time but not
- // considered const by the language spec are not turned into
- // constants until walk. For example, if n is y%1 == 0, the
- // walk of y%1 may have replaced it by 0.
- // Check whether n with its updated args is itself now a constant.
- t := n.Type()
- n = typecheck.EvalConst(n)
- if n.Type() != t {
- base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type())
- }
- if n.Op() == ir.OLITERAL {
- n = typecheck.Expr(n)
+ // Eagerly compute sizes of all expressions for the back end.
+ if typ := n.Type(); typ != nil && typ.Kind() != types.TBLANK && !typ.IsFuncArgStruct() {
+ types.CheckSize(typ)
+ }
+ if ir.IsConst(n, constant.String) {
// Emit string symbol now to avoid emitting
// any concurrently during the backend.
- if v := n.Val(); v.Kind() == constant.String {
- _ = staticdata.StringSym(n.Pos(), constant.StringVal(v))
- }
+ _ = staticdata.StringSym(n.Pos(), constant.StringVal(n.Val()))
}
updateHasCall(n)
@@ -106,7 +88,7 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node {
base.Fatalf("walkexpr: switch 1 unknown op %+v", n.Op())
panic("unreachable")
- case ir.ONONAME, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR:
+ case ir.ONONAME, ir.OGETG, ir.ONEWOBJ:
return n
case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL, ir.ONAMEOFFSET:
@@ -116,6 +98,11 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node {
// stringsym for constant strings.
return n
+ case ir.OMETHEXPR:
+ // TODO(mdempsky): Do this right after type checking.
+ n := n.(*ir.MethodExpr)
+ return n.FuncName()
+
case ir.ONOT, ir.ONEG, ir.OPLUS, ir.OBITNOT, ir.OREAL, ir.OIMAG, ir.OSPTR, ir.OITAB, ir.OIDATA:
n := n.(*ir.UnaryExpr)
n.X = walkExpr(n.X, init)
@@ -429,7 +416,7 @@ func safeExpr(n ir.Node, init *ir.Nodes) ir.Node {
}
// make a copy; must not be used as an lvalue
- if ir.IsAssignable(n) {
+ if ir.IsAddressable(n) {
base.Fatalf("missing lvalue case in safeexpr: %v", n)
}
return cheapExpr(n, init)
@@ -535,22 +522,28 @@ func walkCall1(n *ir.CallExpr, init *ir.Nodes) {
return // already walked
}
- params := n.X.Type().Params()
- args := n.Args
-
- n.X = walkExpr(n.X, init)
- walkExprList(args, init)
-
- // If this is a method call, add the receiver at the beginning of the args.
+ // If this is a method call t.M(...),
+ // rewrite into a function call T.M(t, ...).
+ // TODO(mdempsky): Do this right after type checking.
if n.Op() == ir.OCALLMETH {
- withRecv := make([]ir.Node, len(args)+1)
+ withRecv := make([]ir.Node, len(n.Args)+1)
dot := n.X.(*ir.SelectorExpr)
withRecv[0] = dot.X
- dot.X = nil
- copy(withRecv[1:], args)
- args = withRecv
+ copy(withRecv[1:], n.Args)
+ n.Args = withRecv
+
+ dot = ir.NewSelectorExpr(dot.Pos(), ir.OXDOT, ir.TypeNode(dot.X.Type()), dot.Selection.Sym)
+
+ n.SetOp(ir.OCALLFUNC)
+ n.X = typecheck.Expr(dot)
}
+ args := n.Args
+ params := n.X.Type().Params()
+
+ n.X = walkExpr(n.X, init)
+ walkExprList(args, init)
+
// For any argument whose evaluation might require a function call,
// store that argument into a temporary variable,
// to prevent that calls from clobbering arguments already on the stack.
@@ -559,16 +552,7 @@ func walkCall1(n *ir.CallExpr, init *ir.Nodes) {
for i, arg := range args {
updateHasCall(arg)
// Determine param type.
- var t *types.Type
- if n.Op() == ir.OCALLMETH {
- if i == 0 {
- t = n.X.Type().Recv().Type
- } else {
- t = params.Field(i - 1).Type
- }
- } else {
- t = params.Field(i).Type
- }
+ t := params.Field(i).Type
if base.Flag.Cfg.Instrumenting || fncall(arg, t) {
// make assignment of fncall to tempAt
tmp := typecheck.Temp(t)
@@ -786,21 +770,19 @@ func walkSlice(n *ir.SliceExpr, init *ir.Nodes) ir.Node {
n.X = walkExpr(n.X, init)
}
- low, high, max := n.SliceBounds()
- low = walkExpr(low, init)
- if low != nil && ir.IsZero(low) {
+ n.Low = walkExpr(n.Low, init)
+ if n.Low != nil && ir.IsZero(n.Low) {
// Reduce x[0:j] to x[:j] and x[0:j:k] to x[:j:k].
- low = nil
+ n.Low = nil
}
- high = walkExpr(high, init)
- max = walkExpr(max, init)
- n.SetSliceBounds(low, high, max)
+ n.High = walkExpr(n.High, init)
+ n.Max = walkExpr(n.Max, init)
if checkSlice {
- n.X = walkCheckPtrAlignment(n.X.(*ir.ConvExpr), init, max)
+ n.X = walkCheckPtrAlignment(n.X.(*ir.ConvExpr), init, n.Max)
}
if n.Op().IsSlice3() {
- if max != nil && max.Op() == ir.OCAP && ir.SameSafeExpr(n.X, max.(*ir.UnaryExpr).X) {
+ if n.Max != nil && n.Max.Op() == ir.OCAP && ir.SameSafeExpr(n.X, n.Max.(*ir.UnaryExpr).X) {
// Reduce x[i:j:cap(x)] to x[i:j].
if n.Op() == ir.OSLICE3 {
n.SetOp(ir.OSLICE)
@@ -817,20 +799,18 @@ func walkSlice(n *ir.SliceExpr, init *ir.Nodes) ir.Node {
// walkSliceHeader walks an OSLICEHEADER node.
func walkSliceHeader(n *ir.SliceHeaderExpr, init *ir.Nodes) ir.Node {
n.Ptr = walkExpr(n.Ptr, init)
- n.LenCap[0] = walkExpr(n.LenCap[0], init)
- n.LenCap[1] = walkExpr(n.LenCap[1], init)
+ n.Len = walkExpr(n.Len, init)
+ n.Cap = walkExpr(n.Cap, init)
return n
}
// TODO(josharian): combine this with its caller and simplify
func reduceSlice(n *ir.SliceExpr) ir.Node {
- low, high, max := n.SliceBounds()
- if high != nil && high.Op() == ir.OLEN && ir.SameSafeExpr(n.X, high.(*ir.UnaryExpr).X) {
+ if n.High != nil && n.High.Op() == ir.OLEN && ir.SameSafeExpr(n.X, n.High.(*ir.UnaryExpr).X) {
// Reduce x[i:len(x)] to x[i:].
- high = nil
+ n.High = nil
}
- n.SetSliceBounds(low, high, max)
- if (n.Op() == ir.OSLICE || n.Op() == ir.OSLICESTR) && low == nil && high == nil {
+ if (n.Op() == ir.OSLICE || n.Op() == ir.OSLICESTR) && n.Low == nil && n.High == nil {
// Reduce x[:] to x.
if base.Debug.Slice > 0 {
base.Warn("slice: omit slice operation")
@@ -969,22 +949,13 @@ func usefield(n *ir.SelectorExpr) {
case ir.ODOT, ir.ODOTPTR:
break
}
- if n.Sel == nil {
- // No field name. This DOTPTR was built by the compiler for access
- // to runtime data structures. Ignore.
- return
- }
- t := n.X.Type()
- if t.IsPtr() {
- t = t.Elem()
- }
field := n.Selection
if field == nil {
base.Fatalf("usefield %v %v without paramfld", n.X.Type(), n.Sel)
}
- if field.Sym != n.Sel || field.Offset != n.Offset {
- base.Fatalf("field inconsistency: %v,%v != %v,%v", field.Sym, field.Offset, n.Sel, n.Offset)
+ if field.Sym != n.Sel {
+ base.Fatalf("field inconsistency: %v != %v", field.Sym, n.Sel)
}
if !strings.Contains(field.Note, "go:\"track\"") {
return
diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go
index 03310a50c6..ebbd467570 100644
--- a/src/cmd/compile/internal/walk/order.go
+++ b/src/cmd/compile/internal/walk/order.go
@@ -235,7 +235,7 @@ func (o *orderState) safeExpr(n ir.Node) ir.Node {
// because we emit explicit VARKILL instructions marking the end of those
// temporaries' lifetimes.
func isaddrokay(n ir.Node) bool {
- return ir.IsAssignable(n) && (n.Op() != ir.ONAME || n.(*ir.Name).Class_ == ir.PEXTERN || ir.IsAutoTmp(n))
+ return ir.IsAddressable(n) && (n.Op() != ir.ONAME || n.(*ir.Name).Class_ == ir.PEXTERN || ir.IsAutoTmp(n))
}
// addrTemp ensures that n is okay to pass by address to runtime routines.
@@ -843,12 +843,13 @@ func (o *orderState) stmt(n ir.Node) {
n.X = o.expr(n.X, nil)
orderBody := true
- switch n.Type().Kind() {
+ xt := typecheck.RangeExprType(n.X.Type())
+ switch xt.Kind() {
default:
base.Fatalf("order.stmt range %v", n.Type())
case types.TARRAY, types.TSLICE:
- if len(n.Vars) < 2 || ir.IsBlank(n.Vars[1]) {
+ if n.Value == nil || ir.IsBlank(n.Value) {
// for i := range x will only use x once, to compute len(x).
// No need to copy it.
break
@@ -885,9 +886,10 @@ func (o *orderState) stmt(n ir.Node) {
// n.Prealloc is the temp for the iterator.
// hiter contains pointers and needs to be zeroed.
- n.Prealloc = o.newTemp(reflectdata.MapIterType(n.Type()), true)
+ n.Prealloc = o.newTemp(reflectdata.MapIterType(xt), true)
}
- o.exprListInPlace(n.Vars)
+ n.Key = o.exprInPlace(n.Key)
+ n.Value = o.exprInPlace(n.Value)
if orderBody {
orderBlock(&n.Body, o.free)
}
@@ -912,7 +914,6 @@ func (o *orderState) stmt(n ir.Node) {
n := n.(*ir.SelectStmt)
t := o.markTemp()
for _, ncas := range n.Cases {
- ncas := ncas.(*ir.CaseStmt)
r := ncas.Comm
ir.SetPos(ncas)
@@ -994,7 +995,6 @@ func (o *orderState) stmt(n ir.Node) {
// Also insert any ninit queued during the previous loop.
// (The temporary cleaning must follow that ninit work.)
for _, cas := range n.Cases {
- cas := cas.(*ir.CaseStmt)
orderBlock(&cas.Body, o.free)
cas.Body.Prepend(o.cleanTempNoPop(t)...)
@@ -1034,13 +1034,12 @@ func (o *orderState) stmt(n ir.Node) {
n := n.(*ir.SwitchStmt)
if base.Debug.Libfuzzer != 0 && !hasDefaultCase(n) {
// Add empty "default:" case for instrumentation.
- n.Cases.Append(ir.NewCaseStmt(base.Pos, nil, nil))
+ n.Cases = append(n.Cases, ir.NewCaseStmt(base.Pos, nil, nil))
}
t := o.markTemp()
n.Tag = o.expr(n.Tag, nil)
for _, ncas := range n.Cases {
- ncas := ncas.(*ir.CaseStmt)
o.exprListInPlace(ncas.List)
orderBlock(&ncas.Body, o.free)
}
@@ -1054,7 +1053,6 @@ func (o *orderState) stmt(n ir.Node) {
func hasDefaultCase(n *ir.SwitchStmt) bool {
for _, ncas := range n.Cases {
- ncas := ncas.(*ir.CaseStmt)
if len(ncas.List) == 0 {
return true
}
@@ -1296,14 +1294,9 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node {
case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
n := n.(*ir.SliceExpr)
n.X = o.expr(n.X, nil)
- low, high, max := n.SliceBounds()
- low = o.expr(low, nil)
- low = o.cheapExpr(low)
- high = o.expr(high, nil)
- high = o.cheapExpr(high)
- max = o.expr(max, nil)
- max = o.cheapExpr(max)
- n.SetSliceBounds(low, high, max)
+ n.Low = o.cheapExpr(o.expr(n.Low, nil))
+ n.High = o.cheapExpr(o.expr(n.High, nil))
+ n.Max = o.cheapExpr(o.expr(n.Max, nil))
if lhs == nil || lhs.Op() != ir.ONAME && !ir.SameSafeExpr(lhs, n.X) {
return o.copyExpr(n)
}
diff --git a/src/cmd/compile/internal/walk/range.go b/src/cmd/compile/internal/walk/range.go
index 98a3dc23f9..49a69e9751 100644
--- a/src/cmd/compile/internal/walk/range.go
+++ b/src/cmd/compile/internal/walk/range.go
@@ -56,20 +56,11 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
// hb: hidden bool
// a, v1, v2: not hidden aggregate, val 1, 2
- t := nrange.Type()
-
a := nrange.X
+ t := typecheck.RangeExprType(a.Type())
lno := ir.SetPos(a)
- var v1, v2 ir.Node
- l := len(nrange.Vars)
- if l > 0 {
- v1 = nrange.Vars[0]
- }
-
- if l > 1 {
- v2 = nrange.Vars[1]
- }
+ v1, v2 := nrange.Key, nrange.Value
if ir.IsBlank(v2) {
v2 = nil
@@ -121,7 +112,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
}
// for v1, v2 := range ha { body }
- if cheapComputableIndex(nrange.Type().Elem().Width) {
+ if cheapComputableIndex(t.Elem().Width) {
// v1, v2 = hv1, ha[hv1]
tmp := ir.NewIndexExpr(base.Pos, ha, hv1)
tmp.SetBounded(true)
@@ -150,7 +141,7 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
ifGuard.Cond = ir.NewBinaryExpr(base.Pos, ir.OLT, hv1, hn)
nfor.SetOp(ir.OFORUNTIL)
- hp := typecheck.Temp(types.NewPtr(nrange.Type().Elem()))
+ hp := typecheck.Temp(types.NewPtr(t.Elem()))
tmp := ir.NewIndexExpr(base.Pos, ha, ir.NewInt(0))
tmp.SetBounded(true)
init = append(init, ir.NewAssignStmt(base.Pos, hp, typecheck.NodAddr(tmp)))
@@ -343,15 +334,12 @@ func isMapClear(n *ir.RangeStmt) bool {
return false
}
- if n.Op() != ir.ORANGE || n.Type().Kind() != types.TMAP || len(n.Vars) != 1 {
- return false
- }
-
- k := n.Vars[0]
- if k == nil || ir.IsBlank(k) {
+ t := n.X.Type()
+ if n.Op() != ir.ORANGE || t.Kind() != types.TMAP || n.Key == nil || n.Value != nil {
return false
}
+ k := n.Key
// Require k to be a new variable name.
if !ir.DeclaredBy(k, n) {
return false
@@ -372,7 +360,7 @@ func isMapClear(n *ir.RangeStmt) bool {
}
// Keys where equality is not reflexive can not be deleted from maps.
- if !types.IsReflexive(m.Type().Key()) {
+ if !types.IsReflexive(t.Key()) {
return false
}
@@ -428,7 +416,7 @@ func arrayClear(loop *ir.RangeStmt, v1, v2, a ir.Node) ir.Node {
return nil
}
- elemsize := loop.Type().Elem().Width
+ elemsize := typecheck.RangeExprType(loop.X.Type()).Elem().Width
if elemsize <= 0 || !ir.IsZero(stmt.Y) {
return nil
}
diff --git a/src/cmd/compile/internal/walk/select.go b/src/cmd/compile/internal/walk/select.go
index 438131b294..1c5e1d7e64 100644
--- a/src/cmd/compile/internal/walk/select.go
+++ b/src/cmd/compile/internal/walk/select.go
@@ -21,7 +21,7 @@ func walkSelect(sel *ir.SelectStmt) {
sel.PtrInit().Set(nil)
init = append(init, walkSelectCases(sel.Cases)...)
- sel.Cases = ir.Nodes{}
+ sel.Cases = nil
sel.Compiled.Set(init)
walkStmtList(sel.Compiled)
@@ -29,7 +29,7 @@ func walkSelect(sel *ir.SelectStmt) {
base.Pos = lno
}
-func walkSelectCases(cases ir.Nodes) []ir.Node {
+func walkSelectCases(cases []*ir.CommClause) []ir.Node {
ncas := len(cases)
sellineno := base.Pos
@@ -40,7 +40,7 @@ func walkSelectCases(cases ir.Nodes) []ir.Node {
// optimization: one-case select: single op.
if ncas == 1 {
- cas := cases[0].(*ir.CaseStmt)
+ cas := cases[0]
ir.SetPos(cas)
l := cas.Init()
if cas.Comm != nil { // not default:
@@ -73,9 +73,8 @@ func walkSelectCases(cases ir.Nodes) []ir.Node {
// convert case value arguments to addresses.
// this rewrite is used by both the general code and the next optimization.
- var dflt *ir.CaseStmt
+ var dflt *ir.CommClause
for _, cas := range cases {
- cas := cas.(*ir.CaseStmt)
ir.SetPos(cas)
n := cas.Comm
if n == nil {
@@ -99,9 +98,9 @@ func walkSelectCases(cases ir.Nodes) []ir.Node {
// optimization: two-case select but one is default: single non-blocking op.
if ncas == 2 && dflt != nil {
- cas := cases[0].(*ir.CaseStmt)
+ cas := cases[0]
if cas == dflt {
- cas = cases[1].(*ir.CaseStmt)
+ cas = cases[1]
}
n := cas.Comm
@@ -147,7 +146,7 @@ func walkSelectCases(cases ir.Nodes) []ir.Node {
if dflt != nil {
ncas--
}
- casorder := make([]*ir.CaseStmt, ncas)
+ casorder := make([]*ir.CommClause, ncas)
nsends, nrecvs := 0, 0
var init []ir.Node
@@ -170,7 +169,6 @@ func walkSelectCases(cases ir.Nodes) []ir.Node {
// register cases
for _, cas := range cases {
- cas := cas.(*ir.CaseStmt)
ir.SetPos(cas)
init = append(init, cas.Init()...)
@@ -244,7 +242,7 @@ func walkSelectCases(cases ir.Nodes) []ir.Node {
}
// dispatch cases
- dispatch := func(cond ir.Node, cas *ir.CaseStmt) {
+ dispatch := func(cond ir.Node, cas *ir.CommClause) {
cond = typecheck.Expr(cond)
cond = typecheck.DefaultLit(cond, nil)
@@ -287,9 +285,9 @@ var scase *types.Type
// Keep in sync with src/runtime/select.go.
func scasetype() *types.Type {
if scase == nil {
- scase = typecheck.NewStructType([]*ir.Field{
- ir.NewField(base.Pos, typecheck.Lookup("c"), nil, types.Types[types.TUNSAFEPTR]),
- ir.NewField(base.Pos, typecheck.Lookup("elem"), nil, types.Types[types.TUNSAFEPTR]),
+ scase = types.NewStruct(types.NoPkg, []*types.Field{
+ types.NewField(base.Pos, typecheck.Lookup("c"), types.Types[types.TUNSAFEPTR]),
+ types.NewField(base.Pos, typecheck.Lookup("elem"), types.Types[types.TUNSAFEPTR]),
})
scase.SetNoalg(true)
}
diff --git a/src/cmd/compile/internal/walk/switch.go b/src/cmd/compile/internal/walk/switch.go
index 360086ec79..de0b471b34 100644
--- a/src/cmd/compile/internal/walk/switch.go
+++ b/src/cmd/compile/internal/walk/switch.go
@@ -71,7 +71,6 @@ func walkSwitchExpr(sw *ir.SwitchStmt) {
var defaultGoto ir.Node
var body ir.Nodes
for _, ncase := range sw.Cases {
- ncase := ncase.(*ir.CaseStmt)
label := typecheck.AutoLabel(".s")
jmp := ir.NewBranchStmt(ncase.Pos(), ir.OGOTO, label)
@@ -96,7 +95,7 @@ func walkSwitchExpr(sw *ir.SwitchStmt) {
body.Append(br)
}
}
- sw.Cases.Set(nil)
+ sw.Cases = nil
if defaultGoto == nil {
br := ir.NewBranchStmt(base.Pos, ir.OBREAK, nil)
@@ -259,7 +258,6 @@ func allCaseExprsAreSideEffectFree(sw *ir.SwitchStmt) bool {
// enough.
for _, ncase := range sw.Cases {
- ncase := ncase.(*ir.CaseStmt)
for _, v := range ncase.List {
if v.Op() != ir.OLITERAL {
return false
@@ -318,26 +316,14 @@ func walkSwitchType(sw *ir.SwitchStmt) {
sw.Compiled.Append(ifNil)
// Load hash from type or itab.
- dotHash := ir.NewSelectorExpr(base.Pos, ir.ODOTPTR, itab, nil)
- dotHash.SetType(types.Types[types.TUINT32])
- dotHash.SetTypecheck(1)
- if s.facename.Type().IsEmptyInterface() {
- dotHash.Offset = int64(2 * types.PtrSize) // offset of hash in runtime._type
- } else {
- dotHash.Offset = int64(2 * types.PtrSize) // offset of hash in runtime.itab
- }
- dotHash.SetBounded(true) // guaranteed not to fault
+ dotHash := typeHashFieldOf(base.Pos, itab)
s.hashname = copyExpr(dotHash, dotHash.Type(), &sw.Compiled)
br := ir.NewBranchStmt(base.Pos, ir.OBREAK, nil)
var defaultGoto, nilGoto ir.Node
var body ir.Nodes
for _, ncase := range sw.Cases {
- ncase := ncase.(*ir.CaseStmt)
- var caseVar ir.Node
- if len(ncase.Vars) != 0 {
- caseVar = ncase.Vars[0]
- }
+ caseVar := ncase.Var
// For single-type cases with an interface type,
// we initialize the case variable as part of the type assertion.
@@ -395,7 +381,7 @@ func walkSwitchType(sw *ir.SwitchStmt) {
body.Append(ncase.Body...)
body.Append(br)
}
- sw.Cases.Set(nil)
+ sw.Cases = nil
if defaultGoto == nil {
defaultGoto = br
@@ -412,6 +398,32 @@ func walkSwitchType(sw *ir.SwitchStmt) {
walkStmtList(sw.Compiled)
}
+// typeHashFieldOf returns an expression to select the type hash field
+// from an interface's descriptor word (whether a *runtime._type or
+// *runtime.itab pointer).
+func typeHashFieldOf(pos src.XPos, itab *ir.UnaryExpr) *ir.SelectorExpr {
+ if itab.Op() != ir.OITAB {
+ base.Fatalf("expected OITAB, got %v", itab.Op())
+ }
+ var hashField *types.Field
+ if itab.X.Type().IsEmptyInterface() {
+ // runtime._type's hash field
+ if rtypeHashField == nil {
+ rtypeHashField = runtimeField("hash", int64(2*types.PtrSize), types.Types[types.TUINT32])
+ }
+ hashField = rtypeHashField
+ } else {
+ // runtime.itab's hash field
+ if itabHashField == nil {
+ itabHashField = runtimeField("hash", int64(2*types.PtrSize), types.Types[types.TUINT32])
+ }
+ hashField = itabHashField
+ }
+ return boundedDotPtr(pos, itab, hashField)
+}
+
+var rtypeHashField, itabHashField *types.Field
+
// A typeSwitch walks a type switch.
type typeSwitch struct {
// Temporary variables (i.e., ONAMEs) used by type switch dispatch logic:
diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go
index 9dda367b4d..c4c3debde4 100644
--- a/src/cmd/compile/internal/walk/walk.go
+++ b/src/cmd/compile/internal/walk/walk.go
@@ -539,12 +539,30 @@ func calcHasCall(n ir.Node) bool {
// itabType loads the _type field from a runtime.itab struct.
func itabType(itab ir.Node) ir.Node {
- typ := ir.NewSelectorExpr(base.Pos, ir.ODOTPTR, itab, nil)
- typ.SetType(types.NewPtr(types.Types[types.TUINT8]))
- typ.SetTypecheck(1)
- typ.Offset = int64(types.PtrSize) // offset of _type in runtime.itab
- typ.SetBounded(true) // guaranteed not to fault
- return typ
+ if itabTypeField == nil {
+ // runtime.itab's _type field
+ itabTypeField = runtimeField("_type", int64(types.PtrSize), types.NewPtr(types.Types[types.TUINT8]))
+ }
+ return boundedDotPtr(base.Pos, itab, itabTypeField)
+}
+
+var itabTypeField *types.Field
+
+// boundedDotPtr returns a selector expression representing ptr.field
+// and omits nil-pointer checks for ptr.
+func boundedDotPtr(pos src.XPos, ptr ir.Node, field *types.Field) *ir.SelectorExpr {
+ sel := ir.NewSelectorExpr(pos, ir.ODOTPTR, ptr, field.Sym)
+ sel.Selection = field
+ sel.SetType(field.Type)
+ sel.SetTypecheck(1)
+ sel.SetBounded(true) // guaranteed not to fault
+ return sel
+}
+
+func runtimeField(name string, offset int64, typ *types.Type) *types.Field {
+ f := types.NewField(src.NoXPos, ir.Pkgs.Runtime.Lookup(name), typ)
+ f.Offset = offset
+ return f
}
// ifaceData loads the data field from an interface.