diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index e32233bcaf8..404e89d0f26 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -22,14 +22,14 @@ package main_test var knownFormats = map[string]string{ "*bytes.Buffer %s": "", "*cmd/compile/internal/gc.EscLocation %v": "", - "*cmd/compile/internal/gc.Node %#v": "", - "*cmd/compile/internal/gc.Node %+S": "", - "*cmd/compile/internal/gc.Node %+v": "", - "*cmd/compile/internal/gc.Node %L": "", - "*cmd/compile/internal/gc.Node %S": "", - "*cmd/compile/internal/gc.Node %j": "", - "*cmd/compile/internal/gc.Node %p": "", - "*cmd/compile/internal/gc.Node %v": "", + "*cmd/compile/internal/ir.Node %#v": "", + "*cmd/compile/internal/ir.Node %+S": "", + "*cmd/compile/internal/ir.Node %+v": "", + "*cmd/compile/internal/ir.Node %L": "", + "*cmd/compile/internal/ir.Node %S": "", + "*cmd/compile/internal/ir.Node %j": "", + "*cmd/compile/internal/ir.Node %p": "", + "*cmd/compile/internal/ir.Node %v": "", "*cmd/compile/internal/ssa.Block %s": "", "*cmd/compile/internal/ssa.Block %v": "", "*cmd/compile/internal/ssa.Func %s": "", @@ -78,18 +78,18 @@ var knownFormats = map[string]string{ "byte %q": "", "byte %v": "", "cmd/compile/internal/arm.shift %d": "", - "cmd/compile/internal/gc.Class %d": "", - "cmd/compile/internal/gc.Class %s": "", - "cmd/compile/internal/gc.Class %v": "", - "cmd/compile/internal/gc.Nodes %#v": "", - "cmd/compile/internal/gc.Nodes %+v": "", - "cmd/compile/internal/gc.Nodes %.v": "", - "cmd/compile/internal/gc.Nodes %v": "", - "cmd/compile/internal/gc.Op %#v": "", - "cmd/compile/internal/gc.Op %v": "", - "cmd/compile/internal/gc.fmtMode %d": "", "cmd/compile/internal/gc.initKind %d": "", "cmd/compile/internal/gc.itag %v": "", + "cmd/compile/internal/ir.Class %d": "", + "cmd/compile/internal/ir.Class %s": "", + "cmd/compile/internal/ir.Class %v": "", + "cmd/compile/internal/ir.FmtMode %d": "", + "cmd/compile/internal/ir.Nodes %#v": "", + "cmd/compile/internal/ir.Nodes %+v": "", + "cmd/compile/internal/ir.Nodes %.v": "", + "cmd/compile/internal/ir.Nodes %v": "", + "cmd/compile/internal/ir.Op %#v": "", + "cmd/compile/internal/ir.Op %v": "", "cmd/compile/internal/ssa.BranchPrediction %d": "", "cmd/compile/internal/ssa.Edge %v": "", "cmd/compile/internal/ssa.GCNode %v": "", @@ -162,8 +162,8 @@ var knownFormats = map[string]string{ "interface{} %q": "", "interface{} %s": "", "interface{} %v": "", - "map[*cmd/compile/internal/gc.Node]*cmd/compile/internal/ssa.Value %v": "", - "map[*cmd/compile/internal/gc.Node][]*cmd/compile/internal/gc.Node %v": "", + "map[*cmd/compile/internal/ir.Node]*cmd/compile/internal/ssa.Value %v": "", + "map[*cmd/compile/internal/ir.Node][]*cmd/compile/internal/ir.Node %v": "", "map[cmd/compile/internal/ssa.ID]uint32 %v": "", "map[int64]uint32 %v": "", "math/big.Accuracy %s": "", diff --git a/src/cmd/compile/internal/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go index 7d34cc51700..ff1dd8869e2 100644 --- a/src/cmd/compile/internal/arm/ssa.go +++ b/src/cmd/compile/internal/arm/ssa.go @@ -11,6 +11,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/gc" + "cmd/compile/internal/ir" "cmd/compile/internal/logopt" "cmd/compile/internal/ssa" "cmd/compile/internal/types" @@ -545,7 +546,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case *gc.Node: + case *ir.Node: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index 5e6f607708d..58c00dc3bd1 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -9,6 +9,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/gc" + "cmd/compile/internal/ir" "cmd/compile/internal/logopt" "cmd/compile/internal/ssa" "cmd/compile/internal/types" @@ -395,7 +396,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case *gc.Node: + case *ir.Node: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go index 517aaa4b814..cf82b9d5916 100644 --- a/src/cmd/compile/internal/gc/alg.go +++ b/src/cmd/compile/internal/gc/alg.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/obj" "fmt" @@ -70,11 +71,11 @@ func EqCanPanic(t *types.Type) bool { switch t.Etype { default: return false - case TINTER: + case types.TINTER: return true - case TARRAY: + case types.TARRAY: return EqCanPanic(t.Elem()) - case TSTRUCT: + case types.TSTRUCT: for _, f := range t.FieldSlice() { if !f.Sym.IsBlank() && EqCanPanic(f.Type) { return true @@ -120,45 +121,45 @@ func algtype1(t *types.Type) (AlgKind, *types.Type) { } switch t.Etype { - case TANY, TFORW: + case types.TANY, types.TFORW: // will be defined later. return ANOEQ, t - case TINT8, TUINT8, TINT16, TUINT16, - TINT32, TUINT32, TINT64, TUINT64, - TINT, TUINT, TUINTPTR, - TBOOL, TPTR, - TCHAN, TUNSAFEPTR: + case types.TINT8, types.TUINT8, types.TINT16, types.TUINT16, + types.TINT32, types.TUINT32, types.TINT64, types.TUINT64, + types.TINT, types.TUINT, types.TUINTPTR, + types.TBOOL, types.TPTR, + types.TCHAN, types.TUNSAFEPTR: return AMEM, nil - case TFUNC, TMAP: + case types.TFUNC, types.TMAP: return ANOEQ, t - case TFLOAT32: + case types.TFLOAT32: return AFLOAT32, nil - case TFLOAT64: + case types.TFLOAT64: return AFLOAT64, nil - case TCOMPLEX64: + case types.TCOMPLEX64: return ACPLX64, nil - case TCOMPLEX128: + case types.TCOMPLEX128: return ACPLX128, nil - case TSTRING: + case types.TSTRING: return ASTRING, nil - case TINTER: + case types.TINTER: if t.IsEmptyInterface() { return ANILINTER, nil } return AINTER, nil - case TSLICE: + case types.TSLICE: return ANOEQ, t - case TARRAY: + case types.TARRAY: a, bad := algtype1(t.Elem()) switch a { case AMEM: @@ -178,7 +179,7 @@ func algtype1(t *types.Type) (AlgKind, *types.Type) { return ASPECIAL, nil - case TSTRUCT: + case types.TSTRUCT: fields := t.FieldSlice() // One-field struct is same as that one field alone. @@ -288,19 +289,19 @@ func genhash(t *types.Type) *obj.LSym { } base.Pos = autogeneratedPos // less confusing than end of input - dclcontext = PEXTERN + dclcontext = ir.PEXTERN // func sym(p *T, h uintptr) uintptr - tfn := nod(OTFUNC, nil, nil) + tfn := ir.Nod(ir.OTFUNC, nil, nil) tfn.List.Set2( namedfield("p", types.NewPtr(t)), - namedfield("h", types.Types[TUINTPTR]), + namedfield("h", types.Types[types.TUINTPTR]), ) - tfn.Rlist.Set1(anonfield(types.Types[TUINTPTR])) + tfn.Rlist.Set1(anonfield(types.Types[types.TUINTPTR])) fn := dclfunc(sym, tfn) - np := asNode(tfn.Type.Params().Field(0).Nname) - nh := asNode(tfn.Type.Params().Field(1).Nname) + np := ir.AsNode(tfn.Type.Params().Field(0).Nname) + nh := ir.AsNode(tfn.Type.Params().Field(1).Nname) switch t.Etype { case types.TARRAY: @@ -309,23 +310,23 @@ func genhash(t *types.Type) *obj.LSym { // pure memory. hashel := hashfor(t.Elem()) - n := nod(ORANGE, nil, nod(ODEREF, np, nil)) - ni := newname(lookup("i")) - ni.Type = types.Types[TINT] + n := ir.Nod(ir.ORANGE, nil, ir.Nod(ir.ODEREF, np, nil)) + ni := NewName(lookup("i")) + ni.Type = types.Types[types.TINT] n.List.Set1(ni) n.SetColas(true) colasdefn(n.List.Slice(), n) ni = n.List.First() // h = hashel(&p[i], h) - call := nod(OCALL, hashel, nil) + call := ir.Nod(ir.OCALL, hashel, nil) - nx := nod(OINDEX, np, ni) + nx := ir.Nod(ir.OINDEX, np, ni) nx.SetBounded(true) - na := nod(OADDR, nx, nil) + na := ir.Nod(ir.OADDR, nx, nil) call.List.Append(na) call.List.Append(nh) - n.Nbody.Append(nod(OAS, nh, call)) + n.Nbody.Append(ir.Nod(ir.OAS, nh, call)) fn.Nbody.Append(n) @@ -344,12 +345,12 @@ func genhash(t *types.Type) *obj.LSym { // Hash non-memory fields with appropriate hash function. if !IsRegularMemory(f.Type) { hashel := hashfor(f.Type) - call := nod(OCALL, hashel, nil) - nx := nodSym(OXDOT, np, f.Sym) // TODO: fields from other packages? - na := nod(OADDR, nx, nil) + call := ir.Nod(ir.OCALL, hashel, nil) + nx := nodSym(ir.OXDOT, np, f.Sym) // TODO: fields from other packages? + na := ir.Nod(ir.OADDR, nx, nil) call.List.Append(na) call.List.Append(nh) - fn.Nbody.Append(nod(OAS, nh, call)) + fn.Nbody.Append(ir.Nod(ir.OAS, nh, call)) i++ continue } @@ -359,24 +360,24 @@ func genhash(t *types.Type) *obj.LSym { // h = hashel(&p.first, size, h) hashel := hashmem(f.Type) - call := nod(OCALL, hashel, nil) - nx := nodSym(OXDOT, np, f.Sym) // TODO: fields from other packages? - na := nod(OADDR, nx, nil) + call := ir.Nod(ir.OCALL, hashel, nil) + nx := nodSym(ir.OXDOT, np, f.Sym) // TODO: fields from other packages? + na := ir.Nod(ir.OADDR, nx, nil) call.List.Append(na) call.List.Append(nh) call.List.Append(nodintconst(size)) - fn.Nbody.Append(nod(OAS, nh, call)) + fn.Nbody.Append(ir.Nod(ir.OAS, nh, call)) i = next } } - r := nod(ORETURN, nil, nil) + r := ir.Nod(ir.ORETURN, nil, nil) r.List.Append(nh) fn.Nbody.Append(r) if base.Flag.LowerR != 0 { - dumplist("genhash body", fn.Nbody) + ir.DumpList("genhash body", fn.Nbody) } funcbody() @@ -403,7 +404,7 @@ func genhash(t *types.Type) *obj.LSym { return closure } -func hashfor(t *types.Type) *Node { +func hashfor(t *types.Type) *ir.Node { var sym *types.Sym switch a, _ := algtype1(t); a { @@ -429,13 +430,13 @@ func hashfor(t *types.Type) *Node { sym = typesymprefix(".hash", t) } - n := newname(sym) + n := NewName(sym) setNodeNameFunc(n) - n.Type = functype(nil, []*Node{ + n.Type = functype(nil, []*ir.Node{ anonfield(types.NewPtr(t)), - anonfield(types.Types[TUINTPTR]), - }, []*Node{ - anonfield(types.Types[TUINTPTR]), + anonfield(types.Types[types.TUINTPTR]), + }, []*ir.Node{ + anonfield(types.Types[types.TUINTPTR]), }) return n } @@ -517,20 +518,20 @@ func geneq(t *types.Type) *obj.LSym { // Autogenerate code for equality of structs and arrays. base.Pos = autogeneratedPos // less confusing than end of input - dclcontext = PEXTERN + dclcontext = ir.PEXTERN // func sym(p, q *T) bool - tfn := nod(OTFUNC, nil, nil) + tfn := ir.Nod(ir.OTFUNC, nil, nil) tfn.List.Set2( namedfield("p", types.NewPtr(t)), namedfield("q", types.NewPtr(t)), ) - tfn.Rlist.Set1(namedfield("r", types.Types[TBOOL])) + tfn.Rlist.Set1(namedfield("r", types.Types[types.TBOOL])) fn := dclfunc(sym, tfn) - np := asNode(tfn.Type.Params().Field(0).Nname) - nq := asNode(tfn.Type.Params().Field(1).Nname) - nr := asNode(tfn.Type.Results().Field(0).Nname) + np := ir.AsNode(tfn.Type.Params().Field(0).Nname) + nq := ir.AsNode(tfn.Type.Params().Field(1).Nname) + nr := ir.AsNode(tfn.Type.Results().Field(0).Nname) // Label to jump to if an equality test fails. neq := autolabel(".neq") @@ -542,7 +543,7 @@ func geneq(t *types.Type) *obj.LSym { default: base.Fatalf("geneq %v", t) - case TARRAY: + case types.TARRAY: nelem := t.NumElem() // checkAll generates code to check the equality of all array elements. @@ -566,15 +567,15 @@ func geneq(t *types.Type) *obj.LSym { // // TODO(josharian): consider doing some loop unrolling // for larger nelem as well, processing a few elements at a time in a loop. - checkAll := func(unroll int64, last bool, eq func(pi, qi *Node) *Node) { + checkAll := func(unroll int64, last bool, eq func(pi, qi *ir.Node) *ir.Node) { // checkIdx generates a node to check for equality at index i. - checkIdx := func(i *Node) *Node { + checkIdx := func(i *ir.Node) *ir.Node { // pi := p[i] - pi := nod(OINDEX, np, i) + pi := ir.Nod(ir.OINDEX, np, i) pi.SetBounded(true) pi.Type = t.Elem() // qi := q[i] - qi := nod(OINDEX, nq, i) + qi := ir.Nod(ir.OINDEX, nq, i) qi.SetBounded(true) qi.Type = t.Elem() return eq(pi, qi) @@ -588,68 +589,68 @@ func geneq(t *types.Type) *obj.LSym { // Generate a series of checks. for i := int64(0); i < nelem; i++ { // if check {} else { goto neq } - nif := nod(OIF, checkIdx(nodintconst(i)), nil) - nif.Rlist.Append(nodSym(OGOTO, nil, neq)) + nif := ir.Nod(ir.OIF, checkIdx(nodintconst(i)), nil) + nif.Rlist.Append(nodSym(ir.OGOTO, nil, neq)) fn.Nbody.Append(nif) } if last { - fn.Nbody.Append(nod(OAS, nr, checkIdx(nodintconst(nelem)))) + fn.Nbody.Append(ir.Nod(ir.OAS, nr, checkIdx(nodintconst(nelem)))) } } else { // Generate a for loop. // for i := 0; i < nelem; i++ - i := temp(types.Types[TINT]) - init := nod(OAS, i, nodintconst(0)) - cond := nod(OLT, i, nodintconst(nelem)) - post := nod(OAS, i, nod(OADD, i, nodintconst(1))) - loop := nod(OFOR, cond, post) + i := temp(types.Types[types.TINT]) + init := ir.Nod(ir.OAS, i, nodintconst(0)) + cond := ir.Nod(ir.OLT, i, nodintconst(nelem)) + post := ir.Nod(ir.OAS, i, ir.Nod(ir.OADD, i, nodintconst(1))) + loop := ir.Nod(ir.OFOR, cond, post) loop.Ninit.Append(init) // if eq(pi, qi) {} else { goto neq } - nif := nod(OIF, checkIdx(i), nil) - nif.Rlist.Append(nodSym(OGOTO, nil, neq)) + nif := ir.Nod(ir.OIF, checkIdx(i), nil) + nif.Rlist.Append(nodSym(ir.OGOTO, nil, neq)) loop.Nbody.Append(nif) fn.Nbody.Append(loop) if last { - fn.Nbody.Append(nod(OAS, nr, nodbool(true))) + fn.Nbody.Append(ir.Nod(ir.OAS, nr, nodbool(true))) } } } switch t.Elem().Etype { - case TSTRING: + case types.TSTRING: // Do two loops. First, check that all the lengths match (cheap). // Second, check that all the contents match (expensive). // TODO: when the array size is small, unroll the length match checks. - checkAll(3, false, func(pi, qi *Node) *Node { + checkAll(3, false, func(pi, qi *ir.Node) *ir.Node { // Compare lengths. eqlen, _ := eqstring(pi, qi) return eqlen }) - checkAll(1, true, func(pi, qi *Node) *Node { + checkAll(1, true, func(pi, qi *ir.Node) *ir.Node { // Compare contents. _, eqmem := eqstring(pi, qi) return eqmem }) - case TFLOAT32, TFLOAT64: - checkAll(2, true, func(pi, qi *Node) *Node { + case types.TFLOAT32, types.TFLOAT64: + checkAll(2, true, func(pi, qi *ir.Node) *ir.Node { // p[i] == q[i] - return nod(OEQ, pi, qi) + return ir.Nod(ir.OEQ, pi, qi) }) // TODO: pick apart structs, do them piecemeal too default: - checkAll(1, true, func(pi, qi *Node) *Node { + checkAll(1, true, func(pi, qi *ir.Node) *ir.Node { // p[i] == q[i] - return nod(OEQ, pi, qi) + return ir.Nod(ir.OEQ, pi, qi) }) } - case TSTRUCT: + case types.TSTRUCT: // Build a list of conditions to satisfy. // The conditions are a list-of-lists. Conditions are reorderable // within each inner list. The outer lists must be evaluated in order. - var conds [][]*Node - conds = append(conds, []*Node{}) - and := func(n *Node) { + var conds [][]*ir.Node + conds = append(conds, []*ir.Node{}) + and := func(n *ir.Node) { i := len(conds) - 1 conds[i] = append(conds[i], n) } @@ -669,21 +670,21 @@ func geneq(t *types.Type) *obj.LSym { if !IsRegularMemory(f.Type) { if EqCanPanic(f.Type) { // Enforce ordering by starting a new set of reorderable conditions. - conds = append(conds, []*Node{}) + conds = append(conds, []*ir.Node{}) } - p := nodSym(OXDOT, np, f.Sym) - q := nodSym(OXDOT, nq, f.Sym) + p := nodSym(ir.OXDOT, np, f.Sym) + q := nodSym(ir.OXDOT, nq, f.Sym) switch { case f.Type.IsString(): eqlen, eqmem := eqstring(p, q) and(eqlen) and(eqmem) default: - and(nod(OEQ, p, q)) + and(ir.Nod(ir.OEQ, p, q)) } if EqCanPanic(f.Type) { // Also enforce ordering after something that can panic. - conds = append(conds, []*Node{}) + conds = append(conds, []*ir.Node{}) } i++ continue @@ -708,10 +709,10 @@ func geneq(t *types.Type) *obj.LSym { // Sort conditions to put runtime calls last. // Preserve the rest of the ordering. - var flatConds []*Node + var flatConds []*ir.Node for _, c := range conds { - isCall := func(n *Node) bool { - return n.Op == OCALL || n.Op == OCALLFUNC + isCall := func(n *ir.Node) bool { + return n.Op == ir.OCALL || n.Op == ir.OCALLFUNC } sort.SliceStable(c, func(i, j int) bool { return !isCall(c[i]) && isCall(c[j]) @@ -720,42 +721,42 @@ func geneq(t *types.Type) *obj.LSym { } if len(flatConds) == 0 { - fn.Nbody.Append(nod(OAS, nr, nodbool(true))) + fn.Nbody.Append(ir.Nod(ir.OAS, nr, nodbool(true))) } else { for _, c := range flatConds[:len(flatConds)-1] { // if cond {} else { goto neq } - n := nod(OIF, c, nil) - n.Rlist.Append(nodSym(OGOTO, nil, neq)) + n := ir.Nod(ir.OIF, c, nil) + n.Rlist.Append(nodSym(ir.OGOTO, nil, neq)) fn.Nbody.Append(n) } - fn.Nbody.Append(nod(OAS, nr, flatConds[len(flatConds)-1])) + fn.Nbody.Append(ir.Nod(ir.OAS, nr, flatConds[len(flatConds)-1])) } } // ret: // return ret := autolabel(".ret") - fn.Nbody.Append(nodSym(OLABEL, nil, ret)) - fn.Nbody.Append(nod(ORETURN, nil, nil)) + fn.Nbody.Append(nodSym(ir.OLABEL, nil, ret)) + fn.Nbody.Append(ir.Nod(ir.ORETURN, nil, nil)) // neq: // r = false // return (or goto ret) - fn.Nbody.Append(nodSym(OLABEL, nil, neq)) - fn.Nbody.Append(nod(OAS, nr, nodbool(false))) + fn.Nbody.Append(nodSym(ir.OLABEL, nil, neq)) + fn.Nbody.Append(ir.Nod(ir.OAS, nr, nodbool(false))) if EqCanPanic(t) || hasCall(fn) { // Epilogue is large, so share it with the equal case. - fn.Nbody.Append(nodSym(OGOTO, nil, ret)) + fn.Nbody.Append(nodSym(ir.OGOTO, nil, ret)) } else { // Epilogue is small, so don't bother sharing. - fn.Nbody.Append(nod(ORETURN, nil, nil)) + fn.Nbody.Append(ir.Nod(ir.ORETURN, nil, nil)) } // TODO(khr): the epilogue size detection condition above isn't perfect. // We should really do a generic CL that shares epilogues across // the board. See #24936. if base.Flag.LowerR != 0 { - dumplist("geneq body", fn.Nbody) + ir.DumpList("geneq body", fn.Nbody) } funcbody() @@ -784,8 +785,8 @@ func geneq(t *types.Type) *obj.LSym { return closure } -func hasCall(n *Node) bool { - if n.Op == OCALL || n.Op == OCALLFUNC { +func hasCall(n *ir.Node) bool { + if n.Op == ir.OCALL || n.Op == ir.OCALLFUNC { return true } if n.Left != nil && hasCall(n.Left) { @@ -819,10 +820,10 @@ func hasCall(n *Node) bool { // eqfield returns the node // p.field == q.field -func eqfield(p *Node, q *Node, field *types.Sym) *Node { - nx := nodSym(OXDOT, p, field) - ny := nodSym(OXDOT, q, field) - ne := nod(OEQ, nx, ny) +func eqfield(p *ir.Node, q *ir.Node, field *types.Sym) *ir.Node { + nx := nodSym(ir.OXDOT, p, field) + ny := nodSym(ir.OXDOT, q, field) + ne := ir.Nod(ir.OEQ, nx, ny) return ne } @@ -832,23 +833,23 @@ func eqfield(p *Node, q *Node, field *types.Sym) *Node { // memequal(s.ptr, t.ptr, len(s)) // which can be used to construct string equality comparison. // eqlen must be evaluated before eqmem, and shortcircuiting is required. -func eqstring(s, t *Node) (eqlen, eqmem *Node) { - s = conv(s, types.Types[TSTRING]) - t = conv(t, types.Types[TSTRING]) - sptr := nod(OSPTR, s, nil) - tptr := nod(OSPTR, t, nil) - slen := conv(nod(OLEN, s, nil), types.Types[TUINTPTR]) - tlen := conv(nod(OLEN, t, nil), types.Types[TUINTPTR]) +func eqstring(s, t *ir.Node) (eqlen, eqmem *ir.Node) { + s = conv(s, types.Types[types.TSTRING]) + t = conv(t, types.Types[types.TSTRING]) + sptr := ir.Nod(ir.OSPTR, s, nil) + tptr := ir.Nod(ir.OSPTR, t, nil) + slen := conv(ir.Nod(ir.OLEN, s, nil), types.Types[types.TUINTPTR]) + tlen := conv(ir.Nod(ir.OLEN, t, nil), types.Types[types.TUINTPTR]) fn := syslook("memequal") - fn = substArgTypes(fn, types.Types[TUINT8], types.Types[TUINT8]) - call := nod(OCALL, fn, nil) - call.List.Append(sptr, tptr, slen.copy()) + fn = substArgTypes(fn, types.Types[types.TUINT8], types.Types[types.TUINT8]) + call := ir.Nod(ir.OCALL, fn, nil) + call.List.Append(sptr, tptr, ir.Copy(slen)) call = typecheck(call, ctxExpr|ctxMultiOK) - cmp := nod(OEQ, slen, tlen) + cmp := ir.Nod(ir.OEQ, slen, tlen) cmp = typecheck(cmp, ctxExpr) - cmp.Type = types.Types[TBOOL] + cmp.Type = types.Types[types.TBOOL] return cmp, call } @@ -858,48 +859,48 @@ func eqstring(s, t *Node) (eqlen, eqmem *Node) { // ifaceeq(s.tab, s.data, t.data) (or efaceeq(s.typ, s.data, t.data), as appropriate) // which can be used to construct interface equality comparison. // eqtab must be evaluated before eqdata, and shortcircuiting is required. -func eqinterface(s, t *Node) (eqtab, eqdata *Node) { +func eqinterface(s, t *ir.Node) (eqtab, eqdata *ir.Node) { if !types.Identical(s.Type, t.Type) { base.Fatalf("eqinterface %v %v", s.Type, t.Type) } // func ifaceeq(tab *uintptr, x, y unsafe.Pointer) (ret bool) // func efaceeq(typ *uintptr, x, y unsafe.Pointer) (ret bool) - var fn *Node + var fn *ir.Node if s.Type.IsEmptyInterface() { fn = syslook("efaceeq") } else { fn = syslook("ifaceeq") } - stab := nod(OITAB, s, nil) - ttab := nod(OITAB, t, nil) - sdata := nod(OIDATA, s, nil) - tdata := nod(OIDATA, t, nil) - sdata.Type = types.Types[TUNSAFEPTR] - tdata.Type = types.Types[TUNSAFEPTR] + stab := ir.Nod(ir.OITAB, s, nil) + ttab := ir.Nod(ir.OITAB, t, nil) + sdata := ir.Nod(ir.OIDATA, s, nil) + tdata := ir.Nod(ir.OIDATA, t, nil) + sdata.Type = types.Types[types.TUNSAFEPTR] + tdata.Type = types.Types[types.TUNSAFEPTR] sdata.SetTypecheck(1) tdata.SetTypecheck(1) - call := nod(OCALL, fn, nil) + call := ir.Nod(ir.OCALL, fn, nil) call.List.Append(stab, sdata, tdata) call = typecheck(call, ctxExpr|ctxMultiOK) - cmp := nod(OEQ, stab, ttab) + cmp := ir.Nod(ir.OEQ, stab, ttab) cmp = typecheck(cmp, ctxExpr) - cmp.Type = types.Types[TBOOL] + cmp.Type = types.Types[types.TBOOL] return cmp, call } // eqmem returns the node // memequal(&p.field, &q.field [, size]) -func eqmem(p *Node, q *Node, field *types.Sym, size int64) *Node { - nx := nod(OADDR, nodSym(OXDOT, p, field), nil) - ny := nod(OADDR, nodSym(OXDOT, q, field), nil) +func eqmem(p *ir.Node, q *ir.Node, field *types.Sym, size int64) *ir.Node { + nx := ir.Nod(ir.OADDR, nodSym(ir.OXDOT, p, field), nil) + ny := ir.Nod(ir.OADDR, nodSym(ir.OXDOT, q, field), nil) nx = typecheck(nx, ctxExpr) ny = typecheck(ny, ctxExpr) fn, needsize := eqmemfunc(size, nx.Type.Elem()) - call := nod(OCALL, fn, nil) + call := ir.Nod(ir.OCALL, fn, nil) call.List.Append(nx) call.List.Append(ny) if needsize { @@ -909,7 +910,7 @@ func eqmem(p *Node, q *Node, field *types.Sym, size int64) *Node { return call } -func eqmemfunc(size int64, t *types.Type) (fn *Node, needsize bool) { +func eqmemfunc(size int64, t *types.Type) (fn *ir.Node, needsize bool) { switch size { default: fn = syslook("memequal") diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index a8cbbfd322c..1bc8bf238f7 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -7,6 +7,7 @@ package gc import ( "bytes" "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "fmt" "sort" @@ -117,7 +118,7 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 { o = Rnd(o, int64(f.Type.Align)) } f.Offset = o - if n := asNode(f.Nname); n != nil { + if n := ir.AsNode(f.Nname); n != nil { // addrescapes has similar code to update these offsets. // Usually addrescapes runs after widstruct, // in which case we could drop this, @@ -197,7 +198,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { } *path = append(*path, t) - if p := asNode(t.Nod).Name.Param; p != nil && findTypeLoop(p.Ntype.Type, path) { + if p := ir.AsNode(t.Nod).Name.Param; p != nil && findTypeLoop(p.Ntype.Type, path) { return true } *path = (*path)[:len(*path)-1] @@ -205,17 +206,17 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { // Anonymous type. Recurse on contained types. switch t.Etype { - case TARRAY: + case types.TARRAY: if findTypeLoop(t.Elem(), path) { return true } - case TSTRUCT: + case types.TSTRUCT: for _, f := range t.Fields().Slice() { if findTypeLoop(f.Type, path) { return true } } - case TINTER: + case types.TINTER: for _, m := range t.Methods().Slice() { if m.Type.IsInterface() { // embedded interface if findTypeLoop(m.Type, path) { @@ -306,8 +307,8 @@ func dowidth(t *types.Type) { defercheckwidth() lno := base.Pos - if asNode(t.Nod) != nil { - base.Pos = asNode(t.Nod).Pos + if ir.AsNode(t.Nod) != nil { + base.Pos = ir.AsNode(t.Nod).Pos } t.Width = -2 @@ -315,7 +316,7 @@ func dowidth(t *types.Type) { et := t.Etype switch et { - case TFUNC, TCHAN, TMAP, TSTRING: + case types.TFUNC, types.TCHAN, types.TMAP, types.TSTRING: break // simtype == 0 during bootstrap @@ -331,41 +332,41 @@ func dowidth(t *types.Type) { base.Fatalf("dowidth: unknown type: %v", t) // compiler-specific stuff - case TINT8, TUINT8, TBOOL: + case types.TINT8, types.TUINT8, types.TBOOL: // bool is int8 w = 1 - case TINT16, TUINT16: + case types.TINT16, types.TUINT16: w = 2 - case TINT32, TUINT32, TFLOAT32: + case types.TINT32, types.TUINT32, types.TFLOAT32: w = 4 - case TINT64, TUINT64, TFLOAT64: + case types.TINT64, types.TUINT64, types.TFLOAT64: w = 8 t.Align = uint8(Widthreg) - case TCOMPLEX64: + case types.TCOMPLEX64: w = 8 t.Align = 4 - case TCOMPLEX128: + case types.TCOMPLEX128: w = 16 t.Align = uint8(Widthreg) - case TPTR: + case types.TPTR: w = int64(Widthptr) checkwidth(t.Elem()) - case TUNSAFEPTR: + case types.TUNSAFEPTR: w = int64(Widthptr) - case TINTER: // implemented as 2 pointers + case types.TINTER: // implemented as 2 pointers w = 2 * int64(Widthptr) t.Align = uint8(Widthptr) expandiface(t) - case TCHAN: // implemented as pointer + case types.TCHAN: // implemented as pointer w = int64(Widthptr) checkwidth(t.Elem()) @@ -375,7 +376,7 @@ func dowidth(t *types.Type) { t1 := types.NewChanArgs(t) checkwidth(t1) - case TCHANARGS: + case types.TCHANARGS: t1 := t.ChanArgs() dowidth(t1) // just in case if t1.Elem().Width >= 1<<16 { @@ -383,27 +384,27 @@ func dowidth(t *types.Type) { } w = 1 // anything will do - case TMAP: // implemented as pointer + case types.TMAP: // implemented as pointer w = int64(Widthptr) checkwidth(t.Elem()) checkwidth(t.Key()) - case TFORW: // should have been filled in + case types.TFORW: // should have been filled in reportTypeLoop(t) w = 1 // anything will do - case TANY: + case types.TANY: // not a real type; should be replaced before use. base.Fatalf("dowidth any") - case TSTRING: + case types.TSTRING: if sizeofString == 0 { base.Fatalf("early dowidth string") } w = sizeofString t.Align = uint8(Widthptr) - case TARRAY: + case types.TARRAY: if t.Elem() == nil { break } @@ -418,7 +419,7 @@ func dowidth(t *types.Type) { w = t.NumElem() * t.Elem().Width t.Align = t.Elem().Align - case TSLICE: + case types.TSLICE: if t.Elem() == nil { break } @@ -426,7 +427,7 @@ func dowidth(t *types.Type) { checkwidth(t.Elem()) t.Align = uint8(Widthptr) - case TSTRUCT: + case types.TSTRUCT: if t.IsFuncArgStruct() { base.Fatalf("dowidth fn struct %v", t) } @@ -434,14 +435,14 @@ func dowidth(t *types.Type) { // make fake type to check later to // trigger function argument computation. - case TFUNC: + case types.TFUNC: t1 := types.NewFuncArgs(t) checkwidth(t1) w = int64(Widthptr) // width of func type is pointer // function is 3 cated structures; // compute their widths as side-effect. - case TFUNCARGS: + case types.TFUNCARGS: t1 := t.FuncArgs() w = widstruct(t1, t1.Recvs(), 0, 0) w = widstruct(t1, t1.Params(), w, Widthreg) diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index 6564024a0c8..ff33c6b5fcf 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -5,6 +5,7 @@ package gc import ( + "cmd/compile/internal/ir" "cmd/compile/internal/types" ) @@ -13,8 +14,8 @@ type exporter struct { } // markObject visits a reachable object. -func (p *exporter) markObject(n *Node) { - if n.Op == ONAME && n.Class() == PFUNC { +func (p *exporter) markObject(n *ir.Node) { + if n.Op == ir.ONAME && n.Class() == ir.PFUNC { inlFlood(n) } @@ -34,10 +35,10 @@ func (p *exporter) markType(t *types.Type) { // only their unexpanded method set (i.e., exclusive of // interface embeddings), and the switch statement below // handles their full method set. - if t.Sym != nil && t.Etype != TINTER { + if t.Sym != nil && t.Etype != types.TINTER { for _, m := range t.Methods().Slice() { if types.IsExported(m.Sym.Name) { - p.markObject(asNode(m.Nname)) + p.markObject(ir.AsNode(m.Nname)) } } } @@ -52,31 +53,31 @@ func (p *exporter) markType(t *types.Type) { // the user already needs some way to construct values of // those types. switch t.Etype { - case TPTR, TARRAY, TSLICE: + case types.TPTR, types.TARRAY, types.TSLICE: p.markType(t.Elem()) - case TCHAN: + case types.TCHAN: if t.ChanDir().CanRecv() { p.markType(t.Elem()) } - case TMAP: + case types.TMAP: p.markType(t.Key()) p.markType(t.Elem()) - case TSTRUCT: + case types.TSTRUCT: for _, f := range t.FieldSlice() { if types.IsExported(f.Sym.Name) || f.Embedded != 0 { p.markType(f.Type) } } - case TFUNC: + case types.TFUNC: for _, f := range t.Results().FieldSlice() { p.markType(f.Type) } - case TINTER: + case types.TINTER: for _, f := range t.FieldSlice() { if types.IsExported(f.Sym.Name) { p.markType(f.Type) @@ -133,23 +134,23 @@ func predeclared() []*types.Type { // elements have been initialized before predecl = []*types.Type{ // basic types - types.Types[TBOOL], - types.Types[TINT], - types.Types[TINT8], - types.Types[TINT16], - types.Types[TINT32], - types.Types[TINT64], - types.Types[TUINT], - types.Types[TUINT8], - types.Types[TUINT16], - types.Types[TUINT32], - types.Types[TUINT64], - types.Types[TUINTPTR], - types.Types[TFLOAT32], - types.Types[TFLOAT64], - types.Types[TCOMPLEX64], - types.Types[TCOMPLEX128], - types.Types[TSTRING], + types.Types[types.TBOOL], + types.Types[types.TINT], + types.Types[types.TINT8], + types.Types[types.TINT16], + types.Types[types.TINT32], + types.Types[types.TINT64], + types.Types[types.TUINT], + types.Types[types.TUINT8], + types.Types[types.TUINT16], + types.Types[types.TUINT32], + types.Types[types.TUINT64], + types.Types[types.TUINTPTR], + types.Types[types.TFLOAT32], + types.Types[types.TFLOAT64], + types.Types[types.TCOMPLEX64], + types.Types[types.TCOMPLEX128], + types.Types[types.TSTRING], // basic type aliases types.Bytetype, @@ -165,16 +166,16 @@ func predeclared() []*types.Type { types.UntypedFloat, types.UntypedComplex, types.UntypedString, - types.Types[TNIL], + types.Types[types.TNIL], // package unsafe - types.Types[TUNSAFEPTR], + types.Types[types.TUNSAFEPTR], // invalid type (package contains errors) - types.Types[Txxx], + types.Types[types.Txxx], // any type, for builtin export data - types.Types[TANY], + types.Types[types.TANY], } } return predecl diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go index 911ac4c0dc7..e2dd276f461 100644 --- a/src/cmd/compile/internal/gc/bimport.go +++ b/src/cmd/compile/internal/gc/bimport.go @@ -5,20 +5,15 @@ package gc import ( + "cmd/compile/internal/ir" "cmd/internal/src" ) -// numImport tracks how often a package with a given name is imported. -// It is used to provide a better error message (by using the package -// path to disambiguate) if a package that appears multiple times with -// the same name appears in an error message. -var numImport = make(map[string]int) - -func npos(pos src.XPos, n *Node) *Node { +func npos(pos src.XPos, n *ir.Node) *ir.Node { n.Pos = pos return n } -func builtinCall(op Op) *Node { - return nod(OCALL, mkname(builtinpkg.Lookup(goopnames[op])), nil) +func builtinCall(op ir.Op) *ir.Node { + return ir.Nod(ir.OCALL, mkname(ir.BuiltinPkg.Lookup(ir.OpNames[op])), nil) } diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go index fd95b657b26..5016905f225 100644 --- a/src/cmd/compile/internal/gc/builtin.go +++ b/src/cmd/compile/internal/gc/builtin.go @@ -2,7 +2,10 @@ package gc -import "cmd/compile/internal/types" +import ( + "cmd/compile/internal/ir" + "cmd/compile/internal/types" +) var runtimeDecls = [...]struct { name string @@ -205,134 +208,134 @@ func runtimeTypes() []*types.Type { var typs [131]*types.Type typs[0] = types.Bytetype typs[1] = types.NewPtr(typs[0]) - typs[2] = types.Types[TANY] + typs[2] = types.Types[types.TANY] typs[3] = types.NewPtr(typs[2]) - typs[4] = functype(nil, []*Node{anonfield(typs[1])}, []*Node{anonfield(typs[3])}) - typs[5] = types.Types[TUINTPTR] - typs[6] = types.Types[TBOOL] - typs[7] = types.Types[TUNSAFEPTR] - typs[8] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[1]), anonfield(typs[6])}, []*Node{anonfield(typs[7])}) + typs[4] = functype(nil, []*ir.Node{anonfield(typs[1])}, []*ir.Node{anonfield(typs[3])}) + typs[5] = types.Types[types.TUINTPTR] + typs[6] = types.Types[types.TBOOL] + typs[7] = types.Types[types.TUNSAFEPTR] + typs[8] = functype(nil, []*ir.Node{anonfield(typs[5]), anonfield(typs[1]), anonfield(typs[6])}, []*ir.Node{anonfield(typs[7])}) typs[9] = functype(nil, nil, nil) - typs[10] = types.Types[TINTER] - typs[11] = functype(nil, []*Node{anonfield(typs[10])}, nil) - typs[12] = types.Types[TINT32] + typs[10] = types.Types[types.TINTER] + typs[11] = functype(nil, []*ir.Node{anonfield(typs[10])}, nil) + typs[12] = types.Types[types.TINT32] typs[13] = types.NewPtr(typs[12]) - typs[14] = functype(nil, []*Node{anonfield(typs[13])}, []*Node{anonfield(typs[10])}) - typs[15] = types.Types[TINT] - typs[16] = functype(nil, []*Node{anonfield(typs[15]), anonfield(typs[15])}, nil) - typs[17] = types.Types[TUINT] - typs[18] = functype(nil, []*Node{anonfield(typs[17]), anonfield(typs[15])}, nil) - typs[19] = functype(nil, []*Node{anonfield(typs[6])}, nil) - typs[20] = types.Types[TFLOAT64] - typs[21] = functype(nil, []*Node{anonfield(typs[20])}, nil) - typs[22] = types.Types[TINT64] - typs[23] = functype(nil, []*Node{anonfield(typs[22])}, nil) - typs[24] = types.Types[TUINT64] - typs[25] = functype(nil, []*Node{anonfield(typs[24])}, nil) - typs[26] = types.Types[TCOMPLEX128] - typs[27] = functype(nil, []*Node{anonfield(typs[26])}, nil) - typs[28] = types.Types[TSTRING] - typs[29] = functype(nil, []*Node{anonfield(typs[28])}, nil) - typs[30] = functype(nil, []*Node{anonfield(typs[2])}, nil) - typs[31] = functype(nil, []*Node{anonfield(typs[5])}, nil) + typs[14] = functype(nil, []*ir.Node{anonfield(typs[13])}, []*ir.Node{anonfield(typs[10])}) + typs[15] = types.Types[types.TINT] + typs[16] = functype(nil, []*ir.Node{anonfield(typs[15]), anonfield(typs[15])}, nil) + typs[17] = types.Types[types.TUINT] + typs[18] = functype(nil, []*ir.Node{anonfield(typs[17]), anonfield(typs[15])}, nil) + typs[19] = functype(nil, []*ir.Node{anonfield(typs[6])}, nil) + typs[20] = types.Types[types.TFLOAT64] + typs[21] = functype(nil, []*ir.Node{anonfield(typs[20])}, nil) + typs[22] = types.Types[types.TINT64] + typs[23] = functype(nil, []*ir.Node{anonfield(typs[22])}, nil) + typs[24] = types.Types[types.TUINT64] + typs[25] = functype(nil, []*ir.Node{anonfield(typs[24])}, nil) + typs[26] = types.Types[types.TCOMPLEX128] + typs[27] = functype(nil, []*ir.Node{anonfield(typs[26])}, nil) + typs[28] = types.Types[types.TSTRING] + typs[29] = functype(nil, []*ir.Node{anonfield(typs[28])}, nil) + typs[30] = functype(nil, []*ir.Node{anonfield(typs[2])}, nil) + typs[31] = functype(nil, []*ir.Node{anonfield(typs[5])}, nil) typs[32] = types.NewArray(typs[0], 32) typs[33] = types.NewPtr(typs[32]) - typs[34] = functype(nil, []*Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])}) - typs[35] = functype(nil, []*Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])}) - typs[36] = functype(nil, []*Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])}) - typs[37] = functype(nil, []*Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[28])}) + typs[34] = functype(nil, []*ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Node{anonfield(typs[28])}) + typs[35] = functype(nil, []*ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Node{anonfield(typs[28])}) + typs[36] = functype(nil, []*ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Node{anonfield(typs[28])}) + typs[37] = functype(nil, []*ir.Node{anonfield(typs[33]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28]), anonfield(typs[28])}, []*ir.Node{anonfield(typs[28])}) typs[38] = types.NewSlice(typs[28]) - typs[39] = functype(nil, []*Node{anonfield(typs[33]), anonfield(typs[38])}, []*Node{anonfield(typs[28])}) - typs[40] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[28])}, []*Node{anonfield(typs[15])}) + typs[39] = functype(nil, []*ir.Node{anonfield(typs[33]), anonfield(typs[38])}, []*ir.Node{anonfield(typs[28])}) + typs[40] = functype(nil, []*ir.Node{anonfield(typs[28]), anonfield(typs[28])}, []*ir.Node{anonfield(typs[15])}) typs[41] = types.NewArray(typs[0], 4) typs[42] = types.NewPtr(typs[41]) - typs[43] = functype(nil, []*Node{anonfield(typs[42]), anonfield(typs[22])}, []*Node{anonfield(typs[28])}) - typs[44] = functype(nil, []*Node{anonfield(typs[33]), anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[28])}) - typs[45] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[28])}) + typs[43] = functype(nil, []*ir.Node{anonfield(typs[42]), anonfield(typs[22])}, []*ir.Node{anonfield(typs[28])}) + typs[44] = functype(nil, []*ir.Node{anonfield(typs[33]), anonfield(typs[1]), anonfield(typs[15])}, []*ir.Node{anonfield(typs[28])}) + typs[45] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[15])}, []*ir.Node{anonfield(typs[28])}) typs[46] = types.Runetype typs[47] = types.NewSlice(typs[46]) - typs[48] = functype(nil, []*Node{anonfield(typs[33]), anonfield(typs[47])}, []*Node{anonfield(typs[28])}) + typs[48] = functype(nil, []*ir.Node{anonfield(typs[33]), anonfield(typs[47])}, []*ir.Node{anonfield(typs[28])}) typs[49] = types.NewSlice(typs[0]) - typs[50] = functype(nil, []*Node{anonfield(typs[33]), anonfield(typs[28])}, []*Node{anonfield(typs[49])}) + typs[50] = functype(nil, []*ir.Node{anonfield(typs[33]), anonfield(typs[28])}, []*ir.Node{anonfield(typs[49])}) typs[51] = types.NewArray(typs[46], 32) typs[52] = types.NewPtr(typs[51]) - typs[53] = functype(nil, []*Node{anonfield(typs[52]), anonfield(typs[28])}, []*Node{anonfield(typs[47])}) - typs[54] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []*Node{anonfield(typs[15])}) - typs[55] = functype(nil, []*Node{anonfield(typs[28]), anonfield(typs[15])}, []*Node{anonfield(typs[46]), anonfield(typs[15])}) - typs[56] = functype(nil, []*Node{anonfield(typs[28])}, []*Node{anonfield(typs[15])}) - typs[57] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2])}) - typs[58] = functype(nil, []*Node{anonfield(typs[2])}, []*Node{anonfield(typs[7])}) - typs[59] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, []*Node{anonfield(typs[2])}) - typs[60] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[2])}, []*Node{anonfield(typs[2]), anonfield(typs[6])}) - typs[61] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil) - typs[62] = functype(nil, []*Node{anonfield(typs[1])}, nil) + typs[53] = functype(nil, []*ir.Node{anonfield(typs[52]), anonfield(typs[28])}, []*ir.Node{anonfield(typs[47])}) + typs[54] = functype(nil, []*ir.Node{anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[5])}, []*ir.Node{anonfield(typs[15])}) + typs[55] = functype(nil, []*ir.Node{anonfield(typs[28]), anonfield(typs[15])}, []*ir.Node{anonfield(typs[46]), anonfield(typs[15])}) + typs[56] = functype(nil, []*ir.Node{anonfield(typs[28])}, []*ir.Node{anonfield(typs[15])}) + typs[57] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[2])}, []*ir.Node{anonfield(typs[2])}) + typs[58] = functype(nil, []*ir.Node{anonfield(typs[2])}, []*ir.Node{anonfield(typs[7])}) + typs[59] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[3])}, []*ir.Node{anonfield(typs[2])}) + typs[60] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[2])}, []*ir.Node{anonfield(typs[2]), anonfield(typs[6])}) + typs[61] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[1])}, nil) + typs[62] = functype(nil, []*ir.Node{anonfield(typs[1])}, nil) typs[63] = types.NewPtr(typs[5]) - typs[64] = functype(nil, []*Node{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])}) - typs[65] = types.Types[TUINT32] - typs[66] = functype(nil, nil, []*Node{anonfield(typs[65])}) + typs[64] = functype(nil, []*ir.Node{anonfield(typs[63]), anonfield(typs[7]), anonfield(typs[7])}, []*ir.Node{anonfield(typs[6])}) + typs[65] = types.Types[types.TUINT32] + typs[66] = functype(nil, nil, []*ir.Node{anonfield(typs[65])}) typs[67] = types.NewMap(typs[2], typs[2]) - typs[68] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*Node{anonfield(typs[67])}) - typs[69] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*Node{anonfield(typs[67])}) - typs[70] = functype(nil, nil, []*Node{anonfield(typs[67])}) - typs[71] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3])}) - typs[72] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3])}) - typs[73] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3])}) - typs[74] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*Node{anonfield(typs[3]), anonfield(typs[6])}) - typs[75] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*Node{anonfield(typs[3]), anonfield(typs[6])}) - typs[76] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*Node{anonfield(typs[3]), anonfield(typs[6])}) - typs[77] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil) - typs[78] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil) - typs[79] = functype(nil, []*Node{anonfield(typs[3])}, nil) - typs[80] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[67])}, nil) + typs[68] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[3])}, []*ir.Node{anonfield(typs[67])}) + typs[69] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[3])}, []*ir.Node{anonfield(typs[67])}) + typs[70] = functype(nil, nil, []*ir.Node{anonfield(typs[67])}) + typs[71] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*ir.Node{anonfield(typs[3])}) + typs[72] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*ir.Node{anonfield(typs[3])}) + typs[73] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*ir.Node{anonfield(typs[3])}) + typs[74] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, []*ir.Node{anonfield(typs[3]), anonfield(typs[6])}) + typs[75] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, []*ir.Node{anonfield(typs[3]), anonfield(typs[6])}) + typs[76] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3]), anonfield(typs[1])}, []*ir.Node{anonfield(typs[3]), anonfield(typs[6])}) + typs[77] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[3])}, nil) + typs[78] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[67]), anonfield(typs[2])}, nil) + typs[79] = functype(nil, []*ir.Node{anonfield(typs[3])}, nil) + typs[80] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[67])}, nil) typs[81] = types.NewChan(typs[2], types.Cboth) - typs[82] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22])}, []*Node{anonfield(typs[81])}) - typs[83] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15])}, []*Node{anonfield(typs[81])}) + typs[82] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[22])}, []*ir.Node{anonfield(typs[81])}) + typs[83] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[15])}, []*ir.Node{anonfield(typs[81])}) typs[84] = types.NewChan(typs[2], types.Crecv) - typs[85] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, nil) - typs[86] = functype(nil, []*Node{anonfield(typs[84]), anonfield(typs[3])}, []*Node{anonfield(typs[6])}) + typs[85] = functype(nil, []*ir.Node{anonfield(typs[84]), anonfield(typs[3])}, nil) + typs[86] = functype(nil, []*ir.Node{anonfield(typs[84]), anonfield(typs[3])}, []*ir.Node{anonfield(typs[6])}) typs[87] = types.NewChan(typs[2], types.Csend) - typs[88] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, nil) + typs[88] = functype(nil, []*ir.Node{anonfield(typs[87]), anonfield(typs[3])}, nil) typs[89] = types.NewArray(typs[0], 3) - typs[90] = tostruct([]*Node{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])}) - typs[91] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) - typs[92] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3])}, nil) - typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*Node{anonfield(typs[15])}) - typs[94] = functype(nil, []*Node{anonfield(typs[87]), anonfield(typs[3])}, []*Node{anonfield(typs[6])}) - typs[95] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[84])}, []*Node{anonfield(typs[6])}) + typs[90] = tostruct([]*ir.Node{namedfield("enabled", typs[6]), namedfield("pad", typs[89]), namedfield("needed", typs[6]), namedfield("cgo", typs[6]), namedfield("alignme", typs[24])}) + typs[91] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[3])}, nil) + typs[92] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[3])}, nil) + typs[93] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[3]), anonfield(typs[15]), anonfield(typs[3]), anonfield(typs[15])}, []*ir.Node{anonfield(typs[15])}) + typs[94] = functype(nil, []*ir.Node{anonfield(typs[87]), anonfield(typs[3])}, []*ir.Node{anonfield(typs[6])}) + typs[95] = functype(nil, []*ir.Node{anonfield(typs[3]), anonfield(typs[84])}, []*ir.Node{anonfield(typs[6])}) typs[96] = types.NewPtr(typs[6]) - typs[97] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []*Node{anonfield(typs[6])}) - typs[98] = functype(nil, []*Node{anonfield(typs[63])}, nil) - typs[99] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []*Node{anonfield(typs[15]), anonfield(typs[6])}) - typs[100] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[7])}) - typs[101] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[7])}) - typs[102] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*Node{anonfield(typs[7])}) + typs[97] = functype(nil, []*ir.Node{anonfield(typs[3]), anonfield(typs[96]), anonfield(typs[84])}, []*ir.Node{anonfield(typs[6])}) + typs[98] = functype(nil, []*ir.Node{anonfield(typs[63])}, nil) + typs[99] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[63]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[6])}, []*ir.Node{anonfield(typs[15]), anonfield(typs[6])}) + typs[100] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*ir.Node{anonfield(typs[7])}) + typs[101] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[22]), anonfield(typs[22])}, []*ir.Node{anonfield(typs[7])}) + typs[102] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15]), anonfield(typs[7])}, []*ir.Node{anonfield(typs[7])}) typs[103] = types.NewSlice(typs[2]) - typs[104] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[103]), anonfield(typs[15])}, []*Node{anonfield(typs[103])}) - typs[105] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil) - typs[106] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, nil) - typs[107] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*Node{anonfield(typs[6])}) - typs[108] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3])}, []*Node{anonfield(typs[6])}) - typs[109] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[7])}, []*Node{anonfield(typs[6])}) - typs[110] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*Node{anonfield(typs[5])}) - typs[111] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[5])}, []*Node{anonfield(typs[5])}) - typs[112] = functype(nil, []*Node{anonfield(typs[22]), anonfield(typs[22])}, []*Node{anonfield(typs[22])}) - typs[113] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, []*Node{anonfield(typs[24])}) - typs[114] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[22])}) - typs[115] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[24])}) - typs[116] = functype(nil, []*Node{anonfield(typs[20])}, []*Node{anonfield(typs[65])}) - typs[117] = functype(nil, []*Node{anonfield(typs[22])}, []*Node{anonfield(typs[20])}) - typs[118] = functype(nil, []*Node{anonfield(typs[24])}, []*Node{anonfield(typs[20])}) - typs[119] = functype(nil, []*Node{anonfield(typs[65])}, []*Node{anonfield(typs[20])}) - typs[120] = functype(nil, []*Node{anonfield(typs[26]), anonfield(typs[26])}, []*Node{anonfield(typs[26])}) - typs[121] = functype(nil, []*Node{anonfield(typs[5]), anonfield(typs[5])}, nil) - typs[122] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil) + typs[104] = functype(nil, []*ir.Node{anonfield(typs[1]), anonfield(typs[103]), anonfield(typs[15])}, []*ir.Node{anonfield(typs[103])}) + typs[105] = functype(nil, []*ir.Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, nil) + typs[106] = functype(nil, []*ir.Node{anonfield(typs[7]), anonfield(typs[5])}, nil) + typs[107] = functype(nil, []*ir.Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[5])}, []*ir.Node{anonfield(typs[6])}) + typs[108] = functype(nil, []*ir.Node{anonfield(typs[3]), anonfield(typs[3])}, []*ir.Node{anonfield(typs[6])}) + typs[109] = functype(nil, []*ir.Node{anonfield(typs[7]), anonfield(typs[7])}, []*ir.Node{anonfield(typs[6])}) + typs[110] = functype(nil, []*ir.Node{anonfield(typs[7]), anonfield(typs[5]), anonfield(typs[5])}, []*ir.Node{anonfield(typs[5])}) + typs[111] = functype(nil, []*ir.Node{anonfield(typs[7]), anonfield(typs[5])}, []*ir.Node{anonfield(typs[5])}) + typs[112] = functype(nil, []*ir.Node{anonfield(typs[22]), anonfield(typs[22])}, []*ir.Node{anonfield(typs[22])}) + typs[113] = functype(nil, []*ir.Node{anonfield(typs[24]), anonfield(typs[24])}, []*ir.Node{anonfield(typs[24])}) + typs[114] = functype(nil, []*ir.Node{anonfield(typs[20])}, []*ir.Node{anonfield(typs[22])}) + typs[115] = functype(nil, []*ir.Node{anonfield(typs[20])}, []*ir.Node{anonfield(typs[24])}) + typs[116] = functype(nil, []*ir.Node{anonfield(typs[20])}, []*ir.Node{anonfield(typs[65])}) + typs[117] = functype(nil, []*ir.Node{anonfield(typs[22])}, []*ir.Node{anonfield(typs[20])}) + typs[118] = functype(nil, []*ir.Node{anonfield(typs[24])}, []*ir.Node{anonfield(typs[20])}) + typs[119] = functype(nil, []*ir.Node{anonfield(typs[65])}, []*ir.Node{anonfield(typs[20])}) + typs[120] = functype(nil, []*ir.Node{anonfield(typs[26]), anonfield(typs[26])}, []*ir.Node{anonfield(typs[26])}) + typs[121] = functype(nil, []*ir.Node{anonfield(typs[5]), anonfield(typs[5])}, nil) + typs[122] = functype(nil, []*ir.Node{anonfield(typs[7]), anonfield(typs[1]), anonfield(typs[5])}, nil) typs[123] = types.NewSlice(typs[7]) - typs[124] = functype(nil, []*Node{anonfield(typs[7]), anonfield(typs[123])}, nil) - typs[125] = types.Types[TUINT8] - typs[126] = functype(nil, []*Node{anonfield(typs[125]), anonfield(typs[125])}, nil) - typs[127] = types.Types[TUINT16] - typs[128] = functype(nil, []*Node{anonfield(typs[127]), anonfield(typs[127])}, nil) - typs[129] = functype(nil, []*Node{anonfield(typs[65]), anonfield(typs[65])}, nil) - typs[130] = functype(nil, []*Node{anonfield(typs[24]), anonfield(typs[24])}, nil) + typs[124] = functype(nil, []*ir.Node{anonfield(typs[7]), anonfield(typs[123])}, nil) + typs[125] = types.Types[types.TUINT8] + typs[126] = functype(nil, []*ir.Node{anonfield(typs[125]), anonfield(typs[125])}, nil) + typs[127] = types.Types[types.TUINT16] + typs[128] = functype(nil, []*ir.Node{anonfield(typs[127]), anonfield(typs[127])}, nil) + typs[129] = functype(nil, []*ir.Node{anonfield(typs[65]), anonfield(typs[65])}, nil) + typs[130] = functype(nil, []*ir.Node{anonfield(typs[24]), anonfield(typs[24])}, nil) return typs[:] } diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index ad255c9c06a..e68d7103637 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -6,24 +6,25 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/syntax" "cmd/compile/internal/types" "cmd/internal/src" "fmt" ) -func (p *noder) funcLit(expr *syntax.FuncLit) *Node { +func (p *noder) funcLit(expr *syntax.FuncLit) *ir.Node { xtype := p.typeExpr(expr.Type) ntype := p.typeExpr(expr.Type) - dcl := p.nod(expr, ODCLFUNC, nil, nil) + dcl := p.nod(expr, ir.ODCLFUNC, nil, nil) fn := dcl.Func fn.SetIsHiddenClosure(Curfn != nil) - fn.Nname = newfuncnamel(p.pos(expr), nblank.Sym, fn) // filled in by typecheckclosure + fn.Nname = newfuncnamel(p.pos(expr), ir.BlankNode.Sym, fn) // filled in by typecheckclosure fn.Nname.Name.Param.Ntype = xtype fn.Nname.Name.Defn = dcl - clo := p.nod(expr, OCLOSURE, nil, nil) + clo := p.nod(expr, ir.OCLOSURE, nil, nil) clo.Func = fn fn.ClosureType = ntype fn.OClosure = clo @@ -77,7 +78,7 @@ func (p *noder) funcLit(expr *syntax.FuncLit) *Node { // function associated with the closure. // TODO: This creation of the named function should probably really be done in a // separate pass from type-checking. -func typecheckclosure(clo *Node, top int) { +func typecheckclosure(clo *ir.Node, top int) { fn := clo.Func dcl := fn.Decl // Set current associated iota value, so iota can be used inside @@ -139,7 +140,7 @@ var globClosgen int // closurename generates a new unique name for a closure within // outerfunc. -func closurename(outerfunc *Node) *types.Sym { +func closurename(outerfunc *ir.Node) *types.Sym { outer := "glob." prefix := "func" gen := &globClosgen @@ -149,12 +150,12 @@ func closurename(outerfunc *Node) *types.Sym { prefix = "" } - outer = outerfunc.funcname() + outer = ir.FuncName(outerfunc) // There may be multiple functions named "_". In those // cases, we can't use their individual Closgens as it // would lead to name clashes. - if !outerfunc.Func.Nname.isBlank() { + if !ir.IsBlank(outerfunc.Func.Nname) { gen = &outerfunc.Func.Closgen } } @@ -171,7 +172,7 @@ var capturevarscomplete bool // by value or by reference. // We use value capturing for values <= 128 bytes that are never reassigned // after capturing (effectively constant). -func capturevars(dcl *Node) { +func capturevars(dcl *ir.Node) { lno := base.Pos base.Pos = dcl.Pos fn := dcl.Func @@ -197,11 +198,11 @@ func capturevars(dcl *Node) { outermost := v.Name.Defn // out parameters will be assigned to implicitly upon return. - if outermost.Class() != PPARAMOUT && !outermost.Name.Addrtaken() && !outermost.Name.Assigned() && v.Type.Width <= 128 { + if outermost.Class() != ir.PPARAMOUT && !outermost.Name.Addrtaken() && !outermost.Name.Assigned() && v.Type.Width <= 128 { v.Name.SetByval(true) } else { outermost.Name.SetAddrtaken(true) - outer = nod(OADDR, outer, nil) + outer = ir.Nod(ir.OADDR, outer, nil) } if base.Flag.LowerM > 1 { @@ -226,7 +227,7 @@ func capturevars(dcl *Node) { // transformclosure is called in a separate phase after escape analysis. // It transform closure bodies to properly reference captured variables. -func transformclosure(dcl *Node) { +func transformclosure(dcl *ir.Node) { lno := base.Pos base.Pos = dcl.Pos fn := dcl.Func @@ -252,24 +253,24 @@ func transformclosure(dcl *Node) { // We are going to insert captured variables before input args. var params []*types.Field - var decls []*Node + var decls []*ir.Node for _, v := range fn.ClosureVars.Slice() { if !v.Name.Byval() { // If v of type T is captured by reference, // we introduce function param &v *T // and v remains PAUTOHEAP with &v heapaddr // (accesses will implicitly deref &v). - addr := newname(lookup("&" + v.Sym.Name)) + addr := NewName(lookup("&" + v.Sym.Name)) addr.Type = types.NewPtr(v.Type) v.Name.Param.Heapaddr = addr v = addr } - v.SetClass(PPARAM) + v.SetClass(ir.PPARAM) decls = append(decls, v) fld := types.NewField(src.NoXPos, v.Sym, v.Type) - fld.Nname = asTypesNode(v) + fld.Nname = ir.AsTypesNode(v) params = append(params, fld) } @@ -283,11 +284,11 @@ func transformclosure(dcl *Node) { dcl.Type = f.Type // update type of ODCLFUNC } else { // The closure is not called, so it is going to stay as closure. - var body []*Node + var body []*ir.Node offset := int64(Widthptr) for _, v := range fn.ClosureVars.Slice() { // cv refers to the field inside of closure OSTRUCTLIT. - cv := nod(OCLOSUREVAR, nil, nil) + cv := ir.Nod(ir.OCLOSUREVAR, nil, nil) cv.Type = v.Type if !v.Name.Byval() { @@ -299,23 +300,23 @@ func transformclosure(dcl *Node) { if v.Name.Byval() && v.Type.Width <= int64(2*Widthptr) { // If it is a small variable captured by value, downgrade it to PAUTO. - v.SetClass(PAUTO) + v.SetClass(ir.PAUTO) fn.Dcl = append(fn.Dcl, v) - body = append(body, nod(OAS, v, cv)) + body = append(body, ir.Nod(ir.OAS, v, cv)) } else { // Declare variable holding addresses taken from closure // and initialize in entry prologue. - addr := newname(lookup("&" + v.Sym.Name)) + addr := NewName(lookup("&" + v.Sym.Name)) addr.Type = types.NewPtr(v.Type) - addr.SetClass(PAUTO) + addr.SetClass(ir.PAUTO) addr.Name.SetUsed(true) addr.Name.Curfn = dcl fn.Dcl = append(fn.Dcl, addr) v.Name.Param.Heapaddr = addr if v.Name.Byval() { - cv = nod(OADDR, cv, nil) + cv = ir.Nod(ir.OADDR, cv, nil) } - body = append(body, nod(OAS, addr, cv)) + body = append(body, ir.Nod(ir.OAS, addr, cv)) } } @@ -331,13 +332,13 @@ func transformclosure(dcl *Node) { // hasemptycvars reports whether closure clo has an // empty list of captured vars. -func hasemptycvars(clo *Node) bool { +func hasemptycvars(clo *ir.Node) bool { return clo.Func.ClosureVars.Len() == 0 } // closuredebugruntimecheck applies boilerplate checks for debug flags // and compiling runtime -func closuredebugruntimecheck(clo *Node) { +func closuredebugruntimecheck(clo *ir.Node) { if base.Debug.Closure > 0 { if clo.Esc == EscHeap { base.WarnfAt(clo.Pos, "heap closure, captured vars = %v", clo.Func.ClosureVars) @@ -353,7 +354,7 @@ func closuredebugruntimecheck(clo *Node) { // closureType returns the struct type used to hold all the information // needed in the closure for clo (clo must be a OCLOSURE node). // The address of a variable of the returned type can be cast to a func. -func closureType(clo *Node) *types.Type { +func closureType(clo *ir.Node) *types.Type { // Create closure in the form of a composite literal. // supposing the closure captures an int i and a string s // and has one float64 argument and no results, @@ -367,8 +368,8 @@ func closureType(clo *Node) *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 := []*Node{ - namedfield(".F", types.Types[TUINTPTR]), + fields := []*ir.Node{ + namedfield(".F", types.Types[types.TUINTPTR]), } for _, v := range clo.Func.ClosureVars.Slice() { typ := v.Type @@ -382,7 +383,7 @@ func closureType(clo *Node) *types.Type { return typ } -func walkclosure(clo *Node, init *Nodes) *Node { +func walkclosure(clo *ir.Node, init *ir.Nodes) *ir.Node { fn := clo.Func // If no closure vars, don't bother wrapping. @@ -396,11 +397,11 @@ func walkclosure(clo *Node, init *Nodes) *Node { typ := closureType(clo) - clos := nod(OCOMPLIT, nil, typenod(typ)) + clos := ir.Nod(ir.OCOMPLIT, nil, typenod(typ)) clos.Esc = clo.Esc - clos.List.Set(append([]*Node{nod(OCFUNC, fn.Nname, nil)}, fn.ClosureEnter.Slice()...)) + clos.List.Set(append([]*ir.Node{ir.Nod(ir.OCFUNC, fn.Nname, nil)}, fn.ClosureEnter.Slice()...)) - clos = nod(OADDR, clos, nil) + clos = ir.Nod(ir.OADDR, clos, nil) clos.Esc = clo.Esc // Force type conversion from *struct to the func type. @@ -418,9 +419,9 @@ func walkclosure(clo *Node, init *Nodes) *Node { return walkexpr(clos, init) } -func typecheckpartialcall(dot *Node, sym *types.Sym) { +func typecheckpartialcall(dot *ir.Node, sym *types.Sym) { switch dot.Op { - case ODOTINTER, ODOTMETH: + case ir.ODOTINTER, ir.ODOTMETH: break default: @@ -430,8 +431,8 @@ func typecheckpartialcall(dot *Node, sym *types.Sym) { // Create top-level function. dcl := makepartialcall(dot, dot.Type, sym) dcl.Func.SetWrapper(true) - dot.Op = OCALLPART - dot.Right = newname(sym) + dot.Op = ir.OCALLPART + dot.Right = NewName(sym) dot.Type = dcl.Type dot.Func = dcl.Func dot.SetOpt(nil) // clear types.Field from ODOTMETH @@ -439,12 +440,12 @@ func typecheckpartialcall(dot *Node, sym *types.Sym) { // makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed // for partial calls. -func makepartialcall(dot *Node, t0 *types.Type, meth *types.Sym) *Node { +func makepartialcall(dot *ir.Node, t0 *types.Type, meth *types.Sym) *ir.Node { rcvrtype := dot.Left.Type sym := methodSymSuffix(rcvrtype, meth, "-fm") if sym.Uniq() { - return asNode(sym.Def) + return ir.AsNode(sym.Def) } sym.SetUniq(true) @@ -463,7 +464,7 @@ func makepartialcall(dot *Node, t0 *types.Type, meth *types.Sym) *Node { // number at the use of the method expression in this // case. See issue 29389. - tfn := nod(OTFUNC, nil, nil) + tfn := ir.Nod(ir.OTFUNC, nil, nil) tfn.List.Set(structargs(t0.Params(), true)) tfn.Rlist.Set(structargs(t0.Results(), false)) @@ -476,27 +477,27 @@ func makepartialcall(dot *Node, t0 *types.Type, meth *types.Sym) *Node { // Declare and initialize variable holding receiver. - cv := nod(OCLOSUREVAR, nil, nil) + cv := ir.Nod(ir.OCLOSUREVAR, nil, nil) cv.Type = rcvrtype cv.Xoffset = Rnd(int64(Widthptr), int64(cv.Type.Align)) - ptr := newname(lookup(".this")) - declare(ptr, PAUTO) + ptr := NewName(lookup(".this")) + declare(ptr, ir.PAUTO) ptr.Name.SetUsed(true) - var body []*Node + var body []*ir.Node if rcvrtype.IsPtr() || rcvrtype.IsInterface() { ptr.Type = rcvrtype - body = append(body, nod(OAS, ptr, cv)) + body = append(body, ir.Nod(ir.OAS, ptr, cv)) } else { ptr.Type = types.NewPtr(rcvrtype) - body = append(body, nod(OAS, ptr, nod(OADDR, cv, nil))) + body = append(body, ir.Nod(ir.OAS, ptr, ir.Nod(ir.OADDR, cv, nil))) } - call := nod(OCALL, nodSym(OXDOT, ptr, meth), nil) + call := ir.Nod(ir.OCALL, nodSym(ir.OXDOT, ptr, meth), nil) call.List.Set(paramNnames(tfn.Type)) call.SetIsDDD(tfn.Type.IsVariadic()) if t0.NumResults() != 0 { - n := nod(ORETURN, nil, nil) + n := ir.Nod(ir.ORETURN, nil, nil) n.List.Set1(call) call = n } @@ -510,7 +511,7 @@ func makepartialcall(dot *Node, t0 *types.Type, meth *types.Sym) *Node { // typecheckslice() requires that Curfn is set when processing an ORETURN. Curfn = dcl typecheckslice(dcl.Nbody.Slice(), ctxStmt) - sym.Def = asTypesNode(dcl) + sym.Def = ir.AsTypesNode(dcl) xtop = append(xtop, dcl) Curfn = savecurfn base.Pos = saveLineNo @@ -521,16 +522,16 @@ func makepartialcall(dot *Node, t0 *types.Type, meth *types.Sym) *Node { // partialCallType returns the struct type used to hold all the information // 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 *Node) *types.Type { - t := tostruct([]*Node{ - namedfield("F", types.Types[TUINTPTR]), +func partialCallType(n *ir.Node) *types.Type { + t := tostruct([]*ir.Node{ + namedfield("F", types.Types[types.TUINTPTR]), namedfield("R", n.Left.Type), }) t.SetNoalg(true) return t } -func walkpartialcall(n *Node, init *Nodes) *Node { +func walkpartialcall(n *ir.Node, init *ir.Nodes) *ir.Node { // Create closure in the form of a composite literal. // For x.M with receiver (x) type T, the generated code looks like: // @@ -544,21 +545,21 @@ func walkpartialcall(n *Node, init *Nodes) *Node { n.Left = cheapexpr(n.Left, init) n.Left = walkexpr(n.Left, nil) - tab := nod(OITAB, n.Left, nil) + tab := ir.Nod(ir.OITAB, n.Left, nil) tab = typecheck(tab, ctxExpr) - c := nod(OCHECKNIL, tab, nil) + c := ir.Nod(ir.OCHECKNIL, tab, nil) c.SetTypecheck(1) init.Append(c) } typ := partialCallType(n) - clos := nod(OCOMPLIT, nil, typenod(typ)) + clos := ir.Nod(ir.OCOMPLIT, nil, typenod(typ)) clos.Esc = n.Esc - clos.List.Set2(nod(OCFUNC, n.Func.Nname, nil), n.Left) + clos.List.Set2(ir.Nod(ir.OCFUNC, n.Func.Nname, nil), n.Left) - clos = nod(OADDR, clos, nil) + clos = ir.Nod(ir.OADDR, clos, nil) clos.Esc = n.Esc // Force type conversion from *struct to the func type. @@ -578,8 +579,8 @@ func walkpartialcall(n *Node, init *Nodes) *Node { // callpartMethod returns the *types.Field representing the method // referenced by method value n. -func callpartMethod(n *Node) *types.Field { - if n.Op != OCALLPART { +func callpartMethod(n *ir.Node) *types.Field { + if n.Op != ir.OCALLPART { base.Fatalf("expected OCALLPART, got %v", n) } diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 98473b4cfb0..a557e20d46b 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/src" "fmt" @@ -23,51 +24,6 @@ const ( Mpprec = 512 ) -// ValueInterface returns the constant value stored in n as an interface{}. -// It returns int64s for ints and runes, float64s for floats, -// and complex128s for complex values. -func (n *Node) ValueInterface() interface{} { - switch v := n.Val(); v.Kind() { - default: - base.Fatalf("unexpected constant: %v", v) - panic("unreachable") - case constant.Bool: - return constant.BoolVal(v) - case constant.String: - return constant.StringVal(v) - case constant.Int: - return int64Val(n.Type, v) - case constant.Float: - return float64Val(v) - case constant.Complex: - return complex(float64Val(constant.Real(v)), float64Val(constant.Imag(v))) - } -} - -// int64Val returns v converted to int64. -// Note: if t is uint64, very large values will be converted to negative int64. -func int64Val(t *types.Type, v constant.Value) int64 { - if t.IsUnsigned() { - if x, ok := constant.Uint64Val(v); ok { - return int64(x) - } - } else { - if x, ok := constant.Int64Val(v); ok { - return x - } - } - base.Fatalf("%v out of range for %v", v, t) - panic("unreachable") -} - -func float64Val(v constant.Value) float64 { - if x, _ := constant.Float64Val(v); !math.IsInf(x, 0) { - return x + 0 // avoid -0 (should not be needed, but be conservative) - } - base.Fatalf("bad float64 value: %v", v) - panic("unreachable") -} - func bigFloatVal(v constant.Value) *big.Float { f := new(big.Float) f.SetPrec(Mpprec) @@ -86,62 +42,6 @@ func bigFloatVal(v constant.Value) *big.Float { return f } -// Int64Val returns n as an int64. -// n must be an integer or rune constant. -func (n *Node) Int64Val() int64 { - if !Isconst(n, constant.Int) { - base.Fatalf("Int64Val(%v)", n) - } - x, ok := constant.Int64Val(n.Val()) - if !ok { - base.Fatalf("Int64Val(%v)", n) - } - return x -} - -// CanInt64 reports whether it is safe to call Int64Val() on n. -func (n *Node) CanInt64() bool { - if !Isconst(n, constant.Int) { - return false - } - - // if the value inside n cannot be represented as an int64, the - // return value of Int64 is undefined - _, ok := constant.Int64Val(n.Val()) - return ok -} - -// Uint64Val returns n as an uint64. -// n must be an integer or rune constant. -func (n *Node) Uint64Val() uint64 { - if !Isconst(n, constant.Int) { - base.Fatalf("Uint64Val(%v)", n) - } - x, ok := constant.Uint64Val(n.Val()) - if !ok { - base.Fatalf("Uint64Val(%v)", n) - } - return x -} - -// BoolVal returns n as a bool. -// n must be a boolean constant. -func (n *Node) BoolVal() bool { - if !Isconst(n, constant.Bool) { - base.Fatalf("BoolVal(%v)", n) - } - return constant.BoolVal(n.Val()) -} - -// StringVal returns the value of a literal string Node as a string. -// n must be a string constant. -func (n *Node) StringVal() string { - if !Isconst(n, constant.String) { - base.Fatalf("StringVal(%v)", n) - } - return constant.StringVal(n.Val()) -} - func roundFloat(v constant.Value, sz int64) constant.Value { switch sz { case 4: @@ -184,8 +84,8 @@ func trunccmplxlit(v constant.Value, t *types.Type) constant.Value { } // TODO(mdempsky): Replace these with better APIs. -func convlit(n *Node, t *types.Type) *Node { return convlit1(n, t, false, nil) } -func defaultlit(n *Node, t *types.Type) *Node { return convlit1(n, t, false, nil) } +func convlit(n *ir.Node, t *types.Type) *ir.Node { return convlit1(n, t, false, nil) } +func defaultlit(n *ir.Node, t *types.Type) *ir.Node { return convlit1(n, t, false, nil) } // convlit1 converts an untyped expression n to type t. If n already // has a type, convlit1 has no effect. @@ -198,7 +98,7 @@ func defaultlit(n *Node, t *types.Type) *Node { return convlit1(n, t, false, nil // // If there's an error converting n to t, context is used in the error // message. -func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Node { +func convlit1(n *ir.Node, t *types.Type, explicit bool, context func() string) *ir.Node { if explicit && t == nil { base.Fatalf("explicit conversion missing type") } @@ -215,15 +115,15 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod return n } - if n.Op == OLITERAL || n.Op == ONIL { + if n.Op == ir.OLITERAL || n.Op == ir.ONIL { // Can't always set n.Type directly on OLITERAL nodes. // See discussion on CL 20813. - n = n.rawcopy() + n = n.RawCopy() } // Nil is technically not a constant, so handle it specially. - if n.Type.Etype == TNIL { - if n.Op != ONIL { + if n.Type.Etype == types.TNIL { + if n.Op != ir.ONIL { base.Fatalf("unexpected op: %v (%v)", n, n.Op) } if t == nil { @@ -242,7 +142,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod return n } - if t == nil || !okforconst[t.Etype] { + if t == nil || !ir.OKForConst[t.Etype] { t = defaultType(n.Type) } @@ -250,7 +150,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod default: base.Fatalf("unexpected untyped expression: %v", n) - case OLITERAL: + case ir.OLITERAL: v := convertVal(n.Val(), t, explicit) if v.Kind() == constant.Unknown { break @@ -259,7 +159,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod n.SetVal(v) return n - case OPLUS, ONEG, OBITNOT, ONOT, OREAL, OIMAG: + case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.OREAL, ir.OIMAG: ot := operandType(n.Op, t) if ot == nil { n = defaultlit(n, nil) @@ -274,7 +174,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod n.Type = t return n - case OADD, OSUB, OMUL, ODIV, OMOD, OOR, OXOR, OAND, OANDNOT, OOROR, OANDAND, OCOMPLEX: + case ir.OADD, ir.OSUB, ir.OMUL, ir.ODIV, ir.OMOD, ir.OOR, ir.OXOR, ir.OAND, ir.OANDNOT, ir.OOROR, ir.OANDAND, ir.OCOMPLEX: ot := operandType(n.Op, t) if ot == nil { n = defaultlit(n, nil) @@ -296,14 +196,14 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod n.Type = t return n - case OEQ, ONE, OLT, OLE, OGT, OGE: + case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: if !t.IsBoolean() { break } n.Type = t return n - case OLSH, ORSH: + case ir.OLSH, ir.ORSH: n.Left = convlit1(n.Left, t, explicit, nil) n.Type = n.Left.Type if n.Type != nil && !n.Type.IsInteger() { @@ -329,13 +229,13 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod return n } -func operandType(op Op, t *types.Type) *types.Type { +func operandType(op ir.Op, t *types.Type) *types.Type { switch op { - case OCOMPLEX: + case ir.OCOMPLEX: if t.IsComplex() { return floatForComplex(t) } - case OREAL, OIMAG: + case ir.OREAL, ir.OIMAG: if t.IsFloat() { return complexForFloat(t) } @@ -488,7 +388,7 @@ func overflow(v constant.Value, t *types.Type) bool { return true } if doesoverflow(v, t) { - base.Errorf("constant %v overflows %v", vconv(v, 0), t) + base.Errorf("constant %v overflows %v", ir.FmtConst(v, 0), t) return true } return false @@ -505,57 +405,46 @@ func tostr(v constant.Value) constant.Value { return v } -func consttype(n *Node) constant.Kind { - if n == nil || n.Op != OLITERAL { - return constant.Unknown - } - return n.Val().Kind() -} - -func Isconst(n *Node, ct constant.Kind) bool { - return consttype(n) == ct -} - var tokenForOp = [...]token.Token{ - OPLUS: token.ADD, - ONEG: token.SUB, - ONOT: token.NOT, - OBITNOT: token.XOR, + ir.OPLUS: token.ADD, + ir.ONEG: token.SUB, + ir.ONOT: token.NOT, + ir.OBITNOT: token.XOR, - OADD: token.ADD, - OSUB: token.SUB, - OMUL: token.MUL, - ODIV: token.QUO, - OMOD: token.REM, - OOR: token.OR, - OXOR: token.XOR, - OAND: token.AND, - OANDNOT: token.AND_NOT, - OOROR: token.LOR, - OANDAND: token.LAND, + ir.OADD: token.ADD, + ir.OSUB: token.SUB, + ir.OMUL: token.MUL, + ir.ODIV: token.QUO, + ir.OMOD: token.REM, + ir.OOR: token.OR, + ir.OXOR: token.XOR, + ir.OAND: token.AND, + ir.OANDNOT: token.AND_NOT, + ir.OOROR: token.LOR, + ir.OANDAND: token.LAND, - OEQ: token.EQL, - ONE: token.NEQ, - OLT: token.LSS, - OLE: token.LEQ, - OGT: token.GTR, - OGE: token.GEQ, + ir.OEQ: token.EQL, + ir.ONE: token.NEQ, + ir.OLT: token.LSS, + ir.OLE: token.LEQ, + ir.OGT: token.GTR, + ir.OGE: token.GEQ, - OLSH: token.SHL, - ORSH: token.SHR, + ir.OLSH: token.SHL, + ir.ORSH: token.SHR, } // evalConst returns a constant-evaluated expression equivalent to n. // If n is not a constant, evalConst returns n. // Otherwise, evalConst returns a new OLITERAL with the same value as n, // and with .Orig pointing back to n. -func evalConst(n *Node) *Node { +func evalConst(n *ir.Node) *ir.Node { nl, nr := n.Left, n.Right // Pick off just the opcodes that can be constant evaluated. switch op := n.Op; op { - case OPLUS, ONEG, OBITNOT, ONOT: - if nl.Op == OLITERAL { + case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT: + if nl.Op == ir.OLITERAL { var prec uint if n.Type.IsUnsigned() { prec = uint(n.Type.Size() * 8) @@ -563,36 +452,36 @@ func evalConst(n *Node) *Node { return origConst(n, constant.UnaryOp(tokenForOp[op], nl.Val(), prec)) } - case OADD, OSUB, OMUL, ODIV, OMOD, OOR, OXOR, OAND, OANDNOT, OOROR, OANDAND: - if nl.Op == OLITERAL && nr.Op == OLITERAL { + case ir.OADD, ir.OSUB, ir.OMUL, ir.ODIV, ir.OMOD, ir.OOR, ir.OXOR, ir.OAND, ir.OANDNOT, ir.OOROR, ir.OANDAND: + if nl.Op == ir.OLITERAL && nr.Op == ir.OLITERAL { rval := nr.Val() // check for divisor underflow in complex division (see issue 20227) - if op == ODIV && n.Type.IsComplex() && constant.Sign(square(constant.Real(rval))) == 0 && constant.Sign(square(constant.Imag(rval))) == 0 { + if op == ir.ODIV && n.Type.IsComplex() && constant.Sign(square(constant.Real(rval))) == 0 && constant.Sign(square(constant.Imag(rval))) == 0 { base.Errorf("complex division by zero") n.Type = nil return n } - if (op == ODIV || op == OMOD) && constant.Sign(rval) == 0 { + if (op == ir.ODIV || op == ir.OMOD) && constant.Sign(rval) == 0 { base.Errorf("division by zero") n.Type = nil return n } tok := tokenForOp[op] - if op == ODIV && n.Type.IsInteger() { + if op == ir.ODIV && n.Type.IsInteger() { tok = token.QUO_ASSIGN // integer division } return origConst(n, constant.BinaryOp(nl.Val(), tok, rval)) } - case OEQ, ONE, OLT, OLE, OGT, OGE: - if nl.Op == OLITERAL && nr.Op == OLITERAL { + case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: + if nl.Op == ir.OLITERAL && nr.Op == ir.OLITERAL { return origBoolConst(n, constant.Compare(nl.Val(), tokenForOp[op], nr.Val())) } - case OLSH, ORSH: - if nl.Op == OLITERAL && nr.Op == OLITERAL { + case ir.OLSH, ir.ORSH: + if nl.Op == ir.OLITERAL && nr.Op == ir.OLITERAL { // shiftBound from go/types; "so we can express smallestFloat64" const shiftBound = 1023 - 1 + 52 s, ok := constant.Uint64Val(nr.Val()) @@ -604,24 +493,24 @@ func evalConst(n *Node) *Node { return origConst(n, constant.Shift(toint(nl.Val()), tokenForOp[op], uint(s))) } - case OCONV, ORUNESTR: - if okforconst[n.Type.Etype] && nl.Op == OLITERAL { + case ir.OCONV, ir.ORUNESTR: + if ir.OKForConst[n.Type.Etype] && nl.Op == ir.OLITERAL { return origConst(n, convertVal(nl.Val(), n.Type, true)) } - case OCONVNOP: - if okforconst[n.Type.Etype] && nl.Op == OLITERAL { + case ir.OCONVNOP: + if ir.OKForConst[n.Type.Etype] && nl.Op == ir.OLITERAL { // set so n.Orig gets OCONV instead of OCONVNOP - n.Op = OCONV + n.Op = ir.OCONV return origConst(n, nl.Val()) } - case OADDSTR: + case ir.OADDSTR: // Merge adjacent constants in the argument list. s := n.List.Slice() need := 0 for i := 0; i < len(s); i++ { - if i == 0 || !Isconst(s[i-1], constant.String) || !Isconst(s[i], constant.String) { + if i == 0 || !ir.IsConst(s[i-1], constant.String) || !ir.IsConst(s[i], constant.String) { // Can't merge s[i] into s[i-1]; need a slot in the list. need++ } @@ -636,13 +525,13 @@ func evalConst(n *Node) *Node { } return origConst(n, constant.MakeString(strings.Join(strs, ""))) } - newList := make([]*Node, 0, need) + newList := make([]*ir.Node, 0, need) for i := 0; i < len(s); i++ { - if Isconst(s[i], constant.String) && i+1 < len(s) && Isconst(s[i+1], constant.String) { + if ir.IsConst(s[i], constant.String) && i+1 < len(s) && ir.IsConst(s[i+1], constant.String) { // merge from i up to but not including i2 var strs []string i2 := i - for i2 < len(s) && Isconst(s[i2], constant.String) { + for i2 < len(s) && ir.IsConst(s[i2], constant.String) { strs = append(strs, s[i2].StringVal()) i2++ } @@ -656,37 +545,37 @@ func evalConst(n *Node) *Node { } } - n = n.copy() + n = ir.Copy(n) n.List.Set(newList) return n - case OCAP, OLEN: + case ir.OCAP, ir.OLEN: switch nl.Type.Etype { - case TSTRING: - if Isconst(nl, constant.String) { + case types.TSTRING: + if ir.IsConst(nl, constant.String) { return origIntConst(n, int64(len(nl.StringVal()))) } - case TARRAY: + case types.TARRAY: if !hascallchan(nl) { return origIntConst(n, nl.Type.NumElem()) } } - case OALIGNOF, OOFFSETOF, OSIZEOF: + case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: return origIntConst(n, evalunsafe(n)) - case OREAL: - if nl.Op == OLITERAL { + case ir.OREAL: + if nl.Op == ir.OLITERAL { return origConst(n, constant.Real(nl.Val())) } - case OIMAG: - if nl.Op == OLITERAL { + case ir.OIMAG: + if nl.Op == ir.OLITERAL { return origConst(n, constant.Imag(nl.Val())) } - case OCOMPLEX: - if nl.Op == OLITERAL && nr.Op == OLITERAL { + case ir.OCOMPLEX: + if nl.Op == ir.OLITERAL && nr.Op == ir.OLITERAL { return origConst(n, makeComplex(nl.Val(), nr.Val())) } } @@ -721,16 +610,16 @@ func square(x constant.Value) constant.Value { // For matching historical "constant OP overflow" error messages. // TODO(mdempsky): Replace with error messages like go/types uses. var overflowNames = [...]string{ - OADD: "addition", - OSUB: "subtraction", - OMUL: "multiplication", - OLSH: "shift", - OXOR: "bitwise XOR", - OBITNOT: "bitwise complement", + ir.OADD: "addition", + ir.OSUB: "subtraction", + ir.OMUL: "multiplication", + ir.OLSH: "shift", + ir.OXOR: "bitwise XOR", + ir.OBITNOT: "bitwise complement", } // origConst returns an OLITERAL with orig n and value v. -func origConst(n *Node, v constant.Value) *Node { +func origConst(n *ir.Node, v constant.Value) *ir.Node { lno := setlineno(n) v = convertVal(v, n.Type, false) base.Pos = lno @@ -752,81 +641,28 @@ func origConst(n *Node, v constant.Value) *Node { } orig := n - n = nodl(orig.Pos, OLITERAL, nil, nil) + n = ir.NodAt(orig.Pos, ir.OLITERAL, nil, nil) n.Orig = orig n.Type = orig.Type n.SetVal(v) return n } -func assertRepresents(t *types.Type, v constant.Value) { - if !represents(t, v) { - base.Fatalf("%v does not represent %v", t, v) - } -} - -func represents(t *types.Type, v constant.Value) bool { - switch v.Kind() { - case constant.Unknown: - return okforconst[t.Etype] - case constant.Bool: - return t.IsBoolean() - case constant.String: - return t.IsString() - case constant.Int: - return t.IsInteger() - case constant.Float: - return t.IsFloat() - case constant.Complex: - return t.IsComplex() - } - - base.Fatalf("unexpected constant kind: %v", v) - panic("unreachable") -} - -func origBoolConst(n *Node, v bool) *Node { +func origBoolConst(n *ir.Node, v bool) *ir.Node { return origConst(n, constant.MakeBool(v)) } -func origIntConst(n *Node, v int64) *Node { +func origIntConst(n *ir.Node, v int64) *ir.Node { return origConst(n, constant.MakeInt64(v)) } -// nodlit returns a new untyped constant with value v. -func nodlit(v constant.Value) *Node { - n := nod(OLITERAL, nil, nil) - if k := v.Kind(); k != constant.Unknown { - n.Type = idealType(k) - n.SetVal(v) - } - return n -} - -func idealType(ct constant.Kind) *types.Type { - switch ct { - case constant.String: - return types.UntypedString - case constant.Bool: - return types.UntypedBool - case constant.Int: - return types.UntypedInt - case constant.Float: - return types.UntypedFloat - case constant.Complex: - return types.UntypedComplex - } - base.Fatalf("unexpected Ctype: %v", ct) - return nil -} - // defaultlit on both nodes simultaneously; // if they're both ideal going in they better // get the same type going out. // force means must assign concrete (non-ideal) type. // The results of defaultlit2 MUST be assigned back to l and r, e.g. // n.Left, n.Right = defaultlit2(n.Left, n.Right, force) -func defaultlit2(l *Node, r *Node, force bool) (*Node, *Node) { +func defaultlit2(l *ir.Node, r *ir.Node, force bool) (*ir.Node, *ir.Node) { if l.Type == nil || r.Type == nil { return l, r } @@ -851,7 +687,7 @@ func defaultlit2(l *Node, r *Node, force bool) (*Node, *Node) { if l.Type.IsString() != r.Type.IsString() { return l, r } - if l.isNil() || r.isNil() { + if ir.IsNil(l) || ir.IsNil(r) { return l, r } @@ -888,31 +724,31 @@ func mixUntyped(t1, t2 *types.Type) *types.Type { } func defaultType(t *types.Type) *types.Type { - if !t.IsUntyped() || t.Etype == TNIL { + if !t.IsUntyped() || t.Etype == types.TNIL { return t } switch t { case types.UntypedBool: - return types.Types[TBOOL] + return types.Types[types.TBOOL] case types.UntypedString: - return types.Types[TSTRING] + return types.Types[types.TSTRING] case types.UntypedInt: - return types.Types[TINT] + return types.Types[types.TINT] case types.UntypedRune: return types.Runetype case types.UntypedFloat: - return types.Types[TFLOAT64] + return types.Types[types.TFLOAT64] case types.UntypedComplex: - return types.Types[TCOMPLEX128] + return types.Types[types.TCOMPLEX128] } base.Fatalf("bad type %v", t) return nil } -func smallintconst(n *Node) bool { - if n.Op == OLITERAL { +func smallintconst(n *ir.Node) bool { + if n.Op == ir.OLITERAL { v, ok := constant.Int64Val(n.Val()) return ok && int64(int32(v)) == v } @@ -924,11 +760,11 @@ func smallintconst(n *Node) bool { // If n is not a constant expression, not representable as an // integer, or negative, it returns -1. If n is too large, it // returns -2. -func indexconst(n *Node) int64 { - if n.Op != OLITERAL { +func indexconst(n *ir.Node) int64 { + if n.Op != ir.OLITERAL { return -1 } - if !n.Type.IsInteger() && n.Type.Etype != TIDEAL { + if !n.Type.IsInteger() && n.Type.Etype != types.TIDEAL { return -1 } @@ -936,10 +772,10 @@ func indexconst(n *Node) int64 { if v.Kind() != constant.Int || constant.Sign(v) < 0 { return -1 } - if doesoverflow(v, types.Types[TINT]) { + if doesoverflow(v, types.Types[types.TINT]) { return -2 } - return int64Val(types.Types[TINT], v) + return ir.Int64Val(types.Types[types.TINT], v) } // isGoConst reports whether n is a Go language constant (as opposed to a @@ -947,35 +783,35 @@ func indexconst(n *Node) int64 { // // Expressions derived from nil, like string([]byte(nil)), while they // may be known at compile time, are not Go language constants. -func (n *Node) isGoConst() bool { - return n.Op == OLITERAL +func isGoConst(n *ir.Node) bool { + return n.Op == ir.OLITERAL } -func hascallchan(n *Node) bool { +func hascallchan(n *ir.Node) bool { if n == nil { return false } switch n.Op { - case OAPPEND, - OCALL, - OCALLFUNC, - OCALLINTER, - OCALLMETH, - OCAP, - OCLOSE, - OCOMPLEX, - OCOPY, - ODELETE, - OIMAG, - OLEN, - OMAKE, - ONEW, - OPANIC, - OPRINT, - OPRINTN, - OREAL, - ORECOVER, - ORECV: + case ir.OAPPEND, + ir.OCALL, + ir.OCALLFUNC, + ir.OCALLINTER, + ir.OCALLMETH, + ir.OCAP, + ir.OCLOSE, + ir.OCOMPLEX, + ir.OCOPY, + ir.ODELETE, + ir.OIMAG, + ir.OLEN, + ir.OMAKE, + ir.ONEW, + ir.OPANIC, + ir.OPRINT, + ir.OPRINTN, + ir.OREAL, + ir.ORECOVER, + ir.ORECV: return true } @@ -1015,12 +851,12 @@ type constSetKey struct { // where are used in the error message. // // n must not be an untyped constant. -func (s *constSet) add(pos src.XPos, n *Node, what, where string) { - if n.Op == OCONVIFACE && n.Implicit() { +func (s *constSet) add(pos src.XPos, n *ir.Node, what, where string) { + if n.Op == ir.OCONVIFACE && n.Implicit() { n = n.Left } - if !n.isGoConst() { + if !isGoConst(n) { return } if n.Type.IsUntyped() { @@ -1045,11 +881,11 @@ func (s *constSet) add(pos src.XPos, n *Node, what, where string) { typ := n.Type switch typ { case types.Bytetype: - typ = types.Types[TUINT8] + typ = types.Types[types.TUINT8] case types.Runetype: - typ = types.Types[TINT32] + typ = types.Types[types.TINT32] } - k := constSetKey{typ, n.ValueInterface()} + k := constSetKey{typ, ir.ConstValue(n)} if hasUniquePos(n) { pos = n.Pos @@ -1072,9 +908,9 @@ func (s *constSet) add(pos src.XPos, n *Node, what, where string) { // the latter is non-obvious. // // TODO(mdempsky): This could probably be a fmt.go flag. -func nodeAndVal(n *Node) string { +func nodeAndVal(n *ir.Node) string { show := n.String() - val := n.ValueInterface() + val := ir.ConstValue(n) if s := fmt.Sprintf("%#v", val); show != s { show += " (value " + s + ")" } diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 63a52a9f364..6fee872fd2d 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -7,6 +7,7 @@ package gc import ( "bytes" "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/src" @@ -17,7 +18,7 @@ import ( // Declaration stack & operations -var externdcl []*Node +var externdcl []*ir.Node func testdclstack() { if !types.IsDclstackValid() { @@ -58,25 +59,25 @@ var declare_typegen int // declare records that Node n declares symbol n.Sym in the specified // declaration context. -func declare(n *Node, ctxt Class) { - if n.isBlank() { +func declare(n *ir.Node, ctxt ir.Class) { + if ir.IsBlank(n) { return } if n.Name == nil { // named OLITERAL needs Name; most OLITERALs don't. - n.Name = new(Name) + n.Name = new(ir.Name) } s := n.Sym // kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later. - if !inimport && !typecheckok && s.Pkg != localpkg { + if !inimport && !typecheckok && s.Pkg != ir.LocalPkg { base.ErrorfAt(n.Pos, "cannot declare name %v", s) } gen := 0 - if ctxt == PEXTERN { + if ctxt == ir.PEXTERN { if s.Name == "init" { base.ErrorfAt(n.Pos, "cannot declare init - must be func") } @@ -85,17 +86,17 @@ func declare(n *Node, ctxt Class) { } externdcl = append(externdcl, n) } else { - if Curfn == nil && ctxt == PAUTO { + if Curfn == nil && ctxt == ir.PAUTO { base.Pos = n.Pos base.Fatalf("automatic outside function") } - if Curfn != nil && ctxt != PFUNC { + if Curfn != nil && ctxt != ir.PFUNC { Curfn.Func.Dcl = append(Curfn.Func.Dcl, n) } - if n.Op == OTYPE { + if n.Op == ir.OTYPE { declare_typegen++ gen = declare_typegen - } else if n.Op == ONAME && ctxt == PAUTO && !strings.Contains(s.Name, "·") { + } else if n.Op == ir.ONAME && ctxt == ir.PAUTO && !strings.Contains(s.Name, "·") { vargen++ gen = vargen } @@ -103,58 +104,58 @@ func declare(n *Node, ctxt Class) { n.Name.Curfn = Curfn } - if ctxt == PAUTO { + if ctxt == ir.PAUTO { n.Xoffset = 0 } if s.Block == types.Block { // functype will print errors about duplicate function arguments. // Don't repeat the error here. - if ctxt != PPARAM && ctxt != PPARAMOUT { + if ctxt != ir.PPARAM && ctxt != ir.PPARAMOUT { redeclare(n.Pos, s, "in this block") } } s.Block = types.Block s.Lastlineno = base.Pos - s.Def = asTypesNode(n) + s.Def = ir.AsTypesNode(n) n.Name.Vargen = int32(gen) n.SetClass(ctxt) - if ctxt == PFUNC { + if ctxt == ir.PFUNC { n.Sym.SetFunc(true) } autoexport(n, ctxt) } -func addvar(n *Node, t *types.Type, ctxt Class) { - if n == nil || n.Sym == nil || (n.Op != ONAME && n.Op != ONONAME) || t == nil { +func addvar(n *ir.Node, t *types.Type, ctxt ir.Class) { + if n == nil || n.Sym == nil || (n.Op != ir.ONAME && n.Op != ir.ONONAME) || t == nil { base.Fatalf("addvar: n=%v t=%v nil", n, t) } - n.Op = ONAME + n.Op = ir.ONAME declare(n, ctxt) n.Type = t } // declare variables from grammar // new_name_list (type | [type] = expr_list) -func variter(vl []*Node, t *Node, el []*Node) []*Node { - var init []*Node +func variter(vl []*ir.Node, t *ir.Node, el []*ir.Node) []*ir.Node { + var init []*ir.Node doexpr := len(el) > 0 if len(el) == 1 && len(vl) > 1 { e := el[0] - as2 := nod(OAS2, nil, nil) + as2 := ir.Nod(ir.OAS2, nil, nil) as2.List.Set(vl) as2.Rlist.Set1(e) for _, v := range vl { - v.Op = ONAME + v.Op = ir.ONAME declare(v, dclcontext) v.Name.Param.Ntype = t v.Name.Defn = as2 if Curfn != nil { - init = append(init, nod(ODCL, v, nil)) + init = append(init, ir.Nod(ir.ODCL, v, nil)) } } @@ -163,7 +164,7 @@ func variter(vl []*Node, t *Node, el []*Node) []*Node { nel := len(el) for _, v := range vl { - var e *Node + var e *ir.Node if doexpr { if len(el) == 0 { base.Errorf("assignment mismatch: %d variables but %d values", len(vl), nel) @@ -173,15 +174,15 @@ func variter(vl []*Node, t *Node, el []*Node) []*Node { el = el[1:] } - v.Op = ONAME + v.Op = ir.ONAME declare(v, dclcontext) v.Name.Param.Ntype = t - if e != nil || Curfn != nil || v.isBlank() { + if e != nil || Curfn != nil || ir.IsBlank(v) { if Curfn != nil { - init = append(init, nod(ODCL, v, nil)) + init = append(init, ir.Nod(ir.ODCL, v, nil)) } - e = nod(OAS, v, e) + e = ir.Nod(ir.OAS, v, e) init = append(init, e) if e.Right != nil { v.Name.Defn = e @@ -196,22 +197,22 @@ func variter(vl []*Node, t *Node, el []*Node) []*Node { } // newnoname returns a new ONONAME Node associated with symbol s. -func newnoname(s *types.Sym) *Node { +func newnoname(s *types.Sym) *ir.Node { if s == nil { base.Fatalf("newnoname nil") } - n := nod(ONONAME, nil, nil) + n := ir.Nod(ir.ONONAME, nil, nil) n.Sym = s n.Xoffset = 0 return n } // newfuncnamel generates a new name node for a function or method. -func newfuncnamel(pos src.XPos, s *types.Sym, fn *Func) *Node { +func newfuncnamel(pos src.XPos, s *types.Sym, fn *ir.Func) *ir.Node { if fn.Nname != nil { base.Fatalf("newfuncnamel - already have name") } - n := newnamel(pos, s) + n := ir.NewNameAt(pos, s) n.Func = fn fn.Nname = n return n @@ -219,39 +220,39 @@ func newfuncnamel(pos src.XPos, s *types.Sym, fn *Func) *Node { // this generates a new name node for a name // being declared. -func dclname(s *types.Sym) *Node { - n := newname(s) - n.Op = ONONAME // caller will correct it +func dclname(s *types.Sym) *ir.Node { + n := NewName(s) + n.Op = ir.ONONAME // caller will correct it return n } -func typenod(t *types.Type) *Node { +func typenod(t *types.Type) *ir.Node { return typenodl(src.NoXPos, t) } -func typenodl(pos src.XPos, t *types.Type) *Node { +func typenodl(pos src.XPos, t *types.Type) *ir.Node { // if we copied another type with *t = *u // then t->nod might be out of date, so // check t->nod->type too - if asNode(t.Nod) == nil || asNode(t.Nod).Type != t { - t.Nod = asTypesNode(nodl(pos, OTYPE, nil, nil)) - asNode(t.Nod).Type = t - asNode(t.Nod).Sym = t.Sym + if ir.AsNode(t.Nod) == nil || ir.AsNode(t.Nod).Type != t { + t.Nod = ir.AsTypesNode(ir.NodAt(pos, ir.OTYPE, nil, nil)) + ir.AsNode(t.Nod).Type = t + ir.AsNode(t.Nod).Sym = t.Sym } - return asNode(t.Nod) + return ir.AsNode(t.Nod) } -func anonfield(typ *types.Type) *Node { +func anonfield(typ *types.Type) *ir.Node { return symfield(nil, typ) } -func namedfield(s string, typ *types.Type) *Node { +func namedfield(s string, typ *types.Type) *ir.Node { return symfield(lookup(s), typ) } -func symfield(s *types.Sym, typ *types.Type) *Node { - n := nodSym(ODCLFIELD, nil, s) +func symfield(s *types.Sym, typ *types.Type) *ir.Node { + n := nodSym(ir.ODCLFIELD, nil, s) n.Type = typ return n } @@ -260,8 +261,8 @@ func symfield(s *types.Sym, typ *types.Type) *Node { // If no such Node currently exists, an ONONAME Node is returned instead. // Automatically creates a new closure variable if the referenced symbol was // declared in a different (containing) function. -func oldname(s *types.Sym) *Node { - n := asNode(s.Def) +func oldname(s *types.Sym) *ir.Node { + n := ir.AsNode(s.Def) if n == nil { // Maybe a top-level declaration will come along later to // define s. resolve will check s.Def again once all input @@ -269,7 +270,7 @@ func oldname(s *types.Sym) *Node { return newnoname(s) } - if Curfn != nil && n.Op == ONAME && n.Name.Curfn != nil && n.Name.Curfn != Curfn { + if Curfn != nil && n.Op == ir.ONAME && n.Name.Curfn != nil && n.Name.Curfn != Curfn { // Inner func is referring to var in outer func. // // TODO(rsc): If there is an outer variable x and we @@ -279,8 +280,8 @@ func oldname(s *types.Sym) *Node { c := n.Name.Param.Innermost if c == nil || c.Name.Curfn != Curfn { // Do not have a closure var for the active closure yet; make one. - c = newname(s) - c.SetClass(PAUTOHEAP) + c = NewName(s) + c.SetClass(ir.PAUTOHEAP) c.Name.SetIsClosureVar(true) c.SetIsDDD(n.IsDDD()) c.Name.Defn = n @@ -301,9 +302,9 @@ func oldname(s *types.Sym) *Node { } // importName is like oldname, but it reports an error if sym is from another package and not exported. -func importName(sym *types.Sym) *Node { +func importName(sym *types.Sym) *ir.Node { n := oldname(sym) - if !types.IsExported(sym.Name) && sym.Pkg != localpkg { + if !types.IsExported(sym.Name) && sym.Pkg != ir.LocalPkg { n.SetDiag(true) base.Errorf("cannot refer to unexported name %s.%s", sym.Pkg.Name, sym.Name) } @@ -311,20 +312,20 @@ func importName(sym *types.Sym) *Node { } // := declarations -func colasname(n *Node) bool { +func colasname(n *ir.Node) bool { switch n.Op { - case ONAME, - ONONAME, - OPACK, - OTYPE, - OLITERAL: + case ir.ONAME, + ir.ONONAME, + ir.OPACK, + ir.OTYPE, + ir.OLITERAL: return n.Sym != nil } return false } -func colasdefn(left []*Node, defn *Node) { +func colasdefn(left []*ir.Node, defn *ir.Node) { for _, n := range left { if n.Sym != nil { n.Sym.SetUniq(true) @@ -333,7 +334,7 @@ func colasdefn(left []*Node, defn *Node) { var nnew, nerr int for i, n := range left { - if n.isBlank() { + if ir.IsBlank(n) { continue } if !colasname(n) { @@ -355,10 +356,10 @@ func colasdefn(left []*Node, defn *Node) { } nnew++ - n = newname(n.Sym) + n = NewName(n.Sym) declare(n, dclcontext) n.Name.Defn = defn - defn.Ninit.Append(nod(ODCL, n, nil)) + defn.Ninit.Append(ir.Nod(ir.ODCL, n, nil)) left[i] = n } @@ -369,8 +370,8 @@ func colasdefn(left []*Node, defn *Node) { // declare the arguments in an // interface field declaration. -func ifacedcl(n *Node) { - if n.Op != ODCLFIELD || n.Left == nil { +func ifacedcl(n *ir.Node) { + if n.Op != ir.ODCLFIELD || n.Left == nil { base.Fatalf("ifacedcl") } @@ -383,11 +384,11 @@ func ifacedcl(n *Node) { // and declare the arguments. // called in extern-declaration context // returns in auto-declaration context. -func funchdr(n *Node) { +func funchdr(n *ir.Node) { // change the declaration context from extern to auto funcStack = append(funcStack, funcStackEnt{Curfn, dclcontext}) Curfn = n - dclcontext = PAUTO + dclcontext = ir.PAUTO types.Markdcl() @@ -398,8 +399,8 @@ func funchdr(n *Node) { } } -func funcargs(nt *Node) { - if nt.Op != OTFUNC { +func funcargs(nt *ir.Node) { + if nt.Op != ir.OTFUNC { base.Fatalf("funcargs %v", nt.Op) } @@ -414,10 +415,10 @@ func funcargs(nt *Node) { // declare the receiver and in arguments. if nt.Left != nil { - funcarg(nt.Left, PPARAM) + funcarg(nt.Left, ir.PPARAM) } for _, n := range nt.List.Slice() { - funcarg(n, PPARAM) + funcarg(n, ir.PPARAM) } oldvargen := vargen @@ -442,21 +443,21 @@ func funcargs(nt *Node) { gen++ } - funcarg(n, PPARAMOUT) + funcarg(n, ir.PPARAMOUT) } vargen = oldvargen } -func funcarg(n *Node, ctxt Class) { - if n.Op != ODCLFIELD { +func funcarg(n *ir.Node, ctxt ir.Class) { + if n.Op != ir.ODCLFIELD { base.Fatalf("funcarg %v", n.Op) } if n.Sym == nil { return } - n.Right = newnamel(n.Pos, n.Sym) + n.Right = ir.NewNameAt(n.Pos, n.Sym) n.Right.Name.Param.Ntype = n.Left n.Right.SetIsDDD(n.IsDDD()) declare(n.Right, ctxt) @@ -469,27 +470,27 @@ func funcarg(n *Node, ctxt Class) { // This happens during import, where the hidden_fndcl rule has // used functype directly to parse the function's type. func funcargs2(t *types.Type) { - if t.Etype != TFUNC { + if t.Etype != types.TFUNC { base.Fatalf("funcargs2 %v", t) } for _, f := range t.Recvs().Fields().Slice() { - funcarg2(f, PPARAM) + funcarg2(f, ir.PPARAM) } for _, f := range t.Params().Fields().Slice() { - funcarg2(f, PPARAM) + funcarg2(f, ir.PPARAM) } for _, f := range t.Results().Fields().Slice() { - funcarg2(f, PPARAMOUT) + funcarg2(f, ir.PPARAMOUT) } } -func funcarg2(f *types.Field, ctxt Class) { +func funcarg2(f *types.Field, ctxt ir.Class) { if f.Sym == nil { return } - n := newnamel(f.Pos, f.Sym) - f.Nname = asTypesNode(n) + n := ir.NewNameAt(f.Pos, f.Sym) + f.Nname = ir.AsTypesNode(n) n.Type = f.Type n.SetIsDDD(f.IsDDD()) declare(n, ctxt) @@ -498,8 +499,8 @@ func funcarg2(f *types.Field, ctxt Class) { var funcStack []funcStackEnt // stack of previous values of Curfn/dclcontext type funcStackEnt struct { - curfn *Node - dclcontext Class + curfn *ir.Node + dclcontext ir.Class } // finish the body. @@ -529,16 +530,16 @@ func checkembeddedtype(t *types.Type) { if t.IsPtr() || t.IsUnsafePtr() { base.Errorf("embedded type cannot be a pointer") - } else if t.Etype == TFORW && !t.ForwardType().Embedlineno.IsKnown() { + } else if t.Etype == types.TFORW && !t.ForwardType().Embedlineno.IsKnown() { t.ForwardType().Embedlineno = base.Pos } } -func structfield(n *Node) *types.Field { +func structfield(n *ir.Node) *types.Field { lno := base.Pos base.Pos = n.Pos - if n.Op != ODCLFIELD { + if n.Op != ir.ODCLFIELD { base.Fatalf("structfield: oops %v\n", n) } @@ -581,8 +582,8 @@ func checkdupfields(what string, fss ...[]*types.Field) { // convert a parsed id/type list into // a type for struct/interface/arglist -func tostruct(l []*Node) *types.Type { - t := types.New(TSTRUCT) +func tostruct(l []*ir.Node) *types.Type { + t := types.New(types.TSTRUCT) fields := make([]*types.Field, len(l)) for i, n := range l { @@ -603,8 +604,8 @@ func tostruct(l []*Node) *types.Type { return t } -func tofunargs(l []*Node, funarg types.Funarg) *types.Type { - t := types.New(TSTRUCT) +func tofunargs(l []*ir.Node, funarg types.Funarg) *types.Type { + t := types.New(types.TSTRUCT) t.StructType().Funarg = funarg fields := make([]*types.Field, len(l)) @@ -613,7 +614,7 @@ func tofunargs(l []*Node, funarg types.Funarg) *types.Type { f.SetIsDDD(n.IsDDD()) if n.Right != nil { n.Right.Type = f.Type - f.Nname = asTypesNode(n.Right) + f.Nname = ir.AsTypesNode(n.Right) } if f.Broke() { t.SetBroke(true) @@ -625,17 +626,17 @@ func tofunargs(l []*Node, funarg types.Funarg) *types.Type { } func tofunargsfield(fields []*types.Field, funarg types.Funarg) *types.Type { - t := types.New(TSTRUCT) + t := types.New(types.TSTRUCT) t.StructType().Funarg = funarg t.SetFields(fields) return t } -func interfacefield(n *Node) *types.Field { +func interfacefield(n *ir.Node) *types.Field { lno := base.Pos base.Pos = n.Pos - if n.Op != ODCLFIELD { + if n.Op != ir.ODCLFIELD { base.Fatalf("interfacefield: oops %v\n", n) } @@ -660,11 +661,11 @@ func interfacefield(n *Node) *types.Field { return f } -func tointerface(l []*Node) *types.Type { +func tointerface(l []*ir.Node) *types.Type { if len(l) == 0 { - return types.Types[TINTER] + return types.Types[types.TINTER] } - t := types.New(TINTER) + t := types.New(types.TINTER) var fields []*types.Field for _, n := range l { f := interfacefield(n) @@ -677,7 +678,7 @@ func tointerface(l []*Node) *types.Type { return t } -func fakeRecv() *Node { +func fakeRecv() *ir.Node { return anonfield(types.FakeRecvType()) } @@ -693,12 +694,12 @@ func isifacemethod(f *types.Type) bool { } // turn a parsed function declaration into a type -func functype(this *Node, in, out []*Node) *types.Type { - t := types.New(TFUNC) +func functype(this *ir.Node, in, out []*ir.Node) *types.Type { + t := types.New(types.TFUNC) - var rcvr []*Node + var rcvr []*ir.Node if this != nil { - rcvr = []*Node{this} + rcvr = []*ir.Node{this} } t.FuncType().Receiver = tofunargs(rcvr, types.FunargRcvr) t.FuncType().Params = tofunargs(in, types.FunargParams) @@ -710,13 +711,13 @@ func functype(this *Node, in, out []*Node) *types.Type { t.SetBroke(true) } - t.FuncType().Outnamed = t.NumResults() > 0 && origSym(t.Results().Field(0).Sym) != nil + t.FuncType().Outnamed = t.NumResults() > 0 && ir.OrigSym(t.Results().Field(0).Sym) != nil return t } func functypefield(this *types.Field, in, out []*types.Field) *types.Type { - t := types.New(TFUNC) + t := types.New(types.TFUNC) var rcvr []*types.Field if this != nil { @@ -726,36 +727,11 @@ func functypefield(this *types.Field, in, out []*types.Field) *types.Type { t.FuncType().Params = tofunargsfield(in, types.FunargParams) t.FuncType().Results = tofunargsfield(out, types.FunargResults) - t.FuncType().Outnamed = t.NumResults() > 0 && origSym(t.Results().Field(0).Sym) != nil + t.FuncType().Outnamed = t.NumResults() > 0 && ir.OrigSym(t.Results().Field(0).Sym) != nil return t } -// origSym returns the original symbol written by the user. -func origSym(s *types.Sym) *types.Sym { - if s == nil { - return nil - } - - if len(s.Name) > 1 && s.Name[0] == '~' { - switch s.Name[1] { - case 'r': // originally an unnamed result - return nil - case 'b': // originally the blank identifier _ - // TODO(mdempsky): Does s.Pkg matter here? - return nblank.Sym - } - return s - } - - if strings.HasPrefix(s.Name, ".anon") { - // originally an unnamed or _ name (see subr.go: structargs) - return nil - } - - return s -} - // methodSym returns the method symbol representing a method name // associated with a specific receiver type. // @@ -823,7 +799,7 @@ func methodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy // - msym is the method symbol // - t is function type (with receiver) // Returns a pointer to the existing or added Field; or nil if there's an error. -func addmethod(n *Node, msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field { +func addmethod(n *ir.Node, msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field { if msym == nil { base.Fatalf("no method symbol") } @@ -864,7 +840,7 @@ func addmethod(n *Node, msym *types.Sym, t *types.Type, local, nointerface bool) return nil } - if local && mt.Sym.Pkg != localpkg { + if local && mt.Sym.Pkg != ir.LocalPkg { base.Errorf("cannot define new methods on non-local type %v", mt) return nil } @@ -896,7 +872,7 @@ func addmethod(n *Node, msym *types.Sym, t *types.Type, local, nointerface bool) } f := types.NewField(base.Pos, msym, t) - f.Nname = asTypesNode(n.Func.Nname) + f.Nname = ir.AsTypesNode(n.Func.Nname) f.SetNointerface(nointerface) mt.Methods().Append(f) @@ -959,21 +935,21 @@ func makefuncsym(s *types.Sym) { } // setNodeNameFunc marks a node as a function. -func setNodeNameFunc(n *Node) { - if n.Op != ONAME || n.Class() != Pxxx { +func setNodeNameFunc(n *ir.Node) { + if n.Op != ir.ONAME || n.Class() != ir.Pxxx { base.Fatalf("expected ONAME/Pxxx node, got %v", n) } - n.SetClass(PFUNC) + n.SetClass(ir.PFUNC) n.Sym.SetFunc(true) } -func dclfunc(sym *types.Sym, tfn *Node) *Node { - if tfn.Op != OTFUNC { +func dclfunc(sym *types.Sym, tfn *ir.Node) *ir.Node { + if tfn.Op != ir.OTFUNC { base.Fatalf("expected OTFUNC node, got %v", tfn) } - fn := nod(ODCLFUNC, nil, nil) + fn := ir.Nod(ir.ODCLFUNC, nil, nil) fn.Func.Nname = newfuncnamel(base.Pos, sym, fn.Func) fn.Func.Nname.Name.Defn = fn fn.Func.Nname.Name.Param.Ntype = tfn @@ -987,27 +963,22 @@ type nowritebarrierrecChecker struct { // extraCalls contains extra function calls that may not be // visible during later analysis. It maps from the ODCLFUNC of // the caller to a list of callees. - extraCalls map[*Node][]nowritebarrierrecCall + extraCalls map[*ir.Node][]nowritebarrierrecCall // curfn is the current function during AST walks. - curfn *Node + curfn *ir.Node } type nowritebarrierrecCall struct { - target *Node // ODCLFUNC of caller or callee + target *ir.Node // ODCLFUNC of caller or callee lineno src.XPos // line of call } -type nowritebarrierrecCallSym struct { - target *obj.LSym // LSym of callee - lineno src.XPos // line of call -} - // newNowritebarrierrecChecker creates a nowritebarrierrecChecker. It // must be called before transformclosure and walk. func newNowritebarrierrecChecker() *nowritebarrierrecChecker { c := &nowritebarrierrecChecker{ - extraCalls: make(map[*Node][]nowritebarrierrecCall), + extraCalls: make(map[*ir.Node][]nowritebarrierrecCall), } // Find all systemstack calls and record their targets. In @@ -1016,39 +987,39 @@ func newNowritebarrierrecChecker() *nowritebarrierrecChecker { // directly. This has to happen before transformclosure since // it's a lot harder to work out the argument after. for _, n := range xtop { - if n.Op != ODCLFUNC { + if n.Op != ir.ODCLFUNC { continue } c.curfn = n - inspect(n, c.findExtraCalls) + ir.Inspect(n, c.findExtraCalls) } c.curfn = nil return c } -func (c *nowritebarrierrecChecker) findExtraCalls(n *Node) bool { - if n.Op != OCALLFUNC { +func (c *nowritebarrierrecChecker) findExtraCalls(n *ir.Node) bool { + if n.Op != ir.OCALLFUNC { return true } fn := n.Left - if fn == nil || fn.Op != ONAME || fn.Class() != PFUNC || fn.Name.Defn == nil { + if fn == nil || fn.Op != ir.ONAME || fn.Class() != ir.PFUNC || fn.Name.Defn == nil { return true } if !isRuntimePkg(fn.Sym.Pkg) || fn.Sym.Name != "systemstack" { return true } - var callee *Node + var callee *ir.Node arg := n.List.First() switch arg.Op { - case ONAME: + case ir.ONAME: callee = arg.Name.Defn - case OCLOSURE: + case ir.OCLOSURE: callee = arg.Func.Decl default: base.Fatalf("expected ONAME or OCLOSURE node, got %+v", arg) } - if callee.Op != ODCLFUNC { + if callee.Op != ir.ODCLFUNC { base.Fatalf("expected ODCLFUNC node, got %+v", callee) } c.extraCalls[c.curfn] = append(c.extraCalls[c.curfn], nowritebarrierrecCall{callee, n.Pos}) @@ -1063,17 +1034,17 @@ func (c *nowritebarrierrecChecker) findExtraCalls(n *Node) bool { // because that's all we know after we start SSA. // // This can be called concurrently for different from Nodes. -func (c *nowritebarrierrecChecker) recordCall(from *Node, to *obj.LSym, pos src.XPos) { - if from.Op != ODCLFUNC { +func (c *nowritebarrierrecChecker) recordCall(from *ir.Node, to *obj.LSym, pos src.XPos) { + if from.Op != ir.ODCLFUNC { base.Fatalf("expected ODCLFUNC, got %v", from) } // We record this information on the *Func so this is // concurrent-safe. fn := from.Func - if fn.nwbrCalls == nil { - fn.nwbrCalls = new([]nowritebarrierrecCallSym) + if fn.NWBRCalls == nil { + fn.NWBRCalls = new([]ir.SymAndPos) } - *fn.nwbrCalls = append(*fn.nwbrCalls, nowritebarrierrecCallSym{to, pos}) + *fn.NWBRCalls = append(*fn.NWBRCalls, ir.SymAndPos{Sym: to, Pos: pos}) } func (c *nowritebarrierrecChecker) check() { @@ -1081,39 +1052,39 @@ func (c *nowritebarrierrecChecker) check() { // capture all calls created by lowering, but this means we // only get to see the obj.LSyms of calls. symToFunc lets us // get back to the ODCLFUNCs. - symToFunc := make(map[*obj.LSym]*Node) + symToFunc := make(map[*obj.LSym]*ir.Node) // funcs records the back-edges of the BFS call graph walk. It // maps from the ODCLFUNC of each function that must not have // write barriers to the call that inhibits them. Functions // that are directly marked go:nowritebarrierrec are in this // map with a zero-valued nowritebarrierrecCall. This also // acts as the set of marks for the BFS of the call graph. - funcs := make(map[*Node]nowritebarrierrecCall) + funcs := make(map[*ir.Node]nowritebarrierrecCall) // q is the queue of ODCLFUNC Nodes to visit in BFS order. - var q nodeQueue + var q ir.NodeQueue for _, n := range xtop { - if n.Op != ODCLFUNC { + if n.Op != ir.ODCLFUNC { continue } - symToFunc[n.Func.lsym] = n + symToFunc[n.Func.LSym] = n // Make nowritebarrierrec functions BFS roots. - if n.Func.Pragma&Nowritebarrierrec != 0 { + if n.Func.Pragma&ir.Nowritebarrierrec != 0 { funcs[n] = nowritebarrierrecCall{} - q.pushRight(n) + q.PushRight(n) } // Check go:nowritebarrier functions. - if n.Func.Pragma&Nowritebarrier != 0 && n.Func.WBPos.IsKnown() { + if n.Func.Pragma&ir.Nowritebarrier != 0 && n.Func.WBPos.IsKnown() { base.ErrorfAt(n.Func.WBPos, "write barrier prohibited") } } // Perform a BFS of the call graph from all // go:nowritebarrierrec functions. - enqueue := func(src, target *Node, pos src.XPos) { - if target.Func.Pragma&Yeswritebarrierrec != 0 { + enqueue := func(src, target *ir.Node, pos src.XPos) { + if target.Func.Pragma&ir.Yeswritebarrierrec != 0 { // Don't flow into this function. return } @@ -1124,10 +1095,10 @@ func (c *nowritebarrierrecChecker) check() { // Record the path. funcs[target] = nowritebarrierrecCall{target: src, lineno: pos} - q.pushRight(target) + q.PushRight(target) } - for !q.empty() { - fn := q.popLeft() + for !q.Empty() { + fn := q.PopLeft() // Check fn. if fn.Func.WBPos.IsKnown() { @@ -1145,13 +1116,13 @@ func (c *nowritebarrierrecChecker) check() { for _, callee := range c.extraCalls[fn] { enqueue(fn, callee.target, callee.lineno) } - if fn.Func.nwbrCalls == nil { + if fn.Func.NWBRCalls == nil { continue } - for _, callee := range *fn.Func.nwbrCalls { - target := symToFunc[callee.target] + for _, callee := range *fn.Func.NWBRCalls { + target := symToFunc[callee.Sym] if target != nil { - enqueue(fn, target, callee.lineno) + enqueue(fn, target, callee.Pos) } } } diff --git a/src/cmd/compile/internal/gc/embed.go b/src/cmd/compile/internal/gc/embed.go index f6c1b7cdccf..636aa4a70ed 100644 --- a/src/cmd/compile/internal/gc/embed.go +++ b/src/cmd/compile/internal/gc/embed.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/syntax" "cmd/compile/internal/types" "cmd/internal/obj" @@ -16,7 +17,7 @@ import ( "strings" ) -var embedlist []*Node +var embedlist []*ir.Node const ( embedUnknown = iota @@ -27,7 +28,7 @@ const ( var numLocalEmbed int -func varEmbed(p *noder, names []*Node, typ *Node, exprs []*Node, embeds []PragmaEmbed) (newExprs []*Node) { +func varEmbed(p *noder, names []*ir.Node, typ *ir.Node, exprs []*ir.Node, embeds []PragmaEmbed) (newExprs []*ir.Node) { haveEmbed := false for _, decl := range p.file.DeclList { imp, ok := decl.(*syntax.ImportDecl) @@ -110,14 +111,14 @@ func varEmbed(p *noder, names []*Node, typ *Node, exprs []*Node, embeds []Pragma } v := names[0] - if dclcontext != PEXTERN { + if dclcontext != ir.PEXTERN { numLocalEmbed++ - v = newnamel(v.Pos, lookupN("embed.", numLocalEmbed)) - v.Sym.Def = asTypesNode(v) + v = ir.NewNameAt(v.Pos, lookupN("embed.", numLocalEmbed)) + v.Sym.Def = ir.AsTypesNode(v) v.Name.Param.Ntype = typ - v.SetClass(PEXTERN) + v.SetClass(ir.PEXTERN) externdcl = append(externdcl, v) - exprs = []*Node{v} + exprs = []*ir.Node{v} } v.Name.Param.SetEmbedFiles(list) @@ -129,18 +130,18 @@ func varEmbed(p *noder, names []*Node, typ *Node, exprs []*Node, embeds []Pragma // The match is approximate because we haven't done scope resolution yet and // can't tell whether "string" and "byte" really mean "string" and "byte". // The result must be confirmed later, after type checking, using embedKind. -func embedKindApprox(typ *Node) int { - if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == localpkg && base.Ctxt.Pkgpath == "embed")) { +func embedKindApprox(typ *ir.Node) int { + if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) { return embedFiles } // These are not guaranteed to match only string and []byte - // maybe the local package has redefined one of those words. // But it's the best we can do now during the noder. // The stricter check happens later, in initEmbed calling embedKind. - if typ.Sym != nil && typ.Sym.Name == "string" && typ.Sym.Pkg == localpkg { + if typ.Sym != nil && typ.Sym.Name == "string" && typ.Sym.Pkg == ir.LocalPkg { return embedString } - if typ.Op == OTARRAY && typ.Left == nil && typ.Right.Sym != nil && typ.Right.Sym.Name == "byte" && typ.Right.Sym.Pkg == localpkg { + if typ.Op == ir.OTARRAY && typ.Left == nil && typ.Right.Sym != nil && typ.Right.Sym.Name == "byte" && typ.Right.Sym.Pkg == ir.LocalPkg { return embedBytes } return embedUnknown @@ -148,10 +149,10 @@ func embedKindApprox(typ *Node) int { // embedKind determines the kind of embedding variable. func embedKind(typ *types.Type) int { - if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == localpkg && base.Ctxt.Pkgpath == "embed")) { + if typ.Sym != nil && typ.Sym.Name == "FS" && (typ.Sym.Pkg.Path == "embed" || (typ.Sym.Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) { return embedFiles } - if typ == types.Types[TSTRING] { + if typ == types.Types[types.TSTRING] { return embedString } if typ.Sym == nil && typ.IsSlice() && typ.Elem() == types.Bytetype { @@ -191,7 +192,7 @@ func dumpembeds() { // initEmbed emits the init data for a //go:embed variable, // which is either a string, a []byte, or an embed.FS. -func initEmbed(v *Node) { +func initEmbed(v *ir.Node) { files := v.Name.Param.EmbedFiles() switch kind := embedKind(v.Type); kind { case embedUnknown: diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go deleted file mode 100644 index 5cf8c4a1c64..00000000000 --- a/src/cmd/compile/internal/gc/esc.go +++ /dev/null @@ -1,474 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gc - -import ( - "cmd/compile/internal/base" - "cmd/compile/internal/types" - "fmt" -) - -func escapes(all []*Node) { - visitBottomUp(all, escapeFuncs) -} - -const ( - EscFuncUnknown = 0 + iota - EscFuncPlanned - EscFuncStarted - EscFuncTagged -) - -func min8(a, b int8) int8 { - if a < b { - return a - } - return b -} - -func max8(a, b int8) int8 { - if a > b { - return a - } - return b -} - -const ( - EscUnknown = iota - EscNone // Does not escape to heap, result, or parameters. - EscHeap // Reachable from the heap - EscNever // By construction will not escape. -) - -// funcSym returns fn.Func.Nname.Sym if no nils are encountered along the way. -func funcSym(fn *Node) *types.Sym { - if fn == nil || fn.Func.Nname == nil { - return nil - } - return fn.Func.Nname.Sym -} - -// Mark labels that have no backjumps to them as not increasing e.loopdepth. -// Walk hasn't generated (goto|label).Left.Sym.Label yet, so we'll cheat -// and set it to one of the following two. Then in esc we'll clear it again. -var ( - looping = nod(OXXX, nil, nil) - nonlooping = nod(OXXX, nil, nil) -) - -func isSliceSelfAssign(dst, src *Node) bool { - // Detect the following special case. - // - // func (b *Buffer) Foo() { - // n, m := ... - // b.buf = b.buf[n:m] - // } - // - // This assignment is a no-op for escape analysis, - // it does not store any new pointers into b that were not already there. - // However, without this special case b will escape, because we assign to OIND/ODOTPTR. - // Here we assume that the statement will not contain calls, - // that is, that order will move any calls to init. - // Otherwise base ONAME value could change between the moments - // when we evaluate it for dst and for src. - - // dst is ONAME dereference. - if dst.Op != ODEREF && dst.Op != ODOTPTR || dst.Left.Op != ONAME { - return false - } - // src is a slice operation. - switch src.Op { - case OSLICE, OSLICE3, OSLICESTR: - // OK. - case OSLICEARR, OSLICE3ARR: - // Since arrays are embedded into containing object, - // slice of non-pointer array will introduce a new pointer into b that was not already there - // (pointer to b itself). After such assignment, if b contents escape, - // b escapes as well. If we ignore such OSLICEARR, we will conclude - // that b does not escape when b contents do. - // - // Pointer to an array is OK since it's not stored inside b directly. - // For slicing an array (not pointer to array), there is an implicit OADDR. - // We check that to determine non-pointer array slicing. - if src.Left.Op == OADDR { - return false - } - default: - return false - } - // slice is applied to ONAME dereference. - if src.Left.Op != ODEREF && src.Left.Op != ODOTPTR || src.Left.Left.Op != ONAME { - return false - } - // dst and src reference the same base ONAME. - return dst.Left == src.Left.Left -} - -// isSelfAssign reports whether assignment from src to dst can -// be ignored by the escape analysis as it's effectively a self-assignment. -func isSelfAssign(dst, src *Node) bool { - if isSliceSelfAssign(dst, src) { - return true - } - - // Detect trivial assignments that assign back to the same object. - // - // It covers these cases: - // val.x = val.y - // val.x[i] = val.y[j] - // val.x1.x2 = val.x1.y2 - // ... etc - // - // These assignments do not change assigned object lifetime. - - if dst == nil || src == nil || dst.Op != src.Op { - return false - } - - switch dst.Op { - case ODOT, ODOTPTR: - // Safe trailing accessors that are permitted to differ. - case OINDEX: - if mayAffectMemory(dst.Right) || mayAffectMemory(src.Right) { - return false - } - default: - return false - } - - // The expression prefix must be both "safe" and identical. - return samesafeexpr(dst.Left, src.Left) -} - -// mayAffectMemory reports whether evaluation of n may affect the program's -// memory state. If the expression can't affect memory state, then it can be -// safely ignored by the escape analysis. -func mayAffectMemory(n *Node) bool { - // We may want to use a list of "memory safe" ops instead of generally - // "side-effect free", which would include all calls and other ops that can - // allocate or change global state. For now, it's safer to start with the latter. - // - // We're ignoring things like division by zero, index out of range, - // and nil pointer dereference here. - switch n.Op { - case ONAME, OCLOSUREVAR, OLITERAL, ONIL: - return false - - // Left+Right group. - case OINDEX, OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD: - return mayAffectMemory(n.Left) || mayAffectMemory(n.Right) - - // Left group. - case ODOT, ODOTPTR, ODEREF, OCONVNOP, OCONV, OLEN, OCAP, - ONOT, OBITNOT, OPLUS, ONEG, OALIGNOF, OOFFSETOF, OSIZEOF: - return mayAffectMemory(n.Left) - - default: - return true - } -} - -// heapAllocReason returns the reason the given Node must be heap -// allocated, or the empty string if it doesn't. -func heapAllocReason(n *Node) string { - if n.Type == nil { - return "" - } - - // Parameters are always passed via the stack. - if n.Op == ONAME && (n.Class() == PPARAM || n.Class() == PPARAMOUT) { - return "" - } - - if n.Type.Width > maxStackVarSize { - return "too large for stack" - } - - if (n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= maxImplicitStackVarSize { - return "too large for stack" - } - - if n.Op == OCLOSURE && closureType(n).Size() >= maxImplicitStackVarSize { - return "too large for stack" - } - if n.Op == OCALLPART && partialCallType(n).Size() >= maxImplicitStackVarSize { - return "too large for stack" - } - - if n.Op == OMAKESLICE { - r := n.Right - if r == nil { - r = n.Left - } - if !smallintconst(r) { - return "non-constant size" - } - if t := n.Type; t.Elem().Width != 0 && r.Int64Val() >= maxImplicitStackVarSize/t.Elem().Width { - return "too large for stack" - } - } - - return "" -} - -// addrescapes tags node n as having had its address taken -// by "increasing" the "value" of n.Esc to EscHeap. -// Storage is allocated as necessary to allow the address -// to be taken. -func addrescapes(n *Node) { - switch n.Op { - default: - // Unexpected Op, probably due to a previous type error. Ignore. - - case ODEREF, ODOTPTR: - // Nothing to do. - - case ONAME: - if n == nodfp { - break - } - - // if this is a tmpname (PAUTO), it was tagged by tmpname as not escaping. - // on PPARAM it means something different. - if n.Class() == PAUTO && n.Esc == EscNever { - break - } - - // If a closure reference escapes, mark the outer variable as escaping. - if n.Name.IsClosureVar() { - addrescapes(n.Name.Defn) - break - } - - if n.Class() != PPARAM && n.Class() != PPARAMOUT && n.Class() != PAUTO { - break - } - - // This is a plain parameter or local variable that needs to move to the heap, - // but possibly for the function outside the one we're compiling. - // That is, if we have: - // - // func f(x int) { - // func() { - // global = &x - // } - // } - // - // then we're analyzing the inner closure but we need to move x to the - // heap in f, not in the inner closure. Flip over to f before calling moveToHeap. - oldfn := Curfn - Curfn = n.Name.Curfn - if Curfn.Op == OCLOSURE { - Curfn = Curfn.Func.Decl - panic("can't happen") - } - ln := base.Pos - base.Pos = Curfn.Pos - moveToHeap(n) - Curfn = oldfn - base.Pos = ln - - // ODOTPTR has already been introduced, - // so these are the non-pointer ODOT and OINDEX. - // In &x[0], if x is a slice, then x does not - // escape--the pointer inside x does, but that - // is always a heap pointer anyway. - case ODOT, OINDEX, OPAREN, OCONVNOP: - if !n.Left.Type.IsSlice() { - addrescapes(n.Left) - } - } -} - -// moveToHeap records the parameter or local variable n as moved to the heap. -func moveToHeap(n *Node) { - if base.Flag.LowerR != 0 { - Dump("MOVE", n) - } - if base.Flag.CompilingRuntime { - base.Errorf("%v escapes to heap, not allowed in runtime", n) - } - if n.Class() == PAUTOHEAP { - Dump("n", n) - base.Fatalf("double move to heap") - } - - // Allocate a local stack variable to hold the pointer to the heap copy. - // temp will add it to the function declaration list automatically. - heapaddr := temp(types.NewPtr(n.Type)) - heapaddr.Sym = lookup("&" + n.Sym.Name) - heapaddr.Orig.Sym = heapaddr.Sym - heapaddr.Pos = n.Pos - - // Unset AutoTemp to persist the &foo variable name through SSA to - // liveness analysis. - // TODO(mdempsky/drchase): Cleaner solution? - heapaddr.Name.SetAutoTemp(false) - - // Parameters have a local stack copy used at function start/end - // in addition to the copy in the heap that may live longer than - // the function. - if n.Class() == PPARAM || n.Class() == PPARAMOUT { - if n.Xoffset == BADWIDTH { - base.Fatalf("addrescapes before param assignment") - } - - // We rewrite n below to be a heap variable (indirection of heapaddr). - // Preserve a copy so we can still write code referring to the original, - // and substitute that copy into the function declaration list - // so that analyses of the local (on-stack) variables use it. - stackcopy := newname(n.Sym) - stackcopy.Type = n.Type - stackcopy.Xoffset = n.Xoffset - stackcopy.SetClass(n.Class()) - stackcopy.Name.Param.Heapaddr = heapaddr - if n.Class() == PPARAMOUT { - // Make sure the pointer to the heap copy is kept live throughout the function. - // The function could panic at any point, and then a defer could recover. - // Thus, we need the pointer to the heap copy always available so the - // post-deferreturn code can copy the return value back to the stack. - // See issue 16095. - heapaddr.Name.SetIsOutputParamHeapAddr(true) - } - n.Name.Param.Stackcopy = stackcopy - - // Substitute the stackcopy into the function variable list so that - // liveness and other analyses use the underlying stack slot - // and not the now-pseudo-variable n. - found := false - for i, d := range Curfn.Func.Dcl { - if d == n { - Curfn.Func.Dcl[i] = stackcopy - found = true - break - } - // Parameters are before locals, so can stop early. - // This limits the search even in functions with many local variables. - if d.Class() == PAUTO { - break - } - } - if !found { - base.Fatalf("cannot find %v in local variable list", n) - } - Curfn.Func.Dcl = append(Curfn.Func.Dcl, n) - } - - // Modify n in place so that uses of n now mean indirection of the heapaddr. - n.SetClass(PAUTOHEAP) - n.Xoffset = 0 - n.Name.Param.Heapaddr = heapaddr - n.Esc = EscHeap - if base.Flag.LowerM != 0 { - base.WarnfAt(n.Pos, "moved to heap: %v", n) - } -} - -// This special tag is applied to uintptr variables -// that we believe may hold unsafe.Pointers for -// calls into assembly functions. -const unsafeUintptrTag = "unsafe-uintptr" - -// This special tag is applied to uintptr parameters of functions -// marked go:uintptrescapes. -const uintptrEscapesTag = "uintptr-escapes" - -func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string { - name := func() string { - if f.Sym != nil { - return f.Sym.Name - } - return fmt.Sprintf("arg#%d", narg) - } - - if fn.Nbody.Len() == 0 { - // Assume that uintptr arguments must be held live across the call. - // This is most important for syscall.Syscall. - // See golang.org/issue/13372. - // This really doesn't have much to do with escape analysis per se, - // but we are reusing the ability to annotate an individual function - // argument and pass those annotations along to importing code. - if f.Type.IsUintptr() { - if base.Flag.LowerM != 0 { - base.WarnfAt(f.Pos, "assuming %v is unsafe uintptr", name()) - } - return unsafeUintptrTag - } - - if !f.Type.HasPointers() { // don't bother tagging for scalars - return "" - } - - var esc EscLeaks - - // External functions are assumed unsafe, unless - // //go:noescape is given before the declaration. - if fn.Func.Pragma&Noescape != 0 { - if base.Flag.LowerM != 0 && f.Sym != nil { - base.WarnfAt(f.Pos, "%v does not escape", name()) - } - } else { - if base.Flag.LowerM != 0 && f.Sym != nil { - base.WarnfAt(f.Pos, "leaking param: %v", name()) - } - esc.AddHeap(0) - } - - return esc.Encode() - } - - if fn.Func.Pragma&UintptrEscapes != 0 { - if f.Type.IsUintptr() { - if base.Flag.LowerM != 0 { - base.WarnfAt(f.Pos, "marking %v as escaping uintptr", name()) - } - return uintptrEscapesTag - } - if f.IsDDD() && f.Type.Elem().IsUintptr() { - // final argument is ...uintptr. - if base.Flag.LowerM != 0 { - base.WarnfAt(f.Pos, "marking %v as escaping ...uintptr", name()) - } - return uintptrEscapesTag - } - } - - if !f.Type.HasPointers() { // don't bother tagging for scalars - return "" - } - - // Unnamed parameters are unused and therefore do not escape. - if f.Sym == nil || f.Sym.IsBlank() { - var esc EscLeaks - return esc.Encode() - } - - n := asNode(f.Nname) - loc := e.oldLoc(n) - esc := loc.paramEsc - esc.Optimize() - - if base.Flag.LowerM != 0 && !loc.escapes { - if esc.Empty() { - base.WarnfAt(f.Pos, "%v does not escape", name()) - } - if x := esc.Heap(); x >= 0 { - if x == 0 { - base.WarnfAt(f.Pos, "leaking param: %v", name()) - } else { - // TODO(mdempsky): Mention level=x like below? - base.WarnfAt(f.Pos, "leaking param content: %v", name()) - } - } - for i := 0; i < numEscResults; i++ { - if x := esc.Result(i); x >= 0 { - res := fn.Type.Results().Field(i).Sym - base.WarnfAt(f.Pos, "leaking param: %v to result %v level=%d", name(), res, x) - } - } - } - - return esc.Encode() -} diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index aaf768d85ab..a0aa516d9a4 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/logopt" "cmd/compile/internal/types" "cmd/internal/src" @@ -85,7 +86,7 @@ import ( type Escape struct { allLocs []*EscLocation - curfn *Node + curfn *ir.Node // loopDepth counts the current loop nesting depth within // curfn. It increments within each "for" loop and at each @@ -100,8 +101,8 @@ type Escape struct { // An EscLocation represents an abstract location that stores a Go // variable. type EscLocation struct { - n *Node // represented variable or expression, if any - curfn *Node // enclosing function + n *ir.Node // represented variable or expression, if any + curfn *ir.Node // enclosing function edges []EscEdge // incoming edges loopDepth int // loopDepth at declaration @@ -142,11 +143,11 @@ type EscEdge struct { } func init() { - EscFmt = escFmt + ir.EscFmt = escFmt } // escFmt is called from node printing to print information about escape analysis results. -func escFmt(n *Node, short bool) string { +func escFmt(n *ir.Node, short bool) string { text := "" switch n.Esc { case EscUnknown: @@ -178,9 +179,9 @@ func escFmt(n *Node, short bool) string { // escapeFuncs performs escape analysis on a minimal batch of // functions. -func escapeFuncs(fns []*Node, recursive bool) { +func escapeFuncs(fns []*ir.Node, recursive bool) { for _, fn := range fns { - if fn.Op != ODCLFUNC { + if fn.Op != ir.ODCLFUNC { base.Fatalf("unexpected node: %v", fn) } } @@ -201,13 +202,13 @@ func escapeFuncs(fns []*Node, recursive bool) { e.finish(fns) } -func (e *Escape) initFunc(fn *Node) { - if fn.Op != ODCLFUNC || fn.Esc != EscFuncUnknown { +func (e *Escape) initFunc(fn *ir.Node) { + if fn.Op != ir.ODCLFUNC || fn.Esc != EscFuncUnknown { base.Fatalf("unexpected node: %v", fn) } fn.Esc = EscFuncPlanned if base.Flag.LowerM > 3 { - Dump("escAnalyze", fn) + ir.Dump("escAnalyze", fn) } e.curfn = fn @@ -215,26 +216,26 @@ func (e *Escape) initFunc(fn *Node) { // Allocate locations for local variables. for _, dcl := range fn.Func.Dcl { - if dcl.Op == ONAME { + if dcl.Op == ir.ONAME { e.newLoc(dcl, false) } } } -func (e *Escape) walkFunc(fn *Node) { +func (e *Escape) walkFunc(fn *ir.Node) { fn.Esc = EscFuncStarted // Identify labels that mark the head of an unstructured loop. - inspectList(fn.Nbody, func(n *Node) bool { + ir.InspectList(fn.Nbody, func(n *ir.Node) bool { switch n.Op { - case OLABEL: - n.Sym.Label = asTypesNode(nonlooping) + case ir.OLABEL: + n.Sym.Label = ir.AsTypesNode(nonlooping) - case OGOTO: + case ir.OGOTO: // If we visited the label before the goto, // then this is a looping label. - if n.Sym.Label == asTypesNode(nonlooping) { - n.Sym.Label = asTypesNode(looping) + if n.Sym.Label == ir.AsTypesNode(nonlooping) { + n.Sym.Label = ir.AsTypesNode(looping) } } @@ -273,7 +274,7 @@ func (e *Escape) walkFunc(fn *Node) { // } // stmt evaluates a single Go statement. -func (e *Escape) stmt(n *Node) { +func (e *Escape) stmt(n *ir.Node) { if n == nil { return } @@ -293,23 +294,23 @@ func (e *Escape) stmt(n *Node) { default: base.Fatalf("unexpected stmt: %v", n) - case ODCLCONST, ODCLTYPE, OEMPTY, OFALL, OINLMARK: + case ir.ODCLCONST, ir.ODCLTYPE, ir.OEMPTY, ir.OFALL, ir.OINLMARK: // nop - case OBREAK, OCONTINUE, OGOTO: + case ir.OBREAK, ir.OCONTINUE, ir.OGOTO: // TODO(mdempsky): Handle dead code? - case OBLOCK: + case ir.OBLOCK: e.stmts(n.List) - case ODCL: + case ir.ODCL: // Record loop depth at declaration. - if !n.Left.isBlank() { + if !ir.IsBlank(n.Left) { e.dcl(n.Left) } - case OLABEL: - switch asNode(n.Sym.Label) { + case ir.OLABEL: + switch ir.AsNode(n.Sym.Label) { case nonlooping: if base.Flag.LowerM > 2 { fmt.Printf("%v:%v non-looping label\n", base.FmtPos(base.Pos), n) @@ -324,19 +325,19 @@ func (e *Escape) stmt(n *Node) { } n.Sym.Label = nil - case OIF: + case ir.OIF: e.discard(n.Left) e.block(n.Nbody) e.block(n.Rlist) - case OFOR, OFORUNTIL: + case ir.OFOR, ir.OFORUNTIL: e.loopDepth++ e.discard(n.Left) e.stmt(n.Right) e.block(n.Nbody) e.loopDepth-- - case ORANGE: + case ir.ORANGE: // for List = range Right { Nbody } e.loopDepth++ ks := e.addrs(n.List) @@ -354,8 +355,8 @@ func (e *Escape) stmt(n *Node) { } e.expr(e.later(k), n.Right) - case OSWITCH: - typesw := n.Left != nil && n.Left.Op == OTYPESW + case ir.OSWITCH: + typesw := n.Left != nil && n.Left.Op == ir.OTYPESW var ks []EscHole for _, cas := range n.List.Slice() { // cases @@ -377,68 +378,68 @@ func (e *Escape) stmt(n *Node) { e.discard(n.Left) } - case OSELECT: + case ir.OSELECT: for _, cas := range n.List.Slice() { e.stmt(cas.Left) e.block(cas.Nbody) } - case OSELRECV: + case ir.OSELRECV: e.assign(n.Left, n.Right, "selrecv", n) - case OSELRECV2: + case ir.OSELRECV2: e.assign(n.Left, n.Right, "selrecv", n) e.assign(n.List.First(), nil, "selrecv", n) - case ORECV: + case ir.ORECV: // TODO(mdempsky): Consider e.discard(n.Left). e.exprSkipInit(e.discardHole(), n) // already visited n.Ninit - case OSEND: + case ir.OSEND: e.discard(n.Left) e.assignHeap(n.Right, "send", n) - case OAS, OASOP: + case ir.OAS, ir.OASOP: e.assign(n.Left, n.Right, "assign", n) - case OAS2: + case ir.OAS2: for i, nl := range n.List.Slice() { e.assign(nl, n.Rlist.Index(i), "assign-pair", n) } - case OAS2DOTTYPE: // v, ok = x.(type) + case ir.OAS2DOTTYPE: // v, ok = x.(type) e.assign(n.List.First(), n.Right, "assign-pair-dot-type", n) e.assign(n.List.Second(), nil, "assign-pair-dot-type", n) - case OAS2MAPR: // v, ok = m[k] + case ir.OAS2MAPR: // v, ok = m[k] e.assign(n.List.First(), n.Right, "assign-pair-mapr", n) e.assign(n.List.Second(), nil, "assign-pair-mapr", n) - case OAS2RECV: // v, ok = <-ch + case ir.OAS2RECV: // v, ok = <-ch e.assign(n.List.First(), n.Right, "assign-pair-receive", n) e.assign(n.List.Second(), nil, "assign-pair-receive", n) - case OAS2FUNC: + case ir.OAS2FUNC: e.stmts(n.Right.Ninit) e.call(e.addrs(n.List), n.Right, nil) - case ORETURN: + case ir.ORETURN: results := e.curfn.Type.Results().FieldSlice() for i, v := range n.List.Slice() { - e.assign(asNode(results[i].Nname), v, "return", n) + e.assign(ir.AsNode(results[i].Nname), v, "return", n) } - case OCALLFUNC, OCALLMETH, OCALLINTER, OCLOSE, OCOPY, ODELETE, OPANIC, OPRINT, OPRINTN, ORECOVER: + case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: e.call(nil, n, nil) - case OGO, ODEFER: + case ir.OGO, ir.ODEFER: e.stmts(n.Left.Ninit) e.call(nil, n.Left, n) - case ORETJMP: + case ir.ORETJMP: // TODO(mdempsky): What do? esc.go just ignores it. } } -func (e *Escape) stmts(l Nodes) { +func (e *Escape) stmts(l ir.Nodes) { for _, n := range l.Slice() { e.stmt(n) } } // block is like stmts, but preserves loopDepth. -func (e *Escape) block(l Nodes) { +func (e *Escape) block(l ir.Nodes) { old := e.loopDepth e.stmts(l) e.loopDepth = old @@ -446,7 +447,7 @@ func (e *Escape) block(l Nodes) { // expr models evaluating an expression n and flowing the result into // hole k. -func (e *Escape) expr(k EscHole, n *Node) { +func (e *Escape) expr(k EscHole, n *ir.Node) { if n == nil { return } @@ -454,7 +455,7 @@ func (e *Escape) expr(k EscHole, n *Node) { e.exprSkipInit(k, n) } -func (e *Escape) exprSkipInit(k EscHole, n *Node) { +func (e *Escape) exprSkipInit(k EscHole, n *ir.Node) { if n == nil { return } @@ -467,7 +468,7 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { uintptrEscapesHack := k.uintptrEscapesHack k.uintptrEscapesHack = false - if uintptrEscapesHack && n.Op == OCONVNOP && n.Left.Type.IsUnsafePtr() { + if uintptrEscapesHack && n.Op == ir.OCONVNOP && n.Left.Type.IsUnsafePtr() { // nop } else if k.derefs >= 0 && !n.Type.HasPointers() { k = e.discardHole() @@ -477,32 +478,32 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { default: base.Fatalf("unexpected expr: %v", n) - case OLITERAL, ONIL, OGETG, OCLOSUREVAR, OTYPE, OMETHEXPR: + case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OCLOSUREVAR, ir.OTYPE, ir.OMETHEXPR: // nop - case ONAME: - if n.Class() == PFUNC || n.Class() == PEXTERN { + case ir.ONAME: + if n.Class() == ir.PFUNC || n.Class() == ir.PEXTERN { return } e.flow(k, e.oldLoc(n)) - case OPLUS, ONEG, OBITNOT, ONOT: + case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT: e.discard(n.Left) - case OADD, OSUB, OOR, OXOR, OMUL, ODIV, OMOD, OLSH, ORSH, OAND, OANDNOT, OEQ, ONE, OLT, OLE, OGT, OGE, OANDAND, OOROR: + case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE, ir.OANDAND, ir.OOROR: e.discard(n.Left) e.discard(n.Right) - case OADDR: + case ir.OADDR: e.expr(k.addr(n, "address-of"), n.Left) // "address-of" - case ODEREF: + case ir.ODEREF: e.expr(k.deref(n, "indirection"), n.Left) // "indirection" - case ODOT, ODOTMETH, ODOTINTER: + case ir.ODOT, ir.ODOTMETH, ir.ODOTINTER: e.expr(k.note(n, "dot"), n.Left) - case ODOTPTR: + case ir.ODOTPTR: e.expr(k.deref(n, "dot of pointer"), n.Left) // "dot of pointer" - case ODOTTYPE, ODOTTYPE2: + case ir.ODOTTYPE, ir.ODOTTYPE2: e.expr(k.dotType(n.Type, n, "dot"), n.Left) - case OINDEX: + case ir.OINDEX: if n.Left.Type.IsArray() { e.expr(k.note(n, "fixed-array-index-of"), n.Left) } else { @@ -510,17 +511,17 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { e.expr(k.deref(n, "dot of pointer"), n.Left) } e.discard(n.Right) - case OINDEXMAP: + case ir.OINDEXMAP: e.discard(n.Left) e.discard(n.Right) - case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR: + case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR: e.expr(k.note(n, "slice"), n.Left) low, high, max := n.SliceBounds() e.discard(low) e.discard(high) e.discard(max) - case OCONV, OCONVNOP: + case ir.OCONV, ir.OCONVNOP: if checkPtr(e.curfn, 2) && n.Type.IsUnsafePtr() && n.Left.Type.IsPtr() { // When -d=checkptr=2 is enabled, treat // conversions to unsafe.Pointer as an @@ -534,35 +535,35 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { } else { e.expr(k, n.Left) } - case OCONVIFACE: + case ir.OCONVIFACE: if !n.Left.Type.IsInterface() && !isdirectiface(n.Left.Type) { k = e.spill(k, n) } e.expr(k.note(n, "interface-converted"), n.Left) - case ORECV: + case ir.ORECV: e.discard(n.Left) - case OCALLMETH, OCALLFUNC, OCALLINTER, OLEN, OCAP, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCOPY: + case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OLEN, ir.OCAP, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY: e.call([]EscHole{k}, n, nil) - case ONEW: + case ir.ONEW: e.spill(k, n) - case OMAKESLICE: + case ir.OMAKESLICE: e.spill(k, n) e.discard(n.Left) e.discard(n.Right) - case OMAKECHAN: + case ir.OMAKECHAN: e.discard(n.Left) - case OMAKEMAP: + case ir.OMAKEMAP: e.spill(k, n) e.discard(n.Left) - case ORECOVER: + case ir.ORECOVER: // nop - case OCALLPART: + case ir.OCALLPART: // Flow the receiver argument to both the closure and // to the receiver parameter. @@ -580,38 +581,38 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { for i := m.Type.NumResults(); i > 0; i-- { ks = append(ks, e.heapHole()) } - paramK := e.tagHole(ks, asNode(m.Nname), m.Type.Recv()) + paramK := e.tagHole(ks, ir.AsNode(m.Nname), m.Type.Recv()) e.expr(e.teeHole(paramK, closureK), n.Left) - case OPTRLIT: + case ir.OPTRLIT: e.expr(e.spill(k, n), n.Left) - case OARRAYLIT: + case ir.OARRAYLIT: for _, elt := range n.List.Slice() { - if elt.Op == OKEY { + if elt.Op == ir.OKEY { elt = elt.Right } e.expr(k.note(n, "array literal element"), elt) } - case OSLICELIT: + case ir.OSLICELIT: k = e.spill(k, n) k.uintptrEscapesHack = uintptrEscapesHack // for ...uintptr parameters for _, elt := range n.List.Slice() { - if elt.Op == OKEY { + if elt.Op == ir.OKEY { elt = elt.Right } e.expr(k.note(n, "slice-literal-element"), elt) } - case OSTRUCTLIT: + case ir.OSTRUCTLIT: for _, elt := range n.List.Slice() { e.expr(k.note(n, "struct literal element"), elt.Left) } - case OMAPLIT: + case ir.OMAPLIT: e.spill(k, n) // Map keys and values are always stored in the heap. @@ -620,12 +621,12 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { e.assignHeap(elt.Right, "map literal value", n) } - case OCLOSURE: + case ir.OCLOSURE: k = e.spill(k, n) // Link addresses of captured variables to closure. for _, v := range n.Func.ClosureVars.Slice() { - if v.Op == OXXX { // unnamed out argument; see dcl.go:/^funcargs + if v.Op == ir.OXXX { // unnamed out argument; see dcl.go:/^funcargs continue } @@ -637,11 +638,11 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { e.expr(k.note(n, "captured by a closure"), v.Name.Defn) } - case ORUNES2STR, OBYTES2STR, OSTR2RUNES, OSTR2BYTES, ORUNESTR: + case ir.ORUNES2STR, ir.OBYTES2STR, ir.OSTR2RUNES, ir.OSTR2BYTES, ir.ORUNESTR: e.spill(k, n) e.discard(n.Left) - case OADDSTR: + case ir.OADDSTR: e.spill(k, n) // Arguments of OADDSTR never escape; @@ -652,32 +653,32 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { // unsafeValue evaluates a uintptr-typed arithmetic expression looking // for conversions from an unsafe.Pointer. -func (e *Escape) unsafeValue(k EscHole, n *Node) { - if n.Type.Etype != TUINTPTR { +func (e *Escape) unsafeValue(k EscHole, n *ir.Node) { + if n.Type.Etype != types.TUINTPTR { base.Fatalf("unexpected type %v for %v", n.Type, n) } e.stmts(n.Ninit) switch n.Op { - case OCONV, OCONVNOP: + case ir.OCONV, ir.OCONVNOP: if n.Left.Type.IsUnsafePtr() { e.expr(k, n.Left) } else { e.discard(n.Left) } - case ODOTPTR: + case ir.ODOTPTR: if isReflectHeaderDataField(n) { e.expr(k.deref(n, "reflect.Header.Data"), n.Left) } else { e.discard(n.Left) } - case OPLUS, ONEG, OBITNOT: + case ir.OPLUS, ir.ONEG, ir.OBITNOT: e.unsafeValue(k, n.Left) - case OADD, OSUB, OOR, OXOR, OMUL, ODIV, OMOD, OAND, OANDNOT: + case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OAND, ir.OANDNOT: e.unsafeValue(k, n.Left) e.unsafeValue(k, n.Right) - case OLSH, ORSH: + case ir.OLSH, ir.ORSH: e.unsafeValue(k, n.Left) // RHS need not be uintptr-typed (#32959) and can't meaningfully // flow pointers anyway. @@ -689,11 +690,11 @@ func (e *Escape) unsafeValue(k EscHole, n *Node) { // discard evaluates an expression n for side-effects, but discards // its value. -func (e *Escape) discard(n *Node) { +func (e *Escape) discard(n *ir.Node) { e.expr(e.discardHole(), n) } -func (e *Escape) discards(l Nodes) { +func (e *Escape) discards(l ir.Nodes) { for _, n := range l.Slice() { e.discard(n) } @@ -701,8 +702,8 @@ func (e *Escape) discards(l Nodes) { // addr evaluates an addressable expression n and returns an EscHole // that represents storing into the represented location. -func (e *Escape) addr(n *Node) EscHole { - if n == nil || n.isBlank() { +func (e *Escape) addr(n *ir.Node) EscHole { + if n == nil || ir.IsBlank(n) { // Can happen at least in OSELRECV. // TODO(mdempsky): Anywhere else? return e.discardHole() @@ -713,23 +714,23 @@ func (e *Escape) addr(n *Node) EscHole { switch n.Op { default: base.Fatalf("unexpected addr: %v", n) - case ONAME: - if n.Class() == PEXTERN { + case ir.ONAME: + if n.Class() == ir.PEXTERN { break } k = e.oldLoc(n).asHole() - case ODOT: + case ir.ODOT: k = e.addr(n.Left) - case OINDEX: + case ir.OINDEX: e.discard(n.Right) if n.Left.Type.IsArray() { k = e.addr(n.Left) } else { e.discard(n.Left) } - case ODEREF, ODOTPTR: + case ir.ODEREF, ir.ODOTPTR: e.discard(n) - case OINDEXMAP: + case ir.OINDEXMAP: e.discard(n.Left) e.assignHeap(n.Right, "key of map put", n) } @@ -741,7 +742,7 @@ func (e *Escape) addr(n *Node) EscHole { return k } -func (e *Escape) addrs(l Nodes) []EscHole { +func (e *Escape) addrs(l ir.Nodes) []EscHole { var ks []EscHole for _, n := range l.Slice() { ks = append(ks, e.addr(n)) @@ -750,7 +751,7 @@ func (e *Escape) addrs(l Nodes) []EscHole { } // assign evaluates the assignment dst = src. -func (e *Escape) assign(dst, src *Node, why string, where *Node) { +func (e *Escape) assign(dst, src *ir.Node, why string, where *ir.Node) { // Filter out some no-op assignments for escape analysis. ignore := dst != nil && src != nil && isSelfAssign(dst, src) if ignore && base.Flag.LowerM != 0 { @@ -758,7 +759,7 @@ func (e *Escape) assign(dst, src *Node, why string, where *Node) { } k := e.addr(dst) - if dst != nil && dst.Op == ODOTPTR && isReflectHeaderDataField(dst) { + if dst != nil && dst.Op == ir.ODOTPTR && isReflectHeaderDataField(dst) { e.unsafeValue(e.heapHole().note(where, why), src) } else { if ignore { @@ -768,22 +769,22 @@ func (e *Escape) assign(dst, src *Node, why string, where *Node) { } } -func (e *Escape) assignHeap(src *Node, why string, where *Node) { +func (e *Escape) assignHeap(src *ir.Node, why string, where *ir.Node) { e.expr(e.heapHole().note(where, why), src) } // call evaluates a call expressions, including builtin calls. ks // should contain the holes representing where the function callee's // results flows; where is the OGO/ODEFER context of the call, if any. -func (e *Escape) call(ks []EscHole, call, where *Node) { - topLevelDefer := where != nil && where.Op == ODEFER && e.loopDepth == 1 +func (e *Escape) call(ks []EscHole, call, where *ir.Node) { + topLevelDefer := where != nil && where.Op == ir.ODEFER && e.loopDepth == 1 if topLevelDefer { // force stack allocation of defer record, unless // open-coded defers are used (see ssa.go) where.Esc = EscNever } - argument := func(k EscHole, arg *Node) { + argument := func(k EscHole, arg *ir.Node) { if topLevelDefer { // Top level defers arguments don't escape to // heap, but they do need to last until end of @@ -800,21 +801,21 @@ func (e *Escape) call(ks []EscHole, call, where *Node) { default: base.Fatalf("unexpected call op: %v", call.Op) - case OCALLFUNC, OCALLMETH, OCALLINTER: + case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: fixVariadicCall(call) // Pick out the function callee, if statically known. - var fn *Node + var fn *ir.Node switch call.Op { - case OCALLFUNC: + case ir.OCALLFUNC: switch v := staticValue(call.Left); { - case v.Op == ONAME && v.Class() == PFUNC: + case v.Op == ir.ONAME && v.Class() == ir.PFUNC: fn = v - case v.Op == OCLOSURE: + case v.Op == ir.OCLOSURE: fn = v.Func.Nname } - case OCALLMETH: - fn = call.Left.MethodName() + case ir.OCALLMETH: + fn = methodExprName(call.Left) } fntype := call.Left.Type @@ -824,7 +825,7 @@ func (e *Escape) call(ks []EscHole, call, where *Node) { if ks != nil && fn != nil && e.inMutualBatch(fn) { for i, result := range fn.Type.Results().FieldSlice() { - e.expr(ks[i], asNode(result.Nname)) + e.expr(ks[i], ir.AsNode(result.Nname)) } } @@ -840,7 +841,7 @@ func (e *Escape) call(ks []EscHole, call, where *Node) { argument(e.tagHole(ks, fn, param), args[i]) } - case OAPPEND: + case ir.OAPPEND: args := call.List.Slice() // Appendee slice may flow directly to the result, if @@ -865,7 +866,7 @@ func (e *Escape) call(ks []EscHole, call, where *Node) { } } - case OCOPY: + case ir.OCOPY: argument(e.discardHole(), call.Left) copiedK := e.discardHole() @@ -874,17 +875,17 @@ func (e *Escape) call(ks []EscHole, call, where *Node) { } argument(copiedK, call.Right) - case OPANIC: + case ir.OPANIC: argument(e.heapHole(), call.Left) - case OCOMPLEX: + case ir.OCOMPLEX: argument(e.discardHole(), call.Left) argument(e.discardHole(), call.Right) - case ODELETE, OPRINT, OPRINTN, ORECOVER: + case ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: for _, arg := range call.List.Slice() { argument(e.discardHole(), arg) } - case OLEN, OCAP, OREAL, OIMAG, OCLOSE: + case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE: argument(e.discardHole(), call.Left) } } @@ -893,14 +894,14 @@ func (e *Escape) call(ks []EscHole, call, where *Node) { // ks should contain the holes representing where the function // callee's results flows. fn is the statically-known callee function, // if any. -func (e *Escape) tagHole(ks []EscHole, fn *Node, param *types.Field) EscHole { +func (e *Escape) tagHole(ks []EscHole, fn *ir.Node, param *types.Field) EscHole { // If this is a dynamic call, we can't rely on param.Note. if fn == nil { return e.heapHole() } if e.inMutualBatch(fn) { - return e.addr(asNode(param.Nname)) + return e.addr(ir.AsNode(param.Nname)) } // Call to previously tagged function. @@ -934,7 +935,7 @@ func (e *Escape) tagHole(ks []EscHole, fn *Node, param *types.Field) EscHole { // fn has not yet been analyzed, so its parameters and results // should be incorporated directly into the flow graph instead of // relying on its escape analysis tagging. -func (e *Escape) inMutualBatch(fn *Node) bool { +func (e *Escape) inMutualBatch(fn *ir.Node) bool { if fn.Name.Defn != nil && fn.Name.Defn.Esc < EscFuncTagged { if fn.Name.Defn.Esc == EscFuncUnknown { base.Fatalf("graph inconsistency") @@ -959,11 +960,11 @@ type EscHole struct { type EscNote struct { next *EscNote - where *Node + where *ir.Node why string } -func (k EscHole) note(where *Node, why string) EscHole { +func (k EscHole) note(where *ir.Node, why string) EscHole { if where == nil || why == "" { base.Fatalf("note: missing where/why") } @@ -985,10 +986,10 @@ func (k EscHole) shift(delta int) EscHole { return k } -func (k EscHole) deref(where *Node, why string) EscHole { return k.shift(1).note(where, why) } -func (k EscHole) addr(where *Node, why string) EscHole { return k.shift(-1).note(where, why) } +func (k EscHole) deref(where *ir.Node, why string) EscHole { return k.shift(1).note(where, why) } +func (k EscHole) addr(where *ir.Node, why string) EscHole { return k.shift(-1).note(where, why) } -func (k EscHole) dotType(t *types.Type, where *Node, why string) EscHole { +func (k EscHole) dotType(t *types.Type, where *ir.Node, why string) EscHole { if !t.IsInterface() && !isdirectiface(t) { k = k.shift(1) } @@ -1025,7 +1026,7 @@ func (e *Escape) teeHole(ks ...EscHole) EscHole { return loc.asHole() } -func (e *Escape) dcl(n *Node) EscHole { +func (e *Escape) dcl(n *ir.Node) EscHole { loc := e.oldLoc(n) loc.loopDepth = e.loopDepth return loc.asHole() @@ -1034,7 +1035,7 @@ func (e *Escape) dcl(n *Node) EscHole { // spill allocates a new location associated with expression n, flows // its address to k, and returns a hole that flows values to it. It's // intended for use with most expressions that allocate storage. -func (e *Escape) spill(k EscHole, n *Node) EscHole { +func (e *Escape) spill(k EscHole, n *ir.Node) EscHole { loc := e.newLoc(n, true) e.flow(k.addr(n, "spill"), loc) return loc.asHole() @@ -1051,8 +1052,8 @@ func (e *Escape) later(k EscHole) EscHole { // canonicalNode returns the canonical *Node that n logically // represents. -func canonicalNode(n *Node) *Node { - if n != nil && n.Op == ONAME && n.Name.IsClosureVar() { +func canonicalNode(n *ir.Node) *ir.Node { + if n != nil && n.Op == ir.ONAME && n.Name.IsClosureVar() { n = n.Name.Defn if n.Name.IsClosureVar() { base.Fatalf("still closure var") @@ -1062,7 +1063,7 @@ func canonicalNode(n *Node) *Node { return n } -func (e *Escape) newLoc(n *Node, transient bool) *EscLocation { +func (e *Escape) newLoc(n *ir.Node, transient bool) *EscLocation { if e.curfn == nil { base.Fatalf("e.curfn isn't set") } @@ -1079,7 +1080,7 @@ func (e *Escape) newLoc(n *Node, transient bool) *EscLocation { } e.allLocs = append(e.allLocs, loc) if n != nil { - if n.Op == ONAME && n.Name.Curfn != e.curfn { + if n.Op == ir.ONAME && n.Name.Curfn != e.curfn { base.Fatalf("curfn mismatch: %v != %v", n.Name.Curfn, e.curfn) } @@ -1095,7 +1096,7 @@ func (e *Escape) newLoc(n *Node, transient bool) *EscLocation { return loc } -func (e *Escape) oldLoc(n *Node) *EscLocation { +func (e *Escape) oldLoc(n *ir.Node) *EscLocation { n = canonicalNode(n) return n.Opt().(*EscLocation) } @@ -1120,7 +1121,7 @@ func (e *Escape) flow(k EscHole, src *EscLocation) { } explanation := e.explainFlow(pos, dst, src, k.derefs, k.notes, []*logopt.LoggedOpt{}) if logopt.Enabled() { - logopt.LogOpt(src.n.Pos, "escapes", "escape", e.curfn.funcname(), fmt.Sprintf("%v escapes to heap", src.n), explanation) + logopt.LogOpt(src.n.Pos, "escapes", "escape", ir.FuncName(e.curfn), fmt.Sprintf("%v escapes to heap", src.n), explanation) } } @@ -1214,14 +1215,14 @@ func (e *Escape) walkOne(root *EscLocation, walkgen uint32, enqueue func(*EscLoc // corresponding result parameter, then record // that value flow for tagging the function // later. - if l.isName(PPARAM) { + if l.isName(ir.PPARAM) { if (logopt.Enabled() || base.Flag.LowerM >= 2) && !l.escapes { if base.Flag.LowerM >= 2 { fmt.Printf("%s: parameter %v leaks to %s with derefs=%d:\n", base.FmtPos(l.n.Pos), l.n, e.explainLoc(root), derefs) } explanation := e.explainPath(root, l) if logopt.Enabled() { - logopt.LogOpt(l.n.Pos, "leak", "escape", e.curfn.funcname(), + logopt.LogOpt(l.n.Pos, "leak", "escape", ir.FuncName(e.curfn), fmt.Sprintf("parameter %v leaks to %s with derefs=%d", l.n, e.explainLoc(root), derefs), explanation) } } @@ -1238,7 +1239,7 @@ func (e *Escape) walkOne(root *EscLocation, walkgen uint32, enqueue func(*EscLoc } explanation := e.explainPath(root, l) if logopt.Enabled() { - logopt.LogOpt(l.n.Pos, "escape", "escape", e.curfn.funcname(), fmt.Sprintf("%v escapes to heap", l.n), explanation) + logopt.LogOpt(l.n.Pos, "escape", "escape", ir.FuncName(e.curfn), fmt.Sprintf("%v escapes to heap", l.n), explanation) } } l.escapes = true @@ -1312,7 +1313,7 @@ func (e *Escape) explainFlow(pos string, dst, srcloc *EscLocation, derefs int, n } else if srcloc != nil && srcloc.n != nil { epos = srcloc.n.Pos } - explanation = append(explanation, logopt.NewLoggedOpt(epos, "escflow", "escape", e.curfn.funcname(), flow)) + explanation = append(explanation, logopt.NewLoggedOpt(epos, "escflow", "escape", ir.FuncName(e.curfn), flow)) } for note := notes; note != nil; note = note.next { @@ -1320,7 +1321,7 @@ func (e *Escape) explainFlow(pos string, dst, srcloc *EscLocation, derefs int, n fmt.Printf("%s: from %v (%v) at %s\n", pos, note.where, note.why, base.FmtPos(note.where.Pos)) } if logopt.Enabled() { - explanation = append(explanation, logopt.NewLoggedOpt(note.where.Pos, "escflow", "escape", e.curfn.funcname(), + explanation = append(explanation, logopt.NewLoggedOpt(note.where.Pos, "escflow", "escape", ir.FuncName(e.curfn), fmt.Sprintf(" from %v (%v)", note.where, note.why))) } } @@ -1335,7 +1336,7 @@ func (e *Escape) explainLoc(l *EscLocation) string { // TODO(mdempsky): Omit entirely. return "{temp}" } - if l.n.Op == ONAME { + if l.n.Op == ir.ONAME { return fmt.Sprintf("%v", l.n) } return fmt.Sprintf("{storage for %v}", l.n) @@ -1352,7 +1353,7 @@ func (e *Escape) outlives(l, other *EscLocation) bool { // We don't know what callers do with returned values, so // pessimistically we need to assume they flow to the heap and // outlive everything too. - if l.isName(PPARAMOUT) { + if l.isName(ir.PPARAMOUT) { // Exception: Directly called closures can return // locations allocated outside of them without forcing // them to the heap. For example: @@ -1393,8 +1394,8 @@ func (e *Escape) outlives(l, other *EscLocation) bool { } // containsClosure reports whether c is a closure contained within f. -func containsClosure(f, c *Node) bool { - if f.Op != ODCLFUNC || c.Op != ODCLFUNC { +func containsClosure(f, c *ir.Node) bool { + if f.Op != ir.ODCLFUNC || c.Op != ir.ODCLFUNC { base.Fatalf("bad containsClosure: %v, %v", f, c) } @@ -1414,7 +1415,7 @@ func containsClosure(f, c *Node) bool { func (l *EscLocation) leakTo(sink *EscLocation, derefs int) { // If sink is a result parameter and we can fit return bits // into the escape analysis tag, then record a return leak. - if sink.isName(PPARAMOUT) && sink.curfn == l.curfn { + if sink.isName(ir.PPARAMOUT) && sink.curfn == l.curfn { // TODO(mdempsky): Eliminate dependency on Vargen here. ri := int(sink.n.Name.Vargen) - 1 if ri < numEscResults { @@ -1428,7 +1429,7 @@ func (l *EscLocation) leakTo(sink *EscLocation, derefs int) { l.paramEsc.AddHeap(derefs) } -func (e *Escape) finish(fns []*Node) { +func (e *Escape) finish(fns []*ir.Node) { // Record parameter tags for package export data. for _, fn := range fns { fn.Esc = EscFuncTagged @@ -1452,18 +1453,18 @@ func (e *Escape) finish(fns []*Node) { // Update n.Esc based on escape analysis results. if loc.escapes { - if n.Op != ONAME { + if n.Op != ir.ONAME { if base.Flag.LowerM != 0 { base.WarnfAt(n.Pos, "%S escapes to heap", n) } if logopt.Enabled() { - logopt.LogOpt(n.Pos, "escape", "escape", e.curfn.funcname()) + logopt.LogOpt(n.Pos, "escape", "escape", ir.FuncName(e.curfn)) } } n.Esc = EscHeap addrescapes(n) } else { - if base.Flag.LowerM != 0 && n.Op != ONAME { + if base.Flag.LowerM != 0 && n.Op != ir.ONAME { base.WarnfAt(n.Pos, "%S does not escape", n) } n.Esc = EscNone @@ -1474,8 +1475,8 @@ func (e *Escape) finish(fns []*Node) { } } -func (l *EscLocation) isName(c Class) bool { - return l.n != nil && l.n.Op == ONAME && l.n.Class() == c +func (l *EscLocation) isName(c ir.Class) bool { + return l.n != nil && l.n.Op == ir.ONAME && l.n.Class() == c } const numEscResults = 7 @@ -1572,3 +1573,466 @@ func ParseLeaks(s string) EscLeaks { copy(l[:], s[4:]) return l } + +func escapes(all []*ir.Node) { + visitBottomUp(all, escapeFuncs) +} + +const ( + EscFuncUnknown = 0 + iota + EscFuncPlanned + EscFuncStarted + EscFuncTagged +) + +func min8(a, b int8) int8 { + if a < b { + return a + } + return b +} + +func max8(a, b int8) int8 { + if a > b { + return a + } + return b +} + +const ( + EscUnknown = iota + EscNone // Does not escape to heap, result, or parameters. + EscHeap // Reachable from the heap + EscNever // By construction will not escape. +) + +// funcSym returns fn.Func.Nname.Sym if no nils are encountered along the way. +func funcSym(fn *ir.Node) *types.Sym { + if fn == nil || fn.Func.Nname == nil { + return nil + } + return fn.Func.Nname.Sym +} + +// Mark labels that have no backjumps to them as not increasing e.loopdepth. +// Walk hasn't generated (goto|label).Left.Sym.Label yet, so we'll cheat +// and set it to one of the following two. Then in esc we'll clear it again. +var ( + looping = ir.Nod(ir.OXXX, nil, nil) + nonlooping = ir.Nod(ir.OXXX, nil, nil) +) + +func isSliceSelfAssign(dst, src *ir.Node) bool { + // Detect the following special case. + // + // func (b *Buffer) Foo() { + // n, m := ... + // b.buf = b.buf[n:m] + // } + // + // This assignment is a no-op for escape analysis, + // it does not store any new pointers into b that were not already there. + // However, without this special case b will escape, because we assign to OIND/ODOTPTR. + // Here we assume that the statement will not contain calls, + // that is, that order will move any calls to init. + // Otherwise base ONAME value could change between the moments + // when we evaluate it for dst and for src. + + // dst is ONAME dereference. + if dst.Op != ir.ODEREF && dst.Op != ir.ODOTPTR || dst.Left.Op != ir.ONAME { + return false + } + // src is a slice operation. + switch src.Op { + case ir.OSLICE, ir.OSLICE3, ir.OSLICESTR: + // OK. + case ir.OSLICEARR, ir.OSLICE3ARR: + // Since arrays are embedded into containing object, + // slice of non-pointer array will introduce a new pointer into b that was not already there + // (pointer to b itself). After such assignment, if b contents escape, + // b escapes as well. If we ignore such OSLICEARR, we will conclude + // that b does not escape when b contents do. + // + // Pointer to an array is OK since it's not stored inside b directly. + // For slicing an array (not pointer to array), there is an implicit OADDR. + // We check that to determine non-pointer array slicing. + if src.Left.Op == ir.OADDR { + return false + } + default: + return false + } + // slice is applied to ONAME dereference. + if src.Left.Op != ir.ODEREF && src.Left.Op != ir.ODOTPTR || src.Left.Left.Op != ir.ONAME { + return false + } + // dst and src reference the same base ONAME. + return dst.Left == src.Left.Left +} + +// isSelfAssign reports whether assignment from src to dst can +// be ignored by the escape analysis as it's effectively a self-assignment. +func isSelfAssign(dst, src *ir.Node) bool { + if isSliceSelfAssign(dst, src) { + return true + } + + // Detect trivial assignments that assign back to the same object. + // + // It covers these cases: + // val.x = val.y + // val.x[i] = val.y[j] + // val.x1.x2 = val.x1.y2 + // ... etc + // + // These assignments do not change assigned object lifetime. + + if dst == nil || src == nil || dst.Op != src.Op { + return false + } + + switch dst.Op { + case ir.ODOT, ir.ODOTPTR: + // Safe trailing accessors that are permitted to differ. + case ir.OINDEX: + if mayAffectMemory(dst.Right) || mayAffectMemory(src.Right) { + return false + } + default: + return false + } + + // The expression prefix must be both "safe" and identical. + return samesafeexpr(dst.Left, src.Left) +} + +// mayAffectMemory reports whether evaluation of n may affect the program's +// memory state. If the expression can't affect memory state, then it can be +// safely ignored by the escape analysis. +func mayAffectMemory(n *ir.Node) bool { + // We may want to use a list of "memory safe" ops instead of generally + // "side-effect free", which would include all calls and other ops that can + // allocate or change global state. For now, it's safer to start with the latter. + // + // We're ignoring things like division by zero, index out of range, + // and nil pointer dereference here. + switch n.Op { + case ir.ONAME, ir.OCLOSUREVAR, ir.OLITERAL, ir.ONIL: + return false + + // Left+Right group. + case ir.OINDEX, ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD: + return mayAffectMemory(n.Left) || mayAffectMemory(n.Right) + + // Left group. + case ir.ODOT, ir.ODOTPTR, ir.ODEREF, ir.OCONVNOP, ir.OCONV, ir.OLEN, ir.OCAP, + ir.ONOT, ir.OBITNOT, ir.OPLUS, ir.ONEG, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: + return mayAffectMemory(n.Left) + + default: + return true + } +} + +// heapAllocReason returns the reason the given Node must be heap +// allocated, or the empty string if it doesn't. +func heapAllocReason(n *ir.Node) string { + if n.Type == nil { + return "" + } + + // Parameters are always passed via the stack. + if n.Op == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) { + return "" + } + + if n.Type.Width > maxStackVarSize { + return "too large for stack" + } + + if (n.Op == ir.ONEW || n.Op == ir.OPTRLIT) && n.Type.Elem().Width >= maxImplicitStackVarSize { + return "too large for stack" + } + + if n.Op == ir.OCLOSURE && closureType(n).Size() >= maxImplicitStackVarSize { + return "too large for stack" + } + if n.Op == ir.OCALLPART && partialCallType(n).Size() >= maxImplicitStackVarSize { + return "too large for stack" + } + + if n.Op == ir.OMAKESLICE { + r := n.Right + if r == nil { + r = n.Left + } + if !smallintconst(r) { + return "non-constant size" + } + if t := n.Type; t.Elem().Width != 0 && r.Int64Val() >= maxImplicitStackVarSize/t.Elem().Width { + return "too large for stack" + } + } + + return "" +} + +// addrescapes tags node n as having had its address taken +// by "increasing" the "value" of n.Esc to EscHeap. +// Storage is allocated as necessary to allow the address +// to be taken. +func addrescapes(n *ir.Node) { + switch n.Op { + default: + // Unexpected Op, probably due to a previous type error. Ignore. + + case ir.ODEREF, ir.ODOTPTR: + // Nothing to do. + + case ir.ONAME: + if n == nodfp { + break + } + + // if this is a tmpname (PAUTO), it was tagged by tmpname as not escaping. + // on PPARAM it means something different. + if n.Class() == ir.PAUTO && n.Esc == EscNever { + break + } + + // If a closure reference escapes, mark the outer variable as escaping. + if n.Name.IsClosureVar() { + addrescapes(n.Name.Defn) + break + } + + if n.Class() != ir.PPARAM && n.Class() != ir.PPARAMOUT && n.Class() != ir.PAUTO { + break + } + + // This is a plain parameter or local variable that needs to move to the heap, + // but possibly for the function outside the one we're compiling. + // That is, if we have: + // + // func f(x int) { + // func() { + // global = &x + // } + // } + // + // then we're analyzing the inner closure but we need to move x to the + // heap in f, not in the inner closure. Flip over to f before calling moveToHeap. + oldfn := Curfn + Curfn = n.Name.Curfn + if Curfn.Op == ir.OCLOSURE { + Curfn = Curfn.Func.Decl + panic("can't happen") + } + ln := base.Pos + base.Pos = Curfn.Pos + moveToHeap(n) + Curfn = oldfn + base.Pos = ln + + // ODOTPTR has already been introduced, + // so these are the non-pointer ODOT and OINDEX. + // In &x[0], if x is a slice, then x does not + // escape--the pointer inside x does, but that + // is always a heap pointer anyway. + case ir.ODOT, ir.OINDEX, ir.OPAREN, ir.OCONVNOP: + if !n.Left.Type.IsSlice() { + addrescapes(n.Left) + } + } +} + +// moveToHeap records the parameter or local variable n as moved to the heap. +func moveToHeap(n *ir.Node) { + if base.Flag.LowerR != 0 { + ir.Dump("MOVE", n) + } + if base.Flag.CompilingRuntime { + base.Errorf("%v escapes to heap, not allowed in runtime", n) + } + if n.Class() == ir.PAUTOHEAP { + ir.Dump("n", n) + base.Fatalf("double move to heap") + } + + // Allocate a local stack variable to hold the pointer to the heap copy. + // temp will add it to the function declaration list automatically. + heapaddr := temp(types.NewPtr(n.Type)) + heapaddr.Sym = lookup("&" + n.Sym.Name) + heapaddr.Orig.Sym = heapaddr.Sym + heapaddr.Pos = n.Pos + + // Unset AutoTemp to persist the &foo variable name through SSA to + // liveness analysis. + // TODO(mdempsky/drchase): Cleaner solution? + heapaddr.Name.SetAutoTemp(false) + + // Parameters have a local stack copy used at function start/end + // in addition to the copy in the heap that may live longer than + // the function. + if n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT { + if n.Xoffset == types.BADWIDTH { + base.Fatalf("addrescapes before param assignment") + } + + // We rewrite n below to be a heap variable (indirection of heapaddr). + // Preserve a copy so we can still write code referring to the original, + // and substitute that copy into the function declaration list + // so that analyses of the local (on-stack) variables use it. + stackcopy := NewName(n.Sym) + stackcopy.Type = n.Type + stackcopy.Xoffset = n.Xoffset + stackcopy.SetClass(n.Class()) + stackcopy.Name.Param.Heapaddr = heapaddr + if n.Class() == ir.PPARAMOUT { + // Make sure the pointer to the heap copy is kept live throughout the function. + // The function could panic at any point, and then a defer could recover. + // Thus, we need the pointer to the heap copy always available so the + // post-deferreturn code can copy the return value back to the stack. + // See issue 16095. + heapaddr.Name.SetIsOutputParamHeapAddr(true) + } + n.Name.Param.Stackcopy = stackcopy + + // Substitute the stackcopy into the function variable list so that + // liveness and other analyses use the underlying stack slot + // and not the now-pseudo-variable n. + found := false + for i, d := range Curfn.Func.Dcl { + if d == n { + Curfn.Func.Dcl[i] = stackcopy + found = true + break + } + // Parameters are before locals, so can stop early. + // This limits the search even in functions with many local variables. + if d.Class() == ir.PAUTO { + break + } + } + if !found { + base.Fatalf("cannot find %v in local variable list", n) + } + Curfn.Func.Dcl = append(Curfn.Func.Dcl, n) + } + + // Modify n in place so that uses of n now mean indirection of the heapaddr. + n.SetClass(ir.PAUTOHEAP) + n.Xoffset = 0 + n.Name.Param.Heapaddr = heapaddr + n.Esc = EscHeap + if base.Flag.LowerM != 0 { + base.WarnfAt(n.Pos, "moved to heap: %v", n) + } +} + +// This special tag is applied to uintptr variables +// that we believe may hold unsafe.Pointers for +// calls into assembly functions. +const unsafeUintptrTag = "unsafe-uintptr" + +// This special tag is applied to uintptr parameters of functions +// marked go:uintptrescapes. +const uintptrEscapesTag = "uintptr-escapes" + +func (e *Escape) paramTag(fn *ir.Node, narg int, f *types.Field) string { + name := func() string { + if f.Sym != nil { + return f.Sym.Name + } + return fmt.Sprintf("arg#%d", narg) + } + + if fn.Nbody.Len() == 0 { + // Assume that uintptr arguments must be held live across the call. + // This is most important for syscall.Syscall. + // See golang.org/issue/13372. + // This really doesn't have much to do with escape analysis per se, + // but we are reusing the ability to annotate an individual function + // argument and pass those annotations along to importing code. + if f.Type.IsUintptr() { + if base.Flag.LowerM != 0 { + base.WarnfAt(f.Pos, "assuming %v is unsafe uintptr", name()) + } + return unsafeUintptrTag + } + + if !f.Type.HasPointers() { // don't bother tagging for scalars + return "" + } + + var esc EscLeaks + + // External functions are assumed unsafe, unless + // //go:noescape is given before the declaration. + if fn.Func.Pragma&ir.Noescape != 0 { + if base.Flag.LowerM != 0 && f.Sym != nil { + base.WarnfAt(f.Pos, "%v does not escape", name()) + } + } else { + if base.Flag.LowerM != 0 && f.Sym != nil { + base.WarnfAt(f.Pos, "leaking param: %v", name()) + } + esc.AddHeap(0) + } + + return esc.Encode() + } + + if fn.Func.Pragma&ir.UintptrEscapes != 0 { + if f.Type.IsUintptr() { + if base.Flag.LowerM != 0 { + base.WarnfAt(f.Pos, "marking %v as escaping uintptr", name()) + } + return uintptrEscapesTag + } + if f.IsDDD() && f.Type.Elem().IsUintptr() { + // final argument is ...uintptr. + if base.Flag.LowerM != 0 { + base.WarnfAt(f.Pos, "marking %v as escaping ...uintptr", name()) + } + return uintptrEscapesTag + } + } + + if !f.Type.HasPointers() { // don't bother tagging for scalars + return "" + } + + // Unnamed parameters are unused and therefore do not escape. + if f.Sym == nil || f.Sym.IsBlank() { + var esc EscLeaks + return esc.Encode() + } + + n := ir.AsNode(f.Nname) + loc := e.oldLoc(n) + esc := loc.paramEsc + esc.Optimize() + + if base.Flag.LowerM != 0 && !loc.escapes { + if esc.Empty() { + base.WarnfAt(f.Pos, "%v does not escape", name()) + } + if x := esc.Heap(); x >= 0 { + if x == 0 { + base.WarnfAt(f.Pos, "leaking param: %v", name()) + } else { + // TODO(mdempsky): Mention level=x like below? + base.WarnfAt(f.Pos, "leaking param content: %v", name()) + } + } + for i := 0; i < numEscResults; i++ { + if x := esc.Result(i); x >= 0 { + res := fn.Type.Results().Field(i).Sym + base.WarnfAt(f.Pos, "leaking param: %v to result %v level=%d", name(), res, x) + } + } + } + + return esc.Encode() +} diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 1fa64fbe449..36bbb750507 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/bio" "cmd/internal/src" @@ -20,10 +21,10 @@ func exportf(bout *bio.Writer, format string, args ...interface{}) { } } -var asmlist []*Node +var asmlist []*ir.Node // exportsym marks n for export (or reexport). -func exportsym(n *Node) { +func exportsym(n *ir.Node) { if n.Sym.OnExportList() { return } @@ -40,14 +41,14 @@ func initname(s string) bool { return s == "init" } -func autoexport(n *Node, ctxt Class) { - if n.Sym.Pkg != localpkg { +func autoexport(n *ir.Node, ctxt ir.Class) { + if n.Sym.Pkg != ir.LocalPkg { return } - if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN { + if (ctxt != ir.PEXTERN && ctxt != ir.PFUNC) || dclcontext != ir.PEXTERN { return } - if n.Type != nil && n.Type.IsKind(TFUNC) && n.IsMethod() { + if n.Type != nil && n.Type.IsKind(types.TFUNC) && ir.IsMethod(n) { return } @@ -73,8 +74,8 @@ func dumpexport(bout *bio.Writer) { } } -func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node { - n := asNode(s.PkgDef()) +func importsym(ipkg *types.Pkg, s *types.Sym, op ir.Op) *ir.Node { + n := ir.AsNode(s.PkgDef()) if n == nil { // iimport should have created a stub ONONAME // declaration for all imported symbols. The exception @@ -85,10 +86,10 @@ func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node { } n = dclname(s) - s.SetPkgDef(asTypesNode(n)) + s.SetPkgDef(ir.AsTypesNode(n)) s.Importdef = ipkg } - if n.Op != ONONAME && n.Op != op { + if n.Op != ir.ONONAME && n.Op != op { redeclare(base.Pos, s, fmt.Sprintf("during import %q", ipkg.Path)) } return n @@ -98,16 +99,16 @@ func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node { // If no such type has been declared yet, a forward declaration is returned. // ipkg is the package being imported func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type { - n := importsym(ipkg, s, OTYPE) - if n.Op != OTYPE { - t := types.New(TFORW) + n := importsym(ipkg, s, ir.OTYPE) + if n.Op != ir.OTYPE { + t := types.New(types.TFORW) t.Sym = s - t.Nod = asTypesNode(n) + t.Nod = ir.AsTypesNode(n) - n.Op = OTYPE + n.Op = ir.OTYPE n.Pos = pos n.Type = t - n.SetClass(PEXTERN) + n.SetClass(ir.PEXTERN) } t := n.Type @@ -119,9 +120,9 @@ func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type { // importobj declares symbol s as an imported object representable by op. // ipkg is the package being imported -func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t *types.Type) *Node { +func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class, t *types.Type) *ir.Node { n := importsym(ipkg, s, op) - if n.Op != ONONAME { + if n.Op != ir.ONONAME { if n.Op == op && (n.Class() != ctxt || !types.Identical(n.Type, t)) { redeclare(base.Pos, s, fmt.Sprintf("during import %q", ipkg.Path)) } @@ -131,7 +132,7 @@ func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t n.Op = op n.Pos = pos n.SetClass(ctxt) - if ctxt == PFUNC { + if ctxt == ir.PFUNC { n.Sym.SetFunc(true) } n.Type = t @@ -141,7 +142,7 @@ func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t // importconst declares symbol s as an imported constant with type t and value val. // ipkg is the package being imported func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val constant.Value) { - n := importobj(ipkg, pos, s, OLITERAL, PEXTERN, t) + n := importobj(ipkg, pos, s, ir.OLITERAL, ir.PEXTERN, t) if n == nil { // TODO: Check that value matches. return } @@ -156,12 +157,12 @@ func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val // importfunc declares symbol s as an imported function with type t. // ipkg is the package being imported func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) { - n := importobj(ipkg, pos, s, ONAME, PFUNC, t) + n := importobj(ipkg, pos, s, ir.ONAME, ir.PFUNC, t) if n == nil { return } - n.Func = new(Func) + n.Func = new(ir.Func) if base.Flag.E != 0 { fmt.Printf("import func %v%S\n", s, t) @@ -171,7 +172,7 @@ func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) { // importvar declares symbol s as an imported variable with type t. // ipkg is the package being imported func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) { - n := importobj(ipkg, pos, s, ONAME, PEXTERN, t) + n := importobj(ipkg, pos, s, ir.ONAME, ir.PEXTERN, t) if n == nil { return } @@ -184,7 +185,7 @@ func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) { // importalias declares symbol s as an imported type alias with type t. // ipkg is the package being imported func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) { - n := importobj(ipkg, pos, s, OTYPE, PEXTERN, t) + n := importobj(ipkg, pos, s, ir.OTYPE, ir.PEXTERN, t) if n == nil { return } @@ -199,20 +200,20 @@ func dumpasmhdr() { if err != nil { base.Fatalf("%v", err) } - fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", localpkg.Name) + fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", ir.LocalPkg.Name) for _, n := range asmlist { if n.Sym.IsBlank() { continue } switch n.Op { - case OLITERAL: + case ir.OLITERAL: t := n.Val().Kind() if t == constant.Float || t == constant.Complex { break } fmt.Fprintf(b, "#define const_%s %#v\n", n.Sym.Name, n.Val()) - case OTYPE: + case ir.OTYPE: t := n.Type if !t.IsStruct() || t.StructType().Map != nil || t.IsFuncArgStruct() { break diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index a70bddca813..0f5294b17d1 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/src" @@ -29,14 +30,14 @@ func sysvar(name string) *obj.LSym { // isParamStackCopy reports whether this is the on-stack copy of a // function parameter that moved to the heap. -func (n *Node) isParamStackCopy() bool { - return n.Op == ONAME && (n.Class() == PPARAM || n.Class() == PPARAMOUT) && n.Name.Param.Heapaddr != nil +func isParamStackCopy(n *ir.Node) bool { + return n.Op == ir.ONAME && (n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Name.Param.Heapaddr != nil } // isParamHeapCopy reports whether this is the on-heap copy of // a function parameter that moved to the heap. -func (n *Node) isParamHeapCopy() bool { - return n.Op == ONAME && n.Class() == PAUTOHEAP && n.Name.Param.Stackcopy != nil +func isParamHeapCopy(n *ir.Node) bool { + return n.Op == ir.ONAME && n.Class() == ir.PAUTOHEAP && n.Name.Param.Stackcopy != nil } // autotmpname returns the name for an autotmp variable numbered n. @@ -51,12 +52,12 @@ func autotmpname(n int) string { } // make a new Node off the books -func tempAt(pos src.XPos, curfn *Node, t *types.Type) *Node { +func tempAt(pos src.XPos, curfn *ir.Node, t *types.Type) *ir.Node { if curfn == nil { base.Fatalf("no curfn for tempAt") } - if curfn.Op == OCLOSURE { - Dump("tempAt", curfn) + if curfn.Op == ir.OCLOSURE { + ir.Dump("tempAt", curfn) base.Fatalf("adding tempAt to wrong closure function") } if t == nil { @@ -65,12 +66,12 @@ func tempAt(pos src.XPos, curfn *Node, t *types.Type) *Node { s := &types.Sym{ Name: autotmpname(len(curfn.Func.Dcl)), - Pkg: localpkg, + Pkg: ir.LocalPkg, } - n := newnamel(pos, s) - s.Def = asTypesNode(n) + n := ir.NewNameAt(pos, s) + s.Def = ir.AsTypesNode(n) n.Type = t - n.SetClass(PAUTO) + n.SetClass(ir.PAUTO) n.Esc = EscNever n.Name.Curfn = curfn n.Name.SetUsed(true) @@ -82,6 +83,6 @@ func tempAt(pos src.XPos, curfn *Node, t *types.Type) *Node { return n.Orig } -func temp(t *types.Type) *Node { +func temp(t *types.Type) *ir.Node { return tempAt(base.Pos, Curfn, t) } diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index d9b8f704a93..8642cc4a305 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/ssa" "cmd/compile/internal/types" "cmd/internal/obj" @@ -13,10 +14,6 @@ import ( "sync" ) -const ( - BADWIDTH = types.BADWIDTH -) - var ( // maximum size variable which we will allocate on the stack. // This limit is for explicit variable declarations like "var x T" or "x := ...". @@ -40,7 +37,7 @@ var ( // isRuntimePkg reports whether p is package runtime. func isRuntimePkg(p *types.Pkg) bool { - if base.Flag.CompilingRuntime && p == localpkg { + if base.Flag.CompilingRuntime && p == ir.LocalPkg { return true } return p.Path == "runtime" @@ -48,31 +45,12 @@ func isRuntimePkg(p *types.Pkg) bool { // isReflectPkg reports whether p is package reflect. func isReflectPkg(p *types.Pkg) bool { - if p == localpkg { + if p == ir.LocalPkg { return base.Ctxt.Pkgpath == "reflect" } return p.Path == "reflect" } -// The Class of a variable/function describes the "storage class" -// of a variable or function. During parsing, storage classes are -// called declaration contexts. -type Class uint8 - -//go:generate stringer -type=Class -const ( - Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables - PEXTERN // global variables - PAUTO // local variables - PAUTOHEAP // local variables or parameters moved to heap - PPARAM // input arguments - PPARAMOUT // output results - PFUNC // global functions - - // Careful: Class is stored in three bits in Node.flags. - _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3) -) - // Slices in the runtime are represented by three components: // // type slice struct { @@ -102,8 +80,6 @@ var pragcgobuf [][]string var decldepth int32 -var localpkg *types.Pkg // package being compiled - var inimport bool // set during import var itabpkg *types.Pkg // fake pkg for itab entries @@ -126,55 +102,51 @@ var gopkg *types.Pkg // pseudo-package for method symbols on anonymous receiver var zerosize int64 -var simtype [NTYPE]types.EType +var simtype [types.NTYPE]types.EType var ( - isInt [NTYPE]bool - isFloat [NTYPE]bool - isComplex [NTYPE]bool - issimple [NTYPE]bool + isInt [types.NTYPE]bool + isFloat [types.NTYPE]bool + isComplex [types.NTYPE]bool + issimple [types.NTYPE]bool ) var ( - okforeq [NTYPE]bool - okforadd [NTYPE]bool - okforand [NTYPE]bool - okfornone [NTYPE]bool - okforcmp [NTYPE]bool - okforbool [NTYPE]bool - okforcap [NTYPE]bool - okforlen [NTYPE]bool - okforarith [NTYPE]bool + okforeq [types.NTYPE]bool + okforadd [types.NTYPE]bool + okforand [types.NTYPE]bool + okfornone [types.NTYPE]bool + okforcmp [types.NTYPE]bool + okforbool [types.NTYPE]bool + okforcap [types.NTYPE]bool + okforlen [types.NTYPE]bool + okforarith [types.NTYPE]bool ) -var okforconst [NTYPE]bool - var ( - okfor [OEND][]bool - iscmp [OEND]bool + okfor [ir.OEND][]bool + iscmp [ir.OEND]bool ) -var xtop []*Node +var xtop []*ir.Node -var exportlist []*Node +var exportlist []*ir.Node -var importlist []*Node // imported functions and methods with inlinable bodies +var importlist []*ir.Node // imported functions and methods with inlinable bodies var ( funcsymsmu sync.Mutex // protects funcsyms and associated package lookups (see func funcsym) funcsyms []*types.Sym ) -var dclcontext Class // PEXTERN/PAUTO +var dclcontext ir.Class // PEXTERN/PAUTO -var Curfn *Node +var Curfn *ir.Node var Widthptr int var Widthreg int -var nblank *Node - var typecheckok bool // Whether we are adding any sort of code instrumentation, such as @@ -184,7 +156,7 @@ var instrumenting bool // Whether we are tracking lexical scopes for DWARF. var trackScopes bool -var nodfp *Node +var nodfp *ir.Node var autogeneratedPos src.XPos @@ -221,7 +193,7 @@ var thearch Arch var ( staticuint64s, - zerobase *Node + zerobase *ir.Node assertE2I, assertE2I2, diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go index 92a3611cb78..cf1c85ce292 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -32,6 +32,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/ssa" "cmd/internal/obj" "cmd/internal/objabi" @@ -46,7 +47,7 @@ type Progs struct { next *obj.Prog // next Prog pc int64 // virtual PC; count of Progs pos src.XPos // position to use for new Progs - curfn *Node // fn these Progs are for + curfn *ir.Node // fn these Progs are for progcache []obj.Prog // local progcache cacheidx int // first free element of progcache @@ -56,7 +57,7 @@ type Progs struct { // newProgs returns a new Progs for fn. // worker indicates which of the backend workers will use the Progs. -func newProgs(fn *Node, worker int) *Progs { +func newProgs(fn *ir.Node, worker int) *Progs { pp := new(Progs) if base.Ctxt.CanReuseProgs() { sz := len(sharedProgArray) / base.Flag.LowerC @@ -173,17 +174,17 @@ func (pp *Progs) Appendpp(p *obj.Prog, as obj.As, ftype obj.AddrType, freg int16 return q } -func (pp *Progs) settext(fn *Node) { +func (pp *Progs) settext(fn *ir.Node) { if pp.Text != nil { base.Fatalf("Progs.settext called twice") } ptxt := pp.Prog(obj.ATEXT) pp.Text = ptxt - fn.Func.lsym.Func().Text = ptxt + fn.Func.LSym.Func().Text = ptxt ptxt.From.Type = obj.TYPE_MEM ptxt.From.Name = obj.NAME_EXTERN - ptxt.From.Sym = fn.Func.lsym + ptxt.From.Sym = fn.Func.LSym } // initLSym defines f's obj.LSym and initializes it based on the @@ -192,36 +193,36 @@ func (pp *Progs) settext(fn *Node) { // // initLSym must be called exactly once per function and must be // called for both functions with bodies and functions without bodies. -func (f *Func) initLSym(hasBody bool) { - if f.lsym != nil { +func initLSym(f *ir.Func, hasBody bool) { + if f.LSym != nil { base.Fatalf("Func.initLSym called twice") } - if nam := f.Nname; !nam.isBlank() { - f.lsym = nam.Sym.Linksym() - if f.Pragma&Systemstack != 0 { - f.lsym.Set(obj.AttrCFunc, true) + if nam := f.Nname; !ir.IsBlank(nam) { + f.LSym = nam.Sym.Linksym() + if f.Pragma&ir.Systemstack != 0 { + f.LSym.Set(obj.AttrCFunc, true) } var aliasABI obj.ABI needABIAlias := false - defABI, hasDefABI := symabiDefs[f.lsym.Name] + defABI, hasDefABI := symabiDefs[f.LSym.Name] if hasDefABI && defABI == obj.ABI0 { // Symbol is defined as ABI0. Create an // Internal -> ABI0 wrapper. - f.lsym.SetABI(obj.ABI0) + f.LSym.SetABI(obj.ABI0) needABIAlias, aliasABI = true, obj.ABIInternal } else { // No ABI override. Check that the symbol is // using the expected ABI. want := obj.ABIInternal - if f.lsym.ABI() != want { - base.Fatalf("function symbol %s has the wrong ABI %v, expected %v", f.lsym.Name, f.lsym.ABI(), want) + if f.LSym.ABI() != want { + base.Fatalf("function symbol %s has the wrong ABI %v, expected %v", f.LSym.Name, f.LSym.ABI(), want) } } isLinknameExported := nam.Sym.Linkname != "" && (hasBody || hasDefABI) - if abi, ok := symabiRefs[f.lsym.Name]; (ok && abi == obj.ABI0) || isLinknameExported { + if abi, ok := symabiRefs[f.LSym.Name]; (ok && abi == obj.ABI0) || isLinknameExported { // Either 1) this symbol is definitely // referenced as ABI0 from this package; or 2) // this symbol is defined in this package but @@ -233,7 +234,7 @@ func (f *Func) initLSym(hasBody bool) { // since other packages may "pull" symbols // using linkname and we don't want to create // duplicate ABI wrappers. - if f.lsym.ABI() != obj.ABI0 { + if f.LSym.ABI() != obj.ABI0 { needABIAlias, aliasABI = true, obj.ABI0 } } @@ -244,9 +245,9 @@ func (f *Func) initLSym(hasBody bool) { // rather than looking them up. The uniqueness // of f.lsym ensures uniqueness of asym. asym := &obj.LSym{ - Name: f.lsym.Name, + Name: f.LSym.Name, Type: objabi.SABIALIAS, - R: []obj.Reloc{{Sym: f.lsym}}, // 0 size, so "informational" + R: []obj.Reloc{{Sym: f.LSym}}, // 0 size, so "informational" } asym.SetABI(aliasABI) asym.Set(obj.AttrDuplicateOK, true) @@ -269,7 +270,7 @@ func (f *Func) initLSym(hasBody bool) { if f.Needctxt() { flag |= obj.NEEDCTXT } - if f.Pragma&Nosplit != 0 { + if f.Pragma&ir.Nosplit != 0 { flag |= obj.NOSPLIT } if f.ReflectMethod() { @@ -286,10 +287,10 @@ func (f *Func) initLSym(hasBody bool) { } } - base.Ctxt.InitTextSym(f.lsym, flag) + base.Ctxt.InitTextSym(f.LSym, flag) } -func ggloblnod(nam *Node) { +func ggloblnod(nam *ir.Node) { s := nam.Sym.Linksym() s.Gotype = ngotype(nam).Linksym() flags := 0 diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 246a057ade1..212db2184ed 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -205,6 +205,7 @@ import ( "bufio" "bytes" "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/goobj" "cmd/internal/src" @@ -258,8 +259,8 @@ func iexport(out *bufio.Writer) { p := iexporter{ allPkgs: map[*types.Pkg]bool{}, stringIndex: map[string]uint64{}, - declIndex: map[*Node]uint64{}, - inlineIndex: map[*Node]uint64{}, + declIndex: map[*ir.Node]uint64{}, + inlineIndex: map[*ir.Node]uint64{}, typIndex: map[*types.Type]uint64{}, } @@ -278,8 +279,8 @@ func iexport(out *bufio.Writer) { // Loop until no more work. We use a queue because while // writing out inline bodies, we may discover additional // declarations that are needed. - for !p.declTodo.empty() { - p.doDecl(p.declTodo.popLeft()) + for !p.declTodo.Empty() { + p.doDecl(p.declTodo.PopLeft()) } // Append indices to data0 section. @@ -313,15 +314,15 @@ func iexport(out *bufio.Writer) { // we're writing out the main index, which is also read by // non-compiler tools and includes a complete package description // (i.e., name and height). -func (w *exportWriter) writeIndex(index map[*Node]uint64, mainIndex bool) { +func (w *exportWriter) writeIndex(index map[*ir.Node]uint64, mainIndex bool) { // Build a map from packages to objects from that package. - pkgObjs := map[*types.Pkg][]*Node{} + pkgObjs := map[*types.Pkg][]*ir.Node{} // For the main index, make sure to include every package that // we reference, even if we're not exporting (or reexporting) // any symbols from it. if mainIndex { - pkgObjs[localpkg] = nil + pkgObjs[ir.LocalPkg] = nil for pkg := range w.p.allPkgs { pkgObjs[pkg] = nil } @@ -367,14 +368,14 @@ type iexporter struct { // main index. allPkgs map[*types.Pkg]bool - declTodo nodeQueue + declTodo ir.NodeQueue strings intWriter stringIndex map[string]uint64 data0 intWriter - declIndex map[*Node]uint64 - inlineIndex map[*Node]uint64 + declIndex map[*ir.Node]uint64 + inlineIndex map[*ir.Node]uint64 typIndex map[*types.Type]uint64 } @@ -393,13 +394,13 @@ func (p *iexporter) stringOff(s string) uint64 { } // pushDecl adds n to the declaration work queue, if not already present. -func (p *iexporter) pushDecl(n *Node) { - if n.Sym == nil || asNode(n.Sym.Def) != n && n.Op != OTYPE { +func (p *iexporter) pushDecl(n *ir.Node) { + if n.Sym == nil || ir.AsNode(n.Sym.Def) != n && n.Op != ir.OTYPE { base.Fatalf("weird Sym: %v, %v", n, n.Sym) } // Don't export predeclared declarations. - if n.Sym.Pkg == builtinpkg || n.Sym.Pkg == unsafepkg { + if n.Sym.Pkg == ir.BuiltinPkg || n.Sym.Pkg == unsafepkg { return } @@ -408,7 +409,7 @@ func (p *iexporter) pushDecl(n *Node) { } p.declIndex[n] = ^uint64(0) // mark n present in work queue - p.declTodo.pushRight(n) + p.declTodo.PushRight(n) } // exportWriter handles writing out individual data section chunks. @@ -422,22 +423,22 @@ type exportWriter struct { prevColumn int64 } -func (p *iexporter) doDecl(n *Node) { +func (p *iexporter) doDecl(n *ir.Node) { w := p.newWriter() w.setPkg(n.Sym.Pkg, false) switch n.Op { - case ONAME: + case ir.ONAME: switch n.Class() { - case PEXTERN: + case ir.PEXTERN: // Variable. w.tag('V') w.pos(n.Pos) w.typ(n.Type) w.varExt(n) - case PFUNC: - if n.IsMethod() { + case ir.PFUNC: + if ir.IsMethod(n) { base.Fatalf("unexpected method: %v", n) } @@ -451,14 +452,14 @@ func (p *iexporter) doDecl(n *Node) { base.Fatalf("unexpected class: %v, %v", n, n.Class()) } - case OLITERAL: + case ir.OLITERAL: // Constant. n = typecheck(n, ctxExpr) w.tag('C') w.pos(n.Pos) w.value(n.Type, n.Val()) - case OTYPE: + case ir.OTYPE: if IsAlias(n.Sym) { // Alias. w.tag('A') @@ -514,11 +515,11 @@ func (w *exportWriter) tag(tag byte) { w.data.WriteByte(tag) } -func (p *iexporter) doInline(f *Node) { +func (p *iexporter) doInline(f *ir.Node) { w := p.newWriter() w.setPkg(fnpkg(f), false) - w.stmtList(asNodes(f.Func.Inl.Body)) + w.stmtList(ir.AsNodes(f.Func.Inl.Body)) p.inlineIndex[f] = w.flush() } @@ -569,7 +570,7 @@ func (w *exportWriter) pkg(pkg *types.Pkg) { w.string(pkg.Path) } -func (w *exportWriter) qualifiedIdent(n *Node) { +func (w *exportWriter) qualifiedIdent(n *ir.Node) { // Ensure any referenced declarations are written out too. w.p.pushDecl(n) @@ -592,7 +593,7 @@ func (w *exportWriter) selector(s *types.Sym) { } else { pkg := w.currPkg if types.IsExported(name) { - pkg = localpkg + pkg = ir.LocalPkg } if s.Pkg != pkg { base.Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path) @@ -633,7 +634,7 @@ func (w *exportWriter) startType(k itag) { func (w *exportWriter) doTyp(t *types.Type) { if t.Sym != nil { - if t.Sym.Pkg == builtinpkg || t.Sym.Pkg == unsafepkg { + if t.Sym.Pkg == ir.BuiltinPkg || t.Sym.Pkg == unsafepkg { base.Fatalf("builtin type missing from typIndex: %v", t) } @@ -643,35 +644,35 @@ func (w *exportWriter) doTyp(t *types.Type) { } switch t.Etype { - case TPTR: + case types.TPTR: w.startType(pointerType) w.typ(t.Elem()) - case TSLICE: + case types.TSLICE: w.startType(sliceType) w.typ(t.Elem()) - case TARRAY: + case types.TARRAY: w.startType(arrayType) w.uint64(uint64(t.NumElem())) w.typ(t.Elem()) - case TCHAN: + case types.TCHAN: w.startType(chanType) w.uint64(uint64(t.ChanDir())) w.typ(t.Elem()) - case TMAP: + case types.TMAP: w.startType(mapType) w.typ(t.Key()) w.typ(t.Elem()) - case TFUNC: + case types.TFUNC: w.startType(signatureType) w.setPkg(t.Pkg(), true) w.signature(t) - case TSTRUCT: + case types.TSTRUCT: w.startType(structType) w.setPkg(t.Pkg(), true) @@ -684,7 +685,7 @@ func (w *exportWriter) doTyp(t *types.Type) { w.string(f.Note) } - case TINTER: + case types.TINTER: var embeddeds, methods []*types.Field for _, m := range t.Methods().Slice() { if m.Sym != nil { @@ -719,7 +720,7 @@ func (w *exportWriter) setPkg(pkg *types.Pkg, write bool) { if pkg == nil { // TODO(mdempsky): Proactively set Pkg for types and // remove this fallback logic. - pkg = localpkg + pkg = ir.LocalPkg } if write { @@ -746,7 +747,7 @@ func (w *exportWriter) paramList(fs []*types.Field) { func (w *exportWriter) param(f *types.Field) { w.pos(f.Pos) - w.localIdent(origSym(f.Sym), 0) + w.localIdent(ir.OrigSym(f.Sym), 0) w.typ(f.Type) } @@ -761,16 +762,16 @@ func constTypeOf(typ *types.Type) constant.Kind { } switch typ.Etype { - case TBOOL: + case types.TBOOL: return constant.Bool - case TSTRING: + case types.TSTRING: return constant.String - case TINT, TINT8, TINT16, TINT32, TINT64, - TUINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINTPTR: + case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64, + types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR: return constant.Int - case TFLOAT32, TFLOAT64: + case types.TFLOAT32, types.TFLOAT64: return constant.Float - case TCOMPLEX64, TCOMPLEX128: + case types.TCOMPLEX64, types.TCOMPLEX128: return constant.Complex } @@ -779,7 +780,7 @@ func constTypeOf(typ *types.Type) constant.Kind { } func (w *exportWriter) value(typ *types.Type, v constant.Value) { - assertRepresents(typ, v) + ir.AssertValidTypeForConst(typ, v) w.typ(typ) // Each type has only one admissible constant representation, @@ -808,9 +809,9 @@ func intSize(typ *types.Type) (signed bool, maxBytes uint) { } switch typ.Etype { - case TFLOAT32, TCOMPLEX64: + case types.TFLOAT32, types.TCOMPLEX64: return true, 3 - case TFLOAT64, TCOMPLEX128: + case types.TFLOAT64, types.TCOMPLEX128: return true, 7 } @@ -820,7 +821,7 @@ func intSize(typ *types.Type) (signed bool, maxBytes uint) { // The go/types API doesn't expose sizes to importers, so they // don't know how big these types are. switch typ.Etype { - case TINT, TUINT, TUINTPTR: + case types.TINT, types.TUINT, types.TUINTPTR: maxBytes = 8 } @@ -954,12 +955,12 @@ func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) } // Compiler-specific extensions. -func (w *exportWriter) varExt(n *Node) { +func (w *exportWriter) varExt(n *ir.Node) { w.linkname(n.Sym) w.symIdx(n.Sym) } -func (w *exportWriter) funcExt(n *Node) { +func (w *exportWriter) funcExt(n *ir.Node) { w.linkname(n.Sym) w.symIdx(n.Sym) @@ -993,7 +994,7 @@ func (w *exportWriter) funcExt(n *Node) { func (w *exportWriter) methExt(m *types.Field) { w.bool(m.Nointerface()) - w.funcExt(asNode(m.Nname)) + w.funcExt(ir.AsNode(m.Nname)) } func (w *exportWriter) linkname(s *types.Sym) { @@ -1029,15 +1030,15 @@ func (w *exportWriter) typeExt(t *types.Type) { // Inline bodies. -func (w *exportWriter) stmtList(list Nodes) { +func (w *exportWriter) stmtList(list ir.Nodes) { for _, n := range list.Slice() { w.node(n) } - w.op(OEND) + w.op(ir.OEND) } -func (w *exportWriter) node(n *Node) { - if opprec[n.Op] < 0 { +func (w *exportWriter) node(n *ir.Node) { + if ir.OpPrec[n.Op] < 0 { w.stmt(n) } else { w.expr(n) @@ -1046,8 +1047,8 @@ func (w *exportWriter) node(n *Node) { // Caution: stmt will emit more than one node for statement nodes n that have a non-empty // n.Ninit and where n cannot have a natural init section (such as in "if", "for", etc.). -func (w *exportWriter) stmt(n *Node) { - if n.Ninit.Len() > 0 && !stmtwithinit(n.Op) { +func (w *exportWriter) stmt(n *ir.Node) { + if n.Ninit.Len() > 0 && !ir.StmtWithInit(n.Op) { // can't use stmtList here since we don't want the final OEND for _, n := range n.Ninit.Slice() { w.stmt(n) @@ -1055,8 +1056,8 @@ func (w *exportWriter) stmt(n *Node) { } switch op := n.Op; op { - case ODCL: - w.op(ODCL) + case ir.ODCL: + w.op(ir.ODCL) w.pos(n.Left.Pos) w.localName(n.Left) w.typ(n.Left.Type) @@ -1064,19 +1065,19 @@ func (w *exportWriter) stmt(n *Node) { // case ODCLFIELD: // unimplemented - handled by default case - case OAS: + case ir.OAS: // Don't export "v = " initializing statements, hope they're always // preceded by the DCL which will be re-parsed and typecheck to reproduce // the "v = " again. if n.Right != nil { - w.op(OAS) + w.op(ir.OAS) w.pos(n.Pos) w.expr(n.Left) w.expr(n.Right) } - case OASOP: - w.op(OASOP) + case ir.OASOP: + w.op(ir.OASOP) w.pos(n.Pos) w.op(n.SubOp()) w.expr(n.Left) @@ -1084,54 +1085,54 @@ func (w *exportWriter) stmt(n *Node) { w.expr(n.Right) } - case OAS2: - w.op(OAS2) + case ir.OAS2: + w.op(ir.OAS2) w.pos(n.Pos) w.exprList(n.List) w.exprList(n.Rlist) - case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: - w.op(OAS2) + case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: + w.op(ir.OAS2) w.pos(n.Pos) w.exprList(n.List) - w.exprList(asNodes([]*Node{n.Right})) + w.exprList(ir.AsNodes([]*ir.Node{n.Right})) - case ORETURN: - w.op(ORETURN) + case ir.ORETURN: + w.op(ir.ORETURN) w.pos(n.Pos) w.exprList(n.List) // case ORETJMP: // unreachable - generated by compiler for trampolin routines - case OGO, ODEFER: + case ir.OGO, ir.ODEFER: w.op(op) w.pos(n.Pos) w.expr(n.Left) - case OIF: - w.op(OIF) + case ir.OIF: + w.op(ir.OIF) w.pos(n.Pos) w.stmtList(n.Ninit) w.expr(n.Left) w.stmtList(n.Nbody) w.stmtList(n.Rlist) - case OFOR: - w.op(OFOR) + case ir.OFOR: + w.op(ir.OFOR) w.pos(n.Pos) w.stmtList(n.Ninit) w.exprsOrNil(n.Left, n.Right) w.stmtList(n.Nbody) - case ORANGE: - w.op(ORANGE) + case ir.ORANGE: + w.op(ir.ORANGE) w.pos(n.Pos) w.stmtList(n.List) w.expr(n.Right) w.stmtList(n.Nbody) - case OSELECT, OSWITCH: + case ir.OSELECT, ir.OSWITCH: w.op(op) w.pos(n.Pos) w.stmtList(n.Ninit) @@ -1141,19 +1142,19 @@ func (w *exportWriter) stmt(n *Node) { // case OCASE: // handled by caseList - case OFALL: - w.op(OFALL) + case ir.OFALL: + w.op(ir.OFALL) w.pos(n.Pos) - case OBREAK, OCONTINUE: + case ir.OBREAK, ir.OCONTINUE: w.op(op) w.pos(n.Pos) w.exprsOrNil(n.Left, nil) - case OEMPTY: + case ir.OEMPTY: // nothing to emit - case OGOTO, OLABEL: + case ir.OGOTO, ir.OLABEL: w.op(op) w.pos(n.Pos) w.string(n.Sym.Name) @@ -1163,13 +1164,13 @@ func (w *exportWriter) stmt(n *Node) { } } -func (w *exportWriter) caseList(sw *Node) { - namedTypeSwitch := sw.Op == OSWITCH && sw.Left != nil && sw.Left.Op == OTYPESW && sw.Left.Left != nil +func (w *exportWriter) caseList(sw *ir.Node) { + namedTypeSwitch := sw.Op == ir.OSWITCH && sw.Left != nil && sw.Left.Op == ir.OTYPESW && sw.Left.Left != nil cases := sw.List.Slice() w.uint64(uint64(len(cases))) for _, cas := range cases { - if cas.Op != OCASE { + if cas.Op != ir.OCASE { base.Fatalf("expected OCASE, got %v", cas) } w.pos(cas.Pos) @@ -1181,14 +1182,14 @@ func (w *exportWriter) caseList(sw *Node) { } } -func (w *exportWriter) exprList(list Nodes) { +func (w *exportWriter) exprList(list ir.Nodes) { for _, n := range list.Slice() { w.expr(n) } - w.op(OEND) + w.op(ir.OEND) } -func (w *exportWriter) expr(n *Node) { +func (w *exportWriter) expr(n *ir.Node) { // from nodefmt (fmt.go) // // nodefmt reverts nodes back to their original - we don't need to do @@ -1199,14 +1200,14 @@ func (w *exportWriter) expr(n *Node) { // } // from exprfmt (fmt.go) - for n.Op == OPAREN || n.Implicit() && (n.Op == ODEREF || n.Op == OADDR || n.Op == ODOT || n.Op == ODOTPTR) { + for n.Op == ir.OPAREN || n.Implicit() && (n.Op == ir.ODEREF || n.Op == ir.OADDR || n.Op == ir.ODOT || n.Op == ir.ODOTPTR) { n = n.Left } switch op := n.Op; op { // expressions // (somewhat closely following the structure of exprfmt in fmt.go) - case ONIL: + case ir.ONIL: if !n.Type.HasNil() { base.Fatalf("unexpected type for nil: %v", n.Type) } @@ -1214,49 +1215,49 @@ func (w *exportWriter) expr(n *Node) { w.expr(n.Orig) break } - w.op(OLITERAL) + w.op(ir.OLITERAL) w.pos(n.Pos) w.typ(n.Type) - case OLITERAL: - w.op(OLITERAL) + case ir.OLITERAL: + w.op(ir.OLITERAL) w.pos(n.Pos) w.value(n.Type, n.Val()) - case OMETHEXPR: + case ir.OMETHEXPR: // Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method, // but for export, this should be rendered as (*pkg.T).meth. // These nodes have the special property that they are names with a left OTYPE and a right ONAME. - w.op(OXDOT) + w.op(ir.OXDOT) w.pos(n.Pos) w.expr(n.Left) // n.Left.Op == OTYPE w.selector(n.Right.Sym) - case ONAME: + case ir.ONAME: // Package scope name. - if (n.Class() == PEXTERN || n.Class() == PFUNC) && !n.isBlank() { - w.op(ONONAME) + if (n.Class() == ir.PEXTERN || n.Class() == ir.PFUNC) && !ir.IsBlank(n) { + w.op(ir.ONONAME) w.qualifiedIdent(n) break } // Function scope name. - w.op(ONAME) + w.op(ir.ONAME) w.localName(n) // case OPACK, ONONAME: // should have been resolved by typechecking - handled by default case - case OTYPE: - w.op(OTYPE) + case ir.OTYPE: + w.op(ir.OTYPE) w.typ(n.Type) - case OTYPESW: - w.op(OTYPESW) + case ir.OTYPESW: + w.op(ir.OTYPESW) w.pos(n.Pos) var s *types.Sym if n.Left != nil { - if n.Left.Op != ONONAME { + if n.Left.Op != ir.ONONAME { base.Fatalf("expected ONONAME, got %v", n.Left) } s = n.Left.Sym @@ -1273,149 +1274,149 @@ func (w *exportWriter) expr(n *Node) { // case OCOMPLIT: // should have been resolved by typechecking - handled by default case - case OPTRLIT: - w.op(OADDR) + case ir.OPTRLIT: + w.op(ir.OADDR) w.pos(n.Pos) w.expr(n.Left) - case OSTRUCTLIT: - w.op(OSTRUCTLIT) + case ir.OSTRUCTLIT: + w.op(ir.OSTRUCTLIT) w.pos(n.Pos) w.typ(n.Type) w.elemList(n.List) // special handling of field names - case OARRAYLIT, OSLICELIT, OMAPLIT: - w.op(OCOMPLIT) + case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT: + w.op(ir.OCOMPLIT) w.pos(n.Pos) w.typ(n.Type) w.exprList(n.List) - case OKEY: - w.op(OKEY) + case ir.OKEY: + w.op(ir.OKEY) w.pos(n.Pos) w.exprsOrNil(n.Left, n.Right) // case OSTRUCTKEY: // unreachable - handled in case OSTRUCTLIT by elemList - case OCALLPART: + case ir.OCALLPART: // An OCALLPART is an OXDOT before type checking. - w.op(OXDOT) + w.op(ir.OXDOT) w.pos(n.Pos) w.expr(n.Left) // Right node should be ONAME w.selector(n.Right.Sym) - case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: - w.op(OXDOT) + case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH: + w.op(ir.OXDOT) w.pos(n.Pos) w.expr(n.Left) w.selector(n.Sym) - case ODOTTYPE, ODOTTYPE2: - w.op(ODOTTYPE) + case ir.ODOTTYPE, ir.ODOTTYPE2: + w.op(ir.ODOTTYPE) w.pos(n.Pos) w.expr(n.Left) w.typ(n.Type) - case OINDEX, OINDEXMAP: - w.op(OINDEX) + case ir.OINDEX, ir.OINDEXMAP: + w.op(ir.OINDEX) w.pos(n.Pos) w.expr(n.Left) w.expr(n.Right) - case OSLICE, OSLICESTR, OSLICEARR: - w.op(OSLICE) + case ir.OSLICE, ir.OSLICESTR, ir.OSLICEARR: + w.op(ir.OSLICE) w.pos(n.Pos) w.expr(n.Left) low, high, _ := n.SliceBounds() w.exprsOrNil(low, high) - case OSLICE3, OSLICE3ARR: - w.op(OSLICE3) + case ir.OSLICE3, ir.OSLICE3ARR: + w.op(ir.OSLICE3) w.pos(n.Pos) w.expr(n.Left) low, high, max := n.SliceBounds() w.exprsOrNil(low, high) w.expr(max) - case OCOPY, OCOMPLEX: + case ir.OCOPY, ir.OCOMPLEX: // treated like other builtin calls (see e.g., OREAL) w.op(op) w.pos(n.Pos) w.expr(n.Left) w.expr(n.Right) - w.op(OEND) + w.op(ir.OEND) - case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR: - w.op(OCONV) + case ir.OCONV, ir.OCONVIFACE, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR: + w.op(ir.OCONV) w.pos(n.Pos) w.expr(n.Left) w.typ(n.Type) - case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN: + case 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: w.op(op) w.pos(n.Pos) if n.Left != nil { w.expr(n.Left) - w.op(OEND) + w.op(ir.OEND) } else { w.exprList(n.List) // emits terminating OEND } // only append() calls may contain '...' arguments - if op == OAPPEND { + if op == ir.OAPPEND { w.bool(n.IsDDD()) } else if n.IsDDD() { base.Fatalf("exporter: unexpected '...' with %v call", op) } - case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG: - w.op(OCALL) + case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OGETG: + w.op(ir.OCALL) w.pos(n.Pos) w.stmtList(n.Ninit) w.expr(n.Left) w.exprList(n.List) w.bool(n.IsDDD()) - case OMAKEMAP, OMAKECHAN, OMAKESLICE: + case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE: w.op(op) // must keep separate from OMAKE for importer w.pos(n.Pos) w.typ(n.Type) switch { default: // empty list - w.op(OEND) + w.op(ir.OEND) case n.List.Len() != 0: // pre-typecheck w.exprList(n.List) // emits terminating OEND case n.Right != nil: w.expr(n.Left) w.expr(n.Right) - w.op(OEND) - case n.Left != nil && (n.Op == OMAKESLICE || !n.Left.Type.IsUntyped()): + w.op(ir.OEND) + case n.Left != nil && (n.Op == ir.OMAKESLICE || !n.Left.Type.IsUntyped()): w.expr(n.Left) - w.op(OEND) + w.op(ir.OEND) } // unary expressions - case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV: + case ir.OPLUS, ir.ONEG, ir.OADDR, ir.OBITNOT, ir.ODEREF, ir.ONOT, ir.ORECV: w.op(op) w.pos(n.Pos) w.expr(n.Left) // binary expressions - case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT, - OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR: + case ir.OADD, ir.OAND, ir.OANDAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT, + ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.OOROR, ir.ORSH, ir.OSEND, ir.OSUB, ir.OXOR: w.op(op) w.pos(n.Pos) w.expr(n.Left) w.expr(n.Right) - case OADDSTR: - w.op(OADDSTR) + case ir.OADDSTR: + w.op(ir.OADDSTR) w.pos(n.Pos) w.exprList(n.List) - case ODCLCONST: + case ir.ODCLCONST: // if exporting, DCLCONST should just be removed as its usage // has already been replaced with literals @@ -1425,11 +1426,11 @@ func (w *exportWriter) expr(n *Node) { } } -func (w *exportWriter) op(op Op) { +func (w *exportWriter) op(op ir.Op) { w.uint64(uint64(op)) } -func (w *exportWriter) exprsOrNil(a, b *Node) { +func (w *exportWriter) exprsOrNil(a, b *ir.Node) { ab := 0 if a != nil { ab |= 1 @@ -1446,7 +1447,7 @@ func (w *exportWriter) exprsOrNil(a, b *Node) { } } -func (w *exportWriter) elemList(list Nodes) { +func (w *exportWriter) elemList(list ir.Nodes) { w.uint64(uint64(list.Len())) for _, n := range list.Slice() { w.selector(n.Sym) @@ -1454,7 +1455,7 @@ func (w *exportWriter) elemList(list Nodes) { } } -func (w *exportWriter) localName(n *Node) { +func (w *exportWriter) localName(n *ir.Node) { // Escape analysis happens after inline bodies are saved, but // we're using the same ONAME nodes, so we might still see // PAUTOHEAP here. @@ -1463,7 +1464,7 @@ func (w *exportWriter) localName(n *Node) { // PPARAM/PPARAMOUT, because we only want to include vargen in // non-param names. var v int32 - if n.Class() == PAUTO || (n.Class() == PAUTOHEAP && n.Name.Param.Stackcopy == nil) { + if n.Class() == ir.PAUTO || (n.Class() == ir.PAUTOHEAP && n.Name.Param.Stackcopy == nil) { v = n.Name.Vargen } diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index cc0209ed03d..84386140bb9 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -9,6 +9,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/bio" "cmd/internal/goobj" @@ -40,8 +41,8 @@ var ( inlineImporter = map[*types.Sym]iimporterAndOffset{} ) -func expandDecl(n *Node) { - if n.Op != ONONAME { +func expandDecl(n *ir.Node) { + if n.Op != ir.ONONAME { return } @@ -54,7 +55,7 @@ func expandDecl(n *Node) { r.doDecl(n) } -func expandInline(fn *Node) { +func expandInline(fn *ir.Node) { if fn.Func.Inl.Body != nil { return } @@ -67,7 +68,7 @@ func expandInline(fn *Node) { r.doInline(fn) } -func importReaderFor(n *Node, importers map[*types.Sym]iimporterAndOffset) *importReader { +func importReaderFor(n *ir.Node, importers map[*types.Sym]iimporterAndOffset) *importReader { x, ok := importers[n.Sym] if !ok { return nil @@ -147,10 +148,10 @@ func iimport(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintType) if pkg.Name == "" { pkg.Name = pkgName pkg.Height = pkgHeight - numImport[pkgName]++ + ir.NumImport[pkgName]++ // TODO(mdempsky): This belongs somewhere else. - pkg.Lookup("_").Def = asTypesNode(nblank) + pkg.Lookup("_").Def = ir.AsTypesNode(ir.BlankNode) } else { if pkg.Name != pkgName { base.Fatalf("conflicting package names %v and %v for path %q", pkg.Name, pkgName, pkg.Path) @@ -172,9 +173,9 @@ func iimport(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintType) // Create stub declaration. If used, this will // be overwritten by expandDecl. if s.Def != nil { - base.Fatalf("unexpected definition for %v: %v", s, asNode(s.Def)) + base.Fatalf("unexpected definition for %v: %v", s, ir.AsNode(s.Def)) } - s.Def = asTypesNode(npos(src.NoXPos, dclname(s))) + s.Def = ir.AsTypesNode(npos(src.NoXPos, dclname(s))) } } @@ -280,8 +281,8 @@ func (r *importReader) setPkg() { r.currPkg = r.pkg() } -func (r *importReader) doDecl(n *Node) { - if n.Op != ONONAME { +func (r *importReader) doDecl(n *ir.Node) { + if n.Op != ir.ONONAME { base.Fatalf("doDecl: unexpected Op for %v: %v", n.Sym, n.Op) } @@ -330,13 +331,13 @@ func (r *importReader) doDecl(n *Node) { recv := r.param() mtyp := r.signature(recv) - m := newfuncnamel(mpos, methodSym(recv.Type, msym), new(Func)) + m := newfuncnamel(mpos, methodSym(recv.Type, msym), new(ir.Func)) m.Type = mtyp - m.SetClass(PFUNC) + m.SetClass(ir.PFUNC) // methodSym already marked m.Sym as a function. f := types.NewField(mpos, msym, mtyp) - f.Nname = asTypesNode(m) + f.Nname = ir.AsTypesNode(m) ms[i] = f } t.Methods().Set(ms) @@ -434,7 +435,7 @@ func (r *importReader) ident() *types.Sym { } pkg := r.currPkg if types.IsExported(name) { - pkg = localpkg + pkg = ir.LocalPkg } return pkg.Lookup(name) } @@ -498,11 +499,11 @@ func (r *importReader) typ1() *types.Type { // support inlining functions with local defined // types. Therefore, this must be a package-scope // type. - n := asNode(r.qualifiedIdent().PkgDef()) - if n.Op == ONONAME { + n := ir.AsNode(r.qualifiedIdent().PkgDef()) + if n.Op == ir.ONONAME { expandDecl(n) } - if n.Op != OTYPE { + if n.Op != ir.OTYPE { base.Fatalf("expected OTYPE, got %v: %v, %v", n.Op, n.Sym, n) } return n.Type @@ -542,7 +543,7 @@ func (r *importReader) typ1() *types.Type { fs[i] = f } - t := types.New(TSTRUCT) + t := types.New(types.TSTRUCT) t.SetPkg(r.currPkg) t.SetFields(fs) return t @@ -567,7 +568,7 @@ func (r *importReader) typ1() *types.Type { methods[i] = types.NewField(pos, sym, typ) } - t := types.New(TINTER) + t := types.New(types.TINTER) t.SetPkg(r.currPkg) t.SetInterface(append(embeddeds, methods...)) @@ -634,12 +635,12 @@ func (r *importReader) byte() byte { // Compiler-specific extensions. -func (r *importReader) varExt(n *Node) { +func (r *importReader) varExt(n *ir.Node) { r.linkname(n.Sym) r.symIdx(n.Sym) } -func (r *importReader) funcExt(n *Node) { +func (r *importReader) funcExt(n *ir.Node) { r.linkname(n.Sym) r.symIdx(n.Sym) @@ -652,7 +653,7 @@ func (r *importReader) funcExt(n *Node) { // Inline body. if u := r.uint64(); u > 0 { - n.Func.Inl = &Inline{ + n.Func.Inl = &ir.Inline{ Cost: int32(u - 1), } n.Func.Endlineno = r.pos() @@ -663,7 +664,7 @@ func (r *importReader) methExt(m *types.Field) { if r.bool() { m.SetNointerface(true) } - r.funcExt(asNode(m.Nname)) + r.funcExt(ir.AsNode(m.Nname)) } func (r *importReader) linkname(s *types.Sym) { @@ -694,7 +695,7 @@ func (r *importReader) typeExt(t *types.Type) { // so we can use index to reference the symbol. var typeSymIdx = make(map[*types.Type][2]int64) -func (r *importReader) doInline(n *Node) { +func (r *importReader) doInline(n *ir.Node) { if len(n.Func.Inl.Body) != 0 { base.Fatalf("%v already has inline body", n) } @@ -709,7 +710,7 @@ func (r *importReader) doInline(n *Node) { // (not doing so can cause significant performance // degradation due to unnecessary calls to empty // functions). - body = []*Node{} + body = []*ir.Node{} } n.Func.Inl.Body = body @@ -717,9 +718,9 @@ func (r *importReader) doInline(n *Node) { if base.Flag.E > 0 && base.Flag.LowerM > 2 { if base.Flag.LowerM > 3 { - fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, asNodes(n.Func.Inl.Body)) + fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, ir.AsNodes(n.Func.Inl.Body)) } else { - fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, asNodes(n.Func.Inl.Body)) + fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, ir.AsNodes(n.Func.Inl.Body)) } } } @@ -739,15 +740,15 @@ func (r *importReader) doInline(n *Node) { // unrefined nodes (since this is what the importer uses). The respective case // entries are unreachable in the importer. -func (r *importReader) stmtList() []*Node { - var list []*Node +func (r *importReader) stmtList() []*ir.Node { + var list []*ir.Node for { n := r.node() if n == nil { break } // OBLOCK nodes may be created when importing ODCL nodes - unpack them - if n.Op == OBLOCK { + if n.Op == ir.OBLOCK { list = append(list, n.List.Slice()...) } else { list = append(list, n) @@ -757,18 +758,18 @@ func (r *importReader) stmtList() []*Node { return list } -func (r *importReader) caseList(sw *Node) []*Node { - namedTypeSwitch := sw.Op == OSWITCH && sw.Left != nil && sw.Left.Op == OTYPESW && sw.Left.Left != nil +func (r *importReader) caseList(sw *ir.Node) []*ir.Node { + namedTypeSwitch := sw.Op == ir.OSWITCH && sw.Left != nil && sw.Left.Op == ir.OTYPESW && sw.Left.Left != nil - cases := make([]*Node, r.uint64()) + cases := make([]*ir.Node, r.uint64()) for i := range cases { - cas := nodl(r.pos(), OCASE, nil, nil) + cas := ir.NodAt(r.pos(), ir.OCASE, nil, nil) cas.List.Set(r.stmtList()) if namedTypeSwitch { // Note: per-case variables will have distinct, dotted // names after import. That's okay: swt.go only needs // Sym for diagnostics anyway. - caseVar := newnamel(cas.Pos, r.ident()) + caseVar := ir.NewNameAt(cas.Pos, r.ident()) declare(caseVar, dclcontext) cas.Rlist.Set1(caseVar) caseVar.Name.Defn = sw.Left @@ -779,8 +780,8 @@ func (r *importReader) caseList(sw *Node) []*Node { return cases } -func (r *importReader) exprList() []*Node { - var list []*Node +func (r *importReader) exprList() []*ir.Node { + var list []*ir.Node for { n := r.expr() if n == nil { @@ -791,16 +792,16 @@ func (r *importReader) exprList() []*Node { return list } -func (r *importReader) expr() *Node { +func (r *importReader) expr() *ir.Node { n := r.node() - if n != nil && n.Op == OBLOCK { + if n != nil && n.Op == ir.OBLOCK { base.Fatalf("unexpected block node: %v", n) } return n } // TODO(gri) split into expr and stmt -func (r *importReader) node() *Node { +func (r *importReader) node() *ir.Node { switch op := r.op(); op { // expressions // case OPAREN: @@ -809,34 +810,34 @@ func (r *importReader) node() *Node { // case ONIL: // unreachable - mapped to OLITERAL - case OLITERAL: + case ir.OLITERAL: pos := r.pos() typ := r.typ() - var n *Node + var n *ir.Node if typ.HasNil() { n = nodnil() } else { - n = nodlit(r.value(typ)) + n = ir.NewLiteral(r.value(typ)) } n = npos(pos, n) n.Type = typ return n - case ONONAME: + case ir.ONONAME: return mkname(r.qualifiedIdent()) - case ONAME: + case ir.ONAME: return mkname(r.ident()) // case OPACK, ONONAME: // unreachable - should have been resolved by typechecking - case OTYPE: + case ir.OTYPE: return typenod(r.typ()) - case OTYPESW: - n := nodl(r.pos(), OTYPESW, nil, nil) + case ir.OTYPESW: + n := ir.NodAt(r.pos(), ir.OTYPESW, nil, nil) if s := r.ident(); s != nil { n.Left = npos(n.Pos, newnoname(s)) } @@ -853,11 +854,11 @@ func (r *importReader) node() *Node { // case OPTRLIT: // unreachable - mapped to case OADDR below by exporter - case OSTRUCTLIT: + case ir.OSTRUCTLIT: // TODO(mdempsky): Export position information for OSTRUCTKEY nodes. savedlineno := base.Pos base.Pos = r.pos() - n := nodl(base.Pos, OCOMPLIT, nil, typenod(r.typ())) + n := ir.NodAt(base.Pos, ir.OCOMPLIT, nil, typenod(r.typ())) n.List.Set(r.elemList()) // special handling of field names base.Pos = savedlineno return n @@ -865,15 +866,15 @@ func (r *importReader) node() *Node { // case OARRAYLIT, OSLICELIT, OMAPLIT: // unreachable - mapped to case OCOMPLIT below by exporter - case OCOMPLIT: - n := nodl(r.pos(), OCOMPLIT, nil, typenod(r.typ())) + case ir.OCOMPLIT: + n := ir.NodAt(r.pos(), ir.OCOMPLIT, nil, typenod(r.typ())) n.List.Set(r.exprList()) return n - case OKEY: + case ir.OKEY: pos := r.pos() left, right := r.exprsOrNil() - return nodl(pos, OKEY, left, right) + return ir.NodAt(pos, ir.OKEY, left, right) // case OSTRUCTKEY: // unreachable - handled in case OSTRUCTLIT by elemList @@ -884,28 +885,28 @@ func (r *importReader) node() *Node { // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: // unreachable - mapped to case OXDOT below by exporter - case OXDOT: + case ir.OXDOT: // see parser.new_dotname - return npos(r.pos(), nodSym(OXDOT, r.expr(), r.ident())) + return npos(r.pos(), nodSym(ir.OXDOT, r.expr(), r.ident())) // case ODOTTYPE, ODOTTYPE2: // unreachable - mapped to case ODOTTYPE below by exporter - case ODOTTYPE: - n := nodl(r.pos(), ODOTTYPE, r.expr(), nil) + case ir.ODOTTYPE: + n := ir.NodAt(r.pos(), ir.ODOTTYPE, r.expr(), nil) n.Type = r.typ() return n // case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: // unreachable - mapped to cases below by exporter - case OINDEX: - return nodl(r.pos(), op, r.expr(), r.expr()) + case ir.OINDEX: + return ir.NodAt(r.pos(), op, r.expr(), r.expr()) - case OSLICE, OSLICE3: - n := nodl(r.pos(), op, r.expr(), nil) + case ir.OSLICE, ir.OSLICE3: + n := ir.NodAt(r.pos(), op, r.expr(), nil) low, high := r.exprsOrNil() - var max *Node + var max *ir.Node if n.Op.IsSlice3() { max = r.expr() } @@ -915,15 +916,15 @@ func (r *importReader) node() *Node { // case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR: // unreachable - mapped to OCONV case below by exporter - case OCONV: - n := nodl(r.pos(), OCONV, r.expr(), nil) + case ir.OCONV: + n := ir.NodAt(r.pos(), ir.OCONV, r.expr(), nil) n.Type = r.typ() return n - case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN: + 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 := npos(r.pos(), builtinCall(op)) n.List.Set(r.exprList()) - if op == OAPPEND { + if op == ir.OAPPEND { n.SetIsDDD(r.bool()) } return n @@ -931,45 +932,45 @@ func (r *importReader) node() *Node { // case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG: // unreachable - mapped to OCALL case below by exporter - case OCALL: - n := nodl(r.pos(), OCALL, nil, nil) + case ir.OCALL: + n := ir.NodAt(r.pos(), ir.OCALL, nil, nil) n.Ninit.Set(r.stmtList()) n.Left = r.expr() n.List.Set(r.exprList()) n.SetIsDDD(r.bool()) return n - case OMAKEMAP, OMAKECHAN, OMAKESLICE: - n := npos(r.pos(), builtinCall(OMAKE)) + case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE: + n := npos(r.pos(), builtinCall(ir.OMAKE)) n.List.Append(typenod(r.typ())) n.List.Append(r.exprList()...) return n // unary expressions - case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV: - return nodl(r.pos(), op, r.expr(), nil) + case ir.OPLUS, ir.ONEG, ir.OADDR, ir.OBITNOT, ir.ODEREF, ir.ONOT, ir.ORECV: + return ir.NodAt(r.pos(), op, r.expr(), nil) // binary expressions - case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT, - OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR: - return nodl(r.pos(), op, r.expr(), r.expr()) + case ir.OADD, ir.OAND, ir.OANDAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT, + ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.OOROR, ir.ORSH, ir.OSEND, ir.OSUB, ir.OXOR: + return ir.NodAt(r.pos(), op, r.expr(), r.expr()) - case OADDSTR: + case ir.OADDSTR: pos := r.pos() list := r.exprList() x := npos(pos, list[0]) for _, y := range list[1:] { - x = nodl(pos, OADD, x, y) + x = ir.NodAt(pos, ir.OADD, x, y) } return x // -------------------------------------------------------------------- // statements - case ODCL: + case ir.ODCL: pos := r.pos() lhs := npos(pos, dclname(r.ident())) typ := typenod(r.typ()) - return npos(pos, liststmt(variter([]*Node{lhs}, typ, nil))) // TODO(gri) avoid list creation + return npos(pos, liststmt(variter([]*ir.Node{lhs}, typ, nil))) // TODO(gri) avoid list creation // case ODCLFIELD: // unimplemented @@ -977,11 +978,11 @@ func (r *importReader) node() *Node { // case OAS, OASWB: // unreachable - mapped to OAS case below by exporter - case OAS: - return nodl(r.pos(), OAS, r.expr(), r.expr()) + case ir.OAS: + return ir.NodAt(r.pos(), ir.OAS, r.expr(), r.expr()) - case OASOP: - n := nodl(r.pos(), OASOP, nil, nil) + case ir.OASOP: + n := ir.NodAt(r.pos(), ir.OASOP, nil, nil) n.SetSubOp(r.op()) n.Left = r.expr() if !r.bool() { @@ -995,33 +996,33 @@ func (r *importReader) node() *Node { // case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: // unreachable - mapped to OAS2 case below by exporter - case OAS2: - n := nodl(r.pos(), OAS2, nil, nil) + case ir.OAS2: + n := ir.NodAt(r.pos(), ir.OAS2, nil, nil) n.List.Set(r.exprList()) n.Rlist.Set(r.exprList()) return n - case ORETURN: - n := nodl(r.pos(), ORETURN, nil, nil) + case ir.ORETURN: + n := ir.NodAt(r.pos(), ir.ORETURN, nil, nil) n.List.Set(r.exprList()) return n // case ORETJMP: // unreachable - generated by compiler for trampolin routines (not exported) - case OGO, ODEFER: - return nodl(r.pos(), op, r.expr(), nil) + case ir.OGO, ir.ODEFER: + return ir.NodAt(r.pos(), op, r.expr(), nil) - case OIF: - n := nodl(r.pos(), OIF, nil, nil) + case ir.OIF: + n := ir.NodAt(r.pos(), ir.OIF, nil, nil) n.Ninit.Set(r.stmtList()) n.Left = r.expr() n.Nbody.Set(r.stmtList()) n.Rlist.Set(r.stmtList()) return n - case OFOR: - n := nodl(r.pos(), OFOR, nil, nil) + case ir.OFOR: + n := ir.NodAt(r.pos(), ir.OFOR, nil, nil) n.Ninit.Set(r.stmtList()) left, right := r.exprsOrNil() n.Left = left @@ -1029,15 +1030,15 @@ func (r *importReader) node() *Node { n.Nbody.Set(r.stmtList()) return n - case ORANGE: - n := nodl(r.pos(), ORANGE, nil, nil) + case ir.ORANGE: + n := ir.NodAt(r.pos(), ir.ORANGE, nil, nil) n.List.Set(r.stmtList()) n.Right = r.expr() n.Nbody.Set(r.stmtList()) return n - case OSELECT, OSWITCH: - n := nodl(r.pos(), op, nil, nil) + case ir.OSELECT, ir.OSWITCH: + n := ir.NodAt(r.pos(), op, nil, nil) n.Ninit.Set(r.stmtList()) left, _ := r.exprsOrNil() n.Left = left @@ -1047,27 +1048,27 @@ func (r *importReader) node() *Node { // case OCASE: // handled by caseList - case OFALL: - n := nodl(r.pos(), OFALL, nil, nil) + case ir.OFALL: + n := ir.NodAt(r.pos(), ir.OFALL, nil, nil) return n - case OBREAK, OCONTINUE: + case ir.OBREAK, ir.OCONTINUE: pos := r.pos() left, _ := r.exprsOrNil() if left != nil { - left = newname(left.Sym) + left = NewName(left.Sym) } - return nodl(pos, op, left, nil) + return ir.NodAt(pos, op, left, nil) // case OEMPTY: // unreachable - not emitted by exporter - case OGOTO, OLABEL: - n := nodl(r.pos(), op, nil, nil) + case ir.OGOTO, ir.OLABEL: + n := ir.NodAt(r.pos(), op, nil, nil) n.Sym = lookup(r.string()) return n - case OEND: + case ir.OEND: return nil default: @@ -1077,21 +1078,21 @@ func (r *importReader) node() *Node { } } -func (r *importReader) op() Op { - return Op(r.uint64()) +func (r *importReader) op() ir.Op { + return ir.Op(r.uint64()) } -func (r *importReader) elemList() []*Node { +func (r *importReader) elemList() []*ir.Node { c := r.uint64() - list := make([]*Node, c) + list := make([]*ir.Node, c) for i := range list { s := r.ident() - list[i] = nodSym(OSTRUCTKEY, r.expr(), s) + list[i] = nodSym(ir.OSTRUCTKEY, r.expr(), s) } return list } -func (r *importReader) exprsOrNil() (a, b *Node) { +func (r *importReader) exprsOrNil() (a, b *ir.Node) { ab := r.uint64() if ab&1 != 0 { a = r.expr() diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go index 9319faf6a01..f3c302f6bee 100644 --- a/src/cmd/compile/internal/gc/init.go +++ b/src/cmd/compile/internal/gc/init.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/obj" ) @@ -18,7 +19,7 @@ var renameinitgen int // Function collecting autotmps generated during typechecking, // to be included in the package-level init function. -var initTodo = nod(ODCLFUNC, nil, nil) +var initTodo = ir.Nod(ir.ODCLFUNC, nil, nil) func renameinit() *types.Sym { s := lookupN("init.", renameinitgen) @@ -32,7 +33,7 @@ func renameinit() *types.Sym { // 1) Initialize all of the packages the current package depends on. // 2) Initialize all the variables that have initializers. // 3) Run any init functions. -func fninit(n []*Node) { +func fninit(n []*ir.Node) { nf := initOrder(n) var deps []*obj.LSym // initTask records for packages the current package depends on @@ -47,7 +48,7 @@ func fninit(n []*Node) { if len(nf) > 0 { base.Pos = nf[0].Pos // prolog/epilog gets line number of first init stmt initializers := lookup("init") - fn := dclfunc(initializers, nod(OTFUNC, nil, nil)) + fn := dclfunc(initializers, ir.Nod(ir.OTFUNC, nil, nil)) for _, dcl := range initTodo.Func.Dcl { dcl.Name.Curfn = fn } @@ -75,24 +76,24 @@ func fninit(n []*Node) { // Record user init functions. for i := 0; i < renameinitgen; i++ { s := lookupN("init.", i) - fn := asNode(s.Def).Name.Defn + fn := ir.AsNode(s.Def).Name.Defn // Skip init functions with empty bodies. - if fn.Nbody.Len() == 1 && fn.Nbody.First().Op == OEMPTY { + if fn.Nbody.Len() == 1 && fn.Nbody.First().Op == ir.OEMPTY { continue } fns = append(fns, s.Linksym()) } - if len(deps) == 0 && len(fns) == 0 && localpkg.Name != "main" && localpkg.Name != "runtime" { + if len(deps) == 0 && len(fns) == 0 && ir.LocalPkg.Name != "main" && ir.LocalPkg.Name != "runtime" { return // nothing to initialize } // Make an .inittask structure. sym := lookup(".inittask") - nn := newname(sym) - nn.Type = types.Types[TUINT8] // fake type - nn.SetClass(PEXTERN) - sym.Def = asTypesNode(nn) + nn := NewName(sym) + nn.Type = types.Types[types.TUINT8] // fake type + nn.SetClass(ir.PEXTERN) + sym.Def = ir.AsTypesNode(nn) exportsym(nn) lsym := sym.Linksym() ot := 0 diff --git a/src/cmd/compile/internal/gc/initorder.go b/src/cmd/compile/internal/gc/initorder.go index f553a3f057b..942cb95f207 100644 --- a/src/cmd/compile/internal/gc/initorder.go +++ b/src/cmd/compile/internal/gc/initorder.go @@ -10,6 +10,8 @@ import ( "fmt" "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/compile/internal/types" ) // Package initialization @@ -62,7 +64,7 @@ const ( type InitOrder struct { // blocking maps initialization assignments to the assignments // that depend on it. - blocking map[*Node][]*Node + blocking map[*ir.Node][]*ir.Node // ready is the queue of Pending initialization assignments // that are ready for initialization. @@ -73,22 +75,22 @@ type InitOrder struct { // package-level declarations (in declaration order) and outputs the // corresponding list of statements to include in the init() function // body. -func initOrder(l []*Node) []*Node { +func initOrder(l []*ir.Node) []*ir.Node { s := InitSchedule{ - initplans: make(map[*Node]*InitPlan), - inittemps: make(map[*Node]*Node), + initplans: make(map[*ir.Node]*InitPlan), + inittemps: make(map[*ir.Node]*ir.Node), } o := InitOrder{ - blocking: make(map[*Node][]*Node), + blocking: make(map[*ir.Node][]*ir.Node), } // Process all package-level assignment in declaration order. for _, n := range l { switch n.Op { - case OAS, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: + case ir.OAS, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: o.processAssign(n) o.flushReady(s.staticInit) - case ODCLCONST, ODCLFUNC, ODCLTYPE: + case ir.ODCLCONST, ir.ODCLFUNC, ir.ODCLTYPE: // nop default: base.Fatalf("unexpected package-level statement: %v", n) @@ -99,7 +101,7 @@ func initOrder(l []*Node) []*Node { // have been a dependency cycle. for _, n := range l { switch n.Op { - case OAS, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: + case ir.OAS, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: if n.Initorder() != InitDone { // If there have already been errors // printed, those errors may have @@ -108,7 +110,7 @@ func initOrder(l []*Node) []*Node { // first. base.ExitIfErrors() - findInitLoopAndExit(firstLHS(n), new([]*Node)) + findInitLoopAndExit(firstLHS(n), new([]*ir.Node)) base.Fatalf("initialization unfinished, but failed to identify loop") } } @@ -123,8 +125,8 @@ func initOrder(l []*Node) []*Node { return s.out } -func (o *InitOrder) processAssign(n *Node) { - if n.Initorder() != InitNotStarted || n.Xoffset != BADWIDTH { +func (o *InitOrder) processAssign(n *ir.Node) { + if n.Initorder() != InitNotStarted || n.Xoffset != types.BADWIDTH { base.Fatalf("unexpected state: %v, %v, %v", n, n.Initorder(), n.Xoffset) } @@ -137,7 +139,7 @@ func (o *InitOrder) processAssign(n *Node) { defn := dep.Name.Defn // Skip dependencies on functions (PFUNC) and // variables already initialized (InitDone). - if dep.Class() != PEXTERN || defn.Initorder() == InitDone { + if dep.Class() != ir.PEXTERN || defn.Initorder() == InitDone { continue } n.Xoffset++ @@ -152,16 +154,16 @@ func (o *InitOrder) processAssign(n *Node) { // flushReady repeatedly applies initialize to the earliest (in // declaration order) assignment ready for initialization and updates // the inverse dependency ("blocking") graph. -func (o *InitOrder) flushReady(initialize func(*Node)) { +func (o *InitOrder) flushReady(initialize func(*ir.Node)) { for o.ready.Len() != 0 { - n := heap.Pop(&o.ready).(*Node) + n := heap.Pop(&o.ready).(*ir.Node) if n.Initorder() != InitPending || n.Xoffset != 0 { base.Fatalf("unexpected state: %v, %v, %v", n, n.Initorder(), n.Xoffset) } initialize(n) n.SetInitorder(InitDone) - n.Xoffset = BADWIDTH + n.Xoffset = types.BADWIDTH blocked := o.blocking[n] delete(o.blocking, n) @@ -181,7 +183,7 @@ func (o *InitOrder) flushReady(initialize func(*Node)) { // path points to a slice used for tracking the sequence of // variables/functions visited. Using a pointer to a slice allows the // slice capacity to grow and limit reallocations. -func findInitLoopAndExit(n *Node, path *[]*Node) { +func findInitLoopAndExit(n *ir.Node, path *[]*ir.Node) { // We implement a simple DFS loop-finding algorithm. This // could be faster, but initialization cycles are rare. @@ -194,14 +196,14 @@ func findInitLoopAndExit(n *Node, path *[]*Node) { // There might be multiple loops involving n; by sorting // references, we deterministically pick the one reported. - refers := collectDeps(n.Name.Defn, false).Sorted(func(ni, nj *Node) bool { + refers := collectDeps(n.Name.Defn, false).Sorted(func(ni, nj *ir.Node) bool { return ni.Pos.Before(nj.Pos) }) *path = append(*path, n) for _, ref := range refers { // Short-circuit variables that were initialized. - if ref.Class() == PEXTERN && ref.Name.Defn.Initorder() == InitDone { + if ref.Class() == ir.PEXTERN && ref.Name.Defn.Initorder() == InitDone { continue } @@ -213,12 +215,12 @@ func findInitLoopAndExit(n *Node, path *[]*Node) { // reportInitLoopAndExit reports and initialization loop as an error // and exits. However, if l is not actually an initialization loop, it // simply returns instead. -func reportInitLoopAndExit(l []*Node) { +func reportInitLoopAndExit(l []*ir.Node) { // Rotate loop so that the earliest variable declaration is at // the start. i := -1 for j, n := range l { - if n.Class() == PEXTERN && (i == -1 || n.Pos.Before(l[i].Pos)) { + if n.Class() == ir.PEXTERN && (i == -1 || n.Pos.Before(l[i].Pos)) { i = j } } @@ -236,9 +238,9 @@ func reportInitLoopAndExit(l []*Node) { var msg bytes.Buffer fmt.Fprintf(&msg, "initialization loop:\n") for _, n := range l { - fmt.Fprintf(&msg, "\t%v: %v refers to\n", n.Line(), n) + fmt.Fprintf(&msg, "\t%v: %v refers to\n", ir.Line(n), n) } - fmt.Fprintf(&msg, "\t%v: %v", l[0].Line(), l[0]) + fmt.Fprintf(&msg, "\t%v: %v", ir.Line(l[0]), l[0]) base.ErrorfAt(l[0].Pos, msg.String()) base.ErrorExit() @@ -248,14 +250,14 @@ func reportInitLoopAndExit(l []*Node) { // variables that declaration n depends on. If transitive is true, // then it also includes the transitive dependencies of any depended // upon functions (but not variables). -func collectDeps(n *Node, transitive bool) NodeSet { +func collectDeps(n *ir.Node, transitive bool) ir.NodeSet { d := initDeps{transitive: transitive} switch n.Op { - case OAS: + case ir.OAS: d.inspect(n.Right) - case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV: + case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: d.inspect(n.Right) - case ODCLFUNC: + case ir.ODCLFUNC: d.inspectList(n.Nbody) default: base.Fatalf("unexpected Op: %v", n.Op) @@ -265,31 +267,31 @@ func collectDeps(n *Node, transitive bool) NodeSet { type initDeps struct { transitive bool - seen NodeSet + seen ir.NodeSet } -func (d *initDeps) inspect(n *Node) { inspect(n, d.visit) } -func (d *initDeps) inspectList(l Nodes) { inspectList(l, d.visit) } +func (d *initDeps) inspect(n *ir.Node) { ir.Inspect(n, d.visit) } +func (d *initDeps) inspectList(l ir.Nodes) { ir.InspectList(l, d.visit) } // visit calls foundDep on any package-level functions or variables // referenced by n, if any. -func (d *initDeps) visit(n *Node) bool { +func (d *initDeps) visit(n *ir.Node) bool { switch n.Op { - case OMETHEXPR: - d.foundDep(n.MethodName()) + case ir.OMETHEXPR: + d.foundDep(methodExprName(n)) return false - case ONAME: + case ir.ONAME: switch n.Class() { - case PEXTERN, PFUNC: + case ir.PEXTERN, ir.PFUNC: d.foundDep(n) } - case OCLOSURE: + case ir.OCLOSURE: d.inspectList(n.Func.Decl.Nbody) - case ODOTMETH, OCALLPART: - d.foundDep(n.MethodName()) + case ir.ODOTMETH, ir.OCALLPART: + d.foundDep(methodExprName(n)) } return true @@ -297,7 +299,7 @@ func (d *initDeps) visit(n *Node) bool { // foundDep records that we've found a dependency on n by adding it to // seen. -func (d *initDeps) foundDep(n *Node) { +func (d *initDeps) foundDep(n *ir.Node) { // Can happen with method expressions involving interface // types; e.g., fixedbugs/issue4495.go. if n == nil { @@ -314,7 +316,7 @@ func (d *initDeps) foundDep(n *Node) { return } d.seen.Add(n) - if d.transitive && n.Class() == PFUNC { + if d.transitive && n.Class() == ir.PFUNC { d.inspectList(n.Name.Defn.Nbody) } } @@ -326,13 +328,13 @@ func (d *initDeps) foundDep(n *Node) { // an OAS node's Pos may not be unique. For example, given the // declaration "var a, b = f(), g()", "a" must be ordered before "b", // but both OAS nodes use the "=" token's position as their Pos. -type declOrder []*Node +type declOrder []*ir.Node func (s declOrder) Len() int { return len(s) } func (s declOrder) Less(i, j int) bool { return firstLHS(s[i]).Pos.Before(firstLHS(s[j]).Pos) } func (s declOrder) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s *declOrder) Push(x interface{}) { *s = append(*s, x.(*Node)) } +func (s *declOrder) Push(x interface{}) { *s = append(*s, x.(*ir.Node)) } func (s *declOrder) Pop() interface{} { n := (*s)[len(*s)-1] *s = (*s)[:len(*s)-1] @@ -341,11 +343,11 @@ func (s *declOrder) Pop() interface{} { // firstLHS returns the first expression on the left-hand side of // assignment n. -func firstLHS(n *Node) *Node { +func firstLHS(n *ir.Node) *ir.Node { switch n.Op { - case OAS: + case ir.OAS: return n.Left - case OAS2DOTTYPE, OAS2FUNC, OAS2RECV, OAS2MAPR: + case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2RECV, ir.OAS2MAPR: return n.List.First() } diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index d71ea9b5ed4..f982b43fb92 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -28,6 +28,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/logopt" "cmd/compile/internal/types" "cmd/internal/obj" @@ -52,8 +53,8 @@ const ( // Get the function's package. For ordinary functions it's on the ->sym, but for imported methods // the ->sym can be re-used in the local package, so peel it off the receiver's type. -func fnpkg(fn *Node) *types.Pkg { - if fn.IsMethod() { +func fnpkg(fn *ir.Node) *types.Pkg { + if ir.IsMethod(fn) { // method rcvr := fn.Type.Recv().Type @@ -72,7 +73,7 @@ func fnpkg(fn *Node) *types.Pkg { // Lazy typechecking of imported bodies. For local functions, caninl will set ->typecheck // because they're a copy of an already checked body. -func typecheckinl(fn *Node) { +func typecheckinl(fn *ir.Node) { lno := setlineno(fn) expandInline(fn) @@ -83,12 +84,12 @@ func typecheckinl(fn *Node) { // the ->inl of a local function has been typechecked before caninl copied it. pkg := fnpkg(fn) - if pkg == localpkg || pkg == nil { + if pkg == ir.LocalPkg || pkg == nil { return // typecheckinl on local function } if base.Flag.LowerM > 2 || base.Debug.Export != 0 { - fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym, fn, asNodes(fn.Func.Inl.Body)) + fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym, fn, ir.AsNodes(fn.Func.Inl.Body)) } savefn := Curfn @@ -110,8 +111,8 @@ func typecheckinl(fn *Node) { // Caninl determines whether fn is inlineable. // If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy. // fn and ->nbody will already have been typechecked. -func caninl(fn *Node) { - if fn.Op != ODCLFUNC { +func caninl(fn *ir.Node) { + if fn.Op != ir.ODCLFUNC { base.Fatalf("caninl %v", fn) } if fn.Func.Nname == nil { @@ -123,43 +124,43 @@ func caninl(fn *Node) { defer func() { if reason != "" { if base.Flag.LowerM > 1 { - fmt.Printf("%v: cannot inline %v: %s\n", fn.Line(), fn.Func.Nname, reason) + fmt.Printf("%v: cannot inline %v: %s\n", ir.Line(fn), fn.Func.Nname, reason) } if logopt.Enabled() { - logopt.LogOpt(fn.Pos, "cannotInlineFunction", "inline", fn.funcname(), reason) + logopt.LogOpt(fn.Pos, "cannotInlineFunction", "inline", ir.FuncName(fn), reason) } } }() } // If marked "go:noinline", don't inline - if fn.Func.Pragma&Noinline != 0 { + if fn.Func.Pragma&ir.Noinline != 0 { reason = "marked go:noinline" return } // If marked "go:norace" and -race compilation, don't inline. - if base.Flag.Race && fn.Func.Pragma&Norace != 0 { + if base.Flag.Race && fn.Func.Pragma&ir.Norace != 0 { reason = "marked go:norace with -race compilation" return } // If marked "go:nocheckptr" and -d checkptr compilation, don't inline. - if base.Debug.Checkptr != 0 && fn.Func.Pragma&NoCheckPtr != 0 { + if base.Debug.Checkptr != 0 && fn.Func.Pragma&ir.NoCheckPtr != 0 { reason = "marked go:nocheckptr" return } // If marked "go:cgo_unsafe_args", don't inline, since the // function makes assumptions about its argument frame layout. - if fn.Func.Pragma&CgoUnsafeArgs != 0 { + if fn.Func.Pragma&ir.CgoUnsafeArgs != 0 { reason = "marked go:cgo_unsafe_args" return } // If marked as "go:uintptrescapes", don't inline, since the // escape information is lost during inlining. - if fn.Func.Pragma&UintptrEscapes != 0 { + if fn.Func.Pragma&ir.UintptrEscapes != 0 { reason = "marked as having an escaping uintptr argument" return } @@ -168,7 +169,7 @@ func caninl(fn *Node) { // granularity, so inlining yeswritebarrierrec functions can // confuse it (#22342). As a workaround, disallow inlining // them for now. - if fn.Func.Pragma&Yeswritebarrierrec != 0 { + if fn.Func.Pragma&ir.Yeswritebarrierrec != 0 { reason = "marked go:yeswritebarrierrec" return } @@ -206,7 +207,7 @@ func caninl(fn *Node) { visitor := hairyVisitor{ budget: inlineMaxBudget, extraCallCost: cc, - usedLocals: make(map[*Node]bool), + usedLocals: make(map[*ir.Node]bool), } if visitor.visitList(fn.Nbody) { reason = visitor.reason @@ -217,29 +218,29 @@ func caninl(fn *Node) { return } - n.Func.Inl = &Inline{ + n.Func.Inl = &ir.Inline{ Cost: inlineMaxBudget - visitor.budget, Dcl: inlcopylist(pruneUnusedAutos(n.Name.Defn.Func.Dcl, &visitor)), Body: inlcopylist(fn.Nbody.Slice()), } if base.Flag.LowerM > 1 { - fmt.Printf("%v: can inline %#v with cost %d as: %#v { %#v }\n", fn.Line(), n, inlineMaxBudget-visitor.budget, fn.Type, asNodes(n.Func.Inl.Body)) + fmt.Printf("%v: can inline %#v with cost %d as: %#v { %#v }\n", ir.Line(fn), n, inlineMaxBudget-visitor.budget, fn.Type, ir.AsNodes(n.Func.Inl.Body)) } else if base.Flag.LowerM != 0 { - fmt.Printf("%v: can inline %v\n", fn.Line(), n) + fmt.Printf("%v: can inline %v\n", ir.Line(fn), n) } if logopt.Enabled() { - logopt.LogOpt(fn.Pos, "canInlineFunction", "inline", fn.funcname(), fmt.Sprintf("cost: %d", inlineMaxBudget-visitor.budget)) + logopt.LogOpt(fn.Pos, "canInlineFunction", "inline", ir.FuncName(fn), fmt.Sprintf("cost: %d", inlineMaxBudget-visitor.budget)) } } // inlFlood marks n's inline body for export and recursively ensures // all called functions are marked too. -func inlFlood(n *Node) { +func inlFlood(n *ir.Node) { if n == nil { return } - if n.Op != ONAME || n.Class() != PFUNC { + if n.Op != ir.ONAME || n.Class() != ir.PFUNC { base.Fatalf("inlFlood: unexpected %v, %v, %v", n, n.Op, n.Class()) } if n.Func == nil { @@ -259,28 +260,28 @@ func inlFlood(n *Node) { // Recursively identify all referenced functions for // reexport. We want to include even non-called functions, // because after inlining they might be callable. - inspectList(asNodes(n.Func.Inl.Body), func(n *Node) bool { + ir.InspectList(ir.AsNodes(n.Func.Inl.Body), func(n *ir.Node) bool { switch n.Op { - case OMETHEXPR: - inlFlood(n.MethodName()) + case ir.OMETHEXPR: + inlFlood(methodExprName(n)) - case ONAME: + case ir.ONAME: switch n.Class() { - case PFUNC: + case ir.PFUNC: inlFlood(n) exportsym(n) - case PEXTERN: + case ir.PEXTERN: exportsym(n) } - case ODOTMETH: - fn := n.MethodName() + case ir.ODOTMETH: + fn := methodExprName(n) inlFlood(fn) - case OCALLPART: + case ir.OCALLPART: // Okay, because we don't yet inline indirect // calls to method values. - case OCLOSURE: + case ir.OCLOSURE: // If the closure is inlinable, we'll need to // flood it too. But today we don't support // inlining functions that contain closures. @@ -299,11 +300,11 @@ type hairyVisitor struct { budget int32 reason string extraCallCost int32 - usedLocals map[*Node]bool + usedLocals map[*ir.Node]bool } // Look for anything we want to punt on. -func (v *hairyVisitor) visitList(ll Nodes) bool { +func (v *hairyVisitor) visitList(ll ir.Nodes) bool { for _, n := range ll.Slice() { if v.visit(n) { return true @@ -312,19 +313,19 @@ func (v *hairyVisitor) visitList(ll Nodes) bool { return false } -func (v *hairyVisitor) visit(n *Node) bool { +func (v *hairyVisitor) visit(n *ir.Node) bool { if n == nil { return false } switch n.Op { // Call is okay if inlinable and we have the budget for the body. - case OCALLFUNC: + case ir.OCALLFUNC: // Functions that call runtime.getcaller{pc,sp} can not be inlined // because getcaller{pc,sp} expect a pointer to the caller's first argument. // // runtime.throw is a "cheap call" like panic in normal code. - if n.Left.Op == ONAME && n.Left.Class() == PFUNC && isRuntimePkg(n.Left.Sym.Pkg) { + if n.Left.Op == ir.ONAME && n.Left.Class() == ir.PFUNC && isRuntimePkg(n.Left.Sym.Pkg) { fn := n.Left.Sym.Name if fn == "getcallerpc" || fn == "getcallersp" { v.reason = "call to " + fn @@ -350,7 +351,7 @@ func (v *hairyVisitor) visit(n *Node) bool { v.budget -= v.extraCallCost // Call is okay if inlinable and we have the budget for the body. - case OCALLMETH: + case ir.OCALLMETH: t := n.Left.Type if t == nil { base.Fatalf("no function type for [%p] %+v\n", n.Left, n.Left) @@ -366,7 +367,7 @@ func (v *hairyVisitor) visit(n *Node) bool { break } } - if inlfn := n.Left.MethodName().Func; inlfn.Inl != nil { + if inlfn := methodExprName(n.Left).Func; inlfn.Inl != nil { v.budget -= inlfn.Inl.Cost break } @@ -374,58 +375,58 @@ func (v *hairyVisitor) visit(n *Node) bool { v.budget -= v.extraCallCost // Things that are too hairy, irrespective of the budget - case OCALL, OCALLINTER: + case ir.OCALL, ir.OCALLINTER: // Call cost for non-leaf inlining. v.budget -= v.extraCallCost - case OPANIC: + case ir.OPANIC: v.budget -= inlineExtraPanicCost - case ORECOVER: + case ir.ORECOVER: // recover matches the argument frame pointer to find // the right panic value, so it needs an argument frame. v.reason = "call to recover" return true - case OCLOSURE, - ORANGE, - OSELECT, - OGO, - ODEFER, - ODCLTYPE, // can't print yet - ORETJMP: + case ir.OCLOSURE, + ir.ORANGE, + ir.OSELECT, + ir.OGO, + ir.ODEFER, + ir.ODCLTYPE, // can't print yet + ir.ORETJMP: v.reason = "unhandled op " + n.Op.String() return true - case OAPPEND: + case ir.OAPPEND: v.budget -= inlineExtraAppendCost - case ODCLCONST, OEMPTY, OFALL: + case ir.ODCLCONST, ir.OEMPTY, ir.OFALL: // These nodes don't produce code; omit from inlining budget. return false - case OLABEL: + case ir.OLABEL: // TODO(mdempsky): Add support for inlining labeled control statements. - if n.labeledControl() != nil { + if labeledControl(n) != nil { v.reason = "labeled control" return true } - case OBREAK, OCONTINUE: + case ir.OBREAK, ir.OCONTINUE: if n.Sym != nil { // Should have short-circuited due to labeledControl above. base.Fatalf("unexpected labeled break/continue: %v", n) } - case OIF: - if Isconst(n.Left, constant.Bool) { + case ir.OIF: + if ir.IsConst(n.Left, constant.Bool) { // This if and the condition cost nothing. return v.visitList(n.Ninit) || v.visitList(n.Nbody) || v.visitList(n.Rlist) } - case ONAME: - if n.Class() == PAUTO { + case ir.ONAME: + if n.Class() == ir.PAUTO { v.usedLocals[n] = true } @@ -446,26 +447,26 @@ func (v *hairyVisitor) visit(n *Node) bool { // inlcopylist (together with inlcopy) recursively copies a list of nodes, except // that it keeps the same ONAME, OTYPE, and OLITERAL nodes. It is used for copying // the body and dcls of an inlineable function. -func inlcopylist(ll []*Node) []*Node { - s := make([]*Node, 0, len(ll)) +func inlcopylist(ll []*ir.Node) []*ir.Node { + s := make([]*ir.Node, 0, len(ll)) for _, n := range ll { s = append(s, inlcopy(n)) } return s } -func inlcopy(n *Node) *Node { +func inlcopy(n *ir.Node) *ir.Node { if n == nil { return nil } switch n.Op { - case ONAME, OTYPE, OLITERAL, ONIL: + case ir.ONAME, ir.OTYPE, ir.OLITERAL, ir.ONIL: return n } - m := n.copy() - if n.Op != OCALLPART && m.Func != nil { + m := ir.Copy(n) + if n.Op != ir.OCALLPART && m.Func != nil { base.Fatalf("unexpected Func: %v", m) } m.Left = inlcopy(n.Left) @@ -478,7 +479,7 @@ func inlcopy(n *Node) *Node { return m } -func countNodes(n *Node) int { +func countNodes(n *ir.Node) int { if n == nil { return 0 } @@ -502,7 +503,7 @@ func countNodes(n *Node) int { // Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any // calls made to inlineable functions. This is the external entry point. -func inlcalls(fn *Node) { +func inlcalls(fn *ir.Node) { savefn := Curfn Curfn = fn maxCost := int32(inlineMaxBudget) @@ -515,7 +516,7 @@ func inlcalls(fn *Node) { // but allow inlining if there is a recursion cycle of many functions. // Most likely, the inlining will stop before we even hit the beginning of // the cycle again, but the map catches the unusual case. - inlMap := make(map[*Node]bool) + inlMap := make(map[*ir.Node]bool) fn = inlnode(fn, maxCost, inlMap) if fn != Curfn { base.Fatalf("inlnode replaced curfn") @@ -524,8 +525,8 @@ func inlcalls(fn *Node) { } // Turn an OINLCALL into a statement. -func inlconv2stmt(n *Node) { - n.Op = OBLOCK +func inlconv2stmt(n *ir.Node) { + n.Op = ir.OBLOCK // n->ninit stays n.List.Set(n.Nbody.Slice()) @@ -537,7 +538,7 @@ func inlconv2stmt(n *Node) { // Turn an OINLCALL into a single valued expression. // The result of inlconv2expr MUST be assigned back to n, e.g. // n.Left = inlconv2expr(n.Left) -func inlconv2expr(n *Node) *Node { +func inlconv2expr(n *ir.Node) *ir.Node { r := n.Rlist.First() return addinit(r, append(n.Ninit.Slice(), n.Nbody.Slice()...)) } @@ -547,8 +548,8 @@ func inlconv2expr(n *Node) *Node { // containing the inlined statements on the first list element so // order will be preserved Used in return, oas2func and call // statements. -func inlconv2list(n *Node) []*Node { - if n.Op != OINLCALL || n.Rlist.Len() == 0 { +func inlconv2list(n *ir.Node) []*ir.Node { + if n.Op != ir.OINLCALL || n.Rlist.Len() == 0 { base.Fatalf("inlconv2list %+v\n", n) } @@ -557,7 +558,7 @@ func inlconv2list(n *Node) []*Node { return s } -func inlnodelist(l Nodes, maxCost int32, inlMap map[*Node]bool) { +func inlnodelist(l ir.Nodes, maxCost int32, inlMap map[*ir.Node]bool) { s := l.Slice() for i := range s { s[i] = inlnode(s[i], maxCost, inlMap) @@ -577,23 +578,23 @@ func inlnodelist(l Nodes, maxCost int32, inlMap map[*Node]bool) { // shorter and less complicated. // The result of inlnode MUST be assigned back to n, e.g. // n.Left = inlnode(n.Left) -func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node { +func inlnode(n *ir.Node, maxCost int32, inlMap map[*ir.Node]bool) *ir.Node { if n == nil { return n } switch n.Op { - case ODEFER, OGO: + case ir.ODEFER, ir.OGO: switch n.Left.Op { - case OCALLFUNC, OCALLMETH: + case ir.OCALLFUNC, ir.OCALLMETH: n.Left.SetNoInline(true) } // TODO do them here (or earlier), // so escape analysis can avoid more heapmoves. - case OCLOSURE: + case ir.OCLOSURE: return n - case OCALLMETH: + case ir.OCALLMETH: // Prevent inlining some reflect.Value methods when using checkptr, // even when package reflect was compiled without it (#35073). if s := n.Left.Sym; base.Debug.Checkptr != 0 && isReflectPkg(s.Pkg) && (s.Name == "Value.UnsafeAddr" || s.Name == "Value.Pointer") { @@ -605,24 +606,24 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node { inlnodelist(n.Ninit, maxCost, inlMap) for _, n1 := range n.Ninit.Slice() { - if n1.Op == OINLCALL { + if n1.Op == ir.OINLCALL { inlconv2stmt(n1) } } n.Left = inlnode(n.Left, maxCost, inlMap) - if n.Left != nil && n.Left.Op == OINLCALL { + if n.Left != nil && n.Left.Op == ir.OINLCALL { n.Left = inlconv2expr(n.Left) } n.Right = inlnode(n.Right, maxCost, inlMap) - if n.Right != nil && n.Right.Op == OINLCALL { - if n.Op == OFOR || n.Op == OFORUNTIL { + if n.Right != nil && n.Right.Op == ir.OINLCALL { + if n.Op == ir.OFOR || n.Op == ir.OFORUNTIL { inlconv2stmt(n.Right) - } else if n.Op == OAS2FUNC { + } else if n.Op == ir.OAS2FUNC { n.Rlist.Set(inlconv2list(n.Right)) n.Right = nil - n.Op = OAS2 + n.Op = ir.OAS2 n.SetTypecheck(0) n = typecheck(n, ctxStmt) } else { @@ -631,16 +632,16 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node { } inlnodelist(n.List, maxCost, inlMap) - if n.Op == OBLOCK { + if n.Op == ir.OBLOCK { for _, n2 := range n.List.Slice() { - if n2.Op == OINLCALL { + if n2.Op == ir.OINLCALL { inlconv2stmt(n2) } } } else { s := n.List.Slice() for i1, n1 := range s { - if n1 != nil && n1.Op == OINLCALL { + if n1 != nil && n1.Op == ir.OINLCALL { s[i1] = inlconv2expr(s[i1]) } } @@ -649,8 +650,8 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node { inlnodelist(n.Rlist, maxCost, inlMap) s := n.Rlist.Slice() for i1, n1 := range s { - if n1.Op == OINLCALL { - if n.Op == OIF { + if n1.Op == ir.OINLCALL { + if n.Op == ir.OIF { inlconv2stmt(n1) } else { s[i1] = inlconv2expr(s[i1]) @@ -660,7 +661,7 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node { inlnodelist(n.Nbody, maxCost, inlMap) for _, n := range n.Nbody.Slice() { - if n.Op == OINLCALL { + if n.Op == ir.OINLCALL { inlconv2stmt(n) } } @@ -669,16 +670,16 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node { // transmogrify this node itself unless inhibited by the // switch at the top of this function. switch n.Op { - case OCALLFUNC, OCALLMETH: + case ir.OCALLFUNC, ir.OCALLMETH: if n.NoInline() { return n } } switch n.Op { - case OCALLFUNC: + case ir.OCALLFUNC: if base.Flag.LowerM > 3 { - fmt.Printf("%v:call to func %+v\n", n.Line(), n.Left) + fmt.Printf("%v:call to func %+v\n", ir.Line(n), n.Left) } if isIntrinsicCall(n) { break @@ -687,9 +688,9 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node { n = mkinlcall(n, fn, maxCost, inlMap) } - case OCALLMETH: + case ir.OCALLMETH: if base.Flag.LowerM > 3 { - fmt.Printf("%v:call to meth %L\n", n.Line(), n.Left.Right) + fmt.Printf("%v:call to meth %L\n", ir.Line(n), n.Left.Right) } // typecheck should have resolved ODOTMETH->type, whose nname points to the actual function. @@ -697,7 +698,7 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node { base.Fatalf("no function type for [%p] %+v\n", n.Left, n.Left) } - n = mkinlcall(n, n.Left.MethodName(), maxCost, inlMap) + n = mkinlcall(n, methodExprName(n.Left), maxCost, inlMap) } base.Pos = lno @@ -706,11 +707,11 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node { // inlCallee takes a function-typed expression and returns the underlying function ONAME // that it refers to if statically known. Otherwise, it returns nil. -func inlCallee(fn *Node) *Node { +func inlCallee(fn *ir.Node) *ir.Node { fn = staticValue(fn) switch { - case fn.Op == OMETHEXPR: - n := fn.MethodName() + case fn.Op == ir.OMETHEXPR: + n := methodExprName(fn) // Check that receiver type matches fn.Left. // TODO(mdempsky): Handle implicit dereference // of pointer receiver argument? @@ -718,9 +719,9 @@ func inlCallee(fn *Node) *Node { return nil } return n - case fn.Op == ONAME && fn.Class() == PFUNC: + case fn.Op == ir.ONAME && fn.Class() == ir.PFUNC: return fn - case fn.Op == OCLOSURE: + case fn.Op == ir.OCLOSURE: c := fn.Func.Decl caninl(c) return c.Func.Nname @@ -728,9 +729,9 @@ func inlCallee(fn *Node) *Node { return nil } -func staticValue(n *Node) *Node { +func staticValue(n *ir.Node) *ir.Node { for { - if n.Op == OCONVNOP { + if n.Op == ir.OCONVNOP { n = n.Left continue } @@ -746,8 +747,8 @@ func staticValue(n *Node) *Node { // staticValue1 implements a simple SSA-like optimization. If n is a local variable // that is initialized and never reassigned, staticValue1 returns the initializer // expression. Otherwise, it returns nil. -func staticValue1(n *Node) *Node { - if n.Op != ONAME || n.Class() != PAUTO || n.Name.Addrtaken() { +func staticValue1(n *ir.Node) *ir.Node { + if n.Op != ir.ONAME || n.Class() != ir.PAUTO || n.Name.Addrtaken() { return nil } @@ -756,12 +757,12 @@ func staticValue1(n *Node) *Node { return nil } - var rhs *Node + var rhs *ir.Node FindRHS: switch defn.Op { - case OAS: + case ir.OAS: rhs = defn.Right - case OAS2: + case ir.OAS2: for i, lhs := range defn.List.Slice() { if lhs == n { rhs = defn.Rlist.Index(i) @@ -790,8 +791,8 @@ FindRHS: // useful for -m output documenting the reason for inhibited optimizations. // NB: global variables are always considered to be re-assigned. // TODO: handle initial declaration not including an assignment and followed by a single assignment? -func reassigned(n *Node) (bool, *Node) { - if n.Op != ONAME { +func reassigned(n *ir.Node) (bool, *ir.Node) { + if n.Op != ir.ONAME { base.Fatalf("reassigned %v", n) } // no way to reliably check for no-reassignment of globals, assume it can be @@ -804,7 +805,7 @@ func reassigned(n *Node) (bool, *Node) { // of the corresponding ODCLFUNC. // We need to walk the function body to check for reassignments so we follow the // linkage to the ODCLFUNC node as that is where body is held. - if f.Op == OCLOSURE { + if f.Op == ir.OCLOSURE { f = f.Func.Decl } v := reassignVisitor{name: n} @@ -813,19 +814,19 @@ func reassigned(n *Node) (bool, *Node) { } type reassignVisitor struct { - name *Node + name *ir.Node } -func (v *reassignVisitor) visit(n *Node) *Node { +func (v *reassignVisitor) visit(n *ir.Node) *ir.Node { if n == nil { return nil } switch n.Op { - case OAS: + case ir.OAS: if n.Left == v.name && n != v.name.Name.Defn { return n } - case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE: + case ir.OAS2, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2DOTTYPE: for _, p := range n.List.Slice() { if p == v.name && n != v.name.Name.Defn { return n @@ -853,7 +854,7 @@ func (v *reassignVisitor) visit(n *Node) *Node { return nil } -func (v *reassignVisitor) visitList(l Nodes) *Node { +func (v *reassignVisitor) visitList(l ir.Nodes) *ir.Node { for _, n := range l.Slice() { if a := v.visit(n); a != nil { return a @@ -862,17 +863,17 @@ func (v *reassignVisitor) visitList(l Nodes) *Node { return nil } -func inlParam(t *types.Field, as *Node, inlvars map[*Node]*Node) *Node { - n := asNode(t.Nname) - if n == nil || n.isBlank() { - return nblank +func inlParam(t *types.Field, as *ir.Node, inlvars map[*ir.Node]*ir.Node) *ir.Node { + n := ir.AsNode(t.Nname) + if n == nil || ir.IsBlank(n) { + return ir.BlankNode } inlvar := inlvars[n] if inlvar == nil { base.Fatalf("missing inlvar for %v", n) } - as.Ninit.Append(nod(ODCL, inlvar, nil)) + as.Ninit.Append(ir.Nod(ir.ODCL, inlvar, nil)) inlvar.Name.Defn = as return inlvar } @@ -886,11 +887,11 @@ var inlgen int // parameters. // The result of mkinlcall MUST be assigned back to n, e.g. // n.Left = mkinlcall(n.Left, fn, isddd) -func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { +func mkinlcall(n, fn *ir.Node, maxCost int32, inlMap map[*ir.Node]bool) *ir.Node { if fn.Func.Inl == nil { if logopt.Enabled() { - logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", Curfn.funcname(), - fmt.Sprintf("%s cannot be inlined", fn.pkgFuncName())) + logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", ir.FuncName(Curfn), + fmt.Sprintf("%s cannot be inlined", ir.PkgFuncName(fn))) } return n } @@ -898,8 +899,8 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { // The inlined function body is too big. Typically we use this check to restrict // inlining into very big functions. See issue 26546 and 17566. if logopt.Enabled() { - logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", Curfn.funcname(), - fmt.Sprintf("cost %d of %s exceeds max large caller cost %d", fn.Func.Inl.Cost, fn.pkgFuncName(), maxCost)) + logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", ir.FuncName(Curfn), + fmt.Sprintf("cost %d of %s exceeds max large caller cost %d", fn.Func.Inl.Cost, ir.PkgFuncName(fn), maxCost)) } return n } @@ -907,7 +908,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { if fn == Curfn || fn.Name.Defn == Curfn { // Can't recursively inline a function into itself. if logopt.Enabled() { - logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", fmt.Sprintf("recursive call to %s", Curfn.funcname())) + logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", fmt.Sprintf("recursive call to %s", ir.FuncName(Curfn))) } return n } @@ -924,7 +925,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { if inlMap[fn] { if base.Flag.LowerM > 1 { - fmt.Printf("%v: cannot inline %v into %v: repeated recursive cycle\n", n.Line(), fn, Curfn.funcname()) + fmt.Printf("%v: cannot inline %v into %v: repeated recursive cycle\n", ir.Line(n), fn, ir.FuncName(Curfn)) } return n } @@ -938,15 +939,15 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { // We have a function node, and it has an inlineable body. if base.Flag.LowerM > 1 { - fmt.Printf("%v: inlining call to %v %#v { %#v }\n", n.Line(), fn.Sym, fn.Type, asNodes(fn.Func.Inl.Body)) + fmt.Printf("%v: inlining call to %v %#v { %#v }\n", ir.Line(n), fn.Sym, fn.Type, ir.AsNodes(fn.Func.Inl.Body)) } else if base.Flag.LowerM != 0 { - fmt.Printf("%v: inlining call to %v\n", n.Line(), fn) + fmt.Printf("%v: inlining call to %v\n", ir.Line(n), fn) } if base.Flag.LowerM > 2 { - fmt.Printf("%v: Before inlining: %+v\n", n.Line(), n) + fmt.Printf("%v: Before inlining: %+v\n", ir.Line(n), n) } - if ssaDump != "" && ssaDump == Curfn.funcname() { + if ssaDump != "" && ssaDump == ir.FuncName(Curfn) { ssaDumpInlined = append(ssaDumpInlined, fn) } @@ -956,28 +957,28 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { // may contain side effects (e.g., added by addinit during // inlconv2expr or inlconv2list). Make sure to preserve these, // if necessary (#42703). - if n.Op == OCALLFUNC { + if n.Op == ir.OCALLFUNC { callee := n.Left - for callee.Op == OCONVNOP { + for callee.Op == ir.OCONVNOP { ninit.AppendNodes(&callee.Ninit) callee = callee.Left } - if callee.Op != ONAME && callee.Op != OCLOSURE && callee.Op != OMETHEXPR { + if callee.Op != ir.ONAME && callee.Op != ir.OCLOSURE && callee.Op != ir.OMETHEXPR { base.Fatalf("unexpected callee expression: %v", callee) } } // Make temp names to use instead of the originals. - inlvars := make(map[*Node]*Node) + inlvars := make(map[*ir.Node]*ir.Node) // record formals/locals for later post-processing - var inlfvars []*Node + var inlfvars []*ir.Node // Handle captured variables when inlining closures. if fn.Name.Defn != nil { if c := fn.Name.Defn.Func.OClosure; c != nil { for _, v := range c.Func.ClosureVars.Slice() { - if v.Op == OXXX { + if v.Op == ir.OXXX { continue } @@ -987,38 +988,38 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { // the reassigned check via some sort of copy propagation this would most // likely need to be changed to a loop to walk up to the correct Param if o == nil || (o.Name.Curfn != Curfn && o.Name.Curfn.Func.OClosure != Curfn) { - base.Fatalf("%v: unresolvable capture %v %v\n", n.Line(), fn, v) + base.Fatalf("%v: unresolvable capture %v %v\n", ir.Line(n), fn, v) } if v.Name.Byval() { iv := typecheck(inlvar(v), ctxExpr) - ninit.Append(nod(ODCL, iv, nil)) - ninit.Append(typecheck(nod(OAS, iv, o), ctxStmt)) + ninit.Append(ir.Nod(ir.ODCL, iv, nil)) + ninit.Append(typecheck(ir.Nod(ir.OAS, iv, o), ctxStmt)) inlvars[v] = iv } else { - addr := newname(lookup("&" + v.Sym.Name)) + addr := NewName(lookup("&" + v.Sym.Name)) addr.Type = types.NewPtr(v.Type) ia := typecheck(inlvar(addr), ctxExpr) - ninit.Append(nod(ODCL, ia, nil)) - ninit.Append(typecheck(nod(OAS, ia, nod(OADDR, o, nil)), ctxStmt)) + ninit.Append(ir.Nod(ir.ODCL, ia, nil)) + ninit.Append(typecheck(ir.Nod(ir.OAS, ia, ir.Nod(ir.OADDR, o, nil)), ctxStmt)) inlvars[addr] = ia // When capturing by reference, all occurrence of the captured var // must be substituted with dereference of the temporary address - inlvars[v] = typecheck(nod(ODEREF, ia, nil), ctxExpr) + inlvars[v] = typecheck(ir.Nod(ir.ODEREF, ia, nil), ctxExpr) } } } } for _, ln := range fn.Func.Inl.Dcl { - if ln.Op != ONAME { + if ln.Op != ir.ONAME { continue } - if ln.Class() == PPARAMOUT { // return values handled below. + if ln.Class() == ir.PPARAMOUT { // return values handled below. continue } - if ln.isParamStackCopy() { // ignore the on-stack copy of a parameter that moved to the heap + if isParamStackCopy(ln) { // ignore the on-stack copy of a parameter that moved to the heap // TODO(mdempsky): Remove once I'm confident // this never actually happens. We currently // perform inlining before escape analysis, so @@ -1028,7 +1029,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { inlf := typecheck(inlvar(ln), ctxExpr) inlvars[ln] = inlf if base.Flag.GenDwarfInl > 0 { - if ln.Class() == PPARAM { + if ln.Class() == ir.PPARAM { inlf.Name.SetInlFormal(true) } else { inlf.Name.SetInlLocal(true) @@ -1039,8 +1040,8 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { } nreturns := 0 - inspectList(asNodes(fn.Func.Inl.Body), func(n *Node) bool { - if n != nil && n.Op == ORETURN { + ir.InspectList(ir.AsNodes(fn.Func.Inl.Body), func(n *ir.Node) bool { + if n != nil && n.Op == ir.ORETURN { nreturns++ } return true @@ -1052,10 +1053,10 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { delayretvars := nreturns == 1 // temporaries for return values. - var retvars []*Node + var retvars []*ir.Node for i, t := range fn.Type.Results().Fields().Slice() { - var m *Node - if n := asNode(t.Nname); n != nil && !n.isBlank() && !strings.HasPrefix(n.Sym.Name, "~r") { + var m *ir.Node + if n := ir.AsNode(t.Nname); n != nil && !ir.IsBlank(n) && !strings.HasPrefix(n.Sym.Name, "~r") { m = inlvar(n) m = typecheck(m, ctxExpr) inlvars[n] = m @@ -1080,9 +1081,9 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { } // Assign arguments to the parameters' temp names. - as := nod(OAS2, nil, nil) + as := ir.Nod(ir.OAS2, nil, nil) as.SetColas(true) - if n.Op == OCALLMETH { + if n.Op == ir.OCALLMETH { if n.Left.Left == nil { base.Fatalf("method call without receiver: %+v", n) } @@ -1092,7 +1093,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { // For non-dotted calls to variadic functions, we assign the // variadic parameter's temp name separately. - var vas *Node + var vas *ir.Node if recv := fn.Type.Recv(); recv != nil { as.List.Append(inlParam(recv, as, inlvars)) @@ -1115,13 +1116,13 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { } varargs := as.List.Slice()[x:] - vas = nod(OAS, nil, nil) + vas = ir.Nod(ir.OAS, nil, nil) vas.Left = inlParam(param, vas, inlvars) if len(varargs) == 0 { vas.Right = nodnil() vas.Right.Type = param.Type } else { - vas.Right = nod(OCOMPLIT, nil, typenod(param.Type)) + vas.Right = ir.Nod(ir.OCOMPLIT, nil, typenod(param.Type)) vas.Right.List.Set(varargs) } } @@ -1139,8 +1140,8 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { if !delayretvars { // Zero the return parameters. for _, n := range retvars { - ninit.Append(nod(ODCL, n, nil)) - ras := nod(OAS, n, nil) + ninit.Append(ir.Nod(ir.ODCL, n, nil)) + ras := ir.Nod(ir.OAS, n, nil) ras = typecheck(ras, ctxStmt) ninit.Append(ras) } @@ -1161,7 +1162,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { // to put a breakpoint. Not sure if that's really necessary or not // (in which case it could go at the end of the function instead). // Note issue 28603. - inlMark := nod(OINLMARK, nil, nil) + inlMark := ir.Nod(ir.OINLMARK, nil, nil) inlMark.Pos = n.Pos.WithIsStmt() inlMark.Xoffset = int64(newIndex) ninit.Append(inlMark) @@ -1182,9 +1183,9 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { newInlIndex: newIndex, } - body := subst.list(asNodes(fn.Func.Inl.Body)) + body := subst.list(ir.AsNodes(fn.Func.Inl.Body)) - lab := nodSym(OLABEL, nil, retlabel) + lab := nodSym(ir.OLABEL, nil, retlabel) body = append(body, lab) typecheckslice(body, ctxStmt) @@ -1197,7 +1198,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { //dumplist("ninit post", ninit); - call := nod(OINLCALL, nil, nil) + call := ir.Nod(ir.OINLCALL, nil, nil) call.Ninit.Set(ninit.Slice()) call.Nbody.Set(body) call.Rlist.Set(retvars) @@ -1212,13 +1213,13 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { // luckily these are small. inlnodelist(call.Nbody, maxCost, inlMap) for _, n := range call.Nbody.Slice() { - if n.Op == OINLCALL { + if n.Op == ir.OINLCALL { inlconv2stmt(n) } } if base.Flag.LowerM > 2 { - fmt.Printf("%v: After inlining %+v\n\n", call.Line(), call) + fmt.Printf("%v: After inlining %+v\n\n", ir.Line(call), call) } return call @@ -1227,14 +1228,14 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { // Every time we expand a function we generate a new set of tmpnames, // PAUTO's in the calling functions, and link them off of the // PPARAM's, PAUTOS and PPARAMOUTs of the called function. -func inlvar(var_ *Node) *Node { +func inlvar(var_ *ir.Node) *ir.Node { if base.Flag.LowerM > 3 { fmt.Printf("inlvar %+v\n", var_) } - n := newname(var_.Sym) + n := NewName(var_.Sym) n.Type = var_.Type - n.SetClass(PAUTO) + n.SetClass(ir.PAUTO) n.Name.SetUsed(true) n.Name.Curfn = Curfn // the calling function, not the called one n.Name.SetAddrtaken(var_.Name.Addrtaken()) @@ -1244,10 +1245,10 @@ func inlvar(var_ *Node) *Node { } // Synthesize a variable to store the inlined function's results in. -func retvar(t *types.Field, i int) *Node { - n := newname(lookupN("~R", i)) +func retvar(t *types.Field, i int) *ir.Node { + n := NewName(lookupN("~R", i)) n.Type = t.Type - n.SetClass(PAUTO) + n.SetClass(ir.PAUTO) n.Name.SetUsed(true) n.Name.Curfn = Curfn // the calling function, not the called one Curfn.Func.Dcl = append(Curfn.Func.Dcl, n) @@ -1256,10 +1257,10 @@ func retvar(t *types.Field, i int) *Node { // Synthesize a variable to store the inlined function's arguments // when they come from a multiple return call. -func argvar(t *types.Type, i int) *Node { - n := newname(lookupN("~arg", i)) +func argvar(t *types.Type, i int) *ir.Node { + n := NewName(lookupN("~arg", i)) n.Type = t.Elem() - n.SetClass(PAUTO) + n.SetClass(ir.PAUTO) n.Name.SetUsed(true) n.Name.Curfn = Curfn // the calling function, not the called one Curfn.Func.Dcl = append(Curfn.Func.Dcl, n) @@ -1273,13 +1274,13 @@ type inlsubst struct { retlabel *types.Sym // Temporary result variables. - retvars []*Node + retvars []*ir.Node // Whether result variables should be initialized at the // "return" statement. delayretvars bool - inlvars map[*Node]*Node + inlvars map[*ir.Node]*ir.Node // bases maps from original PosBase to PosBase with an extra // inlined call frame. @@ -1291,8 +1292,8 @@ type inlsubst struct { } // list inlines a list of nodes. -func (subst *inlsubst) list(ll Nodes) []*Node { - s := make([]*Node, 0, ll.Len()) +func (subst *inlsubst) list(ll ir.Nodes) []*ir.Node { + s := make([]*ir.Node, 0, ll.Len()) for _, n := range ll.Slice() { s = append(s, subst.node(n)) } @@ -1303,13 +1304,13 @@ func (subst *inlsubst) list(ll Nodes) []*Node { // inlined function, substituting references to input/output // parameters with ones to the tmpnames, and substituting returns with // assignments to the output. -func (subst *inlsubst) node(n *Node) *Node { +func (subst *inlsubst) node(n *ir.Node) *ir.Node { if n == nil { return nil } switch n.Op { - case ONAME: + case ir.ONAME: if inlvar := subst.inlvars[n]; inlvar != nil { // These will be set during inlnode if base.Flag.LowerM > 2 { fmt.Printf("substituting name %+v -> %+v\n", n, inlvar) @@ -1322,10 +1323,10 @@ func (subst *inlsubst) node(n *Node) *Node { } return n - case OMETHEXPR: + case ir.OMETHEXPR: return n - case OLITERAL, ONIL, OTYPE: + case ir.OLITERAL, ir.ONIL, ir.OTYPE: // If n is a named constant or type, we can continue // using it in the inline copy. Otherwise, make a copy // so we can update the line number. @@ -1336,12 +1337,12 @@ func (subst *inlsubst) node(n *Node) *Node { // Since we don't handle bodies with closures, this return is guaranteed to belong to the current inlined function. // dump("Return before substitution", n); - case ORETURN: - m := nodSym(OGOTO, nil, subst.retlabel) + case ir.ORETURN: + m := nodSym(ir.OGOTO, nil, subst.retlabel) m.Ninit.Set(subst.list(n.Ninit)) if len(subst.retvars) != 0 && n.List.Len() != 0 { - as := nod(OAS2, nil, nil) + as := ir.Nod(ir.OAS2, nil, nil) // Make a shallow copy of retvars. // Otherwise OINLCALL.Rlist will be the same list, @@ -1353,7 +1354,7 @@ func (subst *inlsubst) node(n *Node) *Node { if subst.delayretvars { for _, n := range as.List.Slice() { - as.Ninit.Append(nod(ODCL, n, nil)) + as.Ninit.Append(ir.Nod(ir.ODCL, n, nil)) n.Name.Defn = as } } @@ -1368,8 +1369,8 @@ func (subst *inlsubst) node(n *Node) *Node { // dump("Return after substitution", m); return m - case OGOTO, OLABEL: - m := n.copy() + case ir.OGOTO, ir.OLABEL: + m := ir.Copy(n) m.Pos = subst.updatedPos(m.Pos) m.Ninit.Set(nil) p := fmt.Sprintf("%s·%d", n.Sym.Name, inlgen) @@ -1378,11 +1379,11 @@ func (subst *inlsubst) node(n *Node) *Node { return m } - m := n.copy() + m := ir.Copy(n) m.Pos = subst.updatedPos(m.Pos) m.Ninit.Set(nil) - if n.Op == OCLOSURE { + if n.Op == ir.OCLOSURE { base.Fatalf("cannot inline function containing closure: %+v", n) } @@ -1408,10 +1409,10 @@ func (subst *inlsubst) updatedPos(xpos src.XPos) src.XPos { return base.Ctxt.PosTable.XPos(pos) } -func pruneUnusedAutos(ll []*Node, vis *hairyVisitor) []*Node { - s := make([]*Node, 0, len(ll)) +func pruneUnusedAutos(ll []*ir.Node, vis *hairyVisitor) []*ir.Node { + s := make([]*ir.Node, 0, len(ll)) for _, n := range ll { - if n.Class() == PAUTO { + if n.Class() == ir.PAUTO { if _, found := vis.usedLocals[n]; !found { continue } @@ -1423,19 +1424,19 @@ func pruneUnusedAutos(ll []*Node, vis *hairyVisitor) []*Node { // devirtualize replaces interface method calls within fn with direct // concrete-type method calls where applicable. -func devirtualize(fn *Node) { +func devirtualize(fn *ir.Node) { Curfn = fn - inspectList(fn.Nbody, func(n *Node) bool { - if n.Op == OCALLINTER { + ir.InspectList(fn.Nbody, func(n *ir.Node) bool { + if n.Op == ir.OCALLINTER { devirtualizeCall(n) } return true }) } -func devirtualizeCall(call *Node) { +func devirtualizeCall(call *ir.Node) { recv := staticValue(call.Left.Left) - if recv.Op != OCONVIFACE { + if recv.Op != ir.OCONVIFACE { return } @@ -1444,23 +1445,23 @@ func devirtualizeCall(call *Node) { return } - x := nodl(call.Left.Pos, ODOTTYPE, call.Left.Left, nil) + x := ir.NodAt(call.Left.Pos, ir.ODOTTYPE, call.Left.Left, nil) x.Type = typ - x = nodlSym(call.Left.Pos, OXDOT, x, call.Left.Sym) + x = nodlSym(call.Left.Pos, ir.OXDOT, x, call.Left.Sym) x = typecheck(x, ctxExpr|ctxCallee) switch x.Op { - case ODOTMETH: + case ir.ODOTMETH: if base.Flag.LowerM != 0 { base.WarnfAt(call.Pos, "devirtualizing %v to %v", call.Left, typ) } - call.Op = OCALLMETH + call.Op = ir.OCALLMETH call.Left = x - case ODOTINTER: + case ir.ODOTINTER: // Promoted method from embedded interface-typed field (#42279). if base.Flag.LowerM != 0 { base.WarnfAt(call.Pos, "partially devirtualizing %v to %v", call.Left, typ) } - call.Op = OCALLINTER + call.Op = ir.OCALLINTER call.Left = x default: // TODO(mdempsky): Turn back into Fatalf after more testing. diff --git a/src/cmd/compile/internal/gc/lex.go b/src/cmd/compile/internal/gc/lex.go index 30ef4d0eb20..39d73867e4d 100644 --- a/src/cmd/compile/internal/gc/lex.go +++ b/src/cmd/compile/internal/gc/lex.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/syntax" "cmd/internal/objabi" "cmd/internal/src" @@ -25,78 +26,51 @@ func isQuoted(s string) bool { return len(s) >= 2 && s[0] == '"' && s[len(s)-1] == '"' } -type PragmaFlag int16 - const ( - // Func pragmas. - Nointerface PragmaFlag = 1 << iota - Noescape // func parameters don't escape - Norace // func must not have race detector annotations - Nosplit // func should not execute on separate stack - Noinline // func should not be inlined - NoCheckPtr // func should not be instrumented by checkptr - CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all - UintptrEscapes // pointers converted to uintptr escape + FuncPragmas = ir.Nointerface | + ir.Noescape | + ir.Norace | + ir.Nosplit | + ir.Noinline | + ir.NoCheckPtr | + ir.CgoUnsafeArgs | + ir.UintptrEscapes | + ir.Systemstack | + ir.Nowritebarrier | + ir.Nowritebarrierrec | + ir.Yeswritebarrierrec - // Runtime-only func pragmas. - // See ../../../../runtime/README.md for detailed descriptions. - Systemstack // func must run on system stack - Nowritebarrier // emit compiler error instead of write barrier - Nowritebarrierrec // error on write barrier in this or recursive callees - Yeswritebarrierrec // cancels Nowritebarrierrec in this function and callees - - // Runtime and cgo type pragmas - NotInHeap // values of this type must not be heap allocated - - // Go command pragmas - GoBuildPragma + TypePragmas = ir.NotInHeap ) -const ( - FuncPragmas = Nointerface | - Noescape | - Norace | - Nosplit | - Noinline | - NoCheckPtr | - CgoUnsafeArgs | - UintptrEscapes | - Systemstack | - Nowritebarrier | - Nowritebarrierrec | - Yeswritebarrierrec - - TypePragmas = NotInHeap -) - -func pragmaFlag(verb string) PragmaFlag { +func pragmaFlag(verb string) ir.PragmaFlag { switch verb { case "go:build": - return GoBuildPragma + return ir.GoBuildPragma case "go:nointerface": if objabi.Fieldtrack_enabled != 0 { - return Nointerface + return ir.Nointerface } case "go:noescape": - return Noescape + return ir.Noescape case "go:norace": - return Norace + return ir.Norace case "go:nosplit": - return Nosplit | NoCheckPtr // implies NoCheckPtr (see #34972) + return ir.Nosplit | ir.NoCheckPtr // implies NoCheckPtr (see #34972) case "go:noinline": - return Noinline + return ir.Noinline case "go:nocheckptr": - return NoCheckPtr + return ir.NoCheckPtr case "go:systemstack": - return Systemstack + return ir.Systemstack case "go:nowritebarrier": - return Nowritebarrier + return ir.Nowritebarrier case "go:nowritebarrierrec": - return Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier + return ir.Nowritebarrierrec | ir.Nowritebarrier // implies Nowritebarrier case "go:yeswritebarrierrec": - return Yeswritebarrierrec + return ir.Yeswritebarrierrec case "go:cgo_unsafe_args": - return CgoUnsafeArgs | NoCheckPtr // implies NoCheckPtr (see #34968) + return ir.CgoUnsafeArgs | ir.NoCheckPtr // implies NoCheckPtr (see #34968) case "go:uintptrescapes": // For the next function declared in the file // any uintptr arguments may be pointer values @@ -109,9 +83,9 @@ func pragmaFlag(verb string) PragmaFlag { // call. The conversion to uintptr must appear // in the argument list. // Used in syscall/dll_windows.go. - return UintptrEscapes + return ir.UintptrEscapes case "go:notinheap": - return NotInHeap + return ir.NotInHeap } return 0 } diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index c66139027a6..24e926602bf 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/ir" "cmd/compile/internal/logopt" "cmd/compile/internal/ssa" "cmd/compile/internal/types" @@ -73,17 +74,17 @@ func Main(archInit func(*Arch)) { // See bugs 31188 and 21945 (CLs 170638, 98075, 72371). base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin - localpkg = types.NewPkg("", "") - localpkg.Prefix = "\"\"" + ir.LocalPkg = types.NewPkg("", "") + ir.LocalPkg.Prefix = "\"\"" // We won't know localpkg's height until after import // processing. In the mean time, set to MaxPkgHeight to ensure // height comparisons at least work until then. - localpkg.Height = types.MaxPkgHeight + ir.LocalPkg.Height = types.MaxPkgHeight // pseudo-package, for scoping - builtinpkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin? - builtinpkg.Prefix = "go.builtin" // not go%2ebuiltin + ir.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin? + ir.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin // pseudo-package, accessed by import "unsafe" unsafepkg = types.NewPkg("unsafe", "unsafe") @@ -209,29 +210,18 @@ func Main(archInit func(*Arch)) { types.Widthptr = Widthptr types.Dowidth = dowidth types.Fatalf = base.Fatalf - types.Sconv = func(s *types.Sym, flag, mode int) string { - return sconv(s, FmtFlag(flag), fmtMode(mode)) - } - types.Tconv = func(t *types.Type, flag, mode int) string { - return tconv(t, FmtFlag(flag), fmtMode(mode)) - } - types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) { - symFormat(sym, s, verb, fmtMode(mode)) - } - types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) { - typeFormat(t, s, verb, fmtMode(mode)) - } + ir.InstallTypeFormats() types.TypeLinkSym = func(t *types.Type) *obj.LSym { return typenamesym(t).Linksym() } - types.FmtLeft = int(FmtLeft) - types.FmtUnsigned = int(FmtUnsigned) - types.FErr = int(FErr) + types.FmtLeft = int(ir.FmtLeft) + types.FmtUnsigned = int(ir.FmtUnsigned) + types.FErr = int(ir.FErr) types.Ctxt = base.Ctxt initUniverse() - dclcontext = PEXTERN + dclcontext = ir.PEXTERN autogeneratedPos = makePos(src.NewFileBase("", ""), 1, 0) @@ -263,7 +253,7 @@ func Main(archInit func(*Arch)) { timings.Start("fe", "typecheck", "top1") for i := 0; i < len(xtop); i++ { n := xtop[i] - if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias()) { + if op := n.Op; op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.Left.Name.Param.Alias()) { xtop[i] = typecheck(n, ctxStmt) } } @@ -275,7 +265,7 @@ func Main(archInit func(*Arch)) { timings.Start("fe", "typecheck", "top2") for i := 0; i < len(xtop); i++ { n := xtop[i] - if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias() { + if op := n.Op; op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.Left.Name.Param.Alias() { xtop[i] = typecheck(n, ctxStmt) } } @@ -286,7 +276,7 @@ func Main(archInit func(*Arch)) { var fcount int64 for i := 0; i < len(xtop); i++ { n := xtop[i] - if n.Op == ODCLFUNC { + if n.Op == ir.ODCLFUNC { Curfn = n decldepth = 1 errorsBefore := base.Errors() @@ -316,7 +306,7 @@ func Main(archInit func(*Arch)) { // because variables captured by value do not escape. timings.Start("fe", "capturevars") for _, n := range xtop { - if n.Op == ODCLFUNC && n.Func.OClosure != nil { + if n.Op == ir.ODCLFUNC && n.Func.OClosure != nil { Curfn = n capturevars(n) } @@ -340,7 +330,7 @@ func Main(archInit func(*Arch)) { if base.Flag.LowerL != 0 { // Find functions that can be inlined and clone them before walk expands them. - visitBottomUp(xtop, func(list []*Node, recursive bool) { + visitBottomUp(xtop, func(list []*ir.Node, recursive bool) { numfns := numNonClosures(list) for _, n := range list { if !recursive || numfns > 1 { @@ -350,7 +340,7 @@ func Main(archInit func(*Arch)) { caninl(n) } else { if base.Flag.LowerM > 1 { - fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname) + fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(n), n.Func.Nname) } } inlcalls(n) @@ -359,7 +349,7 @@ func Main(archInit func(*Arch)) { } for _, n := range xtop { - if n.Op == ODCLFUNC { + if n.Op == ir.ODCLFUNC { devirtualize(n) } } @@ -389,7 +379,7 @@ func Main(archInit func(*Arch)) { // before walk reaches a call of a closure. timings.Start("fe", "xclosures") for _, n := range xtop { - if n.Op == ODCLFUNC && n.Func.OClosure != nil { + if n.Op == ir.ODCLFUNC && n.Func.OClosure != nil { Curfn = n transformclosure(n) } @@ -412,7 +402,7 @@ func Main(archInit func(*Arch)) { fcount = 0 for i := 0; i < len(xtop); i++ { n := xtop[i] - if n.Op == ODCLFUNC { + if n.Op == ir.ODCLFUNC { funccompile(n) fcount++ } @@ -440,7 +430,7 @@ func Main(archInit func(*Arch)) { // Phase 9: Check external declarations. timings.Start("be", "externaldcls") for i, n := range externdcl { - if n.Op == ONAME { + if n.Op == ir.ONAME { externdcl[i] = typecheck(externdcl[i], ctxExpr) } } @@ -491,7 +481,7 @@ func Main(archInit func(*Arch)) { } // numNonClosures returns the number of functions in list which are not closures. -func numNonClosures(list []*Node) int { +func numNonClosures(list []*ir.Node) int { count := 0 for _, n := range list { if n.Func.OClosure == nil { @@ -934,14 +924,14 @@ func pkgnotused(lineno src.XPos, path string, name string) { } func mkpackage(pkgname string) { - if localpkg.Name == "" { + if ir.LocalPkg.Name == "" { if pkgname == "_" { base.Errorf("invalid package name _") } - localpkg.Name = pkgname + ir.LocalPkg.Name = pkgname } else { - if pkgname != localpkg.Name { - base.Errorf("package %s; expected %s", pkgname, localpkg.Name) + if pkgname != ir.LocalPkg.Name { + base.Errorf("package %s; expected %s", pkgname, ir.LocalPkg.Name) } } } @@ -954,12 +944,12 @@ func clearImports() { } var unused []importedPkg - for _, s := range localpkg.Syms { - n := asNode(s.Def) + for _, s := range ir.LocalPkg.Syms { + n := ir.AsNode(s.Def) if n == nil { continue } - if n.Op == OPACK { + if n.Op == ir.OPACK { // throw away top-level package name left over // from previous file. // leave s->block set to cause redeclaration @@ -990,7 +980,7 @@ func clearImports() { } func IsAlias(sym *types.Sym) bool { - return sym.Def != nil && asNode(sym.Def).Sym != sym + return sym.Def != nil && ir.AsNode(sym.Def).Sym != sym } // recordFlags records the specified command-line flags to be placed @@ -1057,7 +1047,7 @@ func recordPackageName() { // together two package main archives. So allow dups. s.Set(obj.AttrDuplicateOK, true) base.Ctxt.Data = append(base.Ctxt.Data, s) - s.P = []byte(localpkg.Name) + s.P = []byte(ir.LocalPkg.Name) } // currentLang returns the current language version. @@ -1084,9 +1074,9 @@ var langWant lang func langSupported(major, minor int, pkg *types.Pkg) bool { if pkg == nil { // TODO(mdempsky): Set Pkg for local types earlier. - pkg = localpkg + pkg = ir.LocalPkg } - if pkg != localpkg { + if pkg != ir.LocalPkg { // Assume imported packages passed type-checking. return true } diff --git a/src/cmd/compile/internal/gc/mkbuiltin.go b/src/cmd/compile/internal/gc/mkbuiltin.go index 63d2a12c079..8fa6d02f2c2 100644 --- a/src/cmd/compile/internal/gc/mkbuiltin.go +++ b/src/cmd/compile/internal/gc/mkbuiltin.go @@ -35,7 +35,10 @@ func main() { fmt.Fprintln(&b) fmt.Fprintln(&b, "package gc") fmt.Fprintln(&b) - fmt.Fprintln(&b, `import "cmd/compile/internal/types"`) + fmt.Fprintln(&b, `import (`) + fmt.Fprintln(&b, ` "cmd/compile/internal/ir"`) + fmt.Fprintln(&b, ` "cmd/compile/internal/types"`) + fmt.Fprintln(&b, `)`) mkbuiltin(&b, "runtime") @@ -144,12 +147,12 @@ func (i *typeInterner) mktype(t ast.Expr) string { case "rune": return "types.Runetype" } - return fmt.Sprintf("types.Types[T%s]", strings.ToUpper(t.Name)) + return fmt.Sprintf("types.Types[types.T%s]", strings.ToUpper(t.Name)) case *ast.SelectorExpr: if t.X.(*ast.Ident).Name != "unsafe" || t.Sel.Name != "Pointer" { log.Fatalf("unhandled type: %#v", t) } - return "types.Types[TUNSAFEPTR]" + return "types.Types[types.TUNSAFEPTR]" case *ast.ArrayType: if t.Len == nil { @@ -171,7 +174,7 @@ func (i *typeInterner) mktype(t ast.Expr) string { if len(t.Methods.List) != 0 { log.Fatal("non-empty interfaces unsupported") } - return "types.Types[TINTER]" + return "types.Types[types.TINTER]" case *ast.MapType: return fmt.Sprintf("types.NewMap(%s, %s)", i.subtype(t.Key), i.subtype(t.Value)) case *ast.StarExpr: @@ -204,7 +207,7 @@ func (i *typeInterner) fields(fl *ast.FieldList, keepNames bool) string { } } } - return fmt.Sprintf("[]*Node{%s}", strings.Join(res, ", ")) + return fmt.Sprintf("[]*ir.Node{%s}", strings.Join(res, ", ")) } func intconst(e ast.Expr) int64 { diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 6dae2cd0a41..eeed3740f06 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -17,6 +17,7 @@ import ( "unicode/utf8" "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/syntax" "cmd/compile/internal/types" "cmd/internal/obj" @@ -74,7 +75,7 @@ func parseFiles(filenames []string) uint { testdclstack() } - localpkg.Height = myheight + ir.LocalPkg.Height = myheight return lines } @@ -140,7 +141,7 @@ type noder struct { linknames []linkname pragcgobuf [][]string err chan syntax.Error - scope ScopeID + scope ir.ScopeID importedUnsafe bool importedEmbed bool @@ -151,7 +152,7 @@ type noder struct { lastCloseScopePos syntax.Pos } -func (p *noder) funcBody(fn *Node, block *syntax.BlockStmt) { +func (p *noder) funcBody(fn *ir.Node, block *syntax.BlockStmt) { oldScope := p.scope p.scope = 0 funchdr(fn) @@ -159,7 +160,7 @@ func (p *noder) funcBody(fn *Node, block *syntax.BlockStmt) { if block != nil { body := p.stmts(block.List) if body == nil { - body = []*Node{nod(OEMPTY, nil, nil)} + body = []*ir.Node{ir.Nod(ir.OEMPTY, nil, nil)} } fn.Nbody.Set(body) @@ -177,7 +178,7 @@ func (p *noder) openScope(pos syntax.Pos) { if trackScopes { Curfn.Func.Parents = append(Curfn.Func.Parents, p.scope) p.scopeVars = append(p.scopeVars, len(Curfn.Func.Dcl)) - p.scope = ScopeID(len(Curfn.Func.Parents)) + p.scope = ir.ScopeID(len(Curfn.Func.Parents)) p.markScope(pos) } @@ -202,7 +203,7 @@ func (p *noder) closeScope(pos syntax.Pos) { nmarks := len(Curfn.Func.Marks) Curfn.Func.Marks[nmarks-1].Scope = p.scope - prevScope := ScopeID(0) + prevScope := ir.ScopeID(0) if nmarks >= 2 { prevScope = Curfn.Func.Marks[nmarks-2].Scope } @@ -223,7 +224,7 @@ func (p *noder) markScope(pos syntax.Pos) { if i := len(Curfn.Func.Marks); i > 0 && Curfn.Func.Marks[i-1].Pos == xpos { Curfn.Func.Marks[i-1].Scope = p.scope } else { - Curfn.Func.Marks = append(Curfn.Func.Marks, Mark{xpos, p.scope}) + Curfn.Func.Marks = append(Curfn.Func.Marks, ir.Mark{Pos: xpos, Scope: p.scope}) } } @@ -251,7 +252,7 @@ func (p *noder) node() { mkpackage(p.file.PkgName.Value) if pragma, ok := p.file.Pragma.(*Pragma); ok { - pragma.Flag &^= GoBuildPragma + pragma.Flag &^= ir.GoBuildPragma p.checkUnused(pragma) } @@ -293,7 +294,7 @@ func (p *noder) node() { clearImports() } -func (p *noder) decls(decls []syntax.Decl) (l []*Node) { +func (p *noder) decls(decls []syntax.Decl) (l []*ir.Node) { var cs constState for _, decl := range decls { @@ -355,7 +356,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) { my = lookup(ipkg.Name) } - pack := p.nod(imp, OPACK, nil, nil) + pack := p.nod(imp, ir.OPACK, nil, nil) pack.Sym = my pack.Name.Pkg = ipkg @@ -372,16 +373,16 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) { if my.Def != nil { redeclare(pack.Pos, my, "as imported package name") } - my.Def = asTypesNode(pack) + my.Def = ir.AsTypesNode(pack) my.Lastlineno = pack.Pos my.Block = 1 // at top level } -func (p *noder) varDecl(decl *syntax.VarDecl) []*Node { +func (p *noder) varDecl(decl *syntax.VarDecl) []*ir.Node { names := p.declNames(decl.NameList) typ := p.typeExprOrNil(decl.Type) - var exprs []*Node + var exprs []*ir.Node if decl.Values != nil { exprs = p.exprList(decl.Values) } @@ -413,12 +414,12 @@ func (p *noder) varDecl(decl *syntax.VarDecl) []*Node { // constant declarations are handled correctly (e.g., issue 15550). type constState struct { group *syntax.Group - typ *Node - values []*Node + typ *ir.Node + values []*ir.Node iota int64 } -func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node { +func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*ir.Node { if decl.Group == nil || decl.Group != cs.group { *cs = constState{ group: decl.Group, @@ -432,7 +433,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node { names := p.declNames(decl.NameList) typ := p.typeExprOrNil(decl.Type) - var values []*Node + var values []*ir.Node if decl.Values != nil { values = p.exprList(decl.Values) cs.typ, cs.values = typ, values @@ -443,7 +444,7 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node { typ, values = cs.typ, cs.values } - nn := make([]*Node, 0, len(names)) + nn := make([]*ir.Node, 0, len(names)) for i, n := range names { if i >= len(values) { base.Errorf("missing value in const declaration") @@ -454,14 +455,14 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node { v = treecopy(v, n.Pos) } - n.Op = OLITERAL + n.Op = ir.OLITERAL declare(n, dclcontext) n.Name.Param.Ntype = typ n.Name.Defn = v n.SetIota(cs.iota) - nn = append(nn, p.nod(decl, ODCLCONST, n, nil)) + nn = append(nn, p.nod(decl, ir.ODCLCONST, n, nil)) } if len(values) > len(names) { @@ -473,9 +474,9 @@ func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node { return nn } -func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node { +func (p *noder) typeDecl(decl *syntax.TypeDecl) *ir.Node { n := p.declName(decl.Name) - n.Op = OTYPE + n.Op = ir.OTYPE declare(n, dclcontext) // decl.Type may be nil but in that case we got a syntax error during parsing @@ -492,31 +493,31 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node { p.checkUnused(pragma) } - nod := p.nod(decl, ODCLTYPE, n, nil) - if param.Alias() && !langSupported(1, 9, localpkg) { + nod := p.nod(decl, ir.ODCLTYPE, n, nil) + if param.Alias() && !langSupported(1, 9, ir.LocalPkg) { base.ErrorfAt(nod.Pos, "type aliases only supported as of -lang=go1.9") } return nod } -func (p *noder) declNames(names []*syntax.Name) []*Node { - nodes := make([]*Node, 0, len(names)) +func (p *noder) declNames(names []*syntax.Name) []*ir.Node { + nodes := make([]*ir.Node, 0, len(names)) for _, name := range names { nodes = append(nodes, p.declName(name)) } return nodes } -func (p *noder) declName(name *syntax.Name) *Node { +func (p *noder) declName(name *syntax.Name) *ir.Node { n := dclname(p.name(name)) n.Pos = p.pos(name) return n } -func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node { +func (p *noder) funcDecl(fun *syntax.FuncDecl) *ir.Node { name := p.name(fun.Name) t := p.signature(fun.Recv, fun.Type) - f := p.nod(fun, ODCLFUNC, nil, nil) + f := p.nod(fun, ir.ODCLFUNC, nil, nil) if fun.Recv == nil { if name.Name == "init" { @@ -526,14 +527,14 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node { } } - if localpkg.Name == "main" && name.Name == "main" { + if ir.LocalPkg.Name == "main" && name.Name == "main" { if t.List.Len() > 0 || t.Rlist.Len() > 0 { base.ErrorfAt(f.Pos, "func main must have no arguments and no return values") } } } else { f.Func.Shortname = name - name = nblank.Sym // filled in by typecheckfunc + name = ir.BlankNode.Sym // filled in by typecheckfunc } f.Func.Nname = newfuncnamel(p.pos(fun.Name), name, f.Func) @@ -542,7 +543,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node { if pragma, ok := fun.Pragma.(*Pragma); ok { f.Func.Pragma = pragma.Flag & FuncPragmas - if pragma.Flag&Systemstack != 0 && pragma.Flag&Nosplit != 0 { + if pragma.Flag&ir.Systemstack != 0 && pragma.Flag&ir.Nosplit != 0 { base.ErrorfAt(f.Pos, "go:nosplit and go:systemstack cannot be combined") } pragma.Flag &^= FuncPragmas @@ -550,22 +551,22 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node { } if fun.Recv == nil { - declare(f.Func.Nname, PFUNC) + declare(f.Func.Nname, ir.PFUNC) } p.funcBody(f, fun.Body) if fun.Body != nil { - if f.Func.Pragma&Noescape != 0 { + if f.Func.Pragma&ir.Noescape != 0 { base.ErrorfAt(f.Pos, "can only use //go:noescape with external func implementations") } } else { - if base.Flag.Complete || strings.HasPrefix(f.funcname(), "init.") { + if base.Flag.Complete || strings.HasPrefix(ir.FuncName(f), "init.") { // Linknamed functions are allowed to have no body. Hopefully // the linkname target has a body. See issue 23311. isLinknamed := false for _, n := range p.linknames { - if f.funcname() == n.local { + if ir.FuncName(f) == n.local { isLinknamed = true break } @@ -579,8 +580,8 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node { return f } -func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *Node { - n := p.nod(typ, OTFUNC, nil, nil) +func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *ir.Node { + n := p.nod(typ, ir.OTFUNC, nil, nil) if recv != nil { n.Left = p.param(recv, false, false) } @@ -589,8 +590,8 @@ func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *Node { return n } -func (p *noder) params(params []*syntax.Field, dddOk bool) []*Node { - nodes := make([]*Node, 0, len(params)) +func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Node { + nodes := make([]*ir.Node, 0, len(params)) for i, param := range params { p.setlineno(param) nodes = append(nodes, p.param(param, dddOk, i+1 == len(params))) @@ -598,17 +599,17 @@ func (p *noder) params(params []*syntax.Field, dddOk bool) []*Node { return nodes } -func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node { +func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Node { var name *types.Sym if param.Name != nil { name = p.name(param.Name) } typ := p.typeExpr(param.Type) - n := p.nodSym(param, ODCLFIELD, typ, name) + n := p.nodSym(param, ir.ODCLFIELD, typ, name) // rewrite ...T parameter - if typ.Op == ODDD { + if typ.Op == ir.ODDD { if !dddOk { // We mark these as syntax errors to get automatic elimination // of multiple such errors per line (see ErrorfAt in subr.go). @@ -620,7 +621,7 @@ func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node { p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value) } } - typ.Op = OTARRAY + typ.Op = ir.OTARRAY typ.Right = typ.Left typ.Left = nil n.SetIsDDD(true) @@ -632,22 +633,22 @@ func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node { return n } -func (p *noder) exprList(expr syntax.Expr) []*Node { +func (p *noder) exprList(expr syntax.Expr) []*ir.Node { if list, ok := expr.(*syntax.ListExpr); ok { return p.exprs(list.ElemList) } - return []*Node{p.expr(expr)} + return []*ir.Node{p.expr(expr)} } -func (p *noder) exprs(exprs []syntax.Expr) []*Node { - nodes := make([]*Node, 0, len(exprs)) +func (p *noder) exprs(exprs []syntax.Expr) []*ir.Node { + nodes := make([]*ir.Node, 0, len(exprs)) for _, expr := range exprs { nodes = append(nodes, p.expr(expr)) } return nodes } -func (p *noder) expr(expr syntax.Expr) *Node { +func (p *noder) expr(expr syntax.Expr) *ir.Node { p.setlineno(expr) switch expr := expr.(type) { case nil, *syntax.BadExpr: @@ -655,14 +656,14 @@ func (p *noder) expr(expr syntax.Expr) *Node { case *syntax.Name: return p.mkname(expr) case *syntax.BasicLit: - n := nodlit(p.basicLit(expr)) + n := ir.NewLiteral(p.basicLit(expr)) if expr.Kind == syntax.RuneLit { n.Type = types.UntypedRune } n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error return n case *syntax.CompositeLit: - n := p.nod(expr, OCOMPLIT, nil, nil) + n := p.nod(expr, ir.OCOMPLIT, nil, nil) if expr.Type != nil { n.Right = p.expr(expr.Type) } @@ -675,30 +676,30 @@ func (p *noder) expr(expr syntax.Expr) *Node { return n case *syntax.KeyValueExpr: // use position of expr.Key rather than of expr (which has position of ':') - return p.nod(expr.Key, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value))) + return p.nod(expr.Key, ir.OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value))) case *syntax.FuncLit: return p.funcLit(expr) case *syntax.ParenExpr: - return p.nod(expr, OPAREN, p.expr(expr.X), nil) + return p.nod(expr, ir.OPAREN, p.expr(expr.X), nil) case *syntax.SelectorExpr: // parser.new_dotname obj := p.expr(expr.X) - if obj.Op == OPACK { + if obj.Op == ir.OPACK { obj.Name.SetUsed(true) return importName(obj.Name.Pkg.Lookup(expr.Sel.Value)) } - n := nodSym(OXDOT, obj, p.name(expr.Sel)) + n := nodSym(ir.OXDOT, obj, p.name(expr.Sel)) n.Pos = p.pos(expr) // lineno may have been changed by p.expr(expr.X) return n case *syntax.IndexExpr: - return p.nod(expr, OINDEX, p.expr(expr.X), p.expr(expr.Index)) + return p.nod(expr, ir.OINDEX, p.expr(expr.X), p.expr(expr.Index)) case *syntax.SliceExpr: - op := OSLICE + op := ir.OSLICE if expr.Full { - op = OSLICE3 + op = ir.OSLICE3 } n := p.nod(expr, op, p.expr(expr.X), nil) - var index [3]*Node + var index [3]*ir.Node for i, x := range &expr.Index { if x != nil { index[i] = p.expr(x) @@ -707,7 +708,7 @@ func (p *noder) expr(expr syntax.Expr) *Node { n.SetSliceBounds(index[0], index[1], index[2]) return n case *syntax.AssertExpr: - return p.nod(expr, ODOTTYPE, p.expr(expr.X), p.typeExpr(expr.Type)) + return p.nod(expr, ir.ODOTTYPE, p.expr(expr.X), p.typeExpr(expr.Type)) case *syntax.Operation: if expr.Op == syntax.Add && expr.Y != nil { return p.sum(expr) @@ -718,23 +719,23 @@ func (p *noder) expr(expr syntax.Expr) *Node { } return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y)) case *syntax.CallExpr: - n := p.nod(expr, OCALL, p.expr(expr.Fun), nil) + n := p.nod(expr, ir.OCALL, p.expr(expr.Fun), nil) n.List.Set(p.exprs(expr.ArgList)) n.SetIsDDD(expr.HasDots) return n case *syntax.ArrayType: - var len *Node + var len *ir.Node if expr.Len != nil { len = p.expr(expr.Len) } else { - len = p.nod(expr, ODDD, nil, nil) + len = p.nod(expr, ir.ODDD, nil, nil) } - return p.nod(expr, OTARRAY, len, p.typeExpr(expr.Elem)) + return p.nod(expr, ir.OTARRAY, len, p.typeExpr(expr.Elem)) case *syntax.SliceType: - return p.nod(expr, OTARRAY, nil, p.typeExpr(expr.Elem)) + return p.nod(expr, ir.OTARRAY, nil, p.typeExpr(expr.Elem)) case *syntax.DotsType: - return p.nod(expr, ODDD, p.typeExpr(expr.Elem), nil) + return p.nod(expr, ir.ODDD, p.typeExpr(expr.Elem), nil) case *syntax.StructType: return p.structType(expr) case *syntax.InterfaceType: @@ -742,17 +743,17 @@ func (p *noder) expr(expr syntax.Expr) *Node { case *syntax.FuncType: return p.signature(nil, expr) case *syntax.MapType: - return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value)) + return p.nod(expr, ir.OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value)) case *syntax.ChanType: - n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil) + n := p.nod(expr, ir.OTCHAN, p.typeExpr(expr.Elem), nil) n.SetTChanDir(p.chanDir(expr.Dir)) return n case *syntax.TypeSwitchGuard: - n := p.nod(expr, OTYPESW, nil, p.expr(expr.X)) + n := p.nod(expr, ir.OTYPESW, nil, p.expr(expr.X)) if expr.Lhs != nil { n.Left = p.declName(expr.Lhs) - if n.Left.isBlank() { + if ir.IsBlank(n.Left) { base.Errorf("invalid variable name %v in type switch", n.Left) } } @@ -764,7 +765,7 @@ func (p *noder) expr(expr syntax.Expr) *Node { // sum efficiently handles very large summation expressions (such as // in issue #16394). In particular, it avoids left recursion and // collapses string literals. -func (p *noder) sum(x syntax.Expr) *Node { +func (p *noder) sum(x syntax.Expr) *ir.Node { // While we need to handle long sums with asymptotic // efficiency, the vast majority of sums are very small: ~95% // have only 2 or 3 operands, and ~99% of string literals are @@ -799,11 +800,11 @@ func (p *noder) sum(x syntax.Expr) *Node { // handle correctly. For now, we avoid these problems by // treating named string constants the same as non-constant // operands. - var nstr *Node + var nstr *ir.Node chunks := make([]string, 0, 1) n := p.expr(x) - if Isconst(n, constant.String) && n.Sym == nil { + if ir.IsConst(n, constant.String) && n.Sym == nil { nstr = n chunks = append(chunks, nstr.StringVal()) } @@ -812,7 +813,7 @@ func (p *noder) sum(x syntax.Expr) *Node { add := adds[i] r := p.expr(add.Y) - if Isconst(r, constant.String) && r.Sym == nil { + if ir.IsConst(r, constant.String) && r.Sym == nil { if nstr != nil { // Collapse r into nstr instead of adding to n. chunks = append(chunks, r.StringVal()) @@ -828,7 +829,7 @@ func (p *noder) sum(x syntax.Expr) *Node { nstr = nil chunks = chunks[:0] } - n = p.nod(add, OADD, n, r) + n = p.nod(add, ir.OADD, n, r) } if len(chunks) > 1 { nstr.SetVal(constant.MakeString(strings.Join(chunks, ""))) @@ -837,12 +838,12 @@ func (p *noder) sum(x syntax.Expr) *Node { return n } -func (p *noder) typeExpr(typ syntax.Expr) *Node { +func (p *noder) typeExpr(typ syntax.Expr) *ir.Node { // TODO(mdempsky): Be stricter? typecheck should handle errors anyway. return p.expr(typ) } -func (p *noder) typeExprOrNil(typ syntax.Expr) *Node { +func (p *noder) typeExprOrNil(typ syntax.Expr) *ir.Node { if typ != nil { return p.expr(typ) } @@ -861,15 +862,15 @@ func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir { panic("unhandled ChanDir") } -func (p *noder) structType(expr *syntax.StructType) *Node { - l := make([]*Node, 0, len(expr.FieldList)) +func (p *noder) structType(expr *syntax.StructType) *ir.Node { + l := make([]*ir.Node, 0, len(expr.FieldList)) for i, field := range expr.FieldList { p.setlineno(field) - var n *Node + var n *ir.Node if field.Name == nil { n = p.embedded(field.Type) } else { - n = p.nodSym(field, ODCLFIELD, p.typeExpr(field.Type), p.name(field.Name)) + n = p.nodSym(field, ir.ODCLFIELD, p.typeExpr(field.Type), p.name(field.Name)) } if i < len(expr.TagList) && expr.TagList[i] != nil { n.SetVal(p.basicLit(expr.TagList[i])) @@ -878,29 +879,29 @@ func (p *noder) structType(expr *syntax.StructType) *Node { } p.setlineno(expr) - n := p.nod(expr, OTSTRUCT, nil, nil) + n := p.nod(expr, ir.OTSTRUCT, nil, nil) n.List.Set(l) return n } -func (p *noder) interfaceType(expr *syntax.InterfaceType) *Node { - l := make([]*Node, 0, len(expr.MethodList)) +func (p *noder) interfaceType(expr *syntax.InterfaceType) *ir.Node { + l := make([]*ir.Node, 0, len(expr.MethodList)) for _, method := range expr.MethodList { p.setlineno(method) - var n *Node + var n *ir.Node if method.Name == nil { - n = p.nodSym(method, ODCLFIELD, importName(p.packname(method.Type)), nil) + n = p.nodSym(method, ir.ODCLFIELD, importName(p.packname(method.Type)), nil) } else { mname := p.name(method.Name) sig := p.typeExpr(method.Type) sig.Left = fakeRecv() - n = p.nodSym(method, ODCLFIELD, sig, mname) + n = p.nodSym(method, ir.ODCLFIELD, sig, mname) ifacedcl(n) } l = append(l, n) } - n := p.nod(expr, OTINTER, nil, nil) + n := p.nod(expr, ir.OTINTER, nil, nil) n.List.Set(l) return n } @@ -915,15 +916,15 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym { return name case *syntax.SelectorExpr: name := p.name(expr.X.(*syntax.Name)) - def := asNode(name.Def) + def := ir.AsNode(name.Def) if def == nil { base.Errorf("undefined: %v", name) return name } var pkg *types.Pkg - if def.Op != OPACK { + if def.Op != ir.OPACK { base.Errorf("%v is not a package", name) - pkg = localpkg + pkg = ir.LocalPkg } else { def.Name.SetUsed(true) pkg = def.Name.Pkg @@ -933,7 +934,7 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym { panic(fmt.Sprintf("unexpected packname: %#v", expr)) } -func (p *noder) embedded(typ syntax.Expr) *Node { +func (p *noder) embedded(typ syntax.Expr) *ir.Node { op, isStar := typ.(*syntax.Operation) if isStar { if op.Op != syntax.Mul || op.Y != nil { @@ -943,25 +944,25 @@ func (p *noder) embedded(typ syntax.Expr) *Node { } sym := p.packname(typ) - n := p.nodSym(typ, ODCLFIELD, importName(sym), lookup(sym.Name)) + n := p.nodSym(typ, ir.ODCLFIELD, importName(sym), lookup(sym.Name)) n.SetEmbedded(true) if isStar { - n.Left = p.nod(op, ODEREF, n.Left, nil) + n.Left = p.nod(op, ir.ODEREF, n.Left, nil) } return n } -func (p *noder) stmts(stmts []syntax.Stmt) []*Node { +func (p *noder) stmts(stmts []syntax.Stmt) []*ir.Node { return p.stmtsFall(stmts, false) } -func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []*Node { - var nodes []*Node +func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []*ir.Node { + var nodes []*ir.Node for i, stmt := range stmts { s := p.stmtFall(stmt, fallOK && i+1 == len(stmts)) if s == nil { - } else if s.Op == OBLOCK && s.Ninit.Len() == 0 { + } else if s.Op == ir.OBLOCK && s.Ninit.Len() == 0 { nodes = append(nodes, s.List.Slice()...) } else { nodes = append(nodes, s) @@ -970,11 +971,11 @@ func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []*Node { return nodes } -func (p *noder) stmt(stmt syntax.Stmt) *Node { +func (p *noder) stmt(stmt syntax.Stmt) *ir.Node { return p.stmtFall(stmt, false) } -func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node { +func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *ir.Node { p.setlineno(stmt) switch stmt := stmt.(type) { case *syntax.EmptyStmt: @@ -985,24 +986,24 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node { l := p.blockStmt(stmt) if len(l) == 0 { // TODO(mdempsky): Line number? - return nod(OEMPTY, nil, nil) + return ir.Nod(ir.OEMPTY, nil, nil) } return liststmt(l) case *syntax.ExprStmt: return p.wrapname(stmt, p.expr(stmt.X)) case *syntax.SendStmt: - return p.nod(stmt, OSEND, p.expr(stmt.Chan), p.expr(stmt.Value)) + return p.nod(stmt, ir.OSEND, p.expr(stmt.Chan), p.expr(stmt.Value)) case *syntax.DeclStmt: return liststmt(p.decls(stmt.DeclList)) case *syntax.AssignStmt: if stmt.Op != 0 && stmt.Op != syntax.Def { - n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs)) + n := p.nod(stmt, ir.OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs)) n.SetImplicit(stmt.Rhs == syntax.ImplicitOne) n.SetSubOp(p.binOp(stmt.Op)) return n } - n := p.nod(stmt, OAS, nil, nil) // assume common case + n := p.nod(stmt, ir.OAS, nil, nil) // assume common case rhs := p.exprList(stmt.Rhs) lhs := p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def) @@ -1012,26 +1013,26 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node { n.Left = lhs[0] n.Right = rhs[0] } else { - n.Op = OAS2 + n.Op = ir.OAS2 n.List.Set(lhs) n.Rlist.Set(rhs) } return n case *syntax.BranchStmt: - var op Op + var op ir.Op switch stmt.Tok { case syntax.Break: - op = OBREAK + op = ir.OBREAK case syntax.Continue: - op = OCONTINUE + op = ir.OCONTINUE case syntax.Fallthrough: if !fallOK { base.Errorf("fallthrough statement out of place") } - op = OFALL + op = ir.OFALL case syntax.Goto: - op = OGOTO + op = ir.OGOTO default: panic("unhandled BranchStmt") } @@ -1041,32 +1042,32 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node { } return n case *syntax.CallStmt: - var op Op + var op ir.Op switch stmt.Tok { case syntax.Defer: - op = ODEFER + op = ir.ODEFER case syntax.Go: - op = OGO + op = ir.OGO default: panic("unhandled CallStmt") } return p.nod(stmt, op, p.expr(stmt.Call), nil) case *syntax.ReturnStmt: - var results []*Node + var results []*ir.Node if stmt.Results != nil { results = p.exprList(stmt.Results) } - n := p.nod(stmt, ORETURN, nil, nil) + n := p.nod(stmt, ir.ORETURN, nil, nil) n.List.Set(results) if n.List.Len() == 0 && Curfn != nil { for _, ln := range Curfn.Func.Dcl { - if ln.Class() == PPARAM { + if ln.Class() == ir.PPARAM { continue } - if ln.Class() != PPARAMOUT { + if ln.Class() != ir.PPARAMOUT { break } - if asNode(ln.Sym.Def) != ln { + if ir.AsNode(ln.Sym.Def) != ln { base.Errorf("%s is shadowed during return", ln.Sym.Name) } } @@ -1084,7 +1085,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node { panic("unhandled Stmt") } -func (p *noder) assignList(expr syntax.Expr, defn *Node, colas bool) []*Node { +func (p *noder) assignList(expr syntax.Expr, defn *ir.Node, colas bool) []*ir.Node { if !colas { return p.exprList(expr) } @@ -1098,13 +1099,13 @@ func (p *noder) assignList(expr syntax.Expr, defn *Node, colas bool) []*Node { exprs = []syntax.Expr{expr} } - res := make([]*Node, len(exprs)) + res := make([]*ir.Node, len(exprs)) seen := make(map[*types.Sym]bool, len(exprs)) newOrErr := false for i, expr := range exprs { p.setlineno(expr) - res[i] = nblank + res[i] = ir.BlankNode name, ok := expr.(*syntax.Name) if !ok { @@ -1131,10 +1132,10 @@ func (p *noder) assignList(expr syntax.Expr, defn *Node, colas bool) []*Node { } newOrErr = true - n := newname(sym) + n := NewName(sym) declare(n, dclcontext) n.Name.Defn = defn - defn.Ninit.Append(nod(ODCL, n, nil)) + defn.Ninit.Append(ir.Nod(ir.ODCL, n, nil)) res[i] = n } @@ -1144,16 +1145,16 @@ func (p *noder) assignList(expr syntax.Expr, defn *Node, colas bool) []*Node { return res } -func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node { +func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*ir.Node { p.openScope(stmt.Pos()) nodes := p.stmts(stmt.List) p.closeScope(stmt.Rbrace) return nodes } -func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { +func (p *noder) ifStmt(stmt *syntax.IfStmt) *ir.Node { p.openScope(stmt.Pos()) - n := p.nod(stmt, OIF, nil, nil) + n := p.nod(stmt, ir.OIF, nil, nil) if stmt.Init != nil { n.Ninit.Set1(p.stmt(stmt.Init)) } @@ -1163,7 +1164,7 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { n.Nbody.Set(p.blockStmt(stmt.Then)) if stmt.Else != nil { e := p.stmt(stmt.Else) - if e.Op == OBLOCK && e.Ninit.Len() == 0 { + if e.Op == ir.OBLOCK && e.Ninit.Len() == 0 { n.Rlist.Set(e.List.Slice()) } else { n.Rlist.Set1(e) @@ -1173,20 +1174,20 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { return n } -func (p *noder) forStmt(stmt *syntax.ForStmt) *Node { +func (p *noder) forStmt(stmt *syntax.ForStmt) *ir.Node { p.openScope(stmt.Pos()) - var n *Node + var n *ir.Node if r, ok := stmt.Init.(*syntax.RangeClause); ok { if stmt.Cond != nil || stmt.Post != nil { panic("unexpected RangeClause") } - n = p.nod(r, ORANGE, nil, p.expr(r.X)) + n = p.nod(r, ir.ORANGE, nil, p.expr(r.X)) if r.Lhs != nil { n.List.Set(p.assignList(r.Lhs, n, r.Def)) } } else { - n = p.nod(stmt, OFOR, nil, nil) + n = p.nod(stmt, ir.OFOR, nil, nil) if stmt.Init != nil { n.Ninit.Set1(p.stmt(stmt.Init)) } @@ -1202,9 +1203,9 @@ func (p *noder) forStmt(stmt *syntax.ForStmt) *Node { return n } -func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { +func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *ir.Node { p.openScope(stmt.Pos()) - n := p.nod(stmt, OSWITCH, nil, nil) + n := p.nod(stmt, ir.OSWITCH, nil, nil) if stmt.Init != nil { n.Ninit.Set1(p.stmt(stmt.Init)) } @@ -1213,7 +1214,7 @@ func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { } tswitch := n.Left - if tswitch != nil && tswitch.Op != OTYPESW { + if tswitch != nil && tswitch.Op != ir.OTYPESW { tswitch = nil } n.List.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)) @@ -1222,8 +1223,8 @@ func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { return n } -func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace syntax.Pos) []*Node { - nodes := make([]*Node, 0, len(clauses)) +func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.Node, rbrace syntax.Pos) []*ir.Node { + nodes := make([]*ir.Node, 0, len(clauses)) for i, clause := range clauses { p.setlineno(clause) if i > 0 { @@ -1231,12 +1232,12 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace } p.openScope(clause.Pos()) - n := p.nod(clause, OCASE, nil, nil) + n := p.nod(clause, ir.OCASE, nil, nil) if clause.Cases != nil { n.List.Set(p.exprList(clause.Cases)) } if tswitch != nil && tswitch.Left != nil { - nn := newname(tswitch.Left.Sym) + nn := NewName(tswitch.Left.Sym) declare(nn, dclcontext) n.Rlist.Set1(nn) // keep track of the instances for reporting unused @@ -1255,7 +1256,7 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace } n.Nbody.Set(p.stmtsFall(body, true)) - if l := n.Nbody.Len(); l > 0 && n.Nbody.Index(l-1).Op == OFALL { + if l := n.Nbody.Len(); l > 0 && n.Nbody.Index(l-1).Op == ir.OFALL { if tswitch != nil { base.Errorf("cannot fallthrough in type switch") } @@ -1272,14 +1273,14 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace return nodes } -func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node { - n := p.nod(stmt, OSELECT, nil, nil) +func (p *noder) selectStmt(stmt *syntax.SelectStmt) *ir.Node { + n := p.nod(stmt, ir.OSELECT, nil, nil) n.List.Set(p.commClauses(stmt.Body, stmt.Rbrace)) return n } -func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*Node { - nodes := make([]*Node, 0, len(clauses)) +func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.Node { + nodes := make([]*ir.Node, 0, len(clauses)) for i, clause := range clauses { p.setlineno(clause) if i > 0 { @@ -1287,7 +1288,7 @@ func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []* } p.openScope(clause.Pos()) - n := p.nod(clause, OCASE, nil, nil) + n := p.nod(clause, ir.OCASE, nil, nil) if clause.Comm != nil { n.List.Set1(p.stmt(clause.Comm)) } @@ -1300,18 +1301,18 @@ func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []* return nodes } -func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) *Node { - lhs := p.nodSym(label, OLABEL, nil, p.name(label.Label)) +func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) *ir.Node { + lhs := p.nodSym(label, ir.OLABEL, nil, p.name(label.Label)) - var ls *Node + var ls *ir.Node if label.Stmt != nil { // TODO(mdempsky): Should always be present. ls = p.stmtFall(label.Stmt, fallOK) } lhs.Name.Defn = ls - l := []*Node{lhs} + l := []*ir.Node{lhs} if ls != nil { - if ls.Op == OBLOCK && ls.Ninit.Len() == 0 { + if ls.Op == ir.OBLOCK && ls.Ninit.Len() == 0 { l = append(l, ls.List.Slice()...) } else { l = append(l, ls) @@ -1320,50 +1321,50 @@ func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) *Node { return liststmt(l) } -var unOps = [...]Op{ - syntax.Recv: ORECV, - syntax.Mul: ODEREF, - syntax.And: OADDR, +var unOps = [...]ir.Op{ + syntax.Recv: ir.ORECV, + syntax.Mul: ir.ODEREF, + syntax.And: ir.OADDR, - syntax.Not: ONOT, - syntax.Xor: OBITNOT, - syntax.Add: OPLUS, - syntax.Sub: ONEG, + syntax.Not: ir.ONOT, + syntax.Xor: ir.OBITNOT, + syntax.Add: ir.OPLUS, + syntax.Sub: ir.ONEG, } -func (p *noder) unOp(op syntax.Operator) Op { +func (p *noder) unOp(op syntax.Operator) ir.Op { if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 { panic("invalid Operator") } return unOps[op] } -var binOps = [...]Op{ - syntax.OrOr: OOROR, - syntax.AndAnd: OANDAND, +var binOps = [...]ir.Op{ + syntax.OrOr: ir.OOROR, + syntax.AndAnd: ir.OANDAND, - syntax.Eql: OEQ, - syntax.Neq: ONE, - syntax.Lss: OLT, - syntax.Leq: OLE, - syntax.Gtr: OGT, - syntax.Geq: OGE, + syntax.Eql: ir.OEQ, + syntax.Neq: ir.ONE, + syntax.Lss: ir.OLT, + syntax.Leq: ir.OLE, + syntax.Gtr: ir.OGT, + syntax.Geq: ir.OGE, - syntax.Add: OADD, - syntax.Sub: OSUB, - syntax.Or: OOR, - syntax.Xor: OXOR, + syntax.Add: ir.OADD, + syntax.Sub: ir.OSUB, + syntax.Or: ir.OOR, + syntax.Xor: ir.OXOR, - syntax.Mul: OMUL, - syntax.Div: ODIV, - syntax.Rem: OMOD, - syntax.And: OAND, - syntax.AndNot: OANDNOT, - syntax.Shl: OLSH, - syntax.Shr: ORSH, + syntax.Mul: ir.OMUL, + syntax.Div: ir.ODIV, + syntax.Rem: ir.OMOD, + syntax.And: ir.OAND, + syntax.AndNot: ir.OANDNOT, + syntax.Shl: ir.OLSH, + syntax.Shr: ir.ORSH, } -func (p *noder) binOp(op syntax.Operator) Op { +func (p *noder) binOp(op syntax.Operator) ir.Op { if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 { panic("invalid Operator") } @@ -1374,7 +1375,7 @@ func (p *noder) binOp(op syntax.Operator) Op { // literal is not compatible with the current language version. func checkLangCompat(lit *syntax.BasicLit) { s := lit.Value - if len(s) <= 2 || langSupported(1, 13, localpkg) { + if len(s) <= 2 || langSupported(1, 13, ir.LocalPkg) { return } // len(s) > 2 @@ -1442,32 +1443,32 @@ func (p *noder) name(name *syntax.Name) *types.Sym { return lookup(name.Value) } -func (p *noder) mkname(name *syntax.Name) *Node { +func (p *noder) mkname(name *syntax.Name) *ir.Node { // TODO(mdempsky): Set line number? return mkname(p.name(name)) } -func (p *noder) wrapname(n syntax.Node, x *Node) *Node { +func (p *noder) wrapname(n syntax.Node, x *ir.Node) *ir.Node { // These nodes do not carry line numbers. // Introduce a wrapper node to give them the correct line. switch x.Op { - case OTYPE, OLITERAL: + case ir.OTYPE, ir.OLITERAL: if x.Sym == nil { break } fallthrough - case ONAME, ONONAME, OPACK: - x = p.nod(n, OPAREN, x, nil) + case ir.ONAME, ir.ONONAME, ir.OPACK: + x = p.nod(n, ir.OPAREN, x, nil) x.SetImplicit(true) } return x } -func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node { - return nodl(p.pos(orig), op, left, right) +func (p *noder) nod(orig syntax.Node, op ir.Op, left, right *ir.Node) *ir.Node { + return ir.NodAt(p.pos(orig), op, left, right) } -func (p *noder) nodSym(orig syntax.Node, op Op, left *Node, sym *types.Sym) *Node { +func (p *noder) nodSym(orig syntax.Node, op ir.Op, left *ir.Node, sym *types.Sym) *ir.Node { n := nodSym(op, left, sym) n.Pos = p.pos(orig) return n @@ -1508,13 +1509,13 @@ var allowedStdPragmas = map[string]bool{ // *Pragma is the value stored in a syntax.Pragma during parsing. type Pragma struct { - Flag PragmaFlag // collected bits - Pos []PragmaPos // position of each individual flag + Flag ir.PragmaFlag // collected bits + Pos []PragmaPos // position of each individual flag Embeds []PragmaEmbed } type PragmaPos struct { - Flag PragmaFlag + Flag ir.PragmaFlag Pos syntax.Pos } @@ -1631,7 +1632,7 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P verb = verb[:i] } flag := pragmaFlag(verb) - const runtimePragmas = Systemstack | Nowritebarrier | Nowritebarrierrec | Yeswritebarrierrec + const runtimePragmas = ir.Systemstack | ir.Nowritebarrier | ir.Nowritebarrierrec | ir.Yeswritebarrierrec if !base.Flag.CompilingRuntime && flag&runtimePragmas != 0 { p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)}) } @@ -1667,7 +1668,7 @@ func safeArg(name string) bool { return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf } -func mkname(sym *types.Sym) *Node { +func mkname(sym *types.Sym) *ir.Node { n := oldname(sym) if n.Name != nil && n.Name.Pack != nil { n.Name.Pack.Name.SetUsed(true) diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 6c659c91c77..2961dbf636a 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/bio" "cmd/internal/obj" @@ -83,7 +84,7 @@ func printObjHeader(bout *bio.Writer) { if base.Flag.BuildID != "" { fmt.Fprintf(bout, "build id %q\n", base.Flag.BuildID) } - if localpkg.Name == "main" { + if ir.LocalPkg.Name == "main" { fmt.Fprintf(bout, "main\n") } fmt.Fprintf(bout, "\n") // header ends with blank line @@ -141,7 +142,7 @@ func dumpdata() { for { for i := xtops; i < len(xtop); i++ { n := xtop[i] - if n.Op == ODCLFUNC { + if n.Op == ir.ODCLFUNC { funccompile(n) } } @@ -199,16 +200,16 @@ func dumpLinkerObj(bout *bio.Writer) { } func addptabs() { - if !base.Ctxt.Flag_dynlink || localpkg.Name != "main" { + if !base.Ctxt.Flag_dynlink || ir.LocalPkg.Name != "main" { return } for _, exportn := range exportlist { s := exportn.Sym - n := asNode(s.Def) + n := ir.AsNode(s.Def) if n == nil { continue } - if n.Op != ONAME { + if n.Op != ir.ONAME { continue } if !types.IsExported(s.Name) { @@ -217,37 +218,37 @@ func addptabs() { if s.Pkg.Name != "main" { continue } - if n.Type.Etype == TFUNC && n.Class() == PFUNC { + if n.Type.Etype == types.TFUNC && n.Class() == ir.PFUNC { // function - ptabs = append(ptabs, ptabEntry{s: s, t: asNode(s.Def).Type}) + ptabs = append(ptabs, ptabEntry{s: s, t: ir.AsNode(s.Def).Type}) } else { // variable - ptabs = append(ptabs, ptabEntry{s: s, t: types.NewPtr(asNode(s.Def).Type)}) + ptabs = append(ptabs, ptabEntry{s: s, t: types.NewPtr(ir.AsNode(s.Def).Type)}) } } } -func dumpGlobal(n *Node) { +func dumpGlobal(n *ir.Node) { if n.Type == nil { base.Fatalf("external %v nil type\n", n) } - if n.Class() == PFUNC { + if n.Class() == ir.PFUNC { return } - if n.Sym.Pkg != localpkg { + if n.Sym.Pkg != ir.LocalPkg { return } dowidth(n.Type) ggloblnod(n) } -func dumpGlobalConst(n *Node) { +func dumpGlobalConst(n *ir.Node) { // only export typed constants t := n.Type if t == nil { return } - if n.Sym.Pkg != localpkg { + if n.Sym.Pkg != ir.LocalPkg { return } // only export integer constants for now @@ -257,21 +258,21 @@ func dumpGlobalConst(n *Node) { v := n.Val() if t.IsUntyped() { // Export untyped integers as int (if they fit). - t = types.Types[TINT] + t = types.Types[types.TINT] if doesoverflow(v, t) { return } } - base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym.Name, typesymname(t), int64Val(t, v)) + base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym.Name, typesymname(t), ir.Int64Val(t, v)) } func dumpglobls() { // add globals for _, n := range externdcl { switch n.Op { - case ONAME: + case ir.ONAME: dumpGlobal(n) - case OLITERAL: + case ir.OLITERAL: dumpGlobalConst(n) } } @@ -474,12 +475,12 @@ func fileStringSym(pos src.XPos, file string, readonly bool, hash []byte) (*obj. var slicedataGen int -func slicedata(pos src.XPos, s string) *Node { +func slicedata(pos src.XPos, s string) *ir.Node { slicedataGen++ symname := fmt.Sprintf(".gobytes.%d", slicedataGen) - sym := localpkg.Lookup(symname) - symnode := newname(sym) - sym.Def = asTypesNode(symnode) + sym := ir.LocalPkg.Lookup(symname) + symnode := NewName(sym) + sym.Def = ir.AsTypesNode(symnode) lsym := sym.Linksym() off := dstringdata(lsym, 0, s, pos, "slice") @@ -488,8 +489,8 @@ func slicedata(pos src.XPos, s string) *Node { return symnode } -func slicebytes(nam *Node, s string) { - if nam.Op != ONAME { +func slicebytes(nam *ir.Node, s string) { + if nam.Op != ir.ONAME { base.Fatalf("slicebytes %v", nam) } slicesym(nam, slicedata(nam.Pos, s), int64(len(s))) @@ -529,10 +530,10 @@ func dsymptrWeakOff(s *obj.LSym, off int, x *obj.LSym) int { // slicesym writes a static slice symbol {&arr, lencap, lencap} to n. // arr must be an ONAME. slicesym does not modify n. -func slicesym(n, arr *Node, lencap int64) { +func slicesym(n, arr *ir.Node, lencap int64) { s := n.Sym.Linksym() off := n.Xoffset - if arr.Op != ONAME { + if arr.Op != ir.ONAME { base.Fatalf("slicesym non-name arr %v", arr) } s.WriteAddr(base.Ctxt, off, Widthptr, arr.Sym.Linksym(), arr.Xoffset) @@ -542,14 +543,14 @@ func slicesym(n, arr *Node, lencap int64) { // addrsym writes the static address of a to n. a must be an ONAME. // Neither n nor a is modified. -func addrsym(n, a *Node) { - if n.Op != ONAME { +func addrsym(n, a *ir.Node) { + if n.Op != ir.ONAME { base.Fatalf("addrsym n op %v", n.Op) } if n.Sym == nil { base.Fatalf("addrsym nil n sym") } - if a.Op != ONAME { + if a.Op != ir.ONAME { base.Fatalf("addrsym a op %v", a.Op) } s := n.Sym.Linksym() @@ -558,14 +559,14 @@ func addrsym(n, a *Node) { // pfuncsym writes the static address of f to n. f must be a global function. // Neither n nor f is modified. -func pfuncsym(n, f *Node) { - if n.Op != ONAME { +func pfuncsym(n, f *ir.Node) { + if n.Op != ir.ONAME { base.Fatalf("pfuncsym n op %v", n.Op) } if n.Sym == nil { base.Fatalf("pfuncsym nil n sym") } - if f.Class() != PFUNC { + if f.Class() != ir.PFUNC { base.Fatalf("pfuncsym class not PFUNC %d", f.Class()) } s := n.Sym.Linksym() @@ -574,8 +575,8 @@ func pfuncsym(n, f *Node) { // litsym writes the static literal c to n. // Neither n nor c is modified. -func litsym(n, c *Node, wid int) { - if n.Op != ONAME { +func litsym(n, c *ir.Node, wid int) { + if n.Op != ir.ONAME { base.Fatalf("litsym n op %v", n.Op) } if n.Sym == nil { @@ -584,10 +585,10 @@ func litsym(n, c *Node, wid int) { if !types.Identical(n.Type, c.Type) { base.Fatalf("litsym: type mismatch: %v has type %v, but %v has type %v", n, n.Type, c, c.Type) } - if c.Op == ONIL { + if c.Op == ir.ONIL { return } - if c.Op != OLITERAL { + if c.Op != ir.OLITERAL { base.Fatalf("litsym c op %v", c.Op) } s := n.Sym.Linksym() @@ -597,14 +598,14 @@ func litsym(n, c *Node, wid int) { s.WriteInt(base.Ctxt, n.Xoffset, wid, i) case constant.Int: - s.WriteInt(base.Ctxt, n.Xoffset, wid, int64Val(n.Type, u)) + s.WriteInt(base.Ctxt, n.Xoffset, wid, ir.Int64Val(n.Type, u)) case constant.Float: f, _ := constant.Float64Val(u) switch n.Type.Etype { - case TFLOAT32: + case types.TFLOAT32: s.WriteFloat32(base.Ctxt, n.Xoffset, float32(f)) - case TFLOAT64: + case types.TFLOAT64: s.WriteFloat64(base.Ctxt, n.Xoffset, f) } @@ -612,10 +613,10 @@ func litsym(n, c *Node, wid int) { re, _ := constant.Float64Val(constant.Real(u)) im, _ := constant.Float64Val(constant.Imag(u)) switch n.Type.Etype { - case TCOMPLEX64: + case types.TCOMPLEX64: s.WriteFloat32(base.Ctxt, n.Xoffset, float32(re)) s.WriteFloat32(base.Ctxt, n.Xoffset+4, float32(im)) - case TCOMPLEX128: + case types.TCOMPLEX128: s.WriteFloat64(base.Ctxt, n.Xoffset, re) s.WriteFloat64(base.Ctxt, n.Xoffset+8, im) } diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 3b0f3166962..25bdbd5a414 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/src" "fmt" @@ -43,27 +44,27 @@ import ( // Order holds state during the ordering process. type Order struct { - out []*Node // list of generated statements - temp []*Node // stack of temporary variables - free map[string][]*Node // free list of unused temporaries, by type.LongString(). + out []*ir.Node // list of generated statements + temp []*ir.Node // stack of temporary variables + free map[string][]*ir.Node // free list of unused temporaries, by type.LongString(). } // Order rewrites fn.Nbody to apply the ordering constraints // described in the comment at the top of the file. -func order(fn *Node) { +func order(fn *ir.Node) { if base.Flag.W > 1 { s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym) - dumplist(s, fn.Nbody) + ir.DumpList(s, fn.Nbody) } - orderBlock(&fn.Nbody, map[string][]*Node{}) + orderBlock(&fn.Nbody, map[string][]*ir.Node{}) } // newTemp allocates a new temporary with the given type, // pushes it onto the temp stack, and returns it. // If clear is true, newTemp emits code to zero the temporary. -func (o *Order) newTemp(t *types.Type, clear bool) *Node { - var v *Node +func (o *Order) newTemp(t *types.Type, clear bool) *ir.Node { + var v *ir.Node // Note: LongString is close to the type equality we want, // but not exactly. We still need to double-check with types.Identical. key := t.LongString() @@ -81,7 +82,7 @@ func (o *Order) newTemp(t *types.Type, clear bool) *Node { v = temp(t) } if clear { - a := nod(OAS, v, nil) + a := ir.Nod(ir.OAS, v, nil) a = typecheck(a, ctxStmt) o.out = append(o.out, a) } @@ -102,9 +103,9 @@ func (o *Order) newTemp(t *types.Type, clear bool) *Node { // (The other candidate would be map access, but map access // returns a pointer to the result data instead of taking a pointer // to be filled in.) -func (o *Order) copyExpr(n *Node, t *types.Type, clear bool) *Node { +func (o *Order) copyExpr(n *ir.Node, t *types.Type, clear bool) *ir.Node { v := o.newTemp(t, clear) - a := nod(OAS, v, n) + a := ir.Nod(ir.OAS, v, n) a = typecheck(a, ctxStmt) o.out = append(o.out, a) return v @@ -114,20 +115,20 @@ func (o *Order) copyExpr(n *Node, t *types.Type, clear bool) *Node { // The definition of cheap is that n is a variable or constant. // If not, cheapExpr allocates a new tmp, emits tmp = n, // and then returns tmp. -func (o *Order) cheapExpr(n *Node) *Node { +func (o *Order) cheapExpr(n *ir.Node) *ir.Node { if n == nil { return nil } switch n.Op { - case ONAME, OLITERAL, ONIL: + case ir.ONAME, ir.OLITERAL, ir.ONIL: return n - case OLEN, OCAP: + case ir.OLEN, ir.OCAP: l := o.cheapExpr(n.Left) if l == n.Left { return n } - a := n.sepcopy() + a := ir.SepCopy(n) a.Left = l return typecheck(a, ctxExpr) } @@ -142,31 +143,31 @@ func (o *Order) cheapExpr(n *Node) *Node { // as assigning to the original n. // // The intended use is to apply to x when rewriting x += y into x = x + y. -func (o *Order) safeExpr(n *Node) *Node { +func (o *Order) safeExpr(n *ir.Node) *ir.Node { switch n.Op { - case ONAME, OLITERAL, ONIL: + case ir.ONAME, ir.OLITERAL, ir.ONIL: return n - case ODOT, OLEN, OCAP: + case ir.ODOT, ir.OLEN, ir.OCAP: l := o.safeExpr(n.Left) if l == n.Left { return n } - a := n.sepcopy() + a := ir.SepCopy(n) a.Left = l return typecheck(a, ctxExpr) - case ODOTPTR, ODEREF: + case ir.ODOTPTR, ir.ODEREF: l := o.cheapExpr(n.Left) if l == n.Left { return n } - a := n.sepcopy() + a := ir.SepCopy(n) a.Left = l return typecheck(a, ctxExpr) - case OINDEX, OINDEXMAP: - var l *Node + case ir.OINDEX, ir.OINDEXMAP: + var l *ir.Node if n.Left.Type.IsArray() { l = o.safeExpr(n.Left) } else { @@ -176,7 +177,7 @@ func (o *Order) safeExpr(n *Node) *Node { if l == n.Left && r == n.Right { return n } - a := n.sepcopy() + a := ir.SepCopy(n) a.Left = l a.Right = r return typecheck(a, ctxExpr) @@ -193,8 +194,8 @@ func (o *Order) safeExpr(n *Node) *Node { // of ordinary stack variables, those are not 'isaddrokay'. Temporaries are okay, // because we emit explicit VARKILL instructions marking the end of those // temporaries' lifetimes. -func isaddrokay(n *Node) bool { - return islvalue(n) && (n.Op != ONAME || n.Class() == PEXTERN || n.IsAutoTmp()) +func isaddrokay(n *ir.Node) bool { + return islvalue(n) && (n.Op != ir.ONAME || n.Class() == ir.PEXTERN || n.IsAutoTmp()) } // addrTemp ensures that n is okay to pass by address to runtime routines. @@ -202,8 +203,8 @@ func isaddrokay(n *Node) bool { // tmp = n, and then returns tmp. // The result of addrTemp MUST be assigned back to n, e.g. // n.Left = o.addrTemp(n.Left) -func (o *Order) addrTemp(n *Node) *Node { - if n.Op == OLITERAL || n.Op == ONIL { +func (o *Order) addrTemp(n *ir.Node) *ir.Node { + if n.Op == ir.OLITERAL || n.Op == ir.ONIL { // TODO: expand this to all static composite literal nodes? n = defaultlit(n, nil) dowidth(n.Type) @@ -224,7 +225,7 @@ func (o *Order) addrTemp(n *Node) *Node { // mapKeyTemp prepares n to be a key in a map runtime call and returns n. // It should only be used for map runtime calls which have *_fast* versions. -func (o *Order) mapKeyTemp(t *types.Type, n *Node) *Node { +func (o *Order) mapKeyTemp(t *types.Type, n *ir.Node) *ir.Node { // Most map calls need to take the address of the key. // Exception: map*_fast* calls. See golang.org/issue/19015. if mapfast(t) == mapslow { @@ -247,21 +248,21 @@ func (o *Order) mapKeyTemp(t *types.Type, n *Node) *Node { // It would be nice to handle these generally, but because // []byte keys are not allowed in maps, the use of string(k) // comes up in important cases in practice. See issue 3512. -func mapKeyReplaceStrConv(n *Node) bool { +func mapKeyReplaceStrConv(n *ir.Node) bool { var replaced bool switch n.Op { - case OBYTES2STR: - n.Op = OBYTES2STRTMP + case ir.OBYTES2STR: + n.Op = ir.OBYTES2STRTMP replaced = true - case OSTRUCTLIT: + case ir.OSTRUCTLIT: for _, elem := range n.List.Slice() { if mapKeyReplaceStrConv(elem.Left) { replaced = true } } - case OARRAYLIT: + case ir.OARRAYLIT: for _, elem := range n.List.Slice() { - if elem.Op == OKEY { + if elem.Op == ir.OKEY { elem = elem.Right } if mapKeyReplaceStrConv(elem) { @@ -292,11 +293,11 @@ func (o *Order) popTemp(mark ordermarker) { // cleanTempNoPop emits VARKILL instructions to *out // for each temporary above the mark on the temporary stack. // It does not pop the temporaries from the stack. -func (o *Order) cleanTempNoPop(mark ordermarker) []*Node { - var out []*Node +func (o *Order) cleanTempNoPop(mark ordermarker) []*ir.Node { + var out []*ir.Node for i := len(o.temp) - 1; i >= int(mark); i-- { n := o.temp[i] - kill := nod(OVARKILL, n, nil) + kill := ir.Nod(ir.OVARKILL, n, nil) kill = typecheck(kill, ctxStmt) out = append(out, kill) } @@ -311,7 +312,7 @@ func (o *Order) cleanTemp(top ordermarker) { } // stmtList orders each of the statements in the list. -func (o *Order) stmtList(l Nodes) { +func (o *Order) stmtList(l ir.Nodes) { s := l.Slice() for i := range s { orderMakeSliceCopy(s[i:]) @@ -323,7 +324,7 @@ func (o *Order) stmtList(l Nodes) { // m = OMAKESLICE([]T, x); OCOPY(m, s) // and rewrites it to: // m = OMAKESLICECOPY([]T, x, s); nil -func orderMakeSliceCopy(s []*Node) { +func orderMakeSliceCopy(s []*ir.Node) { if base.Flag.N != 0 || instrumenting { return } @@ -335,17 +336,17 @@ func orderMakeSliceCopy(s []*Node) { asn := s[0] copyn := s[1] - if asn == nil || asn.Op != OAS { + if asn == nil || asn.Op != ir.OAS { return } - if asn.Left.Op != ONAME { + if asn.Left.Op != ir.ONAME { return } - if asn.Left.isBlank() { + if ir.IsBlank(asn.Left) { return } maken := asn.Right - if maken == nil || maken.Op != OMAKESLICE { + if maken == nil || maken.Op != ir.OMAKESLICE { return } if maken.Esc == EscNone { @@ -354,16 +355,16 @@ func orderMakeSliceCopy(s []*Node) { if maken.Left == nil || maken.Right != nil { return } - if copyn.Op != OCOPY { + if copyn.Op != ir.OCOPY { return } - if copyn.Left.Op != ONAME { + if copyn.Left.Op != ir.ONAME { return } if asn.Left.Sym != copyn.Left.Sym { return } - if copyn.Right.Op != ONAME { + if copyn.Right.Op != ir.ONAME { return } @@ -371,10 +372,10 @@ func orderMakeSliceCopy(s []*Node) { return } - maken.Op = OMAKESLICECOPY + maken.Op = ir.OMAKESLICECOPY maken.Right = copyn.Right // Set bounded when m = OMAKESLICE([]T, len(s)); OCOPY(m, s) - maken.SetBounded(maken.Left.Op == OLEN && samesafeexpr(maken.Left.Left, copyn.Right)) + maken.SetBounded(maken.Left.Op == ir.OLEN && samesafeexpr(maken.Left.Left, copyn.Right)) maken = typecheck(maken, ctxExpr) @@ -391,12 +392,12 @@ func (o *Order) edge() { // Create a new uint8 counter to be allocated in section // __libfuzzer_extra_counters. - counter := staticname(types.Types[TUINT8]) + counter := staticname(types.Types[types.TUINT8]) counter.Name.SetLibfuzzerExtraCounter(true) // counter += 1 - incr := nod(OASOP, counter, nodintconst(1)) - incr.SetSubOp(OADD) + incr := ir.Nod(ir.OASOP, counter, nodintconst(1)) + incr.SetSubOp(ir.OADD) incr = typecheck(incr, ctxStmt) o.out = append(o.out, incr) @@ -405,7 +406,7 @@ func (o *Order) edge() { // orderBlock orders the block of statements in n into a new slice, // and then replaces the old slice in n with the new slice. // free is a map that can be used to obtain temporary variables by type. -func orderBlock(n *Nodes, free map[string][]*Node) { +func orderBlock(n *ir.Nodes, free map[string][]*ir.Node) { var order Order order.free = free mark := order.markTemp() @@ -419,7 +420,7 @@ func orderBlock(n *Nodes, free map[string][]*Node) { // leaves them as the init list of the final *np. // The result of exprInPlace MUST be assigned back to n, e.g. // n.Left = o.exprInPlace(n.Left) -func (o *Order) exprInPlace(n *Node) *Node { +func (o *Order) exprInPlace(n *ir.Node) *ir.Node { var order Order order.free = o.free n = order.expr(n, nil) @@ -436,7 +437,7 @@ func (o *Order) exprInPlace(n *Node) *Node { // The result of orderStmtInPlace MUST be assigned back to n, e.g. // n.Left = orderStmtInPlace(n.Left) // free is a map that can be used to obtain temporary variables by type. -func orderStmtInPlace(n *Node, free map[string][]*Node) *Node { +func orderStmtInPlace(n *ir.Node, free map[string][]*ir.Node) *ir.Node { var order Order order.free = free mark := order.markTemp() @@ -446,8 +447,8 @@ func orderStmtInPlace(n *Node, free map[string][]*Node) *Node { } // init moves n's init list to o.out. -func (o *Order) init(n *Node) { - if n.mayBeShared() { +func (o *Order) init(n *ir.Node) { + if ir.MayBeShared(n) { // For concurrency safety, don't mutate potentially shared nodes. // First, ensure that no work is required here. if n.Ninit.Len() > 0 { @@ -461,14 +462,14 @@ func (o *Order) init(n *Node) { // call orders the call expression n. // n.Op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY. -func (o *Order) call(n *Node) { +func (o *Order) call(n *ir.Node) { if n.Ninit.Len() > 0 { // Caller should have already called o.init(n). base.Fatalf("%v with unexpected ninit", n.Op) } // Builtin functions. - if n.Op != OCALLFUNC && n.Op != OCALLMETH && n.Op != OCALLINTER { + if n.Op != ir.OCALLFUNC && n.Op != ir.OCALLMETH && n.Op != ir.OCALLINTER { n.Left = o.expr(n.Left, nil) n.Right = o.expr(n.Right, nil) o.exprList(n.List) @@ -479,26 +480,26 @@ func (o *Order) call(n *Node) { n.Left = o.expr(n.Left, nil) o.exprList(n.List) - if n.Op == OCALLINTER { + if n.Op == ir.OCALLINTER { return } - keepAlive := func(arg *Node) { + keepAlive := func(arg *ir.Node) { // If the argument is really a pointer being converted to uintptr, // arrange for the pointer to be kept alive until the call returns, // by copying it into a temp and marking that temp // still alive when we pop the temp stack. - if arg.Op == OCONVNOP && arg.Left.Type.IsUnsafePtr() { + if arg.Op == ir.OCONVNOP && arg.Left.Type.IsUnsafePtr() { x := o.copyExpr(arg.Left, arg.Left.Type, false) arg.Left = x x.Name.SetAddrtaken(true) // ensure SSA keeps the x variable - n.Nbody.Append(typecheck(nod(OVARLIVE, x, nil), ctxStmt)) + n.Nbody.Append(typecheck(ir.Nod(ir.OVARLIVE, x, nil), ctxStmt)) } } // Check for "unsafe-uintptr" tag provided by escape analysis. for i, param := range n.Left.Type.Params().FieldSlice() { if param.Note == unsafeUintptrTag || param.Note == uintptrEscapesTag { - if arg := n.List.Index(i); arg.Op == OSLICELIT { + if arg := n.List.Index(i); arg.Op == ir.OSLICELIT { for _, elt := range arg.List.Slice() { keepAlive(elt) } @@ -524,16 +525,16 @@ func (o *Order) call(n *Node) { // cases they are also typically registerizable, so not much harm done. // And this only applies to the multiple-assignment form. // We could do a more precise analysis if needed, like in walk.go. -func (o *Order) mapAssign(n *Node) { +func (o *Order) mapAssign(n *ir.Node) { switch n.Op { default: base.Fatalf("order.mapAssign %v", n.Op) - case OAS, OASOP: - if n.Left.Op == OINDEXMAP { + case ir.OAS, ir.OASOP: + if n.Left.Op == ir.OINDEXMAP { // Make sure we evaluate the RHS before starting the map insert. // We need to make sure the RHS won't panic. See issue 22881. - if n.Right.Op == OAPPEND { + if n.Right.Op == ir.OAPPEND { s := n.Right.List.Slice()[1:] for i, n := range s { s[i] = o.cheapExpr(n) @@ -544,11 +545,11 @@ func (o *Order) mapAssign(n *Node) { } o.out = append(o.out, n) - case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC: - var post []*Node + case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2MAPR, ir.OAS2FUNC: + var post []*ir.Node for i, m := range n.List.Slice() { switch { - case m.Op == OINDEXMAP: + case m.Op == ir.OINDEXMAP: if !m.Left.IsAutoTmp() { m.Left = o.copyExpr(m.Left, m.Left.Type, false) } @@ -556,10 +557,10 @@ func (o *Order) mapAssign(n *Node) { m.Right = o.copyExpr(m.Right, m.Right.Type, false) } fallthrough - case instrumenting && n.Op == OAS2FUNC && !m.isBlank(): + case instrumenting && n.Op == ir.OAS2FUNC && !ir.IsBlank(m): t := o.newTemp(m.Type, false) n.List.SetIndex(i, t) - a := nod(OAS, m, t) + a := ir.Nod(ir.OAS, m, t) a = typecheck(a, ctxStmt) post = append(post, a) } @@ -573,7 +574,7 @@ func (o *Order) mapAssign(n *Node) { // stmt orders the statement n, appending to o.out. // Temporaries created during the statement are cleaned // up using VARKILL instructions as possible. -func (o *Order) stmt(n *Node) { +func (o *Order) stmt(n *ir.Node) { if n == nil { return } @@ -585,22 +586,22 @@ func (o *Order) stmt(n *Node) { default: base.Fatalf("order.stmt %v", n.Op) - case OVARKILL, OVARLIVE, OINLMARK: + case ir.OVARKILL, ir.OVARLIVE, ir.OINLMARK: o.out = append(o.out, n) - case OAS: + case ir.OAS: t := o.markTemp() n.Left = o.expr(n.Left, nil) n.Right = o.expr(n.Right, n.Left) o.mapAssign(n) o.cleanTemp(t) - case OASOP: + case ir.OASOP: t := o.markTemp() n.Left = o.expr(n.Left, nil) n.Right = o.expr(n.Right, nil) - if instrumenting || n.Left.Op == OINDEXMAP && (n.SubOp() == ODIV || n.SubOp() == OMOD) { + if instrumenting || n.Left.Op == ir.OINDEXMAP && (n.SubOp() == ir.ODIV || n.SubOp() == ir.OMOD) { // Rewrite m[k] op= r into m[k] = m[k] op r so // that we can ensure that if op panics // because r is zero, the panic happens before @@ -609,22 +610,22 @@ func (o *Order) stmt(n *Node) { n.Left = o.safeExpr(n.Left) l := treecopy(n.Left, src.NoXPos) - if l.Op == OINDEXMAP { + if l.Op == ir.OINDEXMAP { l.SetIndexMapLValue(false) } l = o.copyExpr(l, n.Left.Type, false) - n.Right = nod(n.SubOp(), l, n.Right) + n.Right = ir.Nod(n.SubOp(), l, n.Right) n.Right = typecheck(n.Right, ctxExpr) n.Right = o.expr(n.Right, nil) - n.Op = OAS + n.Op = ir.OAS n.ResetAux() } o.mapAssign(n) o.cleanTemp(t) - case OAS2: + case ir.OAS2: t := o.markTemp() o.exprList(n.List) o.exprList(n.Rlist) @@ -632,7 +633,7 @@ func (o *Order) stmt(n *Node) { o.cleanTemp(t) // Special: avoid copy of func call n.Right - case OAS2FUNC: + case ir.OAS2FUNC: t := o.markTemp() o.exprList(n.List) o.init(n.Right) @@ -646,14 +647,14 @@ func (o *Order) stmt(n *Node) { // // OAS2MAPR: make sure key is addressable if needed, // and make sure OINDEXMAP is not copied out. - case OAS2DOTTYPE, OAS2RECV, OAS2MAPR: + case ir.OAS2DOTTYPE, ir.OAS2RECV, ir.OAS2MAPR: t := o.markTemp() o.exprList(n.List) switch r := n.Right; r.Op { - case ODOTTYPE2, ORECV: + case ir.ODOTTYPE2, ir.ORECV: r.Left = o.expr(r.Left, nil) - case OINDEXMAP: + case ir.OINDEXMAP: r.Left = o.expr(r.Left, nil) r.Right = o.expr(r.Right, nil) // See similar conversion for OINDEXMAP below. @@ -667,34 +668,34 @@ func (o *Order) stmt(n *Node) { o.cleanTemp(t) // Special: does not save n onto out. - case OBLOCK, OEMPTY: + case ir.OBLOCK, ir.OEMPTY: o.stmtList(n.List) // Special: n->left is not an expression; save as is. - case OBREAK, - OCONTINUE, - ODCL, - ODCLCONST, - ODCLTYPE, - OFALL, - OGOTO, - OLABEL, - ORETJMP: + case ir.OBREAK, + ir.OCONTINUE, + ir.ODCL, + ir.ODCLCONST, + ir.ODCLTYPE, + ir.OFALL, + ir.OGOTO, + ir.OLABEL, + ir.ORETJMP: o.out = append(o.out, n) // Special: handle call arguments. - case OCALLFUNC, OCALLINTER, OCALLMETH: + case ir.OCALLFUNC, ir.OCALLINTER, ir.OCALLMETH: t := o.markTemp() o.call(n) o.out = append(o.out, n) o.cleanTemp(t) - case OCLOSE, - OCOPY, - OPRINT, - OPRINTN, - ORECOVER, - ORECV: + case ir.OCLOSE, + ir.OCOPY, + ir.OPRINT, + ir.OPRINTN, + ir.ORECOVER, + ir.ORECV: t := o.markTemp() n.Left = o.expr(n.Left, nil) n.Right = o.expr(n.Right, nil) @@ -704,14 +705,14 @@ func (o *Order) stmt(n *Node) { o.cleanTemp(t) // Special: order arguments to inner call but not call itself. - case ODEFER, OGO: + case ir.ODEFER, ir.OGO: t := o.markTemp() o.init(n.Left) o.call(n.Left) o.out = append(o.out, n) o.cleanTemp(t) - case ODELETE: + case ir.ODELETE: t := o.markTemp() n.List.SetFirst(o.expr(n.List.First(), nil)) n.List.SetSecond(o.expr(n.List.Second(), nil)) @@ -721,7 +722,7 @@ func (o *Order) stmt(n *Node) { // Clean temporaries from condition evaluation at // beginning of loop body and after for statement. - case OFOR: + case ir.OFOR: t := o.markTemp() n.Left = o.exprInPlace(n.Left) n.Nbody.Prepend(o.cleanTempNoPop(t)...) @@ -732,7 +733,7 @@ func (o *Order) stmt(n *Node) { // Clean temporaries from condition at // beginning of both branches. - case OIF: + case ir.OIF: t := o.markTemp() n.Left = o.exprInPlace(n.Left) n.Nbody.Prepend(o.cleanTempNoPop(t)...) @@ -744,7 +745,7 @@ func (o *Order) stmt(n *Node) { // Special: argument will be converted to interface using convT2E // so make sure it is an addressable temporary. - case OPANIC: + case ir.OPANIC: t := o.markTemp() n.Left = o.expr(n.Left, nil) if !n.Left.Type.IsInterface() { @@ -753,7 +754,7 @@ func (o *Order) stmt(n *Node) { o.out = append(o.out, n) o.cleanTemp(t) - case ORANGE: + case ir.ORANGE: // n.Right is the expression being ranged over. // order it, and then make a copy if we need one. // We almost always do, to ensure that we don't @@ -767,8 +768,8 @@ func (o *Order) stmt(n *Node) { // Mark []byte(str) range expression to reuse string backing storage. // It is safe because the storage cannot be mutated. - if n.Right.Op == OSTR2BYTES { - n.Right.Op = OSTR2BYTESTMP + if n.Right.Op == ir.OSTR2BYTES { + n.Right.Op = ir.OSTR2BYTESTMP } t := o.markTemp() @@ -779,28 +780,28 @@ func (o *Order) stmt(n *Node) { default: base.Fatalf("order.stmt range %v", n.Type) - case TARRAY, TSLICE: - if n.List.Len() < 2 || n.List.Second().isBlank() { + case types.TARRAY, types.TSLICE: + if n.List.Len() < 2 || ir.IsBlank(n.List.Second()) { // for i := range x will only use x once, to compute len(x). // No need to copy it. break } fallthrough - case TCHAN, TSTRING: + case types.TCHAN, types.TSTRING: // chan, string, slice, array ranges use value multiple times. // make copy. r := n.Right - if r.Type.IsString() && r.Type != types.Types[TSTRING] { - r = nod(OCONV, r, nil) - r.Type = types.Types[TSTRING] + if r.Type.IsString() && r.Type != types.Types[types.TSTRING] { + r = ir.Nod(ir.OCONV, r, nil) + r.Type = types.Types[types.TSTRING] r = typecheck(r, ctxExpr) } n.Right = o.copyExpr(r, r.Type, false) - case TMAP: + case types.TMAP: if isMapClear(n) { // Preserve the body of the map clear pattern so it can // be detected during walk. The loop body will not be used @@ -826,7 +827,7 @@ func (o *Order) stmt(n *Node) { o.out = append(o.out, n) o.cleanTemp(t) - case ORETURN: + case ir.ORETURN: o.exprList(n.List) o.out = append(o.out, n) @@ -839,11 +840,11 @@ func (o *Order) stmt(n *Node) { // reordered after the channel evaluation for a different // case (if p were nil, then the timing of the fault would // give this away). - case OSELECT: + case ir.OSELECT: t := o.markTemp() for _, n2 := range n.List.Slice() { - if n2.Op != OCASE { + if n2.Op != ir.OCASE { base.Fatalf("order select case %v", n2.Op) } r := n2.Left @@ -859,20 +860,20 @@ func (o *Order) stmt(n *Node) { } switch r.Op { default: - Dump("select case", r) + ir.Dump("select case", r) base.Fatalf("unknown op in select %v", r.Op) // If this is case x := <-ch or case x, y := <-ch, the case has // the ODCL nodes to declare x and y. We want to delay that // declaration (and possible allocation) until inside the case body. // Delete the ODCL nodes here and recreate them inside the body below. - case OSELRECV, OSELRECV2: + case ir.OSELRECV, ir.OSELRECV2: if r.Colas() { i := 0 - if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left { + if r.Ninit.Len() != 0 && r.Ninit.First().Op == ir.ODCL && r.Ninit.First().Left == r.Left { i++ } - if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() { + if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ir.ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() { i++ } if i >= r.Ninit.Len() { @@ -881,7 +882,7 @@ func (o *Order) stmt(n *Node) { } if r.Ninit.Len() != 0 { - dumplist("ninit", r.Ninit) + ir.DumpList("ninit", r.Ninit) base.Fatalf("ninit on select recv") } @@ -892,7 +893,7 @@ func (o *Order) stmt(n *Node) { // c is always evaluated; x and ok are only evaluated when assigned. r.Right.Left = o.expr(r.Right.Left, nil) - if r.Right.Left.Op != ONAME { + if r.Right.Left.Op != ir.ONAME { r.Right.Left = o.copyExpr(r.Right.Left, r.Right.Left.Type, false) } @@ -902,7 +903,7 @@ func (o *Order) stmt(n *Node) { // temporary per distinct type, sharing the temp among all receives // with that temp. Similarly one ok bool could be shared among all // the x,ok receives. Not worth doing until there's a clear need. - if r.Left != nil && r.Left.isBlank() { + if r.Left != nil && ir.IsBlank(r.Left) { r.Left = nil } if r.Left != nil { @@ -912,38 +913,38 @@ func (o *Order) stmt(n *Node) { tmp1 := r.Left if r.Colas() { - tmp2 := nod(ODCL, tmp1, nil) + tmp2 := ir.Nod(ir.ODCL, tmp1, nil) tmp2 = typecheck(tmp2, ctxStmt) n2.Ninit.Append(tmp2) } r.Left = o.newTemp(r.Right.Left.Type.Elem(), r.Right.Left.Type.Elem().HasPointers()) - tmp2 := nod(OAS, tmp1, r.Left) + tmp2 := ir.Nod(ir.OAS, tmp1, r.Left) tmp2 = typecheck(tmp2, ctxStmt) n2.Ninit.Append(tmp2) } - if r.List.Len() != 0 && r.List.First().isBlank() { + if r.List.Len() != 0 && ir.IsBlank(r.List.First()) { r.List.Set(nil) } if r.List.Len() != 0 { tmp1 := r.List.First() if r.Colas() { - tmp2 := nod(ODCL, tmp1, nil) + tmp2 := ir.Nod(ir.ODCL, tmp1, nil) tmp2 = typecheck(tmp2, ctxStmt) n2.Ninit.Append(tmp2) } - r.List.Set1(o.newTemp(types.Types[TBOOL], false)) + r.List.Set1(o.newTemp(types.Types[types.TBOOL], false)) tmp2 := okas(tmp1, r.List.First()) tmp2 = typecheck(tmp2, ctxStmt) n2.Ninit.Append(tmp2) } orderBlock(&n2.Ninit, o.free) - case OSEND: + case ir.OSEND: if r.Ninit.Len() != 0 { - dumplist("ninit", r.Ninit) + ir.DumpList("ninit", r.Ninit) base.Fatalf("ninit on select send") } @@ -977,7 +978,7 @@ func (o *Order) stmt(n *Node) { o.popTemp(t) // Special: value being sent is passed as a pointer; make it addressable. - case OSEND: + case ir.OSEND: t := o.markTemp() n.Left = o.expr(n.Left, nil) n.Right = o.expr(n.Right, nil) @@ -998,16 +999,16 @@ func (o *Order) stmt(n *Node) { // the if-else chain instead.) // For now just clean all the temporaries at the end. // In practice that's fine. - case OSWITCH: + case ir.OSWITCH: if base.Debug.Libfuzzer != 0 && !hasDefaultCase(n) { // Add empty "default:" case for instrumentation. - n.List.Append(nod(OCASE, nil, nil)) + n.List.Append(ir.Nod(ir.OCASE, nil, nil)) } t := o.markTemp() n.Left = o.expr(n.Left, nil) for _, ncas := range n.List.Slice() { - if ncas.Op != OCASE { + if ncas.Op != ir.OCASE { base.Fatalf("order switch case %v", ncas.Op) } o.exprListInPlace(ncas.List) @@ -1021,9 +1022,9 @@ func (o *Order) stmt(n *Node) { base.Pos = lno } -func hasDefaultCase(n *Node) bool { +func hasDefaultCase(n *ir.Node) bool { for _, ncas := range n.List.Slice() { - if ncas.Op != OCASE { + if ncas.Op != ir.OCASE { base.Fatalf("expected case, found %v", ncas.Op) } if ncas.List.Len() == 0 { @@ -1034,7 +1035,7 @@ func hasDefaultCase(n *Node) bool { } // exprList orders the expression list l into o. -func (o *Order) exprList(l Nodes) { +func (o *Order) exprList(l ir.Nodes) { s := l.Slice() for i := range s { s[i] = o.expr(s[i], nil) @@ -1043,7 +1044,7 @@ func (o *Order) exprList(l Nodes) { // exprListInPlace orders the expression list l but saves // the side effects on the individual expression ninit lists. -func (o *Order) exprListInPlace(l Nodes) { +func (o *Order) exprListInPlace(l ir.Nodes) { s := l.Slice() for i := range s { s[i] = o.exprInPlace(s[i]) @@ -1051,7 +1052,7 @@ func (o *Order) exprListInPlace(l Nodes) { } // prealloc[x] records the allocation to use for x. -var prealloc = map[*Node]*Node{} +var prealloc = map[*ir.Node]*ir.Node{} // expr orders a single expression, appending side // effects to o.out as needed. @@ -1060,7 +1061,7 @@ var prealloc = map[*Node]*Node{} // to avoid copying the result of the expression to a temporary.) // The result of expr MUST be assigned back to n, e.g. // n.Left = o.expr(n.Left, lhs) -func (o *Order) expr(n, lhs *Node) *Node { +func (o *Order) expr(n, lhs *ir.Node) *ir.Node { if n == nil { return n } @@ -1078,11 +1079,11 @@ func (o *Order) expr(n, lhs *Node) *Node { // Addition of strings turns into a function call. // Allocate a temporary to hold the strings. // Fewer than 5 strings use direct runtime helpers. - case OADDSTR: + case ir.OADDSTR: o.exprList(n.List) if n.List.Len() > 5 { - t := types.NewArray(types.Types[TSTRING], int64(n.List.Len())) + t := types.NewArray(types.Types[types.TSTRING], int64(n.List.Len())) prealloc[n] = o.newTemp(t, false) } @@ -1097,19 +1098,19 @@ func (o *Order) expr(n, lhs *Node) *Node { haslit := false for _, n1 := range n.List.Slice() { - hasbyte = hasbyte || n1.Op == OBYTES2STR - haslit = haslit || n1.Op == OLITERAL && len(n1.StringVal()) != 0 + hasbyte = hasbyte || n1.Op == ir.OBYTES2STR + haslit = haslit || n1.Op == ir.OLITERAL && len(n1.StringVal()) != 0 } if haslit && hasbyte { for _, n2 := range n.List.Slice() { - if n2.Op == OBYTES2STR { - n2.Op = OBYTES2STRTMP + if n2.Op == ir.OBYTES2STR { + n2.Op = ir.OBYTES2STRTMP } } } - case OINDEXMAP: + case ir.OINDEXMAP: n.Left = o.expr(n.Left, nil) n.Right = o.expr(n.Right, nil) needCopy := false @@ -1136,7 +1137,7 @@ func (o *Order) expr(n, lhs *Node) *Node { // concrete type (not interface) argument might need an addressable // temporary to pass to the runtime conversion routine. - case OCONVIFACE: + case ir.OCONVIFACE: n.Left = o.expr(n.Left, nil) if n.Left.Type.IsInterface() { break @@ -1148,21 +1149,21 @@ func (o *Order) expr(n, lhs *Node) *Node { n.Left = o.addrTemp(n.Left) } - case OCONVNOP: - if n.Type.IsKind(TUNSAFEPTR) && n.Left.Type.IsKind(TUINTPTR) && (n.Left.Op == OCALLFUNC || n.Left.Op == OCALLINTER || n.Left.Op == OCALLMETH) { + case ir.OCONVNOP: + if n.Type.IsKind(types.TUNSAFEPTR) && n.Left.Type.IsKind(types.TUINTPTR) && (n.Left.Op == ir.OCALLFUNC || n.Left.Op == ir.OCALLINTER || n.Left.Op == ir.OCALLMETH) { // When reordering unsafe.Pointer(f()) into a separate // statement, the conversion and function call must stay // together. See golang.org/issue/15329. o.init(n.Left) o.call(n.Left) - if lhs == nil || lhs.Op != ONAME || instrumenting { + if lhs == nil || lhs.Op != ir.ONAME || instrumenting { n = o.copyExpr(n, n.Type, false) } } else { n.Left = o.expr(n.Left, nil) } - case OANDAND, OOROR: + case ir.OANDAND, ir.OOROR: // ... = LHS && RHS // // var r bool @@ -1176,7 +1177,7 @@ func (o *Order) expr(n, lhs *Node) *Node { // Evaluate left-hand side. lhs := o.expr(n.Left, nil) - o.out = append(o.out, typecheck(nod(OAS, r, lhs), ctxStmt)) + o.out = append(o.out, typecheck(ir.Nod(ir.OAS, r, lhs), ctxStmt)) // Evaluate right-hand side, save generated code. saveout := o.out @@ -1184,14 +1185,14 @@ func (o *Order) expr(n, lhs *Node) *Node { t := o.markTemp() o.edge() rhs := o.expr(n.Right, nil) - o.out = append(o.out, typecheck(nod(OAS, r, rhs), ctxStmt)) + o.out = append(o.out, typecheck(ir.Nod(ir.OAS, r, rhs), ctxStmt)) o.cleanTemp(t) gen := o.out o.out = saveout // If left-hand side doesn't cause a short-circuit, issue right-hand side. - nif := nod(OIF, r, nil) - if n.Op == OANDAND { + nif := ir.Nod(ir.OIF, r, nil) + if n.Op == ir.OANDAND { nif.Nbody.Set(gen) } else { nif.Rlist.Set(gen) @@ -1199,24 +1200,24 @@ func (o *Order) expr(n, lhs *Node) *Node { o.out = append(o.out, nif) n = r - case OCALLFUNC, - OCALLINTER, - OCALLMETH, - OCAP, - OCOMPLEX, - OCOPY, - OIMAG, - OLEN, - OMAKECHAN, - OMAKEMAP, - OMAKESLICE, - OMAKESLICECOPY, - ONEW, - OREAL, - ORECOVER, - OSTR2BYTES, - OSTR2BYTESTMP, - OSTR2RUNES: + case ir.OCALLFUNC, + ir.OCALLINTER, + ir.OCALLMETH, + ir.OCAP, + ir.OCOMPLEX, + ir.OCOPY, + ir.OIMAG, + ir.OLEN, + ir.OMAKECHAN, + ir.OMAKEMAP, + ir.OMAKESLICE, + ir.OMAKESLICECOPY, + ir.ONEW, + ir.OREAL, + ir.ORECOVER, + ir.OSTR2BYTES, + ir.OSTR2BYTESTMP, + ir.OSTR2RUNES: if isRuneCount(n) { // len([]rune(s)) is rewritten to runtime.countrunes(s) later. @@ -1225,11 +1226,11 @@ func (o *Order) expr(n, lhs *Node) *Node { o.call(n) } - if lhs == nil || lhs.Op != ONAME || instrumenting { + if lhs == nil || lhs.Op != ir.ONAME || instrumenting { n = o.copyExpr(n, n.Type, false) } - case OAPPEND: + case ir.OAPPEND: // Check for append(x, make([]T, y)...) . if isAppendOfMake(n) { n.List.SetFirst(o.expr(n.List.First(), nil)) // order x @@ -1238,11 +1239,11 @@ func (o *Order) expr(n, lhs *Node) *Node { o.exprList(n.List) } - if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.First()) { + if lhs == nil || lhs.Op != ir.ONAME && !samesafeexpr(lhs, n.List.First()) { n = o.copyExpr(n, n.Type, false) } - case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: + case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR: n.Left = o.expr(n.Left, nil) low, high, max := n.SliceBounds() low = o.expr(low, nil) @@ -1252,16 +1253,16 @@ func (o *Order) expr(n, lhs *Node) *Node { max = o.expr(max, nil) max = o.cheapExpr(max) n.SetSliceBounds(low, high, max) - if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) { + if lhs == nil || lhs.Op != ir.ONAME && !samesafeexpr(lhs, n.Left) { n = o.copyExpr(n, n.Type, false) } - case OCLOSURE: + case ir.OCLOSURE: if n.Transient() && n.Func.ClosureVars.Len() > 0 { prealloc[n] = o.newTemp(closureType(n), false) } - case OSLICELIT, OCALLPART: + case ir.OSLICELIT, ir.OCALLPART: n.Left = o.expr(n.Left, nil) n.Right = o.expr(n.Right, nil) o.exprList(n.List) @@ -1269,25 +1270,25 @@ func (o *Order) expr(n, lhs *Node) *Node { if n.Transient() { var t *types.Type switch n.Op { - case OSLICELIT: + case ir.OSLICELIT: t = types.NewArray(n.Type.Elem(), n.Right.Int64Val()) - case OCALLPART: + case ir.OCALLPART: t = partialCallType(n) } prealloc[n] = o.newTemp(t, false) } - case ODOTTYPE, ODOTTYPE2: + case ir.ODOTTYPE, ir.ODOTTYPE2: n.Left = o.expr(n.Left, nil) if !isdirectiface(n.Type) || instrumenting { n = o.copyExpr(n, n.Type, true) } - case ORECV: + case ir.ORECV: n.Left = o.expr(n.Left, nil) n = o.copyExpr(n, n.Type, true) - case OEQ, ONE, OLT, OLE, OGT, OGE: + case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: n.Left = o.expr(n.Left, nil) n.Right = o.expr(n.Right, nil) @@ -1297,11 +1298,11 @@ func (o *Order) expr(n, lhs *Node) *Node { // Mark string(byteSlice) arguments to reuse byteSlice backing // buffer during conversion. String comparison does not // memorize the strings for later use, so it is safe. - if n.Left.Op == OBYTES2STR { - n.Left.Op = OBYTES2STRTMP + if n.Left.Op == ir.OBYTES2STR { + n.Left.Op = ir.OBYTES2STRTMP } - if n.Right.Op == OBYTES2STR { - n.Right.Op = OBYTES2STRTMP + if n.Right.Op == ir.OBYTES2STR { + n.Right.Op = ir.OBYTES2STRTMP } case t.IsStruct() || t.IsArray(): @@ -1310,7 +1311,7 @@ func (o *Order) expr(n, lhs *Node) *Node { n.Left = o.addrTemp(n.Left) n.Right = o.addrTemp(n.Right) } - case OMAPLIT: + case ir.OMAPLIT: // Order map by converting: // map[int]int{ // a(): b(), @@ -1328,9 +1329,9 @@ func (o *Order) expr(n, lhs *Node) *Node { // See issue 26552. entries := n.List.Slice() statics := entries[:0] - var dynamics []*Node + var dynamics []*ir.Node for _, r := range entries { - if r.Op != OKEY { + if r.Op != ir.OKEY { base.Fatalf("OMAPLIT entry not OKEY: %v\n", r) } @@ -1357,14 +1358,14 @@ func (o *Order) expr(n, lhs *Node) *Node { // Emit the creation of the map (with all its static entries). m := o.newTemp(n.Type, false) - as := nod(OAS, m, n) + as := ir.Nod(ir.OAS, m, n) typecheck(as, ctxStmt) o.stmt(as) n = m // Emit eval+insert of dynamic entries, one at a time. for _, r := range dynamics { - as := nod(OAS, nod(OINDEX, n, r.Left), r.Right) + as := ir.Nod(ir.OAS, ir.Nod(ir.OINDEX, n, r.Left), r.Right) typecheck(as, ctxStmt) // Note: this converts the OINDEX to an OINDEXMAP o.stmt(as) } @@ -1376,11 +1377,11 @@ func (o *Order) expr(n, lhs *Node) *Node { // okas creates and returns an assignment of val to ok, // including an explicit conversion if necessary. -func okas(ok, val *Node) *Node { - if !ok.isBlank() { +func okas(ok, val *ir.Node) *ir.Node { + if !ir.IsBlank(ok) { val = conv(val, ok.Type) } - return nod(OAS, ok, val) + return ir.Nod(ir.OAS, ok, val) } // as2 orders OAS2XXXX nodes. It creates temporaries to ensure left-to-right assignment. @@ -1391,11 +1392,11 @@ func okas(ok, val *Node) *Node { // tmp1, tmp2, tmp3 = ... // a, b, a = tmp1, tmp2, tmp3 // This is necessary to ensure left to right assignment order. -func (o *Order) as2(n *Node) { - tmplist := []*Node{} - left := []*Node{} +func (o *Order) as2(n *ir.Node) { + tmplist := []*ir.Node{} + left := []*ir.Node{} for ni, l := range n.List.Slice() { - if !l.isBlank() { + if !ir.IsBlank(l) { tmp := o.newTemp(l.Type, l.Type.HasPointers()) n.List.SetIndex(ni, tmp) tmplist = append(tmplist, tmp) @@ -1405,7 +1406,7 @@ func (o *Order) as2(n *Node) { o.out = append(o.out, n) - as := nod(OAS2, nil, nil) + as := ir.Nod(ir.OAS2, nil, nil) as.List.Set(left) as.Rlist.Set(tmplist) as = typecheck(as, ctxStmt) @@ -1414,21 +1415,21 @@ func (o *Order) as2(n *Node) { // okAs2 orders OAS2XXX with ok. // Just like as2, this also adds temporaries to ensure left-to-right assignment. -func (o *Order) okAs2(n *Node) { - var tmp1, tmp2 *Node - if !n.List.First().isBlank() { +func (o *Order) okAs2(n *ir.Node) { + var tmp1, tmp2 *ir.Node + if !ir.IsBlank(n.List.First()) { typ := n.Right.Type tmp1 = o.newTemp(typ, typ.HasPointers()) } - if !n.List.Second().isBlank() { - tmp2 = o.newTemp(types.Types[TBOOL], false) + if !ir.IsBlank(n.List.Second()) { + tmp2 = o.newTemp(types.Types[types.TBOOL], false) } o.out = append(o.out, n) if tmp1 != nil { - r := nod(OAS, n.List.First(), tmp1) + r := ir.Nod(ir.OAS, n.List.First(), tmp1) r = typecheck(r, ctxStmt) o.mapAssign(r) n.List.SetFirst(tmp1) diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index f10599dc280..38f416c1c38 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/ssa" "cmd/compile/internal/types" "cmd/internal/dwarf" @@ -23,14 +24,14 @@ import ( // "Portable" code generation. var ( - compilequeue []*Node // functions waiting to be compiled + compilequeue []*ir.Node // functions waiting to be compiled ) -func emitptrargsmap(fn *Node) { - if fn.funcname() == "_" || fn.Func.Nname.Sym.Linkname != "" { +func emitptrargsmap(fn *ir.Node) { + if ir.FuncName(fn) == "_" || fn.Func.Nname.Sym.Linkname != "" { return } - lsym := base.Ctxt.Lookup(fn.Func.lsym.Name + ".args_stackmap") + lsym := base.Ctxt.Lookup(fn.Func.LSym.Name + ".args_stackmap") nptr := int(fn.Type.ArgWidth() / int64(Widthptr)) bv := bvalloc(int32(nptr) * 2) @@ -41,7 +42,7 @@ func emitptrargsmap(fn *Node) { off := duint32(lsym, 0, uint32(nbitmap)) off = duint32(lsym, off, uint32(bv.n)) - if fn.IsMethod() { + if ir.IsMethod(fn) { onebitwalktype1(fn.Type.Recvs(), 0, bv) } if fn.Type.NumParams() > 0 { @@ -67,12 +68,12 @@ func emitptrargsmap(fn *Node) { // really means, in memory, things with pointers needing zeroing at // the top of the stack and increasing in size. // Non-autos sort on offset. -func cmpstackvarlt(a, b *Node) bool { - if (a.Class() == PAUTO) != (b.Class() == PAUTO) { - return b.Class() == PAUTO +func cmpstackvarlt(a, b *ir.Node) bool { + if (a.Class() == ir.PAUTO) != (b.Class() == ir.PAUTO) { + return b.Class() == ir.PAUTO } - if a.Class() != PAUTO { + if a.Class() != ir.PAUTO { return a.Xoffset < b.Xoffset } @@ -100,7 +101,7 @@ func cmpstackvarlt(a, b *Node) bool { } // byStackvar implements sort.Interface for []*Node using cmpstackvarlt. -type byStackVar []*Node +type byStackVar []*ir.Node func (s byStackVar) Len() int { return len(s) } func (s byStackVar) Less(i, j int) bool { return cmpstackvarlt(s[i], s[j]) } @@ -113,28 +114,28 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { // Mark the PAUTO's unused. for _, ln := range fn.Dcl { - if ln.Class() == PAUTO { + if ln.Class() == ir.PAUTO { ln.Name.SetUsed(false) } } for _, l := range f.RegAlloc { if ls, ok := l.(ssa.LocalSlot); ok { - ls.N.(*Node).Name.SetUsed(true) + ls.N.(*ir.Node).Name.SetUsed(true) } } scratchUsed := false for _, b := range f.Blocks { for _, v := range b.Values { - if n, ok := v.Aux.(*Node); ok { + if n, ok := v.Aux.(*ir.Node); ok { switch n.Class() { - case PPARAM, PPARAMOUT: + case ir.PPARAM, ir.PPARAMOUT: // Don't modify nodfp; it is a global. if n != nodfp { n.Name.SetUsed(true) } - case PAUTO: + case ir.PAUTO: n.Name.SetUsed(true) } } @@ -146,7 +147,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { } if f.Config.NeedsFpScratch && scratchUsed { - s.scratchFpMem = tempAt(src.NoXPos, s.curfn, types.Types[TUINT64]) + s.scratchFpMem = tempAt(src.NoXPos, s.curfn, types.Types[types.TUINT64]) } sort.Sort(byStackVar(fn.Dcl)) @@ -154,7 +155,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { // Reassign stack offsets of the locals that are used. lastHasPtr := false for i, n := range fn.Dcl { - if n.Op != ONAME || n.Class() != PAUTO { + if n.Op != ir.ONAME || n.Class() != ir.PAUTO { continue } if !n.Name.Used() { @@ -192,7 +193,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { s.stkptrsize = Rnd(s.stkptrsize, int64(Widthreg)) } -func funccompile(fn *Node) { +func funccompile(fn *ir.Node) { if Curfn != nil { base.Fatalf("funccompile %v inside %v", fn.Func.Nname.Sym, Curfn.Func.Nname.Sym) } @@ -209,21 +210,21 @@ func funccompile(fn *Node) { if fn.Nbody.Len() == 0 { // Initialize ABI wrappers if necessary. - fn.Func.initLSym(false) + initLSym(fn.Func, false) emitptrargsmap(fn) return } - dclcontext = PAUTO + dclcontext = ir.PAUTO Curfn = fn compile(fn) Curfn = nil - dclcontext = PEXTERN + dclcontext = ir.PEXTERN } -func compile(fn *Node) { +func compile(fn *ir.Node) { errorsBefore := base.Errors() order(fn) if base.Errors() > errorsBefore { @@ -233,7 +234,7 @@ func compile(fn *Node) { // Set up the function's LSym early to avoid data races with the assemblers. // Do this before walk, as walk needs the LSym to set attributes/relocations // (e.g. in markTypeUsedInInterface). - fn.Func.initLSym(true) + initLSym(fn.Func, true) walk(fn) if base.Errors() > errorsBefore { @@ -246,7 +247,7 @@ func compile(fn *Node) { // From this point, there should be no uses of Curfn. Enforce that. Curfn = nil - if fn.funcname() == "_" { + if ir.FuncName(fn) == "_" { // We don't need to generate code for this function, just report errors in its body. // At this point we've generated any errors needed. // (Beyond here we generate only non-spec errors, like "stack frame too large".) @@ -260,13 +261,13 @@ func compile(fn *Node) { // phase of the compiler. for _, n := range fn.Func.Dcl { switch n.Class() { - case PPARAM, PPARAMOUT, PAUTO: + case ir.PPARAM, ir.PPARAMOUT, ir.PAUTO: if livenessShouldTrack(n) && n.Name.Addrtaken() { dtypesym(n.Type) // Also make sure we allocate a linker symbol // for the stack object data, for the same reason. - if fn.Func.lsym.Func().StackObjects == nil { - fn.Func.lsym.Func().StackObjects = base.Ctxt.Lookup(fn.Func.lsym.Name + ".stkobj") + if fn.Func.LSym.Func().StackObjects == nil { + fn.Func.LSym.Func().StackObjects = base.Ctxt.Lookup(fn.Func.LSym.Name + ".stkobj") } } } @@ -283,13 +284,13 @@ func compile(fn *Node) { // If functions are not compiled immediately, // they are enqueued in compilequeue, // which is drained by compileFunctions. -func compilenow(fn *Node) bool { +func compilenow(fn *ir.Node) bool { // Issue 38068: if this function is a method AND an inline // candidate AND was not inlined (yet), put it onto the compile // queue instead of compiling it immediately. This is in case we // wind up inlining it into a method wrapper that is generated by // compiling a function later on in the xtop list. - if fn.IsMethod() && isInlinableButNotInlined(fn) { + if ir.IsMethod(fn) && isInlinableButNotInlined(fn) { return false } return base.Flag.LowerC == 1 && base.Debug.CompileLater == 0 @@ -298,7 +299,7 @@ func compilenow(fn *Node) bool { // isInlinableButNotInlined returns true if 'fn' was marked as an // inline candidate but then never inlined (presumably because we // found no call sites). -func isInlinableButNotInlined(fn *Node) bool { +func isInlinableButNotInlined(fn *ir.Node) bool { if fn.Func.Nname.Func.Inl == nil { return false } @@ -314,7 +315,7 @@ const maxStackSize = 1 << 30 // uses it to generate a plist, // and flushes that plist to machine code. // worker indicates which of the backend workers is doing the processing. -func compileSSA(fn *Node, worker int) { +func compileSSA(fn *ir.Node, worker int) { f := buildssa(fn, worker) // Note: check arg size to fix issue 25507. if f.Frontend().(*ssafn).stksize >= maxStackSize || fn.Type.ArgWidth() >= maxStackSize { @@ -359,7 +360,7 @@ func compileFunctions() { sizeCalculationDisabled = true // not safe to calculate sizes concurrently if race.Enabled { // Randomize compilation order to try to shake out races. - tmp := make([]*Node, len(compilequeue)) + tmp := make([]*ir.Node, len(compilequeue)) perm := rand.Perm(len(compilequeue)) for i, v := range perm { tmp[v] = compilequeue[i] @@ -375,7 +376,7 @@ func compileFunctions() { } var wg sync.WaitGroup base.Ctxt.InParallel = true - c := make(chan *Node, base.Flag.LowerC) + c := make(chan *ir.Node, base.Flag.LowerC) for i := 0; i < base.Flag.LowerC; i++ { wg.Add(1) go func(worker int) { @@ -397,7 +398,7 @@ func compileFunctions() { } func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope, dwarf.InlCalls) { - fn := curfn.(*Node) + fn := curfn.(*ir.Node) if fn.Func.Nname != nil { if expect := fn.Func.Nname.Sym.Linksym(); fnsym != expect { base.Fatalf("unexpected fnsym: %v != %v", fnsym, expect) @@ -429,17 +430,17 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S // // These two adjustments keep toolstash -cmp working for now. // Deciding the right answer is, as they say, future work. - isODCLFUNC := fn.Op == ODCLFUNC + isODCLFUNC := fn.Op == ir.ODCLFUNC - var apdecls []*Node + var apdecls []*ir.Node // Populate decls for fn. if isODCLFUNC { for _, n := range fn.Func.Dcl { - if n.Op != ONAME { // might be OTYPE or OLITERAL + if n.Op != ir.ONAME { // might be OTYPE or OLITERAL continue } switch n.Class() { - case PAUTO: + case ir.PAUTO: if !n.Name.Used() { // Text == nil -> generating abstract function if fnsym.Func().Text != nil { @@ -447,7 +448,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S } continue } - case PPARAM, PPARAMOUT: + case ir.PPARAM, ir.PPARAMOUT: default: continue } @@ -474,7 +475,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S } fnsym.Func().Autot = nil - var varScopes []ScopeID + var varScopes []ir.ScopeID for _, decl := range decls { pos := declPos(decl) varScopes = append(varScopes, findScope(fn.Func.Marks, pos)) @@ -488,7 +489,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S return scopes, inlcalls } -func declPos(decl *Node) src.XPos { +func declPos(decl *ir.Node) src.XPos { if decl.Name.Defn != nil && (decl.Name.Captured() || decl.Name.Byval()) { // It's not clear which position is correct for captured variables here: // * decl.Pos is the wrong position for captured variables, in the inner @@ -511,10 +512,10 @@ func declPos(decl *Node) src.XPos { // createSimpleVars creates a DWARF entry for every variable declared in the // function, claiming that they are permanently on the stack. -func createSimpleVars(fnsym *obj.LSym, apDecls []*Node) ([]*Node, []*dwarf.Var, map[*Node]bool) { +func createSimpleVars(fnsym *obj.LSym, apDecls []*ir.Node) ([]*ir.Node, []*dwarf.Var, map[*ir.Node]bool) { var vars []*dwarf.Var - var decls []*Node - selected := make(map[*Node]bool) + var decls []*ir.Node + selected := make(map[*ir.Node]bool) for _, n := range apDecls { if n.IsAutoTmp() { continue @@ -527,12 +528,12 @@ func createSimpleVars(fnsym *obj.LSym, apDecls []*Node) ([]*Node, []*dwarf.Var, return decls, vars, selected } -func createSimpleVar(fnsym *obj.LSym, n *Node) *dwarf.Var { +func createSimpleVar(fnsym *obj.LSym, n *ir.Node) *dwarf.Var { var abbrev int offs := n.Xoffset switch n.Class() { - case PAUTO: + case ir.PAUTO: abbrev = dwarf.DW_ABRV_AUTO if base.Ctxt.FixedFrameSize() == 0 { offs -= int64(Widthptr) @@ -542,7 +543,7 @@ func createSimpleVar(fnsym *obj.LSym, n *Node) *dwarf.Var { offs -= int64(Widthptr) } - case PPARAM, PPARAMOUT: + case ir.PPARAM, ir.PPARAMOUT: abbrev = dwarf.DW_ABRV_PARAM offs += base.Ctxt.FixedFrameSize() default: @@ -563,7 +564,7 @@ func createSimpleVar(fnsym *obj.LSym, n *Node) *dwarf.Var { declpos := base.Ctxt.InnermostPos(declPos(n)) return &dwarf.Var{ Name: n.Sym.Name, - IsReturnValue: n.Class() == PPARAMOUT, + IsReturnValue: n.Class() == ir.PPARAMOUT, IsInlFormal: n.Name.InlFormal(), Abbrev: abbrev, StackOffset: int32(offs), @@ -578,19 +579,19 @@ func createSimpleVar(fnsym *obj.LSym, n *Node) *dwarf.Var { // createComplexVars creates recomposed DWARF vars with location lists, // suitable for describing optimized code. -func createComplexVars(fnsym *obj.LSym, fn *Func) ([]*Node, []*dwarf.Var, map[*Node]bool) { +func createComplexVars(fnsym *obj.LSym, fn *ir.Func) ([]*ir.Node, []*dwarf.Var, map[*ir.Node]bool) { debugInfo := fn.DebugInfo // Produce a DWARF variable entry for each user variable. - var decls []*Node + var decls []*ir.Node var vars []*dwarf.Var - ssaVars := make(map[*Node]bool) + ssaVars := make(map[*ir.Node]bool) for varID, dvar := range debugInfo.Vars { - n := dvar.(*Node) + n := dvar.(*ir.Node) ssaVars[n] = true for _, slot := range debugInfo.VarSlots[varID] { - ssaVars[debugInfo.Slots[slot].N.(*Node)] = true + ssaVars[debugInfo.Slots[slot].N.(*ir.Node)] = true } if dvar := createComplexVar(fnsym, fn, ssa.VarID(varID)); dvar != nil { @@ -604,11 +605,11 @@ func createComplexVars(fnsym *obj.LSym, fn *Func) ([]*Node, []*dwarf.Var, map[*N // createDwarfVars process fn, returning a list of DWARF variables and the // Nodes they represent. -func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *Func, apDecls []*Node) ([]*Node, []*dwarf.Var) { +func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir.Node) ([]*ir.Node, []*dwarf.Var) { // Collect a raw list of DWARF vars. var vars []*dwarf.Var - var decls []*Node - var selected map[*Node]bool + var decls []*ir.Node + var selected map[*ir.Node]bool if base.Ctxt.Flag_locationlists && base.Ctxt.Flag_optimize && fn.DebugInfo != nil && complexOK { decls, vars, selected = createComplexVars(fnsym, fn) } else { @@ -640,7 +641,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *Func, apDecls []*Node) if c == '.' || n.Type.IsUntyped() { continue } - if n.Class() == PPARAM && !canSSAType(n.Type) { + if n.Class() == ir.PPARAM && !canSSAType(n.Type) { // SSA-able args get location lists, and may move in and // out of registers, so those are handled elsewhere. // Autos and named output params seem to get handled @@ -655,10 +656,10 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *Func, apDecls []*Node) typename := dwarf.InfoPrefix + typesymname(n.Type) decls = append(decls, n) abbrev := dwarf.DW_ABRV_AUTO_LOCLIST - isReturnValue := (n.Class() == PPARAMOUT) - if n.Class() == PPARAM || n.Class() == PPARAMOUT { + isReturnValue := (n.Class() == ir.PPARAMOUT) + if n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT { abbrev = dwarf.DW_ABRV_PARAM_LOCLIST - } else if n.Class() == PAUTOHEAP { + } else if n.Class() == ir.PAUTOHEAP { // If dcl in question has been promoted to heap, do a bit // of extra work to recover original class (auto or param); // see issue 30908. This insures that we get the proper @@ -667,9 +668,9 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *Func, apDecls []*Node) // and not stack). // TODO(thanm): generate a better location expression stackcopy := n.Name.Param.Stackcopy - if stackcopy != nil && (stackcopy.Class() == PPARAM || stackcopy.Class() == PPARAMOUT) { + if stackcopy != nil && (stackcopy.Class() == ir.PPARAM || stackcopy.Class() == ir.PPARAMOUT) { abbrev = dwarf.DW_ABRV_PARAM_LOCLIST - isReturnValue = (stackcopy.Class() == PPARAMOUT) + isReturnValue = (stackcopy.Class() == ir.PPARAMOUT) } } inlIndex := 0 @@ -707,9 +708,9 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *Func, apDecls []*Node) // function that is not local to the package being compiled, then the // names of the variables may have been "versioned" to avoid conflicts // with local vars; disregard this versioning when sorting. -func preInliningDcls(fnsym *obj.LSym) []*Node { - fn := base.Ctxt.DwFixups.GetPrecursorFunc(fnsym).(*Node) - var rdcl []*Node +func preInliningDcls(fnsym *obj.LSym) []*ir.Node { + fn := base.Ctxt.DwFixups.GetPrecursorFunc(fnsym).(*ir.Node) + var rdcl []*ir.Node for _, n := range fn.Func.Inl.Dcl { c := n.Sym.Name[0] // Avoid reporting "_" parameters, since if there are more than @@ -726,10 +727,10 @@ func preInliningDcls(fnsym *obj.LSym) []*Node { // stack pointer, suitable for use in a DWARF location entry. This has nothing // to do with its offset in the user variable. func stackOffset(slot ssa.LocalSlot) int32 { - n := slot.N.(*Node) + n := slot.N.(*ir.Node) var off int64 switch n.Class() { - case PAUTO: + case ir.PAUTO: if base.Ctxt.FixedFrameSize() == 0 { off -= int64(Widthptr) } @@ -737,22 +738,22 @@ func stackOffset(slot ssa.LocalSlot) int32 { // There is a word space for FP on ARM64 even if the frame pointer is disabled off -= int64(Widthptr) } - case PPARAM, PPARAMOUT: + case ir.PPARAM, ir.PPARAMOUT: off += base.Ctxt.FixedFrameSize() } return int32(off + n.Xoffset + slot.Off) } // createComplexVar builds a single DWARF variable entry and location list. -func createComplexVar(fnsym *obj.LSym, fn *Func, varID ssa.VarID) *dwarf.Var { +func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var { debug := fn.DebugInfo - n := debug.Vars[varID].(*Node) + n := debug.Vars[varID].(*ir.Node) var abbrev int switch n.Class() { - case PAUTO: + case ir.PAUTO: abbrev = dwarf.DW_ABRV_AUTO_LOCLIST - case PPARAM, PPARAMOUT: + case ir.PPARAM, ir.PPARAMOUT: abbrev = dwarf.DW_ABRV_PARAM_LOCLIST default: return nil @@ -773,7 +774,7 @@ func createComplexVar(fnsym *obj.LSym, fn *Func, varID ssa.VarID) *dwarf.Var { declpos := base.Ctxt.InnermostPos(n.Pos) dvar := &dwarf.Var{ Name: n.Sym.Name, - IsReturnValue: n.Class() == PPARAMOUT, + IsReturnValue: n.Class() == ir.PPARAMOUT, IsInlFormal: n.Name.InlFormal(), Abbrev: abbrev, Type: base.Ctxt.Lookup(typename), diff --git a/src/cmd/compile/internal/gc/pgen_test.go b/src/cmd/compile/internal/gc/pgen_test.go index 932ab47d026..9f1f00d46a5 100644 --- a/src/cmd/compile/internal/gc/pgen_test.go +++ b/src/cmd/compile/internal/gc/pgen_test.go @@ -5,6 +5,7 @@ package gc import ( + "cmd/compile/internal/ir" "cmd/compile/internal/types" "reflect" "sort" @@ -12,133 +13,133 @@ import ( ) func typeWithoutPointers() *types.Type { - t := types.New(TSTRUCT) - f := &types.Field{Type: types.New(TINT)} + t := types.New(types.TSTRUCT) + f := &types.Field{Type: types.New(types.TINT)} t.SetFields([]*types.Field{f}) return t } func typeWithPointers() *types.Type { - t := types.New(TSTRUCT) - f := &types.Field{Type: types.NewPtr(types.New(TINT))} + t := types.New(types.TSTRUCT) + f := &types.Field{Type: types.NewPtr(types.New(types.TINT))} t.SetFields([]*types.Field{f}) return t } -func markUsed(n *Node) *Node { +func markUsed(n *ir.Node) *ir.Node { n.Name.SetUsed(true) return n } -func markNeedZero(n *Node) *Node { +func markNeedZero(n *ir.Node) *ir.Node { n.Name.SetNeedzero(true) return n } // Test all code paths for cmpstackvarlt. func TestCmpstackvar(t *testing.T) { - nod := func(xoffset int64, t *types.Type, s *types.Sym, cl Class) *Node { + nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Node { if s == nil { s = &types.Sym{Name: "."} } - n := newname(s) + n := NewName(s) n.Type = t n.Xoffset = xoffset n.SetClass(cl) return n } testdata := []struct { - a, b *Node + a, b *ir.Node lt bool }{ { - nod(0, nil, nil, PAUTO), - nod(0, nil, nil, PFUNC), + nod(0, nil, nil, ir.PAUTO), + nod(0, nil, nil, ir.PFUNC), false, }, { - nod(0, nil, nil, PFUNC), - nod(0, nil, nil, PAUTO), + nod(0, nil, nil, ir.PFUNC), + nod(0, nil, nil, ir.PAUTO), true, }, { - nod(0, nil, nil, PFUNC), - nod(10, nil, nil, PFUNC), + nod(0, nil, nil, ir.PFUNC), + nod(10, nil, nil, ir.PFUNC), true, }, { - nod(20, nil, nil, PFUNC), - nod(10, nil, nil, PFUNC), + nod(20, nil, nil, ir.PFUNC), + nod(10, nil, nil, ir.PFUNC), false, }, { - nod(10, nil, nil, PFUNC), - nod(10, nil, nil, PFUNC), + nod(10, nil, nil, ir.PFUNC), + nod(10, nil, nil, ir.PFUNC), false, }, { - nod(10, nil, nil, PPARAM), - nod(20, nil, nil, PPARAMOUT), + nod(10, nil, nil, ir.PPARAM), + nod(20, nil, nil, ir.PPARAMOUT), true, }, { - nod(10, nil, nil, PPARAMOUT), - nod(20, nil, nil, PPARAM), + nod(10, nil, nil, ir.PPARAMOUT), + nod(20, nil, nil, ir.PPARAM), true, }, { - markUsed(nod(0, nil, nil, PAUTO)), - nod(0, nil, nil, PAUTO), + markUsed(nod(0, nil, nil, ir.PAUTO)), + nod(0, nil, nil, ir.PAUTO), true, }, { - nod(0, nil, nil, PAUTO), - markUsed(nod(0, nil, nil, PAUTO)), + nod(0, nil, nil, ir.PAUTO), + markUsed(nod(0, nil, nil, ir.PAUTO)), false, }, { - nod(0, typeWithoutPointers(), nil, PAUTO), - nod(0, typeWithPointers(), nil, PAUTO), + nod(0, typeWithoutPointers(), nil, ir.PAUTO), + nod(0, typeWithPointers(), nil, ir.PAUTO), false, }, { - nod(0, typeWithPointers(), nil, PAUTO), - nod(0, typeWithoutPointers(), nil, PAUTO), + nod(0, typeWithPointers(), nil, ir.PAUTO), + nod(0, typeWithoutPointers(), nil, ir.PAUTO), true, }, { - markNeedZero(nod(0, &types.Type{}, nil, PAUTO)), - nod(0, &types.Type{}, nil, PAUTO), + markNeedZero(nod(0, &types.Type{}, nil, ir.PAUTO)), + nod(0, &types.Type{}, nil, ir.PAUTO), true, }, { - nod(0, &types.Type{}, nil, PAUTO), - markNeedZero(nod(0, &types.Type{}, nil, PAUTO)), + nod(0, &types.Type{}, nil, ir.PAUTO), + markNeedZero(nod(0, &types.Type{}, nil, ir.PAUTO)), false, }, { - nod(0, &types.Type{Width: 1}, nil, PAUTO), - nod(0, &types.Type{Width: 2}, nil, PAUTO), + nod(0, &types.Type{Width: 1}, nil, ir.PAUTO), + nod(0, &types.Type{Width: 2}, nil, ir.PAUTO), false, }, { - nod(0, &types.Type{Width: 2}, nil, PAUTO), - nod(0, &types.Type{Width: 1}, nil, PAUTO), + nod(0, &types.Type{Width: 2}, nil, ir.PAUTO), + nod(0, &types.Type{Width: 1}, nil, ir.PAUTO), true, }, { - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), true, }, { - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), false, }, { - nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), false, }, } @@ -155,42 +156,42 @@ func TestCmpstackvar(t *testing.T) { } func TestStackvarSort(t *testing.T) { - nod := func(xoffset int64, t *types.Type, s *types.Sym, cl Class) *Node { - n := newname(s) + nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Node { + n := NewName(s) n.Type = t n.Xoffset = xoffset n.SetClass(cl) return n } - inp := []*Node{ - nod(0, &types.Type{}, &types.Sym{}, PFUNC), - nod(0, &types.Type{}, &types.Sym{}, PAUTO), - nod(0, &types.Type{}, &types.Sym{}, PFUNC), - nod(10, &types.Type{}, &types.Sym{}, PFUNC), - nod(20, &types.Type{}, &types.Sym{}, PFUNC), - markUsed(nod(0, &types.Type{}, &types.Sym{}, PAUTO)), - nod(0, typeWithoutPointers(), &types.Sym{}, PAUTO), - nod(0, &types.Type{}, &types.Sym{}, PAUTO), - markNeedZero(nod(0, &types.Type{}, &types.Sym{}, PAUTO)), - nod(0, &types.Type{Width: 1}, &types.Sym{}, PAUTO), - nod(0, &types.Type{Width: 2}, &types.Sym{}, PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, PAUTO), + inp := []*ir.Node{ + nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), + nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), + nod(10, &types.Type{}, &types.Sym{}, ir.PFUNC), + nod(20, &types.Type{}, &types.Sym{}, ir.PFUNC), + markUsed(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), + nod(0, typeWithoutPointers(), &types.Sym{}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), + markNeedZero(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), + nod(0, &types.Type{Width: 1}, &types.Sym{}, ir.PAUTO), + nod(0, &types.Type{Width: 2}, &types.Sym{}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), } - want := []*Node{ - nod(0, &types.Type{}, &types.Sym{}, PFUNC), - nod(0, &types.Type{}, &types.Sym{}, PFUNC), - nod(10, &types.Type{}, &types.Sym{}, PFUNC), - nod(20, &types.Type{}, &types.Sym{}, PFUNC), - markUsed(nod(0, &types.Type{}, &types.Sym{}, PAUTO)), - markNeedZero(nod(0, &types.Type{}, &types.Sym{}, PAUTO)), - nod(0, &types.Type{Width: 2}, &types.Sym{}, PAUTO), - nod(0, &types.Type{Width: 1}, &types.Sym{}, PAUTO), - nod(0, &types.Type{}, &types.Sym{}, PAUTO), - nod(0, &types.Type{}, &types.Sym{}, PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "abc"}, PAUTO), - nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, PAUTO), - nod(0, typeWithoutPointers(), &types.Sym{}, PAUTO), + want := []*ir.Node{ + nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), + nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), + nod(10, &types.Type{}, &types.Sym{}, ir.PFUNC), + nod(20, &types.Type{}, &types.Sym{}, ir.PFUNC), + markUsed(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), + markNeedZero(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), + nod(0, &types.Type{Width: 2}, &types.Sym{}, ir.PAUTO), + nod(0, &types.Type{Width: 1}, &types.Sym{}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), + nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), + nod(0, typeWithoutPointers(), &types.Sym{}, ir.PAUTO), } sort.Sort(byStackVar(inp)) if !reflect.DeepEqual(want, inp) { diff --git a/src/cmd/compile/internal/gc/phi.go b/src/cmd/compile/internal/gc/phi.go index 4beaa11a7e3..2a88d4a5b43 100644 --- a/src/cmd/compile/internal/gc/phi.go +++ b/src/cmd/compile/internal/gc/phi.go @@ -5,6 +5,7 @@ package gc import ( + "cmd/compile/internal/ir" "cmd/compile/internal/ssa" "cmd/compile/internal/types" "cmd/internal/src" @@ -40,11 +41,11 @@ func (s *state) insertPhis() { } type phiState struct { - s *state // SSA state - f *ssa.Func // function to work on - defvars []map[*Node]*ssa.Value // defined variables at end of each block + s *state // SSA state + f *ssa.Func // function to work on + defvars []map[*ir.Node]*ssa.Value // defined variables at end of each block - varnum map[*Node]int32 // variable numbering + varnum map[*ir.Node]int32 // variable numbering // properties of the dominator tree idom []*ssa.Block // dominator parents @@ -70,15 +71,15 @@ func (s *phiState) insertPhis() { // Find all the variables for which we need to match up reads & writes. // This step prunes any basic-block-only variables from consideration. // Generate a numbering for these variables. - s.varnum = map[*Node]int32{} - var vars []*Node + s.varnum = map[*ir.Node]int32{} + var vars []*ir.Node var vartypes []*types.Type for _, b := range s.f.Blocks { for _, v := range b.Values { if v.Op != ssa.OpFwdRef { continue } - var_ := v.Aux.(*Node) + var_ := v.Aux.(*ir.Node) // Optimization: look back 1 block for the definition. if len(b.Preds) == 1 { @@ -183,7 +184,7 @@ levels: } } -func (s *phiState) insertVarPhis(n int, var_ *Node, defs []*ssa.Block, typ *types.Type) { +func (s *phiState) insertVarPhis(n int, var_ *ir.Node, defs []*ssa.Block, typ *types.Type) { priq := &s.priq q := s.q queued := s.queued @@ -318,7 +319,7 @@ func (s *phiState) resolveFwdRefs() { if v.Op != ssa.OpFwdRef { continue } - n := s.varnum[v.Aux.(*Node)] + n := s.varnum[v.Aux.(*ir.Node)] v.Op = ssa.OpCopy v.Aux = nil v.AddArg(values[n]) @@ -432,11 +433,11 @@ func (s *sparseSet) clear() { // Variant to use for small functions. type simplePhiState struct { - s *state // SSA state - f *ssa.Func // function to work on - fwdrefs []*ssa.Value // list of FwdRefs to be processed - defvars []map[*Node]*ssa.Value // defined variables at end of each block - reachable []bool // which blocks are reachable + s *state // SSA state + f *ssa.Func // function to work on + fwdrefs []*ssa.Value // list of FwdRefs to be processed + defvars []map[*ir.Node]*ssa.Value // defined variables at end of each block + reachable []bool // which blocks are reachable } func (s *simplePhiState) insertPhis() { @@ -449,7 +450,7 @@ func (s *simplePhiState) insertPhis() { continue } s.fwdrefs = append(s.fwdrefs, v) - var_ := v.Aux.(*Node) + var_ := v.Aux.(*ir.Node) if _, ok := s.defvars[b.ID][var_]; !ok { s.defvars[b.ID][var_] = v // treat FwdDefs as definitions. } @@ -463,7 +464,7 @@ loop: v := s.fwdrefs[len(s.fwdrefs)-1] s.fwdrefs = s.fwdrefs[:len(s.fwdrefs)-1] b := v.Block - var_ := v.Aux.(*Node) + var_ := v.Aux.(*ir.Node) if b == s.f.Entry { // No variable should be live at entry. s.s.Fatalf("Value live at entry. It shouldn't be. func %s, node %v, value %v", s.f.Name, var_, v) @@ -511,7 +512,7 @@ loop: } // lookupVarOutgoing finds the variable's value at the end of block b. -func (s *simplePhiState) lookupVarOutgoing(b *ssa.Block, t *types.Type, var_ *Node, line src.XPos) *ssa.Value { +func (s *simplePhiState) lookupVarOutgoing(b *ssa.Block, t *types.Type, var_ *ir.Node, line src.XPos) *ssa.Value { for { if v := s.defvars[b.ID][var_]; v != nil { return v diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index da2298480ad..f0895884668 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -16,6 +16,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/ssa" "cmd/compile/internal/types" "cmd/internal/obj" @@ -100,10 +101,10 @@ type BlockEffects struct { // A collection of global state used by liveness analysis. type Liveness struct { - fn *Node + fn *ir.Node f *ssa.Func - vars []*Node - idx map[*Node]int32 + vars []*ir.Node + idx map[*ir.Node]int32 stkptrsize int64 be []BlockEffects @@ -205,20 +206,20 @@ 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 livenessShouldTrack(n *Node) bool { - return n.Op == ONAME && (n.Class() == PAUTO || n.Class() == PPARAM || n.Class() == PPARAMOUT) && n.Type.HasPointers() +func livenessShouldTrack(n *ir.Node) bool { + return n.Op == ir.ONAME && (n.Class() == ir.PAUTO || n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT) && n.Type.HasPointers() } // getvariables returns the list of on-stack variables that we need to track // and a map for looking up indices by *Node. -func getvariables(fn *Node) ([]*Node, map[*Node]int32) { - var vars []*Node +func getvariables(fn *ir.Node) ([]*ir.Node, map[*ir.Node]int32) { + var vars []*ir.Node for _, n := range fn.Func.Dcl { if livenessShouldTrack(n) { vars = append(vars, n) } } - idx := make(map[*Node]int32, len(vars)) + idx := make(map[*ir.Node]int32, len(vars)) for i, n := range vars { idx[n] = int32(i) } @@ -234,7 +235,7 @@ func (lv *Liveness) initcache() { for i, node := range lv.vars { switch node.Class() { - case PPARAM: + case ir.PPARAM: // A return instruction with a p.to is a tail return, which brings // the stack pointer back up (if it ever went down) and then jumps // to a new function entirely. That form of instruction must read @@ -243,7 +244,7 @@ func (lv *Liveness) initcache() { // function runs. lv.cache.tailuevar = append(lv.cache.tailuevar, int32(i)) - case PPARAMOUT: + case ir.PPARAMOUT: // All results are live at every return point. // Note that this point is after escaping return values // are copied back to the stack using their PAUTOHEAP references. @@ -271,7 +272,7 @@ const ( // 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 != ONAME { // cheapest checks first + if e == 0 || n == nil || n.Op != ir.ONAME { // cheapest checks first return -1, 0 } @@ -311,7 +312,7 @@ func (lv *Liveness) valueEffects(v *ssa.Value) (int32, liveEffect) { } // affectedNode returns the *Node affected by v -func affectedNode(v *ssa.Value) (*Node, ssa.SymEffect) { +func affectedNode(v *ssa.Value) (*ir.Node, ssa.SymEffect) { // Special cases. switch v.Op { case ssa.OpLoadReg: @@ -322,9 +323,9 @@ func affectedNode(v *ssa.Value) (*Node, ssa.SymEffect) { return n, ssa.SymWrite case ssa.OpVarLive: - return v.Aux.(*Node), ssa.SymRead + return v.Aux.(*ir.Node), ssa.SymRead case ssa.OpVarDef, ssa.OpVarKill: - return v.Aux.(*Node), ssa.SymWrite + return v.Aux.(*ir.Node), ssa.SymWrite case ssa.OpKeepAlive: n, _ := AutoVar(v.Args[0]) return n, ssa.SymRead @@ -339,7 +340,7 @@ func affectedNode(v *ssa.Value) (*Node, ssa.SymEffect) { case nil, *obj.LSym: // ok, but no node return nil, e - case *Node: + case *ir.Node: return a, e default: base.Fatalf("weird aux: %s", v.LongString()) @@ -355,7 +356,7 @@ type livenessFuncCache struct { // Constructs a new liveness structure used to hold the global state of the // liveness computation. The cfg argument is a slice of *BasicBlocks and the // vars argument is a slice of *Nodes. -func newliveness(fn *Node, f *ssa.Func, vars []*Node, idx map[*Node]int32, stkptrsize int64) *Liveness { +func newliveness(fn *ir.Node, f *ssa.Func, vars []*ir.Node, idx map[*ir.Node]int32, stkptrsize int64) *Liveness { lv := &Liveness{ fn: fn, f: f, @@ -416,20 +417,20 @@ func onebitwalktype1(t *types.Type, off int64, bv bvec) { } switch t.Etype { - case TPTR, TUNSAFEPTR, TFUNC, TCHAN, TMAP: + case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP: if off&int64(Widthptr-1) != 0 { base.Fatalf("onebitwalktype1: invalid alignment, %v", t) } bv.Set(int32(off / int64(Widthptr))) // pointer - case TSTRING: + case types.TSTRING: // struct { byte *str; intgo len; } if off&int64(Widthptr-1) != 0 { base.Fatalf("onebitwalktype1: invalid alignment, %v", t) } bv.Set(int32(off / int64(Widthptr))) //pointer in first slot - case TINTER: + case types.TINTER: // struct { Itab *tab; void *data; } // or, when isnilinter(t)==true: // struct { Type *type; void *data; } @@ -450,14 +451,14 @@ func onebitwalktype1(t *types.Type, off int64, bv bvec) { // well as scan itabs to update their itab._type fields). bv.Set(int32(off/int64(Widthptr) + 1)) // pointer in second slot - case TSLICE: + case types.TSLICE: // struct { byte *array; uintgo len; uintgo cap; } if off&int64(Widthptr-1) != 0 { base.Fatalf("onebitwalktype1: invalid TARRAY alignment, %v", t) } bv.Set(int32(off / int64(Widthptr))) // pointer in first slot (BitsPointer) - case TARRAY: + case types.TARRAY: elt := t.Elem() if elt.Width == 0 { // Short-circuit for #20739. @@ -468,7 +469,7 @@ func onebitwalktype1(t *types.Type, off int64, bv bvec) { off += elt.Width } - case TSTRUCT: + case types.TSTRUCT: for _, f := range t.Fields().Slice() { onebitwalktype1(f.Type, off+f.Offset, bv) } @@ -481,7 +482,7 @@ func onebitwalktype1(t *types.Type, off int64, bv bvec) { // 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. -func (lv *Liveness) pointerMap(liveout bvec, vars []*Node, args, locals bvec) { +func (lv *Liveness) pointerMap(liveout bvec, vars []*ir.Node, args, locals bvec) { for i := int32(0); ; i++ { i = liveout.Next(i) if i < 0 { @@ -489,10 +490,10 @@ func (lv *Liveness) pointerMap(liveout bvec, vars []*Node, args, locals bvec) { } node := vars[i] switch node.Class() { - case PAUTO: + case ir.PAUTO: onebitwalktype1(node.Type, node.Xoffset+lv.stkptrsize, locals) - case PPARAM, PPARAMOUT: + case ir.PPARAM, ir.PPARAMOUT: onebitwalktype1(node.Type, node.Xoffset, args) } } @@ -789,7 +790,7 @@ func (lv *Liveness) epilogue() { // don't need to keep the stack copy live? if lv.fn.Func.HasDefer() { for i, n := range lv.vars { - if n.Class() == PPARAMOUT { + if n.Class() == ir.PPARAMOUT { if n.Name.IsOutputParamHeapAddr() { // Just to be paranoid. Heap addresses are PAUTOs. base.Fatalf("variable %v both output param and heap output param", n) @@ -887,7 +888,7 @@ func (lv *Liveness) epilogue() { if !liveout.Get(int32(i)) { continue } - if n.Class() == PPARAM { + if n.Class() == ir.PPARAM { continue // ok } base.Fatalf("bad live variable at entry of %v: %L", lv.fn.Func.Nname, n) @@ -920,7 +921,7 @@ func (lv *Liveness) epilogue() { // the only things that can possibly be live are the // input parameters. for j, n := range lv.vars { - if n.Class() != PPARAM && lv.stackMaps[0].Get(int32(j)) { + if n.Class() != ir.PPARAM && lv.stackMaps[0].Get(int32(j)) { lv.f.Fatalf("%v %L recorded as live on entry", lv.fn.Func.Nname, n) } } @@ -967,7 +968,7 @@ func (lv *Liveness) compact(b *ssa.Block) { } func (lv *Liveness) showlive(v *ssa.Value, live bvec) { - if base.Flag.Live == 0 || lv.fn.funcname() == "init" || strings.HasPrefix(lv.fn.funcname(), ".") { + if base.Flag.Live == 0 || ir.FuncName(lv.fn) == "init" || strings.HasPrefix(ir.FuncName(lv.fn), ".") { return } if !(v == nil || v.Op.IsCall()) { @@ -986,7 +987,7 @@ func (lv *Liveness) showlive(v *ssa.Value, live bvec) { s := "live at " if v == nil { - s += fmt.Sprintf("entry to %s:", lv.fn.funcname()) + s += fmt.Sprintf("entry to %s:", ir.FuncName(lv.fn)) } else if sym, ok := v.Aux.(*ssa.AuxCall); ok && sym.Fn != nil { fn := sym.Fn.Name if pos := strings.Index(fn, "."); pos >= 0 { @@ -1051,7 +1052,7 @@ func (lv *Liveness) printeffect(printed bool, name string, pos int32, x bool) bo // This format synthesizes the information used during the multiple passes // into a single presentation. func (lv *Liveness) printDebug() { - fmt.Printf("liveness: %s\n", lv.fn.funcname()) + fmt.Printf("liveness: %s\n", ir.FuncName(lv.fn)) for i, b := range lv.f.Blocks { if i > 0 { @@ -1163,10 +1164,10 @@ func (lv *Liveness) emit() (argsSym, liveSym *obj.LSym) { // Size args bitmaps to be just large enough to hold the largest pointer. // First, find the largest Xoffset node we care about. // (Nodes without pointers aren't in lv.vars; see livenessShouldTrack.) - var maxArgNode *Node + var maxArgNode *ir.Node for _, n := range lv.vars { switch n.Class() { - case PPARAM, PPARAMOUT: + case ir.PPARAM, ir.PPARAMOUT: if maxArgNode == nil || n.Xoffset > maxArgNode.Xoffset { maxArgNode = n } @@ -1265,7 +1266,7 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap { } // Emit the live pointer map data structures - ls := e.curfn.Func.lsym + ls := e.curfn.Func.LSym fninfo := ls.Func() fninfo.GCArgs, fninfo.GCLocals = lv.emit() @@ -1300,16 +1301,16 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap { func isfat(t *types.Type) bool { if t != nil { switch t.Etype { - case TSLICE, TSTRING, - TINTER: // maybe remove later + case types.TSLICE, types.TSTRING, + types.TINTER: // maybe remove later return true - case TARRAY: + case types.TARRAY: // Array of 1 element, check if element is fat if t.NumElem() == 1 { return isfat(t.Elem()) } return true - case TSTRUCT: + case types.TSTRUCT: // Struct with 1 field, check if field is fat if t.NumFields() == 1 { return isfat(t.Field(0).Type) diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go index 20b4bc583b0..d92749589f7 100644 --- a/src/cmd/compile/internal/gc/racewalk.go +++ b/src/cmd/compile/internal/gc/racewalk.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/src" "cmd/internal/sys" @@ -59,8 +60,8 @@ func ispkgin(pkgs []string) bool { return false } -func instrument(fn *Node) { - if fn.Func.Pragma&Norace != 0 { +func instrument(fn *ir.Node) { + if fn.Func.Pragma&ir.Norace != 0 { return } @@ -82,8 +83,8 @@ func instrument(fn *Node) { // This only works for amd64. This will not // work on arm or others that might support // race in the future. - nodpc := nodfp.copy() - nodpc.Type = types.Types[TUINTPTR] + nodpc := ir.Copy(nodfp) + nodpc.Type = types.Types[types.TUINTPTR] nodpc.Xoffset = int64(-Widthptr) fn.Func.Dcl = append(fn.Func.Dcl, nodpc) fn.Func.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc)) diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go index 568c5138ec3..edaec21f920 100644 --- a/src/cmd/compile/internal/gc/range.go +++ b/src/cmd/compile/internal/gc/range.go @@ -6,13 +6,14 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/sys" "unicode/utf8" ) // range -func typecheckrange(n *Node) { +func typecheckrange(n *ir.Node) { // Typechecking order is important here: // 0. first typecheck range expression (slice/map/chan), // it is evaluated only once and so logically it is not part of the loop. @@ -38,7 +39,7 @@ func typecheckrange(n *Node) { decldepth-- } -func typecheckrangeExpr(n *Node) { +func typecheckrangeExpr(n *ir.Node) { n.Right = typecheck(n.Right, ctxExpr) t := n.Right.Type @@ -65,15 +66,15 @@ func typecheckrangeExpr(n *Node) { base.ErrorfAt(n.Pos, "cannot range over %L", n.Right) return - case TARRAY, TSLICE: - t1 = types.Types[TINT] + case types.TARRAY, types.TSLICE: + t1 = types.Types[types.TINT] t2 = t.Elem() - case TMAP: + case types.TMAP: t1 = t.Key() t2 = t.Elem() - case TCHAN: + case types.TCHAN: if !t.ChanDir().CanRecv() { base.ErrorfAt(n.Pos, "invalid operation: range %v (receive from send-only type %v)", n.Right, n.Right.Type) return @@ -85,8 +86,8 @@ func typecheckrangeExpr(n *Node) { toomany = true } - case TSTRING: - t1 = types.Types[TINT] + case types.TSTRING: + t1 = types.Types[types.TINT] t2 = types.Runetype } @@ -94,7 +95,7 @@ func typecheckrangeExpr(n *Node) { base.ErrorfAt(n.Pos, "too many variables in range") } - var v1, v2 *Node + var v1, v2 *ir.Node if n.List.Len() != 0 { v1 = n.List.First() } @@ -106,7 +107,7 @@ func typecheckrangeExpr(n *Node) { // "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 v2.isBlank() { + if ir.IsBlank(v2) { if v1 != nil { n.List.Set1(v1) } @@ -117,7 +118,7 @@ func typecheckrangeExpr(n *Node) { if v1.Name != nil && v1.Name.Defn == n { v1.Type = t1 } else if v1.Type != nil { - if op, why := assignop(t1, v1.Type); op == OXXX { + 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) } } @@ -128,7 +129,7 @@ func typecheckrangeExpr(n *Node) { if v2.Name != nil && v2.Name.Defn == n { v2.Type = t2 } else if v2.Type != nil { - if op, why := assignop(t2, v2.Type); op == OXXX { + 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) } } @@ -156,7 +157,7 @@ func cheapComputableIndex(width int64) bool { // simpler forms. The result must be assigned back to n. // Node n may also be modified in place, and may also be // the returned node. -func walkrange(n *Node) *Node { +func walkrange(n *ir.Node) *ir.Node { if isMapClear(n) { m := n.Right lno := setlineno(m) @@ -178,7 +179,7 @@ func walkrange(n *Node) *Node { lno := setlineno(a) n.Right = nil - var v1, v2 *Node + var v1, v2 *ir.Node l := n.List.Len() if l > 0 { v1 = n.List.First() @@ -188,11 +189,11 @@ func walkrange(n *Node) *Node { v2 = n.List.Second() } - if v2.isBlank() { + if ir.IsBlank(v2) { v2 = nil } - if v1.isBlank() && v2 == nil { + if ir.IsBlank(v1) && v2 == nil { v1 = nil } @@ -204,17 +205,17 @@ func walkrange(n *Node) *Node { // to avoid erroneous processing by racewalk. n.List.Set(nil) - var ifGuard *Node + var ifGuard *ir.Node - translatedLoopOp := OFOR + translatedLoopOp := ir.OFOR - var body []*Node - var init []*Node + var body []*ir.Node + var init []*ir.Node switch t.Etype { default: base.Fatalf("walkrange") - case TARRAY, TSLICE: + case types.TARRAY, types.TSLICE: if arrayClear(n, v1, v2, a) { base.Pos = lno return n @@ -223,14 +224,14 @@ func walkrange(n *Node) *Node { // order.stmt arranged for a copy of the array/slice variable if needed. ha := a - hv1 := temp(types.Types[TINT]) - hn := temp(types.Types[TINT]) + hv1 := temp(types.Types[types.TINT]) + hn := temp(types.Types[types.TINT]) - init = append(init, nod(OAS, hv1, nil)) - init = append(init, nod(OAS, hn, nod(OLEN, ha, nil))) + init = append(init, ir.Nod(ir.OAS, hv1, nil)) + init = append(init, ir.Nod(ir.OAS, hn, ir.Nod(ir.OLEN, ha, nil))) - n.Left = nod(OLT, hv1, hn) - n.Right = nod(OAS, hv1, nod(OADD, hv1, nodintconst(1))) + n.Left = ir.Nod(ir.OLT, hv1, hn) + n.Right = ir.Nod(ir.OAS, hv1, ir.Nod(ir.OADD, hv1, nodintconst(1))) // for range ha { body } if v1 == nil { @@ -239,21 +240,21 @@ func walkrange(n *Node) *Node { // for v1 := range ha { body } if v2 == nil { - body = []*Node{nod(OAS, v1, hv1)} + body = []*ir.Node{ir.Nod(ir.OAS, v1, hv1)} break } // for v1, v2 := range ha { body } if cheapComputableIndex(n.Type.Elem().Width) { // v1, v2 = hv1, ha[hv1] - tmp := nod(OINDEX, ha, hv1) + tmp := ir.Nod(ir.OINDEX, ha, hv1) tmp.SetBounded(true) // Use OAS2 to correctly handle assignments // of the form "v1, a[v1] := range". - a := nod(OAS2, nil, nil) + a := ir.Nod(ir.OAS2, nil, nil) a.List.Set2(v1, v2) a.Rlist.Set2(hv1, tmp) - body = []*Node{a} + body = []*ir.Node{a} break } @@ -269,20 +270,20 @@ func walkrange(n *Node) *Node { // TODO(austin): OFORUNTIL inhibits bounds-check // elimination on the index variable (see #20711). // Enhance the prove pass to understand this. - ifGuard = nod(OIF, nil, nil) - ifGuard.Left = nod(OLT, hv1, hn) - translatedLoopOp = OFORUNTIL + ifGuard = ir.Nod(ir.OIF, nil, nil) + ifGuard.Left = ir.Nod(ir.OLT, hv1, hn) + translatedLoopOp = ir.OFORUNTIL hp := temp(types.NewPtr(n.Type.Elem())) - tmp := nod(OINDEX, ha, nodintconst(0)) + tmp := ir.Nod(ir.OINDEX, ha, nodintconst(0)) tmp.SetBounded(true) - init = append(init, nod(OAS, hp, nod(OADDR, tmp, nil))) + init = append(init, ir.Nod(ir.OAS, hp, ir.Nod(ir.OADDR, tmp, nil))) // Use OAS2 to correctly handle assignments // of the form "v1, a[v1] := range". - a := nod(OAS2, nil, nil) + a := ir.Nod(ir.OAS2, nil, nil) a.List.Set2(v1, v2) - a.Rlist.Set2(hv1, nod(ODEREF, hp, nil)) + a.Rlist.Set2(hv1, ir.Nod(ir.ODEREF, hp, nil)) body = append(body, a) // Advance pointer as part of the late increment. @@ -290,11 +291,11 @@ func walkrange(n *Node) *Node { // This runs *after* the condition check, so we know // advancing the pointer is safe and won't go past the // end of the allocation. - a = nod(OAS, hp, addptr(hp, t.Elem().Width)) + a = ir.Nod(ir.OAS, hp, addptr(hp, t.Elem().Width)) a = typecheck(a, ctxStmt) n.List.Set1(a) - case TMAP: + case types.TMAP: // order.stmt allocated the iterator for us. // we only use a once, so no copy needed. ha := a @@ -308,29 +309,29 @@ func walkrange(n *Node) *Node { fn := syslook("mapiterinit") fn = substArgTypes(fn, t.Key(), t.Elem(), th) - init = append(init, mkcall1(fn, nil, nil, typename(t), ha, nod(OADDR, hit, nil))) - n.Left = nod(ONE, nodSym(ODOT, hit, keysym), nodnil()) + init = append(init, mkcall1(fn, nil, nil, typename(t), ha, ir.Nod(ir.OADDR, hit, nil))) + n.Left = ir.Nod(ir.ONE, nodSym(ir.ODOT, hit, keysym), nodnil()) fn = syslook("mapiternext") fn = substArgTypes(fn, th) - n.Right = mkcall1(fn, nil, nil, nod(OADDR, hit, nil)) + n.Right = mkcall1(fn, nil, nil, ir.Nod(ir.OADDR, hit, nil)) - key := nodSym(ODOT, hit, keysym) - key = nod(ODEREF, key, nil) + key := nodSym(ir.ODOT, hit, keysym) + key = ir.Nod(ir.ODEREF, key, nil) if v1 == nil { body = nil } else if v2 == nil { - body = []*Node{nod(OAS, v1, key)} + body = []*ir.Node{ir.Nod(ir.OAS, v1, key)} } else { - elem := nodSym(ODOT, hit, elemsym) - elem = nod(ODEREF, elem, nil) - a := nod(OAS2, nil, nil) + elem := nodSym(ir.ODOT, hit, elemsym) + elem = ir.Nod(ir.ODEREF, elem, nil) + a := ir.Nod(ir.OAS2, nil, nil) a.List.Set2(v1, v2) a.Rlist.Set2(key, elem) - body = []*Node{a} + body = []*ir.Node{a} } - case TCHAN: + case types.TCHAN: // order.stmt arranged for a copy of the channel variable. ha := a @@ -339,27 +340,27 @@ func walkrange(n *Node) *Node { hv1 := temp(t.Elem()) hv1.SetTypecheck(1) if t.Elem().HasPointers() { - init = append(init, nod(OAS, hv1, nil)) + init = append(init, ir.Nod(ir.OAS, hv1, nil)) } - hb := temp(types.Types[TBOOL]) + hb := temp(types.Types[types.TBOOL]) - n.Left = nod(ONE, hb, nodbool(false)) - a := nod(OAS2RECV, nil, nil) + n.Left = ir.Nod(ir.ONE, hb, nodbool(false)) + a := ir.Nod(ir.OAS2RECV, nil, nil) a.SetTypecheck(1) a.List.Set2(hv1, hb) - a.Right = nod(ORECV, ha, nil) + a.Right = ir.Nod(ir.ORECV, ha, nil) n.Left.Ninit.Set1(a) if v1 == nil { body = nil } else { - body = []*Node{nod(OAS, v1, hv1)} + body = []*ir.Node{ir.Nod(ir.OAS, v1, hv1)} } // Zero hv1. This prevents hv1 from being the sole, inaccessible // reference to an otherwise GC-able value during the next channel receive. // See issue 15281. - body = append(body, nod(OAS, hv1, nil)) + body = append(body, ir.Nod(ir.OAS, hv1, nil)) - case TSTRING: + case types.TSTRING: // Transform string range statements like "for v1, v2 = range a" into // // ha := a @@ -378,35 +379,35 @@ func walkrange(n *Node) *Node { // order.stmt arranged for a copy of the string variable. ha := a - hv1 := temp(types.Types[TINT]) - hv1t := temp(types.Types[TINT]) + hv1 := temp(types.Types[types.TINT]) + hv1t := temp(types.Types[types.TINT]) hv2 := temp(types.Runetype) // hv1 := 0 - init = append(init, nod(OAS, hv1, nil)) + init = append(init, ir.Nod(ir.OAS, hv1, nil)) // hv1 < len(ha) - n.Left = nod(OLT, hv1, nod(OLEN, ha, nil)) + n.Left = ir.Nod(ir.OLT, hv1, ir.Nod(ir.OLEN, ha, nil)) if v1 != nil { // hv1t = hv1 - body = append(body, nod(OAS, hv1t, hv1)) + body = append(body, ir.Nod(ir.OAS, hv1t, hv1)) } // hv2 := rune(ha[hv1]) - nind := nod(OINDEX, ha, hv1) + nind := ir.Nod(ir.OINDEX, ha, hv1) nind.SetBounded(true) - body = append(body, nod(OAS, hv2, conv(nind, types.Runetype))) + body = append(body, ir.Nod(ir.OAS, hv2, conv(nind, types.Runetype))) // if hv2 < utf8.RuneSelf - nif := nod(OIF, nil, nil) - nif.Left = nod(OLT, hv2, nodintconst(utf8.RuneSelf)) + nif := ir.Nod(ir.OIF, nil, nil) + nif.Left = ir.Nod(ir.OLT, hv2, nodintconst(utf8.RuneSelf)) // hv1++ - nif.Nbody.Set1(nod(OAS, hv1, nod(OADD, hv1, nodintconst(1)))) + nif.Nbody.Set1(ir.Nod(ir.OAS, hv1, ir.Nod(ir.OADD, hv1, nodintconst(1)))) // } else { - eif := nod(OAS2, nil, nil) + eif := ir.Nod(ir.OAS2, nil, nil) nif.Rlist.Set1(eif) // hv2, hv1 = decoderune(ha, hv1) @@ -419,13 +420,13 @@ func walkrange(n *Node) *Node { if v1 != nil { if v2 != nil { // v1, v2 = hv1t, hv2 - a := nod(OAS2, nil, nil) + a := ir.Nod(ir.OAS2, nil, nil) a.List.Set2(v1, v2) a.Rlist.Set2(hv1t, hv2) body = append(body, a) } else { // v1 = hv1t - body = append(body, nod(OAS, v1, hv1t)) + body = append(body, ir.Nod(ir.OAS, v1, hv1t)) } } } @@ -466,17 +467,17 @@ func walkrange(n *Node) *Node { // } // // where == for keys of map m is reflexive. -func isMapClear(n *Node) bool { +func isMapClear(n *ir.Node) bool { if base.Flag.N != 0 || instrumenting { return false } - if n.Op != ORANGE || n.Type.Etype != TMAP || n.List.Len() != 1 { + if n.Op != ir.ORANGE || n.Type.Etype != types.TMAP || n.List.Len() != 1 { return false } k := n.List.First() - if k == nil || k.isBlank() { + if k == nil || ir.IsBlank(k) { return false } @@ -490,7 +491,7 @@ func isMapClear(n *Node) bool { } stmt := n.Nbody.First() // only stmt in body - if stmt == nil || stmt.Op != ODELETE { + if stmt == nil || stmt.Op != ir.ODELETE { return false } @@ -508,7 +509,7 @@ func isMapClear(n *Node) bool { } // mapClear constructs a call to runtime.mapclear for the map m. -func mapClear(m *Node) *Node { +func mapClear(m *ir.Node) *ir.Node { t := m.Type // instantiate mapclear(typ *type, hmap map[any]any) @@ -533,7 +534,7 @@ func mapClear(m *Node) *Node { // in which the evaluation of a is side-effect-free. // // Parameters are as in walkrange: "for v1, v2 = range a". -func arrayClear(n, v1, v2, a *Node) bool { +func arrayClear(n, v1, v2, a *ir.Node) bool { if base.Flag.N != 0 || instrumenting { return false } @@ -547,7 +548,7 @@ func arrayClear(n, v1, v2, a *Node) bool { } stmt := n.Nbody.First() // only stmt in body - if stmt.Op != OAS || stmt.Left.Op != OINDEX { + if stmt.Op != ir.OAS || stmt.Left.Op != ir.OINDEX { return false } @@ -567,32 +568,32 @@ func arrayClear(n, v1, v2, a *Node) bool { // memclr{NoHeap,Has}Pointers(hp, hn) // i = len(a) - 1 // } - n.Op = OIF + n.Op = ir.OIF n.Nbody.Set(nil) - n.Left = nod(ONE, nod(OLEN, a, nil), nodintconst(0)) + n.Left = ir.Nod(ir.ONE, ir.Nod(ir.OLEN, a, nil), nodintconst(0)) // hp = &a[0] - hp := temp(types.Types[TUNSAFEPTR]) + hp := temp(types.Types[types.TUNSAFEPTR]) - tmp := nod(OINDEX, a, nodintconst(0)) + tmp := ir.Nod(ir.OINDEX, a, nodintconst(0)) tmp.SetBounded(true) - tmp = nod(OADDR, tmp, nil) - tmp = convnop(tmp, types.Types[TUNSAFEPTR]) - n.Nbody.Append(nod(OAS, hp, tmp)) + tmp = ir.Nod(ir.OADDR, tmp, nil) + tmp = convnop(tmp, types.Types[types.TUNSAFEPTR]) + n.Nbody.Append(ir.Nod(ir.OAS, hp, tmp)) // hn = len(a) * sizeof(elem(a)) - hn := temp(types.Types[TUINTPTR]) + hn := temp(types.Types[types.TUINTPTR]) - tmp = nod(OLEN, a, nil) - tmp = nod(OMUL, tmp, nodintconst(elemsize)) - tmp = conv(tmp, types.Types[TUINTPTR]) - n.Nbody.Append(nod(OAS, hn, tmp)) + tmp = ir.Nod(ir.OLEN, a, nil) + tmp = ir.Nod(ir.OMUL, tmp, nodintconst(elemsize)) + tmp = conv(tmp, types.Types[types.TUINTPTR]) + n.Nbody.Append(ir.Nod(ir.OAS, hn, tmp)) - var fn *Node + var fn *ir.Node if a.Type.Elem().HasPointers() { // memclrHasPointers(hp, hn) - Curfn.Func.setWBPos(stmt.Pos) + Curfn.Func.SetWBPos(stmt.Pos) fn = mkcall("memclrHasPointers", nil, nil, hp, hn) } else { // memclrNoHeapPointers(hp, hn) @@ -602,7 +603,7 @@ func arrayClear(n, v1, v2, a *Node) bool { n.Nbody.Append(fn) // i = len(a) - 1 - v1 = nod(OAS, v1, nod(OSUB, nod(OLEN, a, nil), nodintconst(1))) + v1 = ir.Nod(ir.OAS, v1, ir.Nod(ir.OSUB, ir.Nod(ir.OLEN, a, nil), nodintconst(1))) n.Nbody.Append(v1) @@ -614,15 +615,15 @@ func arrayClear(n, v1, v2, a *Node) bool { } // addptr returns (*T)(uintptr(p) + n). -func addptr(p *Node, n int64) *Node { +func addptr(p *ir.Node, n int64) *ir.Node { t := p.Type - p = nod(OCONVNOP, p, nil) - p.Type = types.Types[TUINTPTR] + p = ir.Nod(ir.OCONVNOP, p, nil) + p.Type = types.Types[types.TUINTPTR] - p = nod(OADD, p, nodintconst(n)) + p = ir.Nod(ir.OADD, p, nodintconst(n)) - p = nod(OCONVNOP, p, nil) + p = ir.Nod(ir.OCONVNOP, p, nil) p.Type = t return p diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 456903e7d75..34047bfefa6 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/gcprog" "cmd/internal/obj" @@ -84,7 +85,7 @@ func bmap(t *types.Type) *types.Type { return t.MapType().Bucket } - bucket := types.New(TSTRUCT) + bucket := types.New(types.TSTRUCT) keytype := t.Key() elemtype := t.Elem() dowidth(keytype) @@ -99,7 +100,7 @@ func bmap(t *types.Type) *types.Type { field := make([]*types.Field, 0, 5) // The first field is: uint8 topbits[BUCKETSIZE]. - arr := types.NewArray(types.Types[TUINT8], BUCKETSIZE) + arr := types.NewArray(types.Types[types.TUINT8], BUCKETSIZE) field = append(field, makefield("topbits", arr)) arr = types.NewArray(keytype, BUCKETSIZE) @@ -120,7 +121,7 @@ func bmap(t *types.Type) *types.Type { // See comment on hmap.overflow in runtime/map.go. otyp := types.NewPtr(bucket) if !elemtype.HasPointers() && !keytype.HasPointers() { - otyp = types.Types[TUINTPTR] + otyp = types.Types[types.TUINTPTR] } overflow := makefield("overflow", otyp) field = append(field, overflow) @@ -209,18 +210,18 @@ func hmap(t *types.Type) *types.Type { // } // must match runtime/map.go:hmap. fields := []*types.Field{ - makefield("count", types.Types[TINT]), - makefield("flags", types.Types[TUINT8]), - makefield("B", types.Types[TUINT8]), - makefield("noverflow", types.Types[TUINT16]), - makefield("hash0", types.Types[TUINT32]), // Used in walk.go for OMAKEMAP. - makefield("buckets", types.NewPtr(bmap)), // Used in walk.go for OMAKEMAP. + makefield("count", types.Types[types.TINT]), + makefield("flags", types.Types[types.TUINT8]), + makefield("B", types.Types[types.TUINT8]), + makefield("noverflow", types.Types[types.TUINT16]), + makefield("hash0", types.Types[types.TUINT32]), // Used in walk.go for OMAKEMAP. + makefield("buckets", types.NewPtr(bmap)), // Used in walk.go for OMAKEMAP. makefield("oldbuckets", types.NewPtr(bmap)), - makefield("nevacuate", types.Types[TUINTPTR]), - makefield("extra", types.Types[TUNSAFEPTR]), + makefield("nevacuate", types.Types[types.TUINTPTR]), + makefield("extra", types.Types[types.TUNSAFEPTR]), } - hmap := types.New(TSTRUCT) + hmap := types.New(types.TSTRUCT) hmap.SetNoalg(true) hmap.SetFields(fields) dowidth(hmap) @@ -268,23 +269,23 @@ func hiter(t *types.Type) *types.Type { fields := []*types.Field{ makefield("key", types.NewPtr(t.Key())), // Used in range.go for TMAP. makefield("elem", types.NewPtr(t.Elem())), // Used in range.go for TMAP. - makefield("t", types.Types[TUNSAFEPTR]), + makefield("t", types.Types[types.TUNSAFEPTR]), makefield("h", types.NewPtr(hmap)), makefield("buckets", types.NewPtr(bmap)), makefield("bptr", types.NewPtr(bmap)), - makefield("overflow", types.Types[TUNSAFEPTR]), - makefield("oldoverflow", types.Types[TUNSAFEPTR]), - makefield("startBucket", types.Types[TUINTPTR]), - makefield("offset", types.Types[TUINT8]), - makefield("wrapped", types.Types[TBOOL]), - makefield("B", types.Types[TUINT8]), - makefield("i", types.Types[TUINT8]), - makefield("bucket", types.Types[TUINTPTR]), - makefield("checkBucket", types.Types[TUINTPTR]), + makefield("overflow", types.Types[types.TUNSAFEPTR]), + makefield("oldoverflow", types.Types[types.TUNSAFEPTR]), + makefield("startBucket", types.Types[types.TUINTPTR]), + makefield("offset", types.Types[types.TUINT8]), + makefield("wrapped", types.Types[types.TBOOL]), + makefield("B", types.Types[types.TUINT8]), + makefield("i", types.Types[types.TUINT8]), + makefield("bucket", types.Types[types.TUINTPTR]), + makefield("checkBucket", types.Types[types.TUINTPTR]), } // build iterator struct holding the above fields - hiter := types.New(TSTRUCT) + hiter := types.New(types.TSTRUCT) hiter.SetNoalg(true) hiter.SetFields(fields) dowidth(hiter) @@ -303,35 +304,35 @@ func deferstruct(stksize int64) *types.Type { // Unlike the global makefield function, this one needs to set Pkg // because these types might be compared (in SSA CSE sorting). // TODO: unify this makefield and the global one above. - sym := &types.Sym{Name: name, Pkg: localpkg} + sym := &types.Sym{Name: name, Pkg: ir.LocalPkg} return types.NewField(src.NoXPos, sym, typ) } - argtype := types.NewArray(types.Types[TUINT8], stksize) + argtype := types.NewArray(types.Types[types.TUINT8], stksize) argtype.Width = stksize argtype.Align = 1 // These fields must match the ones in runtime/runtime2.go:_defer and // cmd/compile/internal/gc/ssa.go:(*state).call. fields := []*types.Field{ - makefield("siz", types.Types[TUINT32]), - makefield("started", types.Types[TBOOL]), - makefield("heap", types.Types[TBOOL]), - makefield("openDefer", types.Types[TBOOL]), - makefield("sp", types.Types[TUINTPTR]), - makefield("pc", types.Types[TUINTPTR]), + makefield("siz", types.Types[types.TUINT32]), + makefield("started", types.Types[types.TBOOL]), + makefield("heap", types.Types[types.TBOOL]), + makefield("openDefer", types.Types[types.TBOOL]), + makefield("sp", types.Types[types.TUINTPTR]), + makefield("pc", types.Types[types.TUINTPTR]), // Note: the types here don't really matter. Defer structures // are always scanned explicitly during stack copying and GC, // so we make them uintptr type even though they are real pointers. - makefield("fn", types.Types[TUINTPTR]), - makefield("_panic", types.Types[TUINTPTR]), - makefield("link", types.Types[TUINTPTR]), - makefield("framepc", types.Types[TUINTPTR]), - makefield("varp", types.Types[TUINTPTR]), - makefield("fd", types.Types[TUINTPTR]), + makefield("fn", types.Types[types.TUINTPTR]), + makefield("_panic", types.Types[types.TUINTPTR]), + makefield("link", types.Types[types.TUINTPTR]), + makefield("framepc", types.Types[types.TUINTPTR]), + makefield("varp", types.Types[types.TUINTPTR]), + makefield("fd", types.Types[types.TUINTPTR]), makefield("args", argtype), } // build struct holding the above fields - s := types.New(TSTRUCT) + s := types.New(types.TSTRUCT) s.SetNoalg(true) s.SetFields(fields) s.Width = widstruct(s, s, 0, 1) @@ -346,7 +347,7 @@ func methodfunc(f *types.Type, receiver *types.Type) *types.Type { if receiver != nil { inLen++ } - in := make([]*Node, 0, inLen) + in := make([]*ir.Node, 0, inLen) if receiver != nil { d := anonfield(receiver) @@ -360,7 +361,7 @@ func methodfunc(f *types.Type, receiver *types.Type) *types.Type { } outLen := f.Results().Fields().Len() - out := make([]*Node, 0, outLen) + out := make([]*ir.Node, 0, outLen) for _, t := range f.Results().Fields().Slice() { d := anonfield(t.Type) out = append(out, d) @@ -447,7 +448,7 @@ func methods(t *types.Type) []*Sig { func imethods(t *types.Type) []*Sig { var methods []*Sig for _, f := range t.Fields().Slice() { - if f.Type.Etype != TFUNC || f.Sym == nil { + if f.Type.Etype != types.TFUNC || f.Sym == nil { continue } if f.Sym.IsBlank() { @@ -494,7 +495,7 @@ func dimportpath(p *types.Pkg) { } str := p.Path - if p == localpkg { + if p == ir.LocalPkg { // Note: myimportpath != "", or else dgopkgpath won't call dimportpath. str = base.Ctxt.Pkgpath } @@ -511,7 +512,7 @@ func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int { return duintptr(s, ot, 0) } - if pkg == localpkg && base.Ctxt.Pkgpath == "" { + if pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "" { // If we don't know the full import path of the package being compiled // (i.e. -p was not passed on the compiler command line), emit a reference to // type..importpath.""., which the linker will rewrite using the correct import path. @@ -530,7 +531,7 @@ func dgopkgpathOff(s *obj.LSym, ot int, pkg *types.Pkg) int { if pkg == nil { return duint32(s, ot, 0) } - if pkg == localpkg && base.Ctxt.Pkgpath == "" { + if pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "" { // If we don't know the full import path of the package being compiled // (i.e. -p was not passed on the compiler command line), emit a reference to // type..importpath.""., which the linker will rewrite using the correct import path. @@ -674,7 +675,7 @@ func typePkg(t *types.Type) *types.Pkg { tsym := t.Sym if tsym == nil { switch t.Etype { - case TARRAY, TSLICE, TPTR, TCHAN: + case types.TARRAY, types.TSLICE, types.TPTR, types.TCHAN: if t.Elem() != nil { tsym = t.Elem().Sym } @@ -717,32 +718,32 @@ func dmethodptrOff(s *obj.LSym, ot int, x *obj.LSym) int { } var kinds = []int{ - TINT: objabi.KindInt, - TUINT: objabi.KindUint, - TINT8: objabi.KindInt8, - TUINT8: objabi.KindUint8, - TINT16: objabi.KindInt16, - TUINT16: objabi.KindUint16, - TINT32: objabi.KindInt32, - TUINT32: objabi.KindUint32, - TINT64: objabi.KindInt64, - TUINT64: objabi.KindUint64, - TUINTPTR: objabi.KindUintptr, - TFLOAT32: objabi.KindFloat32, - TFLOAT64: objabi.KindFloat64, - TBOOL: objabi.KindBool, - TSTRING: objabi.KindString, - TPTR: objabi.KindPtr, - TSTRUCT: objabi.KindStruct, - TINTER: objabi.KindInterface, - TCHAN: objabi.KindChan, - TMAP: objabi.KindMap, - TARRAY: objabi.KindArray, - TSLICE: objabi.KindSlice, - TFUNC: objabi.KindFunc, - TCOMPLEX64: objabi.KindComplex64, - TCOMPLEX128: objabi.KindComplex128, - TUNSAFEPTR: objabi.KindUnsafePointer, + types.TINT: objabi.KindInt, + types.TUINT: objabi.KindUint, + types.TINT8: objabi.KindInt8, + types.TUINT8: objabi.KindUint8, + types.TINT16: objabi.KindInt16, + types.TUINT16: objabi.KindUint16, + types.TINT32: objabi.KindInt32, + types.TUINT32: objabi.KindUint32, + types.TINT64: objabi.KindInt64, + types.TUINT64: objabi.KindUint64, + types.TUINTPTR: objabi.KindUintptr, + types.TFLOAT32: objabi.KindFloat32, + types.TFLOAT64: objabi.KindFloat64, + types.TBOOL: objabi.KindBool, + types.TSTRING: objabi.KindString, + types.TPTR: objabi.KindPtr, + types.TSTRUCT: objabi.KindStruct, + types.TINTER: objabi.KindInterface, + types.TCHAN: objabi.KindChan, + types.TMAP: objabi.KindMap, + types.TARRAY: objabi.KindArray, + types.TSLICE: objabi.KindSlice, + types.TFUNC: objabi.KindFunc, + types.TCOMPLEX64: objabi.KindComplex64, + types.TCOMPLEX128: objabi.KindComplex128, + types.TUNSAFEPTR: objabi.KindUnsafePointer, } // typeptrdata returns the length in bytes of the prefix of t @@ -753,32 +754,32 @@ func typeptrdata(t *types.Type) int64 { } switch t.Etype { - case TPTR, - TUNSAFEPTR, - TFUNC, - TCHAN, - TMAP: + case types.TPTR, + types.TUNSAFEPTR, + types.TFUNC, + types.TCHAN, + types.TMAP: return int64(Widthptr) - case TSTRING: + case types.TSTRING: // struct { byte *str; intgo len; } return int64(Widthptr) - case TINTER: + case types.TINTER: // struct { Itab *tab; void *data; } or // struct { Type *type; void *data; } // Note: see comment in plive.go:onebitwalktype1. return 2 * int64(Widthptr) - case TSLICE: + case types.TSLICE: // struct { byte *array; uintgo len; uintgo cap; } return int64(Widthptr) - case TARRAY: + case types.TARRAY: // haspointers already eliminated t.NumElem() == 0. return (t.NumElem()-1)*t.Elem().Width + typeptrdata(t.Elem()) - case TSTRUCT: + case types.TSTRUCT: // Find the last field that has pointers. var lastPtrField *types.Field for _, t1 := range t.Fields().Slice() { @@ -989,38 +990,38 @@ func typenamesym(t *types.Type) *types.Sym { return s } -func typename(t *types.Type) *Node { +func typename(t *types.Type) *ir.Node { s := typenamesym(t) if s.Def == nil { - n := newnamel(src.NoXPos, s) - n.Type = types.Types[TUINT8] - n.SetClass(PEXTERN) + n := ir.NewNameAt(src.NoXPos, s) + n.Type = types.Types[types.TUINT8] + n.SetClass(ir.PEXTERN) n.SetTypecheck(1) - s.Def = asTypesNode(n) + s.Def = ir.AsTypesNode(n) } - n := nod(OADDR, asNode(s.Def), nil) - n.Type = types.NewPtr(asNode(s.Def).Type) + n := ir.Nod(ir.OADDR, ir.AsNode(s.Def), nil) + n.Type = types.NewPtr(ir.AsNode(s.Def).Type) n.SetTypecheck(1) return n } -func itabname(t, itype *types.Type) *Node { +func itabname(t, itype *types.Type) *ir.Node { if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() || !itype.IsInterface() || itype.IsEmptyInterface() { base.Fatalf("itabname(%v, %v)", t, itype) } s := itabpkg.Lookup(t.ShortString() + "," + itype.ShortString()) if s.Def == nil { - n := newname(s) - n.Type = types.Types[TUINT8] - n.SetClass(PEXTERN) + n := NewName(s) + n.Type = types.Types[types.TUINT8] + n.SetClass(ir.PEXTERN) n.SetTypecheck(1) - s.Def = asTypesNode(n) + s.Def = ir.AsTypesNode(n) itabs = append(itabs, itabEntry{t: t, itype: itype, lsym: s.Linksym()}) } - n := nod(OADDR, asNode(s.Def), nil) - n.Type = types.NewPtr(asNode(s.Def).Type) + n := ir.Nod(ir.OADDR, ir.AsNode(s.Def), nil) + n.Type = types.NewPtr(ir.AsNode(s.Def).Type) n.SetTypecheck(1) return n } @@ -1029,35 +1030,35 @@ func itabname(t, itype *types.Type) *Node { // That is, if x==x for all x of type t. func isreflexive(t *types.Type) bool { switch t.Etype { - case TBOOL, - TINT, - TUINT, - TINT8, - TUINT8, - TINT16, - TUINT16, - TINT32, - TUINT32, - TINT64, - TUINT64, - TUINTPTR, - TPTR, - TUNSAFEPTR, - TSTRING, - TCHAN: + case types.TBOOL, + types.TINT, + types.TUINT, + types.TINT8, + types.TUINT8, + types.TINT16, + types.TUINT16, + types.TINT32, + types.TUINT32, + types.TINT64, + types.TUINT64, + types.TUINTPTR, + types.TPTR, + types.TUNSAFEPTR, + types.TSTRING, + types.TCHAN: return true - case TFLOAT32, - TFLOAT64, - TCOMPLEX64, - TCOMPLEX128, - TINTER: + case types.TFLOAT32, + types.TFLOAT64, + types.TCOMPLEX64, + types.TCOMPLEX128, + types.TINTER: return false - case TARRAY: + case types.TARRAY: return isreflexive(t.Elem()) - case TSTRUCT: + case types.TSTRUCT: for _, t1 := range t.Fields().Slice() { if !isreflexive(t1.Type) { return false @@ -1075,19 +1076,19 @@ func isreflexive(t *types.Type) bool { // need the key to be updated. func needkeyupdate(t *types.Type) bool { switch t.Etype { - case TBOOL, TINT, TUINT, TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, - TINT64, TUINT64, TUINTPTR, TPTR, TUNSAFEPTR, TCHAN: + case types.TBOOL, types.TINT, types.TUINT, types.TINT8, types.TUINT8, types.TINT16, types.TUINT16, types.TINT32, types.TUINT32, + types.TINT64, types.TUINT64, types.TUINTPTR, types.TPTR, types.TUNSAFEPTR, types.TCHAN: return false - case TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, // floats and complex can be +0/-0 - TINTER, - TSTRING: // strings might have smaller backing stores + case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128, // floats and complex can be +0/-0 + types.TINTER, + types.TSTRING: // strings might have smaller backing stores return true - case TARRAY: + case types.TARRAY: return needkeyupdate(t.Elem()) - case TSTRUCT: + case types.TSTRUCT: for _, t1 := range t.Fields().Slice() { if needkeyupdate(t1.Type) { return true @@ -1104,13 +1105,13 @@ func needkeyupdate(t *types.Type) bool { // hashMightPanic reports whether the hash of a map key of type t might panic. func hashMightPanic(t *types.Type) bool { switch t.Etype { - case TINTER: + case types.TINTER: return true - case TARRAY: + case types.TARRAY: return hashMightPanic(t.Elem()) - case TSTRUCT: + case types.TSTRUCT: for _, t1 := range t.Fields().Slice() { if hashMightPanic(t1.Type) { return true @@ -1161,7 +1162,7 @@ func dtypesym(t *types.Type) *obj.LSym { if base.Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Etype] && tbase != types.Bytetype && tbase != types.Runetype && tbase != types.Errortype) { // int, float, etc // named types from other files are defined only by those files - if tbase.Sym != nil && tbase.Sym.Pkg != localpkg { + if tbase.Sym != nil && tbase.Sym.Pkg != ir.LocalPkg { if i, ok := typeSymIdx[tbase]; ok { lsym.Pkg = tbase.Sym.Pkg.Prefix if t != tbase { @@ -1174,7 +1175,7 @@ func dtypesym(t *types.Type) *obj.LSym { return lsym } // TODO(mdempsky): Investigate whether this can happen. - if tbase.Etype == TFORW { + if tbase.Etype == types.TFORW { return lsym } } @@ -1185,7 +1186,7 @@ func dtypesym(t *types.Type) *obj.LSym { ot = dcommontype(lsym, t) ot = dextratype(lsym, ot, t, 0) - case TARRAY: + case types.TARRAY: // ../../../../runtime/type.go:/arrayType s1 := dtypesym(t.Elem()) t2 := types.NewSlice(t.Elem()) @@ -1196,14 +1197,14 @@ func dtypesym(t *types.Type) *obj.LSym { ot = duintptr(lsym, ot, uint64(t.NumElem())) ot = dextratype(lsym, ot, t, 0) - case TSLICE: + case types.TSLICE: // ../../../../runtime/type.go:/sliceType s1 := dtypesym(t.Elem()) ot = dcommontype(lsym, t) ot = dsymptr(lsym, ot, s1, 0) ot = dextratype(lsym, ot, t, 0) - case TCHAN: + case types.TCHAN: // ../../../../runtime/type.go:/chanType s1 := dtypesym(t.Elem()) ot = dcommontype(lsym, t) @@ -1211,7 +1212,7 @@ func dtypesym(t *types.Type) *obj.LSym { ot = duintptr(lsym, ot, uint64(t.ChanDir())) ot = dextratype(lsym, ot, t, 0) - case TFUNC: + case types.TFUNC: for _, t1 := range t.Recvs().Fields().Slice() { dtypesym(t1.Type) } @@ -1250,7 +1251,7 @@ func dtypesym(t *types.Type) *obj.LSym { ot = dsymptr(lsym, ot, dtypesym(t1.Type), 0) } - case TINTER: + case types.TINTER: m := imethods(t) n := len(m) for _, a := range m { @@ -1286,7 +1287,7 @@ func dtypesym(t *types.Type) *obj.LSym { } // ../../../../runtime/type.go:/mapType - case TMAP: + case types.TMAP: s1 := dtypesym(t.Key()) s2 := dtypesym(t.Elem()) s3 := dtypesym(bmap(t)) @@ -1326,8 +1327,8 @@ func dtypesym(t *types.Type) *obj.LSym { ot = duint32(lsym, ot, flags) ot = dextratype(lsym, ot, t, 0) - case TPTR: - if t.Elem().Etype == TANY { + case types.TPTR: + if t.Elem().Etype == types.TANY { // ../../../../runtime/type.go:/UnsafePointerType ot = dcommontype(lsym, t) ot = dextratype(lsym, ot, t, 0) @@ -1344,7 +1345,7 @@ func dtypesym(t *types.Type) *obj.LSym { // ../../../../runtime/type.go:/structType // for security, only the exported fields. - case TSTRUCT: + case types.TSTRUCT: fields := t.Fields().Slice() for _, t1 := range fields { dtypesym(t1.Type) @@ -1403,7 +1404,7 @@ func dtypesym(t *types.Type) *obj.LSym { // functions must return the existing type structure rather // than creating a new one. switch t.Etype { - case TPTR, TARRAY, TCHAN, TFUNC, TMAP, TSLICE, TSTRUCT: + case types.TPTR, types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRUCT: keep = true } } @@ -1515,10 +1516,10 @@ func addsignat(t *types.Type) { } } -func addsignats(dcls []*Node) { +func addsignats(dcls []*ir.Node) { // copy types from dcl list to signatset for _, n := range dcls { - if n.Op == OTYPE { + if n.Op == ir.OTYPE { addsignat(n.Type) } } @@ -1571,7 +1572,7 @@ func dumptabs() { } // process ptabs - if localpkg.Name == "main" && len(ptabs) > 0 { + if ir.LocalPkg.Name == "main" && len(ptabs) > 0 { ot := 0 s := base.Ctxt.Lookup("go.plugin.tabs") for _, p := range ptabs { @@ -1615,17 +1616,17 @@ func dumpbasictypes() { // another possible choice would be package main, // but using runtime means fewer copies in object files. if base.Ctxt.Pkgpath == "runtime" { - for i := types.EType(1); i <= TBOOL; i++ { + for i := types.EType(1); i <= types.TBOOL; i++ { dtypesym(types.NewPtr(types.Types[i])) } - dtypesym(types.NewPtr(types.Types[TSTRING])) - dtypesym(types.NewPtr(types.Types[TUNSAFEPTR])) + dtypesym(types.NewPtr(types.Types[types.TSTRING])) + dtypesym(types.NewPtr(types.Types[types.TUNSAFEPTR])) // emit type structs for error and func(error) string. // The latter is the type of an auto-generated wrapper. dtypesym(types.NewPtr(types.Errortype)) - dtypesym(functype(nil, []*Node{anonfield(types.Errortype)}, []*Node{anonfield(types.Types[TSTRING])})) + dtypesym(functype(nil, []*ir.Node{anonfield(types.Errortype)}, []*ir.Node{anonfield(types.Types[types.TSTRING])})) // add paths for runtime and main, which 6l imports implicitly. dimportpath(Runtimepkg) @@ -1767,7 +1768,7 @@ func fillptrmask(t *types.Type, ptrmask []byte) { // For non-trivial arrays, the program describes the full t.Width size. func dgcprog(t *types.Type) (*obj.LSym, int64) { dowidth(t) - if t.Width == BADWIDTH { + if t.Width == types.BADWIDTH { base.Fatalf("dgcprog: %v badwidth", t) } lsym := typesymprefix(".gcprog", t).Linksym() @@ -1824,17 +1825,17 @@ func (p *GCProg) emit(t *types.Type, offset int64) { default: base.Fatalf("GCProg.emit: unexpected type %v", t) - case TSTRING: + case types.TSTRING: p.w.Ptr(offset / int64(Widthptr)) - case TINTER: + case types.TINTER: // Note: the first word isn't a pointer. See comment in plive.go:onebitwalktype1. p.w.Ptr(offset/int64(Widthptr) + 1) - case TSLICE: + case types.TSLICE: p.w.Ptr(offset / int64(Widthptr)) - case TARRAY: + case types.TARRAY: if t.NumElem() == 0 { // should have been handled by haspointers check above base.Fatalf("GCProg.emit: empty array") @@ -1859,7 +1860,7 @@ func (p *GCProg) emit(t *types.Type, offset int64) { p.w.ZeroUntil((offset + elem.Width) / int64(Widthptr)) p.w.Repeat(elem.Width/int64(Widthptr), count-1) - case TSTRUCT: + case types.TSTRUCT: for _, t1 := range t.Fields().Slice() { p.emit(t1.Type, offset+t1.Offset) } @@ -1868,7 +1869,7 @@ func (p *GCProg) emit(t *types.Type, offset int64) { // zeroaddr returns the address of a symbol with at least // size bytes of zeros. -func zeroaddr(size int64) *Node { +func zeroaddr(size int64) *ir.Node { if size >= 1<<31 { base.Fatalf("map elem too big %d", size) } @@ -1877,14 +1878,14 @@ func zeroaddr(size int64) *Node { } s := mappkg.Lookup("zero") if s.Def == nil { - x := newname(s) - x.Type = types.Types[TUINT8] - x.SetClass(PEXTERN) + x := NewName(s) + x.Type = types.Types[types.TUINT8] + x.SetClass(ir.PEXTERN) x.SetTypecheck(1) - s.Def = asTypesNode(x) + s.Def = ir.AsTypesNode(x) } - z := nod(OADDR, asNode(s.Def), nil) - z.Type = types.NewPtr(types.Types[TUINT8]) + z := ir.Nod(ir.OADDR, ir.AsNode(s.Def), nil) + z.Type = types.NewPtr(types.Types[types.TUINT8]) z.SetTypecheck(1) return z } diff --git a/src/cmd/compile/internal/gc/scc.go b/src/cmd/compile/internal/gc/scc.go index 891012cbc9f..ddde18e5054 100644 --- a/src/cmd/compile/internal/gc/scc.go +++ b/src/cmd/compile/internal/gc/scc.go @@ -4,6 +4,8 @@ package gc +import "cmd/compile/internal/ir" + // Strongly connected components. // // Run analysis on minimal sets of mutually recursive functions @@ -30,10 +32,10 @@ package gc // when analyzing a set of mutually recursive functions. type bottomUpVisitor struct { - analyze func([]*Node, bool) + analyze func([]*ir.Node, bool) visitgen uint32 - nodeID map[*Node]uint32 - stack []*Node + nodeID map[*ir.Node]uint32 + stack []*ir.Node } // visitBottomUp invokes analyze on the ODCLFUNC nodes listed in list. @@ -49,18 +51,18 @@ type bottomUpVisitor struct { // If recursive is false, the list consists of only a single function and its closures. // If recursive is true, the list may still contain only a single function, // if that function is itself recursive. -func visitBottomUp(list []*Node, analyze func(list []*Node, recursive bool)) { +func visitBottomUp(list []*ir.Node, analyze func(list []*ir.Node, recursive bool)) { var v bottomUpVisitor v.analyze = analyze - v.nodeID = make(map[*Node]uint32) + v.nodeID = make(map[*ir.Node]uint32) for _, n := range list { - if n.Op == ODCLFUNC && !n.Func.IsHiddenClosure() { + if n.Op == ir.ODCLFUNC && !n.Func.IsHiddenClosure() { v.visit(n) } } } -func (v *bottomUpVisitor) visit(n *Node) uint32 { +func (v *bottomUpVisitor) visit(n *ir.Node) uint32 { if id := v.nodeID[n]; id > 0 { // already visited return id @@ -73,38 +75,38 @@ func (v *bottomUpVisitor) visit(n *Node) uint32 { min := v.visitgen v.stack = append(v.stack, n) - inspectList(n.Nbody, func(n *Node) bool { + ir.InspectList(n.Nbody, func(n *ir.Node) bool { switch n.Op { - case ONAME: - if n.Class() == PFUNC { + case ir.ONAME: + if n.Class() == ir.PFUNC { if n != nil && n.Name.Defn != nil { if m := v.visit(n.Name.Defn); m < min { min = m } } } - case OMETHEXPR: - fn := n.MethodName() + case ir.OMETHEXPR: + fn := methodExprName(n) if fn != nil && fn.Name.Defn != nil { if m := v.visit(fn.Name.Defn); m < min { min = m } } - case ODOTMETH: - fn := n.MethodName() - if fn != nil && fn.Op == ONAME && fn.Class() == PFUNC && fn.Name.Defn != nil { + case ir.ODOTMETH: + fn := methodExprName(n) + if fn != nil && fn.Op == ir.ONAME && fn.Class() == ir.PFUNC && fn.Name.Defn != nil { if m := v.visit(fn.Name.Defn); m < min { min = m } } - case OCALLPART: - fn := asNode(callpartMethod(n).Nname) - if fn != nil && fn.Op == ONAME && fn.Class() == PFUNC && fn.Name.Defn != nil { + case ir.OCALLPART: + fn := ir.AsNode(callpartMethod(n).Nname) + if fn != nil && fn.Op == ir.ONAME && fn.Class() == ir.PFUNC && fn.Name.Defn != nil { if m := v.visit(fn.Name.Defn); m < min { min = m } } - case OCLOSURE: + case ir.OCLOSURE: if m := v.visit(n.Func.Decl); m < min { min = m } diff --git a/src/cmd/compile/internal/gc/scope.go b/src/cmd/compile/internal/gc/scope.go index ace1d6bd9c5..b5ebce04bec 100644 --- a/src/cmd/compile/internal/gc/scope.go +++ b/src/cmd/compile/internal/gc/scope.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/internal/dwarf" "cmd/internal/obj" "cmd/internal/src" @@ -17,7 +18,7 @@ func xposBefore(p, q src.XPos) bool { return base.Ctxt.PosTable.Pos(p).Before(base.Ctxt.PosTable.Pos(q)) } -func findScope(marks []Mark, pos src.XPos) ScopeID { +func findScope(marks []ir.Mark, pos src.XPos) ir.ScopeID { i := sort.Search(len(marks), func(i int) bool { return xposBefore(pos, marks[i].Pos) }) @@ -27,7 +28,7 @@ func findScope(marks []Mark, pos src.XPos) ScopeID { return marks[i-1].Scope } -func assembleScopes(fnsym *obj.LSym, fn *Node, dwarfVars []*dwarf.Var, varScopes []ScopeID) []dwarf.Scope { +func assembleScopes(fnsym *obj.LSym, fn *ir.Node, dwarfVars []*dwarf.Var, varScopes []ir.ScopeID) []dwarf.Scope { // Initialize the DWARF scope tree based on lexical scopes. dwarfScopes := make([]dwarf.Scope, 1+len(fn.Func.Parents)) for i, parent := range fn.Func.Parents { @@ -40,7 +41,7 @@ func assembleScopes(fnsym *obj.LSym, fn *Node, dwarfVars []*dwarf.Var, varScopes } // scopeVariables assigns DWARF variable records to their scopes. -func scopeVariables(dwarfVars []*dwarf.Var, varScopes []ScopeID, dwarfScopes []dwarf.Scope) { +func scopeVariables(dwarfVars []*dwarf.Var, varScopes []ir.ScopeID, dwarfScopes []dwarf.Scope) { sort.Stable(varsByScopeAndOffset{dwarfVars, varScopes}) i0 := 0 @@ -57,7 +58,7 @@ func scopeVariables(dwarfVars []*dwarf.Var, varScopes []ScopeID, dwarfScopes []d } // scopePCs assigns PC ranges to their scopes. -func scopePCs(fnsym *obj.LSym, marks []Mark, dwarfScopes []dwarf.Scope) { +func scopePCs(fnsym *obj.LSym, marks []ir.Mark, dwarfScopes []dwarf.Scope) { // If there aren't any child scopes (in particular, when scope // tracking is disabled), we can skip a whole lot of work. if len(marks) == 0 { @@ -90,7 +91,7 @@ func compactScopes(dwarfScopes []dwarf.Scope) []dwarf.Scope { type varsByScopeAndOffset struct { vars []*dwarf.Var - scopes []ScopeID + scopes []ir.ScopeID } func (v varsByScopeAndOffset) Len() int { diff --git a/src/cmd/compile/internal/gc/select.go b/src/cmd/compile/internal/gc/select.go index 8d4c8d2be10..ed7db0aaf7b 100644 --- a/src/cmd/compile/internal/gc/select.go +++ b/src/cmd/compile/internal/gc/select.go @@ -6,16 +6,17 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" ) // select -func typecheckselect(sel *Node) { - var def *Node +func typecheckselect(sel *ir.Node) { + var def *ir.Node lno := setlineno(sel) typecheckslice(sel.Ninit.Slice(), ctxStmt) for _, ncase := range sel.List.Slice() { - if ncase.Op != OCASE { + if ncase.Op != ir.OCASE { setlineno(ncase) base.Fatalf("typecheckselect %v", ncase.Op) } @@ -23,7 +24,7 @@ func typecheckselect(sel *Node) { if ncase.List.Len() == 0 { // default if def != nil { - base.ErrorfAt(ncase.Pos, "multiple defaults in select (first at %v)", def.Line()) + base.ErrorfAt(ncase.Pos, "multiple defaults in select (first at %v)", ir.Line(def)) } else { def = ncase } @@ -37,7 +38,7 @@ func typecheckselect(sel *Node) { switch n.Op { default: pos := n.Pos - if n.Op == ONAME { + if n.Op == ir.ONAME { // We don't have the right position for ONAME nodes (see #15459 and // others). Using ncase.Pos for now as it will provide the correct // line number (assuming the expression follows the "case" keyword @@ -49,37 +50,37 @@ func typecheckselect(sel *Node) { // convert x = <-c into OSELRECV(x, <-c). // remove implicit conversions; the eventual assignment // will reintroduce them. - case OAS: - if (n.Right.Op == OCONVNOP || n.Right.Op == OCONVIFACE) && n.Right.Implicit() { + case ir.OAS: + if (n.Right.Op == ir.OCONVNOP || n.Right.Op == ir.OCONVIFACE) && n.Right.Implicit() { n.Right = n.Right.Left } - if n.Right.Op != ORECV { + if n.Right.Op != ir.ORECV { base.ErrorfAt(n.Pos, "select assignment must have receive on right hand side") break } - n.Op = OSELRECV + n.Op = ir.OSELRECV // convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok - case OAS2RECV: - if n.Right.Op != ORECV { + case ir.OAS2RECV: + if n.Right.Op != ir.ORECV { base.ErrorfAt(n.Pos, "select assignment must have receive on right hand side") break } - n.Op = OSELRECV2 + n.Op = ir.OSELRECV2 n.Left = n.List.First() n.List.Set1(n.List.Second()) // convert <-c into OSELRECV(N, <-c) - case ORECV: - n = nodl(n.Pos, OSELRECV, nil, n) + case ir.ORECV: + n = ir.NodAt(n.Pos, ir.OSELRECV, nil, n) n.SetTypecheck(1) ncase.Left = n - case OSEND: + case ir.OSEND: break } } @@ -90,7 +91,7 @@ func typecheckselect(sel *Node) { base.Pos = lno } -func walkselect(sel *Node) { +func walkselect(sel *ir.Node) { lno := setlineno(sel) if sel.Nbody.Len() != 0 { base.Fatalf("double walkselect") @@ -108,13 +109,13 @@ func walkselect(sel *Node) { base.Pos = lno } -func walkselectcases(cases *Nodes) []*Node { +func walkselectcases(cases *ir.Nodes) []*ir.Node { ncas := cases.Len() sellineno := base.Pos // optimization: zero-case select if ncas == 0 { - return []*Node{mkcall("block", nil, nil)} + return []*ir.Node{mkcall("block", nil, nil)} } // optimization: one-case select: single op. @@ -130,25 +131,25 @@ func walkselectcases(cases *Nodes) []*Node { default: base.Fatalf("select %v", n.Op) - case OSEND: + case ir.OSEND: // already ok - case OSELRECV, OSELRECV2: - if n.Op == OSELRECV || n.List.Len() == 0 { + case ir.OSELRECV, ir.OSELRECV2: + if n.Op == ir.OSELRECV || n.List.Len() == 0 { if n.Left == nil { n = n.Right } else { - n.Op = OAS + n.Op = ir.OAS } break } if n.Left == nil { - nblank = typecheck(nblank, ctxExpr|ctxAssign) - n.Left = nblank + ir.BlankNode = typecheck(ir.BlankNode, ctxExpr|ctxAssign) + n.Left = ir.BlankNode } - n.Op = OAS2 + n.Op = ir.OAS2 n.List.Prepend(n.Left) n.Rlist.Set1(n.Right) n.Right = nil @@ -161,13 +162,13 @@ func walkselectcases(cases *Nodes) []*Node { } l = append(l, cas.Nbody.Slice()...) - l = append(l, nod(OBREAK, nil, nil)) + l = append(l, ir.Nod(ir.OBREAK, nil, nil)) return l } // convert case value arguments to addresses. // this rewrite is used by both the general code and the next optimization. - var dflt *Node + var dflt *ir.Node for _, cas := range cases.Slice() { setlineno(cas) n := cas.Left @@ -176,17 +177,17 @@ func walkselectcases(cases *Nodes) []*Node { continue } switch n.Op { - case OSEND: - n.Right = nod(OADDR, n.Right, nil) + case ir.OSEND: + n.Right = ir.Nod(ir.OADDR, n.Right, nil) n.Right = typecheck(n.Right, ctxExpr) - case OSELRECV, OSELRECV2: - if n.Op == OSELRECV2 && n.List.Len() == 0 { - n.Op = OSELRECV + case ir.OSELRECV, ir.OSELRECV2: + if n.Op == ir.OSELRECV2 && n.List.Len() == 0 { + n.Op = ir.OSELRECV } if n.Left != nil { - n.Left = nod(OADDR, n.Left, nil) + n.Left = ir.Nod(ir.OADDR, n.Left, nil) n.Left = typecheck(n.Left, ctxExpr) } } @@ -201,66 +202,66 @@ func walkselectcases(cases *Nodes) []*Node { n := cas.Left setlineno(n) - r := nod(OIF, nil, nil) + r := ir.Nod(ir.OIF, nil, nil) r.Ninit.Set(cas.Ninit.Slice()) switch n.Op { default: base.Fatalf("select %v", n.Op) - case OSEND: + case ir.OSEND: // if selectnbsend(c, v) { body } else { default body } ch := n.Left - r.Left = mkcall1(chanfn("selectnbsend", 2, ch.Type), types.Types[TBOOL], &r.Ninit, ch, n.Right) + r.Left = mkcall1(chanfn("selectnbsend", 2, ch.Type), types.Types[types.TBOOL], &r.Ninit, ch, n.Right) - case OSELRECV: + case ir.OSELRECV: // if selectnbrecv(&v, c) { body } else { default body } ch := n.Right.Left elem := n.Left if elem == nil { elem = nodnil() } - r.Left = mkcall1(chanfn("selectnbrecv", 2, ch.Type), types.Types[TBOOL], &r.Ninit, elem, ch) + r.Left = mkcall1(chanfn("selectnbrecv", 2, ch.Type), types.Types[types.TBOOL], &r.Ninit, elem, ch) - case OSELRECV2: + case ir.OSELRECV2: // if selectnbrecv2(&v, &received, c) { body } else { default body } ch := n.Right.Left elem := n.Left if elem == nil { elem = nodnil() } - receivedp := nod(OADDR, n.List.First(), nil) + receivedp := ir.Nod(ir.OADDR, n.List.First(), nil) receivedp = typecheck(receivedp, ctxExpr) - r.Left = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), types.Types[TBOOL], &r.Ninit, elem, receivedp, ch) + r.Left = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), types.Types[types.TBOOL], &r.Ninit, elem, receivedp, ch) } r.Left = typecheck(r.Left, ctxExpr) r.Nbody.Set(cas.Nbody.Slice()) r.Rlist.Set(append(dflt.Ninit.Slice(), dflt.Nbody.Slice()...)) - return []*Node{r, nod(OBREAK, nil, nil)} + return []*ir.Node{r, ir.Nod(ir.OBREAK, nil, nil)} } if dflt != nil { ncas-- } - casorder := make([]*Node, ncas) + casorder := make([]*ir.Node, ncas) nsends, nrecvs := 0, 0 - var init []*Node + var init []*ir.Node // generate sel-struct base.Pos = sellineno selv := temp(types.NewArray(scasetype(), int64(ncas))) - r := nod(OAS, selv, nil) + r := ir.Nod(ir.OAS, selv, nil) r = typecheck(r, ctxStmt) init = append(init, r) // No initialization for order; runtime.selectgo is responsible for that. - order := temp(types.NewArray(types.Types[TUINT16], 2*int64(ncas))) + order := temp(types.NewArray(types.Types[types.TUINT16], 2*int64(ncas))) - var pc0, pcs *Node + var pc0, pcs *ir.Node if base.Flag.Race { - pcs = temp(types.NewArray(types.Types[TUINTPTR], int64(ncas))) - pc0 = typecheck(nod(OADDR, nod(OINDEX, pcs, nodintconst(0)), nil), ctxExpr) + pcs = temp(types.NewArray(types.Types[types.TUINTPTR], int64(ncas))) + pc0 = typecheck(ir.Nod(ir.OADDR, ir.Nod(ir.OINDEX, pcs, nodintconst(0)), nil), ctxExpr) } else { pc0 = nodnil() } @@ -278,16 +279,16 @@ func walkselectcases(cases *Nodes) []*Node { } var i int - var c, elem *Node + var c, elem *ir.Node switch n.Op { default: base.Fatalf("select %v", n.Op) - case OSEND: + case ir.OSEND: i = nsends nsends++ c = n.Left elem = n.Right - case OSELRECV, OSELRECV2: + case ir.OSELRECV, ir.OSELRECV2: nrecvs++ i = ncas - nrecvs c = n.Right.Left @@ -296,23 +297,23 @@ func walkselectcases(cases *Nodes) []*Node { casorder[i] = cas - setField := func(f string, val *Node) { - r := nod(OAS, nodSym(ODOT, nod(OINDEX, selv, nodintconst(int64(i))), lookup(f)), val) + setField := func(f string, val *ir.Node) { + r := ir.Nod(ir.OAS, nodSym(ir.ODOT, ir.Nod(ir.OINDEX, selv, nodintconst(int64(i))), lookup(f)), val) r = typecheck(r, ctxStmt) init = append(init, r) } - c = convnop(c, types.Types[TUNSAFEPTR]) + c = convnop(c, types.Types[types.TUNSAFEPTR]) setField("c", c) if elem != nil { - elem = convnop(elem, types.Types[TUNSAFEPTR]) + elem = convnop(elem, types.Types[types.TUNSAFEPTR]) setField("elem", elem) } // TODO(mdempsky): There should be a cleaner way to // handle this. if base.Flag.Race { - r = mkcall("selectsetpc", nil, nil, nod(OADDR, nod(OINDEX, pcs, nodintconst(int64(i))), nil)) + r = mkcall("selectsetpc", nil, nil, ir.Nod(ir.OADDR, ir.Nod(ir.OINDEX, pcs, nodintconst(int64(i))), nil)) init = append(init, r) } } @@ -322,9 +323,9 @@ func walkselectcases(cases *Nodes) []*Node { // run the select base.Pos = sellineno - chosen := temp(types.Types[TINT]) - recvOK := temp(types.Types[TBOOL]) - r = nod(OAS2, nil, nil) + chosen := temp(types.Types[types.TINT]) + recvOK := temp(types.Types[types.TBOOL]) + r = ir.Nod(ir.OAS2, nil, nil) r.List.Set2(chosen, recvOK) fn := syslook("selectgo") r.Rlist.Set1(mkcall1(fn, fn.Type.Results(), nil, bytePtrToIndex(selv, 0), bytePtrToIndex(order, 0), pc0, nodintconst(int64(nsends)), nodintconst(int64(nrecvs)), nodbool(dflt == nil))) @@ -332,46 +333,46 @@ func walkselectcases(cases *Nodes) []*Node { init = append(init, r) // selv and order are no longer alive after selectgo. - init = append(init, nod(OVARKILL, selv, nil)) - init = append(init, nod(OVARKILL, order, nil)) + init = append(init, ir.Nod(ir.OVARKILL, selv, nil)) + init = append(init, ir.Nod(ir.OVARKILL, order, nil)) if base.Flag.Race { - init = append(init, nod(OVARKILL, pcs, nil)) + init = append(init, ir.Nod(ir.OVARKILL, pcs, nil)) } // dispatch cases - dispatch := func(cond, cas *Node) { + dispatch := func(cond, cas *ir.Node) { cond = typecheck(cond, ctxExpr) cond = defaultlit(cond, nil) - r := nod(OIF, cond, nil) + r := ir.Nod(ir.OIF, cond, nil) - if n := cas.Left; n != nil && n.Op == OSELRECV2 { - x := nod(OAS, n.List.First(), recvOK) + if n := cas.Left; n != nil && n.Op == ir.OSELRECV2 { + x := ir.Nod(ir.OAS, n.List.First(), recvOK) x = typecheck(x, ctxStmt) r.Nbody.Append(x) } r.Nbody.AppendNodes(&cas.Nbody) - r.Nbody.Append(nod(OBREAK, nil, nil)) + r.Nbody.Append(ir.Nod(ir.OBREAK, nil, nil)) init = append(init, r) } if dflt != nil { setlineno(dflt) - dispatch(nod(OLT, chosen, nodintconst(0)), dflt) + dispatch(ir.Nod(ir.OLT, chosen, nodintconst(0)), dflt) } for i, cas := range casorder { setlineno(cas) - dispatch(nod(OEQ, chosen, nodintconst(int64(i))), cas) + dispatch(ir.Nod(ir.OEQ, chosen, nodintconst(int64(i))), cas) } return init } // bytePtrToIndex returns a Node representing "(*byte)(&n[i])". -func bytePtrToIndex(n *Node, i int64) *Node { - s := nod(OADDR, nod(OINDEX, n, nodintconst(i)), nil) - t := types.NewPtr(types.Types[TUINT8]) +func bytePtrToIndex(n *ir.Node, i int64) *ir.Node { + s := ir.Nod(ir.OADDR, ir.Nod(ir.OINDEX, n, nodintconst(i)), nil) + t := types.NewPtr(types.Types[types.TUINT8]) return convnop(s, t) } @@ -380,9 +381,9 @@ var scase *types.Type // Keep in sync with src/runtime/select.go. func scasetype() *types.Type { if scase == nil { - scase = tostruct([]*Node{ - namedfield("c", types.Types[TUNSAFEPTR]), - namedfield("elem", types.Types[TUNSAFEPTR]), + scase = tostruct([]*ir.Node{ + namedfield("c", types.Types[types.TUNSAFEPTR]), + namedfield("elem", types.Types[types.TUNSAFEPTR]), }) scase.SetNoalg(true) } diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index 219435d6de3..d78b5091276 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/obj" "fmt" @@ -13,8 +14,8 @@ import ( ) type InitEntry struct { - Xoffset int64 // struct, array only - Expr *Node // bytes of run-time computed expressions + Xoffset int64 // struct, array only + Expr *ir.Node // bytes of run-time computed expressions } type InitPlan struct { @@ -28,21 +29,21 @@ type InitPlan struct { type InitSchedule struct { // out is the ordered list of dynamic initialization // statements. - out []*Node + out []*ir.Node - initplans map[*Node]*InitPlan - inittemps map[*Node]*Node + initplans map[*ir.Node]*InitPlan + inittemps map[*ir.Node]*ir.Node } -func (s *InitSchedule) append(n *Node) { +func (s *InitSchedule) append(n *ir.Node) { s.out = append(s.out, n) } // staticInit adds an initialization statement n to the schedule. -func (s *InitSchedule) staticInit(n *Node) { +func (s *InitSchedule) staticInit(n *ir.Node) { if !s.tryStaticInit(n) { if base.Flag.Percent != 0 { - Dump("nonstatic", n) + ir.Dump("nonstatic", n) } s.append(n) } @@ -50,16 +51,16 @@ func (s *InitSchedule) staticInit(n *Node) { // tryStaticInit attempts to statically execute an initialization // statement and reports whether it succeeded. -func (s *InitSchedule) tryStaticInit(n *Node) bool { +func (s *InitSchedule) tryStaticInit(n *ir.Node) bool { // Only worry about simple "l = r" assignments. Multiple // variable/expression OAS2 assignments have already been // replaced by multiple simple OAS assignments, and the other // OAS2* assignments mostly necessitate dynamic execution // anyway. - if n.Op != OAS { + if n.Op != ir.OAS { return false } - if n.Left.isBlank() && candiscard(n.Right) { + if ir.IsBlank(n.Left) && candiscard(n.Right) { return true } lno := setlineno(n) @@ -69,21 +70,21 @@ func (s *InitSchedule) tryStaticInit(n *Node) bool { // like staticassign but we are copying an already // initialized value r. -func (s *InitSchedule) staticcopy(l *Node, r *Node) bool { - if r.Op != ONAME && r.Op != OMETHEXPR { +func (s *InitSchedule) staticcopy(l *ir.Node, r *ir.Node) bool { + if r.Op != ir.ONAME && r.Op != ir.OMETHEXPR { return false } - if r.Class() == PFUNC { + if r.Class() == ir.PFUNC { pfuncsym(l, r) return true } - if r.Class() != PEXTERN || r.Sym.Pkg != localpkg { + if r.Class() != ir.PEXTERN || r.Sym.Pkg != ir.LocalPkg { return false } if r.Name.Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value return false } - if r.Name.Defn.Op != OAS { + if r.Name.Defn.Op != ir.OAS { return false } if r.Type.IsString() { // perhaps overwritten by cmd/link -X (#34675) @@ -92,73 +93,73 @@ func (s *InitSchedule) staticcopy(l *Node, r *Node) bool { orig := r r = r.Name.Defn.Right - for r.Op == OCONVNOP && !types.Identical(r.Type, l.Type) { + for r.Op == ir.OCONVNOP && !types.Identical(r.Type, l.Type) { r = r.Left } switch r.Op { - case ONAME, OMETHEXPR: + case ir.ONAME, ir.OMETHEXPR: if s.staticcopy(l, r) { return true } // We may have skipped past one or more OCONVNOPs, so // use conv to ensure r is assignable to l (#13263). - s.append(nod(OAS, l, conv(r, l.Type))) + s.append(ir.Nod(ir.OAS, l, conv(r, l.Type))) return true - case ONIL: + case ir.ONIL: return true - case OLITERAL: + case ir.OLITERAL: if isZero(r) { return true } litsym(l, r, int(l.Type.Width)) return true - case OADDR: - if a := r.Left; a.Op == ONAME { + case ir.OADDR: + if a := r.Left; a.Op == ir.ONAME { addrsym(l, a) return true } - case OPTRLIT: + case ir.OPTRLIT: switch r.Left.Op { - case OARRAYLIT, OSLICELIT, OSTRUCTLIT, OMAPLIT: + case ir.OARRAYLIT, ir.OSLICELIT, ir.OSTRUCTLIT, ir.OMAPLIT: // copy pointer addrsym(l, s.inittemps[r]) return true } - case OSLICELIT: + case ir.OSLICELIT: // copy slice a := s.inittemps[r] slicesym(l, a, r.Right.Int64Val()) return true - case OARRAYLIT, OSTRUCTLIT: + case ir.OARRAYLIT, ir.OSTRUCTLIT: p := s.initplans[r] - n := l.copy() + n := ir.Copy(l) for i := range p.E { e := &p.E[i] n.Xoffset = l.Xoffset + e.Xoffset n.Type = e.Expr.Type - if e.Expr.Op == OLITERAL || e.Expr.Op == ONIL { + if e.Expr.Op == ir.OLITERAL || e.Expr.Op == ir.ONIL { litsym(n, e.Expr, int(n.Type.Width)) continue } - ll := n.sepcopy() + ll := ir.SepCopy(n) if s.staticcopy(ll, e.Expr) { continue } // Requires computation, but we're // copying someone else's computation. - rr := orig.sepcopy() + rr := ir.SepCopy(orig) rr.Type = ll.Type rr.Xoffset += e.Xoffset setlineno(rr) - s.append(nod(OAS, ll, rr)) + s.append(ir.Nod(ir.OAS, ll, rr)) } return true @@ -167,35 +168,35 @@ func (s *InitSchedule) staticcopy(l *Node, r *Node) bool { return false } -func (s *InitSchedule) staticassign(l *Node, r *Node) bool { - for r.Op == OCONVNOP { +func (s *InitSchedule) staticassign(l *ir.Node, r *ir.Node) bool { + for r.Op == ir.OCONVNOP { r = r.Left } switch r.Op { - case ONAME, OMETHEXPR: + case ir.ONAME, ir.OMETHEXPR: return s.staticcopy(l, r) - case ONIL: + case ir.ONIL: return true - case OLITERAL: + case ir.OLITERAL: if isZero(r) { return true } litsym(l, r, int(l.Type.Width)) return true - case OADDR: + case ir.OADDR: if nam := stataddr(r.Left); nam != nil { addrsym(l, nam) return true } fallthrough - case OPTRLIT: + case ir.OPTRLIT: switch r.Left.Op { - case OARRAYLIT, OSLICELIT, OMAPLIT, OSTRUCTLIT: + case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT: // Init pointer. a := staticname(r.Left.Type) @@ -204,20 +205,20 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { // Init underlying literal. if !s.staticassign(a, r.Left) { - s.append(nod(OAS, a, r.Left)) + s.append(ir.Nod(ir.OAS, a, r.Left)) } return true } //dump("not static ptrlit", r); - case OSTR2BYTES: - if l.Class() == PEXTERN && r.Left.Op == OLITERAL { + case ir.OSTR2BYTES: + if l.Class() == ir.PEXTERN && r.Left.Op == ir.OLITERAL { sval := r.Left.StringVal() slicebytes(l, sval) return true } - case OSLICELIT: + case ir.OSLICELIT: s.initplan(r) // Init slice. bound := r.Right.Int64Val() @@ -230,32 +231,32 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { l = a fallthrough - case OARRAYLIT, OSTRUCTLIT: + case ir.OARRAYLIT, ir.OSTRUCTLIT: s.initplan(r) p := s.initplans[r] - n := l.copy() + n := ir.Copy(l) for i := range p.E { e := &p.E[i] n.Xoffset = l.Xoffset + e.Xoffset n.Type = e.Expr.Type - if e.Expr.Op == OLITERAL || e.Expr.Op == ONIL { + if e.Expr.Op == ir.OLITERAL || e.Expr.Op == ir.ONIL { litsym(n, e.Expr, int(n.Type.Width)) continue } setlineno(e.Expr) - a := n.sepcopy() + a := ir.SepCopy(n) if !s.staticassign(a, e.Expr) { - s.append(nod(OAS, a, e.Expr)) + s.append(ir.Nod(ir.OAS, a, e.Expr)) } } return true - case OMAPLIT: + case ir.OMAPLIT: break - case OCLOSURE: + case ir.OCLOSURE: if hasemptycvars(r) { if base.Debug.Closure > 0 { base.WarnfAt(r.Pos, "closure converted to global") @@ -267,13 +268,13 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { } closuredebugruntimecheck(r) - case OCONVIFACE: + case ir.OCONVIFACE: // This logic is mirrored in isStaticCompositeLiteral. // If you change something here, change it there, and vice versa. // Determine the underlying concrete type and value we are converting from. val := r - for val.Op == OCONVIFACE { + for val.Op == ir.OCONVIFACE { val = val.Left } @@ -283,12 +284,12 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { // both words are zero and so there no work to do, so report success. // If val is non-nil, we have no concrete type to record, // and we won't be able to statically initialize its value, so report failure. - return val.Op == ONIL + return val.Op == ir.ONIL } markTypeUsedInInterface(val.Type, l.Sym.Linksym()) - var itab *Node + var itab *ir.Node if l.Type.IsEmptyInterface() { itab = typename(val.Type) } else { @@ -296,7 +297,7 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { } // Create a copy of l to modify while we emit data. - n := l.copy() + n := ir.Copy(l) // Emit itab, advance offset. addrsym(n, itab.Left) // itab is an OADDR node @@ -304,23 +305,23 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { // Emit data. if isdirectiface(val.Type) { - if val.Op == ONIL { + if val.Op == ir.ONIL { // Nil is zero, nothing to do. return true } // Copy val directly into n. n.Type = val.Type setlineno(val) - a := n.sepcopy() + a := ir.SepCopy(n) if !s.staticassign(a, val) { - s.append(nod(OAS, a, val)) + s.append(ir.Nod(ir.OAS, a, val)) } } else { // Construct temp to hold val, write pointer to temp into n. a := staticname(val.Type) s.inittemps[val] = a if !s.staticassign(a, val) { - s.append(nod(OAS, a, val)) + s.append(ir.Nod(ir.OAS, a, val)) } addrsym(n, a) } @@ -366,29 +367,29 @@ var statuniqgen int // name generator for static temps // staticname returns a name backed by a (writable) static data symbol. // Use readonlystaticname for read-only node. -func staticname(t *types.Type) *Node { +func staticname(t *types.Type) *ir.Node { // Don't use lookupN; it interns the resulting string, but these are all unique. - n := newname(lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen))) + n := NewName(lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen))) statuniqgen++ - addvar(n, t, PEXTERN) + addvar(n, t, ir.PEXTERN) n.Sym.Linksym().Set(obj.AttrLocal, true) return n } // readonlystaticname returns a name backed by a (writable) static data symbol. -func readonlystaticname(t *types.Type) *Node { +func readonlystaticname(t *types.Type) *ir.Node { n := staticname(t) n.MarkReadonly() n.Sym.Linksym().Set(obj.AttrContentAddressable, true) return n } -func (n *Node) isSimpleName() bool { - return (n.Op == ONAME || n.Op == OMETHEXPR) && n.Class() != PAUTOHEAP && n.Class() != PEXTERN +func isSimpleName(n *ir.Node) bool { + return (n.Op == ir.ONAME || n.Op == ir.OMETHEXPR) && n.Class() != ir.PAUTOHEAP && n.Class() != ir.PEXTERN } -func litas(l *Node, r *Node, init *Nodes) { - a := nod(OAS, l, r) +func litas(l *ir.Node, r *ir.Node, init *ir.Nodes) { + a := ir.Nod(ir.OAS, l, r) a = typecheck(a, ctxStmt) a = walkexpr(a, init) init.Append(a) @@ -404,15 +405,15 @@ const ( // getdyn calculates the initGenType for n. // If top is false, getdyn is recursing. -func getdyn(n *Node, top bool) initGenType { +func getdyn(n *ir.Node, top bool) initGenType { switch n.Op { default: - if n.isGoConst() { + if isGoConst(n) { return initConst } return initDynamic - case OSLICELIT: + case ir.OSLICELIT: if !top { return initDynamic } @@ -426,15 +427,15 @@ func getdyn(n *Node, top bool) initGenType { return initDynamic } - case OARRAYLIT, OSTRUCTLIT: + case ir.OARRAYLIT, ir.OSTRUCTLIT: } var mode initGenType for _, n1 := range n.List.Slice() { switch n1.Op { - case OKEY: + case ir.OKEY: n1 = n1.Right - case OSTRUCTKEY: + case ir.OSTRUCTKEY: n1 = n1.Left } mode |= getdyn(n1, false) @@ -446,13 +447,13 @@ func getdyn(n *Node, top bool) initGenType { } // isStaticCompositeLiteral reports whether n is a compile-time constant. -func isStaticCompositeLiteral(n *Node) bool { +func isStaticCompositeLiteral(n *ir.Node) bool { switch n.Op { - case OSLICELIT: + case ir.OSLICELIT: return false - case OARRAYLIT: + case ir.OARRAYLIT: for _, r := range n.List.Slice() { - if r.Op == OKEY { + if r.Op == ir.OKEY { r = r.Right } if !isStaticCompositeLiteral(r) { @@ -460,9 +461,9 @@ func isStaticCompositeLiteral(n *Node) bool { } } return true - case OSTRUCTLIT: + case ir.OSTRUCTLIT: for _, r := range n.List.Slice() { - if r.Op != OSTRUCTKEY { + if r.Op != ir.OSTRUCTKEY { base.Fatalf("isStaticCompositeLiteral: rhs not OSTRUCTKEY: %v", r) } if !isStaticCompositeLiteral(r.Left) { @@ -470,18 +471,18 @@ func isStaticCompositeLiteral(n *Node) bool { } } return true - case OLITERAL, ONIL: + case ir.OLITERAL, ir.ONIL: return true - case OCONVIFACE: + case ir.OCONVIFACE: // See staticassign's OCONVIFACE case for comments. val := n - for val.Op == OCONVIFACE { + for val.Op == ir.OCONVIFACE { val = val.Left } if val.Type.IsInterface() { - return val.Op == ONIL + return val.Op == ir.ONIL } - if isdirectiface(val.Type) && val.Op == ONIL { + if isdirectiface(val.Type) && val.Op == ir.ONIL { return true } return isStaticCompositeLiteral(val) @@ -508,37 +509,37 @@ const ( // fixedlit handles struct, array, and slice literals. // TODO: expand documentation. -func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes) { - isBlank := var_ == nblank - var splitnode func(*Node) (a *Node, value *Node) +func fixedlit(ctxt initContext, kind initKind, n *ir.Node, var_ *ir.Node, init *ir.Nodes) { + isBlank := var_ == ir.BlankNode + var splitnode func(*ir.Node) (a *ir.Node, value *ir.Node) switch n.Op { - case OARRAYLIT, OSLICELIT: + case ir.OARRAYLIT, ir.OSLICELIT: var k int64 - splitnode = func(r *Node) (*Node, *Node) { - if r.Op == OKEY { + splitnode = func(r *ir.Node) (*ir.Node, *ir.Node) { + if r.Op == ir.OKEY { k = indexconst(r.Left) if k < 0 { base.Fatalf("fixedlit: invalid index %v", r.Left) } r = r.Right } - a := nod(OINDEX, var_, nodintconst(k)) + a := ir.Nod(ir.OINDEX, var_, nodintconst(k)) k++ if isBlank { - a = nblank + a = ir.BlankNode } return a, r } - case OSTRUCTLIT: - splitnode = func(r *Node) (*Node, *Node) { - if r.Op != OSTRUCTKEY { + case ir.OSTRUCTLIT: + splitnode = func(r *ir.Node) (*ir.Node, *ir.Node) { + if r.Op != ir.OSTRUCTKEY { base.Fatalf("fixedlit: rhs not OSTRUCTKEY: %v", r) } if r.Sym.IsBlank() || isBlank { - return nblank, r.Left + return ir.BlankNode, r.Left } setlineno(r) - return nodSym(ODOT, var_, r.Sym), r.Left + return nodSym(ir.ODOT, var_, r.Sym), r.Left } default: base.Fatalf("fixedlit bad op: %v", n.Op) @@ -546,36 +547,36 @@ func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes) for _, r := range n.List.Slice() { a, value := splitnode(r) - if a == nblank && candiscard(value) { + if a == ir.BlankNode && candiscard(value) { continue } switch value.Op { - case OSLICELIT: + case ir.OSLICELIT: if (kind == initKindStatic && ctxt == inNonInitFunction) || (kind == initKindDynamic && ctxt == inInitFunction) { slicelit(ctxt, value, a, init) continue } - case OARRAYLIT, OSTRUCTLIT: + case ir.OARRAYLIT, ir.OSTRUCTLIT: fixedlit(ctxt, kind, value, a, init) continue } - islit := value.isGoConst() + islit := isGoConst(value) if (kind == initKindStatic && !islit) || (kind == initKindDynamic && islit) { continue } // build list of assignments: var[index] = expr setlineno(a) - a = nod(OAS, a, value) + a = ir.Nod(ir.OAS, a, value) a = typecheck(a, ctxStmt) switch kind { case initKindStatic: genAsStatic(a) case initKindDynamic, initKindLocalCode: - a = orderStmtInPlace(a, map[string][]*Node{}) + a = orderStmtInPlace(a, map[string][]*ir.Node{}) a = walkstmt(a) init.Append(a) default: @@ -585,8 +586,8 @@ func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes) } } -func isSmallSliceLit(n *Node) bool { - if n.Op != OSLICELIT { +func isSmallSliceLit(n *ir.Node) bool { + if n.Op != ir.OSLICELIT { return false } @@ -595,7 +596,7 @@ func isSmallSliceLit(n *Node) bool { return smallintconst(r) && (n.Type.Elem().Width == 0 || r.Int64Val() <= smallArrayBytes/n.Type.Elem().Width) } -func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { +func slicelit(ctxt initContext, n *ir.Node, var_ *ir.Node, init *ir.Nodes) { // make an array type corresponding the number of elements we have t := types.NewArray(n.Type.Elem(), n.Right.Int64Val()) dowidth(t) @@ -610,7 +611,7 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { // copy static to slice var_ = typecheck(var_, ctxExpr|ctxAssign) nam := stataddr(var_) - if nam == nil || nam.Class() != PEXTERN { + if nam == nil || nam.Class() != ir.PEXTERN { base.Fatalf("slicelit: %v", var_) } slicesym(nam, vstat, t.NumElem()) @@ -638,7 +639,7 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { // if the literal contains constants, // make static initialized array (1),(2) - var vstat *Node + var vstat *ir.Node mode := getdyn(n, true) if mode&initConst != 0 && !isSmallSliceLit(n) { @@ -654,7 +655,7 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { vauto := temp(types.NewPtr(t)) // set auto to point at new temp or heap (3 assign) - var a *Node + var a *ir.Node if x := prealloc[n]; x != nil { // temp allocated during order.go for dddarg if !types.Identical(t, x.Type) { @@ -662,43 +663,43 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { } if vstat == nil { - a = nod(OAS, x, nil) + a = ir.Nod(ir.OAS, x, nil) a = typecheck(a, ctxStmt) init.Append(a) // zero new temp } else { // Declare that we're about to initialize all of x. // (Which happens at the *vauto = vstat below.) - init.Append(nod(OVARDEF, x, nil)) + init.Append(ir.Nod(ir.OVARDEF, x, nil)) } - a = nod(OADDR, x, nil) + a = ir.Nod(ir.OADDR, x, nil) } else if n.Esc == EscNone { a = temp(t) if vstat == nil { - a = nod(OAS, temp(t), nil) + a = ir.Nod(ir.OAS, temp(t), nil) a = typecheck(a, ctxStmt) init.Append(a) // zero new temp a = a.Left } else { - init.Append(nod(OVARDEF, a, nil)) + init.Append(ir.Nod(ir.OVARDEF, a, nil)) } - a = nod(OADDR, a, nil) + a = ir.Nod(ir.OADDR, a, nil) } else { - a = nod(ONEW, nil, nil) + a = ir.Nod(ir.ONEW, nil, nil) a.List.Set1(typenod(t)) } - a = nod(OAS, vauto, a) + a = ir.Nod(ir.OAS, vauto, a) a = typecheck(a, ctxStmt) a = walkexpr(a, init) init.Append(a) if vstat != nil { // copy static to heap (4) - a = nod(ODEREF, vauto, nil) + a = ir.Nod(ir.ODEREF, vauto, nil) - a = nod(OAS, a, vstat) + a = ir.Nod(ir.OAS, a, vstat) a = typecheck(a, ctxStmt) a = walkexpr(a, init) init.Append(a) @@ -707,24 +708,24 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { // put dynamics into array (5) var index int64 for _, value := range n.List.Slice() { - if value.Op == OKEY { + if value.Op == ir.OKEY { index = indexconst(value.Left) if index < 0 { base.Fatalf("slicelit: invalid index %v", value.Left) } value = value.Right } - a := nod(OINDEX, vauto, nodintconst(index)) + a := ir.Nod(ir.OINDEX, vauto, nodintconst(index)) a.SetBounded(true) index++ // TODO need to check bounds? switch value.Op { - case OSLICELIT: + case ir.OSLICELIT: break - case OARRAYLIT, OSTRUCTLIT: + case ir.OARRAYLIT, ir.OSTRUCTLIT: k := initKindDynamic if vstat == nil { // Generate both static and dynamic initializations. @@ -735,32 +736,32 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { continue } - if vstat != nil && value.isGoConst() { // already set by copy from static value + if vstat != nil && isGoConst(value) { // already set by copy from static value continue } // build list of vauto[c] = expr setlineno(value) - a = nod(OAS, a, value) + a = ir.Nod(ir.OAS, a, value) a = typecheck(a, ctxStmt) - a = orderStmtInPlace(a, map[string][]*Node{}) + a = orderStmtInPlace(a, map[string][]*ir.Node{}) a = walkstmt(a) init.Append(a) } // make slice out of heap (6) - a = nod(OAS, var_, nod(OSLICE, vauto, nil)) + a = ir.Nod(ir.OAS, var_, ir.Nod(ir.OSLICE, vauto, nil)) a = typecheck(a, ctxStmt) - a = orderStmtInPlace(a, map[string][]*Node{}) + a = orderStmtInPlace(a, map[string][]*ir.Node{}) a = walkstmt(a) init.Append(a) } -func maplit(n *Node, m *Node, init *Nodes) { +func maplit(n *ir.Node, m *ir.Node, init *ir.Nodes) { // make the map var - a := nod(OMAKE, nil, nil) + a := ir.Nod(ir.OMAKE, nil, nil) a.Esc = n.Esc a.List.Set2(typenod(n.Type), nodintconst(int64(n.List.Len()))) litas(m, a, init) @@ -792,8 +793,8 @@ func maplit(n *Node, m *Node, init *Nodes) { vstatk := readonlystaticname(tk) vstate := readonlystaticname(te) - datak := nod(OARRAYLIT, nil, nil) - datae := nod(OARRAYLIT, nil, nil) + datak := ir.Nod(ir.OARRAYLIT, nil, nil) + datae := ir.Nod(ir.OARRAYLIT, nil, nil) for _, r := range entries { datak.List.Append(r.Left) datae.List.Append(r.Right) @@ -805,20 +806,20 @@ func maplit(n *Node, m *Node, init *Nodes) { // for i = 0; i < len(vstatk); i++ { // map[vstatk[i]] = vstate[i] // } - i := temp(types.Types[TINT]) - rhs := nod(OINDEX, vstate, i) + i := temp(types.Types[types.TINT]) + rhs := ir.Nod(ir.OINDEX, vstate, i) rhs.SetBounded(true) - kidx := nod(OINDEX, vstatk, i) + kidx := ir.Nod(ir.OINDEX, vstatk, i) kidx.SetBounded(true) - lhs := nod(OINDEX, m, kidx) + lhs := ir.Nod(ir.OINDEX, m, kidx) - zero := nod(OAS, i, nodintconst(0)) - cond := nod(OLT, i, nodintconst(tk.NumElem())) - incr := nod(OAS, i, nod(OADD, i, nodintconst(1))) - body := nod(OAS, lhs, rhs) + zero := ir.Nod(ir.OAS, i, nodintconst(0)) + cond := ir.Nod(ir.OLT, i, nodintconst(tk.NumElem())) + incr := ir.Nod(ir.OAS, i, ir.Nod(ir.OADD, i, nodintconst(1))) + body := ir.Nod(ir.OAS, lhs, rhs) - loop := nod(OFOR, cond, incr) + loop := ir.Nod(ir.OFOR, cond, incr) loop.Nbody.Set1(body) loop.Ninit.Set1(zero) @@ -839,88 +840,88 @@ func maplit(n *Node, m *Node, init *Nodes) { index, elem := r.Left, r.Right setlineno(index) - a := nod(OAS, tmpkey, index) + a := ir.Nod(ir.OAS, tmpkey, index) a = typecheck(a, ctxStmt) a = walkstmt(a) init.Append(a) setlineno(elem) - a = nod(OAS, tmpelem, elem) + a = ir.Nod(ir.OAS, tmpelem, elem) a = typecheck(a, ctxStmt) a = walkstmt(a) init.Append(a) setlineno(tmpelem) - a = nod(OAS, nod(OINDEX, m, tmpkey), tmpelem) + a = ir.Nod(ir.OAS, ir.Nod(ir.OINDEX, m, tmpkey), tmpelem) a = typecheck(a, ctxStmt) a = walkstmt(a) init.Append(a) } - a = nod(OVARKILL, tmpkey, nil) + a = ir.Nod(ir.OVARKILL, tmpkey, nil) a = typecheck(a, ctxStmt) init.Append(a) - a = nod(OVARKILL, tmpelem, nil) + a = ir.Nod(ir.OVARKILL, tmpelem, nil) a = typecheck(a, ctxStmt) init.Append(a) } -func anylit(n *Node, var_ *Node, init *Nodes) { +func anylit(n *ir.Node, var_ *ir.Node, init *ir.Nodes) { t := n.Type switch n.Op { default: base.Fatalf("anylit: not lit, op=%v node=%v", n.Op, n) - case ONAME, OMETHEXPR: - a := nod(OAS, var_, n) + case ir.ONAME, ir.OMETHEXPR: + a := ir.Nod(ir.OAS, var_, n) a = typecheck(a, ctxStmt) init.Append(a) - case OPTRLIT: + case ir.OPTRLIT: if !t.IsPtr() { base.Fatalf("anylit: not ptr") } - var r *Node + var r *ir.Node if n.Right != nil { // n.Right is stack temporary used as backing store. - init.Append(nod(OAS, n.Right, nil)) // zero backing store, just in case (#18410) - r = nod(OADDR, n.Right, nil) + init.Append(ir.Nod(ir.OAS, n.Right, nil)) // zero backing store, just in case (#18410) + r = ir.Nod(ir.OADDR, n.Right, nil) r = typecheck(r, ctxExpr) } else { - r = nod(ONEW, nil, nil) + r = ir.Nod(ir.ONEW, nil, nil) r.SetTypecheck(1) r.Type = t r.Esc = n.Esc } r = walkexpr(r, init) - a := nod(OAS, var_, r) + a := ir.Nod(ir.OAS, var_, r) a = typecheck(a, ctxStmt) init.Append(a) - var_ = nod(ODEREF, var_, nil) + var_ = ir.Nod(ir.ODEREF, var_, nil) var_ = typecheck(var_, ctxExpr|ctxAssign) anylit(n.Left, var_, init) - case OSTRUCTLIT, OARRAYLIT: + case ir.OSTRUCTLIT, ir.OARRAYLIT: if !t.IsStruct() && !t.IsArray() { base.Fatalf("anylit: not struct/array") } - if var_.isSimpleName() && n.List.Len() > 4 { + if isSimpleName(var_) && n.List.Len() > 4 { // lay out static data vstat := readonlystaticname(t) ctxt := inInitFunction - if n.Op == OARRAYLIT { + if n.Op == ir.OARRAYLIT { ctxt = inNonInitFunction } fixedlit(ctxt, initKindStatic, n, vstat, init) // copy static to var - a := nod(OAS, var_, vstat) + a := ir.Nod(ir.OAS, var_, vstat) a = typecheck(a, ctxStmt) a = walkexpr(a, init) @@ -932,14 +933,14 @@ func anylit(n *Node, var_ *Node, init *Nodes) { } var components int64 - if n.Op == OARRAYLIT { + if n.Op == ir.OARRAYLIT { components = t.NumElem() } else { components = int64(t.NumFields()) } // initialization of an array or struct with unspecified components (missing fields or arrays) - if var_.isSimpleName() || int64(n.List.Len()) < components { - a := nod(OAS, var_, nil) + if isSimpleName(var_) || int64(n.List.Len()) < components { + a := ir.Nod(ir.OAS, var_, nil) a = typecheck(a, ctxStmt) a = walkexpr(a, init) init.Append(a) @@ -947,10 +948,10 @@ func anylit(n *Node, var_ *Node, init *Nodes) { fixedlit(inInitFunction, initKindLocalCode, n, var_, init) - case OSLICELIT: + case ir.OSLICELIT: slicelit(inInitFunction, n, var_, init) - case OMAPLIT: + case ir.OMAPLIT: if !t.IsMap() { base.Fatalf("anylit: not map") } @@ -958,7 +959,7 @@ func anylit(n *Node, var_ *Node, init *Nodes) { } } -func oaslit(n *Node, init *Nodes) bool { +func oaslit(n *ir.Node, init *ir.Nodes) bool { if n.Left == nil || n.Right == nil { // not a special composite literal assignment return false @@ -967,7 +968,7 @@ func oaslit(n *Node, init *Nodes) bool { // not a special composite literal assignment return false } - if !n.Left.isSimpleName() { + if !isSimpleName(n.Left) { // not a special composite literal assignment return false } @@ -981,7 +982,7 @@ func oaslit(n *Node, init *Nodes) bool { // not a special composite literal assignment return false - case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT: + case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT: if vmatch1(n.Left, n.Right) { // not a special composite literal assignment return false @@ -989,12 +990,12 @@ func oaslit(n *Node, init *Nodes) bool { anylit(n.Right, n.Left, init) } - n.Op = OEMPTY + n.Op = ir.OEMPTY n.Right = nil return true } -func getlit(lit *Node) int { +func getlit(lit *ir.Node) int { if smallintconst(lit) { return int(lit.Int64Val()) } @@ -1002,16 +1003,16 @@ func getlit(lit *Node) int { } // stataddr returns the static address of n, if n has one, or else nil. -func stataddr(n *Node) *Node { +func stataddr(n *ir.Node) *ir.Node { if n == nil { return nil } switch n.Op { - case ONAME, OMETHEXPR: - return n.sepcopy() + case ir.ONAME, ir.OMETHEXPR: + return ir.SepCopy(n) - case ODOT: + case ir.ODOT: nam := stataddr(n.Left) if nam == nil { break @@ -1020,7 +1021,7 @@ func stataddr(n *Node) *Node { nam.Type = n.Type return nam - case OINDEX: + case ir.OINDEX: if n.Left.Type.IsSlice() { break } @@ -1045,7 +1046,7 @@ func stataddr(n *Node) *Node { return nil } -func (s *InitSchedule) initplan(n *Node) { +func (s *InitSchedule) initplan(n *ir.Node) { if s.initplans[n] != nil { return } @@ -1055,10 +1056,10 @@ func (s *InitSchedule) initplan(n *Node) { default: base.Fatalf("initplan") - case OARRAYLIT, OSLICELIT: + case ir.OARRAYLIT, ir.OSLICELIT: var k int64 for _, a := range n.List.Slice() { - if a.Op == OKEY { + if a.Op == ir.OKEY { k = indexconst(a.Left) if k < 0 { base.Fatalf("initplan arraylit: invalid index %v", a.Left) @@ -1069,9 +1070,9 @@ func (s *InitSchedule) initplan(n *Node) { k++ } - case OSTRUCTLIT: + case ir.OSTRUCTLIT: for _, a := range n.List.Slice() { - if a.Op != OSTRUCTKEY { + if a.Op != ir.OSTRUCTKEY { base.Fatalf("initplan structlit") } if a.Sym.IsBlank() { @@ -1080,9 +1081,9 @@ func (s *InitSchedule) initplan(n *Node) { s.addvalue(p, a.Xoffset, a.Left) } - case OMAPLIT: + case ir.OMAPLIT: for _, a := range n.List.Slice() { - if a.Op != OKEY { + if a.Op != ir.OKEY { base.Fatalf("initplan maplit") } s.addvalue(p, -1, a.Right) @@ -1090,7 +1091,7 @@ func (s *InitSchedule) initplan(n *Node) { } } -func (s *InitSchedule) addvalue(p *InitPlan, xoffset int64, n *Node) { +func (s *InitSchedule) addvalue(p *InitPlan, xoffset int64, n *ir.Node) { // special case: zero can be dropped entirely if isZero(n) { return @@ -1112,12 +1113,12 @@ func (s *InitSchedule) addvalue(p *InitPlan, xoffset int64, n *Node) { p.E = append(p.E, InitEntry{Xoffset: xoffset, Expr: n}) } -func isZero(n *Node) bool { +func isZero(n *ir.Node) bool { switch n.Op { - case ONIL: + case ir.ONIL: return true - case OLITERAL: + case ir.OLITERAL: switch u := n.Val(); u.Kind() { case constant.String: return constant.StringVal(u) == "" @@ -1127,9 +1128,9 @@ func isZero(n *Node) bool { return constant.Sign(u) == 0 } - case OARRAYLIT: + case ir.OARRAYLIT: for _, n1 := range n.List.Slice() { - if n1.Op == OKEY { + if n1.Op == ir.OKEY { n1 = n1.Right } if !isZero(n1) { @@ -1138,7 +1139,7 @@ func isZero(n *Node) bool { } return true - case OSTRUCTLIT: + case ir.OSTRUCTLIT: for _, n1 := range n.List.Slice() { if !isZero(n1.Left) { return false @@ -1150,24 +1151,24 @@ func isZero(n *Node) bool { return false } -func isvaluelit(n *Node) bool { - return n.Op == OARRAYLIT || n.Op == OSTRUCTLIT +func isvaluelit(n *ir.Node) bool { + return n.Op == ir.OARRAYLIT || n.Op == ir.OSTRUCTLIT } -func genAsStatic(as *Node) { +func genAsStatic(as *ir.Node) { if as.Left.Type == nil { base.Fatalf("genAsStatic as.Left not typechecked") } nam := stataddr(as.Left) - if nam == nil || (nam.Class() != PEXTERN && as.Left != nblank) { + if nam == nil || (nam.Class() != ir.PEXTERN && as.Left != ir.BlankNode) { base.Fatalf("genAsStatic: lhs %v", as.Left) } switch { - case as.Right.Op == OLITERAL: + case as.Right.Op == ir.OLITERAL: litsym(nam, as.Right, int(as.Right.Type.Width)) - case (as.Right.Op == ONAME || as.Right.Op == OMETHEXPR) && as.Right.Class() == PFUNC: + case (as.Right.Op == ir.ONAME || as.Right.Op == ir.OMETHEXPR) && as.Right.Class() == ir.PFUNC: pfuncsym(nam, as.Right) default: base.Fatalf("genAsStatic: rhs %v", as.Right) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index e892a01da08..658ea28fbe2 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -16,6 +16,7 @@ import ( "bufio" "bytes" "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/ssa" "cmd/compile/internal/types" "cmd/internal/obj" @@ -39,7 +40,7 @@ const ssaDumpFile = "ssa.html" const maxOpenDefers = 8 // ssaDumpInlined holds all inlined functions when ssaDump contains a function name. -var ssaDumpInlined []*Node +var ssaDumpInlined []*ir.Node func initssaconfig() { types_ := ssa.NewTypes() @@ -50,16 +51,16 @@ func initssaconfig() { // Generate a few pointer types that are uncommon in the frontend but common in the backend. // Caching is disabled in the backend, so generating these here avoids allocations. - _ = types.NewPtr(types.Types[TINTER]) // *interface{} - _ = types.NewPtr(types.NewPtr(types.Types[TSTRING])) // **string - _ = types.NewPtr(types.NewSlice(types.Types[TINTER])) // *[]interface{} - _ = types.NewPtr(types.NewPtr(types.Bytetype)) // **byte - _ = types.NewPtr(types.NewSlice(types.Bytetype)) // *[]byte - _ = types.NewPtr(types.NewSlice(types.Types[TSTRING])) // *[]string - _ = types.NewPtr(types.NewPtr(types.NewPtr(types.Types[TUINT8]))) // ***uint8 - _ = types.NewPtr(types.Types[TINT16]) // *int16 - _ = types.NewPtr(types.Types[TINT64]) // *int64 - _ = types.NewPtr(types.Errortype) // *error + _ = types.NewPtr(types.Types[types.TINTER]) // *interface{} + _ = types.NewPtr(types.NewPtr(types.Types[types.TSTRING])) // **string + _ = types.NewPtr(types.NewSlice(types.Types[types.TINTER])) // *[]interface{} + _ = types.NewPtr(types.NewPtr(types.Bytetype)) // **byte + _ = types.NewPtr(types.NewSlice(types.Bytetype)) // *[]byte + _ = types.NewPtr(types.NewSlice(types.Types[types.TSTRING])) // *[]string + _ = types.NewPtr(types.NewPtr(types.NewPtr(types.Types[types.TUINT8]))) // ***uint8 + _ = types.NewPtr(types.Types[types.TINT16]) // *int16 + _ = types.NewPtr(types.Types[types.TINT64]) // *int64 + _ = types.NewPtr(types.Errortype) // *error types.NewPtrCacheEnabled = false ssaConfig = ssa.NewConfig(thearch.LinkArch.Name, *types_, base.Ctxt, base.Flag.N == 0) ssaConfig.SoftFloat = thearch.SoftFloat @@ -185,9 +186,9 @@ func initssaconfig() { // function/method/interface call), where the receiver of a method call is // considered as the 0th parameter. This does not include the receiver of an // interface call. -func getParam(n *Node, i int) *types.Field { +func getParam(n *ir.Node, i int) *types.Field { t := n.Left.Type - if n.Op == OCALLMETH { + if n.Op == ir.OCALLMETH { if i == 0 { return t.Recv() } @@ -241,8 +242,8 @@ func dvarint(x *obj.LSym, off int, v int64) int { // - Size of the argument // - Offset of where argument should be placed in the args frame when making call func (s *state) emitOpenDeferInfo() { - x := base.Ctxt.Lookup(s.curfn.Func.lsym.Name + ".opendefer") - s.curfn.Func.lsym.Func().OpenCodedDeferInfo = x + x := base.Ctxt.Lookup(s.curfn.Func.LSym.Name + ".opendefer") + s.curfn.Func.LSym.Func().OpenCodedDeferInfo = x off := 0 // Compute maxargsize (max size of arguments for all defers) @@ -288,8 +289,8 @@ func (s *state) emitOpenDeferInfo() { // buildssa builds an SSA function for fn. // worker indicates which of the backend workers is doing the processing. -func buildssa(fn *Node, worker int) *ssa.Func { - name := fn.funcname() +func buildssa(fn *ir.Node, worker int) *ssa.Func { + name := ir.FuncName(fn) printssa := false if ssaDump != "" { // match either a simple name e.g. "(*Reader).Reset", or a package.name e.g. "compress/gzip.(*Reader).Reset" printssa = name == ssaDump || base.Ctxt.Pkgpath+"."+name == ssaDump @@ -297,9 +298,9 @@ func buildssa(fn *Node, worker int) *ssa.Func { var astBuf *bytes.Buffer if printssa { astBuf = &bytes.Buffer{} - fdumplist(astBuf, "buildssa-enter", fn.Func.Enter) - fdumplist(astBuf, "buildssa-body", fn.Nbody) - fdumplist(astBuf, "buildssa-exit", fn.Func.Exit) + ir.FDumpList(astBuf, "buildssa-enter", fn.Func.Enter) + ir.FDumpList(astBuf, "buildssa-body", fn.Nbody) + ir.FDumpList(astBuf, "buildssa-exit", fn.Func.Exit) if ssaDumpStdout { fmt.Println("generating SSA for", name) fmt.Print(astBuf.String()) @@ -311,7 +312,7 @@ func buildssa(fn *Node, worker int) *ssa.Func { defer s.popLine() s.hasdefer = fn.Func.HasDefer() - if fn.Func.Pragma&CgoUnsafeArgs != 0 { + if fn.Func.Pragma&ir.CgoUnsafeArgs != 0 { s.cgoUnsafeArgs = true } @@ -330,7 +331,7 @@ func buildssa(fn *Node, worker int) *ssa.Func { s.f.Name = name s.f.DebugTest = s.f.DebugHashMatch("GOSSAHASH") s.f.PrintOrHtmlSSA = printssa - if fn.Func.Pragma&Nosplit != 0 { + if fn.Func.Pragma&ir.Nosplit != 0 { s.f.NoSplit = true } s.panics = map[funcLine]*ssa.Block{} @@ -355,8 +356,8 @@ func buildssa(fn *Node, worker int) *ssa.Func { // Allocate starting values s.labels = map[string]*ssaLabel{} - s.labeledNodes = map[*Node]*ssaLabel{} - s.fwdVars = map[*Node]*ssa.Value{} + s.labeledNodes = map[*ir.Node]*ssaLabel{} + s.fwdVars = map[*ir.Node]*ssa.Value{} s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem) s.hasOpenDefers = base.Flag.N == 0 && s.hasdefer && !s.curfn.Func.OpenCodedDeferDisallowed() @@ -376,7 +377,7 @@ func buildssa(fn *Node, worker int) *ssa.Func { s.hasOpenDefers = false } if s.hasOpenDefers && - s.curfn.Func.numReturns*s.curfn.Func.numDefers > 15 { + s.curfn.Func.NumReturns*s.curfn.Func.NumDefers > 15 { // Since we are generating defer calls at every exit for // open-coded defers, skip doing open-coded defers if there are // too many returns (especially if there are multiple defers). @@ -385,8 +386,8 @@ func buildssa(fn *Node, worker int) *ssa.Func { s.hasOpenDefers = false } - s.sp = s.entryNewValue0(ssa.OpSP, types.Types[TUINTPTR]) // TODO: use generic pointer type (unsafe.Pointer?) instead - s.sb = s.entryNewValue0(ssa.OpSB, types.Types[TUINTPTR]) + s.sp = s.entryNewValue0(ssa.OpSP, types.Types[types.TUINTPTR]) // TODO: use generic pointer type (unsafe.Pointer?) instead + s.sb = s.entryNewValue0(ssa.OpSB, types.Types[types.TUINTPTR]) s.startBlock(s.f.Entry) s.vars[memVar] = s.startmem @@ -394,13 +395,13 @@ func buildssa(fn *Node, worker int) *ssa.Func { // Create the deferBits variable and stack slot. deferBits is a // bitmask showing which of the open-coded defers in this function // have been activated. - deferBitsTemp := tempAt(src.NoXPos, s.curfn, types.Types[TUINT8]) + deferBitsTemp := tempAt(src.NoXPos, s.curfn, types.Types[types.TUINT8]) s.deferBitsTemp = deferBitsTemp // For this value, AuxInt is initialized to zero by default - startDeferBits := s.entryNewValue0(ssa.OpConst8, types.Types[TUINT8]) + startDeferBits := s.entryNewValue0(ssa.OpConst8, types.Types[types.TUINT8]) s.vars[deferBitsVar] = startDeferBits s.deferBitsAddr = s.addr(deferBitsTemp) - s.store(types.Types[TUINT8], s.deferBitsAddr, startDeferBits) + s.store(types.Types[types.TUINT8], s.deferBitsAddr, startDeferBits) // Make sure that the deferBits stack slot is kept alive (for use // by panics) and stores to deferBits are not eliminated, even if // all checking code on deferBits in the function exit can be @@ -410,15 +411,15 @@ func buildssa(fn *Node, worker int) *ssa.Func { } // Generate addresses of local declarations - s.decladdrs = map[*Node]*ssa.Value{} + s.decladdrs = map[*ir.Node]*ssa.Value{} var args []ssa.Param var results []ssa.Param for _, n := range fn.Func.Dcl { switch n.Class() { - case PPARAM: + case ir.PPARAM: s.decladdrs[n] = s.entryNewValue2A(ssa.OpLocalAddr, types.NewPtr(n.Type), n, s.sp, s.startmem) args = append(args, ssa.Param{Type: n.Type, Offset: int32(n.Xoffset)}) - case PPARAMOUT: + case ir.PPARAMOUT: s.decladdrs[n] = s.entryNewValue2A(ssa.OpLocalAddr, types.NewPtr(n.Type), n, s.sp, s.startmem) results = append(results, ssa.Param{Type: n.Type, Offset: int32(n.Xoffset)}) if s.canSSA(n) { @@ -427,12 +428,12 @@ func buildssa(fn *Node, worker int) *ssa.Func { // the function. s.returns = append(s.returns, n) } - case PAUTO: + case ir.PAUTO: // processed at each use, to prevent Addr coming // before the decl. - case PAUTOHEAP: + case ir.PAUTOHEAP: // moved to heap - already handled by frontend - case PFUNC: + case ir.PFUNC: // local function - already handled by frontend default: s.Fatalf("local variable with class %v unimplemented", n.Class()) @@ -441,7 +442,7 @@ func buildssa(fn *Node, worker int) *ssa.Func { // Populate SSAable arguments. for _, n := range fn.Func.Dcl { - if n.Class() == PPARAM && s.canSSA(n) { + if n.Class() == ir.PPARAM && s.canSSA(n) { v := s.newValue0A(ssa.OpArg, n.Type, n) s.vars[n] = v s.addNamedValue(n, v) // This helps with debugging information, not needed for compilation itself. @@ -477,7 +478,7 @@ func buildssa(fn *Node, worker int) *ssa.Func { return s.f } -func dumpSourcesColumn(writer *ssa.HTMLWriter, fn *Node) { +func dumpSourcesColumn(writer *ssa.HTMLWriter, fn *ir.Node) { // Read sources of target function fn. fname := base.Ctxt.PosTable.Pos(fn.Pos).Filename() targetFn, err := readFuncLines(fname, fn.Pos.Line(), fn.Func.Endlineno.Line()) @@ -565,24 +566,24 @@ func (s *state) updateUnsetPredPos(b *ssa.Block) { // Information about each open-coded defer. type openDeferInfo struct { // The ODEFER node representing the function call of the defer - n *Node + n *ir.Node // If defer call is closure call, the address of the argtmp where the // closure is stored. closure *ssa.Value // The node representing the argtmp where the closure is stored - used for // function, method, or interface call, to store a closure that panic // processing can use for this defer. - closureNode *Node + closureNode *ir.Node // If defer call is interface call, the address of the argtmp where the // receiver is stored rcvr *ssa.Value // The node representing the argtmp where the receiver is stored - rcvrNode *Node + rcvrNode *ir.Node // The addresses of the argtmps where the evaluated arguments of the defer // function call are stored. argVals []*ssa.Value // The nodes representing the argtmps where the args of the defer are stored - argNodes []*Node + argNodes []*ir.Node } type state struct { @@ -593,11 +594,11 @@ type state struct { f *ssa.Func // Node for function - curfn *Node + curfn *ir.Node // labels and labeled control flow nodes (OFOR, OFORUNTIL, OSWITCH, OSELECT) in f labels map[string]*ssaLabel - labeledNodes map[*Node]*ssaLabel + labeledNodes map[*ir.Node]*ssaLabel // unlabeled break and continue statement tracking breakTo *ssa.Block // current target for plain break statement @@ -609,18 +610,18 @@ type state struct { // variable assignments in the current block (map from variable symbol to ssa value) // *Node is the unique identifier (an ONAME Node) for the variable. // TODO: keep a single varnum map, then make all of these maps slices instead? - vars map[*Node]*ssa.Value + vars map[*ir.Node]*ssa.Value // fwdVars are variables that are used before they are defined in the current block. // This map exists just to coalesce multiple references into a single FwdRef op. // *Node is the unique identifier (an ONAME Node) for the variable. - fwdVars map[*Node]*ssa.Value + fwdVars map[*ir.Node]*ssa.Value // all defined variables at the end of each block. Indexed by block ID. - defvars []map[*Node]*ssa.Value + defvars []map[*ir.Node]*ssa.Value // addresses of PPARAM and PPARAMOUT variables. - decladdrs map[*Node]*ssa.Value + decladdrs map[*ir.Node]*ssa.Value // starting values. Memory, stack pointer, and globals pointer startmem *ssa.Value @@ -628,7 +629,7 @@ type state struct { sb *ssa.Value // value representing address of where deferBits autotmp is stored deferBitsAddr *ssa.Value - deferBitsTemp *Node + deferBitsTemp *ir.Node // line number stack. The current line number is top of stack line []src.XPos @@ -640,7 +641,7 @@ type state struct { panics map[funcLine]*ssa.Block // list of PPARAMOUT (return) variables. - returns []*Node + returns []*ir.Node cgoUnsafeArgs bool hasdefer bool // whether the function contains a defer statement @@ -692,8 +693,8 @@ func (s *state) Fatalf(msg string, args ...interface{}) { func (s *state) Warnl(pos src.XPos, msg string, args ...interface{}) { s.f.Warnl(pos, msg, args...) } func (s *state) Debug_checknil() bool { return s.f.Frontend().Debug_checknil() } -func ssaMarker(name string) *Node { - return newname(&types.Sym{Name: name}) +func ssaMarker(name string) *ir.Node { + return NewName(&types.Sym{Name: name}) } var ( @@ -716,7 +717,7 @@ func (s *state) startBlock(b *ssa.Block) { s.Fatalf("starting block %v when block %v has not ended", b, s.curBlock) } s.curBlock = b - s.vars = map[*Node]*ssa.Value{} + s.vars = map[*ir.Node]*ssa.Value{} for n := range s.fwdVars { delete(s.fwdVars, n) } @@ -920,7 +921,7 @@ func (s *state) constEmptyString(t *types.Type) *ssa.Value { return s.f.ConstEmptyString(t) } func (s *state) constBool(c bool) *ssa.Value { - return s.f.ConstBool(types.Types[TBOOL], c) + return s.f.ConstBool(types.Types[types.TBOOL], c) } func (s *state) constInt8(t *types.Type, c int8) *ssa.Value { return s.f.ConstInt8(t, c) @@ -1017,7 +1018,7 @@ func (s *state) instrument(t *types.Type, addr *ssa.Value, wr bool) { args := []*ssa.Value{addr} if needWidth { - args = append(args, s.constInt(types.Types[TUINTPTR], w)) + args = append(args, s.constInt(types.Types[types.TUINTPTR], w)) } s.rtcall(fn, true, nil, args...) } @@ -1051,15 +1052,15 @@ func (s *state) move(t *types.Type, dst, src *ssa.Value) { } // stmtList converts the statement list n to SSA and adds it to s. -func (s *state) stmtList(l Nodes) { +func (s *state) stmtList(l ir.Nodes) { for _, n := range l.Slice() { s.stmt(n) } } // stmt converts the statement n to SSA and adds it to s. -func (s *state) stmt(n *Node) { - if !(n.Op == OVARKILL || n.Op == OVARLIVE || n.Op == OVARDEF) { +func (s *state) stmt(n *ir.Node) { + if !(n.Op == ir.OVARKILL || n.Op == ir.OVARLIVE || n.Op == ir.OVARDEF) { // OVARKILL, OVARLIVE, and OVARDEF are invisible to the programmer, so we don't use their line numbers to avoid confusion in debugging. s.pushLine(n.Pos) defer s.popLine() @@ -1067,30 +1068,30 @@ func (s *state) stmt(n *Node) { // If s.curBlock is nil, and n isn't a label (which might have an associated goto somewhere), // then this code is dead. Stop here. - if s.curBlock == nil && n.Op != OLABEL { + if s.curBlock == nil && n.Op != ir.OLABEL { return } s.stmtList(n.Ninit) switch n.Op { - case OBLOCK: + case ir.OBLOCK: s.stmtList(n.List) // No-ops - case OEMPTY, ODCLCONST, ODCLTYPE, OFALL: + case ir.OEMPTY, ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL: // Expression statements - case OCALLFUNC: + case ir.OCALLFUNC: if isIntrinsicCall(n) { s.intrinsicCall(n) return } fallthrough - case OCALLMETH, OCALLINTER: + case ir.OCALLMETH, ir.OCALLINTER: s.callResult(n, callNormal) - if n.Op == OCALLFUNC && n.Left.Op == ONAME && n.Left.Class() == PFUNC { + if n.Op == ir.OCALLFUNC && n.Left.Op == ir.ONAME && n.Left.Class() == ir.PFUNC { if fn := n.Left.Sym.Name; base.Flag.CompilingRuntime && fn == "throw" || n.Left.Sym.Pkg == Runtimepkg && (fn == "throwinit" || fn == "gopanic" || fn == "panicwrap" || fn == "block" || fn == "panicmakeslicelen" || fn == "panicmakeslicecap") { m := s.mem() @@ -1102,7 +1103,7 @@ func (s *state) stmt(n *Node) { // go through SSA. } } - case ODEFER: + case ir.ODEFER: if base.Debug.Defer > 0 { var defertype string if s.hasOpenDefers { @@ -1123,10 +1124,10 @@ func (s *state) stmt(n *Node) { } s.callResult(n.Left, d) } - case OGO: + case ir.OGO: s.callResult(n.Left, callGo) - case OAS2DOTTYPE: + case ir.OAS2DOTTYPE: res, resok := s.dottype(n.Right, true) deref := false if !canSSAType(n.Right.Type) { @@ -1147,7 +1148,7 @@ func (s *state) stmt(n *Node) { s.assign(n.List.Second(), resok, false, 0) return - case OAS2FUNC: + case ir.OAS2FUNC: // We come here only when it is an intrinsic call returning two values. if !isIntrinsicCall(n.Right) { s.Fatalf("non-intrinsic AS2FUNC not expanded %v", n.Right) @@ -1159,17 +1160,17 @@ func (s *state) stmt(n *Node) { s.assign(n.List.Second(), v2, false, 0) return - case ODCL: - if n.Left.Class() == PAUTOHEAP { + case ir.ODCL: + if n.Left.Class() == ir.PAUTOHEAP { s.Fatalf("DCL %v", n) } - case OLABEL: + case ir.OLABEL: sym := n.Sym lab := s.label(sym) // Associate label with its control flow node, if any - if ctl := n.labeledControl(); ctl != nil { + if ctl := labeledControl(n); ctl != nil { s.labeledNodes[ctl] = lab } @@ -1186,7 +1187,7 @@ func (s *state) stmt(n *Node) { } s.startBlock(lab.target) - case OGOTO: + case ir.OGOTO: sym := n.Sym lab := s.label(sym) @@ -1198,8 +1199,8 @@ func (s *state) stmt(n *Node) { b.Pos = s.lastPos.WithIsStmt() // Do this even if b is an empty block. b.AddEdgeTo(lab.target) - case OAS: - if n.Left == n.Right && n.Left.Op == ONAME { + case ir.OAS: + if n.Left == n.Right && n.Left.Op == ir.ONAME { // An x=x assignment. No point in doing anything // here. In addition, skipping this assignment // prevents generating: @@ -1214,7 +1215,7 @@ func (s *state) stmt(n *Node) { rhs := n.Right if rhs != nil { switch rhs.Op { - case OSTRUCTLIT, OARRAYLIT, OSLICELIT: + case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT: // All literals with nonzero fields have already been // rewritten during walk. Any that remain are just T{} // or equivalents. Use the zero value. @@ -1222,7 +1223,7 @@ func (s *state) stmt(n *Node) { s.Fatalf("literal with nonzero value in SSA: %v", rhs) } rhs = nil - case OAPPEND: + case ir.OAPPEND: // Check whether we're writing the result of an append back to the same slice. // If so, we handle it specially to avoid write barriers on the fast // (non-growth) path. @@ -1246,7 +1247,7 @@ func (s *state) stmt(n *Node) { } } - if n.Left.isBlank() { + if ir.IsBlank(n.Left) { // _ = rhs // Just evaluate rhs for side-effects. if rhs != nil { @@ -1279,11 +1280,11 @@ func (s *state) stmt(n *Node) { } var skip skipMask - if rhs != nil && (rhs.Op == OSLICE || rhs.Op == OSLICE3 || rhs.Op == OSLICESTR) && samesafeexpr(rhs.Left, n.Left) { + if rhs != nil && (rhs.Op == ir.OSLICE || rhs.Op == ir.OSLICE3 || rhs.Op == ir.OSLICESTR) && samesafeexpr(rhs.Left, n.Left) { // We're assigning a slicing operation back to its source. // Don't write back fields we aren't changing. See issue #14855. i, j, k := rhs.SliceBounds() - if i != nil && (i.Op == OLITERAL && i.Val().Kind() == constant.Int && i.Int64Val() == 0) { + if i != nil && (i.Op == ir.OLITERAL && i.Val().Kind() == constant.Int && i.Int64Val() == 0) { // [0:...] is the same as [:...] i = nil } @@ -1310,8 +1311,8 @@ func (s *state) stmt(n *Node) { s.assign(n.Left, r, deref, skip) - case OIF: - if Isconst(n.Left, constant.Bool) { + case ir.OIF: + if ir.IsConst(n.Left, constant.Bool) { s.stmtList(n.Left.Ninit) if n.Left.BoolVal() { s.stmtList(n.Nbody) @@ -1356,25 +1357,25 @@ func (s *state) stmt(n *Node) { } s.startBlock(bEnd) - case ORETURN: + case ir.ORETURN: s.stmtList(n.List) b := s.exit() b.Pos = s.lastPos.WithIsStmt() - case ORETJMP: + case ir.ORETJMP: s.stmtList(n.List) b := s.exit() b.Kind = ssa.BlockRetJmp // override BlockRet b.Aux = n.Sym.Linksym() - case OCONTINUE, OBREAK: + case ir.OCONTINUE, ir.OBREAK: var to *ssa.Block if n.Sym == nil { // plain break/continue switch n.Op { - case OCONTINUE: + case ir.OCONTINUE: to = s.continueTo - case OBREAK: + case ir.OBREAK: to = s.breakTo } } else { @@ -1382,9 +1383,9 @@ func (s *state) stmt(n *Node) { sym := n.Sym lab := s.label(sym) switch n.Op { - case OCONTINUE: + case ir.OCONTINUE: to = lab.continueTarget - case OBREAK: + case ir.OBREAK: to = lab.breakTarget } } @@ -1393,7 +1394,7 @@ func (s *state) stmt(n *Node) { b.Pos = s.lastPos.WithIsStmt() // Do this even if b is an empty block. b.AddEdgeTo(to) - case OFOR, OFORUNTIL: + case ir.OFOR, ir.OFORUNTIL: // OFOR: for Ninit; Left; Right { Nbody } // cond (Left); body (Nbody); incr (Right) // @@ -1409,7 +1410,7 @@ func (s *state) stmt(n *Node) { // first, jump to condition test (OFOR) or body (OFORUNTIL) b := s.endBlock() - if n.Op == OFOR { + if n.Op == ir.OFOR { b.AddEdgeTo(bCond) // generate code to test condition s.startBlock(bCond) @@ -1459,12 +1460,12 @@ func (s *state) stmt(n *Node) { if n.Right != nil { s.stmt(n.Right) } - if n.Op == OFOR { + if n.Op == ir.OFOR { if b := s.endBlock(); b != nil { b.AddEdgeTo(bCond) // It can happen that bIncr ends in a block containing only VARKILL, // and that muddles the debugging experience. - if n.Op != OFORUNTIL && b.Pos == src.NoXPos { + if n.Op != ir.OFORUNTIL && b.Pos == src.NoXPos { b.Pos = bCond.Pos } } @@ -1481,7 +1482,7 @@ func (s *state) stmt(n *Node) { s.startBlock(bEnd) - case OSWITCH, OSELECT: + case ir.OSWITCH, ir.OSELECT: // These have been mostly rewritten by the front end into their Nbody fields. // Our main task is to correctly hook up any break statements. bEnd := s.f.NewBlock(ssa.BlockPlain) @@ -1512,11 +1513,11 @@ func (s *state) stmt(n *Node) { } s.startBlock(bEnd) - case OVARDEF: + case ir.OVARDEF: if !s.canSSA(n.Left) { s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, n.Left, s.mem(), false) } - case OVARKILL: + case ir.OVARKILL: // Insert a varkill op to record that a variable is no longer live. // We only care about liveness info at call sites, so putting the // varkill in the store chain is enough to keep it correctly ordered @@ -1525,23 +1526,23 @@ func (s *state) stmt(n *Node) { s.vars[memVar] = s.newValue1Apos(ssa.OpVarKill, types.TypeMem, n.Left, s.mem(), false) } - case OVARLIVE: + case ir.OVARLIVE: // Insert a varlive op to record that a variable is still live. if !n.Left.Name.Addrtaken() { s.Fatalf("VARLIVE variable %v must have Addrtaken set", n.Left) } switch n.Left.Class() { - case PAUTO, PPARAM, PPARAMOUT: + case ir.PAUTO, ir.PPARAM, ir.PPARAMOUT: default: s.Fatalf("VARLIVE variable %v must be Auto or Arg", n.Left) } s.vars[memVar] = s.newValue1A(ssa.OpVarLive, types.TypeMem, n.Left, s.mem()) - case OCHECKNIL: + case ir.OCHECKNIL: p := s.expr(n.Left) s.nilCheck(p) - case OINLMARK: + case ir.OINLMARK: s.newValue1I(ssa.OpInlMark, types.TypeVoid, n.Xoffset, s.mem()) default: @@ -1600,180 +1601,180 @@ func (s *state) exit() *ssa.Block { } type opAndType struct { - op Op + op ir.Op etype types.EType } var opToSSA = map[opAndType]ssa.Op{ - opAndType{OADD, TINT8}: ssa.OpAdd8, - opAndType{OADD, TUINT8}: ssa.OpAdd8, - opAndType{OADD, TINT16}: ssa.OpAdd16, - opAndType{OADD, TUINT16}: ssa.OpAdd16, - opAndType{OADD, TINT32}: ssa.OpAdd32, - opAndType{OADD, TUINT32}: ssa.OpAdd32, - opAndType{OADD, TINT64}: ssa.OpAdd64, - opAndType{OADD, TUINT64}: ssa.OpAdd64, - opAndType{OADD, TFLOAT32}: ssa.OpAdd32F, - opAndType{OADD, TFLOAT64}: ssa.OpAdd64F, + opAndType{ir.OADD, types.TINT8}: ssa.OpAdd8, + opAndType{ir.OADD, types.TUINT8}: ssa.OpAdd8, + opAndType{ir.OADD, types.TINT16}: ssa.OpAdd16, + opAndType{ir.OADD, types.TUINT16}: ssa.OpAdd16, + opAndType{ir.OADD, types.TINT32}: ssa.OpAdd32, + opAndType{ir.OADD, types.TUINT32}: ssa.OpAdd32, + opAndType{ir.OADD, types.TINT64}: ssa.OpAdd64, + opAndType{ir.OADD, types.TUINT64}: ssa.OpAdd64, + opAndType{ir.OADD, types.TFLOAT32}: ssa.OpAdd32F, + opAndType{ir.OADD, types.TFLOAT64}: ssa.OpAdd64F, - opAndType{OSUB, TINT8}: ssa.OpSub8, - opAndType{OSUB, TUINT8}: ssa.OpSub8, - opAndType{OSUB, TINT16}: ssa.OpSub16, - opAndType{OSUB, TUINT16}: ssa.OpSub16, - opAndType{OSUB, TINT32}: ssa.OpSub32, - opAndType{OSUB, TUINT32}: ssa.OpSub32, - opAndType{OSUB, TINT64}: ssa.OpSub64, - opAndType{OSUB, TUINT64}: ssa.OpSub64, - opAndType{OSUB, TFLOAT32}: ssa.OpSub32F, - opAndType{OSUB, TFLOAT64}: ssa.OpSub64F, + opAndType{ir.OSUB, types.TINT8}: ssa.OpSub8, + opAndType{ir.OSUB, types.TUINT8}: ssa.OpSub8, + opAndType{ir.OSUB, types.TINT16}: ssa.OpSub16, + opAndType{ir.OSUB, types.TUINT16}: ssa.OpSub16, + opAndType{ir.OSUB, types.TINT32}: ssa.OpSub32, + opAndType{ir.OSUB, types.TUINT32}: ssa.OpSub32, + opAndType{ir.OSUB, types.TINT64}: ssa.OpSub64, + opAndType{ir.OSUB, types.TUINT64}: ssa.OpSub64, + opAndType{ir.OSUB, types.TFLOAT32}: ssa.OpSub32F, + opAndType{ir.OSUB, types.TFLOAT64}: ssa.OpSub64F, - opAndType{ONOT, TBOOL}: ssa.OpNot, + opAndType{ir.ONOT, types.TBOOL}: ssa.OpNot, - opAndType{ONEG, TINT8}: ssa.OpNeg8, - opAndType{ONEG, TUINT8}: ssa.OpNeg8, - opAndType{ONEG, TINT16}: ssa.OpNeg16, - opAndType{ONEG, TUINT16}: ssa.OpNeg16, - opAndType{ONEG, TINT32}: ssa.OpNeg32, - opAndType{ONEG, TUINT32}: ssa.OpNeg32, - opAndType{ONEG, TINT64}: ssa.OpNeg64, - opAndType{ONEG, TUINT64}: ssa.OpNeg64, - opAndType{ONEG, TFLOAT32}: ssa.OpNeg32F, - opAndType{ONEG, TFLOAT64}: ssa.OpNeg64F, + opAndType{ir.ONEG, types.TINT8}: ssa.OpNeg8, + opAndType{ir.ONEG, types.TUINT8}: ssa.OpNeg8, + opAndType{ir.ONEG, types.TINT16}: ssa.OpNeg16, + opAndType{ir.ONEG, types.TUINT16}: ssa.OpNeg16, + opAndType{ir.ONEG, types.TINT32}: ssa.OpNeg32, + opAndType{ir.ONEG, types.TUINT32}: ssa.OpNeg32, + opAndType{ir.ONEG, types.TINT64}: ssa.OpNeg64, + opAndType{ir.ONEG, types.TUINT64}: ssa.OpNeg64, + opAndType{ir.ONEG, types.TFLOAT32}: ssa.OpNeg32F, + opAndType{ir.ONEG, types.TFLOAT64}: ssa.OpNeg64F, - opAndType{OBITNOT, TINT8}: ssa.OpCom8, - opAndType{OBITNOT, TUINT8}: ssa.OpCom8, - opAndType{OBITNOT, TINT16}: ssa.OpCom16, - opAndType{OBITNOT, TUINT16}: ssa.OpCom16, - opAndType{OBITNOT, TINT32}: ssa.OpCom32, - opAndType{OBITNOT, TUINT32}: ssa.OpCom32, - opAndType{OBITNOT, TINT64}: ssa.OpCom64, - opAndType{OBITNOT, TUINT64}: ssa.OpCom64, + opAndType{ir.OBITNOT, types.TINT8}: ssa.OpCom8, + opAndType{ir.OBITNOT, types.TUINT8}: ssa.OpCom8, + opAndType{ir.OBITNOT, types.TINT16}: ssa.OpCom16, + opAndType{ir.OBITNOT, types.TUINT16}: ssa.OpCom16, + opAndType{ir.OBITNOT, types.TINT32}: ssa.OpCom32, + opAndType{ir.OBITNOT, types.TUINT32}: ssa.OpCom32, + opAndType{ir.OBITNOT, types.TINT64}: ssa.OpCom64, + opAndType{ir.OBITNOT, types.TUINT64}: ssa.OpCom64, - opAndType{OIMAG, TCOMPLEX64}: ssa.OpComplexImag, - opAndType{OIMAG, TCOMPLEX128}: ssa.OpComplexImag, - opAndType{OREAL, TCOMPLEX64}: ssa.OpComplexReal, - opAndType{OREAL, TCOMPLEX128}: ssa.OpComplexReal, + opAndType{ir.OIMAG, types.TCOMPLEX64}: ssa.OpComplexImag, + opAndType{ir.OIMAG, types.TCOMPLEX128}: ssa.OpComplexImag, + opAndType{ir.OREAL, types.TCOMPLEX64}: ssa.OpComplexReal, + opAndType{ir.OREAL, types.TCOMPLEX128}: ssa.OpComplexReal, - opAndType{OMUL, TINT8}: ssa.OpMul8, - opAndType{OMUL, TUINT8}: ssa.OpMul8, - opAndType{OMUL, TINT16}: ssa.OpMul16, - opAndType{OMUL, TUINT16}: ssa.OpMul16, - opAndType{OMUL, TINT32}: ssa.OpMul32, - opAndType{OMUL, TUINT32}: ssa.OpMul32, - opAndType{OMUL, TINT64}: ssa.OpMul64, - opAndType{OMUL, TUINT64}: ssa.OpMul64, - opAndType{OMUL, TFLOAT32}: ssa.OpMul32F, - opAndType{OMUL, TFLOAT64}: ssa.OpMul64F, + opAndType{ir.OMUL, types.TINT8}: ssa.OpMul8, + opAndType{ir.OMUL, types.TUINT8}: ssa.OpMul8, + opAndType{ir.OMUL, types.TINT16}: ssa.OpMul16, + opAndType{ir.OMUL, types.TUINT16}: ssa.OpMul16, + opAndType{ir.OMUL, types.TINT32}: ssa.OpMul32, + opAndType{ir.OMUL, types.TUINT32}: ssa.OpMul32, + opAndType{ir.OMUL, types.TINT64}: ssa.OpMul64, + opAndType{ir.OMUL, types.TUINT64}: ssa.OpMul64, + opAndType{ir.OMUL, types.TFLOAT32}: ssa.OpMul32F, + opAndType{ir.OMUL, types.TFLOAT64}: ssa.OpMul64F, - opAndType{ODIV, TFLOAT32}: ssa.OpDiv32F, - opAndType{ODIV, TFLOAT64}: ssa.OpDiv64F, + opAndType{ir.ODIV, types.TFLOAT32}: ssa.OpDiv32F, + opAndType{ir.ODIV, types.TFLOAT64}: ssa.OpDiv64F, - opAndType{ODIV, TINT8}: ssa.OpDiv8, - opAndType{ODIV, TUINT8}: ssa.OpDiv8u, - opAndType{ODIV, TINT16}: ssa.OpDiv16, - opAndType{ODIV, TUINT16}: ssa.OpDiv16u, - opAndType{ODIV, TINT32}: ssa.OpDiv32, - opAndType{ODIV, TUINT32}: ssa.OpDiv32u, - opAndType{ODIV, TINT64}: ssa.OpDiv64, - opAndType{ODIV, TUINT64}: ssa.OpDiv64u, + opAndType{ir.ODIV, types.TINT8}: ssa.OpDiv8, + opAndType{ir.ODIV, types.TUINT8}: ssa.OpDiv8u, + opAndType{ir.ODIV, types.TINT16}: ssa.OpDiv16, + opAndType{ir.ODIV, types.TUINT16}: ssa.OpDiv16u, + opAndType{ir.ODIV, types.TINT32}: ssa.OpDiv32, + opAndType{ir.ODIV, types.TUINT32}: ssa.OpDiv32u, + opAndType{ir.ODIV, types.TINT64}: ssa.OpDiv64, + opAndType{ir.ODIV, types.TUINT64}: ssa.OpDiv64u, - opAndType{OMOD, TINT8}: ssa.OpMod8, - opAndType{OMOD, TUINT8}: ssa.OpMod8u, - opAndType{OMOD, TINT16}: ssa.OpMod16, - opAndType{OMOD, TUINT16}: ssa.OpMod16u, - opAndType{OMOD, TINT32}: ssa.OpMod32, - opAndType{OMOD, TUINT32}: ssa.OpMod32u, - opAndType{OMOD, TINT64}: ssa.OpMod64, - opAndType{OMOD, TUINT64}: ssa.OpMod64u, + opAndType{ir.OMOD, types.TINT8}: ssa.OpMod8, + opAndType{ir.OMOD, types.TUINT8}: ssa.OpMod8u, + opAndType{ir.OMOD, types.TINT16}: ssa.OpMod16, + opAndType{ir.OMOD, types.TUINT16}: ssa.OpMod16u, + opAndType{ir.OMOD, types.TINT32}: ssa.OpMod32, + opAndType{ir.OMOD, types.TUINT32}: ssa.OpMod32u, + opAndType{ir.OMOD, types.TINT64}: ssa.OpMod64, + opAndType{ir.OMOD, types.TUINT64}: ssa.OpMod64u, - opAndType{OAND, TINT8}: ssa.OpAnd8, - opAndType{OAND, TUINT8}: ssa.OpAnd8, - opAndType{OAND, TINT16}: ssa.OpAnd16, - opAndType{OAND, TUINT16}: ssa.OpAnd16, - opAndType{OAND, TINT32}: ssa.OpAnd32, - opAndType{OAND, TUINT32}: ssa.OpAnd32, - opAndType{OAND, TINT64}: ssa.OpAnd64, - opAndType{OAND, TUINT64}: ssa.OpAnd64, + opAndType{ir.OAND, types.TINT8}: ssa.OpAnd8, + opAndType{ir.OAND, types.TUINT8}: ssa.OpAnd8, + opAndType{ir.OAND, types.TINT16}: ssa.OpAnd16, + opAndType{ir.OAND, types.TUINT16}: ssa.OpAnd16, + opAndType{ir.OAND, types.TINT32}: ssa.OpAnd32, + opAndType{ir.OAND, types.TUINT32}: ssa.OpAnd32, + opAndType{ir.OAND, types.TINT64}: ssa.OpAnd64, + opAndType{ir.OAND, types.TUINT64}: ssa.OpAnd64, - opAndType{OOR, TINT8}: ssa.OpOr8, - opAndType{OOR, TUINT8}: ssa.OpOr8, - opAndType{OOR, TINT16}: ssa.OpOr16, - opAndType{OOR, TUINT16}: ssa.OpOr16, - opAndType{OOR, TINT32}: ssa.OpOr32, - opAndType{OOR, TUINT32}: ssa.OpOr32, - opAndType{OOR, TINT64}: ssa.OpOr64, - opAndType{OOR, TUINT64}: ssa.OpOr64, + opAndType{ir.OOR, types.TINT8}: ssa.OpOr8, + opAndType{ir.OOR, types.TUINT8}: ssa.OpOr8, + opAndType{ir.OOR, types.TINT16}: ssa.OpOr16, + opAndType{ir.OOR, types.TUINT16}: ssa.OpOr16, + opAndType{ir.OOR, types.TINT32}: ssa.OpOr32, + opAndType{ir.OOR, types.TUINT32}: ssa.OpOr32, + opAndType{ir.OOR, types.TINT64}: ssa.OpOr64, + opAndType{ir.OOR, types.TUINT64}: ssa.OpOr64, - opAndType{OXOR, TINT8}: ssa.OpXor8, - opAndType{OXOR, TUINT8}: ssa.OpXor8, - opAndType{OXOR, TINT16}: ssa.OpXor16, - opAndType{OXOR, TUINT16}: ssa.OpXor16, - opAndType{OXOR, TINT32}: ssa.OpXor32, - opAndType{OXOR, TUINT32}: ssa.OpXor32, - opAndType{OXOR, TINT64}: ssa.OpXor64, - opAndType{OXOR, TUINT64}: ssa.OpXor64, + opAndType{ir.OXOR, types.TINT8}: ssa.OpXor8, + opAndType{ir.OXOR, types.TUINT8}: ssa.OpXor8, + opAndType{ir.OXOR, types.TINT16}: ssa.OpXor16, + opAndType{ir.OXOR, types.TUINT16}: ssa.OpXor16, + opAndType{ir.OXOR, types.TINT32}: ssa.OpXor32, + opAndType{ir.OXOR, types.TUINT32}: ssa.OpXor32, + opAndType{ir.OXOR, types.TINT64}: ssa.OpXor64, + opAndType{ir.OXOR, types.TUINT64}: ssa.OpXor64, - opAndType{OEQ, TBOOL}: ssa.OpEqB, - opAndType{OEQ, TINT8}: ssa.OpEq8, - opAndType{OEQ, TUINT8}: ssa.OpEq8, - opAndType{OEQ, TINT16}: ssa.OpEq16, - opAndType{OEQ, TUINT16}: ssa.OpEq16, - opAndType{OEQ, TINT32}: ssa.OpEq32, - opAndType{OEQ, TUINT32}: ssa.OpEq32, - opAndType{OEQ, TINT64}: ssa.OpEq64, - opAndType{OEQ, TUINT64}: ssa.OpEq64, - opAndType{OEQ, TINTER}: ssa.OpEqInter, - opAndType{OEQ, TSLICE}: ssa.OpEqSlice, - opAndType{OEQ, TFUNC}: ssa.OpEqPtr, - opAndType{OEQ, TMAP}: ssa.OpEqPtr, - opAndType{OEQ, TCHAN}: ssa.OpEqPtr, - opAndType{OEQ, TPTR}: ssa.OpEqPtr, - opAndType{OEQ, TUINTPTR}: ssa.OpEqPtr, - opAndType{OEQ, TUNSAFEPTR}: ssa.OpEqPtr, - opAndType{OEQ, TFLOAT64}: ssa.OpEq64F, - opAndType{OEQ, TFLOAT32}: ssa.OpEq32F, + opAndType{ir.OEQ, types.TBOOL}: ssa.OpEqB, + opAndType{ir.OEQ, types.TINT8}: ssa.OpEq8, + opAndType{ir.OEQ, types.TUINT8}: ssa.OpEq8, + opAndType{ir.OEQ, types.TINT16}: ssa.OpEq16, + opAndType{ir.OEQ, types.TUINT16}: ssa.OpEq16, + opAndType{ir.OEQ, types.TINT32}: ssa.OpEq32, + opAndType{ir.OEQ, types.TUINT32}: ssa.OpEq32, + opAndType{ir.OEQ, types.TINT64}: ssa.OpEq64, + opAndType{ir.OEQ, types.TUINT64}: ssa.OpEq64, + opAndType{ir.OEQ, types.TINTER}: ssa.OpEqInter, + opAndType{ir.OEQ, types.TSLICE}: ssa.OpEqSlice, + opAndType{ir.OEQ, types.TFUNC}: ssa.OpEqPtr, + opAndType{ir.OEQ, types.TMAP}: ssa.OpEqPtr, + opAndType{ir.OEQ, types.TCHAN}: ssa.OpEqPtr, + opAndType{ir.OEQ, types.TPTR}: ssa.OpEqPtr, + opAndType{ir.OEQ, types.TUINTPTR}: ssa.OpEqPtr, + opAndType{ir.OEQ, types.TUNSAFEPTR}: ssa.OpEqPtr, + opAndType{ir.OEQ, types.TFLOAT64}: ssa.OpEq64F, + opAndType{ir.OEQ, types.TFLOAT32}: ssa.OpEq32F, - opAndType{ONE, TBOOL}: ssa.OpNeqB, - opAndType{ONE, TINT8}: ssa.OpNeq8, - opAndType{ONE, TUINT8}: ssa.OpNeq8, - opAndType{ONE, TINT16}: ssa.OpNeq16, - opAndType{ONE, TUINT16}: ssa.OpNeq16, - opAndType{ONE, TINT32}: ssa.OpNeq32, - opAndType{ONE, TUINT32}: ssa.OpNeq32, - opAndType{ONE, TINT64}: ssa.OpNeq64, - opAndType{ONE, TUINT64}: ssa.OpNeq64, - opAndType{ONE, TINTER}: ssa.OpNeqInter, - opAndType{ONE, TSLICE}: ssa.OpNeqSlice, - opAndType{ONE, TFUNC}: ssa.OpNeqPtr, - opAndType{ONE, TMAP}: ssa.OpNeqPtr, - opAndType{ONE, TCHAN}: ssa.OpNeqPtr, - opAndType{ONE, TPTR}: ssa.OpNeqPtr, - opAndType{ONE, TUINTPTR}: ssa.OpNeqPtr, - opAndType{ONE, TUNSAFEPTR}: ssa.OpNeqPtr, - opAndType{ONE, TFLOAT64}: ssa.OpNeq64F, - opAndType{ONE, TFLOAT32}: ssa.OpNeq32F, + opAndType{ir.ONE, types.TBOOL}: ssa.OpNeqB, + opAndType{ir.ONE, types.TINT8}: ssa.OpNeq8, + opAndType{ir.ONE, types.TUINT8}: ssa.OpNeq8, + opAndType{ir.ONE, types.TINT16}: ssa.OpNeq16, + opAndType{ir.ONE, types.TUINT16}: ssa.OpNeq16, + opAndType{ir.ONE, types.TINT32}: ssa.OpNeq32, + opAndType{ir.ONE, types.TUINT32}: ssa.OpNeq32, + opAndType{ir.ONE, types.TINT64}: ssa.OpNeq64, + opAndType{ir.ONE, types.TUINT64}: ssa.OpNeq64, + opAndType{ir.ONE, types.TINTER}: ssa.OpNeqInter, + opAndType{ir.ONE, types.TSLICE}: ssa.OpNeqSlice, + opAndType{ir.ONE, types.TFUNC}: ssa.OpNeqPtr, + opAndType{ir.ONE, types.TMAP}: ssa.OpNeqPtr, + opAndType{ir.ONE, types.TCHAN}: ssa.OpNeqPtr, + opAndType{ir.ONE, types.TPTR}: ssa.OpNeqPtr, + opAndType{ir.ONE, types.TUINTPTR}: ssa.OpNeqPtr, + opAndType{ir.ONE, types.TUNSAFEPTR}: ssa.OpNeqPtr, + opAndType{ir.ONE, types.TFLOAT64}: ssa.OpNeq64F, + opAndType{ir.ONE, types.TFLOAT32}: ssa.OpNeq32F, - opAndType{OLT, TINT8}: ssa.OpLess8, - opAndType{OLT, TUINT8}: ssa.OpLess8U, - opAndType{OLT, TINT16}: ssa.OpLess16, - opAndType{OLT, TUINT16}: ssa.OpLess16U, - opAndType{OLT, TINT32}: ssa.OpLess32, - opAndType{OLT, TUINT32}: ssa.OpLess32U, - opAndType{OLT, TINT64}: ssa.OpLess64, - opAndType{OLT, TUINT64}: ssa.OpLess64U, - opAndType{OLT, TFLOAT64}: ssa.OpLess64F, - opAndType{OLT, TFLOAT32}: ssa.OpLess32F, + opAndType{ir.OLT, types.TINT8}: ssa.OpLess8, + opAndType{ir.OLT, types.TUINT8}: ssa.OpLess8U, + opAndType{ir.OLT, types.TINT16}: ssa.OpLess16, + opAndType{ir.OLT, types.TUINT16}: ssa.OpLess16U, + opAndType{ir.OLT, types.TINT32}: ssa.OpLess32, + opAndType{ir.OLT, types.TUINT32}: ssa.OpLess32U, + opAndType{ir.OLT, types.TINT64}: ssa.OpLess64, + opAndType{ir.OLT, types.TUINT64}: ssa.OpLess64U, + opAndType{ir.OLT, types.TFLOAT64}: ssa.OpLess64F, + opAndType{ir.OLT, types.TFLOAT32}: ssa.OpLess32F, - opAndType{OLE, TINT8}: ssa.OpLeq8, - opAndType{OLE, TUINT8}: ssa.OpLeq8U, - opAndType{OLE, TINT16}: ssa.OpLeq16, - opAndType{OLE, TUINT16}: ssa.OpLeq16U, - opAndType{OLE, TINT32}: ssa.OpLeq32, - opAndType{OLE, TUINT32}: ssa.OpLeq32U, - opAndType{OLE, TINT64}: ssa.OpLeq64, - opAndType{OLE, TUINT64}: ssa.OpLeq64U, - opAndType{OLE, TFLOAT64}: ssa.OpLeq64F, - opAndType{OLE, TFLOAT32}: ssa.OpLeq32F, + opAndType{ir.OLE, types.TINT8}: ssa.OpLeq8, + opAndType{ir.OLE, types.TUINT8}: ssa.OpLeq8U, + opAndType{ir.OLE, types.TINT16}: ssa.OpLeq16, + opAndType{ir.OLE, types.TUINT16}: ssa.OpLeq16U, + opAndType{ir.OLE, types.TINT32}: ssa.OpLeq32, + opAndType{ir.OLE, types.TUINT32}: ssa.OpLeq32U, + opAndType{ir.OLE, types.TINT64}: ssa.OpLeq64, + opAndType{ir.OLE, types.TUINT64}: ssa.OpLeq64U, + opAndType{ir.OLE, types.TFLOAT64}: ssa.OpLeq64F, + opAndType{ir.OLE, types.TFLOAT32}: ssa.OpLeq32F, } func (s *state) concreteEtype(t *types.Type) types.EType { @@ -1781,25 +1782,25 @@ func (s *state) concreteEtype(t *types.Type) types.EType { switch e { default: return e - case TINT: + case types.TINT: if s.config.PtrSize == 8 { - return TINT64 + return types.TINT64 } - return TINT32 - case TUINT: + return types.TINT32 + case types.TUINT: if s.config.PtrSize == 8 { - return TUINT64 + return types.TUINT64 } - return TUINT32 - case TUINTPTR: + return types.TUINT32 + case types.TUINTPTR: if s.config.PtrSize == 8 { - return TUINT64 + return types.TUINT64 } - return TUINT32 + return types.TUINT32 } } -func (s *state) ssaOp(op Op, t *types.Type) ssa.Op { +func (s *state) ssaOp(op ir.Op, t *types.Type) ssa.Op { etype := s.concreteEtype(t) x, ok := opToSSA[opAndType{op, etype}] if !ok { @@ -1810,10 +1811,10 @@ func (s *state) ssaOp(op Op, t *types.Type) ssa.Op { func floatForComplex(t *types.Type) *types.Type { switch t.Etype { - case TCOMPLEX64: - return types.Types[TFLOAT32] - case TCOMPLEX128: - return types.Types[TFLOAT64] + case types.TCOMPLEX64: + return types.Types[types.TFLOAT32] + case types.TCOMPLEX128: + return types.Types[types.TFLOAT64] } base.Fatalf("unexpected type: %v", t) return nil @@ -1821,17 +1822,17 @@ func floatForComplex(t *types.Type) *types.Type { func complexForFloat(t *types.Type) *types.Type { switch t.Etype { - case TFLOAT32: - return types.Types[TCOMPLEX64] - case TFLOAT64: - return types.Types[TCOMPLEX128] + case types.TFLOAT32: + return types.Types[types.TCOMPLEX64] + case types.TFLOAT64: + return types.Types[types.TCOMPLEX128] } base.Fatalf("unexpected type: %v", t) return nil } type opAndTwoTypes struct { - op Op + op ir.Op etype1 types.EType etype2 types.EType } @@ -1849,145 +1850,145 @@ type twoOpsAndType struct { var fpConvOpToSSA = map[twoTypes]twoOpsAndType{ - twoTypes{TINT8, TFLOAT32}: twoOpsAndType{ssa.OpSignExt8to32, ssa.OpCvt32to32F, TINT32}, - twoTypes{TINT16, TFLOAT32}: twoOpsAndType{ssa.OpSignExt16to32, ssa.OpCvt32to32F, TINT32}, - twoTypes{TINT32, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32to32F, TINT32}, - twoTypes{TINT64, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64to32F, TINT64}, + twoTypes{types.TINT8, types.TFLOAT32}: twoOpsAndType{ssa.OpSignExt8to32, ssa.OpCvt32to32F, types.TINT32}, + twoTypes{types.TINT16, types.TFLOAT32}: twoOpsAndType{ssa.OpSignExt16to32, ssa.OpCvt32to32F, types.TINT32}, + twoTypes{types.TINT32, types.TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32to32F, types.TINT32}, + twoTypes{types.TINT64, types.TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64to32F, types.TINT64}, - twoTypes{TINT8, TFLOAT64}: twoOpsAndType{ssa.OpSignExt8to32, ssa.OpCvt32to64F, TINT32}, - twoTypes{TINT16, TFLOAT64}: twoOpsAndType{ssa.OpSignExt16to32, ssa.OpCvt32to64F, TINT32}, - twoTypes{TINT32, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32to64F, TINT32}, - twoTypes{TINT64, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64to64F, TINT64}, + twoTypes{types.TINT8, types.TFLOAT64}: twoOpsAndType{ssa.OpSignExt8to32, ssa.OpCvt32to64F, types.TINT32}, + twoTypes{types.TINT16, types.TFLOAT64}: twoOpsAndType{ssa.OpSignExt16to32, ssa.OpCvt32to64F, types.TINT32}, + twoTypes{types.TINT32, types.TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32to64F, types.TINT32}, + twoTypes{types.TINT64, types.TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64to64F, types.TINT64}, - twoTypes{TFLOAT32, TINT8}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to8, TINT32}, - twoTypes{TFLOAT32, TINT16}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to16, TINT32}, - twoTypes{TFLOAT32, TINT32}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpCopy, TINT32}, - twoTypes{TFLOAT32, TINT64}: twoOpsAndType{ssa.OpCvt32Fto64, ssa.OpCopy, TINT64}, + twoTypes{types.TFLOAT32, types.TINT8}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to8, types.TINT32}, + twoTypes{types.TFLOAT32, types.TINT16}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to16, types.TINT32}, + twoTypes{types.TFLOAT32, types.TINT32}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpCopy, types.TINT32}, + twoTypes{types.TFLOAT32, types.TINT64}: twoOpsAndType{ssa.OpCvt32Fto64, ssa.OpCopy, types.TINT64}, - twoTypes{TFLOAT64, TINT8}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to8, TINT32}, - twoTypes{TFLOAT64, TINT16}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to16, TINT32}, - twoTypes{TFLOAT64, TINT32}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpCopy, TINT32}, - twoTypes{TFLOAT64, TINT64}: twoOpsAndType{ssa.OpCvt64Fto64, ssa.OpCopy, TINT64}, + twoTypes{types.TFLOAT64, types.TINT8}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to8, types.TINT32}, + twoTypes{types.TFLOAT64, types.TINT16}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to16, types.TINT32}, + twoTypes{types.TFLOAT64, types.TINT32}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpCopy, types.TINT32}, + twoTypes{types.TFLOAT64, types.TINT64}: twoOpsAndType{ssa.OpCvt64Fto64, ssa.OpCopy, types.TINT64}, // unsigned - twoTypes{TUINT8, TFLOAT32}: twoOpsAndType{ssa.OpZeroExt8to32, ssa.OpCvt32to32F, TINT32}, - twoTypes{TUINT16, TFLOAT32}: twoOpsAndType{ssa.OpZeroExt16to32, ssa.OpCvt32to32F, TINT32}, - twoTypes{TUINT32, TFLOAT32}: twoOpsAndType{ssa.OpZeroExt32to64, ssa.OpCvt64to32F, TINT64}, // go wide to dodge unsigned - twoTypes{TUINT64, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpInvalid, TUINT64}, // Cvt64Uto32F, branchy code expansion instead + twoTypes{types.TUINT8, types.TFLOAT32}: twoOpsAndType{ssa.OpZeroExt8to32, ssa.OpCvt32to32F, types.TINT32}, + twoTypes{types.TUINT16, types.TFLOAT32}: twoOpsAndType{ssa.OpZeroExt16to32, ssa.OpCvt32to32F, types.TINT32}, + twoTypes{types.TUINT32, types.TFLOAT32}: twoOpsAndType{ssa.OpZeroExt32to64, ssa.OpCvt64to32F, types.TINT64}, // go wide to dodge unsigned + twoTypes{types.TUINT64, types.TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpInvalid, types.TUINT64}, // Cvt64Uto32F, branchy code expansion instead - twoTypes{TUINT8, TFLOAT64}: twoOpsAndType{ssa.OpZeroExt8to32, ssa.OpCvt32to64F, TINT32}, - twoTypes{TUINT16, TFLOAT64}: twoOpsAndType{ssa.OpZeroExt16to32, ssa.OpCvt32to64F, TINT32}, - twoTypes{TUINT32, TFLOAT64}: twoOpsAndType{ssa.OpZeroExt32to64, ssa.OpCvt64to64F, TINT64}, // go wide to dodge unsigned - twoTypes{TUINT64, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpInvalid, TUINT64}, // Cvt64Uto64F, branchy code expansion instead + twoTypes{types.TUINT8, types.TFLOAT64}: twoOpsAndType{ssa.OpZeroExt8to32, ssa.OpCvt32to64F, types.TINT32}, + twoTypes{types.TUINT16, types.TFLOAT64}: twoOpsAndType{ssa.OpZeroExt16to32, ssa.OpCvt32to64F, types.TINT32}, + twoTypes{types.TUINT32, types.TFLOAT64}: twoOpsAndType{ssa.OpZeroExt32to64, ssa.OpCvt64to64F, types.TINT64}, // go wide to dodge unsigned + twoTypes{types.TUINT64, types.TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpInvalid, types.TUINT64}, // Cvt64Uto64F, branchy code expansion instead - twoTypes{TFLOAT32, TUINT8}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to8, TINT32}, - twoTypes{TFLOAT32, TUINT16}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to16, TINT32}, - twoTypes{TFLOAT32, TUINT32}: twoOpsAndType{ssa.OpCvt32Fto64, ssa.OpTrunc64to32, TINT64}, // go wide to dodge unsigned - twoTypes{TFLOAT32, TUINT64}: twoOpsAndType{ssa.OpInvalid, ssa.OpCopy, TUINT64}, // Cvt32Fto64U, branchy code expansion instead + twoTypes{types.TFLOAT32, types.TUINT8}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to8, types.TINT32}, + twoTypes{types.TFLOAT32, types.TUINT16}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to16, types.TINT32}, + twoTypes{types.TFLOAT32, types.TUINT32}: twoOpsAndType{ssa.OpCvt32Fto64, ssa.OpTrunc64to32, types.TINT64}, // go wide to dodge unsigned + twoTypes{types.TFLOAT32, types.TUINT64}: twoOpsAndType{ssa.OpInvalid, ssa.OpCopy, types.TUINT64}, // Cvt32Fto64U, branchy code expansion instead - twoTypes{TFLOAT64, TUINT8}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to8, TINT32}, - twoTypes{TFLOAT64, TUINT16}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to16, TINT32}, - twoTypes{TFLOAT64, TUINT32}: twoOpsAndType{ssa.OpCvt64Fto64, ssa.OpTrunc64to32, TINT64}, // go wide to dodge unsigned - twoTypes{TFLOAT64, TUINT64}: twoOpsAndType{ssa.OpInvalid, ssa.OpCopy, TUINT64}, // Cvt64Fto64U, branchy code expansion instead + twoTypes{types.TFLOAT64, types.TUINT8}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to8, types.TINT32}, + twoTypes{types.TFLOAT64, types.TUINT16}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to16, types.TINT32}, + twoTypes{types.TFLOAT64, types.TUINT32}: twoOpsAndType{ssa.OpCvt64Fto64, ssa.OpTrunc64to32, types.TINT64}, // go wide to dodge unsigned + twoTypes{types.TFLOAT64, types.TUINT64}: twoOpsAndType{ssa.OpInvalid, ssa.OpCopy, types.TUINT64}, // Cvt64Fto64U, branchy code expansion instead // float - twoTypes{TFLOAT64, TFLOAT32}: twoOpsAndType{ssa.OpCvt64Fto32F, ssa.OpCopy, TFLOAT32}, - twoTypes{TFLOAT64, TFLOAT64}: twoOpsAndType{ssa.OpRound64F, ssa.OpCopy, TFLOAT64}, - twoTypes{TFLOAT32, TFLOAT32}: twoOpsAndType{ssa.OpRound32F, ssa.OpCopy, TFLOAT32}, - twoTypes{TFLOAT32, TFLOAT64}: twoOpsAndType{ssa.OpCvt32Fto64F, ssa.OpCopy, TFLOAT64}, + twoTypes{types.TFLOAT64, types.TFLOAT32}: twoOpsAndType{ssa.OpCvt64Fto32F, ssa.OpCopy, types.TFLOAT32}, + twoTypes{types.TFLOAT64, types.TFLOAT64}: twoOpsAndType{ssa.OpRound64F, ssa.OpCopy, types.TFLOAT64}, + twoTypes{types.TFLOAT32, types.TFLOAT32}: twoOpsAndType{ssa.OpRound32F, ssa.OpCopy, types.TFLOAT32}, + twoTypes{types.TFLOAT32, types.TFLOAT64}: twoOpsAndType{ssa.OpCvt32Fto64F, ssa.OpCopy, types.TFLOAT64}, } // this map is used only for 32-bit arch, and only includes the difference // on 32-bit arch, don't use int64<->float conversion for uint32 var fpConvOpToSSA32 = map[twoTypes]twoOpsAndType{ - twoTypes{TUINT32, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32Uto32F, TUINT32}, - twoTypes{TUINT32, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32Uto64F, TUINT32}, - twoTypes{TFLOAT32, TUINT32}: twoOpsAndType{ssa.OpCvt32Fto32U, ssa.OpCopy, TUINT32}, - twoTypes{TFLOAT64, TUINT32}: twoOpsAndType{ssa.OpCvt64Fto32U, ssa.OpCopy, TUINT32}, + twoTypes{types.TUINT32, types.TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32Uto32F, types.TUINT32}, + twoTypes{types.TUINT32, types.TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32Uto64F, types.TUINT32}, + twoTypes{types.TFLOAT32, types.TUINT32}: twoOpsAndType{ssa.OpCvt32Fto32U, ssa.OpCopy, types.TUINT32}, + twoTypes{types.TFLOAT64, types.TUINT32}: twoOpsAndType{ssa.OpCvt64Fto32U, ssa.OpCopy, types.TUINT32}, } // uint64<->float conversions, only on machines that have instructions for that var uint64fpConvOpToSSA = map[twoTypes]twoOpsAndType{ - twoTypes{TUINT64, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64Uto32F, TUINT64}, - twoTypes{TUINT64, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64Uto64F, TUINT64}, - twoTypes{TFLOAT32, TUINT64}: twoOpsAndType{ssa.OpCvt32Fto64U, ssa.OpCopy, TUINT64}, - twoTypes{TFLOAT64, TUINT64}: twoOpsAndType{ssa.OpCvt64Fto64U, ssa.OpCopy, TUINT64}, + twoTypes{types.TUINT64, types.TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64Uto32F, types.TUINT64}, + twoTypes{types.TUINT64, types.TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64Uto64F, types.TUINT64}, + twoTypes{types.TFLOAT32, types.TUINT64}: twoOpsAndType{ssa.OpCvt32Fto64U, ssa.OpCopy, types.TUINT64}, + twoTypes{types.TFLOAT64, types.TUINT64}: twoOpsAndType{ssa.OpCvt64Fto64U, ssa.OpCopy, types.TUINT64}, } var shiftOpToSSA = map[opAndTwoTypes]ssa.Op{ - opAndTwoTypes{OLSH, TINT8, TUINT8}: ssa.OpLsh8x8, - opAndTwoTypes{OLSH, TUINT8, TUINT8}: ssa.OpLsh8x8, - opAndTwoTypes{OLSH, TINT8, TUINT16}: ssa.OpLsh8x16, - opAndTwoTypes{OLSH, TUINT8, TUINT16}: ssa.OpLsh8x16, - opAndTwoTypes{OLSH, TINT8, TUINT32}: ssa.OpLsh8x32, - opAndTwoTypes{OLSH, TUINT8, TUINT32}: ssa.OpLsh8x32, - opAndTwoTypes{OLSH, TINT8, TUINT64}: ssa.OpLsh8x64, - opAndTwoTypes{OLSH, TUINT8, TUINT64}: ssa.OpLsh8x64, + opAndTwoTypes{ir.OLSH, types.TINT8, types.TUINT8}: ssa.OpLsh8x8, + opAndTwoTypes{ir.OLSH, types.TUINT8, types.TUINT8}: ssa.OpLsh8x8, + opAndTwoTypes{ir.OLSH, types.TINT8, types.TUINT16}: ssa.OpLsh8x16, + opAndTwoTypes{ir.OLSH, types.TUINT8, types.TUINT16}: ssa.OpLsh8x16, + opAndTwoTypes{ir.OLSH, types.TINT8, types.TUINT32}: ssa.OpLsh8x32, + opAndTwoTypes{ir.OLSH, types.TUINT8, types.TUINT32}: ssa.OpLsh8x32, + opAndTwoTypes{ir.OLSH, types.TINT8, types.TUINT64}: ssa.OpLsh8x64, + opAndTwoTypes{ir.OLSH, types.TUINT8, types.TUINT64}: ssa.OpLsh8x64, - opAndTwoTypes{OLSH, TINT16, TUINT8}: ssa.OpLsh16x8, - opAndTwoTypes{OLSH, TUINT16, TUINT8}: ssa.OpLsh16x8, - opAndTwoTypes{OLSH, TINT16, TUINT16}: ssa.OpLsh16x16, - opAndTwoTypes{OLSH, TUINT16, TUINT16}: ssa.OpLsh16x16, - opAndTwoTypes{OLSH, TINT16, TUINT32}: ssa.OpLsh16x32, - opAndTwoTypes{OLSH, TUINT16, TUINT32}: ssa.OpLsh16x32, - opAndTwoTypes{OLSH, TINT16, TUINT64}: ssa.OpLsh16x64, - opAndTwoTypes{OLSH, TUINT16, TUINT64}: ssa.OpLsh16x64, + opAndTwoTypes{ir.OLSH, types.TINT16, types.TUINT8}: ssa.OpLsh16x8, + opAndTwoTypes{ir.OLSH, types.TUINT16, types.TUINT8}: ssa.OpLsh16x8, + opAndTwoTypes{ir.OLSH, types.TINT16, types.TUINT16}: ssa.OpLsh16x16, + opAndTwoTypes{ir.OLSH, types.TUINT16, types.TUINT16}: ssa.OpLsh16x16, + opAndTwoTypes{ir.OLSH, types.TINT16, types.TUINT32}: ssa.OpLsh16x32, + opAndTwoTypes{ir.OLSH, types.TUINT16, types.TUINT32}: ssa.OpLsh16x32, + opAndTwoTypes{ir.OLSH, types.TINT16, types.TUINT64}: ssa.OpLsh16x64, + opAndTwoTypes{ir.OLSH, types.TUINT16, types.TUINT64}: ssa.OpLsh16x64, - opAndTwoTypes{OLSH, TINT32, TUINT8}: ssa.OpLsh32x8, - opAndTwoTypes{OLSH, TUINT32, TUINT8}: ssa.OpLsh32x8, - opAndTwoTypes{OLSH, TINT32, TUINT16}: ssa.OpLsh32x16, - opAndTwoTypes{OLSH, TUINT32, TUINT16}: ssa.OpLsh32x16, - opAndTwoTypes{OLSH, TINT32, TUINT32}: ssa.OpLsh32x32, - opAndTwoTypes{OLSH, TUINT32, TUINT32}: ssa.OpLsh32x32, - opAndTwoTypes{OLSH, TINT32, TUINT64}: ssa.OpLsh32x64, - opAndTwoTypes{OLSH, TUINT32, TUINT64}: ssa.OpLsh32x64, + opAndTwoTypes{ir.OLSH, types.TINT32, types.TUINT8}: ssa.OpLsh32x8, + opAndTwoTypes{ir.OLSH, types.TUINT32, types.TUINT8}: ssa.OpLsh32x8, + opAndTwoTypes{ir.OLSH, types.TINT32, types.TUINT16}: ssa.OpLsh32x16, + opAndTwoTypes{ir.OLSH, types.TUINT32, types.TUINT16}: ssa.OpLsh32x16, + opAndTwoTypes{ir.OLSH, types.TINT32, types.TUINT32}: ssa.OpLsh32x32, + opAndTwoTypes{ir.OLSH, types.TUINT32, types.TUINT32}: ssa.OpLsh32x32, + opAndTwoTypes{ir.OLSH, types.TINT32, types.TUINT64}: ssa.OpLsh32x64, + opAndTwoTypes{ir.OLSH, types.TUINT32, types.TUINT64}: ssa.OpLsh32x64, - opAndTwoTypes{OLSH, TINT64, TUINT8}: ssa.OpLsh64x8, - opAndTwoTypes{OLSH, TUINT64, TUINT8}: ssa.OpLsh64x8, - opAndTwoTypes{OLSH, TINT64, TUINT16}: ssa.OpLsh64x16, - opAndTwoTypes{OLSH, TUINT64, TUINT16}: ssa.OpLsh64x16, - opAndTwoTypes{OLSH, TINT64, TUINT32}: ssa.OpLsh64x32, - opAndTwoTypes{OLSH, TUINT64, TUINT32}: ssa.OpLsh64x32, - opAndTwoTypes{OLSH, TINT64, TUINT64}: ssa.OpLsh64x64, - opAndTwoTypes{OLSH, TUINT64, TUINT64}: ssa.OpLsh64x64, + opAndTwoTypes{ir.OLSH, types.TINT64, types.TUINT8}: ssa.OpLsh64x8, + opAndTwoTypes{ir.OLSH, types.TUINT64, types.TUINT8}: ssa.OpLsh64x8, + opAndTwoTypes{ir.OLSH, types.TINT64, types.TUINT16}: ssa.OpLsh64x16, + opAndTwoTypes{ir.OLSH, types.TUINT64, types.TUINT16}: ssa.OpLsh64x16, + opAndTwoTypes{ir.OLSH, types.TINT64, types.TUINT32}: ssa.OpLsh64x32, + opAndTwoTypes{ir.OLSH, types.TUINT64, types.TUINT32}: ssa.OpLsh64x32, + opAndTwoTypes{ir.OLSH, types.TINT64, types.TUINT64}: ssa.OpLsh64x64, + opAndTwoTypes{ir.OLSH, types.TUINT64, types.TUINT64}: ssa.OpLsh64x64, - opAndTwoTypes{ORSH, TINT8, TUINT8}: ssa.OpRsh8x8, - opAndTwoTypes{ORSH, TUINT8, TUINT8}: ssa.OpRsh8Ux8, - opAndTwoTypes{ORSH, TINT8, TUINT16}: ssa.OpRsh8x16, - opAndTwoTypes{ORSH, TUINT8, TUINT16}: ssa.OpRsh8Ux16, - opAndTwoTypes{ORSH, TINT8, TUINT32}: ssa.OpRsh8x32, - opAndTwoTypes{ORSH, TUINT8, TUINT32}: ssa.OpRsh8Ux32, - opAndTwoTypes{ORSH, TINT8, TUINT64}: ssa.OpRsh8x64, - opAndTwoTypes{ORSH, TUINT8, TUINT64}: ssa.OpRsh8Ux64, + opAndTwoTypes{ir.ORSH, types.TINT8, types.TUINT8}: ssa.OpRsh8x8, + opAndTwoTypes{ir.ORSH, types.TUINT8, types.TUINT8}: ssa.OpRsh8Ux8, + opAndTwoTypes{ir.ORSH, types.TINT8, types.TUINT16}: ssa.OpRsh8x16, + opAndTwoTypes{ir.ORSH, types.TUINT8, types.TUINT16}: ssa.OpRsh8Ux16, + opAndTwoTypes{ir.ORSH, types.TINT8, types.TUINT32}: ssa.OpRsh8x32, + opAndTwoTypes{ir.ORSH, types.TUINT8, types.TUINT32}: ssa.OpRsh8Ux32, + opAndTwoTypes{ir.ORSH, types.TINT8, types.TUINT64}: ssa.OpRsh8x64, + opAndTwoTypes{ir.ORSH, types.TUINT8, types.TUINT64}: ssa.OpRsh8Ux64, - opAndTwoTypes{ORSH, TINT16, TUINT8}: ssa.OpRsh16x8, - opAndTwoTypes{ORSH, TUINT16, TUINT8}: ssa.OpRsh16Ux8, - opAndTwoTypes{ORSH, TINT16, TUINT16}: ssa.OpRsh16x16, - opAndTwoTypes{ORSH, TUINT16, TUINT16}: ssa.OpRsh16Ux16, - opAndTwoTypes{ORSH, TINT16, TUINT32}: ssa.OpRsh16x32, - opAndTwoTypes{ORSH, TUINT16, TUINT32}: ssa.OpRsh16Ux32, - opAndTwoTypes{ORSH, TINT16, TUINT64}: ssa.OpRsh16x64, - opAndTwoTypes{ORSH, TUINT16, TUINT64}: ssa.OpRsh16Ux64, + opAndTwoTypes{ir.ORSH, types.TINT16, types.TUINT8}: ssa.OpRsh16x8, + opAndTwoTypes{ir.ORSH, types.TUINT16, types.TUINT8}: ssa.OpRsh16Ux8, + opAndTwoTypes{ir.ORSH, types.TINT16, types.TUINT16}: ssa.OpRsh16x16, + opAndTwoTypes{ir.ORSH, types.TUINT16, types.TUINT16}: ssa.OpRsh16Ux16, + opAndTwoTypes{ir.ORSH, types.TINT16, types.TUINT32}: ssa.OpRsh16x32, + opAndTwoTypes{ir.ORSH, types.TUINT16, types.TUINT32}: ssa.OpRsh16Ux32, + opAndTwoTypes{ir.ORSH, types.TINT16, types.TUINT64}: ssa.OpRsh16x64, + opAndTwoTypes{ir.ORSH, types.TUINT16, types.TUINT64}: ssa.OpRsh16Ux64, - opAndTwoTypes{ORSH, TINT32, TUINT8}: ssa.OpRsh32x8, - opAndTwoTypes{ORSH, TUINT32, TUINT8}: ssa.OpRsh32Ux8, - opAndTwoTypes{ORSH, TINT32, TUINT16}: ssa.OpRsh32x16, - opAndTwoTypes{ORSH, TUINT32, TUINT16}: ssa.OpRsh32Ux16, - opAndTwoTypes{ORSH, TINT32, TUINT32}: ssa.OpRsh32x32, - opAndTwoTypes{ORSH, TUINT32, TUINT32}: ssa.OpRsh32Ux32, - opAndTwoTypes{ORSH, TINT32, TUINT64}: ssa.OpRsh32x64, - opAndTwoTypes{ORSH, TUINT32, TUINT64}: ssa.OpRsh32Ux64, + opAndTwoTypes{ir.ORSH, types.TINT32, types.TUINT8}: ssa.OpRsh32x8, + opAndTwoTypes{ir.ORSH, types.TUINT32, types.TUINT8}: ssa.OpRsh32Ux8, + opAndTwoTypes{ir.ORSH, types.TINT32, types.TUINT16}: ssa.OpRsh32x16, + opAndTwoTypes{ir.ORSH, types.TUINT32, types.TUINT16}: ssa.OpRsh32Ux16, + opAndTwoTypes{ir.ORSH, types.TINT32, types.TUINT32}: ssa.OpRsh32x32, + opAndTwoTypes{ir.ORSH, types.TUINT32, types.TUINT32}: ssa.OpRsh32Ux32, + opAndTwoTypes{ir.ORSH, types.TINT32, types.TUINT64}: ssa.OpRsh32x64, + opAndTwoTypes{ir.ORSH, types.TUINT32, types.TUINT64}: ssa.OpRsh32Ux64, - opAndTwoTypes{ORSH, TINT64, TUINT8}: ssa.OpRsh64x8, - opAndTwoTypes{ORSH, TUINT64, TUINT8}: ssa.OpRsh64Ux8, - opAndTwoTypes{ORSH, TINT64, TUINT16}: ssa.OpRsh64x16, - opAndTwoTypes{ORSH, TUINT64, TUINT16}: ssa.OpRsh64Ux16, - opAndTwoTypes{ORSH, TINT64, TUINT32}: ssa.OpRsh64x32, - opAndTwoTypes{ORSH, TUINT64, TUINT32}: ssa.OpRsh64Ux32, - opAndTwoTypes{ORSH, TINT64, TUINT64}: ssa.OpRsh64x64, - opAndTwoTypes{ORSH, TUINT64, TUINT64}: ssa.OpRsh64Ux64, + opAndTwoTypes{ir.ORSH, types.TINT64, types.TUINT8}: ssa.OpRsh64x8, + opAndTwoTypes{ir.ORSH, types.TUINT64, types.TUINT8}: ssa.OpRsh64Ux8, + opAndTwoTypes{ir.ORSH, types.TINT64, types.TUINT16}: ssa.OpRsh64x16, + opAndTwoTypes{ir.ORSH, types.TUINT64, types.TUINT16}: ssa.OpRsh64Ux16, + opAndTwoTypes{ir.ORSH, types.TINT64, types.TUINT32}: ssa.OpRsh64x32, + opAndTwoTypes{ir.ORSH, types.TUINT64, types.TUINT32}: ssa.OpRsh64Ux32, + opAndTwoTypes{ir.ORSH, types.TINT64, types.TUINT64}: ssa.OpRsh64x64, + opAndTwoTypes{ir.ORSH, types.TUINT64, types.TUINT64}: ssa.OpRsh64Ux64, } -func (s *state) ssaShiftOp(op Op, t *types.Type, u *types.Type) ssa.Op { +func (s *state) ssaShiftOp(op ir.Op, t *types.Type, u *types.Type) ssa.Op { etype1 := s.concreteEtype(t) etype2 := s.concreteEtype(u) x, ok := shiftOpToSSA[opAndTwoTypes{op, etype1, etype2}] @@ -1998,7 +1999,7 @@ func (s *state) ssaShiftOp(op Op, t *types.Type, u *types.Type) ssa.Op { } // expr converts the expression n to ssa, adds it to s and returns the ssa result. -func (s *state) expr(n *Node) *ssa.Value { +func (s *state) expr(n *ir.Node) *ssa.Value { if hasUniquePos(n) { // ONAMEs and named OLITERALs have the line number // of the decl, not the use. See issue 14742. @@ -2008,24 +2009,24 @@ func (s *state) expr(n *Node) *ssa.Value { s.stmtList(n.Ninit) switch n.Op { - case OBYTES2STRTMP: + case ir.OBYTES2STRTMP: slice := s.expr(n.Left) ptr := s.newValue1(ssa.OpSlicePtr, s.f.Config.Types.BytePtr, slice) - len := s.newValue1(ssa.OpSliceLen, types.Types[TINT], slice) + len := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], slice) return s.newValue2(ssa.OpStringMake, n.Type, ptr, len) - case OSTR2BYTESTMP: + case ir.OSTR2BYTESTMP: str := s.expr(n.Left) ptr := s.newValue1(ssa.OpStringPtr, s.f.Config.Types.BytePtr, str) - len := s.newValue1(ssa.OpStringLen, types.Types[TINT], str) + len := s.newValue1(ssa.OpStringLen, types.Types[types.TINT], str) return s.newValue3(ssa.OpSliceMake, n.Type, ptr, len, len) - case OCFUNC: + case ir.OCFUNC: aux := n.Left.Sym.Linksym() return s.entryNewValue1A(ssa.OpAddr, n.Type, aux, s.sb) - case OMETHEXPR: + case ir.OMETHEXPR: sym := funcsym(n.Sym).Linksym() return s.entryNewValue1A(ssa.OpAddr, types.NewPtr(n.Type), sym, s.sb) - case ONAME: - if n.Class() == PFUNC { + case ir.ONAME: + if n.Class() == ir.PFUNC { // "value" of a function is the address of the function's closure sym := funcsym(n.Sym).Linksym() return s.entryNewValue1A(ssa.OpAddr, types.NewPtr(n.Type), sym, s.sb) @@ -2035,10 +2036,10 @@ func (s *state) expr(n *Node) *ssa.Value { } addr := s.addr(n) return s.load(n.Type, addr) - case OCLOSUREVAR: + case ir.OCLOSUREVAR: addr := s.addr(n) return s.load(n.Type, addr) - case ONIL: + case ir.ONIL: t := n.Type switch { case t.IsSlice(): @@ -2048,10 +2049,10 @@ func (s *state) expr(n *Node) *ssa.Value { default: return s.constNil(t) } - case OLITERAL: + case ir.OLITERAL: switch u := n.Val(); u.Kind() { case constant.Int: - i := int64Val(n.Type, u) + i := ir.Int64Val(n.Type, u) switch n.Type.Size() { case 1: return s.constInt8(n.Type, int8(i)) @@ -2089,12 +2090,12 @@ func (s *state) expr(n *Node) *ssa.Value { im, _ := constant.Float64Val(constant.Imag(u)) switch n.Type.Size() { case 8: - pt := types.Types[TFLOAT32] + pt := types.Types[types.TFLOAT32] return s.newValue2(ssa.OpComplexMake, n.Type, s.constFloat32(pt, re), s.constFloat32(pt, im)) case 16: - pt := types.Types[TFLOAT64] + pt := types.Types[types.TFLOAT64] return s.newValue2(ssa.OpComplexMake, n.Type, s.constFloat64(pt, re), s.constFloat64(pt, im)) @@ -2106,7 +2107,7 @@ func (s *state) expr(n *Node) *ssa.Value { s.Fatalf("unhandled OLITERAL %v", u.Kind()) return nil } - case OCONVNOP: + case ir.OCONVNOP: to := n.Type from := n.Left.Type @@ -2125,7 +2126,7 @@ func (s *state) expr(n *Node) *ssa.Value { v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type // CONVNOP closure - if to.Etype == TFUNC && from.IsPtrShaped() { + if to.Etype == types.TFUNC && from.IsPtrShaped() { return v } @@ -2140,7 +2141,7 @@ func (s *state) expr(n *Node) *ssa.Value { } // map <--> *hmap - if to.Etype == TMAP && from.IsPtr() && + if to.Etype == types.TMAP && from.IsPtr() && to.MapType().Hmap == from.Elem() { return v } @@ -2171,11 +2172,11 @@ func (s *state) expr(n *Node) *ssa.Value { // integer, same width, same sign return v - case OCONV: + case ir.OCONV: x := s.expr(n.Left) ft := n.Left.Type // from type tt := n.Type // to type - if ft.IsBoolean() && tt.IsKind(TUINT8) { + if ft.IsBoolean() && tt.IsKind(types.TUINT8) { // Bool -> uint8 is generated internally when indexing into runtime.staticbyte. return s.newValue1(ssa.OpCopy, n.Type, x) } @@ -2342,25 +2343,25 @@ func (s *state) expr(n *Node) *ssa.Value { s.Fatalf("unhandled OCONV %s -> %s", n.Left.Type.Etype, n.Type.Etype) return nil - case ODOTTYPE: + case ir.ODOTTYPE: res, _ := s.dottype(n, false) return res // binary ops - case OLT, OEQ, ONE, OLE, OGE, OGT: + case ir.OLT, ir.OEQ, ir.ONE, ir.OLE, ir.OGE, ir.OGT: a := s.expr(n.Left) b := s.expr(n.Right) if n.Left.Type.IsComplex() { pt := floatForComplex(n.Left.Type) - op := s.ssaOp(OEQ, pt) - r := s.newValueOrSfCall2(op, types.Types[TBOOL], s.newValue1(ssa.OpComplexReal, pt, a), s.newValue1(ssa.OpComplexReal, pt, b)) - i := s.newValueOrSfCall2(op, types.Types[TBOOL], s.newValue1(ssa.OpComplexImag, pt, a), s.newValue1(ssa.OpComplexImag, pt, b)) - c := s.newValue2(ssa.OpAndB, types.Types[TBOOL], r, i) + op := s.ssaOp(ir.OEQ, pt) + r := s.newValueOrSfCall2(op, types.Types[types.TBOOL], s.newValue1(ssa.OpComplexReal, pt, a), s.newValue1(ssa.OpComplexReal, pt, b)) + i := s.newValueOrSfCall2(op, types.Types[types.TBOOL], s.newValue1(ssa.OpComplexImag, pt, a), s.newValue1(ssa.OpComplexImag, pt, b)) + c := s.newValue2(ssa.OpAndB, types.Types[types.TBOOL], r, i) switch n.Op { - case OEQ: + case ir.OEQ: return c - case ONE: - return s.newValue1(ssa.OpNot, types.Types[TBOOL], c) + case ir.ONE: + return s.newValue1(ssa.OpNot, types.Types[types.TBOOL], c) default: s.Fatalf("ordered complex compare %v", n.Op) } @@ -2369,26 +2370,26 @@ func (s *state) expr(n *Node) *ssa.Value { // Convert OGE and OGT into OLE and OLT. op := n.Op switch op { - case OGE: - op, a, b = OLE, b, a - case OGT: - op, a, b = OLT, b, a + case ir.OGE: + op, a, b = ir.OLE, b, a + case ir.OGT: + op, a, b = ir.OLT, b, a } if n.Left.Type.IsFloat() { // float comparison - return s.newValueOrSfCall2(s.ssaOp(op, n.Left.Type), types.Types[TBOOL], a, b) + return s.newValueOrSfCall2(s.ssaOp(op, n.Left.Type), types.Types[types.TBOOL], a, b) } // integer comparison - return s.newValue2(s.ssaOp(op, n.Left.Type), types.Types[TBOOL], a, b) - case OMUL: + return s.newValue2(s.ssaOp(op, n.Left.Type), types.Types[types.TBOOL], a, b) + case ir.OMUL: a := s.expr(n.Left) b := s.expr(n.Right) if n.Type.IsComplex() { mulop := ssa.OpMul64F addop := ssa.OpAdd64F subop := ssa.OpSub64F - pt := floatForComplex(n.Type) // Could be Float32 or Float64 - wt := types.Types[TFLOAT64] // Compute in Float64 to minimize cancellation error + pt := floatForComplex(n.Type) // Could be Float32 or Float64 + wt := types.Types[types.TFLOAT64] // Compute in Float64 to minimize cancellation error areal := s.newValue1(ssa.OpComplexReal, pt, a) breal := s.newValue1(ssa.OpComplexReal, pt, b) @@ -2419,7 +2420,7 @@ func (s *state) expr(n *Node) *ssa.Value { return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) - case ODIV: + case ir.ODIV: a := s.expr(n.Left) b := s.expr(n.Right) if n.Type.IsComplex() { @@ -2430,8 +2431,8 @@ func (s *state) expr(n *Node) *ssa.Value { addop := ssa.OpAdd64F subop := ssa.OpSub64F divop := ssa.OpDiv64F - pt := floatForComplex(n.Type) // Could be Float32 or Float64 - wt := types.Types[TFLOAT64] // Compute in Float64 to minimize cancellation error + pt := floatForComplex(n.Type) // Could be Float32 or Float64 + wt := types.Types[types.TFLOAT64] // Compute in Float64 to minimize cancellation error areal := s.newValue1(ssa.OpComplexReal, pt, a) breal := s.newValue1(ssa.OpComplexReal, pt, b) @@ -2466,11 +2467,11 @@ func (s *state) expr(n *Node) *ssa.Value { return s.newValueOrSfCall2(s.ssaOp(n.Op, n.Type), a.Type, a, b) } return s.intDivide(n, a, b) - case OMOD: + case ir.OMOD: a := s.expr(n.Left) b := s.expr(n.Right) return s.intDivide(n, a, b) - case OADD, OSUB: + case ir.OADD, ir.OSUB: a := s.expr(n.Left) b := s.expr(n.Right) if n.Type.IsComplex() { @@ -2484,26 +2485,26 @@ func (s *state) expr(n *Node) *ssa.Value { return s.newValueOrSfCall2(s.ssaOp(n.Op, n.Type), a.Type, a, b) } return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) - case OAND, OOR, OXOR: + case ir.OAND, ir.OOR, ir.OXOR: a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) - case OANDNOT: + case ir.OANDNOT: a := s.expr(n.Left) b := s.expr(n.Right) - b = s.newValue1(s.ssaOp(OBITNOT, b.Type), b.Type, b) - return s.newValue2(s.ssaOp(OAND, n.Type), a.Type, a, b) - case OLSH, ORSH: + b = s.newValue1(s.ssaOp(ir.OBITNOT, b.Type), b.Type, b) + return s.newValue2(s.ssaOp(ir.OAND, n.Type), a.Type, a, b) + case ir.OLSH, ir.ORSH: a := s.expr(n.Left) b := s.expr(n.Right) bt := b.Type if bt.IsSigned() { - cmp := s.newValue2(s.ssaOp(OLE, bt), types.Types[TBOOL], s.zeroVal(bt), b) + cmp := s.newValue2(s.ssaOp(ir.OLE, bt), types.Types[types.TBOOL], s.zeroVal(bt), b) s.check(cmp, panicshift) bt = bt.ToUnsigned() } return s.newValue2(s.ssaShiftOp(n.Op, n.Type, bt), a.Type, a, b) - case OANDAND, OOROR: + case ir.OANDAND, ir.OOROR: // To implement OANDAND (and OOROR), we introduce a // new temporary variable to hold the result. The // variable is associated with the OANDAND node in the @@ -2530,10 +2531,10 @@ func (s *state) expr(n *Node) *ssa.Value { bRight := s.f.NewBlock(ssa.BlockPlain) bResult := s.f.NewBlock(ssa.BlockPlain) - if n.Op == OANDAND { + if n.Op == ir.OANDAND { b.AddEdgeTo(bRight) b.AddEdgeTo(bResult) - } else if n.Op == OOROR { + } else if n.Op == ir.OOROR { b.AddEdgeTo(bResult) b.AddEdgeTo(bRight) } @@ -2546,14 +2547,14 @@ func (s *state) expr(n *Node) *ssa.Value { b.AddEdgeTo(bResult) s.startBlock(bResult) - return s.variable(n, types.Types[TBOOL]) - case OCOMPLEX: + return s.variable(n, types.Types[types.TBOOL]) + case ir.OCOMPLEX: r := s.expr(n.Left) i := s.expr(n.Right) return s.newValue2(ssa.OpComplexMake, n.Type, r, i) // unary ops - case ONEG: + case ir.ONEG: a := s.expr(n.Left) if n.Type.IsComplex() { tp := floatForComplex(n.Type) @@ -2563,19 +2564,19 @@ func (s *state) expr(n *Node) *ssa.Value { s.newValue1(negop, tp, s.newValue1(ssa.OpComplexImag, tp, a))) } return s.newValue1(s.ssaOp(n.Op, n.Type), a.Type, a) - case ONOT, OBITNOT: + case ir.ONOT, ir.OBITNOT: a := s.expr(n.Left) return s.newValue1(s.ssaOp(n.Op, n.Type), a.Type, a) - case OIMAG, OREAL: + case ir.OIMAG, ir.OREAL: a := s.expr(n.Left) return s.newValue1(s.ssaOp(n.Op, n.Left.Type), n.Type, a) - case OPLUS: + case ir.OPLUS: return s.expr(n.Left) - case OADDR: + case ir.OADDR: return s.addr(n.Left) - case ORESULT: + case ir.ORESULT: if s.prevCall == nil || s.prevCall.Op != ssa.OpStaticLECall && s.prevCall.Op != ssa.OpInterLECall && s.prevCall.Op != ssa.OpClosureLECall { // Do the old thing addr := s.constOffPtrSP(types.NewPtr(n.Type), n.Xoffset) @@ -2594,12 +2595,12 @@ func (s *state) expr(n *Node) *ssa.Value { return s.rawLoad(n.Type, addr) } - case ODEREF: + case ir.ODEREF: p := s.exprPtr(n.Left, n.Bounded(), n.Pos) return s.load(n.Type, p) - case ODOT: - if n.Left.Op == OSTRUCTLIT { + case ir.ODOT: + if n.Left.Op == ir.OSTRUCTLIT { // All literals with nonzero fields have already been // rewritten during walk. Any that remain are just T{} // or equivalents. Use the zero value. @@ -2619,32 +2620,32 @@ func (s *state) expr(n *Node) *ssa.Value { v := s.expr(n.Left) return s.newValue1I(ssa.OpStructSelect, n.Type, int64(fieldIdx(n)), v) - case ODOTPTR: + case ir.ODOTPTR: p := s.exprPtr(n.Left, n.Bounded(), n.Pos) p = s.newValue1I(ssa.OpOffPtr, types.NewPtr(n.Type), n.Xoffset, p) return s.load(n.Type, p) - case OINDEX: + case ir.OINDEX: switch { case n.Left.Type.IsString(): - if n.Bounded() && Isconst(n.Left, constant.String) && Isconst(n.Right, constant.Int) { + if n.Bounded() && ir.IsConst(n.Left, constant.String) && ir.IsConst(n.Right, constant.Int) { // Replace "abc"[1] with 'b'. // Delayed until now because "abc"[1] is not an ideal constant. // See test/fixedbugs/issue11370.go. - return s.newValue0I(ssa.OpConst8, types.Types[TUINT8], int64(int8(n.Left.StringVal()[n.Right.Int64Val()]))) + return s.newValue0I(ssa.OpConst8, types.Types[types.TUINT8], int64(int8(n.Left.StringVal()[n.Right.Int64Val()]))) } a := s.expr(n.Left) i := s.expr(n.Right) - len := s.newValue1(ssa.OpStringLen, types.Types[TINT], a) + len := s.newValue1(ssa.OpStringLen, types.Types[types.TINT], a) i = s.boundsCheck(i, len, ssa.BoundsIndex, n.Bounded()) ptrtyp := s.f.Config.Types.BytePtr ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a) - if Isconst(n.Right, constant.Int) { + if ir.IsConst(n.Right, constant.Int) { ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, n.Right.Int64Val(), ptr) } else { ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i) } - return s.load(types.Types[TUINT8], ptr) + return s.load(types.Types[types.TUINT8], ptr) case n.Left.Type.IsSlice(): p := s.addr(n) return s.load(n.Left.Type.Elem(), p) @@ -2657,12 +2658,12 @@ func (s *state) expr(n *Node) *ssa.Value { if bound == 0 { // Bounds check will never succeed. Might as well // use constants for the bounds check. - z := s.constInt(types.Types[TINT], 0) + z := s.constInt(types.Types[types.TINT], 0) s.boundsCheck(z, z, ssa.BoundsIndex, false) // The return value won't be live, return junk. return s.newValue0(ssa.OpUnknown, n.Type) } - len := s.constInt(types.Types[TINT], bound) + len := s.constInt(types.Types[types.TINT], bound) s.boundsCheck(i, len, ssa.BoundsIndex, n.Bounded()) // checks i == 0 return s.newValue1I(ssa.OpArraySelect, n.Type, 0, a) } @@ -2673,23 +2674,23 @@ func (s *state) expr(n *Node) *ssa.Value { return nil } - case OLEN, OCAP: + case ir.OLEN, ir.OCAP: switch { case n.Left.Type.IsSlice(): op := ssa.OpSliceLen - if n.Op == OCAP { + if n.Op == ir.OCAP { op = ssa.OpSliceCap } - return s.newValue1(op, types.Types[TINT], s.expr(n.Left)) + return s.newValue1(op, types.Types[types.TINT], s.expr(n.Left)) case n.Left.Type.IsString(): // string; not reachable for OCAP - return s.newValue1(ssa.OpStringLen, types.Types[TINT], s.expr(n.Left)) + return s.newValue1(ssa.OpStringLen, types.Types[types.TINT], s.expr(n.Left)) case n.Left.Type.IsMap(), n.Left.Type.IsChan(): return s.referenceTypeBuiltin(n, s.expr(n.Left)) default: // array - return s.constInt(types.Types[TINT], n.Left.Type.NumElem()) + return s.constInt(types.Types[types.TINT], n.Left.Type.NumElem()) } - case OSPTR: + case ir.OSPTR: a := s.expr(n.Left) if n.Left.Type.IsSlice() { return s.newValue1(ssa.OpSlicePtr, n.Type, a) @@ -2697,26 +2698,26 @@ func (s *state) expr(n *Node) *ssa.Value { return s.newValue1(ssa.OpStringPtr, n.Type, a) } - case OITAB: + case ir.OITAB: a := s.expr(n.Left) return s.newValue1(ssa.OpITab, n.Type, a) - case OIDATA: + case ir.OIDATA: a := s.expr(n.Left) return s.newValue1(ssa.OpIData, n.Type, a) - case OEFACE: + case ir.OEFACE: tab := s.expr(n.Left) data := s.expr(n.Right) return s.newValue2(ssa.OpIMake, n.Type, tab, data) - case OSLICEHEADER: + case ir.OSLICEHEADER: p := s.expr(n.Left) l := s.expr(n.List.First()) c := s.expr(n.List.Second()) return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c) - case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR: + case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR: v := s.expr(n.Left) var i, j, k *ssa.Value low, high, max := n.SliceBounds() @@ -2732,7 +2733,7 @@ func (s *state) expr(n *Node) *ssa.Value { p, l, c := s.slice(v, i, j, k, n.Bounded()) return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c) - case OSLICESTR: + case ir.OSLICESTR: v := s.expr(n.Left) var i, j *ssa.Value low, high, _ := n.SliceBounds() @@ -2745,22 +2746,22 @@ func (s *state) expr(n *Node) *ssa.Value { p, l, _ := s.slice(v, i, j, nil, n.Bounded()) return s.newValue2(ssa.OpStringMake, n.Type, p, l) - case OCALLFUNC: + case ir.OCALLFUNC: if isIntrinsicCall(n) { return s.intrinsicCall(n) } fallthrough - case OCALLINTER, OCALLMETH: + case ir.OCALLINTER, ir.OCALLMETH: return s.callResult(n, callNormal) - case OGETG: + case ir.OGETG: return s.newValue1(ssa.OpGetG, n.Type, s.mem()) - case OAPPEND: + case ir.OAPPEND: return s.append(n, false) - case OSTRUCTLIT, OARRAYLIT: + case ir.OSTRUCTLIT, ir.OARRAYLIT: // All literals with nonzero fields have already been // rewritten during walk. Any that remain are just T{} // or equivalents. Use the zero value. @@ -2769,7 +2770,7 @@ func (s *state) expr(n *Node) *ssa.Value { } return s.zeroVal(n.Type) - case ONEWOBJ: + case ir.ONEWOBJ: if n.Type.Elem().Size() == 0 { return s.newValue1A(ssa.OpAddr, n.Type, zerobaseSym, s.sb) } @@ -2789,7 +2790,7 @@ func (s *state) expr(n *Node) *ssa.Value { // If inplace is true, it writes the result of the OAPPEND expression n // back to the slice being appended to, and returns nil. // inplace MUST be set to false if the slice can be SSA'd. -func (s *state) append(n *Node, inplace bool) *ssa.Value { +func (s *state) append(n *ir.Node, inplace bool) *ssa.Value { // If inplace is false, process as expression "append(s, e1, e2, e3)": // // ptr, len, cap := s @@ -2844,11 +2845,11 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value { // Decide if we need to grow nargs := int64(n.List.Len() - 1) p := s.newValue1(ssa.OpSlicePtr, pt, slice) - l := s.newValue1(ssa.OpSliceLen, types.Types[TINT], slice) - c := s.newValue1(ssa.OpSliceCap, types.Types[TINT], slice) - nl := s.newValue2(s.ssaOp(OADD, types.Types[TINT]), types.Types[TINT], l, s.constInt(types.Types[TINT], nargs)) + l := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], slice) + c := s.newValue1(ssa.OpSliceCap, types.Types[types.TINT], slice) + nl := s.newValue2(s.ssaOp(ir.OADD, types.Types[types.TINT]), types.Types[types.TINT], l, s.constInt(types.Types[types.TINT], nargs)) - cmp := s.newValue2(s.ssaOp(OLT, types.Types[TUINT]), types.Types[types.TBOOL], c, nl) + cmp := s.newValue2(s.ssaOp(ir.OLT, types.Types[types.TUINT]), types.Types[types.TBOOL], c, nl) s.vars[ptrVar] = p if !inplace { @@ -2868,22 +2869,22 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value { // Call growslice s.startBlock(grow) taddr := s.expr(n.Left) - r := s.rtcall(growslice, true, []*types.Type{pt, types.Types[TINT], types.Types[TINT]}, taddr, p, l, c, nl) + r := s.rtcall(growslice, true, []*types.Type{pt, types.Types[types.TINT], types.Types[types.TINT]}, taddr, p, l, c, nl) if inplace { - if sn.Op == ONAME && sn.Class() != PEXTERN { + if sn.Op == ir.ONAME && sn.Class() != ir.PEXTERN { // Tell liveness we're about to build a new slice s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, sn, s.mem()) } capaddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, sliceCapOffset, addr) - s.store(types.Types[TINT], capaddr, r[2]) + s.store(types.Types[types.TINT], capaddr, r[2]) s.store(pt, addr, r[0]) // load the value we just stored to avoid having to spill it s.vars[ptrVar] = s.load(pt, addr) s.vars[lenVar] = r[1] // avoid a spill in the fast path } else { s.vars[ptrVar] = r[0] - s.vars[newlenVar] = s.newValue2(s.ssaOp(OADD, types.Types[TINT]), types.Types[TINT], r[1], s.constInt(types.Types[TINT], nargs)) + s.vars[newlenVar] = s.newValue2(s.ssaOp(ir.OADD, types.Types[types.TINT]), types.Types[types.TINT], r[1], s.constInt(types.Types[types.TINT], nargs)) s.vars[capVar] = r[2] } @@ -2894,10 +2895,10 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value { s.startBlock(assign) if inplace { - l = s.variable(lenVar, types.Types[TINT]) // generates phi for len - nl = s.newValue2(s.ssaOp(OADD, types.Types[TINT]), types.Types[TINT], l, s.constInt(types.Types[TINT], nargs)) + l = s.variable(lenVar, types.Types[types.TINT]) // generates phi for len + nl = s.newValue2(s.ssaOp(ir.OADD, types.Types[types.TINT]), types.Types[types.TINT], l, s.constInt(types.Types[types.TINT], nargs)) lenaddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, sliceLenOffset, addr) - s.store(types.Types[TINT], lenaddr, nl) + s.store(types.Types[types.TINT], lenaddr, nl) } // Evaluate args @@ -2919,12 +2920,12 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value { p = s.variable(ptrVar, pt) // generates phi for ptr if !inplace { - nl = s.variable(newlenVar, types.Types[TINT]) // generates phi for nl - c = s.variable(capVar, types.Types[TINT]) // generates phi for cap + nl = s.variable(newlenVar, types.Types[types.TINT]) // generates phi for nl + c = s.variable(capVar, types.Types[types.TINT]) // generates phi for cap } p2 := s.newValue2(ssa.OpPtrIndex, pt, p, l) for i, arg := range args { - addr := s.newValue2(ssa.OpPtrIndex, pt, p2, s.constInt(types.Types[TINT], int64(i))) + addr := s.newValue2(ssa.OpPtrIndex, pt, p2, s.constInt(types.Types[types.TINT], int64(i))) if arg.store { s.storeType(et, addr, arg.v, 0, true) } else { @@ -2947,9 +2948,9 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value { // if cond is true and no if cond is false. // This function is intended to handle && and || better than just calling // s.expr(cond) and branching on the result. -func (s *state) condBranch(cond *Node, yes, no *ssa.Block, likely int8) { +func (s *state) condBranch(cond *ir.Node, yes, no *ssa.Block, likely int8) { switch cond.Op { - case OANDAND: + case ir.OANDAND: mid := s.f.NewBlock(ssa.BlockPlain) s.stmtList(cond.Ninit) s.condBranch(cond.Left, mid, no, max8(likely, 0)) @@ -2962,7 +2963,7 @@ func (s *state) condBranch(cond *Node, yes, no *ssa.Block, likely int8) { // the likeliness of the first branch. // TODO: have the frontend give us branch prediction hints for // OANDAND and OOROR nodes (if it ever has such info). - case OOROR: + case ir.OOROR: mid := s.f.NewBlock(ssa.BlockPlain) s.stmtList(cond.Ninit) s.condBranch(cond.Left, yes, mid, min8(likely, 0)) @@ -2972,7 +2973,7 @@ func (s *state) condBranch(cond *Node, yes, no *ssa.Block, likely int8) { // Note: if likely==-1, then both recursive calls pass -1. // If likely==1, then we don't have enough info to decide // the likelihood of the first branch. - case ONOT: + case ir.ONOT: s.stmtList(cond.Ninit) s.condBranch(cond.Left, no, yes, -likely) return @@ -2999,8 +3000,8 @@ const ( // If deref is true, then we do left = *right instead (and right has already been nil-checked). // If deref is true and right == nil, just do left = 0. // skip indicates assignments (at the top level) that can be avoided. -func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask) { - if left.Op == ONAME && left.isBlank() { +func (s *state) assign(left *ir.Node, right *ssa.Value, deref bool, skip skipMask) { + if left.Op == ir.ONAME && ir.IsBlank(left) { return } t := left.Type @@ -3009,7 +3010,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask) if deref { s.Fatalf("can SSA LHS %v but not RHS %s", left, right) } - if left.Op == ODOT { + if left.Op == ir.ODOT { // We're assigning to a field of an ssa-able value. // We need to build a new structure with the new value for the // field we're assigning and the old values for the other fields. @@ -3044,7 +3045,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask) // TODO: do we need to update named values here? return } - if left.Op == OINDEX && left.Left.Type.IsArray() { + if left.Op == ir.OINDEX && left.Left.Type.IsArray() { s.pushLine(left.Pos) defer s.popLine() // We're assigning to an element of an ssa-able array. @@ -3056,7 +3057,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask) if n == 0 { // The bounds check must fail. Might as well // ignore the actual index and just use zeros. - z := s.constInt(types.Types[TINT], 0) + z := s.constInt(types.Types[types.TINT], 0) s.boundsCheck(z, z, ssa.BoundsIndex, false) return } @@ -3064,7 +3065,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask) s.Fatalf("assigning to non-1-length array") } // Rewrite to a = [1]{v} - len := s.constInt(types.Types[TINT], 1) + len := s.constInt(types.Types[types.TINT], 1) s.boundsCheck(i, len, ssa.BoundsIndex, false) // checks i == 0 v := s.newValue1(ssa.OpArrayMake1, t, right) s.assign(left.Left, v, false, 0) @@ -3078,7 +3079,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask) // If this assignment clobbers an entire local variable, then emit // OpVarDef so liveness analysis knows the variable is redefined. - if base := clobberBase(left); base.Op == ONAME && base.Class() != PEXTERN && skip == 0 { + if base := clobberBase(left); base.Op == ir.ONAME && base.Class() != ir.PEXTERN && skip == 0 { s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, base, s.mem(), !base.IsAutoTmp()) } @@ -3090,7 +3091,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask) // is valid, even though they have type uintptr (#19168). // Mark it pointer type to signal the writebarrier pass to // insert a write barrier. - t = types.Types[TUNSAFEPTR] + t = types.Types[types.TUNSAFEPTR] } if deref { // Treat as a mem->mem move. @@ -3133,10 +3134,10 @@ func (s *state) zeroVal(t *types.Type) *ssa.Value { case t.IsComplex(): switch t.Size() { case 8: - z := s.constFloat32(types.Types[TFLOAT32], 0) + z := s.constFloat32(types.Types[types.TFLOAT32], 0) return s.entryNewValue2(ssa.OpComplexMake, t, z, z) case 16: - z := s.constFloat64(types.Types[TFLOAT64], 0) + z := s.constFloat64(types.Types[types.TFLOAT64], 0) return s.entryNewValue2(ssa.OpComplexMake, t, z, z) default: s.Fatalf("bad sized complex type %v", t) @@ -3190,38 +3191,38 @@ var softFloatOps map[ssa.Op]sfRtCallDef func softfloatInit() { // Some of these operations get transformed by sfcall. softFloatOps = map[ssa.Op]sfRtCallDef{ - ssa.OpAdd32F: sfRtCallDef{sysfunc("fadd32"), TFLOAT32}, - ssa.OpAdd64F: sfRtCallDef{sysfunc("fadd64"), TFLOAT64}, - ssa.OpSub32F: sfRtCallDef{sysfunc("fadd32"), TFLOAT32}, - ssa.OpSub64F: sfRtCallDef{sysfunc("fadd64"), TFLOAT64}, - ssa.OpMul32F: sfRtCallDef{sysfunc("fmul32"), TFLOAT32}, - ssa.OpMul64F: sfRtCallDef{sysfunc("fmul64"), TFLOAT64}, - ssa.OpDiv32F: sfRtCallDef{sysfunc("fdiv32"), TFLOAT32}, - ssa.OpDiv64F: sfRtCallDef{sysfunc("fdiv64"), TFLOAT64}, + ssa.OpAdd32F: sfRtCallDef{sysfunc("fadd32"), types.TFLOAT32}, + ssa.OpAdd64F: sfRtCallDef{sysfunc("fadd64"), types.TFLOAT64}, + ssa.OpSub32F: sfRtCallDef{sysfunc("fadd32"), types.TFLOAT32}, + ssa.OpSub64F: sfRtCallDef{sysfunc("fadd64"), types.TFLOAT64}, + ssa.OpMul32F: sfRtCallDef{sysfunc("fmul32"), types.TFLOAT32}, + ssa.OpMul64F: sfRtCallDef{sysfunc("fmul64"), types.TFLOAT64}, + ssa.OpDiv32F: sfRtCallDef{sysfunc("fdiv32"), types.TFLOAT32}, + ssa.OpDiv64F: sfRtCallDef{sysfunc("fdiv64"), types.TFLOAT64}, - ssa.OpEq64F: sfRtCallDef{sysfunc("feq64"), TBOOL}, - ssa.OpEq32F: sfRtCallDef{sysfunc("feq32"), TBOOL}, - ssa.OpNeq64F: sfRtCallDef{sysfunc("feq64"), TBOOL}, - ssa.OpNeq32F: sfRtCallDef{sysfunc("feq32"), TBOOL}, - ssa.OpLess64F: sfRtCallDef{sysfunc("fgt64"), TBOOL}, - ssa.OpLess32F: sfRtCallDef{sysfunc("fgt32"), TBOOL}, - ssa.OpLeq64F: sfRtCallDef{sysfunc("fge64"), TBOOL}, - ssa.OpLeq32F: sfRtCallDef{sysfunc("fge32"), TBOOL}, + ssa.OpEq64F: sfRtCallDef{sysfunc("feq64"), types.TBOOL}, + ssa.OpEq32F: sfRtCallDef{sysfunc("feq32"), types.TBOOL}, + ssa.OpNeq64F: sfRtCallDef{sysfunc("feq64"), types.TBOOL}, + ssa.OpNeq32F: sfRtCallDef{sysfunc("feq32"), types.TBOOL}, + ssa.OpLess64F: sfRtCallDef{sysfunc("fgt64"), types.TBOOL}, + ssa.OpLess32F: sfRtCallDef{sysfunc("fgt32"), types.TBOOL}, + ssa.OpLeq64F: sfRtCallDef{sysfunc("fge64"), types.TBOOL}, + ssa.OpLeq32F: sfRtCallDef{sysfunc("fge32"), types.TBOOL}, - ssa.OpCvt32to32F: sfRtCallDef{sysfunc("fint32to32"), TFLOAT32}, - ssa.OpCvt32Fto32: sfRtCallDef{sysfunc("f32toint32"), TINT32}, - ssa.OpCvt64to32F: sfRtCallDef{sysfunc("fint64to32"), TFLOAT32}, - ssa.OpCvt32Fto64: sfRtCallDef{sysfunc("f32toint64"), TINT64}, - ssa.OpCvt64Uto32F: sfRtCallDef{sysfunc("fuint64to32"), TFLOAT32}, - ssa.OpCvt32Fto64U: sfRtCallDef{sysfunc("f32touint64"), TUINT64}, - ssa.OpCvt32to64F: sfRtCallDef{sysfunc("fint32to64"), TFLOAT64}, - ssa.OpCvt64Fto32: sfRtCallDef{sysfunc("f64toint32"), TINT32}, - ssa.OpCvt64to64F: sfRtCallDef{sysfunc("fint64to64"), TFLOAT64}, - ssa.OpCvt64Fto64: sfRtCallDef{sysfunc("f64toint64"), TINT64}, - ssa.OpCvt64Uto64F: sfRtCallDef{sysfunc("fuint64to64"), TFLOAT64}, - ssa.OpCvt64Fto64U: sfRtCallDef{sysfunc("f64touint64"), TUINT64}, - ssa.OpCvt32Fto64F: sfRtCallDef{sysfunc("f32to64"), TFLOAT64}, - ssa.OpCvt64Fto32F: sfRtCallDef{sysfunc("f64to32"), TFLOAT32}, + ssa.OpCvt32to32F: sfRtCallDef{sysfunc("fint32to32"), types.TFLOAT32}, + ssa.OpCvt32Fto32: sfRtCallDef{sysfunc("f32toint32"), types.TINT32}, + ssa.OpCvt64to32F: sfRtCallDef{sysfunc("fint64to32"), types.TFLOAT32}, + ssa.OpCvt32Fto64: sfRtCallDef{sysfunc("f32toint64"), types.TINT64}, + ssa.OpCvt64Uto32F: sfRtCallDef{sysfunc("fuint64to32"), types.TFLOAT32}, + ssa.OpCvt32Fto64U: sfRtCallDef{sysfunc("f32touint64"), types.TUINT64}, + ssa.OpCvt32to64F: sfRtCallDef{sysfunc("fint32to64"), types.TFLOAT64}, + ssa.OpCvt64Fto32: sfRtCallDef{sysfunc("f64toint32"), types.TINT32}, + ssa.OpCvt64to64F: sfRtCallDef{sysfunc("fint64to64"), types.TFLOAT64}, + ssa.OpCvt64Fto64: sfRtCallDef{sysfunc("f64toint64"), types.TINT64}, + ssa.OpCvt64Uto64F: sfRtCallDef{sysfunc("fuint64to64"), types.TFLOAT64}, + ssa.OpCvt64Fto64U: sfRtCallDef{sysfunc("f64touint64"), types.TUINT64}, + ssa.OpCvt32Fto64F: sfRtCallDef{sysfunc("f32to64"), types.TFLOAT64}, + ssa.OpCvt64Fto32F: sfRtCallDef{sysfunc("f64to32"), types.TFLOAT32}, } } @@ -3237,7 +3238,7 @@ func (s *state) sfcall(op ssa.Op, args ...*ssa.Value) (*ssa.Value, bool) { args[0], args[1] = args[1], args[0] case ssa.OpSub32F, ssa.OpSub64F: - args[1] = s.newValue1(s.ssaOp(ONEG, types.Types[callDef.rtype]), args[1].Type, args[1]) + args[1] = s.newValue1(s.ssaOp(ir.ONEG, types.Types[callDef.rtype]), args[1].Type, args[1]) } result := s.rtcall(callDef.rtfn, true, []*types.Type{types.Types[callDef.rtype]}, args...)[0] @@ -3253,7 +3254,7 @@ var intrinsics map[intrinsicKey]intrinsicBuilder // An intrinsicBuilder converts a call node n into an ssa value that // implements that call as an intrinsic. args is a list of arguments to the func. -type intrinsicBuilder func(s *state, n *Node, args []*ssa.Value) *ssa.Value +type intrinsicBuilder func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value type intrinsicKey struct { arch *sys.Arch @@ -3318,7 +3319,7 @@ func init() { /******** runtime ********/ if !instrumenting { add("runtime", "slicebytetostringtmp", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { // Compiler frontend optimizations emit OBYTES2STRTMP nodes // for the backend instead of slicebytetostringtmp calls // when not instrumenting. @@ -3327,98 +3328,98 @@ func init() { all...) } addF("runtime/internal/math", "MulUintptr", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { if s.config.PtrSize == 4 { - return s.newValue2(ssa.OpMul32uover, types.NewTuple(types.Types[TUINT], types.Types[TUINT]), args[0], args[1]) + return s.newValue2(ssa.OpMul32uover, types.NewTuple(types.Types[types.TUINT], types.Types[types.TUINT]), args[0], args[1]) } - return s.newValue2(ssa.OpMul64uover, types.NewTuple(types.Types[TUINT], types.Types[TUINT]), args[0], args[1]) + return s.newValue2(ssa.OpMul64uover, types.NewTuple(types.Types[types.TUINT], types.Types[types.TUINT]), args[0], args[1]) }, sys.AMD64, sys.I386, sys.MIPS64) add("runtime", "KeepAlive", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { data := s.newValue1(ssa.OpIData, s.f.Config.Types.BytePtr, args[0]) s.vars[memVar] = s.newValue2(ssa.OpKeepAlive, types.TypeMem, data, s.mem()) return nil }, all...) add("runtime", "getclosureptr", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { return s.newValue0(ssa.OpGetClosurePtr, s.f.Config.Types.Uintptr) }, all...) add("runtime", "getcallerpc", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { return s.newValue0(ssa.OpGetCallerPC, s.f.Config.Types.Uintptr) }, all...) add("runtime", "getcallersp", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { return s.newValue0(ssa.OpGetCallerSP, s.f.Config.Types.Uintptr) }, all...) /******** runtime/internal/sys ********/ addF("runtime/internal/sys", "Ctz32", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpCtz32, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpCtz32, types.Types[types.TINT], args[0]) }, sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64) addF("runtime/internal/sys", "Ctz64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpCtz64, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpCtz64, types.Types[types.TINT], args[0]) }, sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64) addF("runtime/internal/sys", "Bswap32", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBswap32, types.Types[TUINT32], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBswap32, types.Types[types.TUINT32], args[0]) }, sys.AMD64, sys.ARM64, sys.ARM, sys.S390X) addF("runtime/internal/sys", "Bswap64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBswap64, types.Types[TUINT64], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBswap64, types.Types[types.TUINT64], args[0]) }, sys.AMD64, sys.ARM64, sys.ARM, sys.S390X) /******** runtime/internal/atomic ********/ addF("runtime/internal/atomic", "Load", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.newValue2(ssa.OpAtomicLoad32, types.NewTuple(types.Types[TUINT32], types.TypeMem), args[0], s.mem()) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.newValue2(ssa.OpAtomicLoad32, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) - return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v) + return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT32], v) }, sys.AMD64, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Load8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.newValue2(ssa.OpAtomicLoad8, types.NewTuple(types.Types[TUINT8], types.TypeMem), args[0], s.mem()) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.newValue2(ssa.OpAtomicLoad8, types.NewTuple(types.Types[types.TUINT8], types.TypeMem), args[0], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) - return s.newValue1(ssa.OpSelect0, types.Types[TUINT8], v) + return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT8], v) }, sys.AMD64, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Load64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.newValue2(ssa.OpAtomicLoad64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], s.mem()) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.newValue2(ssa.OpAtomicLoad64, types.NewTuple(types.Types[types.TUINT64], types.TypeMem), args[0], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) - return s.newValue1(ssa.OpSelect0, types.Types[TUINT64], v) + return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT64], v) }, sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "LoadAcq", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.newValue2(ssa.OpAtomicLoadAcq32, types.NewTuple(types.Types[TUINT32], types.TypeMem), args[0], s.mem()) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.newValue2(ssa.OpAtomicLoadAcq32, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) - return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v) + return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT32], v) }, sys.PPC64, sys.S390X) addF("runtime/internal/atomic", "LoadAcq64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.newValue2(ssa.OpAtomicLoadAcq64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], s.mem()) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.newValue2(ssa.OpAtomicLoadAcq64, types.NewTuple(types.Types[types.TUINT64], types.TypeMem), args[0], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) - return s.newValue1(ssa.OpSelect0, types.Types[TUINT64], v) + return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT64], v) }, sys.PPC64) addF("runtime/internal/atomic", "Loadp", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { v := s.newValue2(ssa.OpAtomicLoadPtr, types.NewTuple(s.f.Config.Types.BytePtr, types.TypeMem), args[0], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) return s.newValue1(ssa.OpSelect0, s.f.Config.Types.BytePtr, v) @@ -3426,65 +3427,65 @@ func init() { sys.AMD64, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Store", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicStore32, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.AMD64, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Store8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicStore8, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.AMD64, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Store64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicStore64, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "StorepNoWB", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicStorePtrNoWB, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.AMD64, sys.ARM64, sys.MIPS, sys.MIPS64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "StoreRel", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicStoreRel32, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.PPC64, sys.S390X) addF("runtime/internal/atomic", "StoreRel64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicStoreRel64, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.PPC64) addF("runtime/internal/atomic", "Xchg", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.newValue3(ssa.OpAtomicExchange32, types.NewTuple(types.Types[TUINT32], types.TypeMem), args[0], args[1], s.mem()) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.newValue3(ssa.OpAtomicExchange32, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], args[1], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) - return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v) + return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT32], v) }, sys.AMD64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Xchg64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.newValue3(ssa.OpAtomicExchange64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], args[1], s.mem()) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.newValue3(ssa.OpAtomicExchange64, types.NewTuple(types.Types[types.TUINT64], types.TypeMem), args[0], args[1], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) - return s.newValue1(ssa.OpSelect0, types.Types[TUINT64], v) + return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT64], v) }, sys.AMD64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) - type atomicOpEmitter func(s *state, n *Node, args []*ssa.Value, op ssa.Op, typ types.EType) + type atomicOpEmitter func(s *state, n *ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) makeAtomicGuardedIntrinsicARM64 := func(op0, op1 ssa.Op, typ, rtyp types.EType, emit atomicOpEmitter) intrinsicBuilder { - return func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + return func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { // Target Atomic feature is identified by dynamic detection - addr := s.entryNewValue1A(ssa.OpAddr, types.Types[TBOOL].PtrTo(), arm64HasATOMICS, s.sb) - v := s.load(types.Types[TBOOL], addr) + addr := s.entryNewValue1A(ssa.OpAddr, types.Types[types.TBOOL].PtrTo(), arm64HasATOMICS, s.sb) + v := s.load(types.Types[types.TBOOL], addr) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(v) @@ -3507,7 +3508,7 @@ func init() { // Merge results. s.startBlock(bEnd) - if rtyp == TNIL { + if rtyp == types.TNIL { return nil } else { return s.variable(n, types.Types[rtyp]) @@ -3515,115 +3516,115 @@ func init() { } } - atomicXchgXaddEmitterARM64 := func(s *state, n *Node, args []*ssa.Value, op ssa.Op, typ types.EType) { + atomicXchgXaddEmitterARM64 := func(s *state, n *ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) { v := s.newValue3(op, types.NewTuple(types.Types[typ], types.TypeMem), args[0], args[1], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v) } addF("runtime/internal/atomic", "Xchg", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicExchange32, ssa.OpAtomicExchange32Variant, TUINT32, TUINT32, atomicXchgXaddEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicExchange32, ssa.OpAtomicExchange32Variant, types.TUINT32, types.TUINT32, atomicXchgXaddEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "Xchg64", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicExchange64, ssa.OpAtomicExchange64Variant, TUINT64, TUINT64, atomicXchgXaddEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicExchange64, ssa.OpAtomicExchange64Variant, types.TUINT64, types.TUINT64, atomicXchgXaddEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "Xadd", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.newValue3(ssa.OpAtomicAdd32, types.NewTuple(types.Types[TUINT32], types.TypeMem), args[0], args[1], s.mem()) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.newValue3(ssa.OpAtomicAdd32, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], args[1], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) - return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v) + return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT32], v) }, sys.AMD64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Xadd64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.newValue3(ssa.OpAtomicAdd64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], args[1], s.mem()) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.newValue3(ssa.OpAtomicAdd64, types.NewTuple(types.Types[types.TUINT64], types.TypeMem), args[0], args[1], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) - return s.newValue1(ssa.OpSelect0, types.Types[TUINT64], v) + return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT64], v) }, sys.AMD64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Xadd", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAdd32, ssa.OpAtomicAdd32Variant, TUINT32, TUINT32, atomicXchgXaddEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAdd32, ssa.OpAtomicAdd32Variant, types.TUINT32, types.TUINT32, atomicXchgXaddEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "Xadd64", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAdd64, ssa.OpAtomicAdd64Variant, TUINT64, TUINT64, atomicXchgXaddEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAdd64, ssa.OpAtomicAdd64Variant, types.TUINT64, types.TUINT64, atomicXchgXaddEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "Cas", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { v := s.newValue4(ssa.OpAtomicCompareAndSwap32, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) return s.newValue1(ssa.OpSelect0, types.Types[types.TBOOL], v) }, sys.AMD64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Cas64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { v := s.newValue4(ssa.OpAtomicCompareAndSwap64, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) return s.newValue1(ssa.OpSelect0, types.Types[types.TBOOL], v) }, sys.AMD64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "CasRel", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { v := s.newValue4(ssa.OpAtomicCompareAndSwap32, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) return s.newValue1(ssa.OpSelect0, types.Types[types.TBOOL], v) }, sys.PPC64) - atomicCasEmitterARM64 := func(s *state, n *Node, args []*ssa.Value, op ssa.Op, typ types.EType) { + atomicCasEmitterARM64 := func(s *state, n *ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) { v := s.newValue4(op, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem()) s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v) } addF("runtime/internal/atomic", "Cas", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicCompareAndSwap32, ssa.OpAtomicCompareAndSwap32Variant, TUINT32, TBOOL, atomicCasEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicCompareAndSwap32, ssa.OpAtomicCompareAndSwap32Variant, types.TUINT32, types.TBOOL, atomicCasEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "Cas64", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicCompareAndSwap64, ssa.OpAtomicCompareAndSwap64Variant, TUINT64, TBOOL, atomicCasEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicCompareAndSwap64, ssa.OpAtomicCompareAndSwap64Variant, types.TUINT64, types.TBOOL, atomicCasEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "And8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicAnd8, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.AMD64, sys.MIPS, sys.PPC64, sys.S390X) addF("runtime/internal/atomic", "And", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicAnd32, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.AMD64, sys.MIPS, sys.PPC64, sys.S390X) addF("runtime/internal/atomic", "Or8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicOr8, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.AMD64, sys.ARM64, sys.MIPS, sys.PPC64, sys.S390X) addF("runtime/internal/atomic", "Or", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue3(ssa.OpAtomicOr32, types.TypeMem, args[0], args[1], s.mem()) return nil }, sys.AMD64, sys.MIPS, sys.PPC64, sys.S390X) - atomicAndOrEmitterARM64 := func(s *state, n *Node, args []*ssa.Value, op ssa.Op, typ types.EType) { + atomicAndOrEmitterARM64 := func(s *state, n *ir.Node, args []*ssa.Value, op ssa.Op, typ types.EType) { s.vars[memVar] = s.newValue3(op, types.TypeMem, args[0], args[1], s.mem()) } addF("runtime/internal/atomic", "And8", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd8, ssa.OpAtomicAnd8Variant, TNIL, TNIL, atomicAndOrEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd8, ssa.OpAtomicAnd8Variant, types.TNIL, types.TNIL, atomicAndOrEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "And", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd32, ssa.OpAtomicAnd32Variant, TNIL, TNIL, atomicAndOrEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd32, ssa.OpAtomicAnd32Variant, types.TNIL, types.TNIL, atomicAndOrEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "Or8", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr8, ssa.OpAtomicOr8Variant, TNIL, TNIL, atomicAndOrEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr8, ssa.OpAtomicOr8Variant, types.TNIL, types.TNIL, atomicAndOrEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "Or", - makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr32, ssa.OpAtomicOr32Variant, TNIL, TNIL, atomicAndOrEmitterARM64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr32, ssa.OpAtomicOr32Variant, types.TNIL, types.TNIL, atomicAndOrEmitterARM64), sys.ARM64) alias("runtime/internal/atomic", "Loadint64", "runtime/internal/atomic", "Load64", all...) @@ -3658,57 +3659,57 @@ func init() { /******** math ********/ addF("math", "Sqrt", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpSqrt, types.Types[TFLOAT64], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpSqrt, types.Types[types.TFLOAT64], args[0]) }, sys.I386, sys.AMD64, sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X, sys.Wasm) addF("math", "Trunc", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpTrunc, types.Types[TFLOAT64], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpTrunc, types.Types[types.TFLOAT64], args[0]) }, sys.ARM64, sys.PPC64, sys.S390X, sys.Wasm) addF("math", "Ceil", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpCeil, types.Types[TFLOAT64], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpCeil, types.Types[types.TFLOAT64], args[0]) }, sys.ARM64, sys.PPC64, sys.S390X, sys.Wasm) addF("math", "Floor", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpFloor, types.Types[TFLOAT64], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpFloor, types.Types[types.TFLOAT64], args[0]) }, sys.ARM64, sys.PPC64, sys.S390X, sys.Wasm) addF("math", "Round", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpRound, types.Types[TFLOAT64], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpRound, types.Types[types.TFLOAT64], args[0]) }, sys.ARM64, sys.PPC64, sys.S390X) addF("math", "RoundToEven", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpRoundToEven, types.Types[TFLOAT64], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpRoundToEven, types.Types[types.TFLOAT64], args[0]) }, sys.ARM64, sys.S390X, sys.Wasm) addF("math", "Abs", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpAbs, types.Types[TFLOAT64], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpAbs, types.Types[types.TFLOAT64], args[0]) }, sys.ARM64, sys.ARM, sys.PPC64, sys.Wasm) addF("math", "Copysign", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue2(ssa.OpCopysign, types.Types[TFLOAT64], args[0], args[1]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue2(ssa.OpCopysign, types.Types[types.TFLOAT64], args[0], args[1]) }, sys.PPC64, sys.Wasm) addF("math", "FMA", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue3(ssa.OpFMA, types.Types[TFLOAT64], args[0], args[1], args[2]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2]) }, sys.ARM64, sys.PPC64, sys.S390X) addF("math", "FMA", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { if !s.config.UseFMA { s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64] - return s.variable(n, types.Types[TFLOAT64]) + return s.variable(n, types.Types[types.TFLOAT64]) } - v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[TBOOL], x86HasFMA) + v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], x86HasFMA) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(v) @@ -3721,7 +3722,7 @@ func init() { // We have the intrinsic - use it directly. s.startBlock(bTrue) - s.vars[n] = s.newValue3(ssa.OpFMA, types.Types[TFLOAT64], args[0], args[1], args[2]) + s.vars[n] = s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2]) s.endBlock().AddEdgeTo(bEnd) // Call the pure Go version. @@ -3731,17 +3732,17 @@ func init() { // Merge results. s.startBlock(bEnd) - return s.variable(n, types.Types[TFLOAT64]) + return s.variable(n, types.Types[types.TFLOAT64]) }, sys.AMD64) addF("math", "FMA", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { if !s.config.UseFMA { s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64] - return s.variable(n, types.Types[TFLOAT64]) + return s.variable(n, types.Types[types.TFLOAT64]) } - addr := s.entryNewValue1A(ssa.OpAddr, types.Types[TBOOL].PtrTo(), armHasVFPv4, s.sb) - v := s.load(types.Types[TBOOL], addr) + addr := s.entryNewValue1A(ssa.OpAddr, types.Types[types.TBOOL].PtrTo(), armHasVFPv4, s.sb) + v := s.load(types.Types[types.TBOOL], addr) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(v) @@ -3754,7 +3755,7 @@ func init() { // We have the intrinsic - use it directly. s.startBlock(bTrue) - s.vars[n] = s.newValue3(ssa.OpFMA, types.Types[TFLOAT64], args[0], args[1], args[2]) + s.vars[n] = s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2]) s.endBlock().AddEdgeTo(bEnd) // Call the pure Go version. @@ -3764,13 +3765,13 @@ func init() { // Merge results. s.startBlock(bEnd) - return s.variable(n, types.Types[TFLOAT64]) + return s.variable(n, types.Types[types.TFLOAT64]) }, sys.ARM) - makeRoundAMD64 := func(op ssa.Op) func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[TBOOL], x86HasSSE41) + makeRoundAMD64 := func(op ssa.Op) func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], x86HasSSE41) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(v) @@ -3783,7 +3784,7 @@ func init() { // We have the intrinsic - use it directly. s.startBlock(bTrue) - s.vars[n] = s.newValue1(op, types.Types[TFLOAT64], args[0]) + s.vars[n] = s.newValue1(op, types.Types[types.TFLOAT64], args[0]) s.endBlock().AddEdgeTo(bEnd) // Call the pure Go version. @@ -3793,7 +3794,7 @@ func init() { // Merge results. s.startBlock(bEnd) - return s.variable(n, types.Types[TFLOAT64]) + return s.variable(n, types.Types[types.TFLOAT64]) } } addF("math", "RoundToEven", @@ -3811,55 +3812,55 @@ func init() { /******** math/bits ********/ addF("math/bits", "TrailingZeros64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpCtz64, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpCtz64, types.Types[types.TINT], args[0]) }, sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm) addF("math/bits", "TrailingZeros32", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpCtz32, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpCtz32, types.Types[types.TINT], args[0]) }, sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm) addF("math/bits", "TrailingZeros16", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - x := s.newValue1(ssa.OpZeroExt16to32, types.Types[TUINT32], args[0]) - c := s.constInt32(types.Types[TUINT32], 1<<16) - y := s.newValue2(ssa.OpOr32, types.Types[TUINT32], x, c) - return s.newValue1(ssa.OpCtz32, types.Types[TINT], y) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + x := s.newValue1(ssa.OpZeroExt16to32, types.Types[types.TUINT32], args[0]) + c := s.constInt32(types.Types[types.TUINT32], 1<<16) + y := s.newValue2(ssa.OpOr32, types.Types[types.TUINT32], x, c) + return s.newValue1(ssa.OpCtz32, types.Types[types.TINT], y) }, sys.MIPS) addF("math/bits", "TrailingZeros16", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpCtz16, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpCtz16, types.Types[types.TINT], args[0]) }, sys.AMD64, sys.I386, sys.ARM, sys.ARM64, sys.Wasm) addF("math/bits", "TrailingZeros16", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - x := s.newValue1(ssa.OpZeroExt16to64, types.Types[TUINT64], args[0]) - c := s.constInt64(types.Types[TUINT64], 1<<16) - y := s.newValue2(ssa.OpOr64, types.Types[TUINT64], x, c) - return s.newValue1(ssa.OpCtz64, types.Types[TINT], y) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + x := s.newValue1(ssa.OpZeroExt16to64, types.Types[types.TUINT64], args[0]) + c := s.constInt64(types.Types[types.TUINT64], 1<<16) + y := s.newValue2(ssa.OpOr64, types.Types[types.TUINT64], x, c) + return s.newValue1(ssa.OpCtz64, types.Types[types.TINT], y) }, sys.S390X, sys.PPC64) addF("math/bits", "TrailingZeros8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - x := s.newValue1(ssa.OpZeroExt8to32, types.Types[TUINT32], args[0]) - c := s.constInt32(types.Types[TUINT32], 1<<8) - y := s.newValue2(ssa.OpOr32, types.Types[TUINT32], x, c) - return s.newValue1(ssa.OpCtz32, types.Types[TINT], y) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + x := s.newValue1(ssa.OpZeroExt8to32, types.Types[types.TUINT32], args[0]) + c := s.constInt32(types.Types[types.TUINT32], 1<<8) + y := s.newValue2(ssa.OpOr32, types.Types[types.TUINT32], x, c) + return s.newValue1(ssa.OpCtz32, types.Types[types.TINT], y) }, sys.MIPS) addF("math/bits", "TrailingZeros8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpCtz8, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpCtz8, types.Types[types.TINT], args[0]) }, sys.AMD64, sys.ARM, sys.ARM64, sys.Wasm) addF("math/bits", "TrailingZeros8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - x := s.newValue1(ssa.OpZeroExt8to64, types.Types[TUINT64], args[0]) - c := s.constInt64(types.Types[TUINT64], 1<<8) - y := s.newValue2(ssa.OpOr64, types.Types[TUINT64], x, c) - return s.newValue1(ssa.OpCtz64, types.Types[TINT], y) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + x := s.newValue1(ssa.OpZeroExt8to64, types.Types[types.TUINT64], args[0]) + c := s.constInt64(types.Types[types.TUINT64], 1<<8) + y := s.newValue2(ssa.OpOr64, types.Types[types.TUINT64], x, c) + return s.newValue1(ssa.OpCtz64, types.Types[types.TINT], y) }, sys.S390X) alias("math/bits", "ReverseBytes64", "runtime/internal/sys", "Bswap64", all...) @@ -3867,116 +3868,116 @@ func init() { // ReverseBytes inlines correctly, no need to intrinsify it. // ReverseBytes16 lowers to a rotate, no need for anything special here. addF("math/bits", "Len64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBitLen64, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], args[0]) }, sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm) addF("math/bits", "Len32", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBitLen32, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], args[0]) }, sys.AMD64, sys.ARM64) addF("math/bits", "Len32", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { if s.config.PtrSize == 4 { - return s.newValue1(ssa.OpBitLen32, types.Types[TINT], args[0]) + return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], args[0]) } - x := s.newValue1(ssa.OpZeroExt32to64, types.Types[TUINT64], args[0]) - return s.newValue1(ssa.OpBitLen64, types.Types[TINT], x) + x := s.newValue1(ssa.OpZeroExt32to64, types.Types[types.TUINT64], args[0]) + return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], x) }, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm) addF("math/bits", "Len16", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { if s.config.PtrSize == 4 { - x := s.newValue1(ssa.OpZeroExt16to32, types.Types[TUINT32], args[0]) - return s.newValue1(ssa.OpBitLen32, types.Types[TINT], x) + x := s.newValue1(ssa.OpZeroExt16to32, types.Types[types.TUINT32], args[0]) + return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], x) } - x := s.newValue1(ssa.OpZeroExt16to64, types.Types[TUINT64], args[0]) - return s.newValue1(ssa.OpBitLen64, types.Types[TINT], x) + x := s.newValue1(ssa.OpZeroExt16to64, types.Types[types.TUINT64], args[0]) + return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], x) }, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm) addF("math/bits", "Len16", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBitLen16, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBitLen16, types.Types[types.TINT], args[0]) }, sys.AMD64) addF("math/bits", "Len8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { if s.config.PtrSize == 4 { - x := s.newValue1(ssa.OpZeroExt8to32, types.Types[TUINT32], args[0]) - return s.newValue1(ssa.OpBitLen32, types.Types[TINT], x) + x := s.newValue1(ssa.OpZeroExt8to32, types.Types[types.TUINT32], args[0]) + return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], x) } - x := s.newValue1(ssa.OpZeroExt8to64, types.Types[TUINT64], args[0]) - return s.newValue1(ssa.OpBitLen64, types.Types[TINT], x) + x := s.newValue1(ssa.OpZeroExt8to64, types.Types[types.TUINT64], args[0]) + return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], x) }, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm) addF("math/bits", "Len8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBitLen8, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBitLen8, types.Types[types.TINT], args[0]) }, sys.AMD64) addF("math/bits", "Len", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { if s.config.PtrSize == 4 { - return s.newValue1(ssa.OpBitLen32, types.Types[TINT], args[0]) + return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], args[0]) } - return s.newValue1(ssa.OpBitLen64, types.Types[TINT], args[0]) + return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], args[0]) }, sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm) // LeadingZeros is handled because it trivially calls Len. addF("math/bits", "Reverse64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBitRev64, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBitRev64, types.Types[types.TINT], args[0]) }, sys.ARM64) addF("math/bits", "Reverse32", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBitRev32, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBitRev32, types.Types[types.TINT], args[0]) }, sys.ARM64) addF("math/bits", "Reverse16", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBitRev16, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBitRev16, types.Types[types.TINT], args[0]) }, sys.ARM64) addF("math/bits", "Reverse8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpBitRev8, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpBitRev8, types.Types[types.TINT], args[0]) }, sys.ARM64) addF("math/bits", "Reverse", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { if s.config.PtrSize == 4 { - return s.newValue1(ssa.OpBitRev32, types.Types[TINT], args[0]) + return s.newValue1(ssa.OpBitRev32, types.Types[types.TINT], args[0]) } - return s.newValue1(ssa.OpBitRev64, types.Types[TINT], args[0]) + return s.newValue1(ssa.OpBitRev64, types.Types[types.TINT], args[0]) }, sys.ARM64) addF("math/bits", "RotateLeft8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue2(ssa.OpRotateLeft8, types.Types[TUINT8], args[0], args[1]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue2(ssa.OpRotateLeft8, types.Types[types.TUINT8], args[0], args[1]) }, sys.AMD64) addF("math/bits", "RotateLeft16", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue2(ssa.OpRotateLeft16, types.Types[TUINT16], args[0], args[1]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue2(ssa.OpRotateLeft16, types.Types[types.TUINT16], args[0], args[1]) }, sys.AMD64) addF("math/bits", "RotateLeft32", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue2(ssa.OpRotateLeft32, types.Types[TUINT32], args[0], args[1]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue2(ssa.OpRotateLeft32, types.Types[types.TUINT32], args[0], args[1]) }, sys.AMD64, sys.ARM, sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm) addF("math/bits", "RotateLeft64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue2(ssa.OpRotateLeft64, types.Types[TUINT64], args[0], args[1]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue2(ssa.OpRotateLeft64, types.Types[types.TUINT64], args[0], args[1]) }, sys.AMD64, sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm) alias("math/bits", "RotateLeft", "math/bits", "RotateLeft64", p8...) - makeOnesCountAMD64 := func(op64 ssa.Op, op32 ssa.Op) func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[TBOOL], x86HasPOPCNT) + makeOnesCountAMD64 := func(op64 ssa.Op, op32 ssa.Op) func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], x86HasPOPCNT) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(v) @@ -3993,7 +3994,7 @@ func init() { if s.config.PtrSize == 4 { op = op32 } - s.vars[n] = s.newValue1(op, types.Types[TINT], args[0]) + s.vars[n] = s.newValue1(op, types.Types[types.TINT], args[0]) s.endBlock().AddEdgeTo(bEnd) // Call the pure Go version. @@ -4003,67 +4004,67 @@ func init() { // Merge results. s.startBlock(bEnd) - return s.variable(n, types.Types[TINT]) + return s.variable(n, types.Types[types.TINT]) } } addF("math/bits", "OnesCount64", makeOnesCountAMD64(ssa.OpPopCount64, ssa.OpPopCount64), sys.AMD64) addF("math/bits", "OnesCount64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpPopCount64, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpPopCount64, types.Types[types.TINT], args[0]) }, sys.PPC64, sys.ARM64, sys.S390X, sys.Wasm) addF("math/bits", "OnesCount32", makeOnesCountAMD64(ssa.OpPopCount32, ssa.OpPopCount32), sys.AMD64) addF("math/bits", "OnesCount32", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpPopCount32, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpPopCount32, types.Types[types.TINT], args[0]) }, sys.PPC64, sys.ARM64, sys.S390X, sys.Wasm) addF("math/bits", "OnesCount16", makeOnesCountAMD64(ssa.OpPopCount16, ssa.OpPopCount16), sys.AMD64) addF("math/bits", "OnesCount16", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpPopCount16, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpPopCount16, types.Types[types.TINT], args[0]) }, sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm) addF("math/bits", "OnesCount8", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue1(ssa.OpPopCount8, types.Types[TINT], args[0]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue1(ssa.OpPopCount8, types.Types[types.TINT], args[0]) }, sys.S390X, sys.PPC64, sys.Wasm) addF("math/bits", "OnesCount", makeOnesCountAMD64(ssa.OpPopCount64, ssa.OpPopCount32), sys.AMD64) addF("math/bits", "Mul64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue2(ssa.OpMul64uhilo, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue2(ssa.OpMul64uhilo, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1]) }, sys.AMD64, sys.ARM64, sys.PPC64, sys.S390X, sys.MIPS64) alias("math/bits", "Mul", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64, sys.ArchS390X, sys.ArchMIPS64, sys.ArchMIPS64LE) addF("math/bits", "Add64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue3(ssa.OpAdd64carry, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1], args[2]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue3(ssa.OpAdd64carry, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1], args[2]) }, sys.AMD64, sys.ARM64, sys.PPC64, sys.S390X) alias("math/bits", "Add", "math/bits", "Add64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64, sys.ArchS390X) addF("math/bits", "Sub64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue3(ssa.OpSub64borrow, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1], args[2]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue3(ssa.OpSub64borrow, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1], args[2]) }, sys.AMD64, sys.ARM64, sys.S390X) alias("math/bits", "Sub", "math/bits", "Sub64", sys.ArchAMD64, sys.ArchARM64, sys.ArchS390X) addF("math/bits", "Div64", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { // check for divide-by-zero/overflow and panic with appropriate message - cmpZero := s.newValue2(s.ssaOp(ONE, types.Types[TUINT64]), types.Types[TBOOL], args[2], s.zeroVal(types.Types[TUINT64])) + cmpZero := s.newValue2(s.ssaOp(ir.ONE, types.Types[types.TUINT64]), types.Types[types.TBOOL], args[2], s.zeroVal(types.Types[types.TUINT64])) s.check(cmpZero, panicdivide) - cmpOverflow := s.newValue2(s.ssaOp(OLT, types.Types[TUINT64]), types.Types[TBOOL], args[0], args[2]) + cmpOverflow := s.newValue2(s.ssaOp(ir.OLT, types.Types[types.TUINT64]), types.Types[types.TBOOL], args[0], args[2]) s.check(cmpOverflow, panicoverflow) - return s.newValue3(ssa.OpDiv128u, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1], args[2]) + return s.newValue3(ssa.OpDiv128u, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1], args[2]) }, sys.AMD64) alias("math/bits", "Div", "math/bits", "Div64", sys.ArchAMD64) @@ -4117,8 +4118,8 @@ func init() { /******** math/big ********/ add("math/big", "mulWW", - func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return s.newValue2(ssa.OpMul64uhilo, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1]) + func(s *state, n *ir.Node, args []*ssa.Value) *ssa.Value { + return s.newValue2(ssa.OpMul64uhilo, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1]) }, sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64LE, sys.ArchPPC64, sys.ArchS390X) } @@ -4130,7 +4131,7 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder { return nil } pkg := sym.Pkg.Path - if sym.Pkg == localpkg { + if sym.Pkg == ir.LocalPkg { pkg = base.Ctxt.Pkgpath } if base.Flag.Race && pkg == "sync/atomic" { @@ -4155,7 +4156,7 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder { return intrinsics[intrinsicKey{thearch.LinkArch.Arch, pkg, fn}] } -func isIntrinsicCall(n *Node) bool { +func isIntrinsicCall(n *ir.Node) bool { if n == nil || n.Left == nil { return false } @@ -4163,7 +4164,7 @@ func isIntrinsicCall(n *Node) bool { } // intrinsicCall converts a call to a recognized intrinsic function into the intrinsic SSA operation. -func (s *state) intrinsicCall(n *Node) *ssa.Value { +func (s *state) intrinsicCall(n *ir.Node) *ssa.Value { v := findIntrinsic(n.Left.Sym)(s, n, s.intrinsicArgs(n)) if ssa.IntrinsicsDebug > 0 { x := v @@ -4179,15 +4180,15 @@ func (s *state) intrinsicCall(n *Node) *ssa.Value { } // intrinsicArgs extracts args from n, evaluates them to SSA values, and returns them. -func (s *state) intrinsicArgs(n *Node) []*ssa.Value { +func (s *state) intrinsicArgs(n *ir.Node) []*ssa.Value { // Construct map of temps; see comments in s.call about the structure of n. - temps := map[*Node]*ssa.Value{} + temps := map[*ir.Node]*ssa.Value{} for _, a := range n.List.Slice() { - if a.Op != OAS { + if a.Op != ir.OAS { s.Fatalf("non-assignment as a temp function argument %v", a.Op) } l, r := a.Left, a.Right - if l.Op != ONAME { + if l.Op != ir.ONAME { s.Fatalf("non-ONAME temp function argument %v", a.Op) } // Evaluate and store to "temporary". @@ -4214,7 +4215,7 @@ func (s *state) intrinsicArgs(n *Node) []*ssa.Value { // call. We will also record funcdata information on where the args are stored // (as well as the deferBits variable), and this will enable us to run the proper // defer calls during panics. -func (s *state) openDeferRecord(n *Node) { +func (s *state) openDeferRecord(n *ir.Node) { // Do any needed expression evaluation for the args (including the // receiver, if any). This may be evaluating something like 'autotmp_3 = // once.mutex'. Such a statement will create a mapping in s.vars[] from @@ -4223,24 +4224,24 @@ func (s *state) openDeferRecord(n *Node) { s.stmtList(n.List) var args []*ssa.Value - var argNodes []*Node + var argNodes []*ir.Node opendefer := &openDeferInfo{ n: n, } fn := n.Left - if n.Op == OCALLFUNC { + if n.Op == ir.OCALLFUNC { // 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 function directly if it is a static function. closureVal := s.expr(fn) closure := s.openDeferSave(nil, fn.Type, closureVal) - opendefer.closureNode = closure.Aux.(*Node) - if !(fn.Op == ONAME && fn.Class() == PFUNC) { + opendefer.closureNode = closure.Aux.(*ir.Node) + if !(fn.Op == ir.ONAME && fn.Class() == ir.PFUNC) { opendefer.closure = closure } - } else if n.Op == OCALLMETH { - if fn.Op != ODOTMETH { + } else if n.Op == ir.OCALLMETH { + if fn.Op != ir.ODOTMETH { base.Fatalf("OCALLMETH: n.Left not an ODOTMETH: %v", fn) } closureVal := s.getMethodClosure(fn) @@ -4248,9 +4249,9 @@ func (s *state) openDeferRecord(n *Node) { // 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.(*Node) + opendefer.closureNode = closure.Aux.(*ir.Node) } else { - if fn.Op != ODOTINTER { + if fn.Op != ir.ODOTINTER { base.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op) } closure, rcvr := s.getClosureAndRcvr(fn) @@ -4258,8 +4259,8 @@ func (s *state) openDeferRecord(n *Node) { // Important to get the receiver type correct, so it is recognized // as a pointer for GC purposes. opendefer.rcvr = s.openDeferSave(nil, fn.Type.Recv().Type, rcvr) - opendefer.closureNode = opendefer.closure.Aux.(*Node) - opendefer.rcvrNode = opendefer.rcvr.Aux.(*Node) + opendefer.closureNode = opendefer.closure.Aux.(*ir.Node) + opendefer.rcvrNode = opendefer.rcvr.Aux.(*ir.Node) } for _, argn := range n.Rlist.Slice() { var v *ssa.Value @@ -4269,7 +4270,7 @@ func (s *state) openDeferRecord(n *Node) { v = s.openDeferSave(argn, argn.Type, nil) } args = append(args, v) - argNodes = append(argNodes, v.Aux.(*Node)) + argNodes = append(argNodes, v.Aux.(*ir.Node)) } opendefer.argVals = args opendefer.argNodes = argNodes @@ -4278,10 +4279,10 @@ func (s *state) openDeferRecord(n *Node) { // Update deferBits only after evaluation and storage to stack of // args/receiver/interface is successful. - bitvalue := s.constInt8(types.Types[TUINT8], 1<= 0; i-- { @@ -4357,12 +4358,12 @@ func (s *state) openDeferExit() { bCond := s.f.NewBlock(ssa.BlockPlain) bEnd := s.f.NewBlock(ssa.BlockPlain) - deferBits := s.variable(deferBitsVar, types.Types[TUINT8]) + deferBits := s.variable(deferBitsVar, types.Types[types.TUINT8]) // Generate code to check if the bit associated with the current // defer is set. - bitval := s.constInt8(types.Types[TUINT8], 1< ssa.MaxStruct { return false } @@ -5011,7 +5012,7 @@ func canSSAType(t *types.Type) bool { } // exprPtr evaluates n to a pointer and nil-checks it. -func (s *state) exprPtr(n *Node, bounded bool, lineno src.XPos) *ssa.Value { +func (s *state) exprPtr(n *ir.Node, bounded bool, lineno src.XPos) *ssa.Value { p := s.expr(n) if bounded || n.NonNil() { if s.f.Frontend().Debug_checknil() && lineno.Line() > 1 { @@ -5092,9 +5093,9 @@ func (s *state) boundsCheck(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bo var cmp *ssa.Value if kind == ssa.BoundsIndex || kind == ssa.BoundsIndexU { - cmp = s.newValue2(ssa.OpIsInBounds, types.Types[TBOOL], idx, len) + cmp = s.newValue2(ssa.OpIsInBounds, types.Types[types.TBOOL], idx, len) } else { - cmp = s.newValue2(ssa.OpIsSliceInBounds, types.Types[TBOOL], idx, len) + cmp = s.newValue2(ssa.OpIsSliceInBounds, types.Types[types.TBOOL], idx, len) } b := s.endBlock() b.Kind = ssa.BlockIf @@ -5120,7 +5121,7 @@ func (s *state) boundsCheck(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bo if kind != ssa.BoundsIndex && kind != ssa.BoundsIndexU { op = ssa.OpSpectreSliceIndex } - idx = s.newValue2(op, types.Types[TINT], idx, len) + idx = s.newValue2(op, types.Types[types.TINT], idx, len) } return idx @@ -5150,7 +5151,7 @@ func (s *state) check(cmp *ssa.Value, fn *obj.LSym) { s.startBlock(bNext) } -func (s *state) intDivide(n *Node, a, b *ssa.Value) *ssa.Value { +func (s *state) intDivide(n *ir.Node, a, b *ssa.Value) *ssa.Value { needcheck := true switch b.Op { case ssa.OpConst8, ssa.OpConst16, ssa.OpConst32, ssa.OpConst64: @@ -5160,7 +5161,7 @@ func (s *state) intDivide(n *Node, a, b *ssa.Value) *ssa.Value { } if needcheck { // do a size-appropriate check for zero - cmp := s.newValue2(s.ssaOp(ONE, n.Type), types.Types[TBOOL], b, s.zeroVal(n.Type)) + cmp := s.newValue2(s.ssaOp(ir.ONE, n.Type), types.Types[types.TBOOL], b, s.zeroVal(n.Type)) s.check(cmp, panicdivide) } return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) @@ -5291,24 +5292,24 @@ func (s *state) storeTypeScalars(t *types.Type, left, right *ssa.Value, skip ski if skip&skipLen != 0 { return } - len := s.newValue1(ssa.OpStringLen, types.Types[TINT], right) + len := s.newValue1(ssa.OpStringLen, types.Types[types.TINT], right) lenAddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, s.config.PtrSize, left) - s.store(types.Types[TINT], lenAddr, len) + s.store(types.Types[types.TINT], lenAddr, len) case t.IsSlice(): if skip&skipLen == 0 { - len := s.newValue1(ssa.OpSliceLen, types.Types[TINT], right) + len := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], right) lenAddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, s.config.PtrSize, left) - s.store(types.Types[TINT], lenAddr, len) + s.store(types.Types[types.TINT], lenAddr, len) } if skip&skipCap == 0 { - cap := s.newValue1(ssa.OpSliceCap, types.Types[TINT], right) + cap := s.newValue1(ssa.OpSliceCap, types.Types[types.TINT], right) capAddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, 2*s.config.PtrSize, left) - s.store(types.Types[TINT], capAddr, cap) + s.store(types.Types[types.TINT], capAddr, cap) } case t.IsInterface(): // itab field doesn't need a write barrier (even though it is a pointer). itab := s.newValue1(ssa.OpITab, s.f.Config.Types.BytePtr, right) - s.store(types.Types[TUINTPTR], left, itab) + s.store(types.Types[types.TUINTPTR], left, itab) case t.IsStruct(): n := t.NumFields() for i := 0; i < n; i++ { @@ -5369,7 +5370,7 @@ func (s *state) storeTypePtrs(t *types.Type, left, right *ssa.Value) { // putArg evaluates n for the purpose of passing it as an argument to a function and returns the corresponding Param for the call. // If forLateExpandedCall is true, it returns the argument value to pass to the call operation. // If forLateExpandedCall is false, then the value is stored at the specified stack offset, and the returned value is nil. -func (s *state) putArg(n *Node, t *types.Type, off int64, forLateExpandedCall bool) (ssa.Param, *ssa.Value) { +func (s *state) putArg(n *ir.Node, t *types.Type, off int64, forLateExpandedCall bool) (ssa.Param, *ssa.Value) { var a *ssa.Value if forLateExpandedCall { if !canSSAType(t) { @@ -5383,7 +5384,7 @@ func (s *state) putArg(n *Node, t *types.Type, off int64, forLateExpandedCall bo return ssa.Param{Type: t, Offset: int32(off)}, a } -func (s *state) storeArgWithBase(n *Node, t *types.Type, base *ssa.Value, off int64) { +func (s *state) storeArgWithBase(n *ir.Node, t *types.Type, base *ssa.Value, off int64) { pt := types.NewPtr(t) var addr *ssa.Value if base == s.sp { @@ -5412,11 +5413,11 @@ func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) switch { case t.IsSlice(): ptr = s.newValue1(ssa.OpSlicePtr, types.NewPtr(t.Elem()), v) - len = s.newValue1(ssa.OpSliceLen, types.Types[TINT], v) - cap = s.newValue1(ssa.OpSliceCap, types.Types[TINT], v) + len = s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], v) + cap = s.newValue1(ssa.OpSliceCap, types.Types[types.TINT], v) case t.IsString(): - ptr = s.newValue1(ssa.OpStringPtr, types.NewPtr(types.Types[TUINT8]), v) - len = s.newValue1(ssa.OpStringLen, types.Types[TINT], v) + ptr = s.newValue1(ssa.OpStringPtr, types.NewPtr(types.Types[types.TUINT8]), v) + len = s.newValue1(ssa.OpStringLen, types.Types[types.TINT], v) cap = len case t.IsPtr(): if !t.Elem().IsArray() { @@ -5424,7 +5425,7 @@ func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) } s.nilCheck(v) ptr = s.newValue1(ssa.OpCopy, types.NewPtr(t.Elem().Elem()), v) - len = s.constInt(types.Types[TINT], t.Elem().NumElem()) + len = s.constInt(types.Types[types.TINT], t.Elem().NumElem()) cap = len default: s.Fatalf("bad type in slice %v\n", t) @@ -5432,7 +5433,7 @@ func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) // Set default values if i == nil { - i = s.constInt(types.Types[TINT], 0) + i = s.constInt(types.Types[types.TINT], 0) } if j == nil { j = len @@ -5470,18 +5471,18 @@ func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) } // Word-sized integer operations. - subOp := s.ssaOp(OSUB, types.Types[TINT]) - mulOp := s.ssaOp(OMUL, types.Types[TINT]) - andOp := s.ssaOp(OAND, types.Types[TINT]) + subOp := s.ssaOp(ir.OSUB, types.Types[types.TINT]) + mulOp := s.ssaOp(ir.OMUL, types.Types[types.TINT]) + andOp := s.ssaOp(ir.OAND, types.Types[types.TINT]) // Calculate the length (rlen) and capacity (rcap) of the new slice. // For strings the capacity of the result is unimportant. However, // we use rcap to test if we've generated a zero-length slice. // Use length of strings for that. - rlen := s.newValue2(subOp, types.Types[TINT], j, i) + rlen := s.newValue2(subOp, types.Types[types.TINT], j, i) rcap := rlen if j != k && !t.IsString() { - rcap = s.newValue2(subOp, types.Types[TINT], k, i) + rcap = s.newValue2(subOp, types.Types[types.TINT], k, i) } if (i.Op == ssa.OpConst64 || i.Op == ssa.OpConst32) && i.AuxInt == 0 { @@ -5503,15 +5504,15 @@ func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) // // Where mask(x) is 0 if x==0 and -1 if x>0 and stride is the width // of the element type. - stride := s.constInt(types.Types[TINT], ptr.Type.Elem().Width) + stride := s.constInt(types.Types[types.TINT], ptr.Type.Elem().Width) // The delta is the number of bytes to offset ptr by. - delta := s.newValue2(mulOp, types.Types[TINT], i, stride) + delta := s.newValue2(mulOp, types.Types[types.TINT], i, stride) // If we're slicing to the point where the capacity is zero, // zero out the delta. - mask := s.newValue1(ssa.OpSlicemask, types.Types[TINT], rcap) - delta = s.newValue2(andOp, types.Types[TINT], delta, mask) + mask := s.newValue1(ssa.OpSlicemask, types.Types[types.TINT], rcap) + delta = s.newValue2(andOp, types.Types[types.TINT], delta, mask) // Compute rptr = ptr + delta. rptr := s.newValue2(ssa.OpAddPtr, ptr.Type, ptr, delta) @@ -5544,15 +5545,15 @@ var u64_f32 = u642fcvtTab{ one: (*state).constInt64, } -func (s *state) uint64Tofloat64(n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) uint64Tofloat64(n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { return s.uint64Tofloat(&u64_f64, n, x, ft, tt) } -func (s *state) uint64Tofloat32(n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) uint64Tofloat32(n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { return s.uint64Tofloat(&u64_f32, n, x, ft, tt) } -func (s *state) uint64Tofloat(cvttab *u642fcvtTab, n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) uint64Tofloat(cvttab *u642fcvtTab, n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { // if x >= 0 { // result = (floatY) x // } else { @@ -5578,7 +5579,7 @@ func (s *state) uint64Tofloat(cvttab *u642fcvtTab, n *Node, x *ssa.Value, ft, tt // equal to 10000000001; that rounds up, and the 1 cannot // be lost else it would round down if the LSB of the // candidate mantissa is 0. - cmp := s.newValue2(cvttab.leq, types.Types[TBOOL], s.zeroVal(ft), x) + cmp := s.newValue2(cvttab.leq, types.Types[types.TBOOL], s.zeroVal(ft), x) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(cmp) @@ -5625,21 +5626,21 @@ var u32_f32 = u322fcvtTab{ cvtF2F: ssa.OpCvt64Fto32F, } -func (s *state) uint32Tofloat64(n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) uint32Tofloat64(n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { return s.uint32Tofloat(&u32_f64, n, x, ft, tt) } -func (s *state) uint32Tofloat32(n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) uint32Tofloat32(n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { return s.uint32Tofloat(&u32_f32, n, x, ft, tt) } -func (s *state) uint32Tofloat(cvttab *u322fcvtTab, n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) uint32Tofloat(cvttab *u322fcvtTab, n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { // if x >= 0 { // result = floatY(x) // } else { // result = floatY(float64(x) + (1<<32)) // } - cmp := s.newValue2(ssa.OpLeq32, types.Types[TBOOL], s.zeroVal(ft), x) + cmp := s.newValue2(ssa.OpLeq32, types.Types[types.TBOOL], s.zeroVal(ft), x) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(cmp) @@ -5658,9 +5659,9 @@ func (s *state) uint32Tofloat(cvttab *u322fcvtTab, n *Node, x *ssa.Value, ft, tt b.AddEdgeTo(bElse) s.startBlock(bElse) - a1 := s.newValue1(ssa.OpCvt32to64F, types.Types[TFLOAT64], x) - twoToThe32 := s.constFloat64(types.Types[TFLOAT64], float64(1<<32)) - a2 := s.newValue2(ssa.OpAdd64F, types.Types[TFLOAT64], a1, twoToThe32) + a1 := s.newValue1(ssa.OpCvt32to64F, types.Types[types.TFLOAT64], x) + twoToThe32 := s.constFloat64(types.Types[types.TFLOAT64], float64(1<<32)) + a2 := s.newValue2(ssa.OpAdd64F, types.Types[types.TFLOAT64], a1, twoToThe32) a3 := s.newValue1(cvttab.cvtF2F, tt, a2) s.vars[n] = a3 @@ -5672,7 +5673,7 @@ func (s *state) uint32Tofloat(cvttab *u322fcvtTab, n *Node, x *ssa.Value, ft, tt } // referenceTypeBuiltin generates code for the len/cap builtins for maps and channels. -func (s *state) referenceTypeBuiltin(n *Node, x *ssa.Value) *ssa.Value { +func (s *state) referenceTypeBuiltin(n *ir.Node, x *ssa.Value) *ssa.Value { if !n.Left.Type.IsMap() && !n.Left.Type.IsChan() { s.Fatalf("node must be a map or a channel") } @@ -5685,8 +5686,8 @@ func (s *state) referenceTypeBuiltin(n *Node, x *ssa.Value) *ssa.Value { // return *(((*int)n)+1) // } lenType := n.Type - nilValue := s.constNil(types.Types[TUINTPTR]) - cmp := s.newValue2(ssa.OpEqPtr, types.Types[TBOOL], x, nilValue) + nilValue := s.constNil(types.Types[types.TUINTPTR]) + cmp := s.newValue2(ssa.OpEqPtr, types.Types[types.TBOOL], x, nilValue) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(cmp) @@ -5706,10 +5707,10 @@ func (s *state) referenceTypeBuiltin(n *Node, x *ssa.Value) *ssa.Value { b.AddEdgeTo(bElse) s.startBlock(bElse) switch n.Op { - case OLEN: + case ir.OLEN: // length is stored in the first word for map/chan s.vars[n] = s.load(lenType, x) - case OCAP: + case ir.OCAP: // capacity is stored in the second word for chan sw := s.newValue1I(ssa.OpOffPtr, lenType.PtrTo(), lenType.Width, x) s.vars[n] = s.load(lenType, sw) @@ -5770,22 +5771,22 @@ var f64_u32 = f2uCvtTab{ cutoff: 1 << 31, } -func (s *state) float32ToUint64(n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) float32ToUint64(n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { return s.floatToUint(&f32_u64, n, x, ft, tt) } -func (s *state) float64ToUint64(n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) float64ToUint64(n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { return s.floatToUint(&f64_u64, n, x, ft, tt) } -func (s *state) float32ToUint32(n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) float32ToUint32(n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { return s.floatToUint(&f32_u32, n, x, ft, tt) } -func (s *state) float64ToUint32(n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) float64ToUint32(n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { return s.floatToUint(&f64_u32, n, x, ft, tt) } -func (s *state) floatToUint(cvttab *f2uCvtTab, n *Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { +func (s *state) floatToUint(cvttab *f2uCvtTab, n *ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value { // cutoff:=1<<(intY_Size-1) // if x < floatX(cutoff) { // result = uintY(x) @@ -5795,7 +5796,7 @@ func (s *state) floatToUint(cvttab *f2uCvtTab, n *Node, x *ssa.Value, ft, tt *ty // result = z | -(cutoff) // } cutoff := cvttab.floatValue(s, ft, float64(cvttab.cutoff)) - cmp := s.newValue2(cvttab.ltf, types.Types[TBOOL], x, cutoff) + cmp := s.newValue2(cvttab.ltf, types.Types[types.TBOOL], x, cutoff) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(cmp) @@ -5829,7 +5830,7 @@ func (s *state) floatToUint(cvttab *f2uCvtTab, n *Node, x *ssa.Value, ft, tt *ty // dottype generates SSA for a type assertion node. // commaok indicates whether to panic or return a bool. // If commaok is false, resok will be nil. -func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) { +func (s *state) dottype(n *ir.Node, commaok bool) (res, resok *ssa.Value) { iface := s.expr(n.Left) // input interface target := s.expr(n.Right) // target type byteptr := s.f.Config.Types.BytePtr @@ -5845,7 +5846,7 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) { // Get itab/type field from input. itab := s.newValue1(ssa.OpITab, byteptr, iface) // Conversion succeeds iff that field is not nil. - cond := s.newValue2(ssa.OpNeqPtr, types.Types[TBOOL], itab, s.constNil(byteptr)) + cond := s.newValue2(ssa.OpNeqPtr, types.Types[types.TBOOL], itab, s.constNil(byteptr)) if n.Left.Type.IsEmptyInterface() && commaok { // Converting empty interface to empty interface with ,ok is just a nil check. @@ -5910,13 +5911,13 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) { } if n.Left.Type.IsEmptyInterface() { if commaok { - call := s.rtcall(assertE2I2, true, []*types.Type{n.Type, types.Types[TBOOL]}, target, iface) + call := s.rtcall(assertE2I2, true, []*types.Type{n.Type, types.Types[types.TBOOL]}, target, iface) return call[0], call[1] } return s.rtcall(assertE2I, true, []*types.Type{n.Type}, target, iface)[0], nil } if commaok { - call := s.rtcall(assertI2I2, true, []*types.Type{n.Type, types.Types[TBOOL]}, target, iface) + call := s.rtcall(assertI2I2, true, []*types.Type{n.Type, types.Types[types.TBOOL]}, target, iface) return call[0], call[1] } return s.rtcall(assertI2I, true, []*types.Type{n.Type}, target, iface)[0], nil @@ -5941,7 +5942,7 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) { targetITab = s.expr(n.List.First()) } - var tmp *Node // temporary for use with large types + var tmp *ir.Node // temporary for use with large types var addr *ssa.Value // address of tmp if commaok && !canSSAType(n.Type) { // unSSAable type, use temporary. @@ -5951,7 +5952,7 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) { addr = s.addr(tmp) } - cond := s.newValue2(ssa.OpEqPtr, types.Types[TBOOL], itab, targetITab) + cond := s.newValue2(ssa.OpEqPtr, types.Types[types.TBOOL], itab, targetITab) b := s.endBlock() b.Kind = ssa.BlockIf b.SetControl(cond) @@ -6031,7 +6032,7 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) { } // variable returns the value of a variable at the current location. -func (s *state) variable(name *Node, t *types.Type) *ssa.Value { +func (s *state) variable(name *ir.Node, t *types.Type) *ssa.Value { v := s.vars[name] if v != nil { return v @@ -6057,8 +6058,8 @@ func (s *state) mem() *ssa.Value { return s.variable(memVar, types.TypeMem) } -func (s *state) addNamedValue(n *Node, v *ssa.Value) { - if n.Class() == Pxxx { +func (s *state) addNamedValue(n *ir.Node, v *ssa.Value) { + if n.Class() == ir.Pxxx { // Don't track our marker nodes (memVar etc.). return } @@ -6066,12 +6067,12 @@ func (s *state) addNamedValue(n *Node, v *ssa.Value) { // Don't track temporary variables. return } - if n.Class() == PPARAMOUT { + if n.Class() == ir.PPARAMOUT { // Don't track named output values. This prevents return values // from being assigned too early. See #14591 and #14762. TODO: allow this. return } - if n.Class() == PAUTO && n.Xoffset != 0 { + if n.Class() == ir.PAUTO && n.Xoffset != 0 { s.Fatalf("AUTO var with offset %v %d", n, n.Xoffset) } loc := ssa.LocalSlot{N: n, Type: n.Type, Off: 0} @@ -6110,7 +6111,7 @@ type SSAGenState struct { bstart []*obj.Prog // Some architectures require a 64-bit temporary for FP-related register shuffling. Examples include PPC and Sparc V8. - ScratchFpMem *Node + ScratchFpMem *ir.Node maxarg int64 // largest frame size for arguments to calls made by the function @@ -6193,14 +6194,14 @@ func (s *SSAGenState) DebugFriendlySetPosFrom(v *ssa.Value) { } // byXoffset implements sort.Interface for []*Node using Xoffset as the ordering. -type byXoffset []*Node +type byXoffset []*ir.Node func (s byXoffset) Len() int { return len(s) } func (s byXoffset) Less(i, j int) bool { return s[i].Xoffset < s[j].Xoffset } func (s byXoffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func emitStackObjects(e *ssafn, pp *Progs) { - var vars []*Node + var vars []*ir.Node for _, n := range e.curfn.Func.Dcl { if livenessShouldTrack(n) && n.Name.Addrtaken() { vars = append(vars, n) @@ -6215,7 +6216,7 @@ func emitStackObjects(e *ssafn, pp *Progs) { // Populate the stack object data. // Format must match runtime/stack.go:stackObjectRecord. - x := e.curfn.Func.lsym.Func().StackObjects + x := e.curfn.Func.LSym.Func().StackObjects off := 0 off = duintptr(x, off, uint64(len(vars))) for _, v := range vars { @@ -6252,7 +6253,7 @@ func genssa(f *ssa.Func, pp *Progs) { s.livenessMap = liveness(e, f, pp) emitStackObjects(e, pp) - openDeferInfo := e.curfn.Func.lsym.Func().OpenCodedDeferInfo + openDeferInfo := e.curfn.Func.LSym.Func().OpenCodedDeferInfo if openDeferInfo != nil { // This function uses open-coded defers -- write out the funcdata // info that we computed at the end of genssa. @@ -6457,7 +6458,7 @@ func genssa(f *ssa.Func, pp *Progs) { // some of the inline marks. // Use this instruction instead. p.Pos = p.Pos.WithIsStmt() // promote position to a statement - pp.curfn.Func.lsym.Func().AddInlMark(p, inlMarks[m]) + pp.curfn.Func.LSym.Func().AddInlMark(p, inlMarks[m]) // Make the inline mark a real nop, so it doesn't generate any code. m.As = obj.ANOP m.Pos = src.NoXPos @@ -6469,7 +6470,7 @@ func genssa(f *ssa.Func, pp *Progs) { // Any unmatched inline marks now need to be added to the inlining tree (and will generate a nop instruction). for _, p := range inlMarkList { if p.As != obj.ANOP { - pp.curfn.Func.lsym.Func().AddInlMark(p, inlMarks[p]) + pp.curfn.Func.LSym.Func().AddInlMark(p, inlMarks[p]) } } } @@ -6489,7 +6490,7 @@ func genssa(f *ssa.Func, pp *Progs) { } return bstart[b].Pc case ssa.BlockEnd.ID: - return e.curfn.Func.lsym.Size + return e.curfn.Func.LSym.Size default: return valueToProgAfter[v].Pc } @@ -6591,7 +6592,7 @@ func defframe(s *SSAGenState, e *ssafn) { if !n.Name.Needzero() { continue } - if n.Class() != PAUTO { + if n.Class() != ir.PAUTO { e.Fatalf(n.Pos, "needzero class %d", n.Class()) } if n.Type.Size()%int64(Widthptr) != 0 || n.Xoffset%int64(Widthptr) != 0 || n.Type.Size() == 0 { @@ -6675,8 +6676,8 @@ func AddAux2(a *obj.Addr, v *ssa.Value, offset int64) { case *obj.LSym: a.Name = obj.NAME_EXTERN a.Sym = n - case *Node: - if n.Class() == PPARAM || n.Class() == PPARAMOUT { + case *ir.Node: + if n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT { a.Name = obj.NAME_PARAM a.Sym = n.Orig.Sym.Linksym() a.Offset += n.Xoffset @@ -6702,17 +6703,17 @@ func (s *state) extendIndex(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bo // high word and branch to out-of-bounds failure if it is not 0. var lo *ssa.Value if idx.Type.IsSigned() { - lo = s.newValue1(ssa.OpInt64Lo, types.Types[TINT], idx) + lo = s.newValue1(ssa.OpInt64Lo, types.Types[types.TINT], idx) } else { - lo = s.newValue1(ssa.OpInt64Lo, types.Types[TUINT], idx) + lo = s.newValue1(ssa.OpInt64Lo, types.Types[types.TUINT], idx) } if bounded || base.Flag.B != 0 { return lo } bNext := s.f.NewBlock(ssa.BlockPlain) bPanic := s.f.NewBlock(ssa.BlockExit) - hi := s.newValue1(ssa.OpInt64Hi, types.Types[TUINT32], idx) - cmp := s.newValue2(ssa.OpEq32, types.Types[TBOOL], hi, s.constInt32(types.Types[TUINT32], 0)) + hi := s.newValue1(ssa.OpInt64Hi, types.Types[types.TUINT32], idx) + cmp := s.newValue2(ssa.OpEq32, types.Types[types.TBOOL], hi, s.constInt32(types.Types[types.TUINT32], 0)) if !idx.Type.IsSigned() { switch kind { case ssa.BoundsIndex: @@ -6781,7 +6782,7 @@ func (s *state) extendIndex(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bo s.Fatalf("bad unsigned index extension %s", idx.Type) } } - return s.newValue1(op, types.Types[TINT], idx) + return s.newValue1(op, types.Types[types.TINT], idx) } // CheckLoweredPhi checks that regalloc and stackalloc correctly handled phi values. @@ -6814,12 +6815,12 @@ func CheckLoweredGetClosurePtr(v *ssa.Value) { // AutoVar returns a *Node and int64 representing the auto variable and offset within it // where v should be spilled. -func AutoVar(v *ssa.Value) (*Node, int64) { +func AutoVar(v *ssa.Value) (*ir.Node, int64) { loc := v.Block.Func.RegAlloc[v.ID].(ssa.LocalSlot) if v.Type.Size() > loc.Type.Size() { v.Fatalf("spill/restore type %s doesn't fit in slot type %s", v.Type, loc.Type) } - return loc.N.(*Node), loc.Off + return loc.N.(*ir.Node), loc.Off } func AddrAuto(a *obj.Addr, v *ssa.Value) { @@ -6828,7 +6829,7 @@ func AddrAuto(a *obj.Addr, v *ssa.Value) { a.Sym = n.Sym.Linksym() a.Reg = int16(thearch.REGSP) a.Offset = n.Xoffset + off - if n.Class() == PPARAM || n.Class() == PPARAMOUT { + if n.Class() == ir.PPARAM || n.Class() == ir.PPARAMOUT { a.Name = obj.NAME_PARAM } else { a.Name = obj.NAME_AUTO @@ -6925,7 +6926,7 @@ func (s *SSAGenState) UseArgs(n int64) { } // fieldIdx finds the index of the field referred to by the ODOT node n. -func fieldIdx(n *Node) int { +func fieldIdx(n *ir.Node) int { t := n.Left.Type f := n.Sym if !t.IsStruct() { @@ -6952,9 +6953,9 @@ func fieldIdx(n *Node) int { // ssafn holds frontend information about a function that the backend is processing. // It also exports a bunch of compiler services for the ssa backend. type ssafn struct { - curfn *Node + curfn *ir.Node strings map[string]*obj.LSym // map from constant string to data symbols - scratchFpMem *Node // temp for floating point register / memory moves on some architectures + scratchFpMem *ir.Node // temp for floating point register / memory moves on some architectures stksize int64 // stack size for current frame stkptrsize int64 // prefix of stack containing pointers log bool // print ssa debug to the stdout @@ -6980,8 +6981,8 @@ func (e *ssafn) Auto(pos src.XPos, t *types.Type) ssa.GCNode { } func (e *ssafn) SplitString(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) { - ptrType := types.NewPtr(types.Types[TUINT8]) - lenType := types.Types[TINT] + ptrType := types.NewPtr(types.Types[types.TUINT8]) + lenType := types.Types[types.TINT] // Split this string up into two separate variables. p := e.SplitSlot(&name, ".ptr", 0, ptrType) l := e.SplitSlot(&name, ".len", ptrType.Size(), lenType) @@ -6989,9 +6990,9 @@ func (e *ssafn) SplitString(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) { } func (e *ssafn) SplitInterface(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) { - n := name.N.(*Node) - u := types.Types[TUINTPTR] - t := types.NewPtr(types.Types[TUINT8]) + n := name.N.(*ir.Node) + u := types.Types[types.TUINTPTR] + t := types.NewPtr(types.Types[types.TUINT8]) // Split this interface up into two separate variables. f := ".itab" if n.Type.IsEmptyInterface() { @@ -7004,7 +7005,7 @@ func (e *ssafn) SplitInterface(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot func (e *ssafn) SplitSlice(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot, ssa.LocalSlot) { ptrType := types.NewPtr(name.Type.Elem()) - lenType := types.Types[TINT] + lenType := types.Types[types.TINT] p := e.SplitSlot(&name, ".ptr", 0, ptrType) l := e.SplitSlot(&name, ".len", ptrType.Size(), lenType) c := e.SplitSlot(&name, ".cap", ptrType.Size()+lenType.Size(), lenType) @@ -7015,9 +7016,9 @@ func (e *ssafn) SplitComplex(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) s := name.Type.Size() / 2 var t *types.Type if s == 8 { - t = types.Types[TFLOAT64] + t = types.Types[types.TFLOAT64] } else { - t = types.Types[TFLOAT32] + t = types.Types[types.TFLOAT32] } r := e.SplitSlot(&name, ".real", 0, t) i := e.SplitSlot(&name, ".imag", t.Size(), t) @@ -7027,14 +7028,14 @@ func (e *ssafn) SplitComplex(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) func (e *ssafn) SplitInt64(name ssa.LocalSlot) (ssa.LocalSlot, ssa.LocalSlot) { var t *types.Type if name.Type.IsSigned() { - t = types.Types[TINT32] + t = types.Types[types.TINT32] } else { - t = types.Types[TUINT32] + t = types.Types[types.TUINT32] } if thearch.LinkArch.ByteOrder == binary.BigEndian { - return e.SplitSlot(&name, ".hi", 0, t), e.SplitSlot(&name, ".lo", t.Size(), types.Types[TUINT32]) + return e.SplitSlot(&name, ".hi", 0, t), e.SplitSlot(&name, ".lo", t.Size(), types.Types[types.TUINT32]) } - return e.SplitSlot(&name, ".hi", t.Size(), t), e.SplitSlot(&name, ".lo", 0, types.Types[TUINT32]) + return e.SplitSlot(&name, ".hi", t.Size(), t), e.SplitSlot(&name, ".lo", 0, types.Types[types.TUINT32]) } func (e *ssafn) SplitStruct(name ssa.LocalSlot, i int) ssa.LocalSlot { @@ -7046,7 +7047,7 @@ func (e *ssafn) SplitStruct(name ssa.LocalSlot, i int) ssa.LocalSlot { } func (e *ssafn) SplitArray(name ssa.LocalSlot) ssa.LocalSlot { - n := name.N.(*Node) + n := name.N.(*ir.Node) at := name.Type if at.NumElem() != 1 { e.Fatalf(n.Pos, "bad array size") @@ -7061,19 +7062,19 @@ func (e *ssafn) DerefItab(it *obj.LSym, offset int64) *obj.LSym { // SplitSlot returns a slot representing the data of parent starting at offset. func (e *ssafn) SplitSlot(parent *ssa.LocalSlot, suffix string, offset int64, t *types.Type) ssa.LocalSlot { - node := parent.N.(*Node) + node := parent.N.(*ir.Node) - if node.Class() != PAUTO || node.Name.Addrtaken() { + if node.Class() != ir.PAUTO || node.Name.Addrtaken() { // addressed things and non-autos retain their parents (i.e., cannot truly be split) return ssa.LocalSlot{N: node, Type: t, Off: parent.Off + offset} } - s := &types.Sym{Name: node.Sym.Name + suffix, Pkg: localpkg} - n := newnamel(parent.N.(*Node).Pos, s) - s.Def = asTypesNode(n) - asNode(s.Def).Name.SetUsed(true) + s := &types.Sym{Name: node.Sym.Name + suffix, Pkg: ir.LocalPkg} + n := ir.NewNameAt(parent.N.(*ir.Node).Pos, s) + s.Def = ir.AsTypesNode(n) + ir.AsNode(s.Def).Name.SetUsed(true) n.Type = t - n.SetClass(PAUTO) + n.SetClass(ir.PAUTO) n.Esc = EscNever n.Name.Curfn = e.curfn e.curfn.Func.Dcl = append(e.curfn.Func.Dcl, n) @@ -7103,7 +7104,7 @@ func (e *ssafn) Log() bool { // Fatal reports a compiler error and exits. func (e *ssafn) Fatalf(pos src.XPos, msg string, args ...interface{}) { base.Pos = pos - nargs := append([]interface{}{e.curfn.funcname()}, args...) + nargs := append([]interface{}{ir.FuncName(e.curfn)}, args...) base.Fatalf("'%s': "+msg, nargs...) } @@ -7139,35 +7140,18 @@ func (e *ssafn) Syslook(name string) *obj.LSym { } func (e *ssafn) SetWBPos(pos src.XPos) { - e.curfn.Func.setWBPos(pos) + e.curfn.Func.SetWBPos(pos) } func (e *ssafn) MyImportPath() string { return base.Ctxt.Pkgpath } -func (n *Node) Typ() *types.Type { - return n.Type -} -func (n *Node) StorageClass() ssa.StorageClass { - switch n.Class() { - case PPARAM: - return ssa.ClassParam - case PPARAMOUT: - return ssa.ClassParamOut - case PAUTO: - return ssa.ClassAuto - default: - base.Fatalf("untranslatable storage class for %v: %s", n, n.Class()) - return 0 - } -} - -func clobberBase(n *Node) *Node { - if n.Op == ODOT && n.Left.Type.NumFields() == 1 { +func clobberBase(n *ir.Node) *ir.Node { + if n.Op == ir.ODOT && n.Left.Type.NumFields() == 1 { return clobberBase(n.Left) } - if n.Op == OINDEX && n.Left.Type.IsArray() && n.Left.Type.NumElem() == 1 { + if n.Op == ir.OINDEX && n.Left.Type.IsArray() && n.Left.Type.NumElem() == 1 { return clobberBase(n.Left) } return n diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 00402a1bee6..46f4153fe19 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/src" "crypto/md5" @@ -39,11 +40,11 @@ var ( // It's primarily used to distinguish references to named objects, // whose Pos will point back to their declaration position rather than // their usage position. -func hasUniquePos(n *Node) bool { +func hasUniquePos(n *ir.Node) bool { switch n.Op { - case ONAME, OPACK: + case ir.ONAME, ir.OPACK: return false - case OLITERAL, ONIL, OTYPE: + case ir.OLITERAL, ir.ONIL, ir.OTYPE: if n.Sym != nil { return false } @@ -59,7 +60,7 @@ func hasUniquePos(n *Node) bool { return true } -func setlineno(n *Node) src.XPos { +func setlineno(n *ir.Node) src.XPos { lno := base.Pos if n != nil && hasUniquePos(n) { base.Pos = n.Pos @@ -68,7 +69,7 @@ func setlineno(n *Node) src.XPos { } func lookup(name string) *types.Sym { - return localpkg.Lookup(name) + return ir.LocalPkg.Lookup(name) } // lookupN looks up the symbol starting with prefix and ending with @@ -77,7 +78,7 @@ func lookupN(prefix string, n int) *types.Sym { var buf [20]byte // plenty long enough for all current users copy(buf[:], prefix) b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10) - return localpkg.LookupBytes(b) + return ir.LocalPkg.LookupBytes(b) } // autolabel generates a new Name node for use with @@ -101,7 +102,7 @@ func autolabel(prefix string) *types.Sym { // find all the exported symbols in package opkg // and make them available in the current package -func importdot(opkg *types.Pkg, pack *Node) { +func importdot(opkg *types.Pkg, pack *ir.Node) { n := 0 for _, s := range opkg.Syms { if s.Def == nil { @@ -119,11 +120,11 @@ func importdot(opkg *types.Pkg, pack *Node) { s1.Def = s.Def s1.Block = s.Block - if asNode(s1.Def).Name == nil { - Dump("s1def", asNode(s1.Def)) + if ir.AsNode(s1.Def).Name == nil { + ir.Dump("s1def", ir.AsNode(s1.Def)) base.Fatalf("missing Name") } - asNode(s1.Def).Name.Pack = pack + ir.AsNode(s1.Def).Name.Pack = pack s1.Origpkg = opkg n++ } @@ -134,118 +135,27 @@ func importdot(opkg *types.Pkg, pack *Node) { } } -func nod(op Op, nleft, nright *Node) *Node { - return nodl(base.Pos, op, nleft, nright) -} - -func nodl(pos src.XPos, op Op, nleft, nright *Node) *Node { - var n *Node - switch op { - case ODCLFUNC: - var x struct { - n Node - f Func - } - n = &x.n - n.Func = &x.f - n.Func.Decl = n - case ONAME: - base.Fatalf("use newname instead") - case OLABEL, OPACK: - var x struct { - n Node - m Name - } - n = &x.n - n.Name = &x.m - default: - n = new(Node) - } - n.Op = op - n.Left = nleft - n.Right = nright - n.Pos = pos - n.Xoffset = BADWIDTH - n.Orig = n - return n -} - // newname returns a new ONAME Node associated with symbol s. -func newname(s *types.Sym) *Node { - n := newnamel(base.Pos, s) +func NewName(s *types.Sym) *ir.Node { + n := ir.NewNameAt(base.Pos, s) n.Name.Curfn = Curfn return n } -// newnamel returns a new ONAME Node associated with symbol s at position pos. -// The caller is responsible for setting n.Name.Curfn. -func newnamel(pos src.XPos, s *types.Sym) *Node { - if s == nil { - base.Fatalf("newnamel nil") - } - - var x struct { - n Node - m Name - p Param - } - n := &x.n - n.Name = &x.m - n.Name.Param = &x.p - - n.Op = ONAME - n.Pos = pos - n.Orig = n - - n.Sym = s - return n -} - // nodSym makes a Node with Op op and with the Left field set to left // and the Sym field set to sym. This is for ODOT and friends. -func nodSym(op Op, left *Node, sym *types.Sym) *Node { +func nodSym(op ir.Op, left *ir.Node, sym *types.Sym) *ir.Node { return nodlSym(base.Pos, op, left, sym) } // nodlSym makes a Node with position Pos, with Op op, and with the Left field set to left // and the Sym field set to sym. This is for ODOT and friends. -func nodlSym(pos src.XPos, op Op, left *Node, sym *types.Sym) *Node { - n := nodl(pos, op, left, nil) +func nodlSym(pos src.XPos, op ir.Op, left *ir.Node, sym *types.Sym) *ir.Node { + n := ir.NodAt(pos, op, left, nil) n.Sym = sym return n } -// rawcopy returns a shallow copy of n. -// Note: copy or sepcopy (rather than rawcopy) is usually the -// correct choice (see comment with Node.copy, below). -func (n *Node) rawcopy() *Node { - copy := *n - return © -} - -// sepcopy returns a separate shallow copy of n, with the copy's -// Orig pointing to itself. -func (n *Node) sepcopy() *Node { - copy := *n - copy.Orig = © - return © -} - -// copy returns shallow copy of n and adjusts the copy's Orig if -// necessary: In general, if n.Orig points to itself, the copy's -// Orig should point to itself as well. Otherwise, if n is modified, -// the copy's Orig node appears modified, too, and then doesn't -// represent the original node anymore. -// (This caused the wrong complit Op to be used when printing error -// messages; see issues #26855, #27765). -func (n *Node) copy() *Node { - copy := *n - if n.Orig == n { - copy.Orig = © - } - return © -} - // methcmp sorts methods by symbol. type methcmp []*types.Field @@ -253,67 +163,60 @@ func (x methcmp) Len() int { return len(x) } func (x methcmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] } func (x methcmp) Less(i, j int) bool { return x[i].Sym.Less(x[j].Sym) } -func nodintconst(v int64) *Node { - return nodlit(constant.MakeInt64(v)) +func nodintconst(v int64) *ir.Node { + return ir.NewLiteral(constant.MakeInt64(v)) } -func nodnil() *Node { - n := nod(ONIL, nil, nil) - n.Type = types.Types[TNIL] +func nodnil() *ir.Node { + n := ir.Nod(ir.ONIL, nil, nil) + n.Type = types.Types[types.TNIL] return n } -func nodbool(b bool) *Node { - return nodlit(constant.MakeBool(b)) +func nodbool(b bool) *ir.Node { + return ir.NewLiteral(constant.MakeBool(b)) } -func nodstr(s string) *Node { - return nodlit(constant.MakeString(s)) +func nodstr(s string) *ir.Node { + return ir.NewLiteral(constant.MakeString(s)) } // treecopy recursively copies n, with the exception of // ONAME, OLITERAL, OTYPE, and ONONAME leaves. // If pos.IsKnown(), it sets the source position of newly // allocated nodes to pos. -func treecopy(n *Node, pos src.XPos) *Node { +func treecopy(n *ir.Node, pos src.XPos) *ir.Node { if n == nil { return nil } switch n.Op { default: - m := n.sepcopy() + m := ir.SepCopy(n) m.Left = treecopy(n.Left, pos) m.Right = treecopy(n.Right, pos) m.List.Set(listtreecopy(n.List.Slice(), pos)) if pos.IsKnown() { m.Pos = pos } - if m.Name != nil && n.Op != ODCLFIELD { - Dump("treecopy", n) + if m.Name != nil && n.Op != ir.ODCLFIELD { + ir.Dump("treecopy", n) base.Fatalf("treecopy Name") } return m - case OPACK: + case ir.OPACK: // OPACK nodes are never valid in const value declarations, // but allow them like any other declared symbol to avoid // crashing (golang.org/issue/11361). fallthrough - case ONAME, ONONAME, OLITERAL, ONIL, OTYPE: + case ir.ONAME, ir.ONONAME, ir.OLITERAL, ir.ONIL, ir.OTYPE: return n } } -// isNil reports whether n represents the universal untyped zero value "nil". -func (n *Node) isNil() bool { - // Check n.Orig because constant propagation may produce typed nil constants, - // which don't exist in the Go spec. - return n.Orig.Op == ONIL -} - func isptrto(t *types.Type, et types.EType) bool { if t == nil { return false @@ -331,13 +234,6 @@ func isptrto(t *types.Type, et types.EType) bool { return true } -func (n *Node) isBlank() bool { - if n == nil { - return false - } - return n.Sym.IsBlank() -} - // methtype returns the underlying type, if any, // that owns methods with receiver parameter t. // The result is either a named type or an anonymous struct. @@ -367,7 +263,7 @@ func methtype(t *types.Type) *types.Type { return t } switch t.Etype { - case TARRAY, TCHAN, TFUNC, TMAP, TSLICE, TSTRING, TSTRUCT: + case types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRING, types.TSTRUCT: return t } return nil @@ -377,17 +273,17 @@ func methtype(t *types.Type) *types.Type { // If so, return op code to use in conversion. // If not, return OXXX. In this case, the string return parameter may // hold a reason why. In all other cases, it'll be the empty string. -func assignop(src, dst *types.Type) (Op, string) { +func assignop(src, dst *types.Type) (ir.Op, string) { if src == dst { - return OCONVNOP, "" + return ir.OCONVNOP, "" } - if src == nil || dst == nil || src.Etype == TFORW || dst.Etype == TFORW || src.Orig == nil || dst.Orig == nil { - return OXXX, "" + if src == nil || dst == nil || src.Etype == types.TFORW || dst.Etype == types.TFORW || src.Orig == nil || dst.Orig == nil { + return ir.OXXX, "" } // 1. src type is identical to dst. if types.Identical(src, dst) { - return OCONVNOP, "" + return ir.OCONVNOP, "" } // 2. src and dst have identical underlying types @@ -401,31 +297,31 @@ func assignop(src, dst *types.Type) (Op, string) { if src.IsEmptyInterface() { // Conversion between two empty interfaces // requires no code. - return OCONVNOP, "" + return ir.OCONVNOP, "" } if (src.Sym == nil || dst.Sym == nil) && !src.IsInterface() { // Conversion between two types, at least one unnamed, // needs no conversion. The exception is nonempty interfaces // which need to have their itab updated. - return OCONVNOP, "" + return ir.OCONVNOP, "" } } // 3. dst is an interface type and src implements dst. - if dst.IsInterface() && src.Etype != TNIL { + if dst.IsInterface() && src.Etype != types.TNIL { var missing, have *types.Field var ptr int if implements(src, dst, &missing, &have, &ptr) { - return OCONVIFACE, "" + return ir.OCONVIFACE, "" } // we'll have complained about this method anyway, suppress spurious messages. if have != nil && have.Sym == missing.Sym && (have.Type.Broke() || missing.Type.Broke()) { - return OCONVIFACE, "" + return ir.OCONVIFACE, "" } var why string - if isptrto(src, TINTER) { + if isptrto(src, types.TINTER) { why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src) } else if have != nil && have.Sym == missing.Sym && have.Nointerface() { why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym) @@ -441,22 +337,22 @@ func assignop(src, dst *types.Type) (Op, string) { why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym) } - return OXXX, why + return ir.OXXX, why } - if isptrto(dst, TINTER) { + if isptrto(dst, types.TINTER) { why := fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst) - return OXXX, why + return ir.OXXX, why } - if src.IsInterface() && dst.Etype != TBLANK { + if src.IsInterface() && dst.Etype != types.TBLANK { var missing, have *types.Field var ptr int var why string if implements(dst, src, &missing, &have, &ptr) { why = ": need type assertion" } - return OXXX, why + return ir.OXXX, why } // 4. src is a bidirectional channel value, dst is a channel type, @@ -464,31 +360,31 @@ func assignop(src, dst *types.Type) (Op, string) { // either src or dst is not a named type. if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() { if types.Identical(src.Elem(), dst.Elem()) && (src.Sym == nil || dst.Sym == nil) { - return OCONVNOP, "" + return ir.OCONVNOP, "" } } // 5. src is the predeclared identifier nil and dst is a nillable type. - if src.Etype == TNIL { + if src.Etype == types.TNIL { switch dst.Etype { - case TPTR, - TFUNC, - TMAP, - TCHAN, - TINTER, - TSLICE: - return OCONVNOP, "" + case types.TPTR, + types.TFUNC, + types.TMAP, + types.TCHAN, + types.TINTER, + types.TSLICE: + return ir.OCONVNOP, "" } } // 6. rule about untyped constants - already converted by defaultlit. // 7. Any typed value can be assigned to the blank identifier. - if dst.Etype == TBLANK { - return OCONVNOP, "" + if dst.Etype == types.TBLANK { + return ir.OCONVNOP, "" } - return OXXX, "" + return ir.OXXX, "" } // Can we convert a value of type src to a value of type dst? @@ -496,12 +392,12 @@ func assignop(src, dst *types.Type) (Op, string) { // If not, return OXXX. In this case, the string return parameter may // hold a reason why. In all other cases, it'll be the empty string. // srcConstant indicates whether the value of type src is a constant. -func convertop(srcConstant bool, src, dst *types.Type) (Op, string) { +func convertop(srcConstant bool, src, dst *types.Type) (ir.Op, string) { if src == dst { - return OCONVNOP, "" + return ir.OCONVNOP, "" } if src == nil || dst == nil { - return OXXX, "" + return ir.OXXX, "" } // Conversions from regular to go:notinheap are not allowed @@ -510,17 +406,17 @@ func convertop(srcConstant bool, src, dst *types.Type) (Op, string) { // (a) Disallow (*T) to (*U) where T is go:notinheap but U isn't. if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() { why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem()) - return OXXX, why + return ir.OXXX, why } // (b) Disallow string to []T where T is go:notinheap. if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Etype == types.Bytetype.Etype || dst.Elem().Etype == types.Runetype.Etype) { why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem()) - return OXXX, why + return ir.OXXX, why } // 1. src can be assigned to dst. op, why := assignop(src, dst) - if op != OXXX { + if op != ir.OXXX { return op, why } @@ -529,57 +425,57 @@ func convertop(srcConstant bool, src, dst *types.Type) (Op, string) { // with the good message from assignop. // Otherwise clear the error. if src.IsInterface() || dst.IsInterface() { - return OXXX, why + return ir.OXXX, why } // 2. Ignoring struct tags, src and dst have identical underlying types. if types.IdenticalIgnoreTags(src.Orig, dst.Orig) { - return OCONVNOP, "" + return ir.OCONVNOP, "" } // 3. src and dst are unnamed pointer types and, ignoring struct tags, // their base types have identical underlying types. if src.IsPtr() && dst.IsPtr() && src.Sym == nil && dst.Sym == nil { if types.IdenticalIgnoreTags(src.Elem().Orig, dst.Elem().Orig) { - return OCONVNOP, "" + return ir.OCONVNOP, "" } } // 4. src and dst are both integer or floating point types. if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) { if simtype[src.Etype] == simtype[dst.Etype] { - return OCONVNOP, "" + return ir.OCONVNOP, "" } - return OCONV, "" + return ir.OCONV, "" } // 5. src and dst are both complex types. if src.IsComplex() && dst.IsComplex() { if simtype[src.Etype] == simtype[dst.Etype] { - return OCONVNOP, "" + return ir.OCONVNOP, "" } - return OCONV, "" + return ir.OCONV, "" } // Special case for constant conversions: any numeric // conversion is potentially okay. We'll validate further // within evconst. See #38117. if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) { - return OCONV, "" + return ir.OCONV, "" } // 6. src is an integer or has type []byte or []rune // and dst is a string type. if src.IsInteger() && dst.IsString() { - return ORUNESTR, "" + return ir.ORUNESTR, "" } if src.IsSlice() && dst.IsString() { if src.Elem().Etype == types.Bytetype.Etype { - return OBYTES2STR, "" + return ir.OBYTES2STR, "" } if src.Elem().Etype == types.Runetype.Etype { - return ORUNES2STR, "" + return ir.ORUNES2STR, "" } } @@ -587,45 +483,45 @@ func convertop(srcConstant bool, src, dst *types.Type) (Op, string) { // String to slice. if src.IsString() && dst.IsSlice() { if dst.Elem().Etype == types.Bytetype.Etype { - return OSTR2BYTES, "" + return ir.OSTR2BYTES, "" } if dst.Elem().Etype == types.Runetype.Etype { - return OSTR2RUNES, "" + return ir.OSTR2RUNES, "" } } // 8. src is a pointer or uintptr and dst is unsafe.Pointer. if (src.IsPtr() || src.IsUintptr()) && dst.IsUnsafePtr() { - return OCONVNOP, "" + return ir.OCONVNOP, "" } // 9. src is unsafe.Pointer and dst is a pointer or uintptr. if src.IsUnsafePtr() && (dst.IsPtr() || dst.IsUintptr()) { - return OCONVNOP, "" + return ir.OCONVNOP, "" } // src is map and dst is a pointer to corresponding hmap. // This rule is needed for the implementation detail that // go gc maps are implemented as a pointer to a hmap struct. - if src.Etype == TMAP && dst.IsPtr() && + if src.Etype == types.TMAP && dst.IsPtr() && src.MapType().Hmap == dst.Elem() { - return OCONVNOP, "" + return ir.OCONVNOP, "" } - return OXXX, "" + return ir.OXXX, "" } -func assignconv(n *Node, t *types.Type, context string) *Node { +func assignconv(n *ir.Node, t *types.Type, context string) *ir.Node { return assignconvfn(n, t, func() string { return context }) } // Convert node n for assignment to type t. -func assignconvfn(n *Node, t *types.Type, context func() string) *Node { +func assignconvfn(n *ir.Node, t *types.Type, context func() string) *ir.Node { if n == nil || n.Type == nil || n.Type.Broke() { return n } - if t.Etype == TBLANK && n.Type.Etype == TNIL { + if t.Etype == types.TBLANK && n.Type.Etype == types.TNIL { base.Errorf("use of untyped nil") } @@ -633,16 +529,16 @@ func assignconvfn(n *Node, t *types.Type, context func() string) *Node { if n.Type == nil { return n } - if t.Etype == TBLANK { + if t.Etype == types.TBLANK { return n } // Convert ideal bool from comparison to plain bool // if the next step is non-bool (like interface{}). if n.Type == types.UntypedBool && !t.IsBoolean() { - if n.Op == ONAME || n.Op == OLITERAL { - r := nod(OCONVNOP, n, nil) - r.Type = types.Types[TBOOL] + if n.Op == ir.ONAME || n.Op == ir.OLITERAL { + r := ir.Nod(ir.OCONVNOP, n, nil) + r.Type = types.Types[types.TBOOL] r.SetTypecheck(1) r.SetImplicit(true) n = r @@ -654,12 +550,12 @@ func assignconvfn(n *Node, t *types.Type, context func() string) *Node { } op, why := assignop(n.Type, t) - if op == OXXX { + if op == ir.OXXX { base.Errorf("cannot use %L as type %v in %s%s", n, t, context(), why) - op = OCONV + op = ir.OCONV } - r := nod(op, n, nil) + r := ir.Nod(op, n, nil) r.Type = t r.SetTypecheck(1) r.SetImplicit(true) @@ -667,103 +563,29 @@ func assignconvfn(n *Node, t *types.Type, context func() string) *Node { return r } -// IsMethod reports whether n is a method. -// n must be a function or a method. -func (n *Node) IsMethod() bool { - return n.Type.Recv() != nil -} - -// 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 *Node) SliceBounds() (low, high, max *Node) { - if n.List.Len() == 0 { - return nil, nil, nil - } - - switch n.Op { - case OSLICE, OSLICEARR, OSLICESTR: - s := n.List.Slice() - return s[0], s[1], nil - case OSLICE3, OSLICE3ARR: - s := n.List.Slice() - 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 *Node) 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.Slice() - if s == nil { - if low == nil && high == nil { - return - } - n.List.Set2(low, high) - return - } - s[0] = low - s[1] = high - return - case OSLICE3, OSLICE3ARR: - s := n.List.Slice() - if s == nil { - if low == nil && high == nil && max == nil { - return - } - n.List.Set3(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 { - switch o { - case OSLICE, OSLICEARR, OSLICESTR: - return false - case OSLICE3, OSLICE3ARR: - return true - } - base.Fatalf("IsSlice3 op %v", o) - return false -} - // backingArrayPtrLen extracts the pointer and length from a slice or string. // This constructs two nodes referring to n, so n must be a cheapexpr. -func (n *Node) backingArrayPtrLen() (ptr, len *Node) { - var init Nodes +func backingArrayPtrLen(n *ir.Node) (ptr, len *ir.Node) { + var init ir.Nodes c := cheapexpr(n, &init) if c != n || init.Len() != 0 { base.Fatalf("backingArrayPtrLen not cheap: %v", n) } - ptr = nod(OSPTR, n, nil) + ptr = ir.Nod(ir.OSPTR, n, nil) if n.Type.IsString() { - ptr.Type = types.Types[TUINT8].PtrTo() + ptr.Type = types.Types[types.TUINT8].PtrTo() } else { ptr.Type = n.Type.Elem().PtrTo() } - len = nod(OLEN, n, nil) - len.Type = types.Types[TINT] + len = ir.Nod(ir.OLEN, n, nil) + len.Type = types.Types[types.TINT] return ptr, len } // labeledControl returns the control flow Node (for, switch, select) // associated with the label n, if any. -func (n *Node) labeledControl() *Node { - if n.Op != OLABEL { +func labeledControl(n *ir.Node) *ir.Node { + if n.Op != ir.OLABEL { base.Fatalf("labeledControl %v", n.Op) } ctl := n.Name.Defn @@ -771,18 +593,18 @@ func (n *Node) labeledControl() *Node { return nil } switch ctl.Op { - case OFOR, OFORUNTIL, OSWITCH, OSELECT: + case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OSELECT: return ctl } return nil } -func syslook(name string) *Node { +func syslook(name string) *ir.Node { s := Runtimepkg.Lookup(name) if s == nil || s.Def == nil { base.Fatalf("syslook: can't find runtime.%s", name) } - return asNode(s.Def) + return ir.AsNode(s.Def) } // typehash computes a hash value for type t to use in type switch statements. @@ -796,49 +618,49 @@ func typehash(t *types.Type) uint32 { // updateHasCall checks whether expression n contains any function // calls and sets the n.HasCall flag if so. -func updateHasCall(n *Node) { +func updateHasCall(n *ir.Node) { if n == nil { return } n.SetHasCall(calcHasCall(n)) } -func calcHasCall(n *Node) bool { +func calcHasCall(n *ir.Node) bool { if n.Ninit.Len() != 0 { // TODO(mdempsky): This seems overly conservative. return true } switch n.Op { - case OLITERAL, ONIL, ONAME, OTYPE: + case ir.OLITERAL, ir.ONIL, ir.ONAME, ir.OTYPE: if n.HasCall() { base.Fatalf("OLITERAL/ONAME/OTYPE should never have calls: %+v", n) } return false - case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER: + case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: return true - case OANDAND, OOROR: + case ir.OANDAND, ir.OOROR: // hard with instrumented code if instrumenting { return true } - case OINDEX, OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR, - ODEREF, ODOTPTR, ODOTTYPE, ODIV, OMOD: + case ir.OINDEX, ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR, + ir.ODEREF, ir.ODOTPTR, ir.ODOTTYPE, ir.ODIV, ir.OMOD: // These ops might panic, make sure they are done // before we start marshaling args for a call. See issue 16760. return true // When using soft-float, these ops might be rewritten to function calls // so we ensure they are evaluated first. - case OADD, OSUB, ONEG, OMUL: + case ir.OADD, ir.OSUB, ir.ONEG, ir.OMUL: if thearch.SoftFloat && (isFloat[n.Type.Etype] || isComplex[n.Type.Etype]) { return true } - case OLT, OEQ, ONE, OLE, OGE, OGT: + case ir.OLT, ir.OEQ, ir.ONE, ir.OLE, ir.OGE, ir.OGT: if thearch.SoftFloat && (isFloat[n.Left.Type.Etype] || isComplex[n.Left.Type.Etype]) { return true } - case OCONV: + case ir.OCONV: if thearch.SoftFloat && ((isFloat[n.Type.Etype] || isComplex[n.Type.Etype]) || (isFloat[n.Left.Type.Etype] || isComplex[n.Left.Type.Etype])) { return true } @@ -853,7 +675,7 @@ func calcHasCall(n *Node) bool { return false } -func badtype(op Op, tl, tr *types.Type) { +func badtype(op ir.Op, tl, tr *types.Type) { var s string if tl != nil { s += fmt.Sprintf("\n\t%v", tl) @@ -876,20 +698,20 @@ func badtype(op Op, tl, tr *types.Type) { // brcom returns !(op). // For example, brcom(==) is !=. -func brcom(op Op) Op { +func brcom(op ir.Op) ir.Op { switch op { - case OEQ: - return ONE - case ONE: - return OEQ - case OLT: - return OGE - case OGT: - return OLE - case OLE: - return OGT - case OGE: - return OLT + case ir.OEQ: + return ir.ONE + case ir.ONE: + return ir.OEQ + case ir.OLT: + return ir.OGE + case ir.OGT: + return ir.OLE + case ir.OLE: + return ir.OGT + case ir.OGE: + return ir.OLT } base.Fatalf("brcom: no com for %v\n", op) return op @@ -897,20 +719,20 @@ func brcom(op Op) Op { // brrev returns reverse(op). // For example, Brrev(<) is >. -func brrev(op Op) Op { +func brrev(op ir.Op) ir.Op { switch op { - case OEQ: - return OEQ - case ONE: - return ONE - case OLT: - return OGT - case OGT: - return OLT - case OLE: - return OGE - case OGE: - return OLE + case ir.OEQ: + return ir.OEQ + case ir.ONE: + return ir.ONE + case ir.OLT: + return ir.OGT + case ir.OGT: + return ir.OLT + case ir.OLE: + return ir.OGE + case ir.OGE: + return ir.OLE } base.Fatalf("brrev: no rev for %v\n", op) return op @@ -918,7 +740,7 @@ func brrev(op Op) Op { // return side effect-free n, appending side effects to init. // result is assignable if n is. -func safeexpr(n *Node, init *Nodes) *Node { +func safeexpr(n *ir.Node, init *ir.Nodes) *ir.Node { if n == nil { return nil } @@ -929,43 +751,43 @@ func safeexpr(n *Node, init *Nodes) *Node { } switch n.Op { - case ONAME, OLITERAL, ONIL: + case ir.ONAME, ir.OLITERAL, ir.ONIL: return n - case ODOT, OLEN, OCAP: + case ir.ODOT, ir.OLEN, ir.OCAP: l := safeexpr(n.Left, init) if l == n.Left { return n } - r := n.copy() + r := ir.Copy(n) r.Left = l r = typecheck(r, ctxExpr) r = walkexpr(r, init) return r - case ODOTPTR, ODEREF: + case ir.ODOTPTR, ir.ODEREF: l := safeexpr(n.Left, init) if l == n.Left { return n } - a := n.copy() + a := ir.Copy(n) a.Left = l a = walkexpr(a, init) return a - case OINDEX, OINDEXMAP: + case ir.OINDEX, ir.OINDEXMAP: l := safeexpr(n.Left, init) r := safeexpr(n.Right, init) if l == n.Left && r == n.Right { return n } - a := n.copy() + a := ir.Copy(n) a.Left = l a.Right = r a = walkexpr(a, init) return a - case OSTRUCTLIT, OARRAYLIT, OSLICELIT: + case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT: if isStaticCompositeLiteral(n) { return n } @@ -978,9 +800,9 @@ func safeexpr(n *Node, init *Nodes) *Node { return cheapexpr(n, init) } -func copyexpr(n *Node, t *types.Type, init *Nodes) *Node { +func copyexpr(n *ir.Node, t *types.Type, init *ir.Nodes) *ir.Node { l := temp(t) - a := nod(OAS, l, n) + a := ir.Nod(ir.OAS, l, n) a = typecheck(a, ctxStmt) a = walkexpr(a, init) init.Append(a) @@ -989,9 +811,9 @@ func copyexpr(n *Node, t *types.Type, init *Nodes) *Node { // return side-effect free and cheap n, appending side effects to init. // result may not be assignable. -func cheapexpr(n *Node, init *Nodes) *Node { +func cheapexpr(n *ir.Node, init *ir.Nodes) *ir.Node { switch n.Op { - case ONAME, OLITERAL, ONIL: + case ir.ONAME, ir.OLITERAL, ir.ONIL: return n } @@ -1135,7 +957,7 @@ func dotpath(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) ( // find missing fields that // will give shortest unique addressing. // modify the tree with missing type names. -func adddot(n *Node) *Node { +func adddot(n *ir.Node) *ir.Node { n.Left = typecheck(n.Left, ctxType|ctxExpr) if n.Left.Diag() { n.SetDiag(true) @@ -1145,7 +967,7 @@ func adddot(n *Node) *Node { return n } - if n.Left.Op == OTYPE { + if n.Left.Op == ir.OTYPE { return n } @@ -1158,7 +980,7 @@ func adddot(n *Node) *Node { case path != nil: // rebuild elided dots for c := len(path) - 1; c >= 0; c-- { - n.Left = nodSym(ODOT, n.Left, path[c].field.Sym) + n.Left = nodSym(ir.ODOT, n.Left, path[c].field.Sym) n.Left.SetImplicit(true) } case ambig: @@ -1294,8 +1116,8 @@ func expandmeth(t *types.Type) { } // Given funarg struct list, return list of ODCLFIELD Node fn args. -func structargs(tl *types.Type, mustname bool) []*Node { - var args []*Node +func structargs(tl *types.Type, mustname bool) []*ir.Node { + var args []*ir.Node gen := 0 for _, t := range tl.Fields().Slice() { s := t.Sym @@ -1341,20 +1163,20 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { // Only generate (*T).M wrappers for T.M in T's own package. if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && - rcvr.Elem().Sym != nil && rcvr.Elem().Sym.Pkg != localpkg { + rcvr.Elem().Sym != nil && rcvr.Elem().Sym.Pkg != ir.LocalPkg { return } // Only generate I.M wrappers for I in I's own package // but keep doing it for error.Error (was issue #29304). - if rcvr.IsInterface() && rcvr.Sym != nil && rcvr.Sym.Pkg != localpkg && rcvr != types.Errortype { + if rcvr.IsInterface() && rcvr.Sym != nil && rcvr.Sym.Pkg != ir.LocalPkg && rcvr != types.Errortype { return } base.Pos = autogeneratedPos - dclcontext = PEXTERN + dclcontext = ir.PEXTERN - tfn := nod(OTFUNC, nil, nil) + tfn := ir.Nod(ir.OTFUNC, nil, nil) tfn.Left = namedfield(".this", rcvr) tfn.List.Set(structargs(method.Type.Params(), true)) tfn.Rlist.Set(structargs(method.Type.Results(), false)) @@ -1362,21 +1184,21 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { fn := dclfunc(newnam, tfn) fn.Func.SetDupok(true) - nthis := asNode(tfn.Type.Recv().Nname) + nthis := ir.AsNode(tfn.Type.Recv().Nname) methodrcvr := method.Type.Recv().Type // generate nil pointer check for better error if rcvr.IsPtr() && rcvr.Elem() == methodrcvr { // generating wrapper from *T to T. - n := nod(OIF, nil, nil) - n.Left = nod(OEQ, nthis, nodnil()) - call := nod(OCALL, syslook("panicwrap"), nil) + n := ir.Nod(ir.OIF, nil, nil) + n.Left = ir.Nod(ir.OEQ, nthis, nodnil()) + call := ir.Nod(ir.OCALL, syslook("panicwrap"), nil) n.Nbody.Set1(call) fn.Nbody.Append(n) } - dot := adddot(nodSym(OXDOT, nthis, method.Sym)) + dot := adddot(nodSym(ir.OXDOT, nthis, method.Sym)) // generate call // It's not possible to use a tail call when dynamic linking on ppc64le. The @@ -1390,18 +1212,18 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { dot = dot.Left // skip final .M // TODO(mdempsky): Remove dependency on dotlist. if !dotlist[0].field.Type.IsPtr() { - dot = nod(OADDR, dot, nil) + dot = ir.Nod(ir.OADDR, dot, nil) } - as := nod(OAS, nthis, convnop(dot, rcvr)) + as := ir.Nod(ir.OAS, nthis, convnop(dot, rcvr)) fn.Nbody.Append(as) - fn.Nbody.Append(nodSym(ORETJMP, nil, methodSym(methodrcvr, method.Sym))) + fn.Nbody.Append(nodSym(ir.ORETJMP, nil, methodSym(methodrcvr, method.Sym))) } else { fn.Func.SetWrapper(true) // ignore frame for panic+recover matching - call := nod(OCALL, dot, nil) + call := ir.Nod(ir.OCALL, dot, nil) call.List.Set(paramNnames(tfn.Type)) call.SetIsDDD(tfn.Type.IsVariadic()) if method.Type.NumResults() > 0 { - n := nod(ORETURN, nil, nil) + n := ir.Nod(ir.ORETURN, nil, nil) n.List.Set1(call) call = n } @@ -1409,7 +1231,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { } if false && base.Flag.LowerR != 0 { - dumplist("genwrapper body", fn.Nbody) + ir.DumpList("genwrapper body", fn.Nbody) } funcbody() @@ -1428,31 +1250,31 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) { if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym != nil { inlcalls(fn) } - escapeFuncs([]*Node{fn}, false) + escapeFuncs([]*ir.Node{fn}, false) Curfn = nil xtop = append(xtop, fn) } -func paramNnames(ft *types.Type) []*Node { - args := make([]*Node, ft.NumParams()) +func paramNnames(ft *types.Type) []*ir.Node { + args := make([]*ir.Node, ft.NumParams()) for i, f := range ft.Params().FieldSlice() { - args[i] = asNode(f.Nname) + args[i] = ir.AsNode(f.Nname) } return args } -func hashmem(t *types.Type) *Node { +func hashmem(t *types.Type) *ir.Node { sym := Runtimepkg.Lookup("memhash") - n := newname(sym) + n := NewName(sym) setNodeNameFunc(n) - n.Type = functype(nil, []*Node{ + n.Type = functype(nil, []*ir.Node{ anonfield(types.NewPtr(t)), - anonfield(types.Types[TUINTPTR]), - anonfield(types.Types[TUINTPTR]), - }, []*Node{ - anonfield(types.Types[TUINTPTR]), + anonfield(types.Types[types.TUINTPTR]), + anonfield(types.Types[types.TUINTPTR]), + }, []*ir.Node{ + anonfield(types.Types[types.TUINTPTR]), }) return n } @@ -1571,16 +1393,16 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool return true } -func listtreecopy(l []*Node, pos src.XPos) []*Node { - var out []*Node +func listtreecopy(l []*ir.Node, pos src.XPos) []*ir.Node { + var out []*ir.Node for _, n := range l { out = append(out, treecopy(n, pos)) } return out } -func liststmt(l []*Node) *Node { - n := nod(OBLOCK, nil, nil) +func liststmt(l []*ir.Node) *ir.Node { + n := ir.Nod(ir.OBLOCK, nil, nil) n.List.Set(l) if len(l) != 0 { n.Pos = l[0].Pos @@ -1588,7 +1410,7 @@ func liststmt(l []*Node) *Node { return n } -func ngotype(n *Node) *types.Sym { +func ngotype(n *ir.Node) *types.Sym { if n.Type != nil { return typenamesym(n.Type) } @@ -1597,13 +1419,13 @@ func ngotype(n *Node) *types.Sym { // The result of addinit MUST be assigned back to n, e.g. // n.Left = addinit(n.Left, init) -func addinit(n *Node, init []*Node) *Node { +func addinit(n *ir.Node, init []*ir.Node) *ir.Node { if len(init) == 0 { return n } - if n.mayBeShared() { + if ir.MayBeShared(n) { // Introduce OCONVNOP to hold init list. - n = nod(OCONVNOP, n, nil) + n = ir.Nod(ir.OCONVNOP, n, nil) n.Type = n.Left.Type n.SetTypecheck(1) } @@ -1674,20 +1496,20 @@ func isdirectiface(t *types.Type) bool { } switch t.Etype { - case TPTR: + case types.TPTR: // Pointers to notinheap types must be stored indirectly. See issue 42076. return !t.Elem().NotInHeap() - case TCHAN, - TMAP, - TFUNC, - TUNSAFEPTR: + case types.TCHAN, + types.TMAP, + types.TFUNC, + types.TUNSAFEPTR: return true - case TARRAY: + case types.TARRAY: // Array of 1 direct iface type can be direct. return t.NumElem() == 1 && isdirectiface(t.Elem()) - case TSTRUCT: + case types.TSTRUCT: // Struct with 1 field of direct iface type can be direct. return t.NumFields() == 1 && isdirectiface(t.Field(0).Type) } @@ -1696,9 +1518,9 @@ func isdirectiface(t *types.Type) bool { } // itabType loads the _type field from a runtime.itab struct. -func itabType(itab *Node) *Node { - typ := nodSym(ODOTPTR, itab, nil) - typ.Type = types.NewPtr(types.Types[TUINT8]) +func itabType(itab *ir.Node) *ir.Node { + typ := nodSym(ir.ODOTPTR, itab, nil) + typ.Type = types.NewPtr(types.Types[types.TUINT8]) typ.SetTypecheck(1) typ.Xoffset = int64(Widthptr) // offset of _type in runtime.itab typ.SetBounded(true) // guaranteed not to fault @@ -1708,11 +1530,11 @@ func itabType(itab *Node) *Node { // ifaceData loads the data field from an interface. // The concrete type must be known to have type t. // It follows the pointer if !isdirectiface(t). -func ifaceData(pos src.XPos, n *Node, t *types.Type) *Node { +func ifaceData(pos src.XPos, n *ir.Node, t *types.Type) *ir.Node { if t.IsInterface() { base.Fatalf("ifaceData interface: %v", t) } - ptr := nodlSym(pos, OIDATA, n, nil) + ptr := nodlSym(pos, ir.OIDATA, n, nil) if isdirectiface(t) { ptr.Type = t ptr.SetTypecheck(1) @@ -1720,7 +1542,7 @@ func ifaceData(pos src.XPos, n *Node, t *types.Type) *Node { } ptr.Type = types.NewPtr(t) ptr.SetTypecheck(1) - ind := nodl(pos, ODEREF, ptr, nil) + ind := ir.NodAt(pos, ir.ODEREF, ptr, nil) ind.Type = t ind.SetTypecheck(1) ind.SetBounded(true) @@ -1730,7 +1552,7 @@ func ifaceData(pos src.XPos, n *Node, t *types.Type) *Node { // typePos returns the position associated with t. // This is where t was declared or where it appeared as a type expression. func typePos(t *types.Type) src.XPos { - n := asNode(t.Nod) + n := ir.AsNode(t.Nod) if n == nil || !n.Pos.IsKnown() { base.Fatalf("bad type: %v", t) } diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go index 7befbdf06c1..f3195df79aa 100644 --- a/src/cmd/compile/internal/gc/swt.go +++ b/src/cmd/compile/internal/gc/swt.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/src" "go/constant" @@ -14,16 +15,16 @@ import ( ) // typecheckswitch typechecks a switch statement. -func typecheckswitch(n *Node) { +func typecheckswitch(n *ir.Node) { typecheckslice(n.Ninit.Slice(), ctxStmt) - if n.Left != nil && n.Left.Op == OTYPESW { + if n.Left != nil && n.Left.Op == ir.OTYPESW { typecheckTypeSwitch(n) } else { typecheckExprSwitch(n) } } -func typecheckTypeSwitch(n *Node) { +func typecheckTypeSwitch(n *ir.Node) { n.Left.Right = typecheck(n.Left.Right, ctxExpr) t := n.Left.Right.Type if t != nil && !t.IsInterface() { @@ -34,17 +35,17 @@ func typecheckTypeSwitch(n *Node) { // We don't actually declare the type switch's guarded // declaration itself. So if there are no cases, we won't // notice that it went unused. - if v := n.Left.Left; v != nil && !v.isBlank() && n.List.Len() == 0 { + if v := n.Left.Left; v != nil && !ir.IsBlank(v) && n.List.Len() == 0 { base.ErrorfAt(v.Pos, "%v declared but not used", v.Sym) } - var defCase, nilCase *Node + var defCase, nilCase *ir.Node var ts typeSet for _, ncase := range n.List.Slice() { ls := ncase.List.Slice() if len(ls) == 0 { // default: if defCase != nil { - base.ErrorfAt(ncase.Pos, "multiple defaults in switch (first at %v)", defCase.Line()) + base.ErrorfAt(ncase.Pos, "multiple defaults in switch (first at %v)", ir.Line(defCase)) } else { defCase = ncase } @@ -60,13 +61,13 @@ func typecheckTypeSwitch(n *Node) { var missing, have *types.Field var ptr int switch { - case n1.isNil(): // case nil: + case ir.IsNil(n1): // case nil: if nilCase != nil { - base.ErrorfAt(ncase.Pos, "multiple nil cases in type switch (first at %v)", nilCase.Line()) + base.ErrorfAt(ncase.Pos, "multiple nil cases in type switch (first at %v)", ir.Line(nilCase)) } else { nilCase = ncase } - case n1.Op != OTYPE: + case n1.Op != ir.OTYPE: base.ErrorfAt(ncase.Pos, "%L is not a type", n1) case !n1.Type.IsInterface() && !implements(n1.Type, t, &missing, &have, &ptr) && !missing.Broke(): if have != nil && !have.Broke() { @@ -81,7 +82,7 @@ func typecheckTypeSwitch(n *Node) { } } - if n1.Op == OTYPE { + if n1.Op == ir.OTYPE { ts.add(ncase.Pos, n1.Type) } } @@ -90,9 +91,9 @@ func typecheckTypeSwitch(n *Node) { // Assign the clause variable's type. vt := t if len(ls) == 1 { - if ls[0].Op == OTYPE { + if ls[0].Op == ir.OTYPE { vt = ls[0].Type - } else if !ls[0].isNil() { + } else if !ir.IsNil(ls[0]) { // Invalid single-type case; // mark variable as broken. vt = nil @@ -143,8 +144,8 @@ func (s *typeSet) add(pos src.XPos, typ *types.Type) { s.m[ls] = append(prevs, typeSetEntry{pos, typ}) } -func typecheckExprSwitch(n *Node) { - t := types.Types[TBOOL] +func typecheckExprSwitch(n *ir.Node) { + t := types.Types[types.TBOOL] if n.Left != nil { n.Left = typecheck(n.Left, ctxExpr) n.Left = defaultlit(n.Left, nil) @@ -156,7 +157,7 @@ func typecheckExprSwitch(n *Node) { switch { case t.IsMap(): nilonly = "map" - case t.Etype == TFUNC: + case t.Etype == types.TFUNC: nilonly = "func" case t.IsSlice(): nilonly = "slice" @@ -171,13 +172,13 @@ func typecheckExprSwitch(n *Node) { } } - var defCase *Node + var defCase *ir.Node var cs constSet for _, ncase := range n.List.Slice() { ls := ncase.List.Slice() if len(ls) == 0 { // default: if defCase != nil { - base.ErrorfAt(ncase.Pos, "multiple defaults in switch (first at %v)", defCase.Line()) + base.ErrorfAt(ncase.Pos, "multiple defaults in switch (first at %v)", ir.Line(defCase)) } else { defCase = ncase } @@ -192,14 +193,14 @@ func typecheckExprSwitch(n *Node) { continue } - if nilonly != "" && !n1.isNil() { + if nilonly != "" && !ir.IsNil(n1) { base.ErrorfAt(ncase.Pos, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left) } else if t.IsInterface() && !n1.Type.IsInterface() && !IsComparable(n1.Type) { base.ErrorfAt(ncase.Pos, "invalid case %L in switch (incomparable type)", n1) } else { op1, _ := assignop(n1.Type, t) op2, _ := assignop(t, n1.Type) - if op1 == OXXX && op2 == OXXX { + if op1 == ir.OXXX && op2 == ir.OXXX { if n.Left != nil { base.ErrorfAt(ncase.Pos, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t) } else { @@ -224,13 +225,13 @@ func typecheckExprSwitch(n *Node) { } // walkswitch walks a switch statement. -func walkswitch(sw *Node) { +func walkswitch(sw *ir.Node) { // Guard against double walk, see #25776. if sw.List.Len() == 0 && sw.Nbody.Len() > 0 { return // Was fatal, but eliminating every possible source of double-walking is hard } - if sw.Left != nil && sw.Left.Op == OTYPESW { + if sw.Left != nil && sw.Left.Op == ir.OTYPESW { walkTypeSwitch(sw) } else { walkExprSwitch(sw) @@ -239,7 +240,7 @@ func walkswitch(sw *Node) { // walkExprSwitch generates an AST implementing sw. sw is an // expression switch. -func walkExprSwitch(sw *Node) { +func walkExprSwitch(sw *ir.Node) { lno := setlineno(sw) cond := sw.Left @@ -259,12 +260,12 @@ func walkExprSwitch(sw *Node) { // because walkexpr will lower the string // conversion into a runtime call. // See issue 24937 for more discussion. - if cond.Op == OBYTES2STR && allCaseExprsAreSideEffectFree(sw) { - cond.Op = OBYTES2STRTMP + if cond.Op == ir.OBYTES2STR && allCaseExprsAreSideEffectFree(sw) { + cond.Op = ir.OBYTES2STRTMP } cond = walkexpr(cond, &sw.Ninit) - if cond.Op != OLITERAL && cond.Op != ONIL { + if cond.Op != ir.OLITERAL && cond.Op != ir.ONIL { cond = copyexpr(cond, cond.Type, &sw.Nbody) } @@ -274,11 +275,11 @@ func walkExprSwitch(sw *Node) { exprname: cond, } - var defaultGoto *Node - var body Nodes + var defaultGoto *ir.Node + var body ir.Nodes for _, ncase := range sw.List.Slice() { label := autolabel(".s") - jmp := npos(ncase.Pos, nodSym(OGOTO, nil, label)) + jmp := npos(ncase.Pos, nodSym(ir.OGOTO, nil, label)) // Process case dispatch. if ncase.List.Len() == 0 { @@ -293,10 +294,10 @@ func walkExprSwitch(sw *Node) { } // Process body. - body.Append(npos(ncase.Pos, nodSym(OLABEL, nil, label))) + body.Append(npos(ncase.Pos, nodSym(ir.OLABEL, nil, label))) body.Append(ncase.Nbody.Slice()...) if fall, pos := hasFall(ncase.Nbody.Slice()); !fall { - br := nod(OBREAK, nil, nil) + br := ir.Nod(ir.OBREAK, nil, nil) br.Pos = pos body.Append(br) } @@ -304,7 +305,7 @@ func walkExprSwitch(sw *Node) { sw.List.Set(nil) if defaultGoto == nil { - br := nod(OBREAK, nil, nil) + br := ir.Nod(ir.OBREAK, nil, nil) br.Pos = br.Pos.WithNotStmt() defaultGoto = br } @@ -317,21 +318,21 @@ func walkExprSwitch(sw *Node) { // An exprSwitch walks an expression switch. type exprSwitch struct { - exprname *Node // value being switched on + exprname *ir.Node // value being switched on - done Nodes + done ir.Nodes clauses []exprClause } type exprClause struct { pos src.XPos - lo, hi *Node - jmp *Node + lo, hi *ir.Node + jmp *ir.Node } -func (s *exprSwitch) Add(pos src.XPos, expr, jmp *Node) { +func (s *exprSwitch) Add(pos src.XPos, expr, jmp *ir.Node) { c := exprClause{pos: pos, lo: expr, hi: expr, jmp: jmp} - if okforcmp[s.exprname.Type.Etype] && expr.Op == OLITERAL { + if okforcmp[s.exprname.Type.Etype] && expr.Op == ir.OLITERAL { s.clauses = append(s.clauses, c) return } @@ -341,7 +342,7 @@ func (s *exprSwitch) Add(pos src.XPos, expr, jmp *Node) { s.flush() } -func (s *exprSwitch) Emit(out *Nodes) { +func (s *exprSwitch) Emit(out *ir.Nodes) { s.flush() out.AppendNodes(&s.done) } @@ -389,12 +390,12 @@ func (s *exprSwitch) flush() { // Perform two-level binary search. binarySearch(len(runs), &s.done, - func(i int) *Node { - return nod(OLE, nod(OLEN, s.exprname, nil), nodintconst(runLen(runs[i-1]))) + func(i int) *ir.Node { + return ir.Nod(ir.OLE, ir.Nod(ir.OLEN, s.exprname, nil), nodintconst(runLen(runs[i-1]))) }, - func(i int, nif *Node) { + func(i int, nif *ir.Node) { run := runs[i] - nif.Left = nod(OEQ, nod(OLEN, s.exprname, nil), nodintconst(runLen(run))) + nif.Left = ir.Nod(ir.OEQ, ir.Nod(ir.OLEN, s.exprname, nil), nodintconst(runLen(run))) s.search(run, &nif.Nbody) }, ) @@ -422,12 +423,12 @@ func (s *exprSwitch) flush() { s.search(cc, &s.done) } -func (s *exprSwitch) search(cc []exprClause, out *Nodes) { +func (s *exprSwitch) search(cc []exprClause, out *ir.Nodes) { binarySearch(len(cc), out, - func(i int) *Node { - return nod(OLE, s.exprname, cc[i-1].hi) + func(i int) *ir.Node { + return ir.Nod(ir.OLE, s.exprname, cc[i-1].hi) }, - func(i int, nif *Node) { + func(i int, nif *ir.Node) { c := &cc[i] nif.Left = c.test(s.exprname) nif.Nbody.Set1(c.jmp) @@ -435,27 +436,27 @@ func (s *exprSwitch) search(cc []exprClause, out *Nodes) { ) } -func (c *exprClause) test(exprname *Node) *Node { +func (c *exprClause) test(exprname *ir.Node) *ir.Node { // Integer range. if c.hi != c.lo { - low := nodl(c.pos, OGE, exprname, c.lo) - high := nodl(c.pos, OLE, exprname, c.hi) - return nodl(c.pos, OANDAND, low, high) + low := ir.NodAt(c.pos, ir.OGE, exprname, c.lo) + high := ir.NodAt(c.pos, ir.OLE, exprname, c.hi) + return ir.NodAt(c.pos, ir.OANDAND, low, high) } // Optimize "switch true { ...}" and "switch false { ... }". - if Isconst(exprname, constant.Bool) && !c.lo.Type.IsInterface() { + if ir.IsConst(exprname, constant.Bool) && !c.lo.Type.IsInterface() { if exprname.BoolVal() { return c.lo } else { - return nodl(c.pos, ONOT, c.lo, nil) + return ir.NodAt(c.pos, ir.ONOT, c.lo, nil) } } - return nodl(c.pos, OEQ, exprname, c.lo) + return ir.NodAt(c.pos, ir.OEQ, exprname, c.lo) } -func allCaseExprsAreSideEffectFree(sw *Node) bool { +func allCaseExprsAreSideEffectFree(sw *ir.Node) bool { // In theory, we could be more aggressive, allowing any // side-effect-free expressions in cases, but it's a bit // tricky because some of that information is unavailable due @@ -464,11 +465,11 @@ func allCaseExprsAreSideEffectFree(sw *Node) bool { // enough. for _, ncase := range sw.List.Slice() { - if ncase.Op != OCASE { + if ncase.Op != ir.OCASE { base.Fatalf("switch string(byteslice) bad op: %v", ncase.Op) } for _, v := range ncase.List.Slice() { - if v.Op != OLITERAL { + if v.Op != ir.OLITERAL { return false } } @@ -477,7 +478,7 @@ func allCaseExprsAreSideEffectFree(sw *Node) bool { } // hasFall reports whether stmts ends with a "fallthrough" statement. -func hasFall(stmts []*Node) (bool, src.XPos) { +func hasFall(stmts []*ir.Node) (bool, src.XPos) { // Search backwards for the index of the fallthrough // statement. Do not assume it'll be in the last // position, since in some cases (e.g. when the statement @@ -485,30 +486,30 @@ func hasFall(stmts []*Node) (bool, src.XPos) { // nodes will be at the end of the list. i := len(stmts) - 1 - for i >= 0 && stmts[i].Op == OVARKILL { + for i >= 0 && stmts[i].Op == ir.OVARKILL { i-- } if i < 0 { return false, src.NoXPos } - return stmts[i].Op == OFALL, stmts[i].Pos + return stmts[i].Op == ir.OFALL, stmts[i].Pos } // walkTypeSwitch generates an AST that implements sw, where sw is a // type switch. -func walkTypeSwitch(sw *Node) { +func walkTypeSwitch(sw *ir.Node) { var s typeSwitch s.facename = sw.Left.Right sw.Left = nil s.facename = walkexpr(s.facename, &sw.Ninit) s.facename = copyexpr(s.facename, s.facename.Type, &sw.Nbody) - s.okname = temp(types.Types[TBOOL]) + s.okname = temp(types.Types[types.TBOOL]) // Get interface descriptor word. // For empty interfaces this will be the type. // For non-empty interfaces this will be the itab. - itab := nod(OITAB, s.facename, nil) + itab := ir.Nod(ir.OITAB, s.facename, nil) // For empty interfaces, do: // if e._type == nil { @@ -516,8 +517,8 @@ func walkTypeSwitch(sw *Node) { // } // h := e._type.hash // Use a similar strategy for non-empty interfaces. - ifNil := nod(OIF, nil, nil) - ifNil.Left = nod(OEQ, itab, nodnil()) + ifNil := ir.Nod(ir.OIF, nil, nil) + ifNil.Left = ir.Nod(ir.OEQ, itab, nodnil()) base.Pos = base.Pos.WithNotStmt() // disable statement marks after the first check. ifNil.Left = typecheck(ifNil.Left, ctxExpr) ifNil.Left = defaultlit(ifNil.Left, nil) @@ -525,8 +526,8 @@ func walkTypeSwitch(sw *Node) { sw.Nbody.Append(ifNil) // Load hash from type or itab. - dotHash := nodSym(ODOTPTR, itab, nil) - dotHash.Type = types.Types[TUINT32] + dotHash := nodSym(ir.ODOTPTR, itab, nil) + dotHash.Type = types.Types[types.TUINT32] dotHash.SetTypecheck(1) if s.facename.Type.IsEmptyInterface() { dotHash.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type @@ -536,11 +537,11 @@ func walkTypeSwitch(sw *Node) { dotHash.SetBounded(true) // guaranteed not to fault s.hashname = copyexpr(dotHash, dotHash.Type, &sw.Nbody) - br := nod(OBREAK, nil, nil) - var defaultGoto, nilGoto *Node - var body Nodes + br := ir.Nod(ir.OBREAK, nil, nil) + var defaultGoto, nilGoto *ir.Node + var body ir.Nodes for _, ncase := range sw.List.Slice() { - var caseVar *Node + var caseVar *ir.Node if ncase.Rlist.Len() != 0 { caseVar = ncase.Rlist.First() } @@ -549,13 +550,13 @@ func walkTypeSwitch(sw *Node) { // we initialize the case variable as part of the type assertion. // In other cases, we initialize it in the body. var singleType *types.Type - if ncase.List.Len() == 1 && ncase.List.First().Op == OTYPE { + if ncase.List.Len() == 1 && ncase.List.First().Op == ir.OTYPE { singleType = ncase.List.First().Type } caseVarInitialized := false label := autolabel(".s") - jmp := npos(ncase.Pos, nodSym(OGOTO, nil, label)) + jmp := npos(ncase.Pos, nodSym(ir.OGOTO, nil, label)) if ncase.List.Len() == 0 { // default: if defaultGoto != nil { @@ -565,7 +566,7 @@ func walkTypeSwitch(sw *Node) { } for _, n1 := range ncase.List.Slice() { - if n1.isNil() { // case nil: + if ir.IsNil(n1) { // case nil: if nilGoto != nil { base.Fatalf("duplicate nil case not detected during typechecking") } @@ -581,7 +582,7 @@ func walkTypeSwitch(sw *Node) { } } - body.Append(npos(ncase.Pos, nodSym(OLABEL, nil, label))) + body.Append(npos(ncase.Pos, nodSym(ir.OLABEL, nil, label))) if caseVar != nil && !caseVarInitialized { val := s.facename if singleType != nil { @@ -591,9 +592,9 @@ func walkTypeSwitch(sw *Node) { } val = ifaceData(ncase.Pos, s.facename, singleType) } - l := []*Node{ - nodl(ncase.Pos, ODCL, caseVar, nil), - nodl(ncase.Pos, OAS, caseVar, val), + l := []*ir.Node{ + ir.NodAt(ncase.Pos, ir.ODCL, caseVar, nil), + ir.NodAt(ncase.Pos, ir.OAS, caseVar, val), } typecheckslice(l, ctxStmt) body.Append(l...) @@ -621,36 +622,36 @@ func walkTypeSwitch(sw *Node) { // A typeSwitch walks a type switch. type typeSwitch struct { // Temporary variables (i.e., ONAMEs) used by type switch dispatch logic: - facename *Node // value being type-switched on - hashname *Node // type hash of the value being type-switched on - okname *Node // boolean used for comma-ok type assertions + facename *ir.Node // value being type-switched on + hashname *ir.Node // type hash of the value being type-switched on + okname *ir.Node // boolean used for comma-ok type assertions - done Nodes + done ir.Nodes clauses []typeClause } type typeClause struct { hash uint32 - body Nodes + body ir.Nodes } -func (s *typeSwitch) Add(pos src.XPos, typ *types.Type, caseVar, jmp *Node) { - var body Nodes +func (s *typeSwitch) Add(pos src.XPos, typ *types.Type, caseVar, jmp *ir.Node) { + var body ir.Nodes if caseVar != nil { - l := []*Node{ - nodl(pos, ODCL, caseVar, nil), - nodl(pos, OAS, caseVar, nil), + l := []*ir.Node{ + ir.NodAt(pos, ir.ODCL, caseVar, nil), + ir.NodAt(pos, ir.OAS, caseVar, nil), } typecheckslice(l, ctxStmt) body.Append(l...) } else { - caseVar = nblank + caseVar = ir.BlankNode } // cv, ok = iface.(type) - as := nodl(pos, OAS2, nil, nil) + as := ir.NodAt(pos, ir.OAS2, nil, nil) as.List.Set2(caseVar, s.okname) // cv, ok = - dot := nodl(pos, ODOTTYPE, s.facename, nil) + dot := ir.NodAt(pos, ir.ODOTTYPE, s.facename, nil) dot.Type = typ // iface.(type) as.Rlist.Set1(dot) as = typecheck(as, ctxStmt) @@ -658,7 +659,7 @@ func (s *typeSwitch) Add(pos src.XPos, typ *types.Type, caseVar, jmp *Node) { body.Append(as) // if ok { goto label } - nif := nodl(pos, OIF, nil, nil) + nif := ir.NodAt(pos, ir.OIF, nil, nil) nif.Left = s.okname nif.Nbody.Set1(jmp) body.Append(nif) @@ -675,7 +676,7 @@ func (s *typeSwitch) Add(pos src.XPos, typ *types.Type, caseVar, jmp *Node) { s.done.AppendNodes(&body) } -func (s *typeSwitch) Emit(out *Nodes) { +func (s *typeSwitch) Emit(out *ir.Nodes) { s.flush() out.AppendNodes(&s.done) } @@ -702,14 +703,14 @@ func (s *typeSwitch) flush() { cc = merged binarySearch(len(cc), &s.done, - func(i int) *Node { - return nod(OLE, s.hashname, nodintconst(int64(cc[i-1].hash))) + func(i int) *ir.Node { + return ir.Nod(ir.OLE, s.hashname, nodintconst(int64(cc[i-1].hash))) }, - func(i int, nif *Node) { + func(i int, nif *ir.Node) { // TODO(mdempsky): Omit hash equality check if // there's only one type. c := cc[i] - nif.Left = nod(OEQ, s.hashname, nodintconst(int64(c.hash))) + nif.Left = ir.Nod(ir.OEQ, s.hashname, nodintconst(int64(c.hash))) nif.Nbody.AppendNodes(&c.body) }, ) @@ -724,15 +725,15 @@ func (s *typeSwitch) flush() { // // leaf(i, nif) should setup nif (an OIF node) to test case i. In // particular, it should set nif.Left and nif.Nbody. -func binarySearch(n int, out *Nodes, less func(i int) *Node, leaf func(i int, nif *Node)) { +func binarySearch(n int, out *ir.Nodes, less func(i int) *ir.Node, leaf func(i int, nif *ir.Node)) { const binarySearchMin = 4 // minimum number of cases for binary search - var do func(lo, hi int, out *Nodes) - do = func(lo, hi int, out *Nodes) { + var do func(lo, hi int, out *ir.Nodes) + do = func(lo, hi int, out *ir.Nodes) { n := hi - lo if n < binarySearchMin { for i := lo; i < hi; i++ { - nif := nod(OIF, nil, nil) + nif := ir.Nod(ir.OIF, nil, nil) leaf(i, nif) base.Pos = base.Pos.WithNotStmt() nif.Left = typecheck(nif.Left, ctxExpr) @@ -744,7 +745,7 @@ func binarySearch(n int, out *Nodes, less func(i int) *Node, leaf func(i int, ni } half := lo + n/2 - nif := nod(OIF, nil, nil) + nif := ir.Nod(ir.OIF, nil, nil) nif.Left = less(half) base.Pos = base.Pos.WithNotStmt() nif.Left = typecheck(nif.Left, ctxExpr) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index b61b9b05258..78fdf100ad2 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "fmt" "go/constant" @@ -19,7 +20,7 @@ const enableTrace = false var traceIndent []byte var skipDowidthForTracing bool -func tracePrint(title string, n *Node) func(np **Node) { +func tracePrint(title string, n *ir.Node) func(np **ir.Node) { indent := traceIndent // guard against nil @@ -36,7 +37,7 @@ func tracePrint(title string, n *Node) func(np **Node) { fmt.Printf("%s: %s%s %p %s %v tc=%d\n", pos, indent, title, n, op, n, tc) traceIndent = append(traceIndent, ". "...) - return func(np **Node) { + return func(np **ir.Node) { traceIndent = traceIndent[:len(traceIndent)-2] // if we have a result, use that @@ -76,11 +77,11 @@ const ( // marks variables that escape the local frame. // rewrites n.Op to be more specific in some cases. -var typecheckdefstack []*Node +var typecheckdefstack []*ir.Node // resolve ONONAME to definition, if any. -func resolve(n *Node) (res *Node) { - if n == nil || n.Op != ONONAME { +func resolve(n *ir.Node) (res *ir.Node) { + if n == nil || n.Op != ir.ONONAME { return n } @@ -89,7 +90,7 @@ func resolve(n *Node) (res *Node) { defer tracePrint("resolve", n)(&res) } - if n.Sym.Pkg != localpkg { + if n.Sym.Pkg != ir.LocalPkg { if inimport { base.Fatalf("recursive inimport") } @@ -99,12 +100,12 @@ func resolve(n *Node) (res *Node) { return n } - r := asNode(n.Sym.Def) + r := ir.AsNode(n.Sym.Def) if r == nil { return n } - if r.Op == OIOTA { + if r.Op == ir.OIOTA { if x := getIotaValue(); x >= 0 { return nodintconst(x) } @@ -114,41 +115,41 @@ func resolve(n *Node) (res *Node) { return r } -func typecheckslice(l []*Node, top int) { +func typecheckslice(l []*ir.Node, top int) { for i := range l { l[i] = typecheck(l[i], top) } } var _typekind = []string{ - TINT: "int", - TUINT: "uint", - TINT8: "int8", - TUINT8: "uint8", - TINT16: "int16", - TUINT16: "uint16", - TINT32: "int32", - TUINT32: "uint32", - TINT64: "int64", - TUINT64: "uint64", - TUINTPTR: "uintptr", - TCOMPLEX64: "complex64", - TCOMPLEX128: "complex128", - TFLOAT32: "float32", - TFLOAT64: "float64", - TBOOL: "bool", - TSTRING: "string", - TPTR: "pointer", - TUNSAFEPTR: "unsafe.Pointer", - TSTRUCT: "struct", - TINTER: "interface", - TCHAN: "chan", - TMAP: "map", - TARRAY: "array", - TSLICE: "slice", - TFUNC: "func", - TNIL: "nil", - TIDEAL: "untyped number", + types.TINT: "int", + types.TUINT: "uint", + types.TINT8: "int8", + types.TUINT8: "uint8", + types.TINT16: "int16", + types.TUINT16: "uint16", + types.TINT32: "int32", + types.TUINT32: "uint32", + types.TINT64: "int64", + types.TUINT64: "uint64", + types.TUINTPTR: "uintptr", + types.TCOMPLEX64: "complex64", + types.TCOMPLEX128: "complex128", + types.TFLOAT32: "float32", + types.TFLOAT64: "float64", + types.TBOOL: "bool", + types.TSTRING: "string", + types.TPTR: "pointer", + types.TUNSAFEPTR: "unsafe.Pointer", + types.TSTRUCT: "struct", + types.TINTER: "interface", + types.TCHAN: "chan", + types.TMAP: "map", + types.TARRAY: "array", + types.TSLICE: "slice", + types.TFUNC: "func", + types.TNIL: "nil", + types.TIDEAL: "untyped number", } func typekind(t *types.Type) string { @@ -165,7 +166,7 @@ func typekind(t *types.Type) string { return fmt.Sprintf("etype=%d", et) } -func cycleFor(start *Node) []*Node { +func cycleFor(start *ir.Node) []*ir.Node { // Find the start node in typecheck_tcstack. // We know that it must exist because each time we mark // a node with n.SetTypecheck(2) we push it on the stack, @@ -178,7 +179,7 @@ func cycleFor(start *Node) []*Node { } // collect all nodes with same Op - var cycle []*Node + var cycle []*ir.Node for _, n := range typecheck_tcstack[i:] { if n.Op == start.Op { cycle = append(cycle, n) @@ -188,20 +189,20 @@ func cycleFor(start *Node) []*Node { return cycle } -func cycleTrace(cycle []*Node) string { +func cycleTrace(cycle []*ir.Node) string { var s string for i, n := range cycle { - s += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cycle[(i+1)%len(cycle)]) + s += fmt.Sprintf("\n\t%v: %v uses %v", ir.Line(n), n, cycle[(i+1)%len(cycle)]) } return s } -var typecheck_tcstack []*Node +var typecheck_tcstack []*ir.Node // typecheck type checks node n. // The result of typecheck MUST be assigned back to n, e.g. // n.Left = typecheck(n.Left, top) -func typecheck(n *Node, top int) (res *Node) { +func typecheck(n *ir.Node, top int) (res *ir.Node) { // cannot type check until all the source has been parsed if !typecheckok { base.Fatalf("early typecheck") @@ -219,7 +220,7 @@ func typecheck(n *Node, top int) (res *Node) { lno := setlineno(n) // Skip over parens. - for n.Op == OPAREN { + for n.Op == ir.OPAREN { n = n.Left } @@ -230,7 +231,7 @@ func typecheck(n *Node, top int) (res *Node) { // But re-typecheck ONAME/OTYPE/OLITERAL/OPACK node in case context has changed. if n.Typecheck() == 1 { switch n.Op { - case ONAME, OTYPE, OLITERAL, OPACK: + case ir.ONAME, ir.OTYPE, ir.OLITERAL, ir.OPACK: break default: @@ -244,12 +245,12 @@ func typecheck(n *Node, top int) (res *Node) { // otherwise a stack trace of typechecking. switch n.Op { // We can already diagnose variables used as types. - case ONAME: + case ir.ONAME: if top&(ctxExpr|ctxType) == ctxType { base.Errorf("%v is not a type", n) } - case OTYPE: + case ir.OTYPE: // Only report a type cycle if we are expecting a type. // Otherwise let other code report an error. if top&ctxType == ctxType { @@ -274,7 +275,7 @@ func typecheck(n *Node, top int) (res *Node) { base.ErrorfAt(n.Pos, "invalid recursive type alias %v%s", n, cycleTrace(cycle)) } - case OLITERAL: + case ir.OLITERAL: if top&(ctxExpr|ctxType) == ctxType { base.Errorf("%v is not a type", n) break @@ -286,7 +287,7 @@ func typecheck(n *Node, top int) (res *Node) { var trace string for i := len(typecheck_tcstack) - 1; i >= 0; i-- { x := typecheck_tcstack[i] - trace += fmt.Sprintf("\n\t%v %v", x.Line(), x) + trace += fmt.Sprintf("\n\t%v %v", ir.Line(x), x) } base.Errorf("typechecking loop involving %v%s", n, trace) } @@ -316,34 +317,34 @@ func typecheck(n *Node, top int) (res *Node) { // value of type int (see also checkmake for comparison). // The result of indexlit MUST be assigned back to n, e.g. // n.Left = indexlit(n.Left) -func indexlit(n *Node) *Node { - if n != nil && n.Type != nil && n.Type.Etype == TIDEAL { - return defaultlit(n, types.Types[TINT]) +func indexlit(n *ir.Node) *ir.Node { + if n != nil && n.Type != nil && n.Type.Etype == types.TIDEAL { + return defaultlit(n, types.Types[types.TINT]) } return n } // The result of typecheck1 MUST be assigned back to n, e.g. // n.Left = typecheck1(n.Left, top) -func typecheck1(n *Node, top int) (res *Node) { +func typecheck1(n *ir.Node, top int) (res *ir.Node) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheck1", n)(&res) } switch n.Op { - case OLITERAL, ONAME, ONONAME, OTYPE: + case ir.OLITERAL, ir.ONAME, ir.ONONAME, ir.OTYPE: if n.Sym == nil { break } - if n.Op == ONAME && n.SubOp() != 0 && top&ctxCallee == 0 { + if n.Op == ir.ONAME && n.SubOp() != 0 && top&ctxCallee == 0 { base.Errorf("use of builtin %v not in function call", n.Sym) n.Type = nil return n } typecheckdef(n) - if n.Op == ONONAME { + if n.Op == ir.ONONAME { n.Type = nil return n } @@ -353,22 +354,22 @@ func typecheck1(n *Node, top int) (res *Node) { switch n.Op { // until typecheck is complete, do nothing. default: - Dump("typecheck", n) + ir.Dump("typecheck", n) base.Fatalf("typecheck %v", n.Op) // names - case OLITERAL: + case ir.OLITERAL: ok |= ctxExpr if n.Type == nil && n.Val().Kind() == constant.String { base.Fatalf("string literal missing type") } - case ONIL, ONONAME: + case ir.ONIL, ir.ONONAME: ok |= ctxExpr - case ONAME: + case ir.ONAME: if n.Name.Decldepth == 0 { n.Name.Decldepth = decldepth } @@ -379,7 +380,7 @@ func typecheck1(n *Node, top int) (res *Node) { if top&ctxAssign == 0 { // not a write to the variable - if n.isBlank() { + if ir.IsBlank(n) { base.Errorf("cannot use _ as value") n.Type = nil return n @@ -390,23 +391,23 @@ func typecheck1(n *Node, top int) (res *Node) { ok |= ctxExpr - case OPACK: + case ir.OPACK: base.Errorf("use of package %v without selector", n.Sym) n.Type = nil return n - case ODDD: + case ir.ODDD: break // types (ODEREF is with exprs) - case OTYPE: + case ir.OTYPE: ok |= ctxType if n.Type == nil { return n } - case OTARRAY: + case ir.OTARRAY: ok |= ctxType r := typecheck(n.Right, ctxType) if r.Type == nil { @@ -417,7 +418,7 @@ func typecheck1(n *Node, top int) (res *Node) { var t *types.Type if n.Left == nil { t = types.NewSlice(r.Type) - } else if n.Left.Op == ODDD { + } else if n.Left.Op == ir.ODDD { if !n.Diag() { n.SetDiag(true) base.Errorf("use of [...] array outside of array literal") @@ -427,11 +428,11 @@ func typecheck1(n *Node, top int) (res *Node) { } else { n.Left = indexlit(typecheck(n.Left, ctxExpr)) l := n.Left - if consttype(l) != constant.Int { + if ir.ConstType(l) != constant.Int { switch { case l.Type == nil: // Error already reported elsewhere. - case l.Type.IsInteger() && l.Op != OLITERAL: + case l.Type.IsInteger() && l.Op != ir.OLITERAL: base.Errorf("non-constant array bound %v", l) default: base.Errorf("invalid array bound %v", l) @@ -441,7 +442,7 @@ func typecheck1(n *Node, top int) (res *Node) { } v := l.Val() - if doesoverflow(v, types.Types[TINT]) { + if doesoverflow(v, types.Types[types.TINT]) { base.Errorf("array bound is too large") n.Type = nil return n @@ -462,7 +463,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Right = nil checkwidth(t) - case OTMAP: + case ir.OTMAP: ok |= ctxType n.Left = typecheck(n.Left, ctxType) n.Right = typecheck(n.Right, ctxType) @@ -484,7 +485,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Left = nil n.Right = nil - case OTCHAN: + case ir.OTCHAN: ok |= ctxType n.Left = typecheck(n.Left, ctxType) l := n.Left @@ -500,16 +501,16 @@ func typecheck1(n *Node, top int) (res *Node) { n.Left = nil n.ResetAux() - case OTSTRUCT: + case ir.OTSTRUCT: ok |= ctxType setTypeNode(n, tostruct(n.List.Slice())) n.List.Set(nil) - case OTINTER: + case ir.OTINTER: ok |= ctxType setTypeNode(n, tointerface(n.List.Slice())) - case OTFUNC: + case ir.OTFUNC: ok |= ctxType setTypeNode(n, functype(n.Left, n.List.Slice(), n.Rlist.Slice())) n.Left = nil @@ -517,7 +518,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Rlist.Set(nil) // type or expr - case ODEREF: + case ir.ODEREF: n.Left = typecheck(n.Left, ctxExpr|ctxType) l := n.Left t := l.Type @@ -525,7 +526,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n } - if l.Op == OTYPE { + if l.Op == ir.OTYPE { ok |= ctxType setTypeNode(n, types.NewPtr(l.Type)) n.Left = nil @@ -548,30 +549,30 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = t.Elem() // arithmetic exprs - case OASOP, - OADD, - OAND, - OANDAND, - OANDNOT, - ODIV, - OEQ, - OGE, - OGT, - OLE, - OLT, - OLSH, - ORSH, - OMOD, - OMUL, - ONE, - OOR, - OOROR, - OSUB, - OXOR: - var l *Node - var op Op - var r *Node - if n.Op == OASOP { + case ir.OASOP, + ir.OADD, + ir.OAND, + ir.OANDAND, + ir.OANDNOT, + ir.ODIV, + ir.OEQ, + ir.OGE, + ir.OGT, + ir.OLE, + ir.OLT, + ir.OLSH, + ir.ORSH, + ir.OMOD, + ir.OMUL, + ir.ONE, + ir.OOR, + ir.OOROR, + ir.OSUB, + ir.OXOR: + var l *ir.Node + var op ir.Op + var r *ir.Node + if n.Op == ir.OASOP { ok |= ctxStmt n.Left = typecheck(n.Left, ctxExpr) n.Right = typecheck(n.Right, ctxExpr) @@ -601,8 +602,8 @@ func typecheck1(n *Node, top int) (res *Node) { } op = n.Op } - if op == OLSH || op == ORSH { - r = defaultlit(r, types.Types[TUINT]) + if op == ir.OLSH || op == ir.ORSH { + r = defaultlit(r, types.Types[types.TUINT]) n.Right = r t := r.Type if !t.IsInteger() { @@ -616,7 +617,7 @@ func typecheck1(n *Node, top int) (res *Node) { return n } t = l.Type - if t != nil && t.Etype != TIDEAL && !t.IsInteger() { + if t != nil && t.Etype != types.TIDEAL && !t.IsInteger() { base.Errorf("invalid operation: %v (shift of type %v)", n, t) n.Type = nil return n @@ -625,7 +626,7 @@ func typecheck1(n *Node, top int) (res *Node) { // no defaultlit for left // the outer context gives the type n.Type = l.Type - if (l.Type == types.UntypedFloat || l.Type == types.UntypedComplex) && r.Op == OLITERAL { + if (l.Type == types.UntypedFloat || l.Type == types.UntypedComplex) && r.Op == ir.OLITERAL { n.Type = types.UntypedInt } @@ -635,7 +636,7 @@ func typecheck1(n *Node, top int) (res *Node) { // For "x == x && len(s)", it's better to report that "len(s)" (type int) // can't be used with "&&" than to report that "x == x" (type untyped bool) // can't be converted to int (see issue #41500). - if n.Op == OANDAND || n.Op == OOROR { + if n.Op == ir.OANDAND || n.Op == ir.OOROR { if !n.Left.Type.IsBoolean() { base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, n.Op, typekind(n.Left.Type)) n.Type = nil @@ -658,15 +659,15 @@ func typecheck1(n *Node, top int) (res *Node) { return n } t := l.Type - if t.Etype == TIDEAL { + if t.Etype == types.TIDEAL { t = r.Type } et := t.Etype - if et == TIDEAL { - et = TINT + if et == types.TIDEAL { + et = types.TINT } - aop := OXXX - if iscmp[n.Op] && t.Etype != TIDEAL && !types.Identical(l.Type, r.Type) { + aop := ir.OXXX + if iscmp[n.Op] && t.Etype != types.TIDEAL && !types.Identical(l.Type, r.Type) { // comparison is okay as long as one side is // assignable to the other. convert so they have // the same type. @@ -675,9 +676,9 @@ func typecheck1(n *Node, top int) (res *Node) { // in that case, check comparability of the concrete type. // The conversion allocates, so only do it if the concrete type is huge. converted := false - if r.Type.Etype != TBLANK { + if r.Type.Etype != types.TBLANK { aop, _ = assignop(l.Type, r.Type) - if aop != OXXX { + if aop != ir.OXXX { if r.Type.IsInterface() && !l.Type.IsInterface() && !IsComparable(l.Type) { base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(l.Type)) n.Type = nil @@ -686,7 +687,7 @@ func typecheck1(n *Node, top int) (res *Node) { dowidth(l.Type) if r.Type.IsInterface() == l.Type.IsInterface() || l.Type.Width >= 1<<16 { - l = nod(aop, l, nil) + l = ir.Nod(aop, l, nil) l.Type = r.Type l.SetTypecheck(1) n.Left = l @@ -697,9 +698,9 @@ func typecheck1(n *Node, top int) (res *Node) { } } - if !converted && l.Type.Etype != TBLANK { + if !converted && l.Type.Etype != types.TBLANK { aop, _ = assignop(r.Type, l.Type) - if aop != OXXX { + if aop != ir.OXXX { if l.Type.IsInterface() && !r.Type.IsInterface() && !IsComparable(r.Type) { base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(r.Type)) n.Type = nil @@ -708,7 +709,7 @@ func typecheck1(n *Node, top int) (res *Node) { dowidth(r.Type) if r.Type.IsInterface() == l.Type.IsInterface() || r.Type.Width >= 1<<16 { - r = nod(aop, r, nil) + r = ir.Nod(aop, r, nil) r.Type = l.Type r.SetTypecheck(1) n.Right = r @@ -721,7 +722,7 @@ func typecheck1(n *Node, top int) (res *Node) { et = t.Etype } - if t.Etype != TIDEAL && !types.Identical(l.Type, r.Type) { + if t.Etype != types.TIDEAL && !types.Identical(l.Type, r.Type) { l, r = defaultlit2(l, r, true) if l.Type == nil || r.Type == nil { n.Type = nil @@ -734,7 +735,7 @@ func typecheck1(n *Node, top int) (res *Node) { } } - if t.Etype == TIDEAL { + if t.Etype == types.TIDEAL { t = mixUntyped(l.Type, r.Type) } if dt := defaultType(t); !okfor[op][dt.Etype] { @@ -751,19 +752,19 @@ func typecheck1(n *Node, top int) (res *Node) { return n } - if l.Type.IsSlice() && !l.isNil() && !r.isNil() { + if l.Type.IsSlice() && !ir.IsNil(l) && !ir.IsNil(r) { base.Errorf("invalid operation: %v (slice can only be compared to nil)", n) n.Type = nil return n } - if l.Type.IsMap() && !l.isNil() && !r.isNil() { + if l.Type.IsMap() && !ir.IsNil(l) && !ir.IsNil(r) { base.Errorf("invalid operation: %v (map can only be compared to nil)", n) n.Type = nil return n } - if l.Type.Etype == TFUNC && !l.isNil() && !r.isNil() { + if l.Type.Etype == types.TFUNC && !ir.IsNil(l) && !ir.IsNil(r) { base.Errorf("invalid operation: %v (func can only be compared to nil)", n) n.Type = nil return n @@ -781,31 +782,31 @@ func typecheck1(n *Node, top int) (res *Node) { t = types.UntypedBool n.Type = t n = evalConst(n) - if n.Op != OLITERAL { + if n.Op != ir.OLITERAL { l, r = defaultlit2(l, r, true) n.Left = l n.Right = r } } - if et == TSTRING && n.Op == OADD { + if et == types.TSTRING && n.Op == ir.OADD { // create or update OADDSTR node with list of strings in x + y + z + (w + v) + ... - if l.Op == OADDSTR { + if l.Op == ir.OADDSTR { orig := n n = l n.Pos = orig.Pos } else { - n = nodl(n.Pos, OADDSTR, nil, nil) + n = ir.NodAt(n.Pos, ir.OADDSTR, nil, nil) n.List.Set1(l) } - if r.Op == OADDSTR { + if r.Op == ir.OADDSTR { n.List.AppendNodes(&r.List) } else { n.List.Append(r) } } - if (op == ODIV || op == OMOD) && Isconst(r, constant.Int) { + if (op == ir.ODIV || op == ir.OMOD) && ir.IsConst(r, constant.Int) { if constant.Sign(r.Val()) == 0 { base.Errorf("division by zero") n.Type = nil @@ -815,7 +816,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = t - case OBITNOT, ONEG, ONOT, OPLUS: + case ir.OBITNOT, ir.ONEG, ir.ONOT, ir.OPLUS: ok |= ctxExpr n.Left = typecheck(n.Left, ctxExpr) l := n.Left @@ -833,7 +834,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = t // exprs - case OADDR: + case ir.OADDR: ok |= ctxExpr n.Left = typecheck(n.Left, ctxExpr) @@ -843,13 +844,13 @@ func typecheck1(n *Node, top int) (res *Node) { } switch n.Left.Op { - case OARRAYLIT, OMAPLIT, OSLICELIT, OSTRUCTLIT: - n.Op = OPTRLIT + case ir.OARRAYLIT, ir.OMAPLIT, ir.OSLICELIT, ir.OSTRUCTLIT: + n.Op = ir.OPTRLIT default: checklvalue(n.Left, "take the address of") r := outervalue(n.Left) - if r.Op == ONAME { + if r.Op == ir.ONAME { if r.Orig != r { base.Fatalf("found non-orig name node %v", r) // TODO(mdempsky): What does this mean? } @@ -871,17 +872,17 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = types.NewPtr(n.Left.Type) - case OCOMPLIT: + case ir.OCOMPLIT: ok |= ctxExpr n = typecheckcomplit(n) if n.Type == nil { return n } - case OXDOT, ODOT: - if n.Op == OXDOT { + case ir.OXDOT, ir.ODOT: + if n.Op == ir.OXDOT { n = adddot(n) - n.Op = ODOT + n.Op = ir.ODOT if n.Left == nil { n.Type = nil return n @@ -894,14 +895,14 @@ func typecheck1(n *Node, top int) (res *Node) { t := n.Left.Type if t == nil { - base.UpdateErrorDot(n.Line(), n.Left.String(), n.String()) + base.UpdateErrorDot(ir.Line(n), n.Left.String(), n.String()) n.Type = nil return n } s := n.Sym - if n.Left.Op == OTYPE { + if n.Left.Op == ir.OTYPE { n = typecheckMethodExpr(n) if n.Type == nil { return n @@ -916,7 +917,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n } - n.Op = ODOTPTR + n.Op = ir.ODOTPTR checkwidth(t) } @@ -952,7 +953,7 @@ func typecheck1(n *Node, top int) (res *Node) { } switch n.Op { - case ODOTINTER, ODOTMETH: + case ir.ODOTINTER, ir.ODOTMETH: if top&ctxCallee != 0 { ok |= ctxCallee } else { @@ -964,7 +965,7 @@ func typecheck1(n *Node, top int) (res *Node) { ok |= ctxExpr } - case ODOTTYPE: + case ir.ODOTTYPE: ok |= ctxExpr n.Left = typecheck(n.Left, ctxExpr) n.Left = defaultlit(n.Left, nil) @@ -1009,7 +1010,7 @@ func typecheck1(n *Node, top int) (res *Node) { } } - case OINDEX: + case ir.OINDEX: ok |= ctxExpr n.Left = typecheck(n.Left, ctxExpr) n.Left = defaultlit(n.Left, nil) @@ -1028,7 +1029,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n - case TSTRING, TARRAY, TSLICE: + case types.TSTRING, types.TARRAY, types.TSLICE: n.Right = indexlit(n.Right) if t.IsString() { n.Type = types.Bytetype @@ -1047,27 +1048,27 @@ func typecheck1(n *Node, top int) (res *Node) { break } - if !n.Bounded() && Isconst(n.Right, constant.Int) { + if !n.Bounded() && ir.IsConst(n.Right, constant.Int) { x := n.Right.Val() if constant.Sign(x) < 0 { base.Errorf("invalid %s index %v (index must be non-negative)", why, n.Right) } else if t.IsArray() && constant.Compare(x, token.GEQ, constant.MakeInt64(t.NumElem())) { base.Errorf("invalid array index %v (out of bounds for %d-element array)", n.Right, t.NumElem()) - } else if Isconst(n.Left, constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(n.Left.StringVal())))) { + } else if ir.IsConst(n.Left, constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(n.Left.StringVal())))) { base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Right, len(n.Left.StringVal())) - } else if doesoverflow(x, types.Types[TINT]) { + } else if doesoverflow(x, types.Types[types.TINT]) { base.Errorf("invalid %s index %v (index too large)", why, n.Right) } } - case TMAP: + case types.TMAP: n.Right = assignconv(n.Right, t.Key(), "map index") n.Type = t.Elem() - n.Op = OINDEXMAP + n.Op = ir.OINDEXMAP n.ResetAux() } - case ORECV: + case ir.ORECV: ok |= ctxStmt | ctxExpr n.Left = typecheck(n.Left, ctxExpr) n.Left = defaultlit(n.Left, nil) @@ -1091,7 +1092,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = t.Elem() - case OSEND: + case ir.OSEND: ok |= ctxStmt n.Left = typecheck(n.Left, ctxExpr) n.Right = typecheck(n.Right, ctxExpr) @@ -1120,7 +1121,7 @@ func typecheck1(n *Node, top int) (res *Node) { } n.Type = nil - case OSLICEHEADER: + case ir.OSLICEHEADER: // Errors here are Fatalf instead of Errorf because only the compiler // can construct an OSLICEHEADER node. // Components used in OSLICEHEADER that are supplied by parsed source code @@ -1147,25 +1148,25 @@ func typecheck1(n *Node, top int) (res *Node) { n.Left = typecheck(n.Left, ctxExpr) l := typecheck(n.List.First(), ctxExpr) c := typecheck(n.List.Second(), ctxExpr) - l = defaultlit(l, types.Types[TINT]) - c = defaultlit(c, types.Types[TINT]) + l = defaultlit(l, types.Types[types.TINT]) + c = defaultlit(c, types.Types[types.TINT]) - if Isconst(l, constant.Int) && l.Int64Val() < 0 { + if ir.IsConst(l, constant.Int) && l.Int64Val() < 0 { base.Fatalf("len for OSLICEHEADER must be non-negative") } - if Isconst(c, constant.Int) && c.Int64Val() < 0 { + if ir.IsConst(c, constant.Int) && c.Int64Val() < 0 { base.Fatalf("cap for OSLICEHEADER must be non-negative") } - if Isconst(l, constant.Int) && Isconst(c, constant.Int) && constant.Compare(l.Val(), token.GTR, c.Val()) { + if ir.IsConst(l, constant.Int) && ir.IsConst(c, constant.Int) && constant.Compare(l.Val(), token.GTR, c.Val()) { base.Fatalf("len larger than cap for OSLICEHEADER") } n.List.SetFirst(l) n.List.SetSecond(c) - case OMAKESLICECOPY: + case ir.OMAKESLICECOPY: // Errors here are Fatalf instead of Errorf because only the compiler // can construct an OMAKESLICECOPY node. // Components used in OMAKESCLICECOPY that are supplied by parsed source code @@ -1193,14 +1194,14 @@ func typecheck1(n *Node, top int) (res *Node) { n.Left = typecheck(n.Left, ctxExpr) n.Right = typecheck(n.Right, ctxExpr) - n.Left = defaultlit(n.Left, types.Types[TINT]) + n.Left = defaultlit(n.Left, types.Types[types.TINT]) - if !n.Left.Type.IsInteger() && n.Type.Etype != TIDEAL { + if !n.Left.Type.IsInteger() && n.Type.Etype != types.TIDEAL { base.Errorf("non-integer len argument in OMAKESLICECOPY") } - if Isconst(n.Left, constant.Int) { - if doesoverflow(n.Left.Val(), types.Types[TINT]) { + if ir.IsConst(n.Left, constant.Int) { + if doesoverflow(n.Left.Val(), types.Types[types.TINT]) { base.Fatalf("len for OMAKESLICECOPY too large") } if constant.Sign(n.Left.Val()) < 0 { @@ -1208,7 +1209,7 @@ func typecheck1(n *Node, top int) (res *Node) { } } - case OSLICE, OSLICE3: + case ir.OSLICE, ir.OSLICE3: ok |= ctxExpr n.Left = typecheck(n.Left, ctxExpr) low, high, max := n.SliceBounds() @@ -1233,7 +1234,7 @@ func typecheck1(n *Node, top int) (res *Node) { return n } - n.Left = nod(OADDR, n.Left, nil) + n.Left = ir.Nod(ir.OADDR, n.Left, nil) n.Left.SetImplicit(true) n.Left = typecheck(n.Left, ctxExpr) l = n.Left @@ -1247,15 +1248,15 @@ func typecheck1(n *Node, top int) (res *Node) { return n } n.Type = t - n.Op = OSLICESTR + n.Op = ir.OSLICESTR } else if t.IsPtr() && t.Elem().IsArray() { tp = t.Elem() n.Type = types.NewSlice(tp.Elem()) dowidth(n.Type) if hasmax { - n.Op = OSLICE3ARR + n.Op = ir.OSLICE3ARR } else { - n.Op = OSLICEARR + n.Op = ir.OSLICEARR } } else if t.IsSlice() { n.Type = t @@ -1283,7 +1284,7 @@ func typecheck1(n *Node, top int) (res *Node) { } // call and call like - case OCALL: + case ir.OCALL: typecheckslice(n.Ninit.Slice(), ctxStmt) // imported rewritten f(g()) calls (#30907) n.Left = typecheck(n.Left, ctxExpr|ctxType|ctxCallee) if n.Left.Diag() { @@ -1292,8 +1293,8 @@ func typecheck1(n *Node, top int) (res *Node) { l := n.Left - if l.Op == ONAME && l.SubOp() != 0 { - if n.IsDDD() && l.SubOp() != OAPPEND { + if l.Op == ir.ONAME && l.SubOp() != 0 { + if n.IsDDD() && l.SubOp() != ir.OAPPEND { base.Errorf("invalid use of ... with builtin %v", l) } @@ -1307,7 +1308,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Left = defaultlit(n.Left, nil) l = n.Left - if l.Op == OTYPE { + if l.Op == ir.OTYPE { if n.IsDDD() { if !l.Type.Broke() { base.Errorf("invalid use of ... in type conversion to %v", l.Type) @@ -1321,7 +1322,7 @@ func typecheck1(n *Node, top int) (res *Node) { // turn CALL(type, arg) into CONV(arg) w/ type n.Left = nil - n.Op = OCONV + n.Op = ir.OCONV n.Type = l.Type if !onearg(n, "conversion to %v", l.Type) { n.Type = nil @@ -1340,11 +1341,11 @@ func typecheck1(n *Node, top int) (res *Node) { checkwidth(t) switch l.Op { - case ODOTINTER: - n.Op = OCALLINTER + case ir.ODOTINTER: + n.Op = ir.OCALLINTER - case ODOTMETH: - n.Op = OCALLMETH + case ir.ODOTMETH: + n.Op = ir.OCALLMETH // typecheckaste was used here but there wasn't enough // information further down the call chain to know if we @@ -1357,8 +1358,8 @@ func typecheck1(n *Node, top int) (res *Node) { } default: - n.Op = OCALLFUNC - if t.Etype != TFUNC { + n.Op = ir.OCALLFUNC + if t.Etype != types.TFUNC { name := l.String() if isBuiltinFuncName(name) && l.Name.Defn != nil { // be more specific when the function @@ -1373,7 +1374,7 @@ func typecheck1(n *Node, top int) (res *Node) { } } - typecheckaste(OCALL, n.Left, n.IsDDD(), t.Params(), n.List, func() string { return fmt.Sprintf("argument to %v", n.Left) }) + typecheckaste(ir.OCALL, n.Left, n.IsDDD(), t.Params(), n.List, func() string { return fmt.Sprintf("argument to %v", n.Left) }) ok |= ctxStmt if t.NumResults() == 0 { break @@ -1382,14 +1383,14 @@ func typecheck1(n *Node, top int) (res *Node) { if t.NumResults() == 1 { n.Type = l.Type.Results().Field(0).Type - if n.Op == OCALLFUNC && n.Left.Op == ONAME && isRuntimePkg(n.Left.Sym.Pkg) && n.Left.Sym.Name == "getg" { + if n.Op == ir.OCALLFUNC && n.Left.Op == ir.ONAME && isRuntimePkg(n.Left.Sym.Pkg) && n.Left.Sym.Name == "getg" { // Emit code for runtime.getg() directly instead of calling function. // Most such rewrites (for example the similar one for math.Sqrt) should be done in walk, // so that the ordering pass can make sure to preserve the semantics of the original code // (in particular, the exact time of the function call) by introducing temporaries. // In this case, we know getg() always returns the same result within a given function // and we want to avoid the temporaries, so we do the rewrite earlier than is typical. - n.Op = OGETG + n.Op = ir.OGETG } break @@ -1403,15 +1404,15 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = l.Type.Results() - case OALIGNOF, OOFFSETOF, OSIZEOF: + case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: ok |= ctxExpr if !onearg(n, "%v", n.Op) { n.Type = nil return n } - n.Type = types.Types[TUINTPTR] + n.Type = types.Types[types.TUINTPTR] - case OCAP, OLEN: + case ir.OCAP, ir.OLEN: ok |= ctxExpr if !onearg(n, "%v", n.Op) { n.Type = nil @@ -1429,7 +1430,7 @@ func typecheck1(n *Node, top int) (res *Node) { } var ok bool - if n.Op == OLEN { + if n.Op == ir.OLEN { ok = okforlen[t.Etype] } else { ok = okforcap[t.Etype] @@ -1440,9 +1441,9 @@ func typecheck1(n *Node, top int) (res *Node) { return n } - n.Type = types.Types[TINT] + n.Type = types.Types[types.TINT] - case OREAL, OIMAG: + case ir.OREAL, ir.OIMAG: ok |= ctxExpr if !onearg(n, "%v", n.Op) { n.Type = nil @@ -1459,19 +1460,19 @@ func typecheck1(n *Node, top int) (res *Node) { // Determine result type. switch t.Etype { - case TIDEAL: + case types.TIDEAL: n.Type = types.UntypedFloat - case TCOMPLEX64: - n.Type = types.Types[TFLOAT32] - case TCOMPLEX128: - n.Type = types.Types[TFLOAT64] + case types.TCOMPLEX64: + n.Type = types.Types[types.TFLOAT32] + case types.TCOMPLEX128: + n.Type = types.Types[types.TFLOAT64] default: base.Errorf("invalid argument %L for %v", l, n.Op) n.Type = nil return n } - case OCOMPLEX: + case ir.OCOMPLEX: ok |= ctxExpr typecheckargs(n) if !twoarg(n) { @@ -1505,18 +1506,18 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n - case TIDEAL: + case types.TIDEAL: t = types.UntypedComplex - case TFLOAT32: - t = types.Types[TCOMPLEX64] + case types.TFLOAT32: + t = types.Types[types.TCOMPLEX64] - case TFLOAT64: - t = types.Types[TCOMPLEX128] + case types.TFLOAT64: + t = types.Types[types.TCOMPLEX128] } n.Type = t - case OCLOSE: + case ir.OCLOSE: if !onearg(n, "%v", n.Op) { n.Type = nil return n @@ -1543,7 +1544,7 @@ func typecheck1(n *Node, top int) (res *Node) { ok |= ctxStmt - case ODELETE: + case ir.ODELETE: ok |= ctxStmt typecheckargs(n) args := n.List @@ -1575,7 +1576,7 @@ func typecheck1(n *Node, top int) (res *Node) { args.SetSecond(assignconv(r, l.Type.Key(), "delete")) - case OAPPEND: + case ir.OAPPEND: ok |= ctxExpr typecheckargs(n) args := n.List @@ -1593,7 +1594,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = t if !t.IsSlice() { - if args.First().isNil() { + if ir.IsNil(args.First()) { base.Errorf("first argument to append must be typed slice; have untyped nil") n.Type = nil return n @@ -1617,8 +1618,8 @@ func typecheck1(n *Node, top int) (res *Node) { return n } - if t.Elem().IsKind(TUINT8) && args.Second().Type.IsString() { - args.SetSecond(defaultlit(args.Second(), types.Types[TSTRING])) + if t.Elem().IsKind(types.TUINT8) && args.Second().Type.IsString() { + args.SetSecond(defaultlit(args.Second(), types.Types[types.TSTRING])) break } @@ -1635,14 +1636,14 @@ func typecheck1(n *Node, top int) (res *Node) { checkwidth(as[i].Type) // ensure width is calculated for backend } - case OCOPY: + case ir.OCOPY: ok |= ctxStmt | ctxExpr typecheckargs(n) if !twoarg(n) { n.Type = nil return n } - n.Type = types.Types[TINT] + n.Type = types.Types[types.TINT] if n.Left.Type == nil || n.Right.Type == nil { n.Type = nil return n @@ -1682,7 +1683,7 @@ func typecheck1(n *Node, top int) (res *Node) { return n } - case OCONV: + case ir.OCONV: ok |= ctxExpr checkwidth(n.Type) // ensure width is calculated for backend n.Left = typecheck(n.Left, ctxExpr) @@ -1692,41 +1693,41 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n } - op, why := convertop(n.Left.Op == OLITERAL, t, n.Type) + op, why := convertop(n.Left.Op == ir.OLITERAL, t, n.Type) n.Op = op - if n.Op == OXXX { + if n.Op == ir.OXXX { if !n.Diag() && !n.Type.Broke() && !n.Left.Diag() { base.Errorf("cannot convert %L to type %v%s", n.Left, n.Type, why) n.SetDiag(true) } - n.Op = OCONV + n.Op = ir.OCONV n.Type = nil return n } switch n.Op { - case OCONVNOP: + case ir.OCONVNOP: if t.Etype == n.Type.Etype { switch t.Etype { - case TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128: + case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128: // Floating point casts imply rounding and // so the conversion must be kept. - n.Op = OCONV + n.Op = ir.OCONV } } // do not convert to []byte literal. See CL 125796. // generated code and compiler memory footprint is better without it. - case OSTR2BYTES: + case ir.OSTR2BYTES: break - case OSTR2RUNES: - if n.Left.Op == OLITERAL { + case ir.OSTR2RUNES: + if n.Left.Op == ir.OLITERAL { n = stringtoruneslit(n) } } - case OMAKE: + case ir.OMAKE: ok |= ctxExpr args := n.List.Slice() if len(args) == 0 { @@ -1751,7 +1752,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n - case TSLICE: + case types.TSLICE: if i >= len(args) { base.Errorf("missing len argument to make(%v)", t) n.Type = nil @@ -1761,7 +1762,7 @@ func typecheck1(n *Node, top int) (res *Node) { l = args[i] i++ l = typecheck(l, ctxExpr) - var r *Node + var r *ir.Node if i < len(args) { r = args[i] i++ @@ -1776,7 +1777,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n } - if Isconst(l, constant.Int) && r != nil && Isconst(r, constant.Int) && constant.Compare(l.Val(), token.GTR, r.Val()) { + if ir.IsConst(l, constant.Int) && r != nil && ir.IsConst(r, constant.Int) && constant.Compare(l.Val(), token.GTR, r.Val()) { base.Errorf("len larger than cap in make(%v)", t) n.Type = nil return n @@ -1784,14 +1785,14 @@ func typecheck1(n *Node, top int) (res *Node) { n.Left = l n.Right = r - n.Op = OMAKESLICE + n.Op = ir.OMAKESLICE - case TMAP: + case types.TMAP: if i < len(args) { l = args[i] i++ l = typecheck(l, ctxExpr) - l = defaultlit(l, types.Types[TINT]) + l = defaultlit(l, types.Types[types.TINT]) if l.Type == nil { n.Type = nil return n @@ -1804,15 +1805,15 @@ func typecheck1(n *Node, top int) (res *Node) { } else { n.Left = nodintconst(0) } - n.Op = OMAKEMAP + n.Op = ir.OMAKEMAP - case TCHAN: + case types.TCHAN: l = nil if i < len(args) { l = args[i] i++ l = typecheck(l, ctxExpr) - l = defaultlit(l, types.Types[TINT]) + l = defaultlit(l, types.Types[types.TINT]) if l.Type == nil { n.Type = nil return n @@ -1825,19 +1826,19 @@ func typecheck1(n *Node, top int) (res *Node) { } else { n.Left = nodintconst(0) } - n.Op = OMAKECHAN + n.Op = ir.OMAKECHAN } if i < len(args) { base.Errorf("too many arguments to make(%v)", t) - n.Op = OMAKE + n.Op = ir.OMAKE n.Type = nil return n } n.Type = t - case ONEW: + case ir.ONEW: ok |= ctxExpr args := n.List if args.Len() == 0 { @@ -1862,33 +1863,33 @@ func typecheck1(n *Node, top int) (res *Node) { n.Left = l n.Type = types.NewPtr(t) - case OPRINT, OPRINTN: + case ir.OPRINT, ir.OPRINTN: ok |= ctxStmt typecheckargs(n) ls := n.List.Slice() for i1, n1 := range ls { // Special case for print: int constant is int64, not int. - if Isconst(n1, constant.Int) { - ls[i1] = defaultlit(ls[i1], types.Types[TINT64]) + if ir.IsConst(n1, constant.Int) { + ls[i1] = defaultlit(ls[i1], types.Types[types.TINT64]) } else { ls[i1] = defaultlit(ls[i1], nil) } } - case OPANIC: + case ir.OPANIC: ok |= ctxStmt if !onearg(n, "panic") { n.Type = nil return n } n.Left = typecheck(n.Left, ctxExpr) - n.Left = defaultlit(n.Left, types.Types[TINTER]) + n.Left = defaultlit(n.Left, types.Types[types.TINTER]) if n.Left.Type == nil { n.Type = nil return n } - case ORECOVER: + case ir.ORECOVER: ok |= ctxExpr | ctxStmt if n.List.Len() != 0 { base.Errorf("too many arguments to recover") @@ -1896,16 +1897,16 @@ func typecheck1(n *Node, top int) (res *Node) { return n } - n.Type = types.Types[TINTER] + n.Type = types.Types[types.TINTER] - case OCLOSURE: + case ir.OCLOSURE: ok |= ctxExpr typecheckclosure(n, top) if n.Type == nil { return n } - case OITAB: + case ir.OITAB: ok |= ctxExpr n.Left = typecheck(n.Left, ctxExpr) t := n.Left.Type @@ -1916,14 +1917,14 @@ func typecheck1(n *Node, top int) (res *Node) { if !t.IsInterface() { base.Fatalf("OITAB of %v", t) } - n.Type = types.NewPtr(types.Types[TUINTPTR]) + n.Type = types.NewPtr(types.Types[types.TUINTPTR]) - case OIDATA: + case ir.OIDATA: // Whoever creates the OIDATA node must know a priori the concrete type at that moment, // usually by just having checked the OITAB. base.Fatalf("cannot typecheck interface data %v", n) - case OSPTR: + case ir.OSPTR: ok |= ctxExpr n.Left = typecheck(n.Left, ctxExpr) t := n.Left.Type @@ -1935,72 +1936,72 @@ func typecheck1(n *Node, top int) (res *Node) { base.Fatalf("OSPTR of %v", t) } if t.IsString() { - n.Type = types.NewPtr(types.Types[TUINT8]) + n.Type = types.NewPtr(types.Types[types.TUINT8]) } else { n.Type = types.NewPtr(t.Elem()) } - case OCLOSUREVAR: + case ir.OCLOSUREVAR: ok |= ctxExpr - case OCFUNC: + case ir.OCFUNC: ok |= ctxExpr n.Left = typecheck(n.Left, ctxExpr) - n.Type = types.Types[TUINTPTR] + n.Type = types.Types[types.TUINTPTR] - case OCONVNOP: + case ir.OCONVNOP: ok |= ctxExpr n.Left = typecheck(n.Left, ctxExpr) // statements - case OAS: + case ir.OAS: ok |= ctxStmt typecheckas(n) // Code that creates temps does not bother to set defn, so do it here. - if n.Left.Op == ONAME && n.Left.IsAutoTmp() { + if n.Left.Op == ir.ONAME && n.Left.IsAutoTmp() { n.Left.Name.Defn = n } - case OAS2: + case ir.OAS2: ok |= ctxStmt typecheckas2(n) - case OBREAK, - OCONTINUE, - ODCL, - OEMPTY, - OGOTO, - OFALL, - OVARKILL, - OVARLIVE: + case ir.OBREAK, + ir.OCONTINUE, + ir.ODCL, + ir.OEMPTY, + ir.OGOTO, + ir.OFALL, + ir.OVARKILL, + ir.OVARLIVE: ok |= ctxStmt - case OLABEL: + case ir.OLABEL: ok |= ctxStmt decldepth++ if n.Sym.IsBlank() { // Empty identifier is valid but useless. // Eliminate now to simplify life later. // See issues 7538, 11589, 11593. - n.Op = OEMPTY + n.Op = ir.OEMPTY n.Left = nil } - case ODEFER: + case ir.ODEFER: ok |= ctxStmt n.Left = typecheck(n.Left, ctxStmt|ctxExpr) if !n.Left.Diag() { checkdefergo(n) } - case OGO: + case ir.OGO: ok |= ctxStmt n.Left = typecheck(n.Left, ctxStmt|ctxExpr) checkdefergo(n) - case OFOR, OFORUNTIL: + case ir.OFOR, ir.OFORUNTIL: ok |= ctxStmt typecheckslice(n.Ninit.Slice(), ctxStmt) decldepth++ @@ -2013,13 +2014,13 @@ func typecheck1(n *Node, top int) (res *Node) { } } n.Right = typecheck(n.Right, ctxStmt) - if n.Op == OFORUNTIL { + if n.Op == ir.OFORUNTIL { typecheckslice(n.List.Slice(), ctxStmt) } typecheckslice(n.Nbody.Slice(), ctxStmt) decldepth-- - case OIF: + case ir.OIF: ok |= ctxStmt typecheckslice(n.Ninit.Slice(), ctxStmt) n.Left = typecheck(n.Left, ctxExpr) @@ -2033,7 +2034,7 @@ func typecheck1(n *Node, top int) (res *Node) { typecheckslice(n.Nbody.Slice(), ctxStmt) typecheckslice(n.Rlist.Slice(), ctxStmt) - case ORETURN: + case ir.ORETURN: ok |= ctxStmt typecheckargs(n) if Curfn == nil { @@ -2045,47 +2046,47 @@ func typecheck1(n *Node, top int) (res *Node) { if Curfn.Type.FuncType().Outnamed && n.List.Len() == 0 { break } - typecheckaste(ORETURN, nil, false, Curfn.Type.Results(), n.List, func() string { return "return argument" }) + typecheckaste(ir.ORETURN, nil, false, Curfn.Type.Results(), n.List, func() string { return "return argument" }) - case ORETJMP: + case ir.ORETJMP: ok |= ctxStmt - case OSELECT: + case ir.OSELECT: ok |= ctxStmt typecheckselect(n) - case OSWITCH: + case ir.OSWITCH: ok |= ctxStmt typecheckswitch(n) - case ORANGE: + case ir.ORANGE: ok |= ctxStmt typecheckrange(n) - case OTYPESW: + case ir.OTYPESW: base.Errorf("use of .(type) outside type switch") n.Type = nil return n - case ODCLFUNC: + case ir.ODCLFUNC: ok |= ctxStmt typecheckfunc(n) - case ODCLCONST: + case ir.ODCLCONST: ok |= ctxStmt n.Left = typecheck(n.Left, ctxExpr) - case ODCLTYPE: + case ir.ODCLTYPE: ok |= ctxStmt n.Left = typecheck(n.Left, ctxType) checkwidth(n.Left.Type) } t := n.Type - if t != nil && !t.IsFuncArgStruct() && n.Op != OTYPE { + if t != nil && !t.IsFuncArgStruct() && n.Op != ir.OTYPE { switch t.Etype { - case TFUNC, // might have TANY; wait until it's called - TANY, TFORW, TIDEAL, TNIL, TBLANK: + case types.TFUNC, // might have TANY; wait until it's called + types.TANY, types.TFORW, types.TIDEAL, types.TNIL, types.TBLANK: break default: @@ -2094,7 +2095,7 @@ func typecheck1(n *Node, top int) (res *Node) { } n = evalConst(n) - if n.Op == OTYPE && top&ctxType == 0 { + if n.Op == ir.OTYPE && top&ctxType == 0 { if !n.Type.Broke() { base.Errorf("type %v is not an expression", n.Type) } @@ -2102,7 +2103,7 @@ func typecheck1(n *Node, top int) (res *Node) { return n } - if top&(ctxExpr|ctxType) == ctxType && n.Op != OTYPE { + if top&(ctxExpr|ctxType) == ctxType && n.Op != ir.OTYPE { base.Errorf("%v is not a type", n) n.Type = nil return n @@ -2128,7 +2129,7 @@ func typecheck1(n *Node, top int) (res *Node) { return n } -func typecheckargs(n *Node) { +func typecheckargs(n *ir.Node) { if n.List.Len() != 1 || n.IsDDD() { typecheckslice(n.List.Slice(), ctxExpr) return @@ -2144,10 +2145,10 @@ func typecheckargs(n *Node) { // Save n as n.Orig for fmt.go. if n.Orig == n { - n.Orig = n.sepcopy() + n.Orig = ir.SepCopy(n) } - as := nod(OAS2, nil, nil) + as := ir.Nod(ir.OAS2, nil, nil) as.Rlist.AppendNodes(&n.List) // If we're outside of function context, then this call will @@ -2161,7 +2162,7 @@ func typecheckargs(n *Node) { } for _, f := range t.FieldSlice() { t := temp(f.Type) - as.Ninit.Append(nod(ODCL, t, nil)) + as.Ninit.Append(ir.Nod(ir.ODCL, t, nil)) as.List.Append(t) n.List.Append(t) } @@ -2173,7 +2174,7 @@ func typecheckargs(n *Node) { n.Ninit.Append(as) } -func checksliceindex(l *Node, r *Node, tp *types.Type) bool { +func checksliceindex(l *ir.Node, r *ir.Node, tp *types.Type) bool { t := r.Type if t == nil { return false @@ -2183,7 +2184,7 @@ func checksliceindex(l *Node, r *Node, tp *types.Type) bool { return false } - if r.Op == OLITERAL { + if r.Op == ir.OLITERAL { x := r.Val() if constant.Sign(x) < 0 { base.Errorf("invalid slice index %v (index must be non-negative)", r) @@ -2191,10 +2192,10 @@ func checksliceindex(l *Node, r *Node, tp *types.Type) bool { } else if tp != nil && tp.NumElem() >= 0 && constant.Compare(x, token.GTR, constant.MakeInt64(tp.NumElem())) { base.Errorf("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem()) return false - } else if Isconst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(l.StringVal())))) { + } else if ir.IsConst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(l.StringVal())))) { base.Errorf("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.StringVal())) return false - } else if doesoverflow(x, types.Types[TINT]) { + } else if doesoverflow(x, types.Types[types.TINT]) { base.Errorf("invalid slice index %v (index too large)", r) return false } @@ -2203,8 +2204,8 @@ func checksliceindex(l *Node, r *Node, tp *types.Type) bool { return true } -func checksliceconst(lo *Node, hi *Node) bool { - if lo != nil && hi != nil && lo.Op == OLITERAL && hi.Op == OLITERAL && constant.Compare(lo.Val(), token.GTR, hi.Val()) { +func checksliceconst(lo *ir.Node, hi *ir.Node) bool { + if lo != nil && hi != nil && lo.Op == ir.OLITERAL && hi.Op == ir.OLITERAL && constant.Compare(lo.Val(), token.GTR, hi.Val()) { base.Errorf("invalid slice index: %v > %v", lo, hi) return false } @@ -2212,39 +2213,39 @@ func checksliceconst(lo *Node, hi *Node) bool { return true } -func checkdefergo(n *Node) { +func checkdefergo(n *ir.Node) { what := "defer" - if n.Op == OGO { + if n.Op == ir.OGO { what = "go" } switch n.Left.Op { // ok - case OCALLINTER, - OCALLMETH, - OCALLFUNC, - OCLOSE, - OCOPY, - ODELETE, - OPANIC, - OPRINT, - OPRINTN, - ORECOVER: + case ir.OCALLINTER, + ir.OCALLMETH, + ir.OCALLFUNC, + ir.OCLOSE, + ir.OCOPY, + ir.ODELETE, + ir.OPANIC, + ir.OPRINT, + ir.OPRINTN, + ir.ORECOVER: return - case OAPPEND, - OCAP, - OCOMPLEX, - OIMAG, - OLEN, - OMAKE, - OMAKESLICE, - OMAKECHAN, - OMAKEMAP, - ONEW, - OREAL, - OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof - if n.Left.Orig != nil && n.Left.Orig.Op == OCONV { + case ir.OAPPEND, + ir.OCAP, + ir.OCOMPLEX, + ir.OIMAG, + ir.OLEN, + ir.OMAKE, + ir.OMAKESLICE, + ir.OMAKECHAN, + ir.OMAKEMAP, + ir.ONEW, + ir.OREAL, + ir.OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof + if n.Left.Orig != nil && n.Left.Orig.Op == ir.OCONV { break } base.ErrorfAt(n.Pos, "%s discards result of %v", what, n.Left) @@ -2267,7 +2268,7 @@ func checkdefergo(n *Node) { // The result of implicitstar MUST be assigned back to n, e.g. // n.Left = implicitstar(n.Left) -func implicitstar(n *Node) *Node { +func implicitstar(n *ir.Node) *ir.Node { // insert implicit * if needed for fixed array t := n.Type if t == nil || !t.IsPtr() { @@ -2280,13 +2281,13 @@ func implicitstar(n *Node) *Node { if !t.IsArray() { return n } - n = nod(ODEREF, n, nil) + n = ir.Nod(ir.ODEREF, n, nil) n.SetImplicit(true) n = typecheck(n, ctxExpr) return n } -func onearg(n *Node, f string, args ...interface{}) bool { +func onearg(n *ir.Node, f string, args ...interface{}) bool { if n.Left != nil { return true } @@ -2309,7 +2310,7 @@ func onearg(n *Node, f string, args ...interface{}) bool { return true } -func twoarg(n *Node) bool { +func twoarg(n *ir.Node) bool { if n.Left != nil { return true } @@ -2327,7 +2328,7 @@ func twoarg(n *Node) bool { return true } -func lookdot1(errnode *Node, s *types.Sym, t *types.Type, fs *types.Fields, dostrcmp int) *types.Field { +func lookdot1(errnode *ir.Node, s *types.Sym, t *types.Type, fs *types.Fields, dostrcmp int) *types.Field { var r *types.Field for _, f := range fs.Slice() { if dostrcmp != 0 && f.Sym.Name == s.Name { @@ -2358,7 +2359,7 @@ func lookdot1(errnode *Node, s *types.Sym, t *types.Type, fs *types.Fields, dost // typecheckMethodExpr checks selector expressions (ODOT) where the // base expression is a type expression (OTYPE). -func typecheckMethodExpr(n *Node) (res *Node) { +func typecheckMethodExpr(n *ir.Node) (res *ir.Node) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckMethodExpr", n)(&res) } @@ -2411,20 +2412,20 @@ func typecheckMethodExpr(n *Node) (res *Node) { return n } - n.Op = OMETHEXPR + n.Op = ir.OMETHEXPR if n.Name == nil { - n.Name = new(Name) + n.Name = new(ir.Name) } - n.Right = newname(n.Sym) + n.Right = NewName(n.Sym) n.Sym = methodSym(t, n.Sym) n.Type = methodfunc(m.Type, n.Left.Type) n.Xoffset = 0 - n.SetClass(PFUNC) + n.SetClass(ir.PFUNC) n.SetOpt(m) // methodSym already marked n.Sym as a function. // Issue 25065. Make sure that we emit the symbol for a local method. - if base.Ctxt.Flag_dynlink && !inimport && (t.Sym == nil || t.Sym.Pkg == localpkg) { + if base.Ctxt.Flag_dynlink && !inimport && (t.Sym == nil || t.Sym.Pkg == ir.LocalPkg) { makefuncsym(n.Sym) } @@ -2446,7 +2447,7 @@ func derefall(t *types.Type) *types.Type { return t } -func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field { +func lookdot(n *ir.Node, t *types.Type, dostrcmp int) *types.Field { s := n.Sym dowidth(t) @@ -2471,19 +2472,19 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field { if f2 != nil { base.Errorf("%v is both field and method", n.Sym) } - if f1.Offset == BADWIDTH { + if f1.Offset == types.BADWIDTH { base.Fatalf("lookdot badwidth %v %p", f1, f1) } n.Xoffset = f1.Offset n.Type = f1.Type if t.IsInterface() { if n.Left.Type.IsPtr() { - n.Left = nod(ODEREF, n.Left, nil) // implicitstar + n.Left = ir.Nod(ir.ODEREF, n.Left, nil) // implicitstar n.Left.SetImplicit(true) n.Left = typecheck(n.Left, ctxExpr) } - n.Op = ODOTINTER + n.Op = ir.ODOTINTER } else { n.SetOpt(f1) } @@ -2502,11 +2503,11 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field { if !types.Identical(rcvr, tt) { if rcvr.IsPtr() && types.Identical(rcvr.Elem(), tt) { checklvalue(n.Left, "call pointer method on") - n.Left = nod(OADDR, n.Left, nil) + n.Left = ir.Nod(ir.OADDR, n.Left, nil) n.Left.SetImplicit(true) n.Left = typecheck(n.Left, ctxType|ctxExpr) } else if tt.IsPtr() && (!rcvr.IsPtr() || rcvr.IsPtr() && rcvr.Elem().NotInHeap()) && types.Identical(tt.Elem(), rcvr) { - n.Left = nod(ODEREF, n.Left, nil) + n.Left = ir.Nod(ir.ODEREF, n.Left, nil) n.Left.SetImplicit(true) n.Left = typecheck(n.Left, ctxType|ctxExpr) } else if tt.IsPtr() && tt.Elem().IsPtr() && types.Identical(derefall(tt), derefall(rcvr)) { @@ -2516,7 +2517,7 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field { if rcvr.IsPtr() && !tt.Elem().IsPtr() { break } - n.Left = nod(ODEREF, n.Left, nil) + n.Left = ir.Nod(ir.ODEREF, n.Left, nil) n.Left.SetImplicit(true) n.Left = typecheck(n.Left, ctxType|ctxExpr) tt = tt.Elem() @@ -2528,11 +2529,11 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field { pll := n ll := n.Left - for ll.Left != nil && (ll.Op == ODOT || ll.Op == ODOTPTR || ll.Op == ODEREF) { + for ll.Left != nil && (ll.Op == ir.ODOT || ll.Op == ir.ODOTPTR || ll.Op == ir.ODEREF) { pll = ll ll = ll.Left } - if pll.Implicit() && ll.Type.IsPtr() && ll.Type.Sym != nil && asNode(ll.Type.Sym.Def) != nil && asNode(ll.Type.Sym.Def).Op == OTYPE { + if pll.Implicit() && ll.Type.IsPtr() && ll.Type.Sym != nil && ir.AsNode(ll.Type.Sym.Def) != nil && ir.AsNode(ll.Type.Sym.Def).Op == ir.OTYPE { // It is invalid to automatically dereference a named pointer type when selecting a method. // Make n.Left == ll to clarify error message. n.Left = ll @@ -2542,7 +2543,7 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field { n.Sym = methodSym(n.Left.Type, f2.Sym) n.Xoffset = f2.Offset n.Type = f2.Type - n.Op = ODOTMETH + n.Op = ir.ODOTMETH n.SetOpt(f2) return f2 @@ -2551,9 +2552,9 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field { return nil } -func nokeys(l Nodes) bool { +func nokeys(l ir.Nodes) bool { for _, n := range l.Slice() { - if n.Op == OKEY || n.Op == OSTRUCTKEY { + if n.Op == ir.OKEY || n.Op == ir.OSTRUCTKEY { return false } } @@ -2571,7 +2572,7 @@ func hasddd(t *types.Type) bool { } // typecheck assignment: type list = expression list -func typecheckaste(op Op, call *Node, isddd bool, tstruct *types.Type, nl Nodes, desc func() string) { +func typecheckaste(op ir.Op, call *ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes, desc func() string) { var t *types.Type var i int @@ -2582,7 +2583,7 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *types.Type, nl Nodes, return } - var n *Node + var n *ir.Node if nl.Len() == 1 { n = nl.First() } @@ -2671,7 +2672,7 @@ notenough: // call is the expression being called, not the overall call. // Method expressions have the form T.M, and the compiler has // rewritten those to ONAME nodes but left T in Left. - if call.Op == OMETHEXPR { + if call.Op == ir.OMETHEXPR { base.Errorf("not enough arguments in call to method expression %v%s", call, details) } else { base.Errorf("not enough arguments in call to %v%s", call, details) @@ -2694,7 +2695,7 @@ toomany: } } -func errorDetails(nl Nodes, tstruct *types.Type, isddd bool) string { +func errorDetails(nl ir.Nodes, tstruct *types.Type, isddd bool) string { // If we don't know any type at a call site, let's suppress any return // message signatures. See Issue https://golang.org/issues/19012. if tstruct == nil { @@ -2706,7 +2707,7 @@ func errorDetails(nl Nodes, tstruct *types.Type, isddd bool) string { return "" } } - return fmt.Sprintf("\n\thave %s\n\twant %v", nl.sigerr(isddd), tstruct) + return fmt.Sprintf("\n\thave %s\n\twant %v", fmtSignature(nl, isddd), tstruct) } // sigrepr is a type's representation to the outside world, @@ -2720,7 +2721,7 @@ func sigrepr(t *types.Type, isddd bool) string { return "bool" } - if t.Etype == TIDEAL { + if t.Etype == types.TIDEAL { // "untyped number" is not commonly used // outside of the compiler, so let's use "number". // TODO(mdempsky): Revisit this. @@ -2738,7 +2739,7 @@ func sigrepr(t *types.Type, isddd bool) string { } // sigerr returns the signature of the types at the call or return. -func (nl Nodes) sigerr(isddd bool) string { +func fmtSignature(nl ir.Nodes, isddd bool) string { if nl.Len() < 1 { return "()" } @@ -2764,7 +2765,7 @@ func fielddup(name string, hash map[string]bool) { // iscomptype reports whether type t is a composite literal type. func iscomptype(t *types.Type) bool { switch t.Etype { - case TARRAY, TSLICE, TSTRUCT, TMAP: + case types.TARRAY, types.TSLICE, types.TSTRUCT, types.TMAP: return true default: return false @@ -2773,8 +2774,8 @@ func iscomptype(t *types.Type) bool { // pushtype adds elided type information for composite literals if // appropriate, and returns the resulting expression. -func pushtype(n *Node, t *types.Type) *Node { - if n == nil || n.Op != OCOMPLIT || n.Right != nil { +func pushtype(n *ir.Node, t *types.Type) *ir.Node { + if n == nil || n.Op != ir.OCOMPLIT || n.Right != nil { return n } @@ -2787,7 +2788,7 @@ func pushtype(n *Node, t *types.Type) *Node { // For *T, return &T{...}. n.Right = typenod(t.Elem()) - n = nodl(n.Pos, OADDR, n, nil) + n = ir.NodAt(n.Pos, ir.OADDR, n, nil) n.SetImplicit(true) } @@ -2796,7 +2797,7 @@ func pushtype(n *Node, t *types.Type) *Node { // The result of typecheckcomplit MUST be assigned back to n, e.g. // n.Left = typecheckcomplit(n.Left) -func typecheckcomplit(n *Node) (res *Node) { +func typecheckcomplit(n *ir.Node) (res *ir.Node) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckcomplit", n)(&res) } @@ -2813,12 +2814,12 @@ func typecheckcomplit(n *Node) (res *Node) { } // Save original node (including n.Right) - n.Orig = n.copy() + n.Orig = ir.Copy(n) setlineno(n.Right) // Need to handle [...]T arrays specially. - if n.Right.Op == OTARRAY && n.Right.Left != nil && n.Right.Left.Op == ODDD { + if n.Right.Op == ir.OTARRAY && n.Right.Left != nil && n.Right.Left.Op == ir.ODDD { n.Right.Right = typecheck(n.Right.Right, ctxType) if n.Right.Right.Type == nil { n.Type = nil @@ -2828,7 +2829,7 @@ func typecheckcomplit(n *Node) (res *Node) { length := typecheckarraylit(elemType, -1, n.List.Slice(), "array literal") - n.Op = OARRAYLIT + n.Op = ir.OARRAYLIT n.Type = types.NewArray(elemType, length) n.Right = nil return n @@ -2847,21 +2848,21 @@ func typecheckcomplit(n *Node) (res *Node) { base.Errorf("invalid composite literal type %v", t) n.Type = nil - case TARRAY: + case types.TARRAY: typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice(), "array literal") - n.Op = OARRAYLIT + n.Op = ir.OARRAYLIT n.Right = nil - case TSLICE: + case types.TSLICE: length := typecheckarraylit(t.Elem(), -1, n.List.Slice(), "slice literal") - n.Op = OSLICELIT + n.Op = ir.OSLICELIT n.Right = nodintconst(length) - case TMAP: + case types.TMAP: var cs constSet for i3, l := range n.List.Slice() { setlineno(l) - if l.Op != OKEY { + if l.Op != ir.OKEY { n.List.SetIndex(i3, typecheck(l, ctxExpr)) base.Errorf("missing key in map literal") continue @@ -2879,10 +2880,10 @@ func typecheckcomplit(n *Node) (res *Node) { l.Right = assignconv(r, t.Elem(), "map value") } - n.Op = OMAPLIT + n.Op = ir.OMAPLIT n.Right = nil - case TSTRUCT: + case types.TSTRUCT: // Need valid field offsets for Xoffset below. dowidth(t) @@ -2904,12 +2905,12 @@ func typecheckcomplit(n *Node) (res *Node) { f := t.Field(i) s := f.Sym - if s != nil && !types.IsExported(s.Name) && s.Pkg != localpkg { + if s != nil && !types.IsExported(s.Name) && s.Pkg != ir.LocalPkg { base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t) } // No pushtype allowed here. Must name fields for that. n1 = assignconv(n1, f.Type, "field value") - n1 = nodSym(OSTRUCTKEY, n1, f.Sym) + n1 = nodSym(ir.OSTRUCTKEY, n1, f.Sym) n1.Xoffset = f.Offset ls[i] = n1 } @@ -2924,10 +2925,10 @@ func typecheckcomplit(n *Node) (res *Node) { for i, l := range ls { setlineno(l) - if l.Op == OKEY { + if l.Op == ir.OKEY { key := l.Left - l.Op = OSTRUCTKEY + l.Op = ir.OSTRUCTKEY l.Left = l.Right l.Right = nil @@ -2935,7 +2936,7 @@ func typecheckcomplit(n *Node) (res *Node) { // the field to the right of the dot, // so s will be non-nil, but an OXDOT // is never a valid struct literal key. - if key.Sym == nil || key.Op == OXDOT || key.Sym.IsBlank() { + if key.Sym == nil || key.Op == ir.OXDOT || key.Sym.IsBlank() { base.Errorf("invalid field name %v in struct initializer", key) l.Left = typecheck(l.Left, ctxExpr) continue @@ -2945,7 +2946,7 @@ func typecheckcomplit(n *Node) (res *Node) { // package, because of import dot. Redirect to correct sym // before we do the lookup. s := key.Sym - if s.Pkg != localpkg && types.IsExported(s.Name) { + if s.Pkg != ir.LocalPkg && types.IsExported(s.Name) { s1 := lookup(s.Name) if s1.Origpkg == s.Pkg { s = s1 @@ -2954,7 +2955,7 @@ func typecheckcomplit(n *Node) (res *Node) { l.Sym = s } - if l.Op != OSTRUCTKEY { + if l.Op != ir.OSTRUCTKEY { if !errored { base.Errorf("mixture of field:value and value initializers") errored = true @@ -2999,7 +3000,7 @@ func typecheckcomplit(n *Node) (res *Node) { } } - n.Op = OSTRUCTLIT + n.Op = ir.OSTRUCTLIT n.Right = nil } @@ -3007,12 +3008,12 @@ func typecheckcomplit(n *Node) (res *Node) { } // typecheckarraylit type-checks a sequence of slice/array literal elements. -func typecheckarraylit(elemType *types.Type, bound int64, elts []*Node, ctx string) int64 { +func typecheckarraylit(elemType *types.Type, bound int64, elts []*ir.Node, ctx string) int64 { // If there are key/value pairs, create a map to keep seen // keys so we can check for duplicate indices. var indices map[int64]bool for _, elt := range elts { - if elt.Op == OKEY { + if elt.Op == ir.OKEY { indices = make(map[int64]bool) break } @@ -3022,8 +3023,8 @@ func typecheckarraylit(elemType *types.Type, bound int64, elts []*Node, ctx stri for i, elt := range elts { setlineno(elt) r := elts[i] - var kv *Node - if elt.Op == OKEY { + var kv *ir.Node + if elt.Op == ir.OKEY { elt.Left = typecheck(elt.Left, ctxExpr) key = indexconst(elt.Left) if key < 0 { @@ -3076,7 +3077,7 @@ func typecheckarraylit(elemType *types.Type, bound int64, elts []*Node, ctx stri // visible reports whether sym is exported or locally defined. func visible(sym *types.Sym) bool { - return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == localpkg) + return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == ir.LocalPkg) } // nonexported reports whether sym is an unexported field. @@ -3085,9 +3086,9 @@ func nonexported(sym *types.Sym) bool { } // lvalue etc -func islvalue(n *Node) bool { +func islvalue(n *ir.Node) bool { switch n.Op { - case OINDEX: + case ir.OINDEX: if n.Left.Type != nil && n.Left.Type.IsArray() { return islvalue(n.Left) } @@ -3095,14 +3096,14 @@ func islvalue(n *Node) bool { return false } fallthrough - case ODEREF, ODOTPTR, OCLOSUREVAR: + case ir.ODEREF, ir.ODOTPTR, ir.OCLOSUREVAR: return true - case ODOT: + case ir.ODOT: return islvalue(n.Left) - case ONAME: - if n.Class() == PFUNC { + case ir.ONAME: + if n.Class() == ir.PFUNC { return false } return true @@ -3111,17 +3112,17 @@ func islvalue(n *Node) bool { return false } -func checklvalue(n *Node, verb string) { +func checklvalue(n *ir.Node, verb string) { if !islvalue(n) { base.Errorf("cannot %s %v", verb, n) } } -func checkassign(stmt *Node, n *Node) { +func checkassign(stmt *ir.Node, n *ir.Node) { // Variables declared in ORANGE are assigned on every iteration. - if n.Name == nil || n.Name.Defn != stmt || stmt.Op == ORANGE { + if n.Name == nil || n.Name.Defn != stmt || stmt.Op == ir.ORANGE { r := outervalue(n) - if r.Op == ONAME { + if r.Op == ir.ONAME { r.Name.SetAssigned(true) if r.Name.IsClosureVar() { r.Name.Defn.Name.SetAssigned(true) @@ -3132,7 +3133,7 @@ func checkassign(stmt *Node, n *Node) { if islvalue(n) { return } - if n.Op == OINDEXMAP { + if n.Op == ir.OINDEXMAP { n.SetIndexMapLValue(true) return } @@ -3143,11 +3144,11 @@ func checkassign(stmt *Node, n *Node) { } switch { - case n.Op == ODOT && n.Left.Op == OINDEXMAP: + case n.Op == ir.ODOT && n.Left.Op == ir.OINDEXMAP: base.Errorf("cannot assign to struct field %v in map", n) - case (n.Op == OINDEX && n.Left.Type.IsString()) || n.Op == OSLICESTR: + case (n.Op == ir.OINDEX && n.Left.Type.IsString()) || n.Op == ir.OSLICESTR: base.Errorf("cannot assign to %v (strings are immutable)", n) - case n.Op == OLITERAL && n.Sym != nil && n.isGoConst(): + case n.Op == ir.OLITERAL && n.Sym != nil && isGoConst(n): base.Errorf("cannot assign to %v (declared const)", n) default: base.Errorf("cannot assign to %v", n) @@ -3155,7 +3156,7 @@ func checkassign(stmt *Node, n *Node) { n.Type = nil } -func checkassignlist(stmt *Node, l Nodes) { +func checkassignlist(stmt *ir.Node, l ir.Nodes) { for _, n := range l.Slice() { checkassign(stmt, n) } @@ -3176,35 +3177,35 @@ func checkassignlist(stmt *Node, l Nodes) { // currently OK, since the only place samesafeexpr gets used on an // lvalue expression is for OSLICE and OAPPEND optimizations, and it // is correct in those settings. -func samesafeexpr(l *Node, r *Node) bool { +func samesafeexpr(l *ir.Node, r *ir.Node) bool { if l.Op != r.Op || !types.Identical(l.Type, r.Type) { return false } switch l.Op { - case ONAME, OCLOSUREVAR: + case ir.ONAME, ir.OCLOSUREVAR: return l == r - case ODOT, ODOTPTR: + case ir.ODOT, ir.ODOTPTR: return l.Sym != nil && r.Sym != nil && l.Sym == r.Sym && samesafeexpr(l.Left, r.Left) - case ODEREF, OCONVNOP, - ONOT, OBITNOT, OPLUS, ONEG: + case ir.ODEREF, ir.OCONVNOP, + ir.ONOT, ir.OBITNOT, ir.OPLUS, ir.ONEG: return samesafeexpr(l.Left, r.Left) - case OCONV: + case ir.OCONV: // Some conversions can't be reused, such as []byte(str). // Allow only numeric-ish types. This is a bit conservative. return issimple[l.Type.Etype] && samesafeexpr(l.Left, r.Left) - case OINDEX, OINDEXMAP, - OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD: + case ir.OINDEX, ir.OINDEXMAP, + ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD: return samesafeexpr(l.Left, r.Left) && samesafeexpr(l.Right, r.Right) - case OLITERAL: + case ir.OLITERAL: return constant.Compare(l.Val(), token.EQL, r.Val()) - case ONIL: + case ir.ONIL: return true } @@ -3214,7 +3215,7 @@ func samesafeexpr(l *Node, r *Node) bool { // type check assignment. // if this assignment is the definition of a var on the left side, // fill in the var's type. -func typecheckas(n *Node) { +func typecheckas(n *ir.Node) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckas", n)(nil) } @@ -3260,19 +3261,19 @@ func typecheckas(n *Node) { if n.Left.Typecheck() == 0 { n.Left = typecheck(n.Left, ctxExpr|ctxAssign) } - if !n.Left.isBlank() { + if !ir.IsBlank(n.Left) { checkwidth(n.Left.Type) // ensure width is calculated for backend } } -func checkassignto(src *types.Type, dst *Node) { - if op, why := assignop(src, dst.Type); op == OXXX { +func checkassignto(src *types.Type, dst *ir.Node) { + 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 } } -func typecheckas2(n *Node) { +func typecheckas2(n *ir.Node) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckas2", n)(nil) } @@ -3297,8 +3298,8 @@ func typecheckas2(n *Node) { } checkassignlist(n, n.List) - var l *Node - var r *Node + var l *ir.Node + var r *ir.Node if cl == cr { // easy ls := n.List.Slice() @@ -3326,7 +3327,7 @@ func typecheckas2(n *Node) { goto out } switch r.Op { - case OCALLMETH, OCALLINTER, OCALLFUNC: + case ir.OCALLMETH, ir.OCALLINTER, ir.OCALLFUNC: if !r.Type.IsFuncArgStruct() { break } @@ -3334,7 +3335,7 @@ func typecheckas2(n *Node) { if cr != cl { goto mismatch } - n.Op = OAS2FUNC + n.Op = ir.OAS2FUNC n.Right = r n.Rlist.Set(nil) for i, l := range n.List.Slice() { @@ -3356,15 +3357,15 @@ func typecheckas2(n *Node) { goto out } switch r.Op { - case OINDEXMAP, ORECV, ODOTTYPE: + case ir.OINDEXMAP, ir.ORECV, ir.ODOTTYPE: switch r.Op { - case OINDEXMAP: - n.Op = OAS2MAPR - case ORECV: - n.Op = OAS2RECV - case ODOTTYPE: - n.Op = OAS2DOTTYPE - r.Op = ODOTTYPE2 + case ir.OINDEXMAP: + n.Op = ir.OAS2MAPR + case ir.ORECV: + n.Op = ir.OAS2RECV + case ir.ODOTTYPE: + n.Op = ir.OAS2DOTTYPE + r.Op = ir.ODOTTYPE2 } n.Right = r n.Rlist.Set(nil) @@ -3376,10 +3377,10 @@ func typecheckas2(n *Node) { } l := n.List.Second() if l.Type != nil && !l.Type.IsBoolean() { - checkassignto(types.Types[TBOOL], l) + checkassignto(types.Types[types.TBOOL], l) } if l.Name != nil && l.Name.Defn == n && l.Name.Param.Ntype == nil { - l.Type = types.Types[TBOOL] + l.Type = types.Types[types.TBOOL] } goto out } @@ -3389,7 +3390,7 @@ mismatch: switch r.Op { default: base.Errorf("assignment mismatch: %d variables but %d values", cl, cr) - case OCALLFUNC, OCALLMETH, OCALLINTER: + case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: base.Errorf("assignment mismatch: %d variables but %v returns %d values", cl, r.Left, cr) } @@ -3405,13 +3406,13 @@ out: } // type check function definition -func typecheckfunc(n *Node) { +func typecheckfunc(n *ir.Node) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckfunc", n)(nil) } for _, ln := range n.Func.Dcl { - if ln.Op == ONAME && (ln.Class() == PPARAM || ln.Class() == PPARAMOUT) { + if ln.Op == ir.ONAME && (ln.Class() == ir.PPARAM || ln.Class() == ir.PPARAMOUT) { ln.Name.Decldepth = 1 } } @@ -3424,13 +3425,13 @@ func typecheckfunc(n *Node) { n.Type = t rcvr := t.Recv() if rcvr != nil && n.Func.Shortname != nil { - m := addmethod(n, n.Func.Shortname, t, true, n.Func.Pragma&Nointerface != 0) + m := addmethod(n, n.Func.Shortname, t, true, n.Func.Pragma&ir.Nointerface != 0) if m == nil { return } n.Func.Nname.Sym = methodSym(rcvr.Type, n.Func.Shortname) - declare(n.Func.Nname, PFUNC) + declare(n.Func.Nname, ir.PFUNC) } if base.Ctxt.Flag_dynlink && !inimport && n.Func.Nname != nil { @@ -3440,25 +3441,25 @@ func typecheckfunc(n *Node) { // The result of stringtoruneslit MUST be assigned back to n, e.g. // n.Left = stringtoruneslit(n.Left) -func stringtoruneslit(n *Node) *Node { - if n.Left.Op != OLITERAL || n.Left.Val().Kind() != constant.String { +func stringtoruneslit(n *ir.Node) *ir.Node { + if n.Left.Op != ir.OLITERAL || n.Left.Val().Kind() != constant.String { base.Fatalf("stringtoarraylit %v", n) } - var l []*Node + var l []*ir.Node i := 0 for _, r := range n.Left.StringVal() { - l = append(l, nod(OKEY, nodintconst(int64(i)), nodintconst(int64(r)))) + l = append(l, ir.Nod(ir.OKEY, nodintconst(int64(i)), nodintconst(int64(r)))) i++ } - nn := nod(OCOMPLIT, nil, typenod(n.Type)) + nn := ir.Nod(ir.OCOMPLIT, nil, typenod(n.Type)) nn.List.Set(l) nn = typecheck(nn, ctxExpr) return nn } -var mapqueue []*Node +var mapqueue []*ir.Node func checkMapKeys() { for _, n := range mapqueue { @@ -3471,13 +3472,13 @@ func checkMapKeys() { } func setUnderlying(t, underlying *types.Type) { - if underlying.Etype == TFORW { + if underlying.Etype == types.TFORW { // This type isn't computed yet; when it is, update n. underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t) return } - n := asNode(t.Nod) + n := ir.AsNode(t.Nod) ft := t.ForwardType() cache := t.Cache @@ -3485,7 +3486,7 @@ func setUnderlying(t, underlying *types.Type) { *t = *underlying // Restore unnecessarily clobbered attributes. - t.Nod = asTypesNode(n) + t.Nod = ir.AsTypesNode(n) t.Sym = n.Sym if n.Name != nil { t.Vargen = n.Name.Vargen @@ -3502,7 +3503,7 @@ func setUnderlying(t, underlying *types.Type) { } // Propagate go:notinheap pragma from the Name to the Type. - if n.Name != nil && n.Name.Param != nil && n.Name.Param.Pragma()&NotInHeap != 0 { + if n.Name != nil && n.Name.Param != nil && n.Name.Param.Pragma()&ir.NotInHeap != 0 { t.SetNotInHeap(true) } @@ -3519,7 +3520,7 @@ func setUnderlying(t, underlying *types.Type) { } } -func typecheckdeftype(n *Node) { +func typecheckdeftype(n *ir.Node) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckdeftype", n)(nil) } @@ -3539,14 +3540,14 @@ func typecheckdeftype(n *Node) { } } -func typecheckdef(n *Node) { +func typecheckdef(n *ir.Node) { if enableTrace && base.Flag.LowerT { defer tracePrint("typecheckdef", n)(nil) } lno := setlineno(n) - if n.Op == ONONAME { + if n.Op == ir.ONONAME { if !n.Diag() { n.SetDiag(true) @@ -3585,7 +3586,7 @@ func typecheckdef(n *Node) { default: base.Fatalf("typecheckdef %v", n.Op) - case OLITERAL: + case ir.OLITERAL: if n.Name.Param.Ntype != nil { n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, ctxType) n.Type = n.Name.Param.Ntype.Type @@ -3599,7 +3600,7 @@ func typecheckdef(n *Node) { e := n.Name.Defn n.Name.Defn = nil if e == nil { - Dump("typecheckdef nil defn", n) + ir.Dump("typecheckdef nil defn", n) base.ErrorfAt(n.Pos, "xxx") } @@ -3607,9 +3608,9 @@ func typecheckdef(n *Node) { if e.Type == nil { goto ret } - if !e.isGoConst() { + if !isGoConst(e) { if !e.Diag() { - if e.Op == ONIL { + if e.Op == ir.ONIL { base.ErrorfAt(n.Pos, "const initializer cannot be nil") } else { base.ErrorfAt(n.Pos, "const initializer %v is not a constant", e) @@ -3621,7 +3622,7 @@ func typecheckdef(n *Node) { t := n.Type if t != nil { - if !okforconst[t.Etype] { + if !ir.OKForConst[t.Etype] { base.ErrorfAt(n.Pos, "invalid constant type %v", t) goto ret } @@ -3639,7 +3640,7 @@ func typecheckdef(n *Node) { n.SetVal(e.Val()) } - case ONAME: + case ir.ONAME: if n.Name.Param.Ntype != nil { n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, ctxType) n.Type = n.Name.Param.Ntype.Type @@ -3667,7 +3668,7 @@ func typecheckdef(n *Node) { base.Fatalf("var without type, init: %v", n.Sym) } - if n.Name.Defn.Op == ONAME { + if n.Name.Defn.Op == ir.ONAME { n.Name.Defn = typecheck(n.Name.Defn, ctxExpr) n.Type = n.Name.Defn.Type break @@ -3675,7 +3676,7 @@ func typecheckdef(n *Node) { n.Name.Defn = typecheck(n.Name.Defn, ctxStmt) // fills in n.Type - case OTYPE: + case ir.OTYPE: if p := n.Name.Param; p.Alias() { // Type alias declaration: Simply use the rhs type - no need // to create a new type. @@ -3690,7 +3691,7 @@ func typecheckdef(n *Node) { // For package-level type aliases, set n.Sym.Def so we can identify // it as a type alias during export. See also #31959. if n.Name.Curfn == nil { - n.Sym.Def = asTypesNode(p.Ntype) + n.Sym.Def = ir.AsTypesNode(p.Ntype) } } break @@ -3699,11 +3700,11 @@ func typecheckdef(n *Node) { // regular type declaration defercheckwidth() n.SetWalkdef(1) - setTypeNode(n, types.New(TFORW)) + setTypeNode(n, types.New(types.TFORW)) n.Type.Sym = n.Sym errorsBefore := base.Errors() typecheckdeftype(n) - if n.Type.Etype == TFORW && base.Errors() > errorsBefore { + if n.Type.Etype == types.TFORW && base.Errors() > errorsBefore { // Something went wrong during type-checking, // but it was reported. Silence future errors. n.Type.SetBroke(true) @@ -3712,7 +3713,7 @@ func typecheckdef(n *Node) { } ret: - if n.Op != OLITERAL && n.Type != nil && n.Type.IsUntyped() { + if n.Op != ir.OLITERAL && n.Type != nil && n.Type.IsUntyped() { base.Fatalf("got %v for %v", n.Type, n) } last := len(typecheckdefstack) - 1 @@ -3726,22 +3727,22 @@ ret: n.SetWalkdef(1) } -func checkmake(t *types.Type, arg string, np **Node) bool { +func checkmake(t *types.Type, arg string, np **ir.Node) bool { n := *np - if !n.Type.IsInteger() && n.Type.Etype != TIDEAL { + if !n.Type.IsInteger() && n.Type.Etype != types.TIDEAL { base.Errorf("non-integer %s argument in make(%v) - %v", arg, t, n.Type) return false } // Do range checks for constants before defaultlit // to avoid redundant "constant NNN overflows int" errors. - if n.Op == OLITERAL { + if n.Op == ir.OLITERAL { v := toint(n.Val()) if constant.Sign(v) < 0 { base.Errorf("negative %s argument in make(%v)", arg, t) return false } - if doesoverflow(v, types.Types[TINT]) { + if doesoverflow(v, types.Types[types.TINT]) { base.Errorf("%s argument too large in make(%v)", arg, t) return false } @@ -3752,30 +3753,30 @@ func checkmake(t *types.Type, arg string, np **Node) bool { // are the same as for index expressions. Factor the code better; // for instance, indexlit might be called here and incorporate some // of the bounds checks done for make. - n = defaultlit(n, types.Types[TINT]) + n = defaultlit(n, types.Types[types.TINT]) *np = n return true } -func markbreak(n *Node, implicit *Node) { +func markbreak(n *ir.Node, implicit *ir.Node) { if n == nil { return } switch n.Op { - case OBREAK: + case ir.OBREAK: if n.Sym == nil { if implicit != nil { implicit.SetHasBreak(true) } } else { - lab := asNode(n.Sym.Label) + lab := ir.AsNode(n.Sym.Label) if lab != nil { lab.SetHasBreak(true) } } - case OFOR, OFORUNTIL, OSWITCH, OTYPESW, OSELECT, ORANGE: + case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OTYPESW, ir.OSELECT, ir.ORANGE: implicit = n fallthrough default: @@ -3788,17 +3789,17 @@ func markbreak(n *Node, implicit *Node) { } } -func markbreaklist(l Nodes, implicit *Node) { +func markbreaklist(l ir.Nodes, implicit *ir.Node) { s := l.Slice() for i := 0; i < len(s); i++ { n := s[i] if n == nil { continue } - if n.Op == OLABEL && i+1 < len(s) && n.Name.Defn == s[i+1] { + if n.Op == ir.OLABEL && i+1 < len(s) && n.Name.Defn == s[i+1] { switch n.Name.Defn.Op { - case OFOR, OFORUNTIL, OSWITCH, OTYPESW, OSELECT, ORANGE: - n.Sym.Label = asTypesNode(n.Name.Defn) + case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OTYPESW, ir.OSELECT, ir.ORANGE: + n.Sym.Label = ir.AsTypesNode(n.Name.Defn) markbreak(n.Name.Defn, n.Name.Defn) n.Sym.Label = nil i++ @@ -3811,31 +3812,31 @@ func markbreaklist(l Nodes, implicit *Node) { } // isterminating reports whether the Nodes list ends with a terminating statement. -func (l Nodes) isterminating() bool { +func isTermNodes(l ir.Nodes) bool { s := l.Slice() c := len(s) if c == 0 { return false } - return s[c-1].isterminating() + return isTermNode(s[c-1]) } // Isterminating reports whether the node n, the last one in a // statement list, is a terminating statement. -func (n *Node) isterminating() bool { +func isTermNode(n *ir.Node) bool { switch n.Op { // NOTE: OLABEL is treated as a separate statement, // not a separate prefix, so skipping to the last statement // in the block handles the labeled statement case by // skipping over the label. No case OLABEL here. - case OBLOCK: - return n.List.isterminating() + case ir.OBLOCK: + return isTermNodes(n.List) - case OGOTO, ORETURN, ORETJMP, OPANIC, OFALL: + case ir.OGOTO, ir.ORETURN, ir.ORETJMP, ir.OPANIC, ir.OFALL: return true - case OFOR, OFORUNTIL: + case ir.OFOR, ir.OFORUNTIL: if n.Left != nil { return false } @@ -3844,16 +3845,16 @@ func (n *Node) isterminating() bool { } return true - case OIF: - return n.Nbody.isterminating() && n.Rlist.isterminating() + case ir.OIF: + return isTermNodes(n.Nbody) && isTermNodes(n.Rlist) - case OSWITCH, OTYPESW, OSELECT: + case ir.OSWITCH, ir.OTYPESW, ir.OSELECT: if n.HasBreak() { return false } def := false for _, n1 := range n.List.Slice() { - if !n1.Nbody.isterminating() { + if !isTermNodes(n1.Nbody) { return false } if n1.List.Len() == 0 { // default @@ -3861,7 +3862,7 @@ func (n *Node) isterminating() bool { } } - if n.Op != OSELECT && !def { + if n.Op != ir.OSELECT && !def { return false } return true @@ -3871,21 +3872,21 @@ func (n *Node) isterminating() bool { } // checkreturn makes sure that fn terminates appropriately. -func checkreturn(fn *Node) { +func checkreturn(fn *ir.Node) { if fn.Type.NumResults() != 0 && fn.Nbody.Len() != 0 { markbreaklist(fn.Nbody, nil) - if !fn.Nbody.isterminating() { + if !isTermNodes(fn.Nbody) { base.ErrorfAt(fn.Func.Endlineno, "missing return at end of function") } } } -func deadcode(fn *Node) { +func deadcode(fn *ir.Node) { deadcodeslice(&fn.Nbody) deadcodefn(fn) } -func deadcodefn(fn *Node) { +func deadcodefn(fn *ir.Node) { if fn.Nbody.Len() == 0 { return } @@ -3895,12 +3896,12 @@ func deadcodefn(fn *Node) { return } switch n.Op { - case OIF: - if !Isconst(n.Left, constant.Bool) || n.Nbody.Len() > 0 || n.Rlist.Len() > 0 { + case ir.OIF: + if !ir.IsConst(n.Left, constant.Bool) || n.Nbody.Len() > 0 || n.Rlist.Len() > 0 { return } - case OFOR: - if !Isconst(n.Left, constant.Bool) || n.Left.BoolVal() { + case ir.OFOR: + if !ir.IsConst(n.Left, constant.Bool) || n.Left.BoolVal() { return } default: @@ -3908,13 +3909,13 @@ func deadcodefn(fn *Node) { } } - fn.Nbody.Set([]*Node{nod(OEMPTY, nil, nil)}) + fn.Nbody.Set([]*ir.Node{ir.Nod(ir.OEMPTY, nil, nil)}) } -func deadcodeslice(nn *Nodes) { +func deadcodeslice(nn *ir.Nodes) { var lastLabel = -1 for i, n := range nn.Slice() { - if n != nil && n.Op == OLABEL { + if n != nil && n.Op == ir.OLABEL { lastLabel = i } } @@ -3926,15 +3927,15 @@ func deadcodeslice(nn *Nodes) { if n == nil { continue } - if n.Op == OIF { + if n.Op == ir.OIF { n.Left = deadcodeexpr(n.Left) - if Isconst(n.Left, constant.Bool) { - var body Nodes + if ir.IsConst(n.Left, constant.Bool) { + var body ir.Nodes if n.Left.BoolVal() { - n.Rlist = Nodes{} + n.Rlist = ir.Nodes{} body = n.Nbody } else { - n.Nbody = Nodes{} + n.Nbody = ir.Nodes{} body = n.Rlist } // If "then" or "else" branch ends with panic or return statement, @@ -3944,7 +3945,7 @@ func deadcodeslice(nn *Nodes) { // might be the target of a goto. See issue 28616. if body := body.Slice(); len(body) != 0 { switch body[(len(body) - 1)].Op { - case ORETURN, ORETJMP, OPANIC: + case ir.ORETURN, ir.ORETJMP, ir.OPANIC: if i > lastLabel { cut = true } @@ -3964,25 +3965,25 @@ func deadcodeslice(nn *Nodes) { } } -func deadcodeexpr(n *Node) *Node { +func deadcodeexpr(n *ir.Node) *ir.Node { // Perform dead-code elimination on short-circuited boolean // expressions involving constants with the intent of // producing a constant 'if' condition. switch n.Op { - case OANDAND: + case ir.OANDAND: n.Left = deadcodeexpr(n.Left) n.Right = deadcodeexpr(n.Right) - if Isconst(n.Left, constant.Bool) { + if ir.IsConst(n.Left, constant.Bool) { if n.Left.BoolVal() { return n.Right // true && x => x } else { return n.Left // false && x => false } } - case OOROR: + case ir.OOROR: n.Left = deadcodeexpr(n.Left) n.Right = deadcodeexpr(n.Right) - if Isconst(n.Left, constant.Bool) { + if ir.IsConst(n.Left, constant.Bool) { if n.Left.BoolVal() { return n.Left // true || x => true } else { @@ -3994,17 +3995,17 @@ func deadcodeexpr(n *Node) *Node { } // setTypeNode sets n to an OTYPE node representing t. -func setTypeNode(n *Node, t *types.Type) { - n.Op = OTYPE +func setTypeNode(n *ir.Node, t *types.Type) { + n.Op = ir.OTYPE n.Type = t - n.Type.Nod = asTypesNode(n) + n.Type.Nod = ir.AsTypesNode(n) } // getIotaValue returns the current value for "iota", // or -1 if not within a ConstSpec. func getIotaValue() int64 { if i := len(typecheckdefstack); i > 0 { - if x := typecheckdefstack[i-1]; x.Op == OLITERAL { + if x := typecheckdefstack[i-1]; x.Op == ir.OLITERAL { return x.Iota() } } @@ -4021,12 +4022,12 @@ func curpkg() *types.Pkg { fn := Curfn if fn == nil { // Initialization expressions for package-scope variables. - return localpkg + return ir.LocalPkg } // TODO(mdempsky): Standardize on either ODCLFUNC or ONAME for // Curfn, rather than mixing them. - if fn.Op == ODCLFUNC { + if fn.Op == ir.ODCLFUNC { fn = fn.Func.Nname } @@ -4036,16 +4037,16 @@ func curpkg() *types.Pkg { // MethodName returns the ONAME representing the method // referenced by expression n, which must be a method selector, // method expression, or method value. -func (n *Node) MethodName() *Node { - return asNode(n.MethodFunc().Nname) +func methodExprName(n *ir.Node) *ir.Node { + return ir.AsNode(methodExprFunc(n).Nname) } // MethodFunc is like MethodName, but returns the types.Field instead. -func (n *Node) MethodFunc() *types.Field { +func methodExprFunc(n *ir.Node) *types.Field { switch n.Op { - case ODOTMETH, OMETHEXPR: + case ir.ODOTMETH, ir.OMETHEXPR: return n.Opt().(*types.Field) - case OCALLPART: + case ir.OCALLPART: return callpartMethod(n) } base.Fatalf("unexpected node: %v (%v)", n, n.Op) diff --git a/src/cmd/compile/internal/gc/types.go b/src/cmd/compile/internal/gc/types.go index 748f8458bdb..e46735df28d 100644 --- a/src/cmd/compile/internal/gc/types.go +++ b/src/cmd/compile/internal/gc/types.go @@ -3,56 +3,3 @@ // license that can be found in the LICENSE file. package gc - -import ( - "cmd/compile/internal/types" -) - -// convenience constants -const ( - Txxx = types.Txxx - - TINT8 = types.TINT8 - TUINT8 = types.TUINT8 - TINT16 = types.TINT16 - TUINT16 = types.TUINT16 - TINT32 = types.TINT32 - TUINT32 = types.TUINT32 - TINT64 = types.TINT64 - TUINT64 = types.TUINT64 - TINT = types.TINT - TUINT = types.TUINT - TUINTPTR = types.TUINTPTR - - TCOMPLEX64 = types.TCOMPLEX64 - TCOMPLEX128 = types.TCOMPLEX128 - - TFLOAT32 = types.TFLOAT32 - TFLOAT64 = types.TFLOAT64 - - TBOOL = types.TBOOL - - TPTR = types.TPTR - TFUNC = types.TFUNC - TSLICE = types.TSLICE - TARRAY = types.TARRAY - TSTRUCT = types.TSTRUCT - TCHAN = types.TCHAN - TMAP = types.TMAP - TINTER = types.TINTER - TFORW = types.TFORW - TANY = types.TANY - TSTRING = types.TSTRING - TUNSAFEPTR = types.TUNSAFEPTR - - // pseudo-types for literals - TIDEAL = types.TIDEAL - TNIL = types.TNIL - TBLANK = types.TBLANK - - // pseudo-types for frame layout - TFUNCARGS = types.TFUNCARGS - TCHANARGS = types.TCHANARGS - - NTYPE = types.NTYPE -) diff --git a/src/cmd/compile/internal/gc/types_acc.go b/src/cmd/compile/internal/gc/types_acc.go index 7240f726f62..d6d53f05cc9 100644 --- a/src/cmd/compile/internal/gc/types_acc.go +++ b/src/cmd/compile/internal/gc/types_acc.go @@ -6,11 +6,3 @@ // TODO(gri) try to eliminate these soon package gc - -import ( - "cmd/compile/internal/types" - "unsafe" -) - -func asNode(n *types.Node) *Node { return (*Node)(unsafe.Pointer(n)) } -func asTypesNode(n *Node) *types.Node { return (*types.Node)(unsafe.Pointer(n)) } diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index aa0ee4075dd..bf31055dcc1 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -8,31 +8,29 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/src" ) -// builtinpkg is a fake package that declares the universe block. -var builtinpkg *types.Pkg - var basicTypes = [...]struct { name string etype types.EType }{ - {"int8", TINT8}, - {"int16", TINT16}, - {"int32", TINT32}, - {"int64", TINT64}, - {"uint8", TUINT8}, - {"uint16", TUINT16}, - {"uint32", TUINT32}, - {"uint64", TUINT64}, - {"float32", TFLOAT32}, - {"float64", TFLOAT64}, - {"complex64", TCOMPLEX64}, - {"complex128", TCOMPLEX128}, - {"bool", TBOOL}, - {"string", TSTRING}, + {"int8", types.TINT8}, + {"int16", types.TINT16}, + {"int32", types.TINT32}, + {"int64", types.TINT64}, + {"uint8", types.TUINT8}, + {"uint16", types.TUINT16}, + {"uint32", types.TUINT32}, + {"uint64", types.TUINT64}, + {"float32", types.TFLOAT32}, + {"float64", types.TFLOAT64}, + {"complex64", types.TCOMPLEX64}, + {"complex128", types.TCOMPLEX128}, + {"bool", types.TBOOL}, + {"string", types.TSTRING}, } var typedefs = [...]struct { @@ -41,30 +39,30 @@ var typedefs = [...]struct { sameas32 types.EType sameas64 types.EType }{ - {"int", TINT, TINT32, TINT64}, - {"uint", TUINT, TUINT32, TUINT64}, - {"uintptr", TUINTPTR, TUINT32, TUINT64}, + {"int", types.TINT, types.TINT32, types.TINT64}, + {"uint", types.TUINT, types.TUINT32, types.TUINT64}, + {"uintptr", types.TUINTPTR, types.TUINT32, types.TUINT64}, } var builtinFuncs = [...]struct { name string - op Op + op ir.Op }{ - {"append", OAPPEND}, - {"cap", OCAP}, - {"close", OCLOSE}, - {"complex", OCOMPLEX}, - {"copy", OCOPY}, - {"delete", ODELETE}, - {"imag", OIMAG}, - {"len", OLEN}, - {"make", OMAKE}, - {"new", ONEW}, - {"panic", OPANIC}, - {"print", OPRINT}, - {"println", OPRINTN}, - {"real", OREAL}, - {"recover", ORECOVER}, + {"append", ir.OAPPEND}, + {"cap", ir.OCAP}, + {"close", ir.OCLOSE}, + {"complex", ir.OCOMPLEX}, + {"copy", ir.OCOPY}, + {"delete", ir.ODELETE}, + {"imag", ir.OIMAG}, + {"len", ir.OLEN}, + {"make", ir.OMAKE}, + {"new", ir.ONEW}, + {"panic", ir.OPANIC}, + {"print", ir.OPRINT}, + {"println", ir.OPRINTN}, + {"real", ir.OREAL}, + {"recover", ir.ORECOVER}, } // isBuiltinFuncName reports whether name matches a builtin function @@ -80,11 +78,11 @@ func isBuiltinFuncName(name string) bool { var unsafeFuncs = [...]struct { name string - op Op + op ir.Op }{ - {"Alignof", OALIGNOF}, - {"Offsetof", OOFFSETOF}, - {"Sizeof", OSIZEOF}, + {"Alignof", ir.OALIGNOF}, + {"Offsetof", ir.OOFFSETOF}, + {"Sizeof", ir.OSIZEOF}, } // initUniverse initializes the universe block. @@ -101,71 +99,71 @@ func lexinit() { if int(etype) >= len(types.Types) { base.Fatalf("lexinit: %s bad etype", s.name) } - s2 := builtinpkg.Lookup(s.name) + s2 := ir.BuiltinPkg.Lookup(s.name) t := types.Types[etype] if t == nil { t = types.New(etype) t.Sym = s2 - if etype != TANY && etype != TSTRING { + if etype != types.TANY && etype != types.TSTRING { dowidth(t) } types.Types[etype] = t } - s2.Def = asTypesNode(typenod(t)) - asNode(s2.Def).Name = new(Name) + s2.Def = ir.AsTypesNode(typenod(t)) + ir.AsNode(s2.Def).Name = new(ir.Name) } for _, s := range &builtinFuncs { - s2 := builtinpkg.Lookup(s.name) - s2.Def = asTypesNode(newname(s2)) - asNode(s2.Def).SetSubOp(s.op) + s2 := ir.BuiltinPkg.Lookup(s.name) + s2.Def = ir.AsTypesNode(NewName(s2)) + ir.AsNode(s2.Def).SetSubOp(s.op) } for _, s := range &unsafeFuncs { s2 := unsafepkg.Lookup(s.name) - s2.Def = asTypesNode(newname(s2)) - asNode(s2.Def).SetSubOp(s.op) + s2.Def = ir.AsTypesNode(NewName(s2)) + ir.AsNode(s2.Def).SetSubOp(s.op) } - types.UntypedString = types.New(TSTRING) - types.UntypedBool = types.New(TBOOL) - types.Types[TANY] = types.New(TANY) + types.UntypedString = types.New(types.TSTRING) + types.UntypedBool = types.New(types.TBOOL) + types.Types[types.TANY] = types.New(types.TANY) - s := builtinpkg.Lookup("true") - s.Def = asTypesNode(nodbool(true)) - asNode(s.Def).Sym = lookup("true") - asNode(s.Def).Name = new(Name) - asNode(s.Def).Type = types.UntypedBool + s := ir.BuiltinPkg.Lookup("true") + s.Def = ir.AsTypesNode(nodbool(true)) + ir.AsNode(s.Def).Sym = lookup("true") + ir.AsNode(s.Def).Name = new(ir.Name) + ir.AsNode(s.Def).Type = types.UntypedBool - s = builtinpkg.Lookup("false") - s.Def = asTypesNode(nodbool(false)) - asNode(s.Def).Sym = lookup("false") - asNode(s.Def).Name = new(Name) - asNode(s.Def).Type = types.UntypedBool + s = ir.BuiltinPkg.Lookup("false") + s.Def = ir.AsTypesNode(nodbool(false)) + ir.AsNode(s.Def).Sym = lookup("false") + ir.AsNode(s.Def).Name = new(ir.Name) + ir.AsNode(s.Def).Type = types.UntypedBool s = lookup("_") s.Block = -100 - s.Def = asTypesNode(newname(s)) - types.Types[TBLANK] = types.New(TBLANK) - asNode(s.Def).Type = types.Types[TBLANK] - nblank = asNode(s.Def) + s.Def = ir.AsTypesNode(NewName(s)) + types.Types[types.TBLANK] = types.New(types.TBLANK) + ir.AsNode(s.Def).Type = types.Types[types.TBLANK] + ir.BlankNode = ir.AsNode(s.Def) - s = builtinpkg.Lookup("_") + s = ir.BuiltinPkg.Lookup("_") s.Block = -100 - s.Def = asTypesNode(newname(s)) - types.Types[TBLANK] = types.New(TBLANK) - asNode(s.Def).Type = types.Types[TBLANK] + s.Def = ir.AsTypesNode(NewName(s)) + types.Types[types.TBLANK] = types.New(types.TBLANK) + ir.AsNode(s.Def).Type = types.Types[types.TBLANK] - types.Types[TNIL] = types.New(TNIL) - s = builtinpkg.Lookup("nil") - s.Def = asTypesNode(nodnil()) - asNode(s.Def).Sym = s - asNode(s.Def).Name = new(Name) + types.Types[types.TNIL] = types.New(types.TNIL) + s = ir.BuiltinPkg.Lookup("nil") + s.Def = ir.AsTypesNode(nodnil()) + ir.AsNode(s.Def).Sym = s + ir.AsNode(s.Def).Name = new(ir.Name) - s = builtinpkg.Lookup("iota") - s.Def = asTypesNode(nod(OIOTA, nil, nil)) - asNode(s.Def).Sym = s - asNode(s.Def).Name = new(Name) + s = ir.BuiltinPkg.Lookup("iota") + s.Def = ir.AsTypesNode(ir.Nod(ir.OIOTA, nil, nil)) + ir.AsNode(s.Def).Sym = s + ir.AsNode(s.Def).Name = new(ir.Name) } func typeinit() { @@ -173,42 +171,42 @@ func typeinit() { base.Fatalf("typeinit before betypeinit") } - for et := types.EType(0); et < NTYPE; et++ { + for et := types.EType(0); et < types.NTYPE; et++ { simtype[et] = et } - types.Types[TPTR] = types.New(TPTR) - dowidth(types.Types[TPTR]) + types.Types[types.TPTR] = types.New(types.TPTR) + dowidth(types.Types[types.TPTR]) - t := types.New(TUNSAFEPTR) - types.Types[TUNSAFEPTR] = t + t := types.New(types.TUNSAFEPTR) + types.Types[types.TUNSAFEPTR] = t t.Sym = unsafepkg.Lookup("Pointer") - t.Sym.Def = asTypesNode(typenod(t)) - asNode(t.Sym.Def).Name = new(Name) - dowidth(types.Types[TUNSAFEPTR]) + t.Sym.Def = ir.AsTypesNode(typenod(t)) + ir.AsNode(t.Sym.Def).Name = new(ir.Name) + dowidth(types.Types[types.TUNSAFEPTR]) - for et := TINT8; et <= TUINT64; et++ { + for et := types.TINT8; et <= types.TUINT64; et++ { isInt[et] = true } - isInt[TINT] = true - isInt[TUINT] = true - isInt[TUINTPTR] = true + isInt[types.TINT] = true + isInt[types.TUINT] = true + isInt[types.TUINTPTR] = true - isFloat[TFLOAT32] = true - isFloat[TFLOAT64] = true + isFloat[types.TFLOAT32] = true + isFloat[types.TFLOAT64] = true - isComplex[TCOMPLEX64] = true - isComplex[TCOMPLEX128] = true + isComplex[types.TCOMPLEX64] = true + isComplex[types.TCOMPLEX128] = true // initialize okfor - for et := types.EType(0); et < NTYPE; et++ { - if isInt[et] || et == TIDEAL { + for et := types.EType(0); et < types.NTYPE; et++ { + if isInt[et] || et == types.TIDEAL { okforeq[et] = true okforcmp[et] = true okforarith[et] = true okforadd[et] = true okforand[et] = true - okforconst[et] = true + ir.OKForConst[et] = true issimple[et] = true } @@ -217,7 +215,7 @@ func typeinit() { okforcmp[et] = true okforadd[et] = true okforarith[et] = true - okforconst[et] = true + ir.OKForConst[et] = true issimple[et] = true } @@ -225,43 +223,43 @@ func typeinit() { okforeq[et] = true okforadd[et] = true okforarith[et] = true - okforconst[et] = true + ir.OKForConst[et] = true issimple[et] = true } } - issimple[TBOOL] = true + issimple[types.TBOOL] = true - okforadd[TSTRING] = true + okforadd[types.TSTRING] = true - okforbool[TBOOL] = true + okforbool[types.TBOOL] = true - okforcap[TARRAY] = true - okforcap[TCHAN] = true - okforcap[TSLICE] = true + okforcap[types.TARRAY] = true + okforcap[types.TCHAN] = true + okforcap[types.TSLICE] = true - okforconst[TBOOL] = true - okforconst[TSTRING] = true + ir.OKForConst[types.TBOOL] = true + ir.OKForConst[types.TSTRING] = true - okforlen[TARRAY] = true - okforlen[TCHAN] = true - okforlen[TMAP] = true - okforlen[TSLICE] = true - okforlen[TSTRING] = true + okforlen[types.TARRAY] = true + okforlen[types.TCHAN] = true + okforlen[types.TMAP] = true + okforlen[types.TSLICE] = true + okforlen[types.TSTRING] = true - okforeq[TPTR] = true - okforeq[TUNSAFEPTR] = true - okforeq[TINTER] = true - okforeq[TCHAN] = true - okforeq[TSTRING] = true - okforeq[TBOOL] = true - okforeq[TMAP] = true // nil only; refined in typecheck - okforeq[TFUNC] = true // nil only; refined in typecheck - okforeq[TSLICE] = true // nil only; refined in typecheck - okforeq[TARRAY] = true // only if element type is comparable; refined in typecheck - okforeq[TSTRUCT] = true // only if all struct fields are comparable; refined in typecheck + okforeq[types.TPTR] = true + okforeq[types.TUNSAFEPTR] = true + okforeq[types.TINTER] = true + okforeq[types.TCHAN] = true + okforeq[types.TSTRING] = true + okforeq[types.TBOOL] = true + okforeq[types.TMAP] = true // nil only; refined in typecheck + okforeq[types.TFUNC] = true // nil only; refined in typecheck + okforeq[types.TSLICE] = true // nil only; refined in typecheck + okforeq[types.TARRAY] = true // only if element type is comparable; refined in typecheck + okforeq[types.TSTRUCT] = true // only if all struct fields are comparable; refined in typecheck - okforcmp[TSTRING] = true + okforcmp[types.TSTRING] = true var i int for i = 0; i < len(okfor); i++ { @@ -269,51 +267,51 @@ func typeinit() { } // binary - okfor[OADD] = okforadd[:] - okfor[OAND] = okforand[:] - okfor[OANDAND] = okforbool[:] - okfor[OANDNOT] = okforand[:] - okfor[ODIV] = okforarith[:] - okfor[OEQ] = okforeq[:] - okfor[OGE] = okforcmp[:] - okfor[OGT] = okforcmp[:] - okfor[OLE] = okforcmp[:] - okfor[OLT] = okforcmp[:] - okfor[OMOD] = okforand[:] - okfor[OMUL] = okforarith[:] - okfor[ONE] = okforeq[:] - okfor[OOR] = okforand[:] - okfor[OOROR] = okforbool[:] - okfor[OSUB] = okforarith[:] - okfor[OXOR] = okforand[:] - okfor[OLSH] = okforand[:] - okfor[ORSH] = okforand[:] + okfor[ir.OADD] = okforadd[:] + okfor[ir.OAND] = okforand[:] + okfor[ir.OANDAND] = okforbool[:] + okfor[ir.OANDNOT] = okforand[:] + okfor[ir.ODIV] = okforarith[:] + okfor[ir.OEQ] = okforeq[:] + okfor[ir.OGE] = okforcmp[:] + okfor[ir.OGT] = okforcmp[:] + okfor[ir.OLE] = okforcmp[:] + okfor[ir.OLT] = okforcmp[:] + okfor[ir.OMOD] = okforand[:] + okfor[ir.OMUL] = okforarith[:] + okfor[ir.ONE] = okforeq[:] + okfor[ir.OOR] = okforand[:] + okfor[ir.OOROR] = okforbool[:] + okfor[ir.OSUB] = okforarith[:] + okfor[ir.OXOR] = okforand[:] + okfor[ir.OLSH] = okforand[:] + okfor[ir.ORSH] = okforand[:] // unary - okfor[OBITNOT] = okforand[:] - okfor[ONEG] = okforarith[:] - okfor[ONOT] = okforbool[:] - okfor[OPLUS] = okforarith[:] + okfor[ir.OBITNOT] = okforand[:] + okfor[ir.ONEG] = okforarith[:] + okfor[ir.ONOT] = okforbool[:] + okfor[ir.OPLUS] = okforarith[:] // special - okfor[OCAP] = okforcap[:] - okfor[OLEN] = okforlen[:] + okfor[ir.OCAP] = okforcap[:] + okfor[ir.OLEN] = okforlen[:] // comparison - iscmp[OLT] = true - iscmp[OGT] = true - iscmp[OGE] = true - iscmp[OLE] = true - iscmp[OEQ] = true - iscmp[ONE] = true + iscmp[ir.OLT] = true + iscmp[ir.OGT] = true + iscmp[ir.OGE] = true + iscmp[ir.OLE] = true + iscmp[ir.OEQ] = true + iscmp[ir.ONE] = true - types.Types[TINTER] = types.New(TINTER) // empty interface + types.Types[types.TINTER] = types.New(types.TINTER) // empty interface // simple aliases - simtype[TMAP] = TPTR - simtype[TCHAN] = TPTR - simtype[TFUNC] = TPTR - simtype[TUNSAFEPTR] = TPTR + simtype[types.TMAP] = types.TPTR + simtype[types.TCHAN] = types.TPTR + simtype[types.TFUNC] = types.TPTR + simtype[types.TUNSAFEPTR] = types.TPTR slicePtrOffset = 0 sliceLenOffset = Rnd(slicePtrOffset+int64(Widthptr), int64(Widthptr)) @@ -323,29 +321,29 @@ func typeinit() { // string is same as slice wo the cap sizeofString = Rnd(sliceLenOffset+int64(Widthptr), int64(Widthptr)) - dowidth(types.Types[TSTRING]) + dowidth(types.Types[types.TSTRING]) dowidth(types.UntypedString) } func makeErrorInterface() *types.Type { sig := functypefield(fakeRecvField(), nil, []*types.Field{ - types.NewField(src.NoXPos, nil, types.Types[TSTRING]), + types.NewField(src.NoXPos, nil, types.Types[types.TSTRING]), }) method := types.NewField(src.NoXPos, lookup("Error"), sig) - t := types.New(TINTER) + t := types.New(types.TINTER) t.SetInterface([]*types.Field{method}) return t } func lexinit1() { // error type - s := builtinpkg.Lookup("error") + s := ir.BuiltinPkg.Lookup("error") types.Errortype = makeErrorInterface() types.Errortype.Sym = s types.Errortype.Orig = makeErrorInterface() - s.Def = asTypesNode(typenod(types.Errortype)) + s.Def = ir.AsTypesNode(typenod(types.Errortype)) dowidth(types.Errortype) // We create separate byte and rune types for better error messages @@ -357,24 +355,24 @@ func lexinit1() { // type aliases, albeit at the cost of having to deal with it everywhere). // byte alias - s = builtinpkg.Lookup("byte") - types.Bytetype = types.New(TUINT8) + s = ir.BuiltinPkg.Lookup("byte") + types.Bytetype = types.New(types.TUINT8) types.Bytetype.Sym = s - s.Def = asTypesNode(typenod(types.Bytetype)) - asNode(s.Def).Name = new(Name) + s.Def = ir.AsTypesNode(typenod(types.Bytetype)) + ir.AsNode(s.Def).Name = new(ir.Name) dowidth(types.Bytetype) // rune alias - s = builtinpkg.Lookup("rune") - types.Runetype = types.New(TINT32) + s = ir.BuiltinPkg.Lookup("rune") + types.Runetype = types.New(types.TINT32) types.Runetype.Sym = s - s.Def = asTypesNode(typenod(types.Runetype)) - asNode(s.Def).Name = new(Name) + s.Def = ir.AsTypesNode(typenod(types.Runetype)) + ir.AsNode(s.Def).Name = new(ir.Name) dowidth(types.Runetype) // backend-dependent builtin types (e.g. int). for _, s := range &typedefs { - s1 := builtinpkg.Lookup(s.name) + s1 := ir.BuiltinPkg.Lookup(s.name) sameas := s.sameas32 if Widthptr == 8 { @@ -386,9 +384,9 @@ func lexinit1() { t := types.New(s.etype) t.Sym = s1 types.Types[s.etype] = t - s1.Def = asTypesNode(typenod(t)) - asNode(s1.Def).Name = new(Name) - s1.Origpkg = builtinpkg + s1.Def = ir.AsTypesNode(typenod(t)) + ir.AsNode(s1.Def).Name = new(ir.Name) + s1.Origpkg = ir.BuiltinPkg dowidth(t) } @@ -400,7 +398,7 @@ func finishUniverse() { // that we silently skip symbols that are already declared in the // package block rather than emitting a redeclared symbol error. - for _, s := range builtinpkg.Syms { + for _, s := range ir.BuiltinPkg.Syms { if s.Def == nil { continue } @@ -413,8 +411,8 @@ func finishUniverse() { s1.Block = s.Block } - nodfp = newname(lookup(".fp")) - nodfp.Type = types.Types[TINT32] - nodfp.SetClass(PPARAM) + nodfp = NewName(lookup(".fp")) + nodfp.Type = types.Types[types.TINT32] + nodfp.SetClass(ir.PPARAM) nodfp.Name.SetUsed(true) } diff --git a/src/cmd/compile/internal/gc/unsafe.go b/src/cmd/compile/internal/gc/unsafe.go index a1c1c1bf6e2..fce79a63196 100644 --- a/src/cmd/compile/internal/gc/unsafe.go +++ b/src/cmd/compile/internal/gc/unsafe.go @@ -4,12 +4,15 @@ package gc -import "cmd/compile/internal/base" +import ( + "cmd/compile/internal/base" + "cmd/compile/internal/ir" +) // evalunsafe evaluates a package unsafe operation and returns the result. -func evalunsafe(n *Node) int64 { +func evalunsafe(n *ir.Node) int64 { switch n.Op { - case OALIGNOF, OSIZEOF: + case ir.OALIGNOF, ir.OSIZEOF: n.Left = typecheck(n.Left, ctxExpr) n.Left = defaultlit(n.Left, nil) tr := n.Left.Type @@ -17,14 +20,14 @@ func evalunsafe(n *Node) int64 { return 0 } dowidth(tr) - if n.Op == OALIGNOF { + if n.Op == ir.OALIGNOF { return int64(tr.Align) } return tr.Width - case OOFFSETOF: + case ir.OOFFSETOF: // must be a selector. - if n.Left.Op != OXDOT { + if n.Left.Op != ir.OXDOT { base.Errorf("invalid expression %v", n) return 0 } @@ -40,9 +43,9 @@ func evalunsafe(n *Node) int64 { return 0 } switch n.Left.Op { - case ODOT, ODOTPTR: + case ir.ODOT, ir.ODOTPTR: break - case OCALLPART: + case ir.OCALLPART: base.Errorf("invalid expression %v: argument is a method value", n) return 0 default: @@ -54,7 +57,7 @@ func evalunsafe(n *Node) int64 { var v int64 for r := n.Left; r != sbase; r = r.Left { switch r.Op { - case ODOTPTR: + case ir.ODOTPTR: // For Offsetof(s.f), s may itself be a pointer, // but accessing f must not otherwise involve // indirection via embedded pointer types. @@ -63,10 +66,10 @@ func evalunsafe(n *Node) int64 { return 0 } fallthrough - case ODOT: + case ir.ODOT: v += r.Xoffset default: - Dump("unsafenmagic", n.Left) + ir.Dump("unsafenmagic", n.Left) base.Fatalf("impossible %#v node after dot insertion", r.Op) } } diff --git a/src/cmd/compile/internal/gc/util.go b/src/cmd/compile/internal/gc/util.go index 597a29a940e..4baddbc029a 100644 --- a/src/cmd/compile/internal/gc/util.go +++ b/src/cmd/compile/internal/gc/util.go @@ -12,12 +12,6 @@ import ( "cmd/compile/internal/base" ) -// Line returns n's position as a string. If n has been inlined, -// it uses the outermost position where n has been inlined. -func (n *Node) Line() string { - return base.FmtPos(n.Pos) -} - var ( memprofilerate int64 traceHandler func(string) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index d7cd7ddf27c..619a413b9e4 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/base" + "cmd/compile/internal/ir" "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/objabi" @@ -21,20 +22,20 @@ import ( const tmpstringbufsize = 32 const zeroValSize = 1024 // must match value of runtime/map.go:maxZero -func walk(fn *Node) { +func walk(fn *ir.Node) { Curfn = fn errorsBefore := base.Errors() if base.Flag.W != 0 { s := fmt.Sprintf("\nbefore walk %v", Curfn.Func.Nname.Sym) - dumplist(s, Curfn.Nbody) + ir.DumpList(s, Curfn.Nbody) } lno := base.Pos // Final typecheck for any unused variables. for i, ln := range fn.Func.Dcl { - if ln.Op == ONAME && (ln.Class() == PAUTO || ln.Class() == PAUTOHEAP) { + if ln.Op == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) { ln = typecheck(ln, ctxExpr|ctxAssign) fn.Func.Dcl[i] = ln } @@ -42,16 +43,16 @@ func walk(fn *Node) { // Propagate the used flag for typeswitch variables up to the NONAME in its definition. for _, ln := range fn.Func.Dcl { - if ln.Op == ONAME && (ln.Class() == PAUTO || ln.Class() == PAUTOHEAP) && ln.Name.Defn != nil && ln.Name.Defn.Op == OTYPESW && ln.Name.Used() { + if ln.Op == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) && ln.Name.Defn != nil && ln.Name.Defn.Op == ir.OTYPESW && ln.Name.Used() { ln.Name.Defn.Left.Name.SetUsed(true) } } for _, ln := range fn.Func.Dcl { - if ln.Op != ONAME || (ln.Class() != PAUTO && ln.Class() != PAUTOHEAP) || ln.Sym.Name[0] == '&' || ln.Name.Used() { + if ln.Op != ir.ONAME || (ln.Class() != ir.PAUTO && ln.Class() != ir.PAUTOHEAP) || ln.Sym.Name[0] == '&' || ln.Name.Used() { continue } - if defn := ln.Name.Defn; defn != nil && defn.Op == OTYPESW { + if defn := ln.Name.Defn; defn != nil && defn.Op == ir.OTYPESW { if defn.Left.Name.Used() { continue } @@ -69,32 +70,32 @@ func walk(fn *Node) { walkstmtlist(Curfn.Nbody.Slice()) if base.Flag.W != 0 { s := fmt.Sprintf("after walk %v", Curfn.Func.Nname.Sym) - dumplist(s, Curfn.Nbody) + ir.DumpList(s, Curfn.Nbody) } zeroResults() heapmoves() if base.Flag.W != 0 && Curfn.Func.Enter.Len() > 0 { s := fmt.Sprintf("enter %v", Curfn.Func.Nname.Sym) - dumplist(s, Curfn.Func.Enter) + ir.DumpList(s, Curfn.Func.Enter) } } -func walkstmtlist(s []*Node) { +func walkstmtlist(s []*ir.Node) { for i := range s { s[i] = walkstmt(s[i]) } } -func paramoutheap(fn *Node) bool { +func paramoutheap(fn *ir.Node) bool { for _, ln := range fn.Func.Dcl { switch ln.Class() { - case PPARAMOUT: - if ln.isParamStackCopy() || ln.Name.Addrtaken() { + case ir.PPARAMOUT: + if isParamStackCopy(ln) || ln.Name.Addrtaken() { return true } - case PAUTO: + case ir.PAUTO: // stop early - parameters are over return false } @@ -105,7 +106,7 @@ func paramoutheap(fn *Node) bool { // The result of walkstmt MUST be assigned back to n, e.g. // n.Left = walkstmt(n.Left) -func walkstmt(n *Node) *Node { +func walkstmt(n *ir.Node) *ir.Node { if n == nil { return n } @@ -116,49 +117,49 @@ func walkstmt(n *Node) *Node { switch n.Op { default: - if n.Op == ONAME { + if n.Op == ir.ONAME { base.Errorf("%v is not a top level statement", n.Sym) } else { base.Errorf("%v is not a top level statement", n.Op) } - Dump("nottop", n) + ir.Dump("nottop", n) - case OAS, - OASOP, - OAS2, - OAS2DOTTYPE, - OAS2RECV, - OAS2FUNC, - OAS2MAPR, - OCLOSE, - OCOPY, - OCALLMETH, - OCALLINTER, - OCALL, - OCALLFUNC, - ODELETE, - OSEND, - OPRINT, - OPRINTN, - OPANIC, - OEMPTY, - ORECOVER, - OGETG: + case ir.OAS, + ir.OASOP, + ir.OAS2, + ir.OAS2DOTTYPE, + ir.OAS2RECV, + ir.OAS2FUNC, + ir.OAS2MAPR, + ir.OCLOSE, + ir.OCOPY, + ir.OCALLMETH, + ir.OCALLINTER, + ir.OCALL, + ir.OCALLFUNC, + ir.ODELETE, + ir.OSEND, + ir.OPRINT, + ir.OPRINTN, + ir.OPANIC, + ir.OEMPTY, + ir.ORECOVER, + ir.OGETG: if n.Typecheck() == 0 { base.Fatalf("missing typecheck: %+v", n) } - wascopy := n.Op == OCOPY + wascopy := n.Op == ir.OCOPY init := n.Ninit n.Ninit.Set(nil) n = walkexpr(n, &init) n = addinit(n, init.Slice()) - if wascopy && n.Op == OCONVNOP { - n.Op = OEMPTY // don't leave plain values as statements. + if wascopy && n.Op == ir.OCONVNOP { + n.Op = ir.OEMPTY // don't leave plain values as statements. } // special case for a receive where we throw away // the value received. - case ORECV: + case ir.ORECV: if n.Typecheck() == 0 { base.Fatalf("missing typecheck: %+v", n) } @@ -171,44 +172,44 @@ func walkstmt(n *Node) *Node { n = addinit(n, init.Slice()) - case OBREAK, - OCONTINUE, - OFALL, - OGOTO, - OLABEL, - ODCLCONST, - ODCLTYPE, - OCHECKNIL, - OVARDEF, - OVARKILL, - OVARLIVE: + case ir.OBREAK, + ir.OCONTINUE, + ir.OFALL, + ir.OGOTO, + ir.OLABEL, + ir.ODCLCONST, + ir.ODCLTYPE, + ir.OCHECKNIL, + ir.OVARDEF, + ir.OVARKILL, + ir.OVARLIVE: break - case ODCL: + case ir.ODCL: v := n.Left - if v.Class() == PAUTOHEAP { + if v.Class() == ir.PAUTOHEAP { if base.Flag.CompilingRuntime { base.Errorf("%v escapes to heap, not allowed in runtime", v) } if prealloc[v] == nil { prealloc[v] = callnew(v.Type) } - nn := nod(OAS, v.Name.Param.Heapaddr, prealloc[v]) + nn := ir.Nod(ir.OAS, v.Name.Param.Heapaddr, prealloc[v]) nn.SetColas(true) nn = typecheck(nn, ctxStmt) return walkstmt(nn) } - case OBLOCK: + case ir.OBLOCK: walkstmtlist(n.List.Slice()) - case OCASE: + case ir.OCASE: base.Errorf("case statement out of place") - case ODEFER: + case ir.ODEFER: Curfn.Func.SetHasDefer(true) - Curfn.Func.numDefers++ - if Curfn.Func.numDefers > maxOpenDefers { + Curfn.Func.NumDefers++ + if Curfn.Func.NumDefers > maxOpenDefers { // Don't allow open-coded defers if there are more than // 8 defers in the function, since we use a single // byte to record active defers. @@ -220,22 +221,22 @@ func walkstmt(n *Node) *Node { Curfn.Func.SetOpenCodedDeferDisallowed(true) } fallthrough - case OGO: + case ir.OGO: switch n.Left.Op { - case OPRINT, OPRINTN: + case ir.OPRINT, ir.OPRINTN: n.Left = wrapCall(n.Left, &n.Ninit) - case ODELETE: + case ir.ODELETE: if mapfast(n.Left.List.First().Type) == mapslow { n.Left = wrapCall(n.Left, &n.Ninit) } else { n.Left = walkexpr(n.Left, &n.Ninit) } - case OCOPY: + case ir.OCOPY: n.Left = copyany(n.Left, &n.Ninit, true) - case OCALLFUNC, OCALLMETH, OCALLINTER: + case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: if n.Left.Nbody.Len() > 0 { n.Left = wrapCall(n.Left, &n.Ninit) } else { @@ -246,7 +247,7 @@ func walkstmt(n *Node) *Node { n.Left = walkexpr(n.Left, &n.Ninit) } - case OFOR, OFORUNTIL: + case ir.OFOR, ir.OFORUNTIL: if n.Left != nil { walkstmtlist(n.Left.Ninit.Slice()) init := n.Left.Ninit @@ -256,34 +257,34 @@ func walkstmt(n *Node) *Node { } n.Right = walkstmt(n.Right) - if n.Op == OFORUNTIL { + if n.Op == ir.OFORUNTIL { walkstmtlist(n.List.Slice()) } walkstmtlist(n.Nbody.Slice()) - case OIF: + case ir.OIF: n.Left = walkexpr(n.Left, &n.Ninit) walkstmtlist(n.Nbody.Slice()) walkstmtlist(n.Rlist.Slice()) - case ORETURN: - Curfn.Func.numReturns++ + case ir.ORETURN: + Curfn.Func.NumReturns++ if n.List.Len() == 0 { break } if (Curfn.Type.FuncType().Outnamed && n.List.Len() > 1) || paramoutheap(Curfn) { // assign to the function out parameters, // so that reorder3 can fix up conflicts - var rl []*Node + var rl []*ir.Node for _, ln := range Curfn.Func.Dcl { cl := ln.Class() - if cl == PAUTO || cl == PAUTOHEAP { + if cl == ir.PAUTO || cl == ir.PAUTOHEAP { break } - if cl == PPARAMOUT { - if ln.isParamStackCopy() { - ln = walkexpr(typecheck(nod(ODEREF, ln.Name.Param.Heapaddr, nil), ctxExpr), nil) + if cl == ir.PPARAMOUT { + if isParamStackCopy(ln) { + ln = walkexpr(typecheck(ir.Nod(ir.ODEREF, ln.Name.Param.Heapaddr, nil), ctxExpr), nil) } rl = append(rl, ln) } @@ -307,34 +308,34 @@ func walkstmt(n *Node) *Node { // For each return parameter (lhs), assign the corresponding result (rhs). lhs := Curfn.Type.Results() rhs := n.List.Slice() - res := make([]*Node, lhs.NumFields()) + res := make([]*ir.Node, lhs.NumFields()) for i, nl := range lhs.FieldSlice() { - nname := asNode(nl.Nname) - if nname.isParamHeapCopy() { + nname := ir.AsNode(nl.Nname) + if isParamHeapCopy(nname) { nname = nname.Name.Param.Stackcopy } - a := nod(OAS, nname, rhs[i]) + a := ir.Nod(ir.OAS, nname, rhs[i]) res[i] = convas(a, &n.Ninit) } n.List.Set(res) - case ORETJMP: + case ir.ORETJMP: break - case OINLMARK: + case ir.OINLMARK: break - case OSELECT: + case ir.OSELECT: walkselect(n) - case OSWITCH: + case ir.OSWITCH: walkswitch(n) - case ORANGE: + case ir.ORANGE: n = walkrange(n) } - if n.Op == ONAME { + if n.Op == ir.ONAME { base.Fatalf("walkstmt ended up with name: %+v", n) } return n @@ -345,20 +346,20 @@ func walkstmt(n *Node) *Node { // the types expressions are calculated. // compile-time constants are evaluated. // complex side effects like statements are appended to init -func walkexprlist(s []*Node, init *Nodes) { +func walkexprlist(s []*ir.Node, init *ir.Nodes) { for i := range s { s[i] = walkexpr(s[i], init) } } -func walkexprlistsafe(s []*Node, init *Nodes) { +func walkexprlistsafe(s []*ir.Node, init *ir.Nodes) { for i, n := range s { s[i] = safeexpr(n, init) s[i] = walkexpr(s[i], init) } } -func walkexprlistcheap(s []*Node, init *Nodes) { +func walkexprlistcheap(s []*ir.Node, init *ir.Nodes) { for i, n := range s { s[i] = cheapexpr(n, init) s[i] = walkexpr(s[i], init) @@ -381,7 +382,7 @@ func convFuncName(from, to *types.Type) (fnname string, needsaddr bool) { return "convT16", false case from.Size() == 4 && from.Align == 4 && !from.HasPointers(): return "convT32", false - case from.Size() == 8 && from.Align == types.Types[TUINT64].Align && !from.HasPointers(): + case from.Size() == 8 && from.Align == types.Types[types.TUINT64].Align && !from.HasPointers(): return "convT64", false } if sc := from.SoleComponent(); sc != nil { @@ -412,7 +413,7 @@ func convFuncName(from, to *types.Type) (fnname string, needsaddr bool) { // The result of walkexpr MUST be assigned back to n, e.g. // n.Left = walkexpr(n.Left, init) -func walkexpr(n *Node, init *Nodes) *Node { +func walkexpr(n *ir.Node, init *ir.Nodes) *ir.Node { if n == nil { return n } @@ -420,7 +421,7 @@ func walkexpr(n *Node, init *Nodes) *Node { // Eagerly checkwidth all expressions for the back end. if n.Type != nil && !n.Type.WidthCalculated() { switch n.Type.Etype { - case TBLANK, TNIL, TIDEAL: + case types.TBLANK, types.TNIL, types.TIDEAL: default: checkwidth(n.Type) } @@ -441,7 +442,7 @@ func walkexpr(n *Node, init *Nodes) *Node { lno := setlineno(n) if base.Flag.LowerW > 1 { - Dump("before walk expr", n) + ir.Dump("before walk expr", n) } if n.Typecheck() != 1 { @@ -452,8 +453,8 @@ func walkexpr(n *Node, init *Nodes) *Node { base.Fatalf("expression has untyped type: %+v", n) } - if n.Op == ONAME && n.Class() == PAUTOHEAP { - nn := nod(ODEREF, n.Name.Param.Heapaddr, nil) + if n.Op == ir.ONAME && n.Class() == ir.PAUTOHEAP { + nn := ir.Nod(ir.ODEREF, n.Name.Param.Heapaddr, nil) nn = typecheck(nn, ctxExpr) nn = walkexpr(nn, init) nn.Left.MarkNonNil() @@ -463,44 +464,44 @@ func walkexpr(n *Node, init *Nodes) *Node { opswitch: switch n.Op { default: - Dump("walk", n) + ir.Dump("walk", n) base.Fatalf("walkexpr: switch 1 unknown op %+S", n) - case ONONAME, OEMPTY, OGETG, ONEWOBJ, OMETHEXPR: + case ir.ONONAME, ir.OEMPTY, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR: - case OTYPE, ONAME, OLITERAL, ONIL: + case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL: // TODO(mdempsky): Just return n; see discussion on CL 38655. // Perhaps refactor to use Node.mayBeShared for these instead. // If these return early, make sure to still call // stringsym for constant strings. - case ONOT, ONEG, OPLUS, OBITNOT, OREAL, OIMAG, ODOTMETH, ODOTINTER, - ODEREF, OSPTR, OITAB, OIDATA, OADDR: + case ir.ONOT, ir.ONEG, ir.OPLUS, ir.OBITNOT, ir.OREAL, ir.OIMAG, ir.ODOTMETH, ir.ODOTINTER, + ir.ODEREF, ir.OSPTR, ir.OITAB, ir.OIDATA, ir.OADDR: n.Left = walkexpr(n.Left, init) - case OEFACE, OAND, OANDNOT, OSUB, OMUL, OADD, OOR, OXOR, OLSH, ORSH: + case ir.OEFACE, ir.OAND, ir.OANDNOT, ir.OSUB, ir.OMUL, ir.OADD, ir.OOR, ir.OXOR, ir.OLSH, ir.ORSH: n.Left = walkexpr(n.Left, init) n.Right = walkexpr(n.Right, init) - case ODOT, ODOTPTR: + case ir.ODOT, ir.ODOTPTR: usefield(n) n.Left = walkexpr(n.Left, init) - case ODOTTYPE, ODOTTYPE2: + case ir.ODOTTYPE, ir.ODOTTYPE2: n.Left = walkexpr(n.Left, init) // Set up interface type addresses for back end. n.Right = typename(n.Type) - if n.Op == ODOTTYPE { + if n.Op == ir.ODOTTYPE { n.Right.Right = typename(n.Left.Type) } if !n.Type.IsInterface() && !n.Left.Type.IsEmptyInterface() { n.List.Set1(itabname(n.Type, n.Left.Type)) } - case OLEN, OCAP: + case ir.OLEN, ir.OCAP: if isRuneCount(n) { // Replace len([]rune(string)) with runtime.countrunes(string). - n = mkcall("countrunes", n.Type, init, conv(n.Left.Left, types.Types[TSTRING])) + n = mkcall("countrunes", n.Type, init, conv(n.Left.Left, types.Types[types.TSTRING])) break } @@ -519,7 +520,7 @@ opswitch: n.SetTypecheck(1) } - case OCOMPLEX: + case ir.OCOMPLEX: // Use results from call expression as arguments for complex. if n.Left == nil && n.Right == nil { n.Left = n.List.First() @@ -528,38 +529,38 @@ opswitch: n.Left = walkexpr(n.Left, init) n.Right = walkexpr(n.Right, init) - case OEQ, ONE, OLT, OLE, OGT, OGE: + case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: n = walkcompare(n, init) - case OANDAND, OOROR: + case ir.OANDAND, ir.OOROR: n.Left = walkexpr(n.Left, init) // cannot put side effects from n.Right on init, // because they cannot run before n.Left is checked. // save elsewhere and store on the eventual n.Right. - var ll Nodes + var ll ir.Nodes n.Right = walkexpr(n.Right, &ll) n.Right = addinit(n.Right, ll.Slice()) - case OPRINT, OPRINTN: + case ir.OPRINT, ir.OPRINTN: n = walkprint(n, init) - case OPANIC: + case ir.OPANIC: n = mkcall("gopanic", nil, init, n.Left) - case ORECOVER: - n = mkcall("gorecover", n.Type, init, nod(OADDR, nodfp, nil)) + case ir.ORECOVER: + n = mkcall("gorecover", n.Type, init, ir.Nod(ir.OADDR, nodfp, nil)) - case OCLOSUREVAR, OCFUNC: + case ir.OCLOSUREVAR, ir.OCFUNC: - case OCALLINTER, OCALLFUNC, OCALLMETH: - if n.Op == OCALLINTER { + case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH: + if n.Op == ir.OCALLINTER { usemethod(n) markUsedIfaceMethod(n) } - if n.Op == OCALLFUNC && n.Left.Op == OCLOSURE { + if n.Op == ir.OCALLFUNC && n.Left.Op == ir.OCLOSURE { // Transform direct call of a closure to call of a normal function. // transformclosure already did all preparation work. @@ -581,12 +582,12 @@ opswitch: walkCall(n, init) - case OAS, OASOP: + case ir.OAS, ir.OASOP: init.AppendNodes(&n.Ninit) // Recognize m[k] = append(m[k], ...) so we can reuse // the mapassign call. - mapAppend := n.Left.Op == OINDEXMAP && n.Right.Op == OAPPEND + mapAppend := n.Left.Op == ir.OINDEXMAP && n.Right.Op == ir.OAPPEND if mapAppend && !samesafeexpr(n.Left, n.Right.List.First()) { base.Fatalf("not same expressions: %v != %v", n.Left, n.Right.List.First()) } @@ -598,12 +599,12 @@ opswitch: n.Right.List.SetFirst(n.Left) } - if n.Op == OASOP { + if n.Op == ir.OASOP { // Rewrite x op= y into x = x op y. - n.Right = nod(n.SubOp(), n.Left, n.Right) + n.Right = ir.Nod(n.SubOp(), n.Left, n.Right) n.Right = typecheck(n.Right, ctxExpr) - n.Op = OAS + n.Op = ir.OAS n.ResetAux() } @@ -624,18 +625,18 @@ opswitch: default: n.Right = walkexpr(n.Right, init) - case ORECV: + case ir.ORECV: // x = <-c; n.Left is x, n.Right.Left is c. // order.stmt made sure x is addressable. n.Right.Left = walkexpr(n.Right.Left, init) - n1 := nod(OADDR, n.Left, nil) + n1 := ir.Nod(ir.OADDR, n.Left, nil) r := n.Right.Left // the channel n = mkcall1(chanfn("chanrecv1", 2, r.Type), nil, init, r, n1) n = walkexpr(n, init) break opswitch - case OAPPEND: + case ir.OAPPEND: // x = append(...) r := n.Right if r.Type.Elem().NotInHeap() { @@ -651,7 +652,7 @@ opswitch: r = walkappend(r, init, n) } n.Right = r - if r.Op == OAPPEND { + if r.Op == ir.OAPPEND { // Left in place for back end. // Do not add a new write barrier. // Set up address of type for back end. @@ -666,16 +667,16 @@ opswitch: n = convas(n, init) } - case OAS2: + case ir.OAS2: init.AppendNodes(&n.Ninit) walkexprlistsafe(n.List.Slice(), init) walkexprlistsafe(n.Rlist.Slice(), init) - ll := ascompatee(OAS, n.List.Slice(), n.Rlist.Slice(), init) + ll := ascompatee(ir.OAS, n.List.Slice(), n.Rlist.Slice(), init) ll = reorder3(ll) n = liststmt(ll) // a,b,... = fn() - case OAS2FUNC: + case ir.OAS2FUNC: init.AppendNodes(&n.Ninit) r := n.Right @@ -693,26 +694,26 @@ opswitch: // x, y = <-c // order.stmt made sure x is addressable or blank. - case OAS2RECV: + case ir.OAS2RECV: init.AppendNodes(&n.Ninit) r := n.Right walkexprlistsafe(n.List.Slice(), init) r.Left = walkexpr(r.Left, init) - var n1 *Node - if n.List.First().isBlank() { + var n1 *ir.Node + if ir.IsBlank(n.List.First()) { n1 = nodnil() } else { - n1 = nod(OADDR, n.List.First(), nil) + n1 = ir.Nod(ir.OADDR, n.List.First(), nil) } fn := chanfn("chanrecv2", 2, r.Left.Type) ok := n.List.Second() - call := mkcall1(fn, types.Types[TBOOL], init, r.Left, n1) - n = nod(OAS, ok, call) + call := mkcall1(fn, types.Types[types.TBOOL], init, r.Left, n1) + n = ir.Nod(ir.OAS, ok, call) n = typecheck(n, ctxStmt) // a,b = m[i] - case OAS2MAPR: + case ir.OAS2MAPR: init.AppendNodes(&n.Ninit) r := n.Right @@ -722,14 +723,14 @@ opswitch: t := r.Left.Type fast := mapfast(t) - var key *Node + var key *ir.Node if fast != mapslow { // fast versions take key by value key = r.Right } else { // standard version takes key by reference // order.expr made sure key is addressable. - key = nod(OADDR, r.Right, nil) + key = ir.Nod(ir.OADDR, r.Right, nil) } // from: @@ -751,27 +752,27 @@ opswitch: // mapaccess2* returns a typed bool, but due to spec changes, // the boolean result of i.(T) is now untyped so we make it the // same type as the variable on the lhs. - if ok := n.List.Second(); !ok.isBlank() && ok.Type.IsBoolean() { + if ok := n.List.Second(); !ir.IsBlank(ok) && ok.Type.IsBoolean() { r.Type.Field(1).Type = ok.Type } n.Right = r - n.Op = OAS2FUNC + n.Op = ir.OAS2FUNC // don't generate a = *var if a is _ - if !a.isBlank() { + if !ir.IsBlank(a) { var_ := temp(types.NewPtr(t.Elem())) var_.SetTypecheck(1) var_.MarkNonNil() // mapaccess always returns a non-nil pointer n.List.SetFirst(var_) n = walkexpr(n, init) init.Append(n) - n = nod(OAS, a, nod(ODEREF, var_, nil)) + n = ir.Nod(ir.OAS, a, ir.Nod(ir.ODEREF, var_, nil)) } n = typecheck(n, ctxStmt) n = walkexpr(n, init) - case ODELETE: + case ir.ODELETE: init.AppendNodes(&n.Ninit) map_ := n.List.First() key := n.List.Second() @@ -782,26 +783,26 @@ opswitch: fast := mapfast(t) if fast == mapslow { // order.stmt made sure key is addressable. - key = nod(OADDR, key, nil) + key = ir.Nod(ir.OADDR, key, nil) } n = mkcall1(mapfndel(mapdelete[fast], t), nil, init, typename(t), map_, key) - case OAS2DOTTYPE: + case ir.OAS2DOTTYPE: walkexprlistsafe(n.List.Slice(), init) n.Right = walkexpr(n.Right, init) - case OCONVIFACE: + case ir.OCONVIFACE: n.Left = walkexpr(n.Left, init) fromType := n.Left.Type toType := n.Type - if !fromType.IsInterface() && !Curfn.Func.Nname.isBlank() { // skip unnamed functions (func _()) - markTypeUsedInInterface(fromType, Curfn.Func.lsym) + if !fromType.IsInterface() && !ir.IsBlank(Curfn.Func.Nname) { // skip unnamed functions (func _()) + markTypeUsedInInterface(fromType, Curfn.Func.LSym) } // typeword generates the type word of the interface value. - typeword := func() *Node { + typeword := func() *ir.Node { if toType.IsEmptyInterface() { return typename(fromType) } @@ -810,7 +811,7 @@ opswitch: // Optimize convT2E or convT2I as a two-word copy when T is pointer-shaped. if isdirectiface(fromType) { - l := nod(OEFACE, typeword(), n.Left) + l := ir.Nod(ir.OEFACE, typeword(), n.Left) l.Type = toType l.SetTypecheck(n.Typecheck()) n = l @@ -818,20 +819,20 @@ opswitch: } if staticuint64s == nil { - staticuint64s = newname(Runtimepkg.Lookup("staticuint64s")) - staticuint64s.SetClass(PEXTERN) + staticuint64s = NewName(Runtimepkg.Lookup("staticuint64s")) + staticuint64s.SetClass(ir.PEXTERN) // The actual type is [256]uint64, but we use [256*8]uint8 so we can address // individual bytes. - staticuint64s.Type = types.NewArray(types.Types[TUINT8], 256*8) - zerobase = newname(Runtimepkg.Lookup("zerobase")) - zerobase.SetClass(PEXTERN) - zerobase.Type = types.Types[TUINTPTR] + staticuint64s.Type = types.NewArray(types.Types[types.TUINT8], 256*8) + zerobase = NewName(Runtimepkg.Lookup("zerobase")) + zerobase.SetClass(ir.PEXTERN) + zerobase.Type = types.Types[types.TUINTPTR] } // Optimize convT2{E,I} for many cases in which T is not pointer-shaped, // by using an existing addressable value identical to n.Left // or creating one on the stack. - var value *Node + var value *ir.Node switch { case fromType.Size() == 0: // n.Left is zero-sized. Use zerobase. @@ -842,25 +843,25 @@ opswitch: // and staticuint64s[n.Left * 8 + 7] on big-endian. n.Left = cheapexpr(n.Left, init) // byteindex widens n.Left so that the multiplication doesn't overflow. - index := nod(OLSH, byteindex(n.Left), nodintconst(3)) + index := ir.Nod(ir.OLSH, byteindex(n.Left), nodintconst(3)) if thearch.LinkArch.ByteOrder == binary.BigEndian { - index = nod(OADD, index, nodintconst(7)) + index = ir.Nod(ir.OADD, index, nodintconst(7)) } - value = nod(OINDEX, staticuint64s, index) + value = ir.Nod(ir.OINDEX, staticuint64s, index) value.SetBounded(true) - case n.Left.Class() == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly(): + case n.Left.Class() == ir.PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly(): // n.Left is a readonly global; use it directly. value = n.Left case !fromType.IsInterface() && n.Esc == EscNone && fromType.Width <= 1024: // n.Left does not escape. Use a stack temporary initialized to n.Left. value = temp(fromType) - init.Append(typecheck(nod(OAS, value, n.Left), ctxStmt)) + init.Append(typecheck(ir.Nod(ir.OAS, value, n.Left), ctxStmt)) } if value != nil { // Value is identical to n.Left. // Construct the interface directly: {type/itab, &value}. - l := nod(OEFACE, typeword(), typecheck(nod(OADDR, value, nil), ctxExpr)) + l := ir.Nod(ir.OEFACE, typeword(), typecheck(ir.Nod(ir.OADDR, value, nil), ctxExpr)) l.Type = toType l.SetTypecheck(n.Typecheck()) n = l @@ -876,19 +877,19 @@ opswitch: if toType.IsEmptyInterface() && fromType.IsInterface() && !fromType.IsEmptyInterface() { // Evaluate the input interface. c := temp(fromType) - init.Append(nod(OAS, c, n.Left)) + init.Append(ir.Nod(ir.OAS, c, n.Left)) // Get the itab out of the interface. - tmp := temp(types.NewPtr(types.Types[TUINT8])) - init.Append(nod(OAS, tmp, typecheck(nod(OITAB, c, nil), ctxExpr))) + tmp := temp(types.NewPtr(types.Types[types.TUINT8])) + init.Append(ir.Nod(ir.OAS, tmp, typecheck(ir.Nod(ir.OITAB, c, nil), ctxExpr))) // Get the type out of the itab. - nif := nod(OIF, typecheck(nod(ONE, tmp, nodnil()), ctxExpr), nil) - nif.Nbody.Set1(nod(OAS, tmp, itabType(tmp))) + nif := ir.Nod(ir.OIF, typecheck(ir.Nod(ir.ONE, tmp, nodnil()), ctxExpr), nil) + nif.Nbody.Set1(ir.Nod(ir.OAS, tmp, itabType(tmp))) init.Append(nif) // Build the result. - e := nod(OEFACE, tmp, ifaceData(n.Pos, c, types.NewPtr(types.Types[TUINT8]))) + e := ir.Nod(ir.OEFACE, tmp, ifaceData(n.Pos, c, types.NewPtr(types.Types[types.TUINT8]))) e.Type = toType // assign type manually, typecheck doesn't understand OEFACE. e.SetTypecheck(1) n = e @@ -905,19 +906,19 @@ opswitch: dowidth(fromType) fn = substArgTypes(fn, fromType) dowidth(fn.Type) - call := nod(OCALL, fn, nil) + call := ir.Nod(ir.OCALL, fn, nil) call.List.Set1(n.Left) call = typecheck(call, ctxExpr) call = walkexpr(call, init) call = safeexpr(call, init) - e := nod(OEFACE, typeword(), call) + e := ir.Nod(ir.OEFACE, typeword(), call) e.Type = toType e.SetTypecheck(1) n = e break } - var tab *Node + var tab *ir.Node if fromType.IsInterface() { // convI2I tab = typename(toType) @@ -937,21 +938,21 @@ opswitch: if !islvalue(v) { v = copyexpr(v, v.Type, init) } - v = nod(OADDR, v, nil) + v = ir.Nod(ir.OADDR, v, nil) } dowidth(fromType) fn := syslook(fnname) fn = substArgTypes(fn, fromType, toType) dowidth(fn.Type) - n = nod(OCALL, fn, nil) + n = ir.Nod(ir.OCALL, fn, nil) n.List.Set2(tab, v) n = typecheck(n, ctxExpr) n = walkexpr(n, init) - case OCONV, OCONVNOP: + case ir.OCONV, ir.OCONVNOP: n.Left = walkexpr(n.Left, init) - if n.Op == OCONVNOP && checkPtr(Curfn, 1) { + if n.Op == ir.OCONVNOP && checkPtr(Curfn, 1) { if n.Type.IsPtr() && n.Left.Type.IsUnsafePtr() { // unsafe.Pointer to *T n = walkCheckPtrAlignment(n, init, nil) break @@ -962,22 +963,22 @@ opswitch: } } param, result := rtconvfn(n.Left.Type, n.Type) - if param == Txxx { + if param == types.Txxx { break } - fn := basicnames[param] + "to" + basicnames[result] + fn := ir.BasicTypeNames[param] + "to" + ir.BasicTypeNames[result] n = conv(mkcall(fn, types.Types[result], init, conv(n.Left, types.Types[param])), n.Type) - case ODIV, OMOD: + case ir.ODIV, ir.OMOD: n.Left = walkexpr(n.Left, init) n.Right = walkexpr(n.Right, init) // rewrite complex div into function call. et := n.Left.Type.Etype - if isComplex[et] && n.Op == ODIV { + if isComplex[et] && n.Op == ir.ODIV { t := n.Type - n = mkcall("complex128div", types.Types[TCOMPLEX128], init, conv(n.Left, types.Types[TCOMPLEX128]), conv(n.Right, types.Types[TCOMPLEX128])) + n = mkcall("complex128div", types.Types[types.TCOMPLEX128], init, conv(n.Left, types.Types[types.TCOMPLEX128]), conv(n.Right, types.Types[types.TCOMPLEX128])) n = conv(n, t) break } @@ -990,12 +991,12 @@ opswitch: // rewrite 64-bit div and mod on 32-bit architectures. // TODO: Remove this code once we can introduce // runtime calls late in SSA processing. - if Widthreg < 8 && (et == TINT64 || et == TUINT64) { - if n.Right.Op == OLITERAL { + if Widthreg < 8 && (et == types.TINT64 || et == types.TUINT64) { + if n.Right.Op == ir.OLITERAL { // Leave div/mod by constant powers of 2 or small 16-bit constants. // The SSA backend will handle those. switch et { - case TINT64: + case types.TINT64: c := n.Right.Int64Val() if c < 0 { c = -c @@ -1003,7 +1004,7 @@ opswitch: if c != 0 && c&(c-1) == 0 { break opswitch } - case TUINT64: + case types.TUINT64: c := n.Right.Uint64Val() if c < 1<<16 { break opswitch @@ -1014,12 +1015,12 @@ opswitch: } } var fn string - if et == TINT64 { + if et == types.TINT64 { fn = "int64" } else { fn = "uint64" } - if n.Op == ODIV { + if n.Op == ir.ODIV { fn += "div" } else { fn += "mod" @@ -1027,7 +1028,7 @@ opswitch: n = mkcall(fn, n.Type, init, conv(n.Left, types.Types[et]), conv(n.Right, types.Types[et])) } - case OINDEX: + case ir.OINDEX: n.Left = walkexpr(n.Left, init) // save the original node for bounds checking elision. @@ -1047,15 +1048,15 @@ opswitch: } if t.IsArray() { n.SetBounded(bounded(r, t.NumElem())) - if base.Flag.LowerM != 0 && n.Bounded() && !Isconst(n.Right, constant.Int) { + if base.Flag.LowerM != 0 && n.Bounded() && !ir.IsConst(n.Right, constant.Int) { base.Warn("index bounds check elided") } if smallintconst(n.Right) && !n.Bounded() { base.Errorf("index out of bounds") } - } else if Isconst(n.Left, constant.String) { + } else if ir.IsConst(n.Left, constant.String) { n.SetBounded(bounded(r, int64(len(n.Left.StringVal())))) - if base.Flag.LowerM != 0 && n.Bounded() && !Isconst(n.Right, constant.Int) { + if base.Flag.LowerM != 0 && n.Bounded() && !ir.IsConst(n.Right, constant.Int) { base.Warn("index bounds check elided") } if smallintconst(n.Right) && !n.Bounded() { @@ -1063,13 +1064,13 @@ opswitch: } } - if Isconst(n.Right, constant.Int) { - if v := n.Right.Val(); constant.Sign(v) < 0 || doesoverflow(v, types.Types[TINT]) { + if ir.IsConst(n.Right, constant.Int) { + if v := n.Right.Val(); constant.Sign(v) < 0 || doesoverflow(v, types.Types[types.TINT]) { base.Errorf("index out of bounds") } } - case OINDEXMAP: + case ir.OINDEXMAP: // Replace m[k] with *map{access1,assign}(maptype, m, &k) n.Left = walkexpr(n.Left, init) n.Right = walkexpr(n.Right, init) @@ -1082,7 +1083,7 @@ opswitch: if fast == mapslow { // standard version takes key by reference. // order.expr made sure key is addressable. - key = nod(OADDR, key, nil) + key = ir.Nod(ir.OADDR, key, nil) } n = mkcall1(mapfn(mapassign[fast], t), nil, init, typename(t), map_, key) } else { @@ -1091,7 +1092,7 @@ opswitch: if fast == mapslow { // standard version takes key by reference. // order.expr made sure key is addressable. - key = nod(OADDR, key, nil) + key = ir.Nod(ir.OADDR, key, nil) } if w := t.Elem().Width; w <= zeroValSize { @@ -1103,20 +1104,20 @@ opswitch: } n.Type = types.NewPtr(t.Elem()) n.MarkNonNil() // mapaccess1* and mapassign always return non-nil pointers. - n = nod(ODEREF, n, nil) + n = ir.Nod(ir.ODEREF, n, nil) n.Type = t.Elem() n.SetTypecheck(1) - case ORECV: + case ir.ORECV: base.Fatalf("walkexpr ORECV") // should see inside OAS only - case OSLICEHEADER: + case ir.OSLICEHEADER: n.Left = walkexpr(n.Left, init) n.List.SetFirst(walkexpr(n.List.First(), init)) n.List.SetSecond(walkexpr(n.List.Second(), init)) - case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: - checkSlice := checkPtr(Curfn, 1) && n.Op == OSLICE3ARR && n.Left.Op == OCONVNOP && n.Left.Left.Type.IsUnsafePtr() + case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR: + checkSlice := checkPtr(Curfn, 1) && n.Op == ir.OSLICE3ARR && n.Left.Op == ir.OCONVNOP && n.Left.Left.Type.IsUnsafePtr() if checkSlice { n.Left.Left = walkexpr(n.Left.Left, init) } else { @@ -1135,12 +1136,12 @@ opswitch: n.Left = walkCheckPtrAlignment(n.Left, init, max) } if n.Op.IsSlice3() { - if max != nil && max.Op == OCAP && samesafeexpr(n.Left, max.Left) { + if max != nil && max.Op == ir.OCAP && samesafeexpr(n.Left, max.Left) { // Reduce x[i:j:cap(x)] to x[i:j]. - if n.Op == OSLICE3 { - n.Op = OSLICE + if n.Op == ir.OSLICE3 { + n.Op = ir.OSLICE } else { - n.Op = OSLICEARR + n.Op = ir.OSLICEARR } n = reduceSlice(n) } @@ -1148,7 +1149,7 @@ opswitch: n = reduceSlice(n) } - case ONEW: + case ir.ONEW: if n.Type.Elem().NotInHeap() { base.Errorf("%v can't be allocated in Go; it is incomplete (or unallocatable)", n.Type.Elem()) } @@ -1157,74 +1158,74 @@ opswitch: base.Fatalf("large ONEW with EscNone: %v", n) } r := temp(n.Type.Elem()) - r = nod(OAS, r, nil) // zero temp + r = ir.Nod(ir.OAS, r, nil) // zero temp r = typecheck(r, ctxStmt) init.Append(r) - r = nod(OADDR, r.Left, nil) + r = ir.Nod(ir.OADDR, r.Left, nil) r = typecheck(r, ctxExpr) n = r } else { n = callnew(n.Type.Elem()) } - case OADDSTR: + case ir.OADDSTR: n = addstr(n, init) - case OAPPEND: + case ir.OAPPEND: // order should make sure we only see OAS(node, OAPPEND), which we handle above. base.Fatalf("append outside assignment") - case OCOPY: + case ir.OCOPY: n = copyany(n, init, instrumenting && !base.Flag.CompilingRuntime) // cannot use chanfn - closechan takes any, not chan any - case OCLOSE: + case ir.OCLOSE: fn := syslook("closechan") fn = substArgTypes(fn, n.Left.Type) n = mkcall1(fn, nil, init, n.Left) - case OMAKECHAN: + case ir.OMAKECHAN: // When size fits into int, use makechan instead of // makechan64, which is faster and shorter on 32 bit platforms. size := n.Left fnname := "makechan64" - argtype := types.Types[TINT64] + argtype := types.Types[types.TINT64] // Type checking guarantees that TIDEAL size is positive and fits in an int. // The case of size overflow when converting TUINT or TUINTPTR to TINT // will be handled by the negative range checks in makechan during runtime. - if size.Type.IsKind(TIDEAL) || size.Type.Size() <= types.Types[TUINT].Size() { + if size.Type.IsKind(types.TIDEAL) || size.Type.Size() <= types.Types[types.TUINT].Size() { fnname = "makechan" - argtype = types.Types[TINT] + argtype = types.Types[types.TINT] } n = mkcall1(chanfn(fnname, 1, n.Type), n.Type, init, typename(n.Type), conv(size, argtype)) - case OMAKEMAP: + case ir.OMAKEMAP: t := n.Type hmapType := hmap(t) hint := n.Left // var h *hmap - var h *Node + var h *ir.Node if n.Esc == EscNone { // Allocate hmap on stack. // var hv hmap hv := temp(hmapType) - zero := nod(OAS, hv, nil) + zero := ir.Nod(ir.OAS, hv, nil) zero = typecheck(zero, ctxStmt) init.Append(zero) // h = &hv - h = nod(OADDR, hv, nil) + h = ir.Nod(ir.OADDR, hv, nil) // Allocate one bucket pointed to by hmap.buckets on stack if hint // is not larger than BUCKETSIZE. In case hint is larger than // BUCKETSIZE runtime.makemap will allocate the buckets on the heap. // Maximum key and elem size is 128 bytes, larger objects // are stored with an indirection. So max bucket size is 2048+eps. - if !Isconst(hint, constant.Int) || + if !ir.IsConst(hint, constant.Int) || constant.Compare(hint.Val(), token.LEQ, constant.MakeInt64(BUCKETSIZE)) { // In case hint is larger than BUCKETSIZE runtime.makemap @@ -1236,20 +1237,20 @@ opswitch: // h.buckets = b // } - nif := nod(OIF, nod(OLE, hint, nodintconst(BUCKETSIZE)), nil) + nif := ir.Nod(ir.OIF, ir.Nod(ir.OLE, hint, nodintconst(BUCKETSIZE)), nil) nif.SetLikely(true) // var bv bmap bv := temp(bmap(t)) - zero = nod(OAS, bv, nil) + zero = ir.Nod(ir.OAS, bv, nil) nif.Nbody.Append(zero) // b = &bv - b := nod(OADDR, bv, nil) + b := ir.Nod(ir.OADDR, bv, nil) // h.buckets = b bsym := hmapType.Field(5).Sym // hmap.buckets see reflect.go:hmap - na := nod(OAS, nodSym(ODOT, h, bsym), b) + na := ir.Nod(ir.OAS, nodSym(ir.ODOT, h, bsym), b) nif.Nbody.Append(na) nif = typecheck(nif, ctxStmt) @@ -1258,7 +1259,7 @@ opswitch: } } - if Isconst(hint, constant.Int) && constant.Compare(hint.Val(), token.LEQ, constant.MakeInt64(BUCKETSIZE)) { + if ir.IsConst(hint, constant.Int) && constant.Compare(hint.Val(), token.LEQ, constant.MakeInt64(BUCKETSIZE)) { // Handling make(map[any]any) and // make(map[any]any, hint) where hint <= BUCKETSIZE // special allows for faster map initialization and @@ -1270,9 +1271,9 @@ opswitch: // Only need to initialize h.hash0 since // hmap h has been allocated on the stack already. // h.hash0 = fastrand() - rand := mkcall("fastrand", types.Types[TUINT32], init) + rand := mkcall("fastrand", types.Types[types.TUINT32], init) hashsym := hmapType.Field(4).Sym // hmap.hash0 see reflect.go:hmap - a := nod(OAS, nodSym(ODOT, h, hashsym), rand) + a := ir.Nod(ir.OAS, nodSym(ir.ODOT, h, hashsym), rand) a = typecheck(a, ctxStmt) a = walkexpr(a, init) init.Append(a) @@ -1296,15 +1297,15 @@ opswitch: // When hint fits into int, use makemap instead of // makemap64, which is faster and shorter on 32 bit platforms. fnname := "makemap64" - argtype := types.Types[TINT64] + argtype := types.Types[types.TINT64] // Type checking guarantees that TIDEAL hint is positive and fits in an int. // See checkmake call in TMAP case of OMAKE case in OpSwitch in typecheck1 function. // The case of hint overflow when converting TUINT or TUINTPTR to TINT // will be handled by the negative range checks in makemap during runtime. - if hint.Type.IsKind(TIDEAL) || hint.Type.Size() <= types.Types[TUINT].Size() { + if hint.Type.IsKind(types.TIDEAL) || hint.Type.Size() <= types.Types[types.TUINT].Size() { fnname = "makemap" - argtype = types.Types[TINT] + argtype = types.Types[types.TINT] } fn := syslook(fnname) @@ -1312,7 +1313,7 @@ opswitch: n = mkcall1(fn, n.Type, init, typename(n.Type), conv(hint, argtype), h) } - case OMAKESLICE: + case ir.OMAKESLICE: l := n.Left r := n.Right if r == nil { @@ -1341,8 +1342,8 @@ opswitch: // if len < 0 { panicmakeslicelen() } // panicmakeslicecap() // } - nif := nod(OIF, nod(OGT, conv(l, types.Types[TUINT64]), nodintconst(i)), nil) - niflen := nod(OIF, nod(OLT, l, nodintconst(0)), nil) + nif := ir.Nod(ir.OIF, ir.Nod(ir.OGT, conv(l, types.Types[types.TUINT64]), nodintconst(i)), nil) + niflen := ir.Nod(ir.OIF, ir.Nod(ir.OLT, l, nodintconst(0)), nil) niflen.Nbody.Set1(mkcall("panicmakeslicelen", nil, init)) nif.Nbody.Append(niflen, mkcall("panicmakeslicecap", nil, init)) nif = typecheck(nif, ctxStmt) @@ -1350,10 +1351,10 @@ opswitch: t = types.NewArray(t.Elem(), i) // [r]T var_ := temp(t) - a := nod(OAS, var_, nil) // zero temp + a := ir.Nod(ir.OAS, var_, nil) // zero temp a = typecheck(a, ctxStmt) init.Append(a) - r := nod(OSLICE, var_, nil) // arr[:l] + r := ir.Nod(ir.OSLICE, var_, nil) // arr[:l] r.SetSliceBounds(nil, l, nil) r = conv(r, n.Type) // in case n.Type is named. r = typecheck(r, ctxExpr) @@ -1367,31 +1368,31 @@ opswitch: len, cap := l, r fnname := "makeslice64" - argtype := types.Types[TINT64] + argtype := types.Types[types.TINT64] // Type checking guarantees that TIDEAL len/cap are positive and fit in an int. // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT // will be handled by the negative range checks in makeslice during runtime. - if (len.Type.IsKind(TIDEAL) || len.Type.Size() <= types.Types[TUINT].Size()) && - (cap.Type.IsKind(TIDEAL) || cap.Type.Size() <= types.Types[TUINT].Size()) { + if (len.Type.IsKind(types.TIDEAL) || len.Type.Size() <= types.Types[types.TUINT].Size()) && + (cap.Type.IsKind(types.TIDEAL) || cap.Type.Size() <= types.Types[types.TUINT].Size()) { fnname = "makeslice" - argtype = types.Types[TINT] + argtype = types.Types[types.TINT] } - m := nod(OSLICEHEADER, nil, nil) + m := ir.Nod(ir.OSLICEHEADER, nil, nil) m.Type = t fn := syslook(fnname) - m.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype)) + m.Left = mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype)) m.Left.MarkNonNil() - m.List.Set2(conv(len, types.Types[TINT]), conv(cap, types.Types[TINT])) + m.List.Set2(conv(len, types.Types[types.TINT]), conv(cap, types.Types[types.TINT])) m = typecheck(m, ctxExpr) m = walkexpr(m, init) n = m } - case OMAKESLICECOPY: + case ir.OMAKESLICECOPY: if n.Esc == EscNone { base.Fatalf("OMAKESLICECOPY with EscNone: %v", n) } @@ -1401,9 +1402,9 @@ opswitch: base.Errorf("%v can't be allocated in Go; it is incomplete (or unallocatable)", t.Elem()) } - length := conv(n.Left, types.Types[TINT]) - copylen := nod(OLEN, n.Right, nil) - copyptr := nod(OSPTR, n.Right, nil) + length := conv(n.Left, types.Types[types.TINT]) + copylen := ir.Nod(ir.OLEN, n.Right, nil) + copyptr := ir.Nod(ir.OSPTR, n.Right, nil) if !t.Elem().HasPointers() && n.Bounded() { // When len(to)==len(from) and elements have no pointers: @@ -1412,25 +1413,25 @@ opswitch: // We do not check for overflow of len(to)*elem.Width here // since len(from) is an existing checked slice capacity // with same elem.Width for the from slice. - size := nod(OMUL, conv(length, types.Types[TUINTPTR]), conv(nodintconst(t.Elem().Width), types.Types[TUINTPTR])) + size := ir.Nod(ir.OMUL, conv(length, types.Types[types.TUINTPTR]), conv(nodintconst(t.Elem().Width), types.Types[types.TUINTPTR])) // instantiate mallocgc(size uintptr, typ *byte, needszero bool) unsafe.Pointer fn := syslook("mallocgc") - sh := nod(OSLICEHEADER, nil, nil) - sh.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, size, nodnil(), nodbool(false)) + sh := ir.Nod(ir.OSLICEHEADER, nil, nil) + sh.Left = mkcall1(fn, types.Types[types.TUNSAFEPTR], init, size, nodnil(), nodbool(false)) sh.Left.MarkNonNil() sh.List.Set2(length, length) sh.Type = t s := temp(t) - r := typecheck(nod(OAS, s, sh), ctxStmt) + r := typecheck(ir.Nod(ir.OAS, s, sh), ctxStmt) r = walkexpr(r, init) init.Append(r) // instantiate memmove(to *any, frm *any, size uintptr) fn = syslook("memmove") fn = substArgTypes(fn, t.Elem(), t.Elem()) - ncopy := mkcall1(fn, nil, init, nod(OSPTR, s, nil), copyptr, size) + ncopy := mkcall1(fn, nil, init, ir.Nod(ir.OSPTR, s, nil), copyptr, size) ncopy = typecheck(ncopy, ctxStmt) ncopy = walkexpr(ncopy, init) init.Append(ncopy) @@ -1439,8 +1440,8 @@ opswitch: } else { // Replace make+copy with runtime.makeslicecopy. // instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer fn := syslook("makeslicecopy") - s := nod(OSLICEHEADER, nil, nil) - s.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[TUNSAFEPTR])) + s := ir.Nod(ir.OSLICEHEADER, nil, nil) + s.Left = mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[types.TUNSAFEPTR])) s.Left.MarkNonNil() s.List.Set2(length, length) s.Type = t @@ -1448,33 +1449,33 @@ opswitch: n = walkexpr(n, init) } - case ORUNESTR: + case ir.ORUNESTR: a := nodnil() if n.Esc == EscNone { - t := types.NewArray(types.Types[TUINT8], 4) - a = nod(OADDR, temp(t), nil) + t := types.NewArray(types.Types[types.TUINT8], 4) + a = ir.Nod(ir.OADDR, temp(t), nil) } // intstring(*[4]byte, rune) - n = mkcall("intstring", n.Type, init, a, conv(n.Left, types.Types[TINT64])) + n = mkcall("intstring", n.Type, init, a, conv(n.Left, types.Types[types.TINT64])) - case OBYTES2STR, ORUNES2STR: + case ir.OBYTES2STR, ir.ORUNES2STR: a := nodnil() if n.Esc == EscNone { // Create temporary buffer for string on stack. - t := types.NewArray(types.Types[TUINT8], tmpstringbufsize) - a = nod(OADDR, temp(t), nil) + t := types.NewArray(types.Types[types.TUINT8], tmpstringbufsize) + a = ir.Nod(ir.OADDR, temp(t), nil) } - if n.Op == ORUNES2STR { + if n.Op == ir.ORUNES2STR { // slicerunetostring(*[32]byte, []rune) string n = mkcall("slicerunetostring", n.Type, init, a, n.Left) } else { // slicebytetostring(*[32]byte, ptr *byte, n int) string n.Left = cheapexpr(n.Left, init) - ptr, len := n.Left.backingArrayPtrLen() + ptr, len := backingArrayPtrLen(n.Left) n = mkcall("slicebytetostring", n.Type, init, a, ptr, len) } - case OBYTES2STRTMP: + case ir.OBYTES2STRTMP: n.Left = walkexpr(n.Left, init) if !instrumenting { // Let the backend handle OBYTES2STRTMP directly @@ -1483,37 +1484,37 @@ opswitch: } // slicebytetostringtmp(ptr *byte, n int) string n.Left = cheapexpr(n.Left, init) - ptr, len := n.Left.backingArrayPtrLen() + ptr, len := backingArrayPtrLen(n.Left) n = mkcall("slicebytetostringtmp", n.Type, init, ptr, len) - case OSTR2BYTES: + case ir.OSTR2BYTES: s := n.Left - if Isconst(s, constant.String) { + if ir.IsConst(s, constant.String) { sc := s.StringVal() // Allocate a [n]byte of the right size. - t := types.NewArray(types.Types[TUINT8], int64(len(sc))) - var a *Node + t := types.NewArray(types.Types[types.TUINT8], int64(len(sc))) + var a *ir.Node if n.Esc == EscNone && len(sc) <= int(maxImplicitStackVarSize) { - a = nod(OADDR, temp(t), nil) + a = ir.Nod(ir.OADDR, temp(t), nil) } else { a = callnew(t) } p := temp(t.PtrTo()) // *[n]byte - init.Append(typecheck(nod(OAS, p, a), ctxStmt)) + init.Append(typecheck(ir.Nod(ir.OAS, p, a), ctxStmt)) // Copy from the static string data to the [n]byte. if len(sc) > 0 { - as := nod(OAS, - nod(ODEREF, p, nil), - nod(ODEREF, convnop(nod(OSPTR, s, nil), t.PtrTo()), nil)) + as := ir.Nod(ir.OAS, + ir.Nod(ir.ODEREF, p, nil), + ir.Nod(ir.ODEREF, convnop(ir.Nod(ir.OSPTR, s, nil), t.PtrTo()), nil)) as = typecheck(as, ctxStmt) as = walkstmt(as) init.Append(as) } // Slice the [n]byte to a []byte. - n.Op = OSLICEARR + n.Op = ir.OSLICEARR n.Left = p n = walkexpr(n, init) break @@ -1522,13 +1523,13 @@ opswitch: a := nodnil() if n.Esc == EscNone { // Create temporary buffer for slice on stack. - t := types.NewArray(types.Types[TUINT8], tmpstringbufsize) - a = nod(OADDR, temp(t), nil) + t := types.NewArray(types.Types[types.TUINT8], tmpstringbufsize) + a = ir.Nod(ir.OADDR, temp(t), nil) } // stringtoslicebyte(*32[byte], string) []byte - n = mkcall("stringtoslicebyte", n.Type, init, a, conv(s, types.Types[TSTRING])) + n = mkcall("stringtoslicebyte", n.Type, init, a, conv(s, types.Types[types.TSTRING])) - case OSTR2BYTESTMP: + case ir.OSTR2BYTESTMP: // []byte(string) conversion that creates a slice // referring to the actual string bytes. // This conversion is handled later by the backend and @@ -1538,17 +1539,17 @@ opswitch: // for i, c := range []byte(string) n.Left = walkexpr(n.Left, init) - case OSTR2RUNES: + case ir.OSTR2RUNES: a := nodnil() if n.Esc == EscNone { // Create temporary buffer for slice on stack. - t := types.NewArray(types.Types[TINT32], tmpstringbufsize) - a = nod(OADDR, temp(t), nil) + t := types.NewArray(types.Types[types.TINT32], tmpstringbufsize) + a = ir.Nod(ir.OADDR, temp(t), nil) } // stringtoslicerune(*[32]rune, string) []rune - n = mkcall("stringtoslicerune", n.Type, init, a, conv(n.Left, types.Types[TSTRING])) + n = mkcall("stringtoslicerune", n.Type, init, a, conv(n.Left, types.Types[types.TSTRING])) - case OARRAYLIT, OSLICELIT, OMAPLIT, OSTRUCTLIT, OPTRLIT: + case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT, ir.OPTRLIT: if isStaticCompositeLiteral(n) && !canSSAType(n.Type) { // n can be directly represented in the read-only data section. // Make direct reference to the static data. See issue 12841. @@ -1562,17 +1563,17 @@ opswitch: anylit(n, var_, init) n = var_ - case OSEND: + case ir.OSEND: n1 := n.Right n1 = assignconv(n1, n.Left.Type.Elem(), "chan send") n1 = walkexpr(n1, init) - n1 = nod(OADDR, n1, nil) + n1 = ir.Nod(ir.OADDR, n1, nil) n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, n.Left, n1) - case OCLOSURE: + case ir.OCLOSURE: n = walkclosure(n, init) - case OCALLPART: + case ir.OCALLPART: n = walkpartialcall(n, init) } @@ -1586,7 +1587,7 @@ opswitch: if n.Type != t { base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type) } - if n.Op == OLITERAL { + if n.Op == ir.OLITERAL { n = typecheck(n, ctxExpr) // Emit string symbol now to avoid emitting // any concurrently during the backend. @@ -1598,7 +1599,7 @@ opswitch: updateHasCall(n) if base.Flag.LowerW != 0 && n != nil { - Dump("after walk expr", n) + ir.Dump("after walk expr", n) } base.Pos = lno @@ -1618,10 +1619,10 @@ func markTypeUsedInInterface(t *types.Type, from *obj.LSym) { // markUsedIfaceMethod marks that an interface method is used in the current // function. n is OCALLINTER node. -func markUsedIfaceMethod(n *Node) { +func markUsedIfaceMethod(n *ir.Node) { ityp := n.Left.Left.Type tsym := typenamesym(ityp).Linksym() - r := obj.Addrel(Curfn.Func.lsym) + r := obj.Addrel(Curfn.Func.LSym) r.Sym = tsym // n.Left.Xoffset is the method index * Widthptr (the offset of code pointer // in itab). @@ -1637,54 +1638,54 @@ func markUsedIfaceMethod(n *Node) { // If no such function is necessary, it returns (Txxx, Txxx). func rtconvfn(src, dst *types.Type) (param, result types.EType) { if thearch.SoftFloat { - return Txxx, Txxx + return types.Txxx, types.Txxx } switch thearch.LinkArch.Family { case sys.ARM, sys.MIPS: if src.IsFloat() { switch dst.Etype { - case TINT64, TUINT64: - return TFLOAT64, dst.Etype + case types.TINT64, types.TUINT64: + return types.TFLOAT64, dst.Etype } } if dst.IsFloat() { switch src.Etype { - case TINT64, TUINT64: - return src.Etype, TFLOAT64 + case types.TINT64, types.TUINT64: + return src.Etype, types.TFLOAT64 } } case sys.I386: if src.IsFloat() { switch dst.Etype { - case TINT64, TUINT64: - return TFLOAT64, dst.Etype - case TUINT32, TUINT, TUINTPTR: - return TFLOAT64, TUINT32 + case types.TINT64, types.TUINT64: + return types.TFLOAT64, dst.Etype + case types.TUINT32, types.TUINT, types.TUINTPTR: + return types.TFLOAT64, types.TUINT32 } } if dst.IsFloat() { switch src.Etype { - case TINT64, TUINT64: - return src.Etype, TFLOAT64 - case TUINT32, TUINT, TUINTPTR: - return TUINT32, TFLOAT64 + case types.TINT64, types.TUINT64: + return src.Etype, types.TFLOAT64 + case types.TUINT32, types.TUINT, types.TUINTPTR: + return types.TUINT32, types.TFLOAT64 } } } - return Txxx, Txxx + return types.Txxx, types.Txxx } // TODO(josharian): combine this with its caller and simplify -func reduceSlice(n *Node) *Node { +func reduceSlice(n *ir.Node) *ir.Node { low, high, max := n.SliceBounds() - if high != nil && high.Op == OLEN && samesafeexpr(n.Left, high.Left) { + if high != nil && high.Op == ir.OLEN && samesafeexpr(n.Left, high.Left) { // Reduce x[i:len(x)] to x[i:]. high = nil } n.SetSliceBounds(low, high, max) - if (n.Op == OSLICE || n.Op == OSLICESTR) && low == nil && high == nil { + if (n.Op == ir.OSLICE || n.Op == ir.OSLICESTR) && low == nil && high == nil { // Reduce x[:] to x. if base.Debug.Slice > 0 { base.Warn("slice: omit slice operation") @@ -1694,19 +1695,19 @@ func reduceSlice(n *Node) *Node { return n } -func ascompatee1(l *Node, r *Node, init *Nodes) *Node { +func ascompatee1(l *ir.Node, r *ir.Node, init *ir.Nodes) *ir.Node { // convas will turn map assigns into function calls, // making it impossible for reorder3 to work. - n := nod(OAS, l, r) + n := ir.Nod(ir.OAS, l, r) - if l.Op == OINDEXMAP { + if l.Op == ir.OINDEXMAP { return n } return convas(n, init) } -func ascompatee(op Op, nl, nr []*Node, init *Nodes) []*Node { +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 @@ -1719,14 +1720,14 @@ func ascompatee(op Op, nl, nr []*Node, init *Nodes) []*Node { nr[i1] = safeexpr(nr[i1], init) } - var nn []*Node + var nn []*ir.Node i := 0 for ; i < len(nl); i++ { if i >= len(nr) { break } // Do not generate 'x = x' during return. See issue 4014. - if op == ORETURN && samesafeexpr(nl[i], nr[i]) { + if op == ir.ORETURN && samesafeexpr(nl[i], nr[i]) { continue } nn = append(nn, ascompatee1(nl[i], nr[i], init)) @@ -1734,17 +1735,17 @@ func ascompatee(op Op, nl, nr []*Node, init *Nodes) []*Node { // cannot happen: caller checked that lists had same length if i < len(nl) || i < len(nr) { - var nln, nrn Nodes + 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), Curfn.funcname()) + base.Fatalf("error in shape across %+v %v %+v / %d %d [%s]", nln, op, nrn, len(nl), len(nr), ir.FuncName(Curfn)) } return nn } // fncall reports whether assigning an rvalue of type rt to an lvalue l might involve a function call. -func fncall(l *Node, rt *types.Type) bool { - if l.HasCall() || l.Op == OINDEXMAP { +func fncall(l *ir.Node, rt *types.Type) bool { + if l.HasCall() || l.Op == ir.OINDEXMAP { return true } if types.Identical(l.Type, rt) { @@ -1757,14 +1758,14 @@ func fncall(l *Node, rt *types.Type) bool { // check assign type list to // an expression list. called in // expr-list = func() -func ascompatet(nl Nodes, nr *types.Type) []*Node { +func ascompatet(nl ir.Nodes, nr *types.Type) []*ir.Node { if nl.Len() != nr.NumFields() { base.Fatalf("ascompatet: assignment count mismatch: %d = %d", nl.Len(), nr.NumFields()) } - var nn, mm Nodes + var nn, mm ir.Nodes for i, l := range nl.Slice() { - if l.isBlank() { + if ir.IsBlank(l) { continue } r := nr.Field(i) @@ -1774,22 +1775,22 @@ func ascompatet(nl Nodes, nr *types.Type) []*Node { if fncall(l, r.Type) { tmp := temp(r.Type) tmp = typecheck(tmp, ctxExpr) - a := nod(OAS, l, tmp) + a := ir.Nod(ir.OAS, l, tmp) a = convas(a, &mm) mm.Append(a) l = tmp } - res := nod(ORESULT, nil, nil) + res := ir.Nod(ir.ORESULT, nil, nil) res.Xoffset = base.Ctxt.FixedFrameSize() + r.Offset res.Type = r.Type res.SetTypecheck(1) - a := nod(OAS, l, res) + a := ir.Nod(ir.OAS, l, res) a = convas(a, &nn) updateHasCall(a) if a.HasCall() { - Dump("ascompatet ucount", a) + ir.Dump("ascompatet ucount", a) base.Fatalf("ascompatet: too many function calls evaluating parameters") } @@ -1799,13 +1800,13 @@ func ascompatet(nl Nodes, nr *types.Type) []*Node { } // package all the arguments that match a ... T parameter into a []T. -func mkdotargslice(typ *types.Type, args []*Node) *Node { - var n *Node +func mkdotargslice(typ *types.Type, args []*ir.Node) *ir.Node { + var n *ir.Node if len(args) == 0 { n = nodnil() n.Type = typ } else { - n = nod(OCOMPLIT, nil, typenod(typ)) + n = ir.Nod(ir.OCOMPLIT, nil, typenod(typ)) n.List.Append(args...) n.SetImplicit(true) } @@ -1819,7 +1820,7 @@ func mkdotargslice(typ *types.Type, args []*Node) *Node { // fixVariadicCall rewrites calls to variadic functions to use an // explicit ... argument if one is not already present. -func fixVariadicCall(call *Node) { +func fixVariadicCall(call *ir.Node) { fntype := call.Left.Type if !fntype.IsVariadic() || call.IsDDD() { return @@ -1839,7 +1840,7 @@ func fixVariadicCall(call *Node) { call.SetIsDDD(true) } -func walkCall(n *Node, init *Nodes) { +func walkCall(n *ir.Node, init *ir.Nodes) { if n.Rlist.Len() != 0 { return // already walked } @@ -1851,8 +1852,8 @@ func walkCall(n *Node, init *Nodes) { walkexprlist(args, init) // If this is a method call, add the receiver at the beginning of the args. - if n.Op == OCALLMETH { - withRecv := make([]*Node, len(args)+1) + if n.Op == ir.OCALLMETH { + withRecv := make([]*ir.Node, len(args)+1) withRecv[0] = n.Left.Left n.Left.Left = nil copy(withRecv[1:], args) @@ -1863,12 +1864,12 @@ func walkCall(n *Node, init *Nodes) { // store that argument into a temporary variable, // to prevent that calls from clobbering arguments already on the stack. // When instrumenting, all arguments might require function calls. - var tempAssigns []*Node + var tempAssigns []*ir.Node for i, arg := range args { updateHasCall(arg) // Determine param type. var t *types.Type - if n.Op == OCALLMETH { + if n.Op == ir.OCALLMETH { if i == 0 { t = n.Left.Type.Recv().Type } else { @@ -1880,7 +1881,7 @@ func walkCall(n *Node, init *Nodes) { if instrumenting || fncall(arg, t) { // make assignment of fncall to tempAt tmp := temp(t) - a := nod(OAS, tmp, arg) + a := ir.Nod(ir.OAS, tmp, arg) a = convas(a, init) tempAssigns = append(tempAssigns, a) // replace arg with temp @@ -1893,14 +1894,14 @@ func walkCall(n *Node, init *Nodes) { } // generate code for print -func walkprint(nn *Node, init *Nodes) *Node { +func walkprint(nn *ir.Node, init *ir.Nodes) *ir.Node { // Hoist all the argument evaluation up before the lock. walkexprlistcheap(nn.List.Slice(), init) // For println, add " " between elements and "\n" at the end. - if nn.Op == OPRINTN { + if nn.Op == ir.OPRINTN { s := nn.List.Slice() - t := make([]*Node, 0, len(s)*2) + t := make([]*ir.Node, 0, len(s)*2) for i, n := range s { if i != 0 { t = append(t, nodstr(" ")) @@ -1913,10 +1914,10 @@ func walkprint(nn *Node, init *Nodes) *Node { // Collapse runs of constant strings. s := nn.List.Slice() - t := make([]*Node, 0, len(s)) + t := make([]*ir.Node, 0, len(s)) for i := 0; i < len(s); { var strs []string - for i < len(s) && Isconst(s[i], constant.String) { + for i < len(s) && ir.IsConst(s[i], constant.String) { strs = append(strs, s[i].StringVal()) i++ } @@ -1930,73 +1931,73 @@ func walkprint(nn *Node, init *Nodes) *Node { } nn.List.Set(t) - calls := []*Node{mkcall("printlock", nil, init)} + calls := []*ir.Node{mkcall("printlock", nil, init)} for i, n := range nn.List.Slice() { - if n.Op == OLITERAL { + if n.Op == ir.OLITERAL { if n.Type == types.UntypedRune { n = defaultlit(n, types.Runetype) } switch n.Val().Kind() { case constant.Int: - n = defaultlit(n, types.Types[TINT64]) + n = defaultlit(n, types.Types[types.TINT64]) case constant.Float: - n = defaultlit(n, types.Types[TFLOAT64]) + n = defaultlit(n, types.Types[types.TFLOAT64]) } } - if n.Op != OLITERAL && n.Type != nil && n.Type.Etype == TIDEAL { - n = defaultlit(n, types.Types[TINT64]) + if n.Op != ir.OLITERAL && n.Type != nil && n.Type.Etype == types.TIDEAL { + n = defaultlit(n, types.Types[types.TINT64]) } n = defaultlit(n, nil) nn.List.SetIndex(i, n) - if n.Type == nil || n.Type.Etype == TFORW { + if n.Type == nil || n.Type.Etype == types.TFORW { continue } - var on *Node + var on *ir.Node switch n.Type.Etype { - case TINTER: + case types.TINTER: if n.Type.IsEmptyInterface() { on = syslook("printeface") } else { on = syslook("printiface") } on = substArgTypes(on, n.Type) // any-1 - case TPTR: + case types.TPTR: if n.Type.Elem().NotInHeap() { on = syslook("printuintptr") - n = nod(OCONV, n, nil) - n.Type = types.Types[TUNSAFEPTR] - n = nod(OCONV, n, nil) - n.Type = types.Types[TUINTPTR] + n = ir.Nod(ir.OCONV, n, nil) + n.Type = types.Types[types.TUNSAFEPTR] + n = ir.Nod(ir.OCONV, n, nil) + n.Type = types.Types[types.TUINTPTR] break } fallthrough - case TCHAN, TMAP, TFUNC, TUNSAFEPTR: + case types.TCHAN, types.TMAP, types.TFUNC, types.TUNSAFEPTR: on = syslook("printpointer") on = substArgTypes(on, n.Type) // any-1 - case TSLICE: + case types.TSLICE: on = syslook("printslice") on = substArgTypes(on, n.Type) // any-1 - case TUINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINTPTR: + case types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINTPTR: if isRuntimePkg(n.Type.Sym.Pkg) && n.Type.Sym.Name == "hex" { on = syslook("printhex") } else { on = syslook("printuint") } - case TINT, TINT8, TINT16, TINT32, TINT64: + case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64: on = syslook("printint") - case TFLOAT32, TFLOAT64: + case types.TFLOAT32, types.TFLOAT64: on = syslook("printfloat") - case TCOMPLEX64, TCOMPLEX128: + case types.TCOMPLEX64, types.TCOMPLEX128: on = syslook("printcomplex") - case TBOOL: + case types.TBOOL: on = syslook("printbool") - case TSTRING: + case types.TSTRING: cs := "" - if Isconst(n, constant.String) { + if ir.IsConst(n, constant.String) { cs = n.StringVal() } switch cs { @@ -2008,15 +2009,15 @@ func walkprint(nn *Node, init *Nodes) *Node { on = syslook("printstring") } default: - badtype(OPRINT, n.Type, nil) + badtype(ir.OPRINT, n.Type, nil) continue } - r := nod(OCALL, on, nil) + r := ir.Nod(ir.OCALL, on, nil) if params := on.Type.Params().FieldSlice(); len(params) > 0 { t := params[0].Type if !types.Identical(t, n.Type) { - n = nod(OCONV, n, nil) + n = ir.Nod(ir.OCONV, n, nil) n.Type = t } r.List.Append(n) @@ -2029,16 +2030,16 @@ func walkprint(nn *Node, init *Nodes) *Node { typecheckslice(calls, ctxStmt) walkexprlist(calls, init) - r := nod(OEMPTY, nil, nil) + r := ir.Nod(ir.OEMPTY, nil, nil) r = typecheck(r, ctxStmt) r = walkexpr(r, init) r.Ninit.Set(calls) return r } -func callnew(t *types.Type) *Node { +func callnew(t *types.Type) *ir.Node { dowidth(t) - n := nod(ONEWOBJ, typename(t), nil) + n := ir.Nod(ir.ONEWOBJ, typename(t), nil) n.Type = types.NewPtr(t) n.SetTypecheck(1) n.MarkNonNil() @@ -2047,16 +2048,16 @@ func callnew(t *types.Type) *Node { // isReflectHeaderDataField reports whether l is an expression p.Data // where p has type reflect.SliceHeader or reflect.StringHeader. -func isReflectHeaderDataField(l *Node) bool { - if l.Type != types.Types[TUINTPTR] { +func isReflectHeaderDataField(l *ir.Node) bool { + if l.Type != types.Types[types.TUINTPTR] { return false } var tsym *types.Sym switch l.Op { - case ODOT: + case ir.ODOT: tsym = l.Left.Type.Sym - case ODOTPTR: + case ir.ODOTPTR: tsym = l.Left.Type.Elem().Sym default: return false @@ -2068,8 +2069,8 @@ func isReflectHeaderDataField(l *Node) bool { return tsym.Name == "SliceHeader" || tsym.Name == "StringHeader" } -func convas(n *Node, init *Nodes) *Node { - if n.Op != OAS { +func convas(n *ir.Node, init *ir.Nodes) *ir.Node { + if n.Op != ir.OAS { base.Fatalf("convas: not OAS %v", n.Op) } defer updateHasCall(n) @@ -2086,7 +2087,7 @@ func convas(n *Node, init *Nodes) *Node { return n } - if n.Left.isBlank() { + if ir.IsBlank(n.Left) { n.Right = defaultlit(n.Right, nil) return n } @@ -2106,25 +2107,25 @@ func convas(n *Node, init *Nodes) *Node { // be later use of an earlier lvalue. // // function calls have been removed. -func reorder3(all []*Node) []*Node { +func reorder3(all []*ir.Node) []*ir.Node { // 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 []*Node + var early []*ir.Node - var mapinit Nodes + var mapinit ir.Nodes for i, n := range all { l := n.Left // Save subexpressions needed on left side. // Drill through non-dereferences. for { - if l.Op == ODOT || l.Op == OPAREN { + if l.Op == ir.ODOT || l.Op == ir.OPAREN { l = l.Left continue } - if l.Op == OINDEX && l.Left.Type.IsArray() { + if l.Op == ir.OINDEX && l.Left.Type.IsArray() { l.Right = reorder3save(l.Right, all, i, &early) l = l.Left continue @@ -2137,17 +2138,17 @@ func reorder3(all []*Node) []*Node { default: base.Fatalf("reorder3 unexpected lvalue %#v", l.Op) - case ONAME: + case ir.ONAME: break - case OINDEX, OINDEXMAP: + case ir.OINDEX, ir.OINDEXMAP: l.Left = reorder3save(l.Left, all, i, &early) l.Right = reorder3save(l.Right, all, i, &early) - if l.Op == OINDEXMAP { + if l.Op == ir.OINDEXMAP { all[i] = convas(all[i], &mapinit) } - case ODEREF, ODOTPTR: + case ir.ODEREF, ir.ODOTPTR: l.Left = reorder3save(l.Left, all, i, &early) } @@ -2165,13 +2166,13 @@ func reorder3(all []*Node) []*Node { // 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 *Node, all []*Node, i int, early *[]*Node) *Node { +func reorder3save(n *ir.Node, all []*ir.Node, i int, early *[]*ir.Node) *ir.Node { if !aliased(n, all[:i]) { return n } q := temp(n.Type) - q = nod(OAS, q, n) + q = ir.Nod(ir.OAS, q, n) q = typecheck(q, ctxStmt) *early = append(*early, q) return q.Left @@ -2179,15 +2180,15 @@ func reorder3save(n *Node, all []*Node, i int, early *[]*Node) *Node { // what's the outer value that a write to n affects? // outer value means containing struct or array. -func outervalue(n *Node) *Node { +func outervalue(n *ir.Node) *ir.Node { for { switch n.Op { - case OXDOT: + case ir.OXDOT: base.Fatalf("OXDOT in walk") - case ODOT, OPAREN, OCONVNOP: + case ir.ODOT, ir.OPAREN, ir.OCONVNOP: n = n.Left continue - case OINDEX: + case ir.OINDEX: if n.Left.Type != nil && n.Left.Type.IsArray() { n = n.Left continue @@ -2200,14 +2201,14 @@ func outervalue(n *Node) *Node { // Is it possible that the computation of r might be // affected by assignments in all? -func aliased(r *Node, all []*Node) bool { +func aliased(r *ir.Node, all []*ir.Node) 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 == ODOT { + for r.Op == ir.ODOT { r = r.Left } @@ -2219,12 +2220,12 @@ func aliased(r *Node, all []*Node) bool { memwrite := false for _, as := range all { // We can ignore assignments to blank. - if as.Left.isBlank() { + if ir.IsBlank(as.Left) { continue } l := outervalue(as.Left) - if l.Op != ONAME { + if l.Op != ir.ONAME { memwrite = true continue } @@ -2233,11 +2234,11 @@ func aliased(r *Node, all []*Node) bool { default: base.Fatalf("unexpected class: %v, %v", l, l.Class()) - case PAUTOHEAP, PEXTERN: + case ir.PAUTOHEAP, ir.PEXTERN: memwrite = true continue - case PAUTO, PPARAM, PPARAMOUT: + case ir.PAUTO, ir.PPARAM, ir.PPARAMOUT: if l.Name.Addrtaken() { memwrite = true continue @@ -2274,18 +2275,18 @@ func aliased(r *Node, all []*Node) bool { // does the evaluation of n only refer to variables // whose addresses have not been taken? // (and no other memory) -func varexpr(n *Node) bool { +func varexpr(n *ir.Node) bool { if n == nil { return true } switch n.Op { - case OLITERAL, ONIL: + case ir.OLITERAL, ir.ONIL: return true - case ONAME: + case ir.ONAME: switch n.Class() { - case PAUTO, PPARAM, PPARAMOUT: + case ir.PAUTO, ir.PPARAM, ir.PPARAMOUT: if !n.Name.Addrtaken() { return true } @@ -2293,30 +2294,30 @@ func varexpr(n *Node) bool { return false - case OADD, - OSUB, - OOR, - OXOR, - OMUL, - ODIV, - OMOD, - OLSH, - ORSH, - OAND, - OANDNOT, - OPLUS, - ONEG, - OBITNOT, - OPAREN, - OANDAND, - OOROR, - OCONV, - OCONVNOP, - OCONVIFACE, - ODOTTYPE: + case ir.OADD, + ir.OSUB, + ir.OOR, + ir.OXOR, + ir.OMUL, + ir.ODIV, + ir.OMOD, + ir.OLSH, + ir.ORSH, + ir.OAND, + ir.OANDNOT, + ir.OPLUS, + ir.ONEG, + ir.OBITNOT, + ir.OPAREN, + ir.OANDAND, + ir.OOROR, + ir.OCONV, + ir.OCONVNOP, + ir.OCONVIFACE, + ir.ODOTTYPE: return varexpr(n.Left) && varexpr(n.Right) - case ODOT: // but not ODOTPTR + case ir.ODOT: // but not ODOTPTR // Should have been handled in aliased. base.Fatalf("varexpr unexpected ODOT") } @@ -2326,16 +2327,16 @@ func varexpr(n *Node) bool { } // is the name l mentioned in r? -func vmatch2(l *Node, r *Node) bool { +func vmatch2(l *ir.Node, r *ir.Node) bool { if r == nil { return false } switch r.Op { // match each right given left - case ONAME: + case ir.ONAME: return l == r - case OLITERAL, ONIL: + case ir.OLITERAL, ir.ONIL: return false } @@ -2355,15 +2356,15 @@ func vmatch2(l *Node, r *Node) bool { // is any name mentioned in l also mentioned in r? // called by sinit.go -func vmatch1(l *Node, r *Node) bool { +func vmatch1(l *ir.Node, r *ir.Node) bool { // isolate all left sides if l == nil || r == nil { return false } switch l.Op { - case ONAME: + case ir.ONAME: switch l.Class() { - case PPARAM, PAUTO: + case ir.PPARAM, ir.PAUTO: break default: @@ -2376,7 +2377,7 @@ func vmatch1(l *Node, r *Node) bool { return vmatch2(l, r) - case OLITERAL, ONIL: + case ir.OLITERAL, ir.ONIL: return false } @@ -2396,10 +2397,10 @@ func vmatch1(l *Node, r *Node) bool { // paramstoheap returns code to allocate memory for heap-escaped parameters // and to copy non-result parameters' values from the stack. -func paramstoheap(params *types.Type) []*Node { - var nn []*Node +func paramstoheap(params *types.Type) []*ir.Node { + var nn []*ir.Node for _, t := range params.Fields().Slice() { - v := asNode(t.Nname) + v := ir.AsNode(t.Nname) if v != nil && v.Sym != nil && strings.HasPrefix(v.Sym.Name, "~r") { // unnamed result v = nil } @@ -2408,9 +2409,9 @@ func paramstoheap(params *types.Type) []*Node { } if stackcopy := v.Name.Param.Stackcopy; stackcopy != nil { - nn = append(nn, walkstmt(nod(ODCL, v, nil))) - if stackcopy.Class() == PPARAM { - nn = append(nn, walkstmt(typecheck(nod(OAS, v, stackcopy), ctxStmt))) + nn = append(nn, walkstmt(ir.Nod(ir.ODCL, v, nil))) + if stackcopy.Class() == ir.PPARAM { + nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, v, stackcopy), ctxStmt))) } } } @@ -2427,14 +2428,14 @@ func paramstoheap(params *types.Type) []*Node { // The generated code is added to Curfn's Enter list. func zeroResults() { for _, f := range Curfn.Type.Results().Fields().Slice() { - v := asNode(f.Nname) + v := ir.AsNode(f.Nname) if v != nil && v.Name.Param.Heapaddr != nil { // The local which points to the return value is the // thing that needs zeroing. This is already handled // by a Needzero annotation in plive.go:livenessepilogue. continue } - if v.isParamHeapCopy() { + if isParamHeapCopy(v) { // TODO(josharian/khr): Investigate whether we can switch to "continue" here, // and document more in either case. // In the review of CL 114797, Keith wrote (roughly): @@ -2444,21 +2445,21 @@ func zeroResults() { v = v.Name.Param.Stackcopy } // Zero the stack location containing f. - Curfn.Func.Enter.Append(nodl(Curfn.Pos, OAS, v, nil)) + Curfn.Func.Enter.Append(ir.NodAt(Curfn.Pos, ir.OAS, v, nil)) } } // returnsfromheap returns code to copy values for heap-escaped parameters // back to the stack. -func returnsfromheap(params *types.Type) []*Node { - var nn []*Node +func returnsfromheap(params *types.Type) []*ir.Node { + var nn []*ir.Node for _, t := range params.Fields().Slice() { - v := asNode(t.Nname) + v := ir.AsNode(t.Nname) if v == nil { continue } - if stackcopy := v.Name.Param.Stackcopy; stackcopy != nil && stackcopy.Class() == PPARAMOUT { - nn = append(nn, walkstmt(typecheck(nod(OAS, stackcopy, v), ctxStmt))) + if stackcopy := v.Name.Param.Stackcopy; stackcopy != nil && stackcopy.Class() == ir.PPARAMOUT { + nn = append(nn, walkstmt(typecheck(ir.Nod(ir.OAS, stackcopy, v), ctxStmt))) } } @@ -2480,8 +2481,8 @@ func heapmoves() { base.Pos = lno } -func vmkcall(fn *Node, t *types.Type, init *Nodes, va []*Node) *Node { - if fn.Type == nil || fn.Type.Etype != TFUNC { +func vmkcall(fn *ir.Node, t *types.Type, init *ir.Nodes, va []*ir.Node) *ir.Node { + if fn.Type == nil || fn.Type.Etype != types.TFUNC { base.Fatalf("mkcall %v %v", fn, fn.Type) } @@ -2490,7 +2491,7 @@ func vmkcall(fn *Node, t *types.Type, init *Nodes, va []*Node) *Node { base.Fatalf("vmkcall %v needs %v args got %v", fn, n, len(va)) } - r := nod(OCALL, fn, nil) + r := ir.Nod(ir.OCALL, fn, nil) r.List.Set(va) if fn.Type.NumResults() > 0 { r = typecheck(r, ctxExpr|ctxMultiOK) @@ -2502,19 +2503,19 @@ func vmkcall(fn *Node, t *types.Type, init *Nodes, va []*Node) *Node { return r } -func mkcall(name string, t *types.Type, init *Nodes, args ...*Node) *Node { +func mkcall(name string, t *types.Type, init *ir.Nodes, args ...*ir.Node) *ir.Node { return vmkcall(syslook(name), t, init, args) } -func mkcall1(fn *Node, t *types.Type, init *Nodes, args ...*Node) *Node { +func mkcall1(fn *ir.Node, t *types.Type, init *ir.Nodes, args ...*ir.Node) *ir.Node { return vmkcall(fn, t, init, args) } -func conv(n *Node, t *types.Type) *Node { +func conv(n *ir.Node, t *types.Type) *ir.Node { if types.Identical(n.Type, t) { return n } - n = nod(OCONV, n, nil) + n = ir.Nod(ir.OCONV, n, nil) n.Type = t n = typecheck(n, ctxExpr) return n @@ -2522,11 +2523,11 @@ func conv(n *Node, t *types.Type) *Node { // convnop converts node n to type t using the OCONVNOP op // and typechecks the result with ctxExpr. -func convnop(n *Node, t *types.Type) *Node { +func convnop(n *ir.Node, t *types.Type) *ir.Node { if types.Identical(n.Type, t) { return n } - n = nod(OCONVNOP, n, nil) + n = ir.Nod(ir.OCONVNOP, n, nil) n.Type = t n = typecheck(n, ctxExpr) return n @@ -2535,23 +2536,23 @@ func convnop(n *Node, t *types.Type) *Node { // byteindex converts n, which is byte-sized, to an int used to index into an array. // We cannot use conv, because we allow converting bool to int here, // which is forbidden in user code. -func byteindex(n *Node) *Node { +func byteindex(n *ir.Node) *ir.Node { // We cannot convert from bool to int directly. // While converting from int8 to int is possible, it would yield // the wrong result for negative values. // Reinterpreting the value as an unsigned byte solves both cases. - if !types.Identical(n.Type, types.Types[TUINT8]) { - n = nod(OCONV, n, nil) - n.Type = types.Types[TUINT8] + if !types.Identical(n.Type, types.Types[types.TUINT8]) { + n = ir.Nod(ir.OCONV, n, nil) + n.Type = types.Types[types.TUINT8] n.SetTypecheck(1) } - n = nod(OCONV, n, nil) - n.Type = types.Types[TINT] + n = ir.Nod(ir.OCONV, n, nil) + n.Type = types.Types[types.TINT] n.SetTypecheck(1) return n } -func chanfn(name string, n int, t *types.Type) *Node { +func chanfn(name string, n int, t *types.Type) *ir.Node { if !t.IsChan() { base.Fatalf("chanfn %v", t) } @@ -2567,7 +2568,7 @@ func chanfn(name string, n int, t *types.Type) *Node { return fn } -func mapfn(name string, t *types.Type) *Node { +func mapfn(name string, t *types.Type) *ir.Node { if !t.IsMap() { base.Fatalf("mapfn %v", t) } @@ -2576,7 +2577,7 @@ func mapfn(name string, t *types.Type) *Node { return fn } -func mapfndel(name string, t *types.Type) *Node { +func mapfndel(name string, t *types.Type) *ir.Node { if !t.IsMap() { base.Fatalf("mapfn %v", t) } @@ -2635,13 +2636,13 @@ func mapfast(t *types.Type) int { return mapslow } -func writebarrierfn(name string, l *types.Type, r *types.Type) *Node { +func writebarrierfn(name string, l *types.Type, r *types.Type) *ir.Node { fn := syslook(name) fn = substArgTypes(fn, l, r) return fn } -func addstr(n *Node, init *Nodes) *Node { +func addstr(n *ir.Node, init *ir.Nodes) *ir.Node { // order.expr rewrote OADDSTR to have a list of strings. c := n.List.Len() @@ -2653,7 +2654,7 @@ func addstr(n *Node, init *Nodes) *Node { if n.Esc == EscNone { sz := int64(0) for _, n1 := range n.List.Slice() { - if n1.Op == OLITERAL { + if n1.Op == ir.OLITERAL { sz += int64(len(n1.StringVal())) } } @@ -2661,15 +2662,15 @@ func addstr(n *Node, init *Nodes) *Node { // Don't allocate the buffer if the result won't fit. if sz < tmpstringbufsize { // Create temporary buffer for result string on stack. - t := types.NewArray(types.Types[TUINT8], tmpstringbufsize) - buf = nod(OADDR, temp(t), nil) + t := types.NewArray(types.Types[types.TUINT8], tmpstringbufsize) + buf = ir.Nod(ir.OADDR, temp(t), nil) } } // build list of string arguments - args := []*Node{buf} + args := []*ir.Node{buf} for _, n2 := range n.List.Slice() { - args = append(args, conv(n2, types.Types[TSTRING])) + args = append(args, conv(n2, types.Types[types.TSTRING])) } var fn string @@ -2681,18 +2682,18 @@ func addstr(n *Node, init *Nodes) *Node { // large numbers of strings are passed to the runtime as a slice. fn = "concatstrings" - t := types.NewSlice(types.Types[TSTRING]) - slice := nod(OCOMPLIT, nil, typenod(t)) + t := types.NewSlice(types.Types[types.TSTRING]) + slice := ir.Nod(ir.OCOMPLIT, nil, typenod(t)) if prealloc[n] != nil { prealloc[slice] = prealloc[n] } slice.List.Set(args[1:]) // skip buf arg - args = []*Node{buf, slice} + args = []*ir.Node{buf, slice} slice.Esc = EscNone } cat := syslook(fn) - r := nod(OCALL, cat, nil) + r := ir.Nod(ir.OCALL, cat, nil) r.List.Set(args) r = typecheck(r, ctxExpr) r = walkexpr(r, init) @@ -2701,7 +2702,7 @@ func addstr(n *Node, init *Nodes) *Node { return r } -func walkAppendArgs(n *Node, init *Nodes) { +func walkAppendArgs(n *ir.Node, init *ir.Nodes) { walkexprlistsafe(n.List.Slice(), init) // walkexprlistsafe will leave OINDEX (s[n]) alone if both s @@ -2727,7 +2728,7 @@ func walkAppendArgs(n *Node, init *Nodes) { // s // // l2 is allowed to be a string. -func appendslice(n *Node, init *Nodes) *Node { +func appendslice(n *ir.Node, init *ir.Nodes) *ir.Node { walkAppendArgs(n, init) l1 := n.List.First() @@ -2735,82 +2736,82 @@ func appendslice(n *Node, init *Nodes) *Node { l2 = cheapexpr(l2, init) n.List.SetSecond(l2) - var nodes Nodes + var nodes ir.Nodes // var s []T s := temp(l1.Type) - nodes.Append(nod(OAS, s, l1)) // s = l1 + nodes.Append(ir.Nod(ir.OAS, s, l1)) // s = l1 elemtype := s.Type.Elem() // n := len(s) + len(l2) - nn := temp(types.Types[TINT]) - nodes.Append(nod(OAS, nn, nod(OADD, nod(OLEN, s, nil), nod(OLEN, l2, nil)))) + nn := temp(types.Types[types.TINT]) + nodes.Append(ir.Nod(ir.OAS, nn, ir.Nod(ir.OADD, ir.Nod(ir.OLEN, s, nil), ir.Nod(ir.OLEN, l2, nil)))) // if uint(n) > uint(cap(s)) - nif := nod(OIF, nil, nil) - nuint := conv(nn, types.Types[TUINT]) - scapuint := conv(nod(OCAP, s, nil), types.Types[TUINT]) - nif.Left = nod(OGT, nuint, scapuint) + nif := ir.Nod(ir.OIF, nil, nil) + nuint := conv(nn, types.Types[types.TUINT]) + scapuint := conv(ir.Nod(ir.OCAP, s, nil), types.Types[types.TUINT]) + nif.Left = ir.Nod(ir.OGT, nuint, scapuint) // instantiate growslice(typ *type, []any, int) []any fn := syslook("growslice") fn = substArgTypes(fn, elemtype, elemtype) // s = growslice(T, s, n) - nif.Nbody.Set1(nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(elemtype), s, nn))) + nif.Nbody.Set1(ir.Nod(ir.OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(elemtype), s, nn))) nodes.Append(nif) // s = s[:n] - nt := nod(OSLICE, s, nil) + nt := ir.Nod(ir.OSLICE, s, nil) nt.SetSliceBounds(nil, nn, nil) nt.SetBounded(true) - nodes.Append(nod(OAS, s, nt)) + nodes.Append(ir.Nod(ir.OAS, s, nt)) - var ncopy *Node + var ncopy *ir.Node if elemtype.HasPointers() { // copy(s[len(l1):], l2) - nptr1 := nod(OSLICE, s, nil) + nptr1 := ir.Nod(ir.OSLICE, s, nil) nptr1.Type = s.Type - nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil) + nptr1.SetSliceBounds(ir.Nod(ir.OLEN, l1, nil), nil, nil) nptr1 = cheapexpr(nptr1, &nodes) nptr2 := l2 - Curfn.Func.setWBPos(n.Pos) + Curfn.Func.SetWBPos(n.Pos) // instantiate typedslicecopy(typ *type, dstPtr *any, dstLen int, srcPtr *any, srcLen int) int fn := syslook("typedslicecopy") fn = substArgTypes(fn, l1.Type.Elem(), l2.Type.Elem()) - ptr1, len1 := nptr1.backingArrayPtrLen() - ptr2, len2 := nptr2.backingArrayPtrLen() - ncopy = mkcall1(fn, types.Types[TINT], &nodes, typename(elemtype), ptr1, len1, ptr2, len2) + ptr1, len1 := backingArrayPtrLen(nptr1) + ptr2, len2 := backingArrayPtrLen(nptr2) + ncopy = mkcall1(fn, types.Types[types.TINT], &nodes, typename(elemtype), ptr1, len1, ptr2, len2) } else if instrumenting && !base.Flag.CompilingRuntime { // rely on runtime to instrument: // copy(s[len(l1):], l2) // l2 can be a slice or string. - nptr1 := nod(OSLICE, s, nil) + nptr1 := ir.Nod(ir.OSLICE, s, nil) nptr1.Type = s.Type - nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil) + nptr1.SetSliceBounds(ir.Nod(ir.OLEN, l1, nil), nil, nil) nptr1 = cheapexpr(nptr1, &nodes) nptr2 := l2 - ptr1, len1 := nptr1.backingArrayPtrLen() - ptr2, len2 := nptr2.backingArrayPtrLen() + ptr1, len1 := backingArrayPtrLen(nptr1) + ptr2, len2 := backingArrayPtrLen(nptr2) fn := syslook("slicecopy") fn = substArgTypes(fn, ptr1.Type.Elem(), ptr2.Type.Elem()) - ncopy = mkcall1(fn, types.Types[TINT], &nodes, ptr1, len1, ptr2, len2, nodintconst(elemtype.Width)) + ncopy = mkcall1(fn, types.Types[types.TINT], &nodes, ptr1, len1, ptr2, len2, nodintconst(elemtype.Width)) } else { // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) - nptr1 := nod(OINDEX, s, nod(OLEN, l1, nil)) + nptr1 := ir.Nod(ir.OINDEX, s, ir.Nod(ir.OLEN, l1, nil)) nptr1.SetBounded(true) - nptr1 = nod(OADDR, nptr1, nil) + nptr1 = ir.Nod(ir.OADDR, nptr1, nil) - nptr2 := nod(OSPTR, l2, nil) + nptr2 := ir.Nod(ir.OSPTR, l2, nil) - nwid := cheapexpr(conv(nod(OLEN, l2, nil), types.Types[TUINTPTR]), &nodes) - nwid = nod(OMUL, nwid, nodintconst(elemtype.Width)) + nwid := cheapexpr(conv(ir.Nod(ir.OLEN, l2, nil), types.Types[types.TUINTPTR]), &nodes) + nwid = ir.Nod(ir.OMUL, nwid, nodintconst(elemtype.Width)) // instantiate func memmove(to *any, frm *any, length uintptr) fn := syslook("memmove") @@ -2827,7 +2828,7 @@ func appendslice(n *Node, init *Nodes) *Node { // isAppendOfMake reports whether n is of the form append(x , make([]T, y)...). // isAppendOfMake assumes n has already been typechecked. -func isAppendOfMake(n *Node) bool { +func isAppendOfMake(n *ir.Node) bool { if base.Flag.N != 0 || instrumenting { return false } @@ -2836,12 +2837,12 @@ func isAppendOfMake(n *Node) bool { base.Fatalf("missing typecheck: %+v", n) } - if n.Op != OAPPEND || !n.IsDDD() || n.List.Len() != 2 { + if n.Op != ir.OAPPEND || !n.IsDDD() || n.List.Len() != 2 { return false } second := n.List.Second() - if second.Op != OMAKESLICE || second.Right != nil { + if second.Op != ir.OMAKESLICE || second.Right != nil { return false } @@ -2852,7 +2853,7 @@ func isAppendOfMake(n *Node) bool { // The care of overflow of the len argument to make will be handled by an explicit check of int(len) < 0 during runtime. y := second.Left - if !Isconst(y, constant.Int) && y.Type.Size() > types.Types[TUINT].Size() { + if !ir.IsConst(y, constant.Int) && y.Type.Size() > types.Types[types.TUINT].Size() { return false } @@ -2886,11 +2887,11 @@ func isAppendOfMake(n *Node) bool { // } // } // s -func extendslice(n *Node, init *Nodes) *Node { +func extendslice(n *ir.Node, init *ir.Nodes) *ir.Node { // isAppendOfMake made sure all possible positive values of l2 fit into an uint. // The case of l2 overflow when converting from e.g. uint to int is handled by an explicit // check of l2 < 0 at runtime which is generated below. - l2 := conv(n.List.Second().Left, types.Types[TINT]) + l2 := conv(n.List.Second().Left, types.Types[types.TINT]) l2 = typecheck(l2, ctxExpr) n.List.SetSecond(l2) // walkAppendArgs expects l2 in n.List.Second(). @@ -2899,10 +2900,10 @@ func extendslice(n *Node, init *Nodes) *Node { l1 := n.List.First() l2 = n.List.Second() // re-read l2, as it may have been updated by walkAppendArgs - var nodes []*Node + var nodes []*ir.Node // if l2 >= 0 (likely happens), do nothing - nifneg := nod(OIF, nod(OGE, l2, nodintconst(0)), nil) + nifneg := ir.Nod(ir.OIF, ir.Nod(ir.OGE, l2, nodintconst(0)), nil) nifneg.SetLikely(true) // else panicmakeslicelen() @@ -2911,67 +2912,67 @@ func extendslice(n *Node, init *Nodes) *Node { // s := l1 s := temp(l1.Type) - nodes = append(nodes, nod(OAS, s, l1)) + nodes = append(nodes, ir.Nod(ir.OAS, s, l1)) elemtype := s.Type.Elem() // n := len(s) + l2 - nn := temp(types.Types[TINT]) - nodes = append(nodes, nod(OAS, nn, nod(OADD, nod(OLEN, s, nil), l2))) + nn := temp(types.Types[types.TINT]) + nodes = append(nodes, ir.Nod(ir.OAS, nn, ir.Nod(ir.OADD, ir.Nod(ir.OLEN, s, nil), l2))) // if uint(n) > uint(cap(s)) - nuint := conv(nn, types.Types[TUINT]) - capuint := conv(nod(OCAP, s, nil), types.Types[TUINT]) - nif := nod(OIF, nod(OGT, nuint, capuint), nil) + nuint := conv(nn, types.Types[types.TUINT]) + capuint := conv(ir.Nod(ir.OCAP, s, nil), types.Types[types.TUINT]) + nif := ir.Nod(ir.OIF, ir.Nod(ir.OGT, nuint, capuint), nil) // instantiate growslice(typ *type, old []any, newcap int) []any fn := syslook("growslice") fn = substArgTypes(fn, elemtype, elemtype) // s = growslice(T, s, n) - nif.Nbody.Set1(nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(elemtype), s, nn))) + nif.Nbody.Set1(ir.Nod(ir.OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(elemtype), s, nn))) nodes = append(nodes, nif) // s = s[:n] - nt := nod(OSLICE, s, nil) + nt := ir.Nod(ir.OSLICE, s, nil) nt.SetSliceBounds(nil, nn, nil) nt.SetBounded(true) - nodes = append(nodes, nod(OAS, s, nt)) + nodes = append(nodes, ir.Nod(ir.OAS, s, nt)) // lptr := &l1[0] l1ptr := temp(l1.Type.Elem().PtrTo()) - tmp := nod(OSPTR, l1, nil) - nodes = append(nodes, nod(OAS, l1ptr, tmp)) + tmp := ir.Nod(ir.OSPTR, l1, nil) + nodes = append(nodes, ir.Nod(ir.OAS, l1ptr, tmp)) // sptr := &s[0] sptr := temp(elemtype.PtrTo()) - tmp = nod(OSPTR, s, nil) - nodes = append(nodes, nod(OAS, sptr, tmp)) + tmp = ir.Nod(ir.OSPTR, s, nil) + nodes = append(nodes, ir.Nod(ir.OAS, sptr, tmp)) // hp := &s[len(l1)] - hp := nod(OINDEX, s, nod(OLEN, l1, nil)) + hp := ir.Nod(ir.OINDEX, s, ir.Nod(ir.OLEN, l1, nil)) hp.SetBounded(true) - hp = nod(OADDR, hp, nil) - hp = convnop(hp, types.Types[TUNSAFEPTR]) + hp = ir.Nod(ir.OADDR, hp, nil) + hp = convnop(hp, types.Types[types.TUNSAFEPTR]) // hn := l2 * sizeof(elem(s)) - hn := nod(OMUL, l2, nodintconst(elemtype.Width)) - hn = conv(hn, types.Types[TUINTPTR]) + hn := ir.Nod(ir.OMUL, l2, nodintconst(elemtype.Width)) + hn = conv(hn, types.Types[types.TUINTPTR]) clrname := "memclrNoHeapPointers" hasPointers := elemtype.HasPointers() if hasPointers { clrname = "memclrHasPointers" - Curfn.Func.setWBPos(n.Pos) + Curfn.Func.SetWBPos(n.Pos) } - var clr Nodes + var clr ir.Nodes clrfn := mkcall(clrname, nil, &clr, hp, hn) clr.Append(clrfn) if hasPointers { // if l1ptr == sptr - nifclr := nod(OIF, nod(OEQ, l1ptr, sptr), nil) + nifclr := ir.Nod(ir.OIF, ir.Nod(ir.OEQ, l1ptr, sptr), nil) nifclr.Nbody = clr nodes = append(nodes, nifclr) } else { @@ -3005,7 +3006,7 @@ func extendslice(n *Node, init *Nodes) *Node { // ... // } // s -func walkappend(n *Node, init *Nodes, dst *Node) *Node { +func walkappend(n *ir.Node, init *ir.Nodes, dst *ir.Node) *ir.Node { if !samesafeexpr(dst, n.List.First()) { n.List.SetFirst(safeexpr(n.List.First(), init)) n.List.SetFirst(walkexpr(n.List.First(), init)) @@ -3041,39 +3042,39 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node { return n } - var l []*Node + var l []*ir.Node ns := temp(nsrc.Type) - l = append(l, nod(OAS, ns, nsrc)) // s = src + l = append(l, ir.Nod(ir.OAS, ns, nsrc)) // s = src na := nodintconst(int64(argc)) // const argc - nx := nod(OIF, nil, nil) // if cap(s) - len(s) < argc - nx.Left = nod(OLT, nod(OSUB, nod(OCAP, ns, nil), nod(OLEN, ns, nil)), na) + nx := ir.Nod(ir.OIF, nil, nil) // if cap(s) - len(s) < argc + nx.Left = ir.Nod(ir.OLT, ir.Nod(ir.OSUB, ir.Nod(ir.OCAP, ns, nil), ir.Nod(ir.OLEN, ns, nil)), na) fn := syslook("growslice") // growslice(, old []T, mincap int) (ret []T) fn = substArgTypes(fn, ns.Type.Elem(), ns.Type.Elem()) - nx.Nbody.Set1(nod(OAS, ns, + nx.Nbody.Set1(ir.Nod(ir.OAS, ns, mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type.Elem()), ns, - nod(OADD, nod(OLEN, ns, nil), na)))) + ir.Nod(ir.OADD, ir.Nod(ir.OLEN, ns, nil), na)))) l = append(l, nx) - nn := temp(types.Types[TINT]) - l = append(l, nod(OAS, nn, nod(OLEN, ns, nil))) // n = len(s) + nn := temp(types.Types[types.TINT]) + l = append(l, ir.Nod(ir.OAS, nn, ir.Nod(ir.OLEN, ns, nil))) // n = len(s) - nx = nod(OSLICE, ns, nil) // ...s[:n+argc] - nx.SetSliceBounds(nil, nod(OADD, nn, na), nil) + nx = ir.Nod(ir.OSLICE, ns, nil) // ...s[:n+argc] + nx.SetSliceBounds(nil, ir.Nod(ir.OADD, nn, na), nil) nx.SetBounded(true) - l = append(l, nod(OAS, ns, nx)) // s = s[:n+argc] + l = append(l, ir.Nod(ir.OAS, ns, nx)) // s = s[:n+argc] ls = n.List.Slice()[1:] for i, n := range ls { - nx = nod(OINDEX, ns, nn) // s[n] ... + nx = ir.Nod(ir.OINDEX, ns, nn) // s[n] ... nx.SetBounded(true) - l = append(l, nod(OAS, nx, n)) // s[n] = arg + l = append(l, ir.Nod(ir.OAS, nx, n)) // s[n] = arg if i+1 < len(ls) { - l = append(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))) // n = n + 1 + l = append(l, ir.Nod(ir.OAS, nn, ir.Nod(ir.OADD, nn, nodintconst(1)))) // n = n + 1 } } @@ -3094,14 +3095,14 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node { // // Also works if b is a string. // -func copyany(n *Node, init *Nodes, runtimecall bool) *Node { +func copyany(n *ir.Node, init *ir.Nodes, runtimecall bool) *ir.Node { if n.Left.Type.Elem().HasPointers() { - Curfn.Func.setWBPos(n.Pos) + Curfn.Func.SetWBPos(n.Pos) fn := writebarrierfn("typedslicecopy", n.Left.Type.Elem(), n.Right.Type.Elem()) n.Left = cheapexpr(n.Left, init) - ptrL, lenL := n.Left.backingArrayPtrLen() + ptrL, lenL := backingArrayPtrLen(n.Left) n.Right = cheapexpr(n.Right, init) - ptrR, lenR := n.Right.backingArrayPtrLen() + ptrR, lenR := backingArrayPtrLen(n.Right) return mkcall1(fn, n.Type, init, typename(n.Left.Type.Elem()), ptrL, lenL, ptrR, lenR) } @@ -3111,9 +3112,9 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node { // n.Right can be a slice or string. n.Left = cheapexpr(n.Left, init) - ptrL, lenL := n.Left.backingArrayPtrLen() + ptrL, lenL := backingArrayPtrLen(n.Left) n.Right = cheapexpr(n.Right, init) - ptrR, lenR := n.Right.backingArrayPtrLen() + ptrR, lenR := backingArrayPtrLen(n.Right) fn := syslook("slicecopy") fn = substArgTypes(fn, ptrL.Type.Elem(), ptrR.Type.Elem()) @@ -3125,36 +3126,36 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node { n.Right = walkexpr(n.Right, init) nl := temp(n.Left.Type) nr := temp(n.Right.Type) - var l []*Node - l = append(l, nod(OAS, nl, n.Left)) - l = append(l, nod(OAS, nr, n.Right)) + var l []*ir.Node + l = append(l, ir.Nod(ir.OAS, nl, n.Left)) + l = append(l, ir.Nod(ir.OAS, nr, n.Right)) - nfrm := nod(OSPTR, nr, nil) - nto := nod(OSPTR, nl, nil) + nfrm := ir.Nod(ir.OSPTR, nr, nil) + nto := ir.Nod(ir.OSPTR, nl, nil) - nlen := temp(types.Types[TINT]) + nlen := temp(types.Types[types.TINT]) // n = len(to) - l = append(l, nod(OAS, nlen, nod(OLEN, nl, nil))) + l = append(l, ir.Nod(ir.OAS, nlen, ir.Nod(ir.OLEN, nl, nil))) // if n > len(frm) { n = len(frm) } - nif := nod(OIF, nil, nil) + nif := ir.Nod(ir.OIF, nil, nil) - nif.Left = nod(OGT, nlen, nod(OLEN, nr, nil)) - nif.Nbody.Append(nod(OAS, nlen, nod(OLEN, nr, nil))) + nif.Left = ir.Nod(ir.OGT, nlen, ir.Nod(ir.OLEN, nr, nil)) + nif.Nbody.Append(ir.Nod(ir.OAS, nlen, ir.Nod(ir.OLEN, nr, nil))) l = append(l, nif) // if to.ptr != frm.ptr { memmove( ... ) } - ne := nod(OIF, nod(ONE, nto, nfrm), nil) + ne := ir.Nod(ir.OIF, ir.Nod(ir.ONE, nto, nfrm), nil) ne.SetLikely(true) l = append(l, ne) fn := syslook("memmove") fn = substArgTypes(fn, nl.Type.Elem(), nl.Type.Elem()) - nwid := temp(types.Types[TUINTPTR]) - setwid := nod(OAS, nwid, conv(nlen, types.Types[TUINTPTR])) + nwid := temp(types.Types[types.TUINTPTR]) + setwid := ir.Nod(ir.OAS, nwid, conv(nlen, types.Types[types.TUINTPTR])) ne.Nbody.Append(setwid) - nwid = nod(OMUL, nwid, nodintconst(nl.Type.Elem().Width)) + nwid = ir.Nod(ir.OMUL, nwid, nodintconst(nl.Type.Elem().Width)) call := mkcall1(fn, nil, init, nto, nfrm, nwid) ne.Nbody.Append(call) @@ -3164,7 +3165,7 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node { return nlen } -func eqfor(t *types.Type) (n *Node, needsize bool) { +func eqfor(t *types.Type) (n *ir.Node, needsize bool) { // Should only arrive here with large memory or // a struct/array containing a non-memory field/element. // Small memory is handled inline, and single non-memory @@ -3176,13 +3177,13 @@ func eqfor(t *types.Type) (n *Node, needsize bool) { return n, true case ASPECIAL: sym := typesymprefix(".eq", t) - n := newname(sym) + n := NewName(sym) setNodeNameFunc(n) - n.Type = functype(nil, []*Node{ + n.Type = functype(nil, []*ir.Node{ anonfield(types.NewPtr(t)), anonfield(types.NewPtr(t)), - }, []*Node{ - anonfield(types.Types[TBOOL]), + }, []*ir.Node{ + anonfield(types.Types[types.TBOOL]), }) return n, false } @@ -3192,8 +3193,8 @@ func eqfor(t *types.Type) (n *Node, needsize bool) { // The result of walkcompare MUST be assigned back to n, e.g. // n.Left = walkcompare(n.Left, init) -func walkcompare(n *Node, init *Nodes) *Node { - if n.Left.Type.IsInterface() && n.Right.Type.IsInterface() && n.Left.Op != ONIL && n.Right.Op != ONIL { +func walkcompare(n *ir.Node, init *ir.Nodes) *ir.Node { + if n.Left.Type.IsInterface() && n.Right.Type.IsInterface() && n.Left.Op != ir.ONIL && n.Right.Op != ir.ONIL { return walkcompareInterface(n, init) } @@ -3218,31 +3219,31 @@ func walkcompare(n *Node, init *Nodes) *Node { // Handle both == and !=. eq := n.Op - andor := OOROR - if eq == OEQ { - andor = OANDAND + andor := ir.OOROR + if eq == ir.OEQ { + andor = ir.OANDAND } // Check for types equal. // For empty interface, this is: // l.tab == type(r) // For non-empty interface, this is: // l.tab != nil && l.tab._type == type(r) - var eqtype *Node - tab := nod(OITAB, l, nil) + var eqtype *ir.Node + tab := ir.Nod(ir.OITAB, l, nil) rtyp := typename(r.Type) if l.Type.IsEmptyInterface() { - tab.Type = types.NewPtr(types.Types[TUINT8]) + tab.Type = types.NewPtr(types.Types[types.TUINT8]) tab.SetTypecheck(1) - eqtype = nod(eq, tab, rtyp) + eqtype = ir.Nod(eq, tab, rtyp) } else { - nonnil := nod(brcom(eq), nodnil(), tab) - match := nod(eq, itabType(tab), rtyp) - eqtype = nod(andor, nonnil, match) + nonnil := ir.Nod(brcom(eq), nodnil(), tab) + match := ir.Nod(eq, itabType(tab), rtyp) + eqtype = ir.Nod(andor, nonnil, match) } // Check for data equal. - eqdata := nod(eq, ifaceData(n.Pos, l, r.Type), r) + eqdata := ir.Nod(eq, ifaceData(n.Pos, l, r.Type), r) // Put it all together. - expr := nod(andor, eqtype, eqdata) + expr := ir.Nod(andor, eqtype, eqdata) n = finishcompare(n, expr, init) return n } @@ -3272,10 +3273,10 @@ func walkcompare(n *Node, init *Nodes) *Node { // instead, and arrange for the constant // operand to be the first argument. l, r := n.Left, n.Right - if r.Op == OLITERAL { + if r.Op == ir.OLITERAL { l, r = r, l } - constcmp := l.Op == OLITERAL && r.Op != OLITERAL + constcmp := l.Op == ir.OLITERAL && r.Op != ir.OLITERAL var fn string var paramType *types.Type @@ -3285,44 +3286,44 @@ func walkcompare(n *Node, init *Nodes) *Node { if constcmp { fn = "libfuzzerTraceConstCmp1" } - paramType = types.Types[TUINT8] + paramType = types.Types[types.TUINT8] case 2: fn = "libfuzzerTraceCmp2" if constcmp { fn = "libfuzzerTraceConstCmp2" } - paramType = types.Types[TUINT16] + paramType = types.Types[types.TUINT16] case 4: fn = "libfuzzerTraceCmp4" if constcmp { fn = "libfuzzerTraceConstCmp4" } - paramType = types.Types[TUINT32] + paramType = types.Types[types.TUINT32] case 8: fn = "libfuzzerTraceCmp8" if constcmp { fn = "libfuzzerTraceConstCmp8" } - paramType = types.Types[TUINT64] + paramType = types.Types[types.TUINT64] default: base.Fatalf("unexpected integer size %d for %v", t.Size(), t) } init.Append(mkcall(fn, nil, init, tracecmpArg(l, paramType, init), tracecmpArg(r, paramType, init))) } return n - case TARRAY: + case types.TARRAY: // We can compare several elements at once with 2/4/8 byte integer compares inline = t.NumElem() <= 1 || (issimple[t.Elem().Etype] && (t.NumElem() <= 4 || t.Elem().Width*t.NumElem() <= maxcmpsize)) - case TSTRUCT: + case types.TSTRUCT: inline = t.NumComponents(types.IgnoreBlankFields) <= 4 } cmpl := n.Left - for cmpl != nil && cmpl.Op == OCONVNOP { + for cmpl != nil && cmpl.Op == ir.OCONVNOP { cmpl = cmpl.Left } cmpr := n.Right - for cmpr != nil && cmpr.Op == OCONVNOP { + for cmpr != nil && cmpr.Op == ir.OCONVNOP { cmpr = cmpr.Left } @@ -3334,32 +3335,32 @@ func walkcompare(n *Node, init *Nodes) *Node { } fn, needsize := eqfor(t) - call := nod(OCALL, fn, nil) - call.List.Append(nod(OADDR, cmpl, nil)) - call.List.Append(nod(OADDR, cmpr, nil)) + call := ir.Nod(ir.OCALL, fn, nil) + call.List.Append(ir.Nod(ir.OADDR, cmpl, nil)) + call.List.Append(ir.Nod(ir.OADDR, cmpr, nil)) if needsize { call.List.Append(nodintconst(t.Width)) } res := call - if n.Op != OEQ { - res = nod(ONOT, res, nil) + if n.Op != ir.OEQ { + res = ir.Nod(ir.ONOT, res, nil) } n = finishcompare(n, res, init) return n } // inline: build boolean expression comparing element by element - andor := OANDAND - if n.Op == ONE { - andor = OOROR + andor := ir.OANDAND + if n.Op == ir.ONE { + andor = ir.OOROR } - var expr *Node - compare := func(el, er *Node) { - a := nod(n.Op, el, er) + var expr *ir.Node + compare := func(el, er *ir.Node) { + a := ir.Nod(n.Op, el, er) if expr == nil { expr = a } else { - expr = nod(andor, expr, a) + expr = ir.Nod(andor, expr, a) } } cmpl = safeexpr(cmpl, init) @@ -3371,8 +3372,8 @@ func walkcompare(n *Node, init *Nodes) *Node { continue } compare( - nodSym(OXDOT, cmpl, sym), - nodSym(OXDOT, cmpr, sym), + nodSym(ir.OXDOT, cmpl, sym), + nodSym(ir.OXDOT, cmpr, sym), ) } } else { @@ -3385,45 +3386,45 @@ func walkcompare(n *Node, init *Nodes) *Node { var convType *types.Type switch { case remains >= 8 && combine64bit: - convType = types.Types[TINT64] + convType = types.Types[types.TINT64] step = 8 / t.Elem().Width case remains >= 4 && combine32bit: - convType = types.Types[TUINT32] + convType = types.Types[types.TUINT32] step = 4 / t.Elem().Width case remains >= 2 && combine16bit: - convType = types.Types[TUINT16] + convType = types.Types[types.TUINT16] step = 2 / t.Elem().Width default: step = 1 } if step == 1 { compare( - nod(OINDEX, cmpl, nodintconst(i)), - nod(OINDEX, cmpr, nodintconst(i)), + ir.Nod(ir.OINDEX, cmpl, nodintconst(i)), + ir.Nod(ir.OINDEX, cmpr, nodintconst(i)), ) i++ remains -= t.Elem().Width } else { elemType := t.Elem().ToUnsigned() - cmplw := nod(OINDEX, cmpl, nodintconst(i)) + cmplw := ir.Nod(ir.OINDEX, cmpl, nodintconst(i)) cmplw = conv(cmplw, elemType) // convert to unsigned cmplw = conv(cmplw, convType) // widen - cmprw := nod(OINDEX, cmpr, nodintconst(i)) + cmprw := ir.Nod(ir.OINDEX, cmpr, nodintconst(i)) cmprw = conv(cmprw, elemType) cmprw = conv(cmprw, convType) // For code like this: uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 ... // ssa will generate a single large load. for offset := int64(1); offset < step; offset++ { - lb := nod(OINDEX, cmpl, nodintconst(i+offset)) + lb := ir.Nod(ir.OINDEX, cmpl, nodintconst(i+offset)) lb = conv(lb, elemType) lb = conv(lb, convType) - lb = nod(OLSH, lb, nodintconst(8*t.Elem().Width*offset)) - cmplw = nod(OOR, cmplw, lb) - rb := nod(OINDEX, cmpr, nodintconst(i+offset)) + lb = ir.Nod(ir.OLSH, lb, nodintconst(8*t.Elem().Width*offset)) + cmplw = ir.Nod(ir.OOR, cmplw, lb) + rb := ir.Nod(ir.OINDEX, cmpr, nodintconst(i+offset)) rb = conv(rb, elemType) rb = conv(rb, convType) - rb = nod(OLSH, rb, nodintconst(8*t.Elem().Width*offset)) - cmprw = nod(OOR, cmprw, rb) + rb = ir.Nod(ir.OLSH, rb, nodintconst(8*t.Elem().Width*offset)) + cmprw = ir.Nod(ir.OOR, cmprw, rb) } compare(cmplw, cmprw) i += step @@ -3432,13 +3433,13 @@ func walkcompare(n *Node, init *Nodes) *Node { } } if expr == nil { - expr = nodbool(n.Op == OEQ) + expr = nodbool(n.Op == ir.OEQ) // We still need to use cmpl and cmpr, in case they contain // an expression which might panic. See issue 23837. t := temp(cmpl.Type) - a1 := nod(OAS, t, cmpl) + a1 := ir.Nod(ir.OAS, t, cmpl) a1 = typecheck(a1, ctxStmt) - a2 := nod(OAS, t, cmpr) + a2 := ir.Nod(ir.OAS, t, cmpr) a2 = typecheck(a2, ctxStmt) init.Append(a1, a2) } @@ -3446,39 +3447,39 @@ func walkcompare(n *Node, init *Nodes) *Node { return n } -func tracecmpArg(n *Node, t *types.Type, init *Nodes) *Node { +func tracecmpArg(n *ir.Node, t *types.Type, init *ir.Nodes) *ir.Node { // Ugly hack to avoid "constant -1 overflows uintptr" errors, etc. - if n.Op == OLITERAL && n.Type.IsSigned() && n.Int64Val() < 0 { + if n.Op == ir.OLITERAL && n.Type.IsSigned() && n.Int64Val() < 0 { n = copyexpr(n, n.Type, init) } return conv(n, t) } -func walkcompareInterface(n *Node, init *Nodes) *Node { +func walkcompareInterface(n *ir.Node, init *ir.Nodes) *ir.Node { n.Right = cheapexpr(n.Right, init) n.Left = cheapexpr(n.Left, init) eqtab, eqdata := eqinterface(n.Left, n.Right) - var cmp *Node - if n.Op == OEQ { - cmp = nod(OANDAND, eqtab, eqdata) + var cmp *ir.Node + if n.Op == ir.OEQ { + cmp = ir.Nod(ir.OANDAND, eqtab, eqdata) } else { - eqtab.Op = ONE - cmp = nod(OOROR, eqtab, nod(ONOT, eqdata, nil)) + eqtab.Op = ir.ONE + cmp = ir.Nod(ir.OOROR, eqtab, ir.Nod(ir.ONOT, eqdata, nil)) } return finishcompare(n, cmp, init) } -func walkcompareString(n *Node, init *Nodes) *Node { +func walkcompareString(n *ir.Node, init *ir.Nodes) *ir.Node { // Rewrite comparisons to short constant strings as length+byte-wise comparisons. - var cs, ncs *Node // const string, non-const string + var cs, ncs *ir.Node // const string, non-const string switch { - case Isconst(n.Left, constant.String) && Isconst(n.Right, constant.String): + case ir.IsConst(n.Left, constant.String) && ir.IsConst(n.Right, constant.String): // ignore; will be constant evaluated - case Isconst(n.Left, constant.String): + case ir.IsConst(n.Left, constant.String): cs = n.Left ncs = n.Right - case Isconst(n.Right, constant.String): + case ir.IsConst(n.Right, constant.String): cs = n.Right ncs = n.Left } @@ -3487,7 +3488,7 @@ func walkcompareString(n *Node, init *Nodes) *Node { // Our comparison below assumes that the non-constant string // is on the left hand side, so rewrite "" cmp x to x cmp "". // See issue 24817. - if Isconst(n.Left, constant.String) { + if ir.IsConst(n.Left, constant.String) { cmp = brrev(cmp) } @@ -3506,12 +3507,12 @@ func walkcompareString(n *Node, init *Nodes) *Node { combine64bit = thearch.LinkArch.RegSize >= 8 } - var and Op + var and ir.Op switch cmp { - case OEQ: - and = OANDAND - case ONE: - and = OOROR + case ir.OEQ: + and = ir.OANDAND + case ir.ONE: + and = ir.OOROR default: // Don't do byte-wise comparisons for <, <=, etc. // They're fairly complicated. @@ -3522,13 +3523,13 @@ func walkcompareString(n *Node, init *Nodes) *Node { if len(s) > 0 { ncs = safeexpr(ncs, init) } - r := nod(cmp, nod(OLEN, ncs, nil), nodintconst(int64(len(s)))) + r := ir.Nod(cmp, ir.Nod(ir.OLEN, ncs, nil), nodintconst(int64(len(s)))) remains := len(s) for i := 0; remains > 0; { if remains == 1 || !canCombineLoads { cb := nodintconst(int64(s[i])) - ncb := nod(OINDEX, ncs, nodintconst(int64(i))) - r = nod(and, r, nod(cmp, ncb, cb)) + ncb := ir.Nod(ir.OINDEX, ncs, nodintconst(int64(i))) + r = ir.Nod(and, r, ir.Nod(cmp, ncb, cb)) remains-- i++ continue @@ -3537,31 +3538,31 @@ func walkcompareString(n *Node, init *Nodes) *Node { var convType *types.Type switch { case remains >= 8 && combine64bit: - convType = types.Types[TINT64] + convType = types.Types[types.TINT64] step = 8 case remains >= 4: - convType = types.Types[TUINT32] + convType = types.Types[types.TUINT32] step = 4 case remains >= 2: - convType = types.Types[TUINT16] + convType = types.Types[types.TUINT16] step = 2 } - ncsubstr := nod(OINDEX, ncs, nodintconst(int64(i))) + ncsubstr := ir.Nod(ir.OINDEX, ncs, nodintconst(int64(i))) ncsubstr = conv(ncsubstr, convType) csubstr := int64(s[i]) // Calculate large constant from bytes as sequence of shifts and ors. // Like this: uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 ... // ssa will combine this into a single large load. for offset := 1; offset < step; offset++ { - b := nod(OINDEX, ncs, nodintconst(int64(i+offset))) + b := ir.Nod(ir.OINDEX, ncs, nodintconst(int64(i+offset))) b = conv(b, convType) - b = nod(OLSH, b, nodintconst(int64(8*offset))) - ncsubstr = nod(OOR, ncsubstr, b) + b = ir.Nod(ir.OLSH, b, nodintconst(int64(8*offset))) + ncsubstr = ir.Nod(ir.OOR, ncsubstr, b) csubstr |= int64(s[i+offset]) << uint8(8*offset) } csubstrPart := nodintconst(csubstr) // Compare "step" bytes as once - r = nod(and, r, nod(cmp, csubstrPart, ncsubstr)) + r = ir.Nod(and, r, ir.Nod(cmp, csubstrPart, ncsubstr)) remains -= step i += step } @@ -3569,26 +3570,26 @@ func walkcompareString(n *Node, init *Nodes) *Node { } } - var r *Node - if n.Op == OEQ || n.Op == ONE { + var r *ir.Node + if n.Op == ir.OEQ || n.Op == ir.ONE { // prepare for rewrite below n.Left = cheapexpr(n.Left, init) n.Right = cheapexpr(n.Right, init) eqlen, eqmem := eqstring(n.Left, n.Right) // quick check of len before full compare for == or !=. // memequal then tests equality up to length len. - if n.Op == OEQ { + if n.Op == ir.OEQ { // len(left) == len(right) && memequal(left, right, len) - r = nod(OANDAND, eqlen, eqmem) + r = ir.Nod(ir.OANDAND, eqlen, eqmem) } else { // len(left) != len(right) || !memequal(left, right, len) - eqlen.Op = ONE - r = nod(OOROR, eqlen, nod(ONOT, eqmem, nil)) + eqlen.Op = ir.ONE + r = ir.Nod(ir.OOROR, eqlen, ir.Nod(ir.ONOT, eqmem, nil)) } } else { // sys_cmpstring(s1, s2) :: 0 - r = mkcall("cmpstring", types.Types[TINT], init, conv(n.Left, types.Types[TSTRING]), conv(n.Right, types.Types[TSTRING])) - r = nod(n.Op, r, nodintconst(0)) + r = mkcall("cmpstring", types.Types[types.TINT], init, conv(n.Left, types.Types[types.TSTRING]), conv(n.Right, types.Types[types.TSTRING])) + r = ir.Nod(n.Op, r, nodintconst(0)) } return finishcompare(n, r, init) @@ -3596,7 +3597,7 @@ func walkcompareString(n *Node, init *Nodes) *Node { // The result of finishcompare MUST be assigned back to n, e.g. // n.Left = finishcompare(n.Left, x, r, init) -func finishcompare(n, r *Node, init *Nodes) *Node { +func finishcompare(n, r *ir.Node, init *ir.Nodes) *ir.Node { r = typecheck(r, ctxExpr) r = conv(r, n.Type) r = walkexpr(r, init) @@ -3604,7 +3605,7 @@ func finishcompare(n, r *Node, init *Nodes) *Node { } // return 1 if integer n must be in range [0, max), 0 otherwise -func bounded(n *Node, max int64) bool { +func bounded(n *ir.Node, max int64) bool { if n.Type == nil || !n.Type.IsInteger() { return false } @@ -3618,14 +3619,14 @@ func bounded(n *Node, max int64) bool { } switch n.Op { - case OAND, OANDNOT: + case ir.OAND, ir.OANDNOT: v := int64(-1) switch { case smallintconst(n.Left): v = n.Left.Int64Val() case smallintconst(n.Right): v = n.Right.Int64Val() - if n.Op == OANDNOT { + if n.Op == ir.OANDNOT { v = ^v if !sign { v &= 1< 0 && v >= 2 { @@ -3653,7 +3654,7 @@ func bounded(n *Node, max int64) bool { } } - case ORSH: + case ir.ORSH: if !sign && smallintconst(n.Right) { v := n.Right.Int64Val() if v > int64(bits) { @@ -3671,7 +3672,7 @@ func bounded(n *Node, max int64) bool { } // usemethod checks interface method calls for uses of reflect.Type.Method. -func usemethod(n *Node) { +func usemethod(n *ir.Node) { t := n.Left.Type // Looking for either of: @@ -3694,7 +3695,7 @@ func usemethod(n *Node) { } if res1 == nil { - if p0.Type.Etype != TINT { + if p0.Type.Etype != types.TINT { return } } else { @@ -3712,11 +3713,11 @@ func usemethod(n *Node) { if s := res0.Type.Sym; s != nil && s.Name == "Method" && isReflectPkg(s.Pkg) { Curfn.Func.SetReflectMethod(true) // The LSym is initialized at this point. We need to set the attribute on the LSym. - Curfn.Func.lsym.Set(obj.AttrReflectMethod, true) + Curfn.Func.LSym.Set(obj.AttrReflectMethod, true) } } -func usefield(n *Node) { +func usefield(n *ir.Node) { if objabi.Fieldtrack_enabled == 0 { return } @@ -3725,7 +3726,7 @@ func usefield(n *Node) { default: base.Fatalf("usefield %v", n.Op) - case ODOT, ODOTPTR: + case ir.ODOT, ir.ODOTPTR: break } if n.Sym == nil { @@ -3767,7 +3768,7 @@ func usefield(n *Node) { Curfn.Func.FieldTrack[sym] = struct{}{} } -func candiscardlist(l Nodes) bool { +func candiscardlist(l ir.Nodes) bool { for _, n := range l.Slice() { if !candiscard(n) { return false @@ -3776,7 +3777,7 @@ func candiscardlist(l Nodes) bool { return true } -func candiscard(n *Node) bool { +func candiscard(n *ir.Node) bool { if n == nil { return true } @@ -3786,80 +3787,80 @@ func candiscard(n *Node) bool { return false // Discardable as long as the subpieces are. - case ONAME, - ONONAME, - OTYPE, - OPACK, - OLITERAL, - ONIL, - OADD, - OSUB, - OOR, - OXOR, - OADDSTR, - OADDR, - OANDAND, - OBYTES2STR, - ORUNES2STR, - OSTR2BYTES, - OSTR2RUNES, - OCAP, - OCOMPLIT, - OMAPLIT, - OSTRUCTLIT, - OARRAYLIT, - OSLICELIT, - OPTRLIT, - OCONV, - OCONVIFACE, - OCONVNOP, - ODOT, - OEQ, - ONE, - OLT, - OLE, - OGT, - OGE, - OKEY, - OSTRUCTKEY, - OLEN, - OMUL, - OLSH, - ORSH, - OAND, - OANDNOT, - ONEW, - ONOT, - OBITNOT, - OPLUS, - ONEG, - OOROR, - OPAREN, - ORUNESTR, - OREAL, - OIMAG, - OCOMPLEX: + case ir.ONAME, + ir.ONONAME, + ir.OTYPE, + ir.OPACK, + ir.OLITERAL, + ir.ONIL, + ir.OADD, + ir.OSUB, + ir.OOR, + ir.OXOR, + ir.OADDSTR, + ir.OADDR, + ir.OANDAND, + ir.OBYTES2STR, + ir.ORUNES2STR, + ir.OSTR2BYTES, + ir.OSTR2RUNES, + ir.OCAP, + ir.OCOMPLIT, + ir.OMAPLIT, + ir.OSTRUCTLIT, + ir.OARRAYLIT, + ir.OSLICELIT, + ir.OPTRLIT, + ir.OCONV, + ir.OCONVIFACE, + ir.OCONVNOP, + ir.ODOT, + ir.OEQ, + ir.ONE, + ir.OLT, + ir.OLE, + ir.OGT, + ir.OGE, + ir.OKEY, + ir.OSTRUCTKEY, + ir.OLEN, + ir.OMUL, + ir.OLSH, + ir.ORSH, + ir.OAND, + ir.OANDNOT, + ir.ONEW, + ir.ONOT, + ir.OBITNOT, + ir.OPLUS, + ir.ONEG, + ir.OOROR, + ir.OPAREN, + ir.ORUNESTR, + ir.OREAL, + ir.OIMAG, + ir.OCOMPLEX: break // Discardable as long as we know it's not division by zero. - case ODIV, OMOD: - if n.Right.Op == OLITERAL && constant.Sign(n.Right.Val()) != 0 { + case ir.ODIV, ir.OMOD: + if n.Right.Op == ir.OLITERAL && constant.Sign(n.Right.Val()) != 0 { break } return false // Discardable as long as we know it won't fail because of a bad size. - case OMAKECHAN, OMAKEMAP: - if Isconst(n.Left, constant.Int) && constant.Sign(n.Left.Val()) == 0 { + case ir.OMAKECHAN, ir.OMAKEMAP: + if ir.IsConst(n.Left, constant.Int) && constant.Sign(n.Left.Val()) == 0 { break } return false // Difficult to tell what sizes are okay. - case OMAKESLICE: + case ir.OMAKESLICE: return false - case OMAKESLICECOPY: + case ir.OMAKESLICECOPY: return false } @@ -3890,29 +3891,29 @@ var wrapCall_prgen int // The result of wrapCall MUST be assigned back to n, e.g. // n.Left = wrapCall(n.Left, init) -func wrapCall(n *Node, init *Nodes) *Node { +func wrapCall(n *ir.Node, init *ir.Nodes) *ir.Node { if n.Ninit.Len() != 0 { walkstmtlist(n.Ninit.Slice()) init.AppendNodes(&n.Ninit) } - isBuiltinCall := n.Op != OCALLFUNC && n.Op != OCALLMETH && n.Op != OCALLINTER + isBuiltinCall := n.Op != ir.OCALLFUNC && n.Op != ir.OCALLMETH && n.Op != ir.OCALLINTER // Turn f(a, b, []T{c, d, e}...) back into f(a, b, c, d, e). if !isBuiltinCall && n.IsDDD() { last := n.List.Len() - 1 - if va := n.List.Index(last); va.Op == OSLICELIT { + if va := n.List.Index(last); va.Op == ir.OSLICELIT { n.List.Set(append(n.List.Slice()[:last], va.List.Slice()...)) n.SetIsDDD(false) } } // origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion. - origArgs := make([]*Node, n.List.Len()) - t := nod(OTFUNC, nil, nil) + origArgs := make([]*ir.Node, n.List.Len()) + t := ir.Nod(ir.OTFUNC, nil, nil) for i, arg := range n.List.Slice() { s := lookupN("a", i) - if !isBuiltinCall && arg.Op == OCONVNOP && arg.Type.IsUintptr() && arg.Left.Type.IsUnsafePtr() { + if !isBuiltinCall && arg.Op == ir.OCONVNOP && arg.Type.IsUintptr() && arg.Left.Type.IsUnsafePtr() { origArgs[i] = arg arg = arg.Left n.List.SetIndex(i, arg) @@ -3929,13 +3930,13 @@ func wrapCall(n *Node, init *Nodes) *Node { if origArg == nil { continue } - arg := nod(origArg.Op, args[i], nil) + arg := ir.Nod(origArg.Op, args[i], nil) arg.Type = origArg.Type args[i] = arg } - call := nod(n.Op, nil, nil) + call := ir.Nod(n.Op, nil, nil) if !isBuiltinCall { - call.Op = OCALL + call.Op = ir.OCALL call.Left = n.Left call.SetIsDDD(n.IsDDD()) } @@ -3948,7 +3949,7 @@ func wrapCall(n *Node, init *Nodes) *Node { typecheckslice(fn.Nbody.Slice(), ctxStmt) xtop = append(xtop, fn) - call = nod(OCALL, nil, nil) + call = ir.Nod(ir.OCALL, nil, nil) call.Left = fn.Func.Nname call.List.Set(n.List.Slice()) call = typecheck(call, ctxStmt) @@ -3961,8 +3962,8 @@ func wrapCall(n *Node, init *Nodes) *Node { // type syntax expression n.Type. // The result of substArgTypes MUST be assigned back to old, e.g. // n.Left = substArgTypes(n.Left, t1, t2) -func substArgTypes(old *Node, types_ ...*types.Type) *Node { - n := old.copy() +func substArgTypes(old *ir.Node, types_ ...*types.Type) *ir.Node { + n := ir.Copy(old) for _, t := range types_ { dowidth(t) @@ -3991,11 +3992,11 @@ func canMergeLoads() bool { // isRuneCount reports whether n is of the form len([]rune(string)). // These are optimized into a call to runtime.countrunes. -func isRuneCount(n *Node) bool { - return base.Flag.N == 0 && !instrumenting && n.Op == OLEN && n.Left.Op == OSTR2RUNES +func isRuneCount(n *ir.Node) bool { + return base.Flag.N == 0 && !instrumenting && n.Op == ir.OLEN && n.Left.Op == ir.OSTR2RUNES } -func walkCheckPtrAlignment(n *Node, init *Nodes, count *Node) *Node { +func walkCheckPtrAlignment(n *ir.Node, init *ir.Nodes, count *ir.Node) *ir.Node { if !n.Type.IsPtr() { base.Fatalf("expected pointer type: %v", n.Type) } @@ -4017,13 +4018,13 @@ func walkCheckPtrAlignment(n *Node, init *Nodes, count *Node) *Node { } n.Left = cheapexpr(n.Left, init) - init.Append(mkcall("checkptrAlignment", nil, init, convnop(n.Left, types.Types[TUNSAFEPTR]), typename(elem), conv(count, types.Types[TUINTPTR]))) + init.Append(mkcall("checkptrAlignment", nil, init, convnop(n.Left, types.Types[types.TUNSAFEPTR]), typename(elem), conv(count, types.Types[types.TUINTPTR]))) return n } var walkCheckPtrArithmeticMarker byte -func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node { +func walkCheckPtrArithmetic(n *ir.Node, init *ir.Nodes) *ir.Node { // Calling cheapexpr(n, init) below leads to a recursive call // to walkexpr, which leads us back here again. Use n.Opt to // prevent infinite loops. @@ -4040,11 +4041,11 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node { // TODO(mdempsky): Make stricter. We only need to exempt // reflect.Value.Pointer and reflect.Value.UnsafeAddr. switch n.Left.Op { - case OCALLFUNC, OCALLMETH, OCALLINTER: + case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: return n } - if n.Left.Op == ODOTPTR && isReflectHeaderDataField(n.Left) { + if n.Left.Op == ir.ODOTPTR && isReflectHeaderDataField(n.Left) { return n } @@ -4054,19 +4055,19 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node { // "It is valid both to add and to subtract offsets from a // pointer in this way. It is also valid to use &^ to round // pointers, usually for alignment." - var originals []*Node - var walk func(n *Node) - walk = func(n *Node) { + var originals []*ir.Node + var walk func(n *ir.Node) + walk = func(n *ir.Node) { switch n.Op { - case OADD: + case ir.OADD: walk(n.Left) walk(n.Right) - case OSUB, OANDNOT: + case ir.OSUB, ir.OANDNOT: walk(n.Left) - case OCONVNOP: + case ir.OCONVNOP: if n.Left.Type.IsUnsafePtr() { n.Left = cheapexpr(n.Left, init) - originals = append(originals, convnop(n.Left, types.Types[TUNSAFEPTR])) + originals = append(originals, convnop(n.Left, types.Types[types.TUNSAFEPTR])) } } } @@ -4074,10 +4075,10 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node { n = cheapexpr(n, init) - slice := mkdotargslice(types.NewSlice(types.Types[TUNSAFEPTR]), originals) + slice := mkdotargslice(types.NewSlice(types.Types[types.TUNSAFEPTR]), originals) slice.Esc = EscNone - init.Append(mkcall("checkptrArithmetic", nil, init, convnop(n, types.Types[TUNSAFEPTR]), slice)) + init.Append(mkcall("checkptrArithmetic", nil, init, convnop(n, types.Types[types.TUNSAFEPTR]), slice)) // TODO(khr): Mark backing store of slice as dead. This will allow us to reuse // the backing store for multiple calls to checkptrArithmetic. @@ -4087,6 +4088,6 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node { // checkPtr reports whether pointer checking should be enabled for // function fn at a given level. See debugHelpFooter for defined // levels. -func checkPtr(fn *Node, level int) bool { - return base.Debug.Checkptr >= level && fn.Func.Pragma&NoCheckPtr == 0 +func checkPtr(fn *ir.Node, level int) bool { + return base.Debug.Checkptr >= level && fn.Func.Pragma&ir.NoCheckPtr == 0 } diff --git a/src/cmd/compile/internal/gc/bitset.go b/src/cmd/compile/internal/ir/bitset.go similarity index 99% rename from src/cmd/compile/internal/gc/bitset.go rename to src/cmd/compile/internal/ir/bitset.go index ed5eea0a11b..29f136296fd 100644 --- a/src/cmd/compile/internal/gc/bitset.go +++ b/src/cmd/compile/internal/ir/bitset.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package gc +package ir type bitset8 uint8 diff --git a/src/cmd/compile/internal/gc/class_string.go b/src/cmd/compile/internal/ir/class_string.go similarity index 98% rename from src/cmd/compile/internal/gc/class_string.go rename to src/cmd/compile/internal/ir/class_string.go index a4084a75352..866bf1a6b5b 100644 --- a/src/cmd/compile/internal/gc/class_string.go +++ b/src/cmd/compile/internal/ir/class_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=Class"; DO NOT EDIT. -package gc +package ir import "strconv" diff --git a/src/cmd/compile/internal/gc/dump.go b/src/cmd/compile/internal/ir/dump.go similarity index 96% rename from src/cmd/compile/internal/gc/dump.go rename to src/cmd/compile/internal/ir/dump.go index 56dc4744657..9306366e8ad 100644 --- a/src/cmd/compile/internal/gc/dump.go +++ b/src/cmd/compile/internal/ir/dump.go @@ -6,22 +6,23 @@ // for debugging purposes. The code is customized for Node graphs // and may be used for an alternative view of the node structure. -package gc +package ir import ( - "cmd/compile/internal/base" - "cmd/compile/internal/types" - "cmd/internal/src" "fmt" "io" "os" "reflect" "regexp" + + "cmd/compile/internal/base" + "cmd/compile/internal/types" + "cmd/internal/src" ) // dump is like fdump but prints to stderr. -func dump(root interface{}, filter string, depth int) { - fdump(os.Stderr, root, filter, depth) +func DumpAny(root interface{}, filter string, depth int) { + FDumpAny(os.Stderr, root, filter, depth) } // fdump prints the structure of a rooted data structure @@ -41,7 +42,7 @@ func dump(root interface{}, filter string, depth int) { // rather than their type; struct fields with zero values or // non-matching field names are omitted, and "…" means recursion // depth has been reached or struct fields have been omitted. -func fdump(w io.Writer, root interface{}, filter string, depth int) { +func FDumpAny(w io.Writer, root interface{}, filter string, depth int) { if root == nil { fmt.Fprintln(w, "nil") return @@ -151,7 +152,7 @@ func (p *dumper) dump(x reflect.Value, depth int) { return case *types.Node: - x = reflect.ValueOf(asNode(v)) + x = reflect.ValueOf(AsNode(v)) } switch x.Kind() { diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/ir/fmt.go similarity index 87% rename from src/cmd/compile/internal/gc/fmt.go rename to src/cmd/compile/internal/ir/fmt.go index 9248eb22aa2..5dea0880fc1 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package gc +package ir import ( "bytes" - "cmd/compile/internal/base" - "cmd/compile/internal/types" - "cmd/internal/src" "fmt" "go/constant" "io" @@ -16,6 +13,10 @@ import ( "strings" "sync" "unicode/utf8" + + "cmd/compile/internal/base" + "cmd/compile/internal/types" + "cmd/internal/src" ) // A FmtFlag value is a set of flags (or 0). @@ -98,7 +99,7 @@ func fmtFlag(s fmt.State, verb rune) FmtFlag { // *types.Sym, *types.Type, and *Node types use the flags below to set the format mode const ( - FErr fmtMode = iota + FErr FmtMode = iota FDbg FTypeId FTypeIdName // same as FTypeId, but use package name instead of prefix @@ -131,7 +132,7 @@ const ( // %- v type identifiers with package name instead of prefix (typesym, dcommontype, typehash) // update returns the results of applying f to mode. -func (f FmtFlag) update(mode fmtMode) (FmtFlag, fmtMode) { +func (f FmtFlag) update(mode FmtMode) (FmtFlag, FmtMode) { switch { case f&FmtSign != 0: mode = FDbg @@ -147,7 +148,7 @@ func (f FmtFlag) update(mode fmtMode) (FmtFlag, fmtMode) { return f, mode } -var goopnames = []string{ +var OpNames = []string{ OADDR: "&", OADD: "+", OADDSTR: "+", @@ -217,7 +218,7 @@ func (o Op) GoString() string { return fmt.Sprintf("%#v", o) } -func (o Op) format(s fmt.State, verb rune, mode fmtMode) { +func (o Op) format(s fmt.State, verb rune, mode FmtMode) { switch verb { case 'v': o.oconv(s, fmtFlag(s, verb), mode) @@ -227,10 +228,10 @@ func (o Op) format(s fmt.State, verb rune, mode fmtMode) { } } -func (o Op) oconv(s fmt.State, flag FmtFlag, mode fmtMode) { +func (o Op) oconv(s fmt.State, flag FmtFlag, mode FmtMode) { if flag&FmtSharp != 0 || mode != FDbg { - if int(o) < len(goopnames) && goopnames[o] != "" { - fmt.Fprint(s, goopnames[o]) + if int(o) < len(OpNames) && OpNames[o] != "" { + fmt.Fprint(s, OpNames[o]) return } } @@ -239,66 +240,73 @@ func (o Op) oconv(s fmt.State, flag FmtFlag, mode fmtMode) { fmt.Fprint(s, o.String()) } -type fmtMode int +type FmtMode int type fmtNode struct { x *Node - m fmtMode + m FmtMode } func (f *fmtNode) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } type fmtOp struct { x Op - m fmtMode + m FmtMode } func (f *fmtOp) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } type fmtType struct { x *types.Type - m fmtMode + m FmtMode } func (f *fmtType) Format(s fmt.State, verb rune) { typeFormat(f.x, s, verb, f.m) } type fmtSym struct { x *types.Sym - m fmtMode + m FmtMode } func (f *fmtSym) Format(s fmt.State, verb rune) { symFormat(f.x, s, verb, f.m) } type fmtNodes struct { x Nodes - m fmtMode + m FmtMode } func (f *fmtNodes) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } -func (n *Node) Format(s fmt.State, verb rune) { n.format(s, verb, FErr) } -func (o Op) Format(s fmt.State, verb rune) { o.format(s, verb, FErr) } +func (n *Node) Format(s fmt.State, verb rune) { + FmtNode(n, s, verb) +} + +func FmtNode(n *Node, s fmt.State, verb rune) { + n.format(s, verb, FErr) +} + +func (o Op) Format(s fmt.State, verb rune) { o.format(s, verb, FErr) } // func (t *types.Type) Format(s fmt.State, verb rune) // in package types // func (y *types.Sym) Format(s fmt.State, verb rune) // in package types { y.format(s, verb, FErr) } func (n Nodes) Format(s fmt.State, verb rune) { n.format(s, verb, FErr) } -func (m fmtMode) Fprintf(s fmt.State, format string, args ...interface{}) { +func (m FmtMode) Fprintf(s fmt.State, format string, args ...interface{}) { m.prepareArgs(args) fmt.Fprintf(s, format, args...) } -func (m fmtMode) Sprintf(format string, args ...interface{}) string { +func (m FmtMode) Sprintf(format string, args ...interface{}) string { m.prepareArgs(args) return fmt.Sprintf(format, args...) } -func (m fmtMode) Sprint(args ...interface{}) string { +func (m FmtMode) Sprint(args ...interface{}) string { m.prepareArgs(args) return fmt.Sprint(args...) } -func (m fmtMode) prepareArgs(args []interface{}) { +func (m FmtMode) prepareArgs(args []interface{}) { for i, arg := range args { switch arg := arg.(type) { case Op: @@ -319,13 +327,13 @@ func (m fmtMode) prepareArgs(args []interface{}) { } } -func (n *Node) format(s fmt.State, verb rune, mode fmtMode) { +func (n *Node) format(s fmt.State, verb rune, mode FmtMode) { switch verb { case 'v', 'S', 'L': - n.nconv(s, fmtFlag(s, verb), mode) + nconvFmt(n, s, fmtFlag(s, verb), mode) case 'j': - n.jconv(s, fmtFlag(s, verb)) + jconvFmt(n, s, fmtFlag(s, verb)) default: fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n) @@ -336,7 +344,7 @@ func (n *Node) format(s fmt.State, verb rune, mode fmtMode) { var EscFmt func(n *Node, short bool) string // *Node details -func (n *Node) jconv(s fmt.State, flag FmtFlag) { +func jconvFmt(n *Node, s fmt.State, flag FmtFlag) { short := flag&FmtShort != 0 // Useful to see which nodes in an AST printout are actually identical @@ -363,7 +371,7 @@ func (n *Node) jconv(s fmt.State, flag FmtFlag) { fmt.Fprintf(s, " l(%s%d)", pfx, n.Pos.Line()) } - if !short && n.Xoffset != BADWIDTH { + if !short && n.Xoffset != types.BADWIDTH { fmt.Fprintf(s, " x(%d)", n.Xoffset) } @@ -430,7 +438,7 @@ func (n *Node) jconv(s fmt.State, flag FmtFlag) { } } -func vconv(v constant.Value, flag FmtFlag) string { +func FmtConst(v constant.Value, flag FmtFlag) string { if flag&FmtSharp == 0 && v.Kind() == constant.Complex { real, imag := constant.Real(v), constant.Imag(v) @@ -473,17 +481,17 @@ s%^ ........*\]%&~%g s%~ %%g */ -func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode fmtMode) { +func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { if flag&FmtShort == 0 { switch mode { case FErr: // This is for the user - if s.Pkg == builtinpkg || s.Pkg == localpkg { + if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg { b.WriteString(s.Name) return } // If the name was used by multiple packages, display the full path, - if s.Pkg.Name != "" && numImport[s.Pkg.Name] > 1 { + if s.Pkg.Name != "" && NumImport[s.Pkg.Name] > 1 { fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name) return } @@ -534,28 +542,28 @@ func symfmt(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode fmtMode) { b.WriteString(s.Name) } -var basicnames = []string{ - TINT: "int", - TUINT: "uint", - TINT8: "int8", - TUINT8: "uint8", - TINT16: "int16", - TUINT16: "uint16", - TINT32: "int32", - TUINT32: "uint32", - TINT64: "int64", - TUINT64: "uint64", - TUINTPTR: "uintptr", - TFLOAT32: "float32", - TFLOAT64: "float64", - TCOMPLEX64: "complex64", - TCOMPLEX128: "complex128", - TBOOL: "bool", - TANY: "any", - TSTRING: "string", - TNIL: "nil", - TIDEAL: "untyped number", - TBLANK: "blank", +var BasicTypeNames = []string{ + types.TINT: "int", + types.TUINT: "uint", + types.TINT8: "int8", + types.TUINT8: "uint8", + types.TINT16: "int16", + types.TUINT16: "uint16", + types.TINT32: "int32", + types.TUINT32: "uint32", + types.TINT64: "int64", + types.TUINT64: "uint64", + types.TUINTPTR: "uintptr", + types.TFLOAT32: "float32", + types.TFLOAT64: "float64", + types.TCOMPLEX64: "complex64", + types.TCOMPLEX128: "complex128", + types.TBOOL: "bool", + types.TANY: "any", + types.TSTRING: "string", + types.TNIL: "nil", + types.TIDEAL: "untyped number", + types.TBLANK: "blank", } var fmtBufferPool = sync.Pool{ @@ -564,7 +572,7 @@ var fmtBufferPool = sync.Pool{ }, } -func tconv(t *types.Type, flag FmtFlag, mode fmtMode) string { +func tconv(t *types.Type, flag FmtFlag, mode FmtMode) string { buf := fmtBufferPool.Get().(*bytes.Buffer) buf.Reset() defer fmtBufferPool.Put(buf) @@ -577,7 +585,7 @@ func tconv(t *types.Type, flag FmtFlag, mode fmtMode) string { // flag and mode control exactly what is printed. // Any types x that are already in the visited map get printed as @%d where %d=visited[x]. // See #16897 before changing the implementation of tconv. -func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited map[*types.Type]int) { +func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode FmtMode, visited map[*types.Type]int) { if off, ok := visited[t]; ok { // We've seen this type before, so we're trying to print it recursively. // Print a reference to it instead. @@ -648,7 +656,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited return } - if t.Sym.Pkg == localpkg && t.Vargen != 0 { + if t.Sym.Pkg == LocalPkg && t.Vargen != 0 { b.WriteString(mode.Sprintf("%v·%d", t.Sym, t.Vargen)) return } @@ -658,7 +666,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited return } - if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" { + if int(t.Etype) < len(BasicTypeNames) && BasicTypeNames[t.Etype] != "" { var name string switch t { case types.UntypedBool: @@ -674,7 +682,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited case types.UntypedComplex: name = "untyped complex" default: - name = basicnames[t.Etype] + name = BasicTypeNames[t.Etype] } b.WriteString(name) return @@ -701,7 +709,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited defer delete(visited, t) switch t.Etype { - case TPTR: + case types.TPTR: b.WriteByte('*') switch mode { case FTypeId, FTypeIdName: @@ -712,17 +720,17 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited } tconv2(b, t.Elem(), 0, mode, visited) - case TARRAY: + case types.TARRAY: b.WriteByte('[') b.WriteString(strconv.FormatInt(t.NumElem(), 10)) b.WriteByte(']') tconv2(b, t.Elem(), 0, mode, visited) - case TSLICE: + case types.TSLICE: b.WriteString("[]") tconv2(b, t.Elem(), 0, mode, visited) - case TCHAN: + case types.TCHAN: switch t.ChanDir() { case types.Crecv: b.WriteString("<-chan ") @@ -741,13 +749,13 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited } } - case TMAP: + case types.TMAP: b.WriteString("map[") tconv2(b, t.Key(), 0, mode, visited) b.WriteByte(']') tconv2(b, t.Elem(), 0, mode, visited) - case TINTER: + case types.TINTER: if t.IsEmptyInterface() { b.WriteString("interface {}") break @@ -779,7 +787,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited } b.WriteByte('}') - case TFUNC: + case types.TFUNC: if flag&FmtShort != 0 { // no leading func } else { @@ -805,7 +813,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited tconv2(b, t.Results(), 0, mode, visited) } - case TSTRUCT: + case types.TSTRUCT: if m := t.StructType().Map; m != nil { mt := m.MapType() // Format the bucket struct for map[x]y as map.bucket[x]y. @@ -856,17 +864,17 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited b.WriteByte('}') } - case TFORW: + case types.TFORW: b.WriteString("undefined") if t.Sym != nil { b.WriteByte(' ') sconv2(b, t.Sym, 0, mode) } - case TUNSAFEPTR: + case types.TUNSAFEPTR: b.WriteString("unsafe.Pointer") - case Txxx: + case types.Txxx: b.WriteString("Txxx") default: // Don't know how to handle - fall back to detailed prints. @@ -875,7 +883,7 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited } // Statements which may be rendered with a simplestmt as init. -func stmtwithinit(op Op) bool { +func StmtWithInit(op Op) bool { switch op { case OIF, OFOR, OFORUNTIL, OSWITCH: return true @@ -884,20 +892,20 @@ func stmtwithinit(op Op) bool { return false } -func (n *Node) stmtfmt(s fmt.State, mode fmtMode) { +func stmtFmt(n *Node, s fmt.State, mode FmtMode) { // some statements allow for an init, but at most one, // but we may have an arbitrary number added, eg by typecheck // and inlining. If it doesn't fit the syntax, emit an enclosing // block starting with the init statements. // if we can just say "for" n->ninit; ... then do so - simpleinit := n.Ninit.Len() == 1 && n.Ninit.First().Ninit.Len() == 0 && stmtwithinit(n.Op) + simpleinit := n.Ninit.Len() == 1 && n.Ninit.First().Ninit.Len() == 0 && StmtWithInit(n.Op) // otherwise, print the inits as separate statements complexinit := n.Ninit.Len() != 0 && !simpleinit && (mode != FErr) // but if it was for if/for/switch, put in an extra surrounding block to limit the scope - extrablock := complexinit && stmtwithinit(n.Op) + extrablock := complexinit && StmtWithInit(n.Op) if extrablock { fmt.Fprint(s, "{") @@ -1064,7 +1072,7 @@ func (n *Node) stmtfmt(s fmt.State, mode fmtMode) { } } -var opprec = []int{ +var OpPrec = []int{ OALIGNOF: 8, OAPPEND: 8, OBYTES2STR: 8, @@ -1184,7 +1192,7 @@ var opprec = []int{ OEND: 0, } -func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { +func exprFmt(n *Node, s fmt.State, prec int, mode FmtMode) { for n != nil && n.Implicit() && (n.Op == ODEREF || n.Op == OADDR) { n = n.Left } @@ -1194,7 +1202,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { return } - nprec := opprec[n.Op] + nprec := OpPrec[n.Op] if n.Op == OTYPE && n.Sym != nil { nprec = 8 } @@ -1214,7 +1222,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { case OLITERAL: // this is a bit of a mess if mode == FErr { if n.Orig != nil && n.Orig != n { - n.Orig.exprfmt(s, prec, mode) + exprFmt(n.Orig, s, prec, mode) return } if n.Sym != nil { @@ -1252,7 +1260,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { fmt.Fprintf(s, "'\\U%08x'", uint64(x)) } } else { - fmt.Fprint(s, vconv(n.Val(), fmtFlag(s, 'v'))) + fmt.Fprint(s, FmtConst(n.Val(), fmtFlag(s, 'v'))) } if needUnparen { @@ -1369,7 +1377,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { mode.Fprintf(s, "%v:%v", n.Sym, n.Left) case OCALLPART: - n.Left.exprfmt(s, nprec, mode) + exprFmt(n.Left, s, nprec, mode) if n.Right == nil || n.Right.Sym == nil { fmt.Fprint(s, ".") return @@ -1377,7 +1385,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { mode.Fprintf(s, ".%0S", n.Right.Sym) case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: - n.Left.exprfmt(s, nprec, mode) + exprFmt(n.Left, s, nprec, mode) if n.Sym == nil { fmt.Fprint(s, ".") return @@ -1385,7 +1393,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { mode.Fprintf(s, ".%0S", n.Sym) case ODOTTYPE, ODOTTYPE2: - n.Left.exprfmt(s, nprec, mode) + exprFmt(n.Left, s, nprec, mode) if n.Right != nil { mode.Fprintf(s, ".(%v)", n.Right) return @@ -1393,24 +1401,24 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { mode.Fprintf(s, ".(%v)", n.Type) case OINDEX, OINDEXMAP: - n.Left.exprfmt(s, nprec, mode) + exprFmt(n.Left, s, nprec, mode) mode.Fprintf(s, "[%v]", n.Right) case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR: - n.Left.exprfmt(s, nprec, mode) + exprFmt(n.Left, s, nprec, mode) fmt.Fprint(s, "[") low, high, max := n.SliceBounds() if low != nil { - fmt.Fprint(s, low.modeString(mode)) + fmt.Fprint(s, modeString(low, mode)) } fmt.Fprint(s, ":") if high != nil { - fmt.Fprint(s, high.modeString(mode)) + fmt.Fprint(s, modeString(high, mode)) } if n.Op.IsSlice3() { fmt.Fprint(s, ":") if max != nil { - fmt.Fprint(s, max.modeString(mode)) + fmt.Fprint(s, modeString(max, mode)) } } fmt.Fprint(s, "]") @@ -1474,7 +1482,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { mode.Fprintf(s, "%#v(%.v)", n.Op, n.List) case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG: - n.Left.exprfmt(s, nprec, mode) + exprFmt(n.Left, s, nprec, mode) if n.IsDDD() { mode.Fprintf(s, "(%.v...)", n.List) return @@ -1505,7 +1513,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { if n.Left != nil && n.Left.Op == n.Op { fmt.Fprint(s, " ") } - n.Left.exprfmt(s, nprec+1, mode) + exprFmt(n.Left, s, nprec+1, mode) // Binary case OADD, @@ -1528,16 +1536,16 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { OSEND, OSUB, OXOR: - n.Left.exprfmt(s, nprec, mode) + exprFmt(n.Left, s, nprec, mode) mode.Fprintf(s, " %#v ", n.Op) - n.Right.exprfmt(s, nprec+1, mode) + exprFmt(n.Right, s, nprec+1, mode) case OADDSTR: for i, n1 := range n.List.Slice() { if i != 0 { fmt.Fprint(s, " + ") } - n1.exprfmt(s, nprec, mode) + exprFmt(n1, s, nprec, mode) } case ODDD: mode.Fprintf(s, "...") @@ -1546,7 +1554,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { } } -func (n *Node) nodefmt(s fmt.State, flag FmtFlag, mode fmtMode) { +func nodeFmt(n *Node, s fmt.State, flag FmtFlag, mode FmtMode) { t := n.Type // We almost always want the original. @@ -1556,7 +1564,7 @@ func (n *Node) nodefmt(s fmt.State, flag FmtFlag, mode fmtMode) { } if flag&FmtLong != 0 && t != nil { - if t.Etype == TNIL { + if t.Etype == types.TNIL { fmt.Fprint(s, "nil") } else if n.Op == ONAME && n.Name.AutoTemp() { mode.Fprintf(s, "%v value", t) @@ -1568,15 +1576,15 @@ func (n *Node) nodefmt(s fmt.State, flag FmtFlag, mode fmtMode) { // TODO inlining produces expressions with ninits. we can't print these yet. - if opprec[n.Op] < 0 { - n.stmtfmt(s, mode) + if OpPrec[n.Op] < 0 { + stmtFmt(n, s, mode) return } - n.exprfmt(s, 0, mode) + exprFmt(n, s, 0, mode) } -func (n *Node) nodedump(s fmt.State, flag FmtFlag, mode fmtMode) { +func nodeDumpFmt(n *Node, s fmt.State, flag FmtFlag, mode FmtMode) { recur := flag&FmtShort == 0 if recur { @@ -1647,7 +1655,7 @@ func (n *Node) nodedump(s fmt.State, flag FmtFlag, mode fmtMode) { if n.Op == ODCLFUNC && n.Func != nil && n.Func.Dcl != nil && len(n.Func.Dcl) != 0 { indent(s) // The dcls for a func or closure - mode.Fprintf(s, "%v-dcl%v", n.Op, asNodes(n.Func.Dcl)) + mode.Fprintf(s, "%v-dcl%v", n.Op, AsNodes(n.Func.Dcl)) } if n.List.Len() != 0 { indent(s) @@ -1667,7 +1675,7 @@ func (n *Node) nodedump(s fmt.State, flag FmtFlag, mode fmtMode) { } // "%S" suppresses qualifying with package -func symFormat(s *types.Sym, f fmt.State, verb rune, mode fmtMode) { +func symFormat(s *types.Sym, f fmt.State, verb rune, mode FmtMode) { switch verb { case 'v', 'S': fmt.Fprint(f, sconv(s, fmtFlag(f, verb), mode)) @@ -1677,10 +1685,10 @@ func symFormat(s *types.Sym, f fmt.State, verb rune, mode fmtMode) { } } -func smodeString(s *types.Sym, mode fmtMode) string { return sconv(s, 0, mode) } +func smodeString(s *types.Sym, mode FmtMode) string { return sconv(s, 0, mode) } // See #16897 before changing the implementation of sconv. -func sconv(s *types.Sym, flag FmtFlag, mode fmtMode) string { +func sconv(s *types.Sym, flag FmtFlag, mode FmtMode) string { if flag&FmtLong != 0 { panic("linksymfmt") } @@ -1701,7 +1709,7 @@ func sconv(s *types.Sym, flag FmtFlag, mode fmtMode) string { return types.InternString(buf.Bytes()) } -func sconv2(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode fmtMode) { +func sconv2(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode FmtMode) { if flag&FmtLong != 0 { panic("linksymfmt") } @@ -1718,7 +1726,7 @@ func sconv2(b *bytes.Buffer, s *types.Sym, flag FmtFlag, mode fmtMode) { symfmt(b, s, flag, mode) } -func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode fmtMode, visited map[*types.Type]int, funarg types.Funarg) { +func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode FmtMode, visited map[*types.Type]int, funarg types.Funarg) { if f == nil { b.WriteString("") return @@ -1734,12 +1742,12 @@ func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode fmtMode, visite // Take the name from the original. if mode == FErr { - s = origSym(s) + s = OrigSym(s) } if s != nil && f.Embedded == 0 { if funarg != types.FunargNone { - name = asNode(f.Nname).modeString(mode) + name = modeString(AsNode(f.Nname), mode) } else if flag&FmtLong != 0 { name = mode.Sprintf("%0S", s) if !types.IsExported(name) && flag&FmtUnsigned == 0 { @@ -1775,7 +1783,7 @@ func fldconv(b *bytes.Buffer, f *types.Field, flag FmtFlag, mode fmtMode, visite // "%L" print definition, not name // "%S" omit 'func' and receiver from function types, short type names -func typeFormat(t *types.Type, s fmt.State, verb rune, mode fmtMode) { +func typeFormat(t *types.Type, s fmt.State, verb rune, mode FmtMode) { switch verb { case 'v', 'S', 'L': fmt.Fprint(s, tconv(t, fmtFlag(s, verb), mode)) @@ -1784,12 +1792,12 @@ func typeFormat(t *types.Type, s fmt.State, verb rune, mode fmtMode) { } } -func (n *Node) String() string { return fmt.Sprint(n) } -func (n *Node) modeString(mode fmtMode) string { return mode.Sprint(n) } +func (n *Node) String() string { return fmt.Sprint(n) } +func modeString(n *Node, mode FmtMode) string { return mode.Sprint(n) } // "%L" suffix with "(type %T)" where possible // "%+S" in debug mode, don't recurse, no multiline output -func (n *Node) nconv(s fmt.State, flag FmtFlag, mode fmtMode) { +func nconvFmt(n *Node, s fmt.State, flag FmtFlag, mode FmtMode) { if n == nil { fmt.Fprint(s, "") return @@ -1799,11 +1807,11 @@ func (n *Node) nconv(s fmt.State, flag FmtFlag, mode fmtMode) { switch mode { case FErr: - n.nodefmt(s, flag, mode) + nodeFmt(n, s, flag, mode) case FDbg: dumpdepth++ - n.nodedump(s, flag, mode) + nodeDumpFmt(n, s, flag, mode) dumpdepth-- default: @@ -1811,7 +1819,7 @@ func (n *Node) nconv(s fmt.State, flag FmtFlag, mode fmtMode) { } } -func (l Nodes) format(s fmt.State, verb rune, mode fmtMode) { +func (l Nodes) format(s fmt.State, verb rune, mode FmtMode) { switch verb { case 'v': l.hconv(s, fmtFlag(s, verb), mode) @@ -1826,7 +1834,7 @@ func (n Nodes) String() string { } // Flags: all those of %N plus '.': separate with comma's instead of semicolons. -func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode fmtMode) { +func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode FmtMode) { if l.Len() == 0 && mode == FDbg { fmt.Fprint(s, "") return @@ -1841,18 +1849,18 @@ func (l Nodes) hconv(s fmt.State, flag FmtFlag, mode fmtMode) { } for i, n := range l.Slice() { - fmt.Fprint(s, n.modeString(mode)) + fmt.Fprint(s, modeString(n, mode)) if i+1 < l.Len() { fmt.Fprint(s, sep) } } } -func dumplist(s string, l Nodes) { +func DumpList(s string, l Nodes) { fmt.Printf("%s%+v\n", s, l) } -func fdumplist(w io.Writer, s string, l Nodes) { +func FDumpList(w io.Writer, s string, l Nodes) { fmt.Fprintf(w, "%s%+v\n", s, l) } @@ -1877,3 +1885,30 @@ func ellipsisIf(b bool) string { } return "" } + +// numImport tracks how often a package with a given name is imported. +// It is used to provide a better error message (by using the package +// path to disambiguate) if a package that appears multiple times with +// the same name appears in an error message. +var NumImport = make(map[string]int) + +func InstallTypeFormats() { + types.Sconv = func(s *types.Sym, flag, mode int) string { + return sconv(s, FmtFlag(flag), FmtMode(mode)) + } + types.Tconv = func(t *types.Type, flag, mode int) string { + return tconv(t, FmtFlag(flag), FmtMode(mode)) + } + types.FormatSym = func(sym *types.Sym, s fmt.State, verb rune, mode int) { + symFormat(sym, s, verb, FmtMode(mode)) + } + types.FormatType = func(t *types.Type, s fmt.State, verb rune, mode int) { + typeFormat(t, s, verb, FmtMode(mode)) + } +} + +// Line returns n's position as a string. If n has been inlined, +// it uses the outermost position where n has been inlined. +func Line(n *Node) string { + return base.FmtPos(n.Pos) +} diff --git a/src/cmd/compile/internal/ir/ir.go b/src/cmd/compile/internal/ir/ir.go new file mode 100644 index 00000000000..ad7f692b077 --- /dev/null +++ b/src/cmd/compile/internal/ir/ir.go @@ -0,0 +1,12 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ir + +import "cmd/compile/internal/types" + +var LocalPkg *types.Pkg // package being compiled + +// builtinpkg is a fake package that declares the universe block. +var BuiltinPkg *types.Pkg diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/ir/node.go similarity index 82% rename from src/cmd/compile/internal/gc/syntax.go rename to src/cmd/compile/internal/ir/node.go index 11671fc54a0..e6ed178f495 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/ir/node.go @@ -4,17 +4,20 @@ // “Abstract” syntax representation. -package gc +package ir import ( + "go/constant" + "sort" + "strings" + "unsafe" + "cmd/compile/internal/base" "cmd/compile/internal/ssa" "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/objabi" "cmd/internal/src" - "go/constant" - "sort" ) // A Node is a single node in the syntax tree. @@ -290,7 +293,7 @@ func (n *Node) SetVal(v constant.Value) { base.Fatalf("have Opt") } if n.Op == OLITERAL { - assertRepresents(n.Type, v) + AssertValidTypeForConst(n.Type, v) } n.SetHasVal(true) n.E = &v @@ -333,7 +336,7 @@ func (n *Node) SetIota(x int64) { // mayBeShared reports whether n may occur in multiple places in the AST. // Extra care must be taken when mutating such a node. -func (n *Node) mayBeShared() bool { +func MayBeShared(n *Node) bool { switch n.Op { case ONAME, OLITERAL, ONIL, OTYPE: return true @@ -342,7 +345,7 @@ func (n *Node) mayBeShared() bool { } // funcname returns the name (without the package) of the function n. -func (n *Node) funcname() string { +func FuncName(n *Node) string { if n == nil || n.Func == nil || n.Func.Nname == nil { return "" } @@ -353,7 +356,7 @@ func (n *Node) funcname() string { // 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 (n *Node) pkgFuncName() string { +func PkgFuncName(n *Node) string { var s *types.Sym if n == nil { return "" @@ -681,7 +684,7 @@ type Func struct { FieldTrack map[*types.Sym]struct{} DebugInfo *ssa.FuncDebug - lsym *obj.LSym + LSym *obj.LSym Inl *Inline @@ -693,13 +696,13 @@ type Func struct { Pragma PragmaFlag // go:xxx function annotations flags bitset16 - numDefers int // number of defer calls in the function - numReturns int // number of explicit returns in the function + NumDefers int // number of defer calls in the function + NumReturns int // number of explicit returns in the function // nwbrCalls records the LSyms of functions called by this // function for go:nowritebarrierrec analysis. Only filled in // if nowritebarrierrecCheck != nil. - nwbrCalls *[]nowritebarrierrecCallSym + NWBRCalls *[]SymAndPos } // An Inline holds fields used for function bodies that can be inlined. @@ -764,7 +767,7 @@ func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInlin func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) } func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) } -func (f *Func) setWBPos(pos src.XPos) { +func (f *Func) SetWBPos(pos src.XPos) { if base.Debug.WB != 0 { base.WarnfAt(pos, "write barrier") } @@ -996,7 +999,7 @@ const ( type Nodes struct{ slice *[]*Node } // asNodes returns a slice of *Node as a Nodes value. -func asNodes(s []*Node) Nodes { +func AsNodes(s []*Node) Nodes { return Nodes{&s} } @@ -1136,38 +1139,38 @@ func (n *Nodes) AppendNodes(n2 *Nodes) { // inspect invokes f on each node in an AST in depth-first order. // If f(n) returns false, inspect skips visiting n's children. -func inspect(n *Node, f func(*Node) bool) { +func Inspect(n *Node, f func(*Node) bool) { if n == nil || !f(n) { return } - inspectList(n.Ninit, f) - inspect(n.Left, f) - inspect(n.Right, f) - inspectList(n.List, f) - inspectList(n.Nbody, f) - inspectList(n.Rlist, f) + InspectList(n.Ninit, f) + Inspect(n.Left, f) + Inspect(n.Right, f) + InspectList(n.List, f) + InspectList(n.Nbody, f) + InspectList(n.Rlist, f) } -func inspectList(l Nodes, f func(*Node) bool) { +func InspectList(l Nodes, f func(*Node) bool) { for _, n := range l.Slice() { - inspect(n, f) + Inspect(n, f) } } // nodeQueue is a FIFO queue of *Node. The zero value of nodeQueue is // a ready-to-use empty queue. -type nodeQueue struct { +type NodeQueue struct { ring []*Node head, tail int } // empty reports whether q contains no Nodes. -func (q *nodeQueue) empty() bool { +func (q *NodeQueue) Empty() bool { return q.head == q.tail } // pushRight appends n to the right of the queue. -func (q *nodeQueue) pushRight(n *Node) { +func (q *NodeQueue) PushRight(n *Node) { if len(q.ring) == 0 { q.ring = make([]*Node, 16) } else if q.head+len(q.ring) == q.tail { @@ -1191,8 +1194,8 @@ func (q *nodeQueue) pushRight(n *Node) { // popLeft pops a node from the left of the queue. It panics if q is // empty. -func (q *nodeQueue) popLeft() *Node { - if q.empty() { +func (q *NodeQueue) PopLeft() *Node { + if q.Empty() { panic("dequeue empty") } n := q.ring[q.head%len(q.ring)] @@ -1226,3 +1229,342 @@ func (s NodeSet) Sorted(less func(*Node, *Node) bool) []*Node { sort.Slice(res, func(i, j int) bool { return less(res[i], res[j]) }) return res } + +func Nod(op Op, nleft, nright *Node) *Node { + return NodAt(base.Pos, op, nleft, nright) +} + +func NodAt(pos src.XPos, op Op, nleft, nright *Node) *Node { + var n *Node + switch op { + case ODCLFUNC: + var x struct { + n Node + f Func + } + n = &x.n + n.Func = &x.f + n.Func.Decl = n + case ONAME: + base.Fatalf("use newname instead") + case OLABEL, OPACK: + var x struct { + n Node + m Name + } + n = &x.n + n.Name = &x.m + default: + n = new(Node) + } + n.Op = op + n.Left = nleft + n.Right = nright + n.Pos = pos + n.Xoffset = types.BADWIDTH + n.Orig = n + return n +} + +// newnamel returns a new ONAME Node associated with symbol s at position pos. +// The caller is responsible for setting n.Name.Curfn. +func NewNameAt(pos src.XPos, s *types.Sym) *Node { + if s == nil { + base.Fatalf("newnamel nil") + } + + var x struct { + n Node + m Name + p Param + } + n := &x.n + n.Name = &x.m + n.Name.Param = &x.p + + n.Op = ONAME + n.Pos = pos + n.Orig = n + + n.Sym = s + return n +} + +// The Class of a variable/function describes the "storage class" +// of a variable or function. During parsing, storage classes are +// called declaration contexts. +type Class uint8 + +//go:generate stringer -type=Class +const ( + Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables + PEXTERN // global variables + PAUTO // local variables + PAUTOHEAP // local variables or parameters moved to heap + PPARAM // input arguments + PPARAMOUT // output results + PFUNC // global functions + + // Careful: Class is stored in three bits in Node.flags. + _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3) +) + +type PragmaFlag int16 + +const ( + // Func pragmas. + Nointerface PragmaFlag = 1 << iota + Noescape // func parameters don't escape + Norace // func must not have race detector annotations + Nosplit // func should not execute on separate stack + Noinline // func should not be inlined + NoCheckPtr // func should not be instrumented by checkptr + CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all + UintptrEscapes // pointers converted to uintptr escape + + // Runtime-only func pragmas. + // See ../../../../runtime/README.md for detailed descriptions. + Systemstack // func must run on system stack + Nowritebarrier // emit compiler error instead of write barrier + Nowritebarrierrec // error on write barrier in this or recursive callees + Yeswritebarrierrec // cancels Nowritebarrierrec in this function and callees + + // Runtime and cgo type pragmas + NotInHeap // values of this type must not be heap allocated + + // Go command pragmas + GoBuildPragma +) + +type SymAndPos struct { + Sym *obj.LSym // LSym of callee + Pos src.XPos // line of call +} + +func AsNode(n *types.Node) *Node { return (*Node)(unsafe.Pointer(n)) } + +func AsTypesNode(n *Node) *types.Node { return (*types.Node)(unsafe.Pointer(n)) } + +var BlankNode *Node + +// origSym returns the original symbol written by the user. +func OrigSym(s *types.Sym) *types.Sym { + if s == nil { + return nil + } + + if len(s.Name) > 1 && s.Name[0] == '~' { + switch s.Name[1] { + case 'r': // originally an unnamed result + return nil + case 'b': // originally the blank identifier _ + // TODO(mdempsky): Does s.Pkg matter here? + return BlankNode.Sym + } + return s + } + + if strings.HasPrefix(s.Name, ".anon") { + // originally an unnamed or _ name (see subr.go: structargs) + return nil + } + + return s +} + +// 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 *Node) SliceBounds() (low, high, max *Node) { + if n.List.Len() == 0 { + return nil, nil, nil + } + + switch n.Op { + case OSLICE, OSLICEARR, OSLICESTR: + s := n.List.Slice() + return s[0], s[1], nil + case OSLICE3, OSLICE3ARR: + s := n.List.Slice() + 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 *Node) 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.Slice() + if s == nil { + if low == nil && high == nil { + return + } + n.List.Set2(low, high) + return + } + s[0] = low + s[1] = high + return + case OSLICE3, OSLICE3ARR: + s := n.List.Slice() + if s == nil { + if low == nil && high == nil && max == nil { + return + } + n.List.Set3(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 { + switch o { + case OSLICE, OSLICEARR, OSLICESTR: + return false + case OSLICE3, OSLICE3ARR: + return true + } + base.Fatalf("IsSlice3 op %v", o) + return false +} + +func IsConst(n *Node, ct constant.Kind) bool { + return ConstType(n) == ct +} + +// Int64Val returns n as an int64. +// n must be an integer or rune constant. +func (n *Node) Int64Val() int64 { + if !IsConst(n, constant.Int) { + base.Fatalf("Int64Val(%v)", n) + } + x, ok := constant.Int64Val(n.Val()) + if !ok { + base.Fatalf("Int64Val(%v)", n) + } + return x +} + +// CanInt64 reports whether it is safe to call Int64Val() on n. +func (n *Node) CanInt64() bool { + if !IsConst(n, constant.Int) { + return false + } + + // if the value inside n cannot be represented as an int64, the + // return value of Int64 is undefined + _, ok := constant.Int64Val(n.Val()) + return ok +} + +// Uint64Val returns n as an uint64. +// n must be an integer or rune constant. +func (n *Node) Uint64Val() uint64 { + if !IsConst(n, constant.Int) { + base.Fatalf("Uint64Val(%v)", n) + } + x, ok := constant.Uint64Val(n.Val()) + if !ok { + base.Fatalf("Uint64Val(%v)", n) + } + return x +} + +// BoolVal returns n as a bool. +// n must be a boolean constant. +func (n *Node) BoolVal() bool { + if !IsConst(n, constant.Bool) { + base.Fatalf("BoolVal(%v)", n) + } + return constant.BoolVal(n.Val()) +} + +// StringVal returns the value of a literal string Node as a string. +// n must be a string constant. +func (n *Node) StringVal() string { + if !IsConst(n, constant.String) { + base.Fatalf("StringVal(%v)", n) + } + return constant.StringVal(n.Val()) +} + +// rawcopy returns a shallow copy of n. +// Note: copy or sepcopy (rather than rawcopy) is usually the +// correct choice (see comment with Node.copy, below). +func (n *Node) RawCopy() *Node { + copy := *n + return © +} + +// sepcopy returns a separate shallow copy of n, with the copy's +// Orig pointing to itself. +func SepCopy(n *Node) *Node { + copy := *n + copy.Orig = © + return © +} + +// copy returns shallow copy of n and adjusts the copy's Orig if +// necessary: In general, if n.Orig points to itself, the copy's +// Orig should point to itself as well. Otherwise, if n is modified, +// the copy's Orig node appears modified, too, and then doesn't +// represent the original node anymore. +// (This caused the wrong complit Op to be used when printing error +// messages; see issues #26855, #27765). +func Copy(n *Node) *Node { + copy := *n + if n.Orig == n { + copy.Orig = © + } + return © +} + +// isNil reports whether n represents the universal untyped zero value "nil". +func IsNil(n *Node) bool { + // Check n.Orig because constant propagation may produce typed nil constants, + // which don't exist in the Go spec. + return n.Orig.Op == ONIL +} + +func IsBlank(n *Node) bool { + if n == nil { + return false + } + return n.Sym.IsBlank() +} + +// IsMethod reports whether n is a method. +// n must be a function or a method. +func IsMethod(n *Node) bool { + return n.Type.Recv() != nil +} + +func (n *Node) Typ() *types.Type { + return n.Type +} + +func (n *Node) StorageClass() ssa.StorageClass { + switch n.Class() { + case PPARAM: + return ssa.ClassParam + case PPARAMOUT: + return ssa.ClassParamOut + case PAUTO: + return ssa.ClassAuto + default: + base.Fatalf("untranslatable storage class for %v: %s", n, n.Class()) + return 0 + } +} diff --git a/src/cmd/compile/internal/gc/op_string.go b/src/cmd/compile/internal/ir/op_string.go similarity index 99% rename from src/cmd/compile/internal/gc/op_string.go rename to src/cmd/compile/internal/ir/op_string.go index 16fd79e4778..d0d3778357e 100644 --- a/src/cmd/compile/internal/gc/op_string.go +++ b/src/cmd/compile/internal/ir/op_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=Op -trimprefix=O"; DO NOT EDIT. -package gc +package ir import "strconv" diff --git a/src/cmd/compile/internal/gc/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go similarity index 98% rename from src/cmd/compile/internal/gc/sizeof_test.go rename to src/cmd/compile/internal/ir/sizeof_test.go index 2f2eba4c675..c5169b9092a 100644 --- a/src/cmd/compile/internal/gc/sizeof_test.go +++ b/src/cmd/compile/internal/ir/sizeof_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package gc +package ir import ( "reflect" diff --git a/src/cmd/compile/internal/ir/val.go b/src/cmd/compile/internal/ir/val.go new file mode 100644 index 00000000000..00b5bfd1ad4 --- /dev/null +++ b/src/cmd/compile/internal/ir/val.go @@ -0,0 +1,120 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ir + +import ( + "go/constant" + "math" + + "cmd/compile/internal/base" + "cmd/compile/internal/types" +) + +func ConstType(n *Node) constant.Kind { + if n == nil || n.Op != OLITERAL { + return constant.Unknown + } + return n.Val().Kind() +} + +// ValueInterface returns the constant value stored in n as an interface{}. +// It returns int64s for ints and runes, float64s for floats, +// and complex128s for complex values. +func ConstValue(n *Node) interface{} { + switch v := n.Val(); v.Kind() { + default: + base.Fatalf("unexpected constant: %v", v) + panic("unreachable") + case constant.Bool: + return constant.BoolVal(v) + case constant.String: + return constant.StringVal(v) + case constant.Int: + return Int64Val(n.Type, v) + case constant.Float: + return Float64Val(v) + case constant.Complex: + return complex(Float64Val(constant.Real(v)), Float64Val(constant.Imag(v))) + } +} + +// int64Val returns v converted to int64. +// Note: if t is uint64, very large values will be converted to negative int64. +func Int64Val(t *types.Type, v constant.Value) int64 { + if t.IsUnsigned() { + if x, ok := constant.Uint64Val(v); ok { + return int64(x) + } + } else { + if x, ok := constant.Int64Val(v); ok { + return x + } + } + base.Fatalf("%v out of range for %v", v, t) + panic("unreachable") +} + +func Float64Val(v constant.Value) float64 { + if x, _ := constant.Float64Val(v); !math.IsInf(x, 0) { + return x + 0 // avoid -0 (should not be needed, but be conservative) + } + base.Fatalf("bad float64 value: %v", v) + panic("unreachable") +} + +func AssertValidTypeForConst(t *types.Type, v constant.Value) { + if !ValidTypeForConst(t, v) { + base.Fatalf("%v does not represent %v", t, v) + } +} + +func ValidTypeForConst(t *types.Type, v constant.Value) bool { + switch v.Kind() { + case constant.Unknown: + return OKForConst[t.Etype] + case constant.Bool: + return t.IsBoolean() + case constant.String: + return t.IsString() + case constant.Int: + return t.IsInteger() + case constant.Float: + return t.IsFloat() + case constant.Complex: + return t.IsComplex() + } + + base.Fatalf("unexpected constant kind: %v", v) + panic("unreachable") +} + +// nodlit returns a new untyped constant with value v. +func NewLiteral(v constant.Value) *Node { + n := Nod(OLITERAL, nil, nil) + if k := v.Kind(); k != constant.Unknown { + n.Type = idealType(k) + n.SetVal(v) + } + return n +} + +func idealType(ct constant.Kind) *types.Type { + switch ct { + case constant.String: + return types.UntypedString + case constant.Bool: + return types.UntypedBool + case constant.Int: + return types.UntypedInt + case constant.Float: + return types.UntypedFloat + case constant.Complex: + return types.UntypedComplex + } + base.Fatalf("unexpected Ctype: %v", ct) + return nil +} + +var OKForConst [types.NTYPE]bool diff --git a/src/cmd/compile/internal/mips/ssa.go b/src/cmd/compile/internal/mips/ssa.go index c37a2e07149..87e6f5b0c7a 100644 --- a/src/cmd/compile/internal/mips/ssa.go +++ b/src/cmd/compile/internal/mips/ssa.go @@ -9,6 +9,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/gc" + "cmd/compile/internal/ir" "cmd/compile/internal/logopt" "cmd/compile/internal/ssa" "cmd/compile/internal/types" @@ -288,7 +289,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case *gc.Node: + case *ir.Node: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go index a7c10d8869b..ea22c488aab 100644 --- a/src/cmd/compile/internal/mips64/ssa.go +++ b/src/cmd/compile/internal/mips64/ssa.go @@ -9,6 +9,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/gc" + "cmd/compile/internal/ir" "cmd/compile/internal/logopt" "cmd/compile/internal/ssa" "cmd/compile/internal/types" @@ -262,7 +263,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case *gc.Node: + case *ir.Node: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index e3f0ee1a932..848f27af843 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -7,6 +7,7 @@ package ppc64 import ( "cmd/compile/internal/base" "cmd/compile/internal/gc" + "cmd/compile/internal/ir" "cmd/compile/internal/logopt" "cmd/compile/internal/ssa" "cmd/compile/internal/types" @@ -751,7 +752,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p.To.Reg = v.Reg() } - case *obj.LSym, *gc.Node: + case *obj.LSym, *ir.Node: p := s.Prog(ppc64.AMOVD) p.From.Type = obj.TYPE_ADDR p.From.Reg = v.Args[0].Reg() diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index 5a71b33c00c..a3dc07fe030 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -7,6 +7,7 @@ package riscv64 import ( "cmd/compile/internal/base" "cmd/compile/internal/gc" + "cmd/compile/internal/ir" "cmd/compile/internal/ssa" "cmd/compile/internal/types" "cmd/internal/obj" @@ -323,7 +324,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case *obj.LSym: wantreg = "SB" gc.AddAux(&p.From, v) - case *gc.Node: + case *ir.Node: wantreg = "SP" gc.AddAux(&p.From, v) case nil: diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go index 373dc431e54..1a8b5691ef0 100644 --- a/src/cmd/compile/internal/wasm/ssa.go +++ b/src/cmd/compile/internal/wasm/ssa.go @@ -7,6 +7,7 @@ package wasm import ( "cmd/compile/internal/base" "cmd/compile/internal/gc" + "cmd/compile/internal/ir" "cmd/compile/internal/logopt" "cmd/compile/internal/ssa" "cmd/compile/internal/types" @@ -236,7 +237,7 @@ func ssaGenValueOnStack(s *gc.SSAGenState, v *ssa.Value, extend bool) { switch v.Aux.(type) { case *obj.LSym: gc.AddAux(&p.From, v) - case *gc.Node: + case *ir.Node: p.From.Reg = v.Args[0].Reg() gc.AddAux(&p.From, v) default: diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index f8e1f2f9513..839579349a2 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -42,6 +42,7 @@ var bootstrapDirs = []string{ "cmd/compile/internal/arm", "cmd/compile/internal/arm64", "cmd/compile/internal/gc", + "cmd/compile/internal/ir", "cmd/compile/internal/logopt", "cmd/compile/internal/mips", "cmd/compile/internal/mips64",