mirror of
https://github.com/golang/go
synced 2024-11-11 23:40:22 -07:00
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like structures (see #13493 and #14858). This is unlikely to change. As a result, when invoking a function that accepts a **Node parameter, we usually allocate a *Node on the heap. This happens a whole lot. This CL changes functions from taking a **Node to acting more like append: It both modifies the input and returns a replacement for it. Because of the cascading nature of escape analysis, in order to get the benefits, I had to modify almost all such functions. The remaining functions are in racewalk and the backend. I would be happy to update them as well in a separate CL. This CL was created by manually updating the function signatures and the directly impacted bits of code. The callsites were then automatically updated using a bespoke script: https://gist.github.com/josharian/046b1be7aceae244de39 For ease of reviewing and future understanding, this CL is also broken down into four CLs, mailed separately, which show the manual and the automated changes separately. They are CLs 20990, 20991, 20992, and 20993. Passes toolstash -cmp. name old time/op new time/op delta Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24) Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24) GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24) Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24) MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23) name old alloc/op new alloc/op delta Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23) Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25) GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25) Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25) name old allocs/op new allocs/op delta Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25) Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24) GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25) Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25) name old text-bytes new text-bytes delta HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal) CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal) name old data-bytes new data-bytes delta HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal) CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal) name old exe-bytes new exe-bytes delta HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal) CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal) Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475 Reviewed-on: https://go-review.googlesource.com/20959 Reviewed-by: Dave Cheney <dave@cheney.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
d1b8871f13
commit
34699bc7a8
@ -186,7 +186,7 @@ func genhash(sym *Sym, t *Type) {
|
||||
tfn.Rlist.Append(n)
|
||||
|
||||
funchdr(fn)
|
||||
typecheck(&fn.Func.Nname.Name.Param.Ntype, Etype)
|
||||
fn.Func.Nname.Name.Param.Ntype = typecheck(fn.Func.Nname.Name.Param.Ntype, Etype)
|
||||
|
||||
// genhash is only called for types that have equality but
|
||||
// cannot be handled by the standard algorithms,
|
||||
@ -281,7 +281,7 @@ func genhash(sym *Sym, t *Type) {
|
||||
funcbody(fn)
|
||||
Curfn = fn
|
||||
fn.Func.Dupok = true
|
||||
typecheck(&fn, Etop)
|
||||
fn = typecheck(fn, Etop)
|
||||
typecheckslice(fn.Nbody.Slice(), Etop)
|
||||
Curfn = nil
|
||||
popdcl()
|
||||
@ -331,7 +331,7 @@ func hashfor(t *Type) *Node {
|
||||
tfn.List.Append(Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
|
||||
tfn.List.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
||||
tfn.Rlist.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
||||
typecheck(&tfn, Etype)
|
||||
tfn = typecheck(tfn, Etype)
|
||||
n.Type = tfn.Type
|
||||
return n
|
||||
}
|
||||
@ -365,7 +365,7 @@ func geneq(sym *Sym, t *Type) {
|
||||
tfn.Rlist.Append(n)
|
||||
|
||||
funchdr(fn)
|
||||
typecheck(&fn.Func.Nname.Name.Param.Ntype, Etype)
|
||||
fn.Func.Nname.Name.Param.Ntype = typecheck(fn.Func.Nname.Name.Param.Ntype, Etype)
|
||||
|
||||
// geneq is only called for types that have equality but
|
||||
// cannot be handled by the standard algorithms,
|
||||
@ -474,7 +474,7 @@ func geneq(sym *Sym, t *Type) {
|
||||
funcbody(fn)
|
||||
Curfn = fn
|
||||
fn.Func.Dupok = true
|
||||
typecheck(&fn, Etop)
|
||||
fn = typecheck(fn, Etop)
|
||||
typecheckslice(fn.Nbody.Slice(), Etop)
|
||||
Curfn = nil
|
||||
popdcl()
|
||||
@ -516,8 +516,8 @@ func eqmem(p *Node, q *Node, field *Sym, size int64) *Node {
|
||||
nx.Etype = 1 // does not escape
|
||||
ny := Nod(OADDR, NodSym(OXDOT, q, field), nil)
|
||||
ny.Etype = 1 // does not escape
|
||||
typecheck(&nx, Erv)
|
||||
typecheck(&ny, Erv)
|
||||
nx = typecheck(nx, Erv)
|
||||
ny = typecheck(ny, Erv)
|
||||
|
||||
fn, needsize := eqmemfunc(size, nx.Type.Type)
|
||||
call := Nod(OCALL, fn, nil)
|
||||
@ -540,7 +540,7 @@ func eqmemfunc(size int64, t *Type) (fn *Node, needsize bool) {
|
||||
fn = syslook(buf)
|
||||
}
|
||||
|
||||
substArgTypes(&fn, t, t)
|
||||
fn = substArgTypes(fn, t, t)
|
||||
return fn, needsize
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ func Export(out *obj.Biobuf, trace bool) int {
|
||||
switch n := sym.Def; n.Op {
|
||||
case OLITERAL:
|
||||
// constant
|
||||
typecheck(&n, Erv)
|
||||
n = typecheck(n, Erv)
|
||||
if n == nil || n.Op != OLITERAL {
|
||||
Fatalf("exporter: dumpexportconst: oconst nil: %v", sym)
|
||||
}
|
||||
@ -201,7 +201,7 @@ func Export(out *obj.Biobuf, trace bool) int {
|
||||
|
||||
case ONAME:
|
||||
// variable or function
|
||||
typecheck(&n, Erv|Ecall)
|
||||
n = typecheck(n, Erv|Ecall)
|
||||
if n == nil || n.Type == nil {
|
||||
Fatalf("exporter: variable/function exported but not defined: %v", sym)
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ func cgen_wb(n, res *Node, wb bool) {
|
||||
case OMINUS:
|
||||
if Isfloat[nl.Type.Etype] {
|
||||
nr = Nodintconst(-1)
|
||||
convlit(&nr, n.Type)
|
||||
nr = convlit(nr, n.Type)
|
||||
a = Thearch.Optoas(OMUL, nl.Type)
|
||||
goto sbop
|
||||
}
|
||||
@ -803,7 +803,7 @@ func cgen_wbptr(n, res *Node) {
|
||||
|
||||
wbVar := syslook("writeBarrier")
|
||||
wbEnabled := NodSym(ODOT, wbVar, wbVar.Type.Field(0).Sym)
|
||||
wbEnabled = typecheck(&wbEnabled, Erv)
|
||||
wbEnabled = typecheck(wbEnabled, Erv)
|
||||
pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
|
||||
Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)
|
||||
pjmp := Gbranch(obj.AJMP, nil, 0)
|
||||
@ -1784,7 +1784,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
|
||||
Genlist(n.Ninit)
|
||||
|
||||
if n.Type == nil {
|
||||
convlit(&n, Types[TBOOL])
|
||||
n = convlit(n, Types[TBOOL])
|
||||
if n.Type == nil {
|
||||
return
|
||||
}
|
||||
@ -2866,7 +2866,7 @@ func cgen_append(n, res *Node) {
|
||||
Regfree(&rlen)
|
||||
|
||||
fn := syslook("growslice")
|
||||
substArgTypes(&fn, res.Type.Type, res.Type.Type)
|
||||
fn = substArgTypes(fn, res.Type.Type, res.Type.Type)
|
||||
Ginscall(fn, 0)
|
||||
|
||||
if Widthptr == 4 && Widthreg == 8 {
|
||||
|
@ -97,7 +97,7 @@ func typecheckclosure(func_ *Node, top int) {
|
||||
}
|
||||
|
||||
oldfn := Curfn
|
||||
typecheck(&func_.Func.Ntype, Etype)
|
||||
func_.Func.Ntype = typecheck(func_.Func.Ntype, Etype)
|
||||
func_.Type = func_.Func.Ntype.Type
|
||||
func_.Func.Top = top
|
||||
|
||||
@ -197,7 +197,7 @@ func makeclosure(func_ *Node) *Node {
|
||||
if len(xfunc.Nbody.Slice()) == 0 {
|
||||
Fatalf("empty body - won't generate any code")
|
||||
}
|
||||
typecheck(&xfunc, Etop)
|
||||
xfunc = typecheck(xfunc, Etop)
|
||||
|
||||
xfunc.Func.Closure = func_
|
||||
func_.Func.Closure = xfunc
|
||||
@ -262,7 +262,7 @@ func capturevars(xfunc *Node) {
|
||||
Warnl(v.Lineno, "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym, v.Name.Param.Closure.Addrtaken, v.Name.Param.Closure.Assigned, int32(v.Type.Width))
|
||||
}
|
||||
|
||||
typecheck(&outer, Erv)
|
||||
outer = typecheck(outer, Erv)
|
||||
func_.Func.Enter.Append(outer)
|
||||
}
|
||||
|
||||
@ -442,7 +442,7 @@ func walkclosure(func_ *Node, init *Nodes) *Node {
|
||||
|
||||
clos.Type = func_.Type
|
||||
|
||||
typecheck(&clos, Erv)
|
||||
clos = typecheck(clos, Erv)
|
||||
|
||||
// typecheck will insert a PTRLIT node under CONVNOP,
|
||||
// tag it with escape analysis result.
|
||||
@ -457,7 +457,7 @@ func walkclosure(func_ *Node, init *Nodes) *Node {
|
||||
delete(prealloc, func_)
|
||||
}
|
||||
|
||||
walkexpr(&clos, init)
|
||||
clos = walkexpr(clos, init)
|
||||
|
||||
return clos
|
||||
}
|
||||
@ -608,7 +608,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Sym) *Node {
|
||||
|
||||
xfunc.Nbody.Set(body)
|
||||
|
||||
typecheck(&xfunc, Etop)
|
||||
xfunc = typecheck(xfunc, Etop)
|
||||
sym.Def = xfunc
|
||||
xtop = append(xtop, xfunc)
|
||||
Curfn = savecurfn
|
||||
@ -647,7 +647,7 @@ func walkpartialcall(n *Node, init *Nodes) *Node {
|
||||
|
||||
clos.Type = n.Type
|
||||
|
||||
typecheck(&clos, Erv)
|
||||
clos = typecheck(clos, Erv)
|
||||
|
||||
// typecheck will insert a PTRLIT node under CONVNOP,
|
||||
// tag it with escape analysis result.
|
||||
@ -662,7 +662,7 @@ func walkpartialcall(n *Node, init *Nodes) *Node {
|
||||
delete(prealloc, n)
|
||||
}
|
||||
|
||||
walkexpr(&clos, init)
|
||||
clos = walkexpr(clos, init)
|
||||
|
||||
return clos
|
||||
}
|
||||
|
@ -91,33 +91,35 @@ func truncfltlit(oldv *Mpflt, t *Type) *Mpflt {
|
||||
// NegOne returns a Node of type t with value -1.
|
||||
func NegOne(t *Type) *Node {
|
||||
n := Nodintconst(-1)
|
||||
convlit(&n, t)
|
||||
n = convlit(n, t)
|
||||
return n
|
||||
}
|
||||
|
||||
// convert n, if literal, to type t.
|
||||
// implicit conversion.
|
||||
func convlit(np **Node, t *Type) {
|
||||
convlit1(np, t, false)
|
||||
// The result of convlit MUST be assigned back to n, e.g.
|
||||
// n.Left = convlit(n.Left, t)
|
||||
func convlit(n *Node, t *Type) *Node {
|
||||
return convlit1(n, t, false)
|
||||
}
|
||||
|
||||
// convert n, if literal, to type t.
|
||||
// return a new node if necessary
|
||||
//(if n is a named constant, can't edit n->type directly).
|
||||
func convlit1(np **Node, t *Type, explicit bool) {
|
||||
n := *np
|
||||
// (if n is a named constant, can't edit n->type directly).
|
||||
// The result of convlit1 MUST be assigned back to n, e.g.
|
||||
// n.Left = convlit1(n.Left, t, explicit)
|
||||
func convlit1(n *Node, t *Type, explicit bool) *Node {
|
||||
if n == nil || t == nil || n.Type == nil || isideal(t) || n.Type == t {
|
||||
return
|
||||
return n
|
||||
}
|
||||
if !explicit && !isideal(n.Type) {
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
if n.Op == OLITERAL {
|
||||
nn := Nod(OXXX, nil, nil)
|
||||
*nn = *n
|
||||
n = nn
|
||||
*np = n
|
||||
}
|
||||
|
||||
switch n.Op {
|
||||
@ -131,23 +133,22 @@ func convlit1(np **Node, t *Type, explicit bool) {
|
||||
}
|
||||
|
||||
if n.Type.Etype == TIDEAL {
|
||||
convlit(&n.Left, t)
|
||||
convlit(&n.Right, t)
|
||||
n.Left = convlit(n.Left, t)
|
||||
n.Right = convlit(n.Right, t)
|
||||
n.Type = t
|
||||
}
|
||||
|
||||
return
|
||||
return n
|
||||
|
||||
// target is invalid type for a constant? leave alone.
|
||||
case OLITERAL:
|
||||
if !okforconst[t.Etype] && n.Type.Etype != TNIL {
|
||||
defaultlit(&n, nil)
|
||||
*np = n
|
||||
return
|
||||
n = defaultlit(n, nil)
|
||||
return n
|
||||
}
|
||||
|
||||
case OLSH, ORSH:
|
||||
convlit1(&n.Left, t, explicit && isideal(n.Left.Type))
|
||||
n.Left = convlit1(n.Left, t, explicit && isideal(n.Left.Type))
|
||||
t = n.Left.Type
|
||||
if t != nil && t.Etype == TIDEAL && n.Val().Ctype() != CTINT {
|
||||
n.SetVal(toint(n.Val()))
|
||||
@ -158,7 +159,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
|
||||
}
|
||||
|
||||
n.Type = t
|
||||
return
|
||||
return n
|
||||
|
||||
case OCOMPLEX:
|
||||
if n.Type.Etype == TIDEAL {
|
||||
@ -173,22 +174,22 @@ func convlit1(np **Node, t *Type, explicit bool) {
|
||||
case TCOMPLEX128:
|
||||
n.Type = t
|
||||
|
||||
convlit(&n.Left, Types[TFLOAT64])
|
||||
convlit(&n.Right, Types[TFLOAT64])
|
||||
n.Left = convlit(n.Left, Types[TFLOAT64])
|
||||
n.Right = convlit(n.Right, Types[TFLOAT64])
|
||||
|
||||
case TCOMPLEX64:
|
||||
n.Type = t
|
||||
convlit(&n.Left, Types[TFLOAT32])
|
||||
convlit(&n.Right, Types[TFLOAT32])
|
||||
n.Left = convlit(n.Left, Types[TFLOAT32])
|
||||
n.Right = convlit(n.Right, Types[TFLOAT32])
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
// avoided repeated calculations, errors
|
||||
if Eqtype(n.Type, t) {
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
ct := consttype(n)
|
||||
@ -201,11 +202,11 @@ func convlit1(np **Node, t *Type, explicit bool) {
|
||||
if et == TINTER {
|
||||
if ct == CTNIL && n.Type == Types[TNIL] {
|
||||
n.Type = t
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
defaultlit(np, nil)
|
||||
return
|
||||
n = defaultlit(n, nil)
|
||||
return n
|
||||
}
|
||||
|
||||
switch ct {
|
||||
@ -220,7 +221,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
|
||||
|
||||
// let normal conversion code handle it
|
||||
case TSTRING:
|
||||
return
|
||||
return n
|
||||
|
||||
case TARRAY:
|
||||
if !Isslice(t) {
|
||||
@ -301,7 +302,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
|
||||
}
|
||||
|
||||
n.Type = t
|
||||
return
|
||||
return n
|
||||
|
||||
bad:
|
||||
if n.Diag == 0 {
|
||||
@ -312,9 +313,9 @@ bad:
|
||||
}
|
||||
|
||||
if isideal(n.Type) {
|
||||
defaultlit(&n, nil)
|
||||
*np = n
|
||||
n = defaultlit(n, nil)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func copyval(v Val) Val {
|
||||
@ -667,7 +668,7 @@ func evconst(n *Node) {
|
||||
OCONV_ | CTFLT_,
|
||||
OCONV_ | CTSTR_,
|
||||
OCONV_ | CTBOOL_:
|
||||
convlit1(&nl, n.Type, true)
|
||||
nl = convlit1(nl, n.Type, true)
|
||||
|
||||
v = nl.Val()
|
||||
|
||||
@ -748,12 +749,12 @@ func evconst(n *Node) {
|
||||
// ideal const mixes with anything but otherwise must match.
|
||||
default:
|
||||
if nl.Type.Etype != TIDEAL {
|
||||
defaultlit(&nr, nl.Type)
|
||||
nr = defaultlit(nr, nl.Type)
|
||||
n.Right = nr
|
||||
}
|
||||
|
||||
if nr.Type.Etype != TIDEAL {
|
||||
defaultlit(&nl, nr.Type)
|
||||
nl = defaultlit(nl, nr.Type)
|
||||
n.Left = nl
|
||||
}
|
||||
|
||||
@ -764,7 +765,7 @@ func evconst(n *Node) {
|
||||
// right must be unsigned.
|
||||
// left can be ideal.
|
||||
case OLSH, ORSH:
|
||||
defaultlit(&nr, Types[TUINT])
|
||||
nr = defaultlit(nr, Types[TUINT])
|
||||
|
||||
n.Right = nr
|
||||
if nr.Type != nil && (Issigned[nr.Type.Etype] || !Isint[nr.Type.Etype]) {
|
||||
@ -1244,17 +1245,17 @@ func idealkind(n *Node) Ctype {
|
||||
}
|
||||
}
|
||||
|
||||
func defaultlit(np **Node, t *Type) {
|
||||
n := *np
|
||||
// The result of defaultlit MUST be assigned back to n, e.g.
|
||||
// n.Left = defaultlit(n.Left, t)
|
||||
func defaultlit(n *Node, t *Type) *Node {
|
||||
if n == nil || !isideal(n.Type) {
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
if n.Op == OLITERAL {
|
||||
nn := Nod(OXXX, nil, nil)
|
||||
*nn = *n
|
||||
n = nn
|
||||
*np = n
|
||||
}
|
||||
|
||||
lno := setlineno(n)
|
||||
@ -1263,8 +1264,8 @@ func defaultlit(np **Node, t *Type) {
|
||||
switch ctype {
|
||||
default:
|
||||
if t != nil {
|
||||
convlit(np, t)
|
||||
return
|
||||
n = convlit(n, t)
|
||||
return n
|
||||
}
|
||||
|
||||
if n.Val().Ctype() == CTNIL {
|
||||
@ -1280,7 +1281,7 @@ func defaultlit(np **Node, t *Type) {
|
||||
|
||||
if n.Val().Ctype() == CTSTR {
|
||||
t1 := Types[TSTRING]
|
||||
convlit(np, t1)
|
||||
n = convlit(n, t1)
|
||||
break
|
||||
}
|
||||
|
||||
@ -1294,7 +1295,7 @@ func defaultlit(np **Node, t *Type) {
|
||||
if t != nil && t.Etype == TBOOL {
|
||||
t1 = t
|
||||
}
|
||||
convlit(np, t1)
|
||||
n = convlit(n, t1)
|
||||
|
||||
case CTINT:
|
||||
t1 = Types[TINT]
|
||||
@ -1314,7 +1315,7 @@ func defaultlit(np **Node, t *Type) {
|
||||
}
|
||||
|
||||
lineno = lno
|
||||
return
|
||||
return n
|
||||
|
||||
num:
|
||||
// Note: n.Val().Ctype() can be CTxxx (not a constant) here
|
||||
@ -1339,62 +1340,64 @@ num:
|
||||
if n.Val().Ctype() != CTxxx {
|
||||
overflow(n.Val(), t1)
|
||||
}
|
||||
convlit(np, t1)
|
||||
n = convlit(n, t1)
|
||||
lineno = lno
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
// 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.
|
||||
func defaultlit2(lp **Node, rp **Node, force bool) {
|
||||
l := *lp
|
||||
r := *rp
|
||||
// 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) {
|
||||
if l.Type == nil || r.Type == nil {
|
||||
return
|
||||
return l, r
|
||||
}
|
||||
if !isideal(l.Type) {
|
||||
convlit(rp, l.Type)
|
||||
return
|
||||
r = convlit(r, l.Type)
|
||||
return l, r
|
||||
}
|
||||
|
||||
if !isideal(r.Type) {
|
||||
convlit(lp, r.Type)
|
||||
return
|
||||
l = convlit(l, r.Type)
|
||||
return l, r
|
||||
}
|
||||
|
||||
if !force {
|
||||
return
|
||||
return l, r
|
||||
}
|
||||
|
||||
if l.Type.Etype == TBOOL {
|
||||
convlit(lp, Types[TBOOL])
|
||||
convlit(rp, Types[TBOOL])
|
||||
l = convlit(l, Types[TBOOL])
|
||||
r = convlit(r, Types[TBOOL])
|
||||
}
|
||||
|
||||
lkind := idealkind(l)
|
||||
rkind := idealkind(r)
|
||||
if lkind == CTCPLX || rkind == CTCPLX {
|
||||
convlit(lp, Types[TCOMPLEX128])
|
||||
convlit(rp, Types[TCOMPLEX128])
|
||||
return
|
||||
l = convlit(l, Types[TCOMPLEX128])
|
||||
r = convlit(r, Types[TCOMPLEX128])
|
||||
return l, r
|
||||
}
|
||||
|
||||
if lkind == CTFLT || rkind == CTFLT {
|
||||
convlit(lp, Types[TFLOAT64])
|
||||
convlit(rp, Types[TFLOAT64])
|
||||
return
|
||||
l = convlit(l, Types[TFLOAT64])
|
||||
r = convlit(r, Types[TFLOAT64])
|
||||
return l, r
|
||||
}
|
||||
|
||||
if lkind == CTRUNE || rkind == CTRUNE {
|
||||
convlit(lp, runetype)
|
||||
convlit(rp, runetype)
|
||||
return
|
||||
l = convlit(l, runetype)
|
||||
r = convlit(r, runetype)
|
||||
return l, r
|
||||
}
|
||||
|
||||
convlit(lp, Types[TINT])
|
||||
convlit(rp, Types[TINT])
|
||||
l = convlit(l, Types[TINT])
|
||||
r = convlit(r, Types[TINT])
|
||||
|
||||
return l, r
|
||||
}
|
||||
|
||||
// strlit returns the value of a literal string Node as a string.
|
||||
|
@ -750,7 +750,7 @@ func structfield(n *Node) *Field {
|
||||
f.Isddd = n.Isddd
|
||||
|
||||
if n.Right != nil {
|
||||
typecheck(&n.Right, Etype)
|
||||
n.Right = typecheck(n.Right, Etype)
|
||||
n.Type = n.Right.Type
|
||||
if n.Left != nil {
|
||||
n.Left.Type = n.Type
|
||||
@ -904,7 +904,7 @@ func interfacefield(n *Node) *Field {
|
||||
f.Sym = f.Nname.Sym
|
||||
}
|
||||
} else {
|
||||
typecheck(&n.Right, Etype)
|
||||
n.Right = typecheck(n.Right, Etype)
|
||||
n.Type = n.Right.Type
|
||||
|
||||
if n.Embedded != 0 {
|
||||
|
@ -912,7 +912,7 @@ func esc(e *EscState, n *Node, up *Node) {
|
||||
a = Nod(OADDR, a, nil)
|
||||
a.Lineno = v.Lineno
|
||||
e.nodeEscState(a).Escloopdepth = e.loopdepth
|
||||
typecheck(&a, Erv)
|
||||
a = typecheck(a, Erv)
|
||||
}
|
||||
|
||||
escassignNilWhy(e, n, a, "captured by a closure")
|
||||
|
@ -226,7 +226,7 @@ func reexportdep(n *Node) {
|
||||
|
||||
func dumpexportconst(s *Sym) {
|
||||
n := s.Def
|
||||
typecheck(&n, Erv)
|
||||
n = typecheck(n, Erv)
|
||||
if n == nil || n.Op != OLITERAL {
|
||||
Fatalf("dumpexportconst: oconst nil: %v", s)
|
||||
}
|
||||
@ -243,7 +243,7 @@ func dumpexportconst(s *Sym) {
|
||||
|
||||
func dumpexportvar(s *Sym) {
|
||||
n := s.Def
|
||||
typecheck(&n, Erv|Ecall)
|
||||
n = typecheck(n, Erv|Ecall)
|
||||
if n == nil || n.Type == nil {
|
||||
Yyerror("variable exported but not defined: %v", s)
|
||||
return
|
||||
@ -511,7 +511,7 @@ func importimport(s *Sym, path string) {
|
||||
|
||||
func importconst(s *Sym, t *Type, n *Node) {
|
||||
importsym(s, OLITERAL)
|
||||
convlit(&n, t)
|
||||
n = convlit(n, t)
|
||||
|
||||
if s.Def != nil { // TODO: check if already the same.
|
||||
return
|
||||
|
@ -177,7 +177,7 @@ func fninit(n []*Node) {
|
||||
funcbody(fn)
|
||||
|
||||
Curfn = fn
|
||||
typecheck(&fn, Etop)
|
||||
fn = typecheck(fn, Etop)
|
||||
typecheckslice(r, Etop)
|
||||
Curfn = nil
|
||||
funccompile(fn)
|
||||
|
@ -269,7 +269,7 @@ func inlcopy(n *Node) *Node {
|
||||
func inlcalls(fn *Node) {
|
||||
savefn := Curfn
|
||||
Curfn = fn
|
||||
inlnode(&fn)
|
||||
fn = inlnode(fn)
|
||||
if fn != Curfn {
|
||||
Fatalf("inlnode replaced curfn")
|
||||
}
|
||||
@ -288,11 +288,12 @@ func inlconv2stmt(n *Node) {
|
||||
}
|
||||
|
||||
// Turn an OINLCALL into a single valued expression.
|
||||
func inlconv2expr(np **Node) {
|
||||
n := *np
|
||||
// The result of inlconv2expr MUST be assigned back to n, e.g.
|
||||
// n.Left = inlconv2expr(n.Left)
|
||||
func inlconv2expr(n *Node) *Node {
|
||||
r := n.Rlist.First()
|
||||
addinit(&r, append(n.Ninit.Slice(), n.Nbody.Slice()...))
|
||||
*np = r
|
||||
r = addinit(r, append(n.Ninit.Slice(), n.Nbody.Slice()...))
|
||||
return r
|
||||
}
|
||||
|
||||
// Turn the rlist (with the return values) of the OINLCALL in
|
||||
@ -306,14 +307,14 @@ func inlconv2list(n *Node) []*Node {
|
||||
}
|
||||
|
||||
s := n.Rlist.Slice()
|
||||
addinit(&s[0], append(n.Ninit.Slice(), n.Nbody.Slice()...))
|
||||
s[0] = addinit(s[0], append(n.Ninit.Slice(), n.Nbody.Slice()...))
|
||||
return s
|
||||
}
|
||||
|
||||
func inlnodelist(l Nodes) {
|
||||
s := l.Slice()
|
||||
for i := range s {
|
||||
inlnode(&s[i])
|
||||
s[i] = inlnode(s[i])
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,13 +329,13 @@ func inlnodelist(l Nodes) {
|
||||
// have to edit /this/ n, so you'd have to push that one down as well,
|
||||
// but then you may as well do it here. so this is cleaner and
|
||||
// shorter and less complicated.
|
||||
func inlnode(np **Node) {
|
||||
if *np == nil {
|
||||
return
|
||||
// The result of inlnode MUST be assigned back to n, e.g.
|
||||
// n.Left = inlnode(n.Left)
|
||||
func inlnode(n *Node) *Node {
|
||||
if n == nil {
|
||||
return n
|
||||
}
|
||||
|
||||
n := *np
|
||||
|
||||
switch n.Op {
|
||||
// inhibit inlining of their argument
|
||||
case ODEFER, OPROC:
|
||||
@ -348,7 +349,7 @@ func inlnode(np **Node) {
|
||||
// TODO do them here (or earlier),
|
||||
// so escape analysis can avoid more heapmoves.
|
||||
case OCLOSURE:
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
lno := setlineno(n)
|
||||
@ -360,17 +361,17 @@ func inlnode(np **Node) {
|
||||
}
|
||||
}
|
||||
|
||||
inlnode(&n.Left)
|
||||
n.Left = inlnode(n.Left)
|
||||
if n.Left != nil && n.Left.Op == OINLCALL {
|
||||
inlconv2expr(&n.Left)
|
||||
n.Left = inlconv2expr(n.Left)
|
||||
}
|
||||
|
||||
inlnode(&n.Right)
|
||||
n.Right = inlnode(n.Right)
|
||||
if n.Right != nil && n.Right.Op == OINLCALL {
|
||||
if n.Op == OFOR {
|
||||
inlconv2stmt(n.Right)
|
||||
} else {
|
||||
inlconv2expr(&n.Right)
|
||||
n.Right = inlconv2expr(n.Right)
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,7 +402,7 @@ func inlnode(np **Node) {
|
||||
s := n.List.Slice()
|
||||
for i1, n1 := range s {
|
||||
if n1.Op == OINLCALL {
|
||||
inlconv2expr(&s[i1])
|
||||
s[i1] = inlconv2expr(s[i1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -413,7 +414,7 @@ func inlnode(np **Node) {
|
||||
n.Rlist.Set(inlconv2list(n.Rlist.First()))
|
||||
n.Op = OAS2
|
||||
n.Typecheck = 0
|
||||
typecheck(np, Etop)
|
||||
n = typecheck(n, Etop)
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
@ -425,7 +426,7 @@ func inlnode(np **Node) {
|
||||
if n.Op == OIF {
|
||||
inlconv2stmt(n1)
|
||||
} else {
|
||||
inlconv2expr(&s[i1])
|
||||
s[i1] = inlconv2expr(s[i1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -445,7 +446,7 @@ func inlnode(np **Node) {
|
||||
case OCALLFUNC, OCALLMETH:
|
||||
// TODO(marvin): Fix Node.EType type union.
|
||||
if n.Etype == EType(OPROC) || n.Etype == EType(ODEFER) {
|
||||
return
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,10 +456,10 @@ func inlnode(np **Node) {
|
||||
fmt.Printf("%v:call to func %v\n", n.Line(), Nconv(n.Left, FmtSign))
|
||||
}
|
||||
if n.Left.Func != nil && len(n.Left.Func.Inl.Slice()) != 0 { // normal case
|
||||
mkinlcall(np, n.Left, n.Isddd)
|
||||
n = mkinlcall(n, n.Left, n.Isddd)
|
||||
} else if n.Left.Op == ONAME && n.Left.Left != nil && n.Left.Left.Op == OTYPE && n.Left.Right != nil && n.Left.Right.Op == ONAME { // methods called as functions
|
||||
if n.Left.Sym.Def != nil {
|
||||
mkinlcall(np, n.Left.Sym.Def, n.Isddd)
|
||||
n = mkinlcall(n, n.Left.Sym.Def, n.Isddd)
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,13 +477,16 @@ func inlnode(np **Node) {
|
||||
Fatalf("no function definition for [%p] %v\n", n.Left.Type, Tconv(n.Left.Type, FmtSign))
|
||||
}
|
||||
|
||||
mkinlcall(np, n.Left.Type.Nname, n.Isddd)
|
||||
n = mkinlcall(n, n.Left.Type.Nname, n.Isddd)
|
||||
}
|
||||
|
||||
lineno = lno
|
||||
return n
|
||||
}
|
||||
|
||||
func mkinlcall(np **Node, fn *Node, isddd bool) {
|
||||
// The result of mkinlcall MUST be assigned back to n, e.g.
|
||||
// n.Left = mkinlcall(n.Left, fn, isddd)
|
||||
func mkinlcall(n *Node, fn *Node, isddd bool) *Node {
|
||||
save_safemode := safemode
|
||||
|
||||
// imported functions may refer to unsafe as long as the
|
||||
@ -492,8 +496,9 @@ func mkinlcall(np **Node, fn *Node, isddd bool) {
|
||||
if pkg != localpkg && pkg != nil {
|
||||
safemode = 0
|
||||
}
|
||||
mkinlcall1(np, fn, isddd)
|
||||
n = mkinlcall1(n, fn, isddd)
|
||||
safemode = save_safemode
|
||||
return n
|
||||
}
|
||||
|
||||
func tinlvar(t *Field) *Node {
|
||||
@ -504,7 +509,7 @@ func tinlvar(t *Field) *Node {
|
||||
return t.Nname.Name.Inlvar
|
||||
}
|
||||
|
||||
typecheck(&nblank, Erv|Easgn)
|
||||
nblank = typecheck(nblank, Erv|Easgn)
|
||||
return nblank
|
||||
}
|
||||
|
||||
@ -514,22 +519,22 @@ var inlgen int
|
||||
// On return ninit has the parameter assignments, the nbody is the
|
||||
// inlined function body and list, rlist contain the input, output
|
||||
// parameters.
|
||||
func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
// The result of mkinlcall1 MUST be assigned back to n, e.g.
|
||||
// n.Left = mkinlcall1(n.Left, fn, isddd)
|
||||
func mkinlcall1(n *Node, fn *Node, isddd bool) *Node {
|
||||
// For variadic fn.
|
||||
if len(fn.Func.Inl.Slice()) == 0 {
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
if fn == Curfn || fn.Name.Defn == Curfn {
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
if Debug['l'] < 2 {
|
||||
typecheckinl(fn)
|
||||
}
|
||||
|
||||
n := *np
|
||||
|
||||
// Bingo, we have a function node, and it has an inlineable body
|
||||
if Debug['m'] > 1 {
|
||||
fmt.Printf("%v: inlining call to %v %v { %v }\n", n.Line(), fn.Sym, Tconv(fn.Type, FmtSharp), Hconv(fn.Func.Inl, FmtSharp))
|
||||
@ -566,7 +571,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
ln.Name.Inlvar = inlvar(ln)
|
||||
|
||||
// Typecheck because inlvar is not necessarily a function parameter.
|
||||
typecheck(&ln.Name.Inlvar, Erv)
|
||||
ln.Name.Inlvar = typecheck(ln.Name.Inlvar, Erv)
|
||||
|
||||
if ln.Class&^PHEAP != PAUTO {
|
||||
ninit.Append(Nod(ODCL, ln.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs
|
||||
@ -579,7 +584,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
for _, t := range fn.Type.Results().Fields().Slice() {
|
||||
if t != nil && t.Nname != nil && !isblank(t.Nname) {
|
||||
m = inlvar(t.Nname)
|
||||
typecheck(&m, Erv)
|
||||
m = typecheck(m, Erv)
|
||||
t.Nname.Name.Inlvar = m
|
||||
} else {
|
||||
// anonymous return values, synthesize names for use in assignment that replaces return
|
||||
@ -607,7 +612,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
}
|
||||
as := Nod(OAS, tinlvar(t), n.Left.Left)
|
||||
if as != nil {
|
||||
typecheck(&as, Etop)
|
||||
as = typecheck(as, Etop)
|
||||
ninit.Append(as)
|
||||
}
|
||||
}
|
||||
@ -734,7 +739,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
}
|
||||
|
||||
if as.Rlist.Len() != 0 {
|
||||
typecheck(&as, Etop)
|
||||
as = typecheck(as, Etop)
|
||||
ninit.Append(as)
|
||||
}
|
||||
|
||||
@ -754,14 +759,14 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil))
|
||||
}
|
||||
|
||||
typecheck(&as, Etop)
|
||||
as = typecheck(as, Etop)
|
||||
ninit.Append(as)
|
||||
}
|
||||
|
||||
// zero the outparams
|
||||
for _, n := range retvars {
|
||||
as = Nod(OAS, n, nil)
|
||||
typecheck(&as, Etop)
|
||||
as = typecheck(as, Etop)
|
||||
ninit.Append(as)
|
||||
}
|
||||
|
||||
@ -801,7 +806,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
|
||||
//dumplist("call body", body);
|
||||
|
||||
*np = call
|
||||
n = call
|
||||
|
||||
// transitive inlining
|
||||
// might be nice to do this before exporting the body,
|
||||
@ -820,8 +825,10 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
fn.Func.Inl.Set(body)
|
||||
|
||||
if Debug['m'] > 2 {
|
||||
fmt.Printf("%v: After inlining %v\n\n", n.Line(), Nconv(*np, FmtSign))
|
||||
fmt.Printf("%v: After inlining %v\n\n", n.Line(), Nconv(n, FmtSign))
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
// Every time we expand a function we generate a new set of tmpnames,
|
||||
@ -945,12 +952,12 @@ func (subst *inlsubst) node(n *Node) *Node {
|
||||
as.List.Append(n)
|
||||
}
|
||||
as.Rlist.Set(subst.list(n.List))
|
||||
typecheck(&as, Etop)
|
||||
as = typecheck(as, Etop)
|
||||
m.Ninit.Append(as)
|
||||
}
|
||||
|
||||
typecheckslice(m.Ninit.Slice(), Etop)
|
||||
typecheck(&m, Etop)
|
||||
m = typecheck(m, Etop)
|
||||
|
||||
// dump("Return after substitution", m);
|
||||
return m
|
||||
|
@ -371,7 +371,7 @@ func Main() {
|
||||
// Don't use range--typecheck can add closures to xtop.
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
if xtop[i].Op != ODCL && xtop[i].Op != OAS && xtop[i].Op != OAS2 {
|
||||
typecheck(&xtop[i], Etop)
|
||||
xtop[i] = typecheck(xtop[i], Etop)
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,7 +381,7 @@ func Main() {
|
||||
// Don't use range--typecheck can add closures to xtop.
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
if xtop[i].Op == ODCL || xtop[i].Op == OAS || xtop[i].Op == OAS2 {
|
||||
typecheck(&xtop[i], Etop)
|
||||
xtop[i] = typecheck(xtop[i], Etop)
|
||||
}
|
||||
}
|
||||
resumecheckwidth()
|
||||
@ -488,7 +488,7 @@ func Main() {
|
||||
// Phase 9: Check external declarations.
|
||||
for i, n := range externdcl {
|
||||
if n.Op == ONAME {
|
||||
typecheck(&externdcl[i], Erv)
|
||||
externdcl[i] = typecheck(externdcl[i], Erv)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ func ordertemp(t *Type, order *Order, clear bool) *Node {
|
||||
var_ := temp(t)
|
||||
if clear {
|
||||
a := Nod(OAS, var_, nil)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
order.out = append(order.out, a)
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ func ordertemp(t *Type, order *Order, clear bool) *Node {
|
||||
func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node {
|
||||
var_ := ordertemp(t, order, clear != 0)
|
||||
a := Nod(OAS, var_, n)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
order.out = append(order.out, a)
|
||||
return var_
|
||||
}
|
||||
@ -111,7 +111,7 @@ func ordercheapexpr(n *Node, order *Order) *Node {
|
||||
*a = *n
|
||||
a.Orig = a
|
||||
a.Left = l
|
||||
typecheck(&a, Erv)
|
||||
a = typecheck(a, Erv)
|
||||
return a
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
|
||||
*a = *n
|
||||
a.Orig = a
|
||||
a.Left = l
|
||||
typecheck(&a, Erv)
|
||||
a = typecheck(a, Erv)
|
||||
return a
|
||||
|
||||
case ODOTPTR, OIND:
|
||||
@ -151,7 +151,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
|
||||
*a = *n
|
||||
a.Orig = a
|
||||
a.Left = l
|
||||
typecheck(&a, Erv)
|
||||
a = typecheck(a, Erv)
|
||||
return a
|
||||
|
||||
case OINDEX, OINDEXMAP:
|
||||
@ -170,7 +170,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
|
||||
a.Orig = a
|
||||
a.Left = l
|
||||
a.Right = r
|
||||
typecheck(&a, Erv)
|
||||
a = typecheck(a, Erv)
|
||||
return a
|
||||
}
|
||||
|
||||
@ -199,12 +199,11 @@ func isaddrokay(n *Node) bool {
|
||||
// Orderaddrtemp ensures that *np is okay to pass by address to runtime routines.
|
||||
// If the original argument *np is not okay, orderaddrtemp creates a tmp, emits
|
||||
// tmp = *np, and then sets *np to the tmp variable.
|
||||
func orderaddrtemp(np **Node, order *Order) {
|
||||
n := *np
|
||||
func orderaddrtemp(n *Node, order *Order) *Node {
|
||||
if isaddrokay(n) {
|
||||
return
|
||||
return n
|
||||
}
|
||||
*np = ordercopyexpr(n, n.Type, order, 0)
|
||||
return ordercopyexpr(n, n.Type, order, 0)
|
||||
}
|
||||
|
||||
type ordermarker int
|
||||
@ -232,11 +231,11 @@ func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) {
|
||||
n.Name.Keepalive = false
|
||||
n.Addrtaken = true // ensure SSA keeps the n variable
|
||||
kill = Nod(OVARLIVE, n, nil)
|
||||
typecheck(&kill, Etop)
|
||||
kill = typecheck(kill, Etop)
|
||||
*out = append(*out, kill)
|
||||
}
|
||||
kill = Nod(OVARKILL, n, nil)
|
||||
typecheck(&kill, Etop)
|
||||
kill = typecheck(kill, Etop)
|
||||
*out = append(*out, kill)
|
||||
}
|
||||
}
|
||||
@ -277,28 +276,29 @@ func orderblockNodes(n *Nodes) {
|
||||
|
||||
// Orderexprinplace orders the side effects in *np and
|
||||
// leaves them as the init list of the final *np.
|
||||
func orderexprinplace(np **Node, outer *Order) {
|
||||
n := *np
|
||||
// The result of orderexprinplace MUST be assigned back to n, e.g.
|
||||
// n.Left = orderexprinplace(n.Left, outer)
|
||||
func orderexprinplace(n *Node, outer *Order) *Node {
|
||||
var order Order
|
||||
orderexpr(&n, &order, nil)
|
||||
addinit(&n, order.out)
|
||||
n = orderexpr(n, &order, nil)
|
||||
n = addinit(n, order.out)
|
||||
|
||||
// insert new temporaries from order
|
||||
// at head of outer list.
|
||||
outer.temp = append(outer.temp, order.temp...)
|
||||
|
||||
*np = n
|
||||
return n
|
||||
}
|
||||
|
||||
// Orderstmtinplace orders the side effects of the single statement *np
|
||||
// and replaces it with the resulting statement list.
|
||||
func orderstmtinplace(np **Node) {
|
||||
n := *np
|
||||
// The result of orderstmtinplace MUST be assigned back to n, e.g.
|
||||
// n.Left = orderstmtinplace(n.Left)
|
||||
func orderstmtinplace(n *Node) *Node {
|
||||
var order Order
|
||||
mark := marktemp(&order)
|
||||
orderstmt(n, &order)
|
||||
cleantemp(mark, &order)
|
||||
*np = liststmt(order.out)
|
||||
return liststmt(order.out)
|
||||
}
|
||||
|
||||
// Orderinit moves n's init list to order->out.
|
||||
@ -347,7 +347,7 @@ func copyret(n *Node, order *Order) []*Node {
|
||||
as := Nod(OAS2, nil, nil)
|
||||
as.List.Set(l1)
|
||||
as.Rlist.Set1(n)
|
||||
typecheck(&as, Etop)
|
||||
as = typecheck(as, Etop)
|
||||
orderstmt(as, order)
|
||||
|
||||
return l2
|
||||
@ -366,8 +366,8 @@ func ordercallargs(l *Nodes, order *Order) {
|
||||
// Ordercall orders the call expression n.
|
||||
// n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
|
||||
func ordercall(n *Node, order *Order) {
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right, order, nil) // ODDDARG temp
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, nil) // ODDDARG temp
|
||||
ordercallargs(&n.List, order)
|
||||
|
||||
if n.Op == OCALLFUNC {
|
||||
@ -434,7 +434,7 @@ func ordermapassign(n *Node, order *Order) {
|
||||
m := n.Left
|
||||
n.Left = ordertemp(m.Type, order, false)
|
||||
a := Nod(OAS, m, n.Left)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
order.out = append(order.out, a)
|
||||
}
|
||||
|
||||
@ -453,14 +453,14 @@ func ordermapassign(n *Node, order *Order) {
|
||||
}
|
||||
n.List.SetIndex(i1, ordertemp(m.Type, order, false))
|
||||
a = Nod(OAS, m, n.List.Index(i1))
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
post = append(post, a)
|
||||
} else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Index(i1)) {
|
||||
m = n.List.Index(i1)
|
||||
t := ordertemp(m.Type, order, false)
|
||||
n.List.SetIndex(i1, t)
|
||||
a = Nod(OAS, m, t)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
post = append(post, a)
|
||||
}
|
||||
}
|
||||
@ -491,8 +491,8 @@ func orderstmt(n *Node, order *Order) {
|
||||
|
||||
case OAS:
|
||||
t := marktemp(order)
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right, order, n.Left)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, n.Left)
|
||||
ordermapassign(n, order)
|
||||
cleantemp(t, order)
|
||||
|
||||
@ -504,8 +504,8 @@ func orderstmt(n *Node, order *Order) {
|
||||
ORECOVER,
|
||||
ORECV:
|
||||
t := marktemp(order)
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, nil)
|
||||
orderexprlist(n.List, order)
|
||||
orderexprlist(n.Rlist, order)
|
||||
switch n.Op {
|
||||
@ -524,7 +524,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
// a map index expression.
|
||||
t := marktemp(order)
|
||||
|
||||
orderexpr(&n.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Left = ordersafeexpr(n.Left, order)
|
||||
tmp1 := treecopy(n.Left, 0)
|
||||
if tmp1.Op == OINDEXMAP {
|
||||
@ -533,8 +533,8 @@ func orderstmt(n *Node, order *Order) {
|
||||
tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
|
||||
// TODO(marvin): Fix Node.EType type union.
|
||||
n.Right = Nod(Op(n.Etype), tmp1, n.Right)
|
||||
typecheck(&n.Right, Erv)
|
||||
orderexpr(&n.Right, order, nil)
|
||||
n.Right = typecheck(n.Right, Erv)
|
||||
n.Right = orderexpr(n.Right, order, nil)
|
||||
n.Etype = 0
|
||||
n.Op = OAS
|
||||
ordermapassign(n, order)
|
||||
@ -547,14 +547,14 @@ func orderstmt(n *Node, order *Order) {
|
||||
|
||||
orderexprlist(n.List, order)
|
||||
r := n.Rlist.First()
|
||||
orderexpr(&r.Left, order, nil)
|
||||
orderexpr(&r.Right, order, nil)
|
||||
r.Left = orderexpr(r.Left, order, nil)
|
||||
r.Right = orderexpr(r.Right, order, nil)
|
||||
|
||||
// See case OINDEXMAP below.
|
||||
if r.Right.Op == OARRAYBYTESTR {
|
||||
r.Right.Op = OARRAYBYTESTRTMP
|
||||
}
|
||||
orderaddrtemp(&r.Right, order)
|
||||
r.Right = orderaddrtemp(r.Right, order)
|
||||
ordermapassign(n, order)
|
||||
cleantemp(t, order)
|
||||
|
||||
@ -574,7 +574,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
t := marktemp(order)
|
||||
|
||||
orderexprlist(n.List, order)
|
||||
orderexpr(&n.Rlist.First().Left, order, nil) // i in i.(T)
|
||||
n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // i in i.(T)
|
||||
if isblank(n.List.First()) {
|
||||
order.out = append(order.out, n)
|
||||
} else {
|
||||
@ -582,7 +582,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
tmp1 := ordertemp(typ, order, haspointers(typ))
|
||||
order.out = append(order.out, n)
|
||||
r := Nod(OAS, n.List.First(), tmp1)
|
||||
typecheck(&r, Etop)
|
||||
r = typecheck(r, Etop)
|
||||
ordermapassign(r, order)
|
||||
n.List.Set([]*Node{tmp1, n.List.Second()})
|
||||
}
|
||||
@ -595,7 +595,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
t := marktemp(order)
|
||||
|
||||
orderexprlist(n.List, order)
|
||||
orderexpr(&n.Rlist.First().Left, order, nil) // arg to recv
|
||||
n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // arg to recv
|
||||
ch := n.Rlist.First().Left.Type
|
||||
tmp1 := ordertemp(ch.Type, order, haspointers(ch.Type))
|
||||
var tmp2 *Node
|
||||
@ -606,10 +606,10 @@ func orderstmt(n *Node, order *Order) {
|
||||
}
|
||||
order.out = append(order.out, n)
|
||||
r := Nod(OAS, n.List.First(), tmp1)
|
||||
typecheck(&r, Etop)
|
||||
r = typecheck(r, Etop)
|
||||
ordermapassign(r, order)
|
||||
r = Nod(OAS, n.List.Second(), tmp2)
|
||||
typecheck(&r, Etop)
|
||||
r = typecheck(r, Etop)
|
||||
ordermapassign(r, order)
|
||||
n.List.Set([]*Node{tmp1, tmp2})
|
||||
cleantemp(t, order)
|
||||
@ -664,9 +664,9 @@ func orderstmt(n *Node, order *Order) {
|
||||
|
||||
case ODELETE:
|
||||
t := marktemp(order)
|
||||
orderexpr(n.List.Addr(0), order, nil)
|
||||
orderexpr(n.List.Addr(1), order, nil)
|
||||
orderaddrtemp(n.List.Addr(1), order) // map key
|
||||
n.List.SetIndex(0, orderexpr(n.List.Index(0), order, nil))
|
||||
n.List.SetIndex(1, orderexpr(n.List.Index(1), order, nil))
|
||||
n.List.SetIndex(1, orderaddrtemp(n.List.Index(1), order)) // map key
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
@ -675,12 +675,12 @@ func orderstmt(n *Node, order *Order) {
|
||||
case OFOR:
|
||||
t := marktemp(order)
|
||||
|
||||
orderexprinplace(&n.Left, order)
|
||||
n.Left = orderexprinplace(n.Left, order)
|
||||
var l []*Node
|
||||
cleantempnopop(t, order, &l)
|
||||
n.Nbody.Set(append(l, n.Nbody.Slice()...))
|
||||
orderblockNodes(&n.Nbody)
|
||||
orderstmtinplace(&n.Right)
|
||||
n.Right = orderstmtinplace(n.Right)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
@ -689,7 +689,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
case OIF:
|
||||
t := marktemp(order)
|
||||
|
||||
orderexprinplace(&n.Left, order)
|
||||
n.Left = orderexprinplace(n.Left, order)
|
||||
var l []*Node
|
||||
cleantempnopop(t, order, &l)
|
||||
n.Nbody.Set(append(l, n.Nbody.Slice()...))
|
||||
@ -706,9 +706,9 @@ func orderstmt(n *Node, order *Order) {
|
||||
case OPANIC:
|
||||
t := marktemp(order)
|
||||
|
||||
orderexpr(&n.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
if !Isinter(n.Left.Type) {
|
||||
orderaddrtemp(&n.Left, order)
|
||||
n.Left = orderaddrtemp(n.Left, order)
|
||||
}
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
@ -724,7 +724,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
case ORANGE:
|
||||
t := marktemp(order)
|
||||
|
||||
orderexpr(&n.Right, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, nil)
|
||||
switch n.Type.Etype {
|
||||
default:
|
||||
Fatalf("orderstmt range %v", n.Type)
|
||||
@ -751,7 +751,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
if r.Type.Etype == TSTRING && r.Type != Types[TSTRING] {
|
||||
r = Nod(OCONV, r, nil)
|
||||
r.Type = Types[TSTRING]
|
||||
typecheck(&r, Erv)
|
||||
r = typecheck(r, Erv)
|
||||
}
|
||||
|
||||
n.Right = ordercopyexpr(r, r.Type, order, 0)
|
||||
@ -768,7 +768,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
prealloc[n] = ordertemp(Types[TUINT8], order, true)
|
||||
}
|
||||
for i := range n.List.Slice() {
|
||||
orderexprinplace(n.List.Addr(i), order)
|
||||
n.List.SetIndex(i, orderexprinplace(n.List.Index(i), order))
|
||||
}
|
||||
orderblockNodes(&n.Nbody)
|
||||
order.out = append(order.out, n)
|
||||
@ -839,7 +839,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
// r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
|
||||
// r->left == N means 'case <-c'.
|
||||
// c is always evaluated; x and ok are only evaluated when assigned.
|
||||
orderexpr(&r.Right.Left, order, nil)
|
||||
r.Right.Left = orderexpr(r.Right.Left, order, nil)
|
||||
|
||||
if r.Right.Left.Op != ONAME {
|
||||
r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0)
|
||||
@ -862,13 +862,13 @@ func orderstmt(n *Node, order *Order) {
|
||||
|
||||
if r.Colas {
|
||||
tmp2 = Nod(ODCL, tmp1, nil)
|
||||
typecheck(&tmp2, Etop)
|
||||
tmp2 = typecheck(tmp2, Etop)
|
||||
n2.Ninit.Append(tmp2)
|
||||
}
|
||||
|
||||
r.Left = ordertemp(r.Right.Left.Type.Type, order, haspointers(r.Right.Left.Type.Type))
|
||||
tmp2 = Nod(OAS, tmp1, r.Left)
|
||||
typecheck(&tmp2, Etop)
|
||||
tmp2 = typecheck(tmp2, Etop)
|
||||
n2.Ninit.Append(tmp2)
|
||||
}
|
||||
|
||||
@ -879,13 +879,13 @@ func orderstmt(n *Node, order *Order) {
|
||||
tmp1 = r.List.First()
|
||||
if r.Colas {
|
||||
tmp2 = Nod(ODCL, tmp1, nil)
|
||||
typecheck(&tmp2, Etop)
|
||||
tmp2 = typecheck(tmp2, Etop)
|
||||
n2.Ninit.Append(tmp2)
|
||||
}
|
||||
|
||||
r.List.Set1(ordertemp(tmp1.Type, order, false))
|
||||
tmp2 = Nod(OAS, tmp1, r.List.First())
|
||||
typecheck(&tmp2, Etop)
|
||||
tmp2 = typecheck(tmp2, Etop)
|
||||
n2.Ninit.Append(tmp2)
|
||||
}
|
||||
n2.Ninit.Set(orderblock(n2.Ninit))
|
||||
@ -898,12 +898,12 @@ func orderstmt(n *Node, order *Order) {
|
||||
|
||||
// case c <- x
|
||||
// r->left is c, r->right is x, both are always evaluated.
|
||||
orderexpr(&r.Left, order, nil)
|
||||
r.Left = orderexpr(r.Left, order, nil)
|
||||
|
||||
if !istemp(r.Left) {
|
||||
r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0)
|
||||
}
|
||||
orderexpr(&r.Right, order, nil)
|
||||
r.Right = orderexpr(r.Right, order, nil)
|
||||
if !istemp(r.Right) {
|
||||
r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0)
|
||||
}
|
||||
@ -929,9 +929,9 @@ func orderstmt(n *Node, order *Order) {
|
||||
case OSEND:
|
||||
t := marktemp(order)
|
||||
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right, order, nil)
|
||||
orderaddrtemp(&n.Right, order)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, nil)
|
||||
n.Right = orderaddrtemp(n.Right, order)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
@ -945,7 +945,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
case OSWITCH:
|
||||
t := marktemp(order)
|
||||
|
||||
orderexpr(&n.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
for _, n4 := range n.List.Slice() {
|
||||
if n4.Op != OXCASE {
|
||||
Fatalf("order switch case %v", Oconv(n4.Op, 0))
|
||||
@ -965,7 +965,7 @@ func orderstmt(n *Node, order *Order) {
|
||||
func orderexprlist(l Nodes, order *Order) {
|
||||
s := l.Slice()
|
||||
for i := range s {
|
||||
orderexpr(&s[i], order, nil)
|
||||
s[i] = orderexpr(s[i], order, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -974,7 +974,7 @@ func orderexprlist(l Nodes, order *Order) {
|
||||
func orderexprlistinplace(l Nodes, order *Order) {
|
||||
s := l.Slice()
|
||||
for i := range s {
|
||||
orderexprinplace(&s[i], order)
|
||||
s[i] = orderexprinplace(s[i], order)
|
||||
}
|
||||
}
|
||||
|
||||
@ -986,10 +986,11 @@ var prealloc = map[*Node]*Node{}
|
||||
// If this is part of an assignment lhs = *np, lhs is given.
|
||||
// Otherwise lhs == nil. (When lhs != nil it may be possible
|
||||
// to avoid copying the result of the expression to a temporary.)
|
||||
func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
n := *np
|
||||
// The result of orderexpr MUST be assigned back to n, e.g.
|
||||
// n.Left = orderexpr(n.Left, order, lhs)
|
||||
func orderexpr(n *Node, order *Order, lhs *Node) *Node {
|
||||
if n == nil {
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
lno := setlineno(n)
|
||||
@ -997,8 +998,8 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
|
||||
switch n.Op {
|
||||
default:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, nil)
|
||||
orderexprlist(n.List, order)
|
||||
orderexprlist(n.Rlist, order)
|
||||
|
||||
@ -1039,8 +1040,8 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
}
|
||||
|
||||
case OCMPSTR:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, nil)
|
||||
|
||||
// Mark string(byteSlice) arguments to reuse byteSlice backing
|
||||
// buffer during conversion. String comparison does not
|
||||
@ -1054,9 +1055,9 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
|
||||
// key must be addressable
|
||||
case OINDEXMAP:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
|
||||
orderexpr(&n.Right, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, nil)
|
||||
|
||||
// For x = m[string(k)] where k is []byte, the allocation of
|
||||
// backing bytes for the string can be avoided by reusing
|
||||
@ -1072,7 +1073,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
n.Right.Op = OARRAYBYTESTRTMP
|
||||
}
|
||||
|
||||
orderaddrtemp(&n.Right, order)
|
||||
n.Right = orderaddrtemp(n.Right, order)
|
||||
if n.Etype == 0 {
|
||||
// use of value (not being assigned);
|
||||
// make copy in temporary.
|
||||
@ -1082,15 +1083,15 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
// concrete type (not interface) argument must be addressable
|
||||
// temporary to pass to runtime.
|
||||
case OCONVIFACE:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
|
||||
if !Isinter(n.Left.Type) {
|
||||
orderaddrtemp(&n.Left, order)
|
||||
n.Left = orderaddrtemp(n.Left, order)
|
||||
}
|
||||
|
||||
case OANDAND, OOROR:
|
||||
mark := marktemp(order)
|
||||
orderexpr(&n.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
|
||||
// Clean temporaries from first branch at beginning of second.
|
||||
// Leave them on the stack so that they can be killed in the outer
|
||||
@ -1099,7 +1100,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
|
||||
cleantempnopop(mark, order, &s)
|
||||
n.Right.Ninit.Set(append(s, n.Right.Ninit.Slice()...))
|
||||
orderexprinplace(&n.Right, order)
|
||||
n.Right = orderexprinplace(n.Right, order)
|
||||
|
||||
case OCALLFUNC,
|
||||
OCALLINTER,
|
||||
@ -1130,22 +1131,22 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
}
|
||||
|
||||
case OSLICE, OSLICEARR, OSLICESTR:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right.Left = orderexpr(n.Right.Left, order, nil)
|
||||
n.Right.Left = ordercheapexpr(n.Right.Left, order)
|
||||
orderexpr(&n.Right.Right, order, nil)
|
||||
n.Right.Right = orderexpr(n.Right.Right, order, nil)
|
||||
n.Right.Right = ordercheapexpr(n.Right.Right, order)
|
||||
if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
|
||||
n = ordercopyexpr(n, n.Type, order, 0)
|
||||
}
|
||||
|
||||
case OSLICE3, OSLICE3ARR:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right.Left = orderexpr(n.Right.Left, order, nil)
|
||||
n.Right.Left = ordercheapexpr(n.Right.Left, order)
|
||||
orderexpr(&n.Right.Right.Left, order, nil)
|
||||
n.Right.Right.Left = orderexpr(n.Right.Right.Left, order, nil)
|
||||
n.Right.Right.Left = ordercheapexpr(n.Right.Right.Left, order)
|
||||
orderexpr(&n.Right.Right.Right, order, nil)
|
||||
n.Right.Right.Right = orderexpr(n.Right.Right.Right, order, nil)
|
||||
n.Right.Right.Right = ordercheapexpr(n.Right.Right.Right, order)
|
||||
if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
|
||||
n = ordercopyexpr(n, n.Type, order, 0)
|
||||
@ -1157,8 +1158,8 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
}
|
||||
|
||||
case OARRAYLIT, OCALLPART:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, nil)
|
||||
orderexprlist(n.List, order)
|
||||
orderexprlist(n.Rlist, order)
|
||||
if n.Noescape {
|
||||
@ -1175,7 +1176,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
}
|
||||
|
||||
case ODOTTYPE, ODOTTYPE2:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
// TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
|
||||
// It needs to be removed in all three places.
|
||||
// That would allow inlining x.(struct{*int}) the same as x.(*int).
|
||||
@ -1184,22 +1185,21 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
||||
}
|
||||
|
||||
case ORECV:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n = ordercopyexpr(n, n.Type, order, 1)
|
||||
|
||||
case OEQ, ONE:
|
||||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right, order, nil)
|
||||
n.Left = orderexpr(n.Left, order, nil)
|
||||
n.Right = orderexpr(n.Right, order, nil)
|
||||
t := n.Left.Type
|
||||
if t.Etype == TSTRUCT || Isfixedarray(t) {
|
||||
// for complex comparisons, we need both args to be
|
||||
// addressable so we can pass them to the runtime.
|
||||
orderaddrtemp(&n.Left, order)
|
||||
orderaddrtemp(&n.Right, order)
|
||||
n.Left = orderaddrtemp(n.Left, order)
|
||||
n.Right = orderaddrtemp(n.Right, order)
|
||||
}
|
||||
}
|
||||
|
||||
lineno = lno
|
||||
|
||||
*np = n
|
||||
return n
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ func compile(fn *Node) {
|
||||
for _, t := range Curfn.Type.Results().Fields().Slice() {
|
||||
if t.Nname != nil {
|
||||
n := Nod(OAS, t.Nname, nil)
|
||||
typecheck(&n, Etop)
|
||||
n = typecheck(n, Etop)
|
||||
Curfn.Nbody.Set(append([]*Node{n}, Curfn.Nbody.Slice()...))
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ func instrumentnode(np **Node, init *Nodes, wr int, skip int) {
|
||||
n1 := Nod(OCONVNOP, n.Left, nil)
|
||||
n1.Type = Ptrto(Types[TUINT8])
|
||||
n1 = Nod(OIND, n1, nil)
|
||||
typecheck(&n1, Erv)
|
||||
n1 = typecheck(n1, Erv)
|
||||
callinstr(&n1, init, 0, skip)
|
||||
}
|
||||
|
||||
@ -581,12 +581,12 @@ func detachexpr(n *Node, init *Nodes) *Node {
|
||||
addr := Nod(OADDR, n, nil)
|
||||
l := temp(Ptrto(n.Type))
|
||||
as := Nod(OAS, l, addr)
|
||||
typecheck(&as, Etop)
|
||||
walkexpr(&as, init)
|
||||
as = typecheck(as, Etop)
|
||||
as = walkexpr(as, init)
|
||||
init.Append(as)
|
||||
ind := Nod(OIND, l, nil)
|
||||
typecheck(&ind, Erv)
|
||||
walkexpr(&ind, init)
|
||||
ind = typecheck(ind, Erv)
|
||||
ind = walkexpr(ind, init)
|
||||
return ind
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ func typecheckrange(n *Node) {
|
||||
// 3. typecheck body.
|
||||
// 4. decldepth--.
|
||||
|
||||
typecheck(&n.Right, Erv)
|
||||
n.Right = typecheck(n.Right, Erv)
|
||||
|
||||
t := n.Right.Type
|
||||
if t == nil {
|
||||
@ -34,7 +34,7 @@ func typecheckrange(n *Node) {
|
||||
ls = n.List.Slice()
|
||||
for i1, n1 := range ls {
|
||||
if n1.Name == nil || n1.Name.Defn != n {
|
||||
typecheck(&ls[i1], Erv|Easgn)
|
||||
ls[i1] = typecheck(ls[i1], Erv|Easgn)
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ out:
|
||||
ls = n.List.Slice()
|
||||
for i1, n1 := range ls {
|
||||
if n1.Typecheck == 0 {
|
||||
typecheck(&ls[i1], Erv|Easgn)
|
||||
ls[i1] = typecheck(ls[i1], Erv|Easgn)
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ func walkrange(n *Node) {
|
||||
tmp.Right.Type = Types[Tptr]
|
||||
tmp.Right.Typecheck = 1
|
||||
a = Nod(OAS, hp, tmp)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
n.Right.Ninit.Set1(a)
|
||||
}
|
||||
|
||||
@ -231,12 +231,12 @@ func walkrange(n *Node) {
|
||||
|
||||
fn := syslook("mapiterinit")
|
||||
|
||||
substArgTypes(&fn, t.Key(), t.Type, th)
|
||||
fn = substArgTypes(fn, t.Key(), t.Type, th)
|
||||
init = append(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
|
||||
n.Left = Nod(ONE, NodSym(ODOT, hit, keysym), nodnil())
|
||||
|
||||
fn = syslook("mapiternext")
|
||||
substArgTypes(&fn, th)
|
||||
fn = substArgTypes(fn, th)
|
||||
n.Right = mkcall1(fn, nil, nil, Nod(OADDR, hit, nil))
|
||||
|
||||
key := NodSym(ODOT, hit, keysym)
|
||||
@ -316,11 +316,11 @@ func walkrange(n *Node) {
|
||||
typecheckslice(init, Etop)
|
||||
n.Ninit.Append(init...)
|
||||
typecheckslice(n.Left.Ninit.Slice(), Etop)
|
||||
typecheck(&n.Left, Erv)
|
||||
typecheck(&n.Right, Etop)
|
||||
n.Left = typecheck(n.Left, Erv)
|
||||
n.Right = typecheck(n.Right, Etop)
|
||||
typecheckslice(body, Etop)
|
||||
n.Nbody.Set(append(body, n.Nbody.Slice()...))
|
||||
walkstmt(&n)
|
||||
n = walkstmt(n)
|
||||
|
||||
lineno = lno
|
||||
}
|
||||
@ -398,8 +398,8 @@ func memclrrange(n, v1, v2, a *Node) bool {
|
||||
|
||||
n.Nbody.Append(v1)
|
||||
|
||||
typecheck(&n.Left, Erv)
|
||||
n.Left = typecheck(n.Left, Erv)
|
||||
typecheckslice(n.Nbody.Slice(), Etop)
|
||||
walkstmt(&n)
|
||||
n = walkstmt(n)
|
||||
return true
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ func typecheckselect(sel *Node) {
|
||||
} else if ncase.List.Len() > 1 {
|
||||
Yyerror("select cases cannot be lists")
|
||||
} else {
|
||||
n = typecheck(ncase.List.Addr(0), Etop)
|
||||
ncase.List.SetIndex(0, typecheck(ncase.List.Index(0), Etop))
|
||||
n = ncase.List.Index(0)
|
||||
ncase.Left = n
|
||||
ncase.List.Set(nil)
|
||||
setlineno(n)
|
||||
@ -137,7 +138,7 @@ func walkselect(sel *Node) {
|
||||
}
|
||||
|
||||
if n.Left == nil {
|
||||
typecheck(&nblank, Erv|Easgn)
|
||||
nblank = typecheck(nblank, Erv|Easgn)
|
||||
n.Left = nblank
|
||||
}
|
||||
|
||||
@ -147,7 +148,7 @@ func walkselect(sel *Node) {
|
||||
n.Right = nil
|
||||
n.Left = nil
|
||||
n.Typecheck = 0
|
||||
typecheck(&n, Etop)
|
||||
n = typecheck(n, Etop)
|
||||
}
|
||||
|
||||
// if ch == nil { block() }; n;
|
||||
@ -158,7 +159,7 @@ func walkselect(sel *Node) {
|
||||
ln.Set(l)
|
||||
a.Nbody.Set1(mkcall("block", nil, &ln))
|
||||
l = ln.Slice()
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
l = append(l, a)
|
||||
l = append(l, n)
|
||||
}
|
||||
@ -179,7 +180,7 @@ func walkselect(sel *Node) {
|
||||
switch n.Op {
|
||||
case OSEND:
|
||||
n.Right = Nod(OADDR, n.Right, nil)
|
||||
typecheck(&n.Right, Erv)
|
||||
n.Right = typecheck(n.Right, Erv)
|
||||
|
||||
case OSELRECV, OSELRECV2:
|
||||
if n.Op == OSELRECV2 && n.List.Len() == 0 {
|
||||
@ -187,14 +188,14 @@ func walkselect(sel *Node) {
|
||||
}
|
||||
if n.Op == OSELRECV2 {
|
||||
n.List.SetIndex(0, Nod(OADDR, n.List.First(), nil))
|
||||
typecheck(n.List.Addr(0), Erv)
|
||||
n.List.SetIndex(0, typecheck(n.List.Index(0), Erv))
|
||||
}
|
||||
|
||||
if n.Left == nil {
|
||||
n.Left = nodnil()
|
||||
} else {
|
||||
n.Left = Nod(OADDR, n.Left, nil)
|
||||
typecheck(&n.Left, Erv)
|
||||
n.Left = typecheck(n.Left, Erv)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -242,7 +243,7 @@ func walkselect(sel *Node) {
|
||||
r.Left = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, n.List.First(), ch)
|
||||
}
|
||||
|
||||
typecheck(&r.Left, Erv)
|
||||
r.Left = typecheck(r.Left, Erv)
|
||||
r.Nbody.Set(cas.Nbody.Slice())
|
||||
r.Rlist.Set(append(dflt.Ninit.Slice(), dflt.Nbody.Slice()...))
|
||||
sel.Nbody.Set1(r)
|
||||
@ -257,11 +258,11 @@ func walkselect(sel *Node) {
|
||||
|
||||
selv = temp(selecttype(int32(sel.Xoffset)))
|
||||
r = Nod(OAS, selv, nil)
|
||||
typecheck(&r, Etop)
|
||||
r = typecheck(r, Etop)
|
||||
init = append(init, r)
|
||||
var_ = conv(conv(Nod(OADDR, selv, nil), Types[TUNSAFEPTR]), Ptrto(Types[TUINT8]))
|
||||
r = mkcall("newselect", nil, nil, var_, Nodintconst(selv.Type.Width), Nodintconst(sel.Xoffset))
|
||||
typecheck(&r, Etop)
|
||||
r = typecheck(r, Etop)
|
||||
init = append(init, r)
|
||||
// register cases
|
||||
for _, cas := range sel.List.Slice() {
|
||||
@ -330,7 +331,7 @@ func selecttype(size int32) *Type {
|
||||
scase.List.Append(Nod(ODCLFIELD, newname(Lookup("so")), typenod(Types[TUINT16])))
|
||||
scase.List.Append(Nod(ODCLFIELD, newname(Lookup("receivedp")), typenod(Ptrto(Types[TUINT8]))))
|
||||
scase.List.Append(Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64])))
|
||||
typecheck(&scase, Etype)
|
||||
scase = typecheck(scase, Etype)
|
||||
scase.Type.Noalg = true
|
||||
scase.Type.Local = true
|
||||
|
||||
@ -345,7 +346,7 @@ func selecttype(size int32) *Type {
|
||||
sel.List.Append(Nod(ODCLFIELD, newname(Lookup("lockorderarr")), arr))
|
||||
arr = Nod(OTARRAY, Nodintconst(int64(size)), typenod(Types[TUINT16]))
|
||||
sel.List.Append(Nod(ODCLFIELD, newname(Lookup("pollorderarr")), arr))
|
||||
typecheck(&sel, Etype)
|
||||
sel = typecheck(sel, Etype)
|
||||
sel.Type.Noalg = true
|
||||
sel.Type.Local = true
|
||||
|
||||
|
@ -520,8 +520,8 @@ func (n *Node) isSimpleName() bool {
|
||||
|
||||
func litas(l *Node, r *Node, init *Nodes) {
|
||||
a := Nod(OAS, l, r)
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
init.Append(a)
|
||||
}
|
||||
|
||||
@ -608,16 +608,16 @@ func structlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
|
||||
a = NodSym(ODOT, var_, index.Sym)
|
||||
|
||||
a = Nod(OAS, a, value)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
if pass == 1 {
|
||||
walkexpr(&a, init) // add any assignments in r to top
|
||||
a = walkexpr(a, init) // add any assignments in r to top
|
||||
if a.Op != OAS {
|
||||
Fatalf("structlit: not as")
|
||||
}
|
||||
a.Dodata = 2
|
||||
} else {
|
||||
orderstmtinplace(&a)
|
||||
walkstmt(&a)
|
||||
a = orderstmtinplace(a)
|
||||
a = walkstmt(a)
|
||||
}
|
||||
|
||||
init.Append(a)
|
||||
@ -672,16 +672,16 @@ func arraylit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
|
||||
a = Nod(OINDEX, var_, index)
|
||||
|
||||
a = Nod(OAS, a, value)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
if pass == 1 {
|
||||
walkexpr(&a, init)
|
||||
a = walkexpr(a, init)
|
||||
if a.Op != OAS {
|
||||
Fatalf("arraylit: not as")
|
||||
}
|
||||
a.Dodata = 2
|
||||
} else {
|
||||
orderstmtinplace(&a)
|
||||
walkstmt(&a)
|
||||
a = orderstmtinplace(a)
|
||||
a = walkstmt(a)
|
||||
}
|
||||
|
||||
init.Append(a)
|
||||
@ -708,7 +708,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
a := Nod(OSLICE, vstat, Nod(OKEY, nil, nil))
|
||||
|
||||
a = Nod(OAS, var_, a)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
a.Dodata = 2
|
||||
init.Append(a)
|
||||
return
|
||||
@ -754,7 +754,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
|
||||
if vstat == nil {
|
||||
a = Nod(OAS, x, nil)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
init.Append(a) // zero new temp
|
||||
}
|
||||
|
||||
@ -763,7 +763,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
a = temp(t)
|
||||
if vstat == nil {
|
||||
a = Nod(OAS, temp(t), nil)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
init.Append(a) // zero new temp
|
||||
a = a.Left
|
||||
}
|
||||
@ -775,8 +775,8 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
}
|
||||
|
||||
a = Nod(OAS, vauto, a)
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
init.Append(a)
|
||||
|
||||
if vstat != nil {
|
||||
@ -784,17 +784,17 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
a = Nod(OIND, vauto, nil)
|
||||
|
||||
a = Nod(OAS, a, vstat)
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
init.Append(a)
|
||||
}
|
||||
|
||||
// make slice out of heap (5)
|
||||
a = Nod(OAS, var_, Nod(OSLICE, vauto, Nod(OKEY, nil, nil)))
|
||||
|
||||
typecheck(&a, Etop)
|
||||
orderstmtinplace(&a)
|
||||
walkstmt(&a)
|
||||
a = typecheck(a, Etop)
|
||||
a = orderstmtinplace(a)
|
||||
a = walkstmt(a)
|
||||
init.Append(a)
|
||||
// put dynamics into slice (6)
|
||||
for _, r := range n.List.Slice() {
|
||||
@ -829,9 +829,9 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
setlineno(value)
|
||||
a = Nod(OAS, a, value)
|
||||
|
||||
typecheck(&a, Etop)
|
||||
orderstmtinplace(&a)
|
||||
walkstmt(&a)
|
||||
a = typecheck(a, Etop)
|
||||
a = orderstmtinplace(a)
|
||||
a = walkstmt(a)
|
||||
init.Append(a)
|
||||
}
|
||||
}
|
||||
@ -906,8 +906,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
a = Nod(OINDEX, vstat, a)
|
||||
a = NodSym(ODOT, a, syma)
|
||||
a = Nod(OAS, a, index)
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
a.Dodata = 2
|
||||
init.Append(a)
|
||||
|
||||
@ -918,8 +918,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
a = Nod(OINDEX, vstat, a)
|
||||
a = NodSym(ODOT, a, symb)
|
||||
a = Nod(OAS, a, value)
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
a.Dodata = 2
|
||||
init.Append(a)
|
||||
|
||||
@ -951,8 +951,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
a.Left = Nod(OLT, index, Nodintconst(tarr.Bound))
|
||||
a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
|
||||
|
||||
typecheck(&a, Etop)
|
||||
walkstmt(&a)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkstmt(a)
|
||||
init.Append(a)
|
||||
}
|
||||
|
||||
@ -978,19 +978,19 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
|
||||
setlineno(r.Left)
|
||||
a = Nod(OAS, key, r.Left)
|
||||
typecheck(&a, Etop)
|
||||
walkstmt(&a)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkstmt(a)
|
||||
init.Append(a)
|
||||
setlineno(r.Right)
|
||||
a = Nod(OAS, val, r.Right)
|
||||
typecheck(&a, Etop)
|
||||
walkstmt(&a)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkstmt(a)
|
||||
init.Append(a)
|
||||
|
||||
setlineno(val)
|
||||
a = Nod(OAS, Nod(OINDEX, var_, key), val)
|
||||
typecheck(&a, Etop)
|
||||
walkstmt(&a)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkstmt(a)
|
||||
init.Append(a)
|
||||
|
||||
if nerr != nerrors {
|
||||
@ -1000,10 +1000,10 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
|
||||
if key != nil {
|
||||
a = Nod(OVARKILL, key, nil)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
init.Append(a)
|
||||
a = Nod(OVARKILL, val, nil)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
init.Append(a)
|
||||
}
|
||||
}
|
||||
@ -1022,7 +1022,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
var r *Node
|
||||
if n.Right != nil {
|
||||
r = Nod(OADDR, n.Right, nil)
|
||||
typecheck(&r, Erv)
|
||||
r = typecheck(r, Erv)
|
||||
} else {
|
||||
r = Nod(ONEW, nil, nil)
|
||||
r.Typecheck = 1
|
||||
@ -1030,14 +1030,14 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
r.Esc = n.Esc
|
||||
}
|
||||
|
||||
walkexpr(&r, init)
|
||||
r = walkexpr(r, init)
|
||||
a := Nod(OAS, var_, r)
|
||||
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
init.Append(a)
|
||||
|
||||
var_ = Nod(OIND, var_, nil)
|
||||
typecheck(&var_, Erv|Easgn)
|
||||
var_ = typecheck(var_, Erv|Easgn)
|
||||
anylit(ctxt, n.Left, var_, init)
|
||||
|
||||
case OSTRUCTLIT:
|
||||
@ -1055,8 +1055,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
// copy static to var
|
||||
a := Nod(OAS, var_, vstat)
|
||||
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
init.Append(a)
|
||||
|
||||
// add expressions to automatic
|
||||
@ -1073,8 +1073,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
// initialize of not completely specified
|
||||
if var_.isSimpleName() || n.List.Len() < t.NumFields() {
|
||||
a := Nod(OAS, var_, nil)
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
init.Append(a)
|
||||
}
|
||||
|
||||
@ -1099,8 +1099,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
// copy static to automatic
|
||||
a := Nod(OAS, var_, vstat)
|
||||
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
init.Append(a)
|
||||
|
||||
// add expressions to automatic
|
||||
@ -1117,8 +1117,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
// initialize of not completely specified
|
||||
if var_.isSimpleName() || int64(n.List.Len()) < t.Bound {
|
||||
a := Nod(OAS, var_, nil)
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
init.Append(a)
|
||||
}
|
||||
|
||||
|
@ -484,7 +484,7 @@ func Nodbool(b bool) *Node {
|
||||
|
||||
func aindex(b *Node, t *Type) *Type {
|
||||
bound := int64(-1) // open bound
|
||||
typecheck(&b, Erv)
|
||||
b = typecheck(b, Erv)
|
||||
if b != nil {
|
||||
switch consttype(b) {
|
||||
default:
|
||||
@ -1042,7 +1042,7 @@ func assignconvfn(n *Node, t *Type, context func() string) *Node {
|
||||
|
||||
old := n
|
||||
old.Diag++ // silence errors about n; we'll issue one below
|
||||
defaultlit(&n, t)
|
||||
n = defaultlit(n, t)
|
||||
old.Diag--
|
||||
if t.Etype == TBLANK {
|
||||
return n
|
||||
@ -1082,10 +1082,11 @@ func assignconvfn(n *Node, t *Type, context func() string) *Node {
|
||||
// substArgTypes substitutes the given list of types for
|
||||
// successive occurrences of the "any" placeholder in the
|
||||
// type syntax expression n.Type.
|
||||
func substArgTypes(np **Node, types ...*Type) {
|
||||
n := Nod(0, nil, nil)
|
||||
*n = **np
|
||||
*np = n
|
||||
// The result of substArgTypes MUST be assigned back to old, e.g.
|
||||
// n.Left = substArgTypes(n.Left, t1, t2)
|
||||
func substArgTypes(old *Node, types ...*Type) *Node {
|
||||
n := Nod(OXXX, nil, nil)
|
||||
*n = *old // make shallow copy
|
||||
|
||||
for _, t := range types {
|
||||
dowidth(t)
|
||||
@ -1094,6 +1095,7 @@ func substArgTypes(np **Node, types ...*Type) {
|
||||
if len(types) > 0 {
|
||||
Fatalf("substArgTypes: too many argument types")
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// substAny walks t, replacing instances of "any" with successive
|
||||
@ -1478,8 +1480,8 @@ func safeexpr(n *Node, init *Nodes) *Node {
|
||||
r := Nod(OXXX, nil, nil)
|
||||
*r = *n
|
||||
r.Left = l
|
||||
typecheck(&r, Erv)
|
||||
walkexpr(&r, init)
|
||||
r = typecheck(r, Erv)
|
||||
r = walkexpr(r, init)
|
||||
return r
|
||||
|
||||
case ODOTPTR, OIND:
|
||||
@ -1490,7 +1492,7 @@ func safeexpr(n *Node, init *Nodes) *Node {
|
||||
a := Nod(OXXX, nil, nil)
|
||||
*a = *n
|
||||
a.Left = l
|
||||
walkexpr(&a, init)
|
||||
a = walkexpr(a, init)
|
||||
return a
|
||||
|
||||
case OINDEX, OINDEXMAP:
|
||||
@ -1503,7 +1505,7 @@ func safeexpr(n *Node, init *Nodes) *Node {
|
||||
*a = *n
|
||||
a.Left = l
|
||||
a.Right = r
|
||||
walkexpr(&a, init)
|
||||
a = walkexpr(a, init)
|
||||
return a
|
||||
}
|
||||
|
||||
@ -1517,8 +1519,8 @@ func safeexpr(n *Node, init *Nodes) *Node {
|
||||
func copyexpr(n *Node, t *Type, init *Nodes) *Node {
|
||||
l := temp(t)
|
||||
a := Nod(OAS, l, n)
|
||||
typecheck(&a, Etop)
|
||||
walkexpr(&a, init)
|
||||
a = typecheck(a, Etop)
|
||||
a = walkexpr(a, init)
|
||||
init.Append(a)
|
||||
return l
|
||||
}
|
||||
@ -1684,7 +1686,7 @@ func dotpath(s *Sym, t *Type, save **Field, ignorecase bool) (path []Dlist, ambi
|
||||
// will give shortest unique addressing.
|
||||
// modify the tree with missing type names.
|
||||
func adddot(n *Node) *Node {
|
||||
typecheck(&n.Left, Etype|Erv)
|
||||
n.Left = typecheck(n.Left, Etype|Erv)
|
||||
n.Diag |= n.Left.Diag
|
||||
t := n.Left.Type
|
||||
if t == nil {
|
||||
@ -2018,7 +2020,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
|
||||
if rcvr.Etype == TSTRUCT || rcvr.Etype == TINTER || Isptr[rcvr.Etype] && rcvr.Type.Etype == TSTRUCT {
|
||||
fn.Func.Dupok = true
|
||||
}
|
||||
typecheck(&fn, Etop)
|
||||
fn = typecheck(fn, Etop)
|
||||
typecheckslice(fn.Nbody.Slice(), Etop)
|
||||
|
||||
inlcalls(fn)
|
||||
@ -2038,7 +2040,7 @@ func hashmem(t *Type) *Node {
|
||||
tfn.List.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
||||
tfn.List.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
||||
tfn.Rlist.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
||||
typecheck(&tfn, Etype)
|
||||
tfn = typecheck(tfn, Etype)
|
||||
n.Type = tfn.Type
|
||||
return n
|
||||
}
|
||||
@ -2305,25 +2307,25 @@ func mkpkg(path string) *Pkg {
|
||||
return p
|
||||
}
|
||||
|
||||
func addinit(np **Node, init []*Node) {
|
||||
// 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 {
|
||||
if len(init) == 0 {
|
||||
return
|
||||
return n
|
||||
}
|
||||
|
||||
n := *np
|
||||
switch n.Op {
|
||||
// There may be multiple refs to this node;
|
||||
// introduce OCONVNOP to hold init list.
|
||||
case ONAME, OLITERAL:
|
||||
n = Nod(OCONVNOP, n, nil)
|
||||
|
||||
n.Type = n.Left.Type
|
||||
n.Typecheck = 1
|
||||
*np = n
|
||||
}
|
||||
|
||||
n.Ninit.Set(append(init, n.Ninit.Slice()...))
|
||||
n.Ullman = UINF
|
||||
return n
|
||||
}
|
||||
|
||||
var reservedimports = []string{
|
||||
@ -2377,7 +2379,7 @@ func isbadimport(path string) bool {
|
||||
func checknil(x *Node, init *Nodes) {
|
||||
if Isinter(x.Type) {
|
||||
x = Nod(OITAB, x, nil)
|
||||
typecheck(&x, Erv)
|
||||
x = typecheck(x, Erv)
|
||||
}
|
||||
|
||||
n := Nod(OCHECKNIL, x, nil)
|
||||
|
@ -67,7 +67,7 @@ func typecheckswitch(n *Node) {
|
||||
if n.Left != nil && n.Left.Op == OTYPESW {
|
||||
// type switch
|
||||
top = Etype
|
||||
typecheck(&n.Left.Right, Erv)
|
||||
n.Left.Right = typecheck(n.Left.Right, Erv)
|
||||
t = n.Left.Right.Type
|
||||
if t != nil && t.Etype != TINTER {
|
||||
Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, FmtLong))
|
||||
@ -76,8 +76,8 @@ func typecheckswitch(n *Node) {
|
||||
// expression switch
|
||||
top = Erv
|
||||
if n.Left != nil {
|
||||
typecheck(&n.Left, Erv)
|
||||
defaultlit(&n.Left, nil)
|
||||
n.Left = typecheck(n.Left, Erv)
|
||||
n.Left = defaultlit(n.Left, nil)
|
||||
t = n.Left.Type
|
||||
} else {
|
||||
t = Types[TBOOL]
|
||||
@ -117,7 +117,7 @@ func typecheckswitch(n *Node) {
|
||||
ls := ncase.List.Slice()
|
||||
for i1, n1 := range ls {
|
||||
setlineno(n1)
|
||||
typecheck(&ls[i1], Erv|Etype)
|
||||
ls[i1] = typecheck(ls[i1], Erv|Etype)
|
||||
n1 = ls[i1]
|
||||
if n1.Type == nil || t == nil {
|
||||
continue
|
||||
@ -126,7 +126,7 @@ func typecheckswitch(n *Node) {
|
||||
switch top {
|
||||
// expression switch
|
||||
case Erv:
|
||||
defaultlit(&ls[i1], t)
|
||||
ls[i1] = defaultlit(ls[i1], t)
|
||||
n1 = ls[i1]
|
||||
switch {
|
||||
case n1.Op == OTYPE:
|
||||
@ -177,7 +177,7 @@ func typecheckswitch(n *Node) {
|
||||
nvar.Name.Param.Ntype = typenod(n.Type)
|
||||
}
|
||||
|
||||
typecheck(&nvar, Erv|Easgn)
|
||||
nvar = typecheck(nvar, Erv|Easgn)
|
||||
ncase.Rlist.SetIndex(0, nvar)
|
||||
}
|
||||
}
|
||||
@ -193,7 +193,7 @@ func walkswitch(sw *Node) {
|
||||
// convert switch {...} to switch true {...}
|
||||
if sw.Left == nil {
|
||||
sw.Left = Nodbool(true)
|
||||
typecheck(&sw.Left, Erv)
|
||||
sw.Left = typecheck(sw.Left, Erv)
|
||||
}
|
||||
|
||||
if sw.Left.Op == OTYPESW {
|
||||
@ -224,7 +224,7 @@ func (s *exprSwitch) walk(sw *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
walkexpr(&cond, &sw.Ninit)
|
||||
cond = walkexpr(cond, &sw.Ninit)
|
||||
t := sw.Type
|
||||
if t == nil {
|
||||
return
|
||||
@ -296,13 +296,13 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
|
||||
a := Nod(OIF, nil, nil)
|
||||
if (s.kind != switchKindTrue && s.kind != switchKindFalse) || assignop(n.Left.Type, s.exprname.Type, nil) == OCONVIFACE || assignop(s.exprname.Type, n.Left.Type, nil) == OCONVIFACE {
|
||||
a.Left = Nod(OEQ, s.exprname, n.Left) // if name == val
|
||||
typecheck(&a.Left, Erv)
|
||||
a.Left = typecheck(a.Left, Erv)
|
||||
} else if s.kind == switchKindTrue {
|
||||
a.Left = n.Left // if val
|
||||
} else {
|
||||
// s.kind == switchKindFalse
|
||||
a.Left = Nod(ONOT, n.Left, nil) // if !val
|
||||
typecheck(&a.Left, Erv)
|
||||
a.Left = typecheck(a.Left, Erv)
|
||||
}
|
||||
a.Nbody.Set1(n.Right) // goto l
|
||||
|
||||
@ -325,7 +325,7 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
|
||||
} else {
|
||||
a.Left = le
|
||||
}
|
||||
typecheck(&a.Left, Erv)
|
||||
a.Left = typecheck(a.Left, Erv)
|
||||
a.Nbody.Set1(s.walkCases(cc[:half]))
|
||||
a.Rlist.Set1(s.walkCases(cc[half:]))
|
||||
return a
|
||||
@ -526,7 +526,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||
return
|
||||
}
|
||||
|
||||
walkexpr(&cond.Right, &sw.Ninit)
|
||||
cond.Right = walkexpr(cond.Right, &sw.Ninit)
|
||||
if !Istype(cond.Right.Type, TINTER) {
|
||||
Yyerror("type switch must be on an interface")
|
||||
return
|
||||
@ -538,14 +538,14 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||
s.facename = temp(cond.Right.Type)
|
||||
|
||||
a := Nod(OAS, s.facename, cond.Right)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
cas = append(cas, a)
|
||||
|
||||
s.okname = temp(Types[TBOOL])
|
||||
typecheck(&s.okname, Erv)
|
||||
s.okname = typecheck(s.okname, Erv)
|
||||
|
||||
s.hashname = temp(Types[TUINT32])
|
||||
typecheck(&s.hashname, Erv)
|
||||
s.hashname = typecheck(s.hashname, Erv)
|
||||
|
||||
// set up labels and jumps
|
||||
casebody(sw, s.facename)
|
||||
@ -590,7 +590,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||
blk.List.Set([]*Node{Nod(OLABEL, lbl, nil), def})
|
||||
def = blk
|
||||
}
|
||||
typecheck(&i.Left, Erv)
|
||||
i.Left = typecheck(i.Left, Erv)
|
||||
cas = append(cas, i)
|
||||
|
||||
if !isnilinter(cond.Right.Type) {
|
||||
@ -608,7 +608,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||
h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type
|
||||
h.Bounded = true // guaranteed not to fault
|
||||
a = Nod(OAS, s.hashname, h)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
cas = append(cas, a)
|
||||
|
||||
// insert type equality check into each case block
|
||||
@ -680,12 +680,12 @@ func (s *typeSwitch) typeone(t *Node) *Node {
|
||||
var init []*Node
|
||||
if t.Rlist.Len() == 0 {
|
||||
name = nblank
|
||||
typecheck(&nblank, Erv|Easgn)
|
||||
nblank = typecheck(nblank, Erv|Easgn)
|
||||
} else {
|
||||
name = t.Rlist.First()
|
||||
init = []*Node{Nod(ODCL, name, nil)}
|
||||
a := Nod(OAS, name, nil)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
init = append(init, a)
|
||||
}
|
||||
|
||||
@ -694,7 +694,7 @@ func (s *typeSwitch) typeone(t *Node) *Node {
|
||||
b := Nod(ODOTTYPE, s.facename, nil)
|
||||
b.Type = t.Left.Type // interface.(type)
|
||||
a.Rlist.Set1(b)
|
||||
typecheck(&a, Etop)
|
||||
a = typecheck(a, Etop)
|
||||
init = append(init, a)
|
||||
|
||||
c := Nod(OIF, nil, nil)
|
||||
@ -715,7 +715,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
|
||||
}
|
||||
a := Nod(OIF, nil, nil)
|
||||
a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash)))
|
||||
typecheck(&a.Left, Erv)
|
||||
a.Left = typecheck(a.Left, Erv)
|
||||
a.Nbody.Set1(n.Right)
|
||||
cas = append(cas, a)
|
||||
}
|
||||
@ -726,7 +726,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
|
||||
half := len(cc) / 2
|
||||
a := Nod(OIF, nil, nil)
|
||||
a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
|
||||
typecheck(&a.Left, Erv)
|
||||
a.Left = typecheck(a.Left, Erv)
|
||||
a.Nbody.Set1(s.walkCases(cc[:half]))
|
||||
a.Rlist.Set1(s.walkCases(cc[half:]))
|
||||
return a
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,8 +30,8 @@ func unsafenmagic(nn *Node) *Node {
|
||||
var v int64
|
||||
switch s.Name {
|
||||
case "Alignof", "Sizeof":
|
||||
typecheck(&r, Erv)
|
||||
defaultlit(&r, nil)
|
||||
r = typecheck(r, Erv)
|
||||
r = defaultlit(r, nil)
|
||||
tr := r.Type
|
||||
if tr == nil {
|
||||
goto bad
|
||||
@ -52,10 +52,10 @@ func unsafenmagic(nn *Node) *Node {
|
||||
// Remember base of selector to find it back after dot insertion.
|
||||
// Since r->left may be mutated by typechecking, check it explicitly
|
||||
// first to track it correctly.
|
||||
typecheck(&r.Left, Erv)
|
||||
r.Left = typecheck(r.Left, Erv)
|
||||
base := r.Left
|
||||
|
||||
typecheck(&r, Erv)
|
||||
r = typecheck(r, Erv)
|
||||
switch r.Op {
|
||||
case ODOT, ODOTPTR:
|
||||
break
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user