Commit 34699bc7 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

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/20959Reviewed-by: default avatarDave Cheney <dave@cheney.net>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent d1b8871f
...@@ -186,7 +186,7 @@ func genhash(sym *Sym, t *Type) { ...@@ -186,7 +186,7 @@ func genhash(sym *Sym, t *Type) {
tfn.Rlist.Append(n) tfn.Rlist.Append(n)
funchdr(fn) 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 // genhash is only called for types that have equality but
// cannot be handled by the standard algorithms, // cannot be handled by the standard algorithms,
...@@ -281,7 +281,7 @@ func genhash(sym *Sym, t *Type) { ...@@ -281,7 +281,7 @@ func genhash(sym *Sym, t *Type) {
funcbody(fn) funcbody(fn)
Curfn = fn Curfn = fn
fn.Func.Dupok = true fn.Func.Dupok = true
typecheck(&fn, Etop) fn = typecheck(fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop) typecheckslice(fn.Nbody.Slice(), Etop)
Curfn = nil Curfn = nil
popdcl() popdcl()
...@@ -331,7 +331,7 @@ func hashfor(t *Type) *Node { ...@@ -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(Ptrto(t))))
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]))) tfn.Rlist.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
typecheck(&tfn, Etype) tfn = typecheck(tfn, Etype)
n.Type = tfn.Type n.Type = tfn.Type
return n return n
} }
...@@ -365,7 +365,7 @@ func geneq(sym *Sym, t *Type) { ...@@ -365,7 +365,7 @@ func geneq(sym *Sym, t *Type) {
tfn.Rlist.Append(n) tfn.Rlist.Append(n)
funchdr(fn) 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 // geneq is only called for types that have equality but
// cannot be handled by the standard algorithms, // cannot be handled by the standard algorithms,
...@@ -474,7 +474,7 @@ func geneq(sym *Sym, t *Type) { ...@@ -474,7 +474,7 @@ func geneq(sym *Sym, t *Type) {
funcbody(fn) funcbody(fn)
Curfn = fn Curfn = fn
fn.Func.Dupok = true fn.Func.Dupok = true
typecheck(&fn, Etop) fn = typecheck(fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop) typecheckslice(fn.Nbody.Slice(), Etop)
Curfn = nil Curfn = nil
popdcl() popdcl()
...@@ -516,8 +516,8 @@ func eqmem(p *Node, q *Node, field *Sym, size int64) *Node { ...@@ -516,8 +516,8 @@ func eqmem(p *Node, q *Node, field *Sym, size int64) *Node {
nx.Etype = 1 // does not escape nx.Etype = 1 // does not escape
ny := Nod(OADDR, NodSym(OXDOT, q, field), nil) ny := Nod(OADDR, NodSym(OXDOT, q, field), nil)
ny.Etype = 1 // does not escape ny.Etype = 1 // does not escape
typecheck(&nx, Erv) nx = typecheck(nx, Erv)
typecheck(&ny, Erv) ny = typecheck(ny, Erv)
fn, needsize := eqmemfunc(size, nx.Type.Type) fn, needsize := eqmemfunc(size, nx.Type.Type)
call := Nod(OCALL, fn, nil) call := Nod(OCALL, fn, nil)
...@@ -540,7 +540,7 @@ func eqmemfunc(size int64, t *Type) (fn *Node, needsize bool) { ...@@ -540,7 +540,7 @@ func eqmemfunc(size int64, t *Type) (fn *Node, needsize bool) {
fn = syslook(buf) fn = syslook(buf)
} }
substArgTypes(&fn, t, t) fn = substArgTypes(fn, t, t)
return fn, needsize return fn, needsize
} }
......
...@@ -193,7 +193,7 @@ func Export(out *obj.Biobuf, trace bool) int { ...@@ -193,7 +193,7 @@ func Export(out *obj.Biobuf, trace bool) int {
switch n := sym.Def; n.Op { switch n := sym.Def; n.Op {
case OLITERAL: case OLITERAL:
// constant // constant
typecheck(&n, Erv) n = typecheck(n, Erv)
if n == nil || n.Op != OLITERAL { if n == nil || n.Op != OLITERAL {
Fatalf("exporter: dumpexportconst: oconst nil: %v", sym) Fatalf("exporter: dumpexportconst: oconst nil: %v", sym)
} }
...@@ -201,7 +201,7 @@ func Export(out *obj.Biobuf, trace bool) int { ...@@ -201,7 +201,7 @@ func Export(out *obj.Biobuf, trace bool) int {
case ONAME: case ONAME:
// variable or function // variable or function
typecheck(&n, Erv|Ecall) n = typecheck(n, Erv|Ecall)
if n == nil || n.Type == nil { if n == nil || n.Type == nil {
Fatalf("exporter: variable/function exported but not defined: %v", sym) Fatalf("exporter: variable/function exported but not defined: %v", sym)
} }
......
...@@ -391,7 +391,7 @@ func cgen_wb(n, res *Node, wb bool) { ...@@ -391,7 +391,7 @@ func cgen_wb(n, res *Node, wb bool) {
case OMINUS: case OMINUS:
if Isfloat[nl.Type.Etype] { if Isfloat[nl.Type.Etype] {
nr = Nodintconst(-1) nr = Nodintconst(-1)
convlit(&nr, n.Type) nr = convlit(nr, n.Type)
a = Thearch.Optoas(OMUL, nl.Type) a = Thearch.Optoas(OMUL, nl.Type)
goto sbop goto sbop
} }
...@@ -803,7 +803,7 @@ func cgen_wbptr(n, res *Node) { ...@@ -803,7 +803,7 @@ func cgen_wbptr(n, res *Node) {
wbVar := syslook("writeBarrier") wbVar := syslook("writeBarrier")
wbEnabled := NodSym(ODOT, wbVar, wbVar.Type.Field(0).Sym) 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) pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst) Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)
pjmp := Gbranch(obj.AJMP, nil, 0) pjmp := Gbranch(obj.AJMP, nil, 0)
...@@ -1784,7 +1784,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { ...@@ -1784,7 +1784,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
Genlist(n.Ninit) Genlist(n.Ninit)
if n.Type == nil { if n.Type == nil {
convlit(&n, Types[TBOOL]) n = convlit(n, Types[TBOOL])
if n.Type == nil { if n.Type == nil {
return return
} }
...@@ -2866,7 +2866,7 @@ func cgen_append(n, res *Node) { ...@@ -2866,7 +2866,7 @@ func cgen_append(n, res *Node) {
Regfree(&rlen) Regfree(&rlen)
fn := syslook("growslice") fn := syslook("growslice")
substArgTypes(&fn, res.Type.Type, res.Type.Type) fn = substArgTypes(fn, res.Type.Type, res.Type.Type)
Ginscall(fn, 0) Ginscall(fn, 0)
if Widthptr == 4 && Widthreg == 8 { if Widthptr == 4 && Widthreg == 8 {
......
...@@ -97,7 +97,7 @@ func typecheckclosure(func_ *Node, top int) { ...@@ -97,7 +97,7 @@ func typecheckclosure(func_ *Node, top int) {
} }
oldfn := Curfn oldfn := Curfn
typecheck(&func_.Func.Ntype, Etype) func_.Func.Ntype = typecheck(func_.Func.Ntype, Etype)
func_.Type = func_.Func.Ntype.Type func_.Type = func_.Func.Ntype.Type
func_.Func.Top = top func_.Func.Top = top
...@@ -197,7 +197,7 @@ func makeclosure(func_ *Node) *Node { ...@@ -197,7 +197,7 @@ func makeclosure(func_ *Node) *Node {
if len(xfunc.Nbody.Slice()) == 0 { if len(xfunc.Nbody.Slice()) == 0 {
Fatalf("empty body - won't generate any code") Fatalf("empty body - won't generate any code")
} }
typecheck(&xfunc, Etop) xfunc = typecheck(xfunc, Etop)
xfunc.Func.Closure = func_ xfunc.Func.Closure = func_
func_.Func.Closure = xfunc func_.Func.Closure = xfunc
...@@ -262,7 +262,7 @@ func capturevars(xfunc *Node) { ...@@ -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)) 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) func_.Func.Enter.Append(outer)
} }
...@@ -442,7 +442,7 @@ func walkclosure(func_ *Node, init *Nodes) *Node { ...@@ -442,7 +442,7 @@ func walkclosure(func_ *Node, init *Nodes) *Node {
clos.Type = func_.Type clos.Type = func_.Type
typecheck(&clos, Erv) clos = typecheck(clos, Erv)
// typecheck will insert a PTRLIT node under CONVNOP, // typecheck will insert a PTRLIT node under CONVNOP,
// tag it with escape analysis result. // tag it with escape analysis result.
...@@ -457,7 +457,7 @@ func walkclosure(func_ *Node, init *Nodes) *Node { ...@@ -457,7 +457,7 @@ func walkclosure(func_ *Node, init *Nodes) *Node {
delete(prealloc, func_) delete(prealloc, func_)
} }
walkexpr(&clos, init) clos = walkexpr(clos, init)
return clos return clos
} }
...@@ -608,7 +608,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Sym) *Node { ...@@ -608,7 +608,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Sym) *Node {
xfunc.Nbody.Set(body) xfunc.Nbody.Set(body)
typecheck(&xfunc, Etop) xfunc = typecheck(xfunc, Etop)
sym.Def = xfunc sym.Def = xfunc
xtop = append(xtop, xfunc) xtop = append(xtop, xfunc)
Curfn = savecurfn Curfn = savecurfn
...@@ -647,7 +647,7 @@ func walkpartialcall(n *Node, init *Nodes) *Node { ...@@ -647,7 +647,7 @@ func walkpartialcall(n *Node, init *Nodes) *Node {
clos.Type = n.Type clos.Type = n.Type
typecheck(&clos, Erv) clos = typecheck(clos, Erv)
// typecheck will insert a PTRLIT node under CONVNOP, // typecheck will insert a PTRLIT node under CONVNOP,
// tag it with escape analysis result. // tag it with escape analysis result.
...@@ -662,7 +662,7 @@ func walkpartialcall(n *Node, init *Nodes) *Node { ...@@ -662,7 +662,7 @@ func walkpartialcall(n *Node, init *Nodes) *Node {
delete(prealloc, n) delete(prealloc, n)
} }
walkexpr(&clos, init) clos = walkexpr(clos, init)
return clos return clos
} }
...@@ -91,33 +91,35 @@ func truncfltlit(oldv *Mpflt, t *Type) *Mpflt { ...@@ -91,33 +91,35 @@ func truncfltlit(oldv *Mpflt, t *Type) *Mpflt {
// NegOne returns a Node of type t with value -1. // NegOne returns a Node of type t with value -1.
func NegOne(t *Type) *Node { func NegOne(t *Type) *Node {
n := Nodintconst(-1) n := Nodintconst(-1)
convlit(&n, t) n = convlit(n, t)
return n return n
} }
// convert n, if literal, to type t. // convert n, if literal, to type t.
// implicit conversion. // implicit conversion.
func convlit(np **Node, t *Type) { // The result of convlit MUST be assigned back to n, e.g.
convlit1(np, t, false) // 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. // convert n, if literal, to type t.
// return a new node if necessary // return a new node if necessary
//(if n is a named constant, can't edit n->type directly). // (if n is a named constant, can't edit n->type directly).
func convlit1(np **Node, t *Type, explicit bool) { // The result of convlit1 MUST be assigned back to n, e.g.
n := *np // 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 { if n == nil || t == nil || n.Type == nil || isideal(t) || n.Type == t {
return return n
} }
if !explicit && !isideal(n.Type) { if !explicit && !isideal(n.Type) {
return return n
} }
if n.Op == OLITERAL { if n.Op == OLITERAL {
nn := Nod(OXXX, nil, nil) nn := Nod(OXXX, nil, nil)
*nn = *n *nn = *n
n = nn n = nn
*np = n
} }
switch n.Op { switch n.Op {
...@@ -131,23 +133,22 @@ func convlit1(np **Node, t *Type, explicit bool) { ...@@ -131,23 +133,22 @@ func convlit1(np **Node, t *Type, explicit bool) {
} }
if n.Type.Etype == TIDEAL { if n.Type.Etype == TIDEAL {
convlit(&n.Left, t) n.Left = convlit(n.Left, t)
convlit(&n.Right, t) n.Right = convlit(n.Right, t)
n.Type = t n.Type = t
} }
return return n
// target is invalid type for a constant? leave alone. // target is invalid type for a constant? leave alone.
case OLITERAL: case OLITERAL:
if !okforconst[t.Etype] && n.Type.Etype != TNIL { if !okforconst[t.Etype] && n.Type.Etype != TNIL {
defaultlit(&n, nil) n = defaultlit(n, nil)
*np = n return n
return
} }
case OLSH, ORSH: 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 t = n.Left.Type
if t != nil && t.Etype == TIDEAL && n.Val().Ctype() != CTINT { if t != nil && t.Etype == TIDEAL && n.Val().Ctype() != CTINT {
n.SetVal(toint(n.Val())) n.SetVal(toint(n.Val()))
...@@ -158,7 +159,7 @@ func convlit1(np **Node, t *Type, explicit bool) { ...@@ -158,7 +159,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
} }
n.Type = t n.Type = t
return return n
case OCOMPLEX: case OCOMPLEX:
if n.Type.Etype == TIDEAL { if n.Type.Etype == TIDEAL {
...@@ -173,22 +174,22 @@ func convlit1(np **Node, t *Type, explicit bool) { ...@@ -173,22 +174,22 @@ func convlit1(np **Node, t *Type, explicit bool) {
case TCOMPLEX128: case TCOMPLEX128:
n.Type = t n.Type = t
convlit(&n.Left, Types[TFLOAT64]) n.Left = convlit(n.Left, Types[TFLOAT64])
convlit(&n.Right, Types[TFLOAT64]) n.Right = convlit(n.Right, Types[TFLOAT64])
case TCOMPLEX64: case TCOMPLEX64:
n.Type = t n.Type = t
convlit(&n.Left, Types[TFLOAT32]) n.Left = convlit(n.Left, Types[TFLOAT32])
convlit(&n.Right, Types[TFLOAT32]) n.Right = convlit(n.Right, Types[TFLOAT32])
} }
} }
return return n
} }
// avoided repeated calculations, errors // avoided repeated calculations, errors
if Eqtype(n.Type, t) { if Eqtype(n.Type, t) {
return return n
} }
ct := consttype(n) ct := consttype(n)
...@@ -201,11 +202,11 @@ func convlit1(np **Node, t *Type, explicit bool) { ...@@ -201,11 +202,11 @@ func convlit1(np **Node, t *Type, explicit bool) {
if et == TINTER { if et == TINTER {
if ct == CTNIL && n.Type == Types[TNIL] { if ct == CTNIL && n.Type == Types[TNIL] {
n.Type = t n.Type = t
return return n
} }
defaultlit(np, nil) n = defaultlit(n, nil)
return return n
} }
switch ct { switch ct {
...@@ -220,7 +221,7 @@ func convlit1(np **Node, t *Type, explicit bool) { ...@@ -220,7 +221,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
// let normal conversion code handle it // let normal conversion code handle it
case TSTRING: case TSTRING:
return return n
case TARRAY: case TARRAY:
if !Isslice(t) { if !Isslice(t) {
...@@ -301,7 +302,7 @@ func convlit1(np **Node, t *Type, explicit bool) { ...@@ -301,7 +302,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
} }
n.Type = t n.Type = t
return return n
bad: bad:
if n.Diag == 0 { if n.Diag == 0 {
...@@ -312,9 +313,9 @@ bad: ...@@ -312,9 +313,9 @@ bad:
} }
if isideal(n.Type) { if isideal(n.Type) {
defaultlit(&n, nil) n = defaultlit(n, nil)
*np = n
} }
return n
} }
func copyval(v Val) Val { func copyval(v Val) Val {
...@@ -667,7 +668,7 @@ func evconst(n *Node) { ...@@ -667,7 +668,7 @@ func evconst(n *Node) {
OCONV_ | CTFLT_, OCONV_ | CTFLT_,
OCONV_ | CTSTR_, OCONV_ | CTSTR_,
OCONV_ | CTBOOL_: OCONV_ | CTBOOL_:
convlit1(&nl, n.Type, true) nl = convlit1(nl, n.Type, true)
v = nl.Val() v = nl.Val()
...@@ -748,12 +749,12 @@ func evconst(n *Node) { ...@@ -748,12 +749,12 @@ func evconst(n *Node) {
// ideal const mixes with anything but otherwise must match. // ideal const mixes with anything but otherwise must match.
default: default:
if nl.Type.Etype != TIDEAL { if nl.Type.Etype != TIDEAL {
defaultlit(&nr, nl.Type) nr = defaultlit(nr, nl.Type)
n.Right = nr n.Right = nr
} }
if nr.Type.Etype != TIDEAL { if nr.Type.Etype != TIDEAL {
defaultlit(&nl, nr.Type) nl = defaultlit(nl, nr.Type)
n.Left = nl n.Left = nl
} }
...@@ -764,7 +765,7 @@ func evconst(n *Node) { ...@@ -764,7 +765,7 @@ func evconst(n *Node) {
// right must be unsigned. // right must be unsigned.
// left can be ideal. // left can be ideal.
case OLSH, ORSH: case OLSH, ORSH:
defaultlit(&nr, Types[TUINT]) nr = defaultlit(nr, Types[TUINT])
n.Right = nr n.Right = nr
if nr.Type != nil && (Issigned[nr.Type.Etype] || !Isint[nr.Type.Etype]) { if nr.Type != nil && (Issigned[nr.Type.Etype] || !Isint[nr.Type.Etype]) {
...@@ -1244,17 +1245,17 @@ func idealkind(n *Node) Ctype { ...@@ -1244,17 +1245,17 @@ func idealkind(n *Node) Ctype {
} }
} }
func defaultlit(np **Node, t *Type) { // The result of defaultlit MUST be assigned back to n, e.g.
n := *np // n.Left = defaultlit(n.Left, t)
func defaultlit(n *Node, t *Type) *Node {
if n == nil || !isideal(n.Type) { if n == nil || !isideal(n.Type) {
return return n
} }
if n.Op == OLITERAL { if n.Op == OLITERAL {
nn := Nod(OXXX, nil, nil) nn := Nod(OXXX, nil, nil)
*nn = *n *nn = *n
n = nn n = nn
*np = n
} }
lno := setlineno(n) lno := setlineno(n)
...@@ -1263,8 +1264,8 @@ func defaultlit(np **Node, t *Type) { ...@@ -1263,8 +1264,8 @@ func defaultlit(np **Node, t *Type) {
switch ctype { switch ctype {
default: default:
if t != nil { if t != nil {
convlit(np, t) n = convlit(n, t)
return return n
} }
if n.Val().Ctype() == CTNIL { if n.Val().Ctype() == CTNIL {
...@@ -1280,7 +1281,7 @@ func defaultlit(np **Node, t *Type) { ...@@ -1280,7 +1281,7 @@ func defaultlit(np **Node, t *Type) {
if n.Val().Ctype() == CTSTR { if n.Val().Ctype() == CTSTR {
t1 := Types[TSTRING] t1 := Types[TSTRING]
convlit(np, t1) n = convlit(n, t1)
break break
} }
...@@ -1294,7 +1295,7 @@ func defaultlit(np **Node, t *Type) { ...@@ -1294,7 +1295,7 @@ func defaultlit(np **Node, t *Type) {
if t != nil && t.Etype == TBOOL { if t != nil && t.Etype == TBOOL {
t1 = t t1 = t
} }
convlit(np, t1) n = convlit(n, t1)
case CTINT: case CTINT:
t1 = Types[TINT] t1 = Types[TINT]
...@@ -1314,7 +1315,7 @@ func defaultlit(np **Node, t *Type) { ...@@ -1314,7 +1315,7 @@ func defaultlit(np **Node, t *Type) {
} }
lineno = lno lineno = lno
return return n
num: num:
// Note: n.Val().Ctype() can be CTxxx (not a constant) here // Note: n.Val().Ctype() can be CTxxx (not a constant) here
...@@ -1339,62 +1340,64 @@ num: ...@@ -1339,62 +1340,64 @@ num:
if n.Val().Ctype() != CTxxx { if n.Val().Ctype() != CTxxx {
overflow(n.Val(), t1) overflow(n.Val(), t1)
} }
convlit(np, t1) n = convlit(n, t1)
lineno = lno lineno = lno
return return n
} }
// defaultlit on both nodes simultaneously; // defaultlit on both nodes simultaneously;
// if they're both ideal going in they better // if they're both ideal going in they better
// get the same type going out. // get the same type going out.
// force means must assign concrete (non-ideal) type. // force means must assign concrete (non-ideal) type.
func defaultlit2(lp **Node, rp **Node, force bool) { // The results of defaultlit2 MUST be assigned back to l and r, e.g.
l := *lp // n.Left, n.Right = defaultlit2(n.Left, n.Right, force)
r := *rp func defaultlit2(l *Node, r *Node, force bool) (*Node, *Node) {
if l.Type == nil || r.Type == nil { if l.Type == nil || r.Type == nil {
return return l, r
} }
if !isideal(l.Type) { if !isideal(l.Type) {
convlit(rp, l.Type) r = convlit(r, l.Type)
return return l, r
} }
if !isideal(r.Type) { if !isideal(r.Type) {
convlit(lp, r.Type) l = convlit(l, r.Type)
return return l, r
} }
if !force { if !force {
return return l, r
} }
if l.Type.Etype == TBOOL { if l.Type.Etype == TBOOL {
convlit(lp, Types[TBOOL]) l = convlit(l, Types[TBOOL])
convlit(rp, Types[TBOOL]) r = convlit(r, Types[TBOOL])
} }
lkind := idealkind(l) lkind := idealkind(l)
rkind := idealkind(r) rkind := idealkind(r)
if lkind == CTCPLX || rkind == CTCPLX { if lkind == CTCPLX || rkind == CTCPLX {
convlit(lp, Types[TCOMPLEX128]) l = convlit(l, Types[TCOMPLEX128])
convlit(rp, Types[TCOMPLEX128]) r = convlit(r, Types[TCOMPLEX128])
return return l, r
} }
if lkind == CTFLT || rkind == CTFLT { if lkind == CTFLT || rkind == CTFLT {
convlit(lp, Types[TFLOAT64]) l = convlit(l, Types[TFLOAT64])
convlit(rp, Types[TFLOAT64]) r = convlit(r, Types[TFLOAT64])
return return l, r
} }
if lkind == CTRUNE || rkind == CTRUNE { if lkind == CTRUNE || rkind == CTRUNE {
convlit(lp, runetype) l = convlit(l, runetype)
convlit(rp, runetype) r = convlit(r, runetype)
return return l, r
} }
convlit(lp, Types[TINT]) l = convlit(l, Types[TINT])
convlit(rp, Types[TINT]) r = convlit(r, Types[TINT])
return l, r
} }
// strlit returns the value of a literal string Node as a string. // strlit returns the value of a literal string Node as a string.
......
...@@ -750,7 +750,7 @@ func structfield(n *Node) *Field { ...@@ -750,7 +750,7 @@ func structfield(n *Node) *Field {
f.Isddd = n.Isddd f.Isddd = n.Isddd
if n.Right != nil { if n.Right != nil {
typecheck(&n.Right, Etype) n.Right = typecheck(n.Right, Etype)
n.Type = n.Right.Type n.Type = n.Right.Type
if n.Left != nil { if n.Left != nil {
n.Left.Type = n.Type n.Left.Type = n.Type
...@@ -904,7 +904,7 @@ func interfacefield(n *Node) *Field { ...@@ -904,7 +904,7 @@ func interfacefield(n *Node) *Field {
f.Sym = f.Nname.Sym f.Sym = f.Nname.Sym
} }
} else { } else {
typecheck(&n.Right, Etype) n.Right = typecheck(n.Right, Etype)
n.Type = n.Right.Type n.Type = n.Right.Type
if n.Embedded != 0 { if n.Embedded != 0 {
......
...@@ -912,7 +912,7 @@ func esc(e *EscState, n *Node, up *Node) { ...@@ -912,7 +912,7 @@ func esc(e *EscState, n *Node, up *Node) {
a = Nod(OADDR, a, nil) a = Nod(OADDR, a, nil)
a.Lineno = v.Lineno a.Lineno = v.Lineno
e.nodeEscState(a).Escloopdepth = e.loopdepth e.nodeEscState(a).Escloopdepth = e.loopdepth
typecheck(&a, Erv) a = typecheck(a, Erv)
} }
escassignNilWhy(e, n, a, "captured by a closure") escassignNilWhy(e, n, a, "captured by a closure")
......
...@@ -226,7 +226,7 @@ func reexportdep(n *Node) { ...@@ -226,7 +226,7 @@ func reexportdep(n *Node) {
func dumpexportconst(s *Sym) { func dumpexportconst(s *Sym) {
n := s.Def n := s.Def
typecheck(&n, Erv) n = typecheck(n, Erv)
if n == nil || n.Op != OLITERAL { if n == nil || n.Op != OLITERAL {
Fatalf("dumpexportconst: oconst nil: %v", s) Fatalf("dumpexportconst: oconst nil: %v", s)
} }
...@@ -243,7 +243,7 @@ func dumpexportconst(s *Sym) { ...@@ -243,7 +243,7 @@ func dumpexportconst(s *Sym) {
func dumpexportvar(s *Sym) { func dumpexportvar(s *Sym) {
n := s.Def n := s.Def
typecheck(&n, Erv|Ecall) n = typecheck(n, Erv|Ecall)
if n == nil || n.Type == nil { if n == nil || n.Type == nil {
Yyerror("variable exported but not defined: %v", s) Yyerror("variable exported but not defined: %v", s)
return return
...@@ -511,7 +511,7 @@ func importimport(s *Sym, path string) { ...@@ -511,7 +511,7 @@ func importimport(s *Sym, path string) {
func importconst(s *Sym, t *Type, n *Node) { func importconst(s *Sym, t *Type, n *Node) {
importsym(s, OLITERAL) importsym(s, OLITERAL)
convlit(&n, t) n = convlit(n, t)
if s.Def != nil { // TODO: check if already the same. if s.Def != nil { // TODO: check if already the same.
return return
......
...@@ -177,7 +177,7 @@ func fninit(n []*Node) { ...@@ -177,7 +177,7 @@ func fninit(n []*Node) {
funcbody(fn) funcbody(fn)
Curfn = fn Curfn = fn
typecheck(&fn, Etop) fn = typecheck(fn, Etop)
typecheckslice(r, Etop) typecheckslice(r, Etop)
Curfn = nil Curfn = nil
funccompile(fn) funccompile(fn)
......
...@@ -269,7 +269,7 @@ func inlcopy(n *Node) *Node { ...@@ -269,7 +269,7 @@ func inlcopy(n *Node) *Node {
func inlcalls(fn *Node) { func inlcalls(fn *Node) {
savefn := Curfn savefn := Curfn
Curfn = fn Curfn = fn
inlnode(&fn) fn = inlnode(fn)
if fn != Curfn { if fn != Curfn {
Fatalf("inlnode replaced curfn") Fatalf("inlnode replaced curfn")
} }
...@@ -288,11 +288,12 @@ func inlconv2stmt(n *Node) { ...@@ -288,11 +288,12 @@ func inlconv2stmt(n *Node) {
} }
// Turn an OINLCALL into a single valued expression. // Turn an OINLCALL into a single valued expression.
func inlconv2expr(np **Node) { // The result of inlconv2expr MUST be assigned back to n, e.g.
n := *np // n.Left = inlconv2expr(n.Left)
func inlconv2expr(n *Node) *Node {
r := n.Rlist.First() r := n.Rlist.First()
addinit(&r, append(n.Ninit.Slice(), n.Nbody.Slice()...)) r = addinit(r, append(n.Ninit.Slice(), n.Nbody.Slice()...))
*np = r return r
} }
// Turn the rlist (with the return values) of the OINLCALL in // Turn the rlist (with the return values) of the OINLCALL in
...@@ -306,14 +307,14 @@ func inlconv2list(n *Node) []*Node { ...@@ -306,14 +307,14 @@ func inlconv2list(n *Node) []*Node {
} }
s := n.Rlist.Slice() 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 return s
} }
func inlnodelist(l Nodes) { func inlnodelist(l Nodes) {
s := l.Slice() s := l.Slice()
for i := range s { for i := range s {
inlnode(&s[i]) s[i] = inlnode(s[i])
} }
} }
...@@ -328,13 +329,13 @@ func inlnodelist(l Nodes) { ...@@ -328,13 +329,13 @@ func inlnodelist(l Nodes) {
// have to edit /this/ n, so you'd have to push that one down as well, // 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 // but then you may as well do it here. so this is cleaner and
// shorter and less complicated. // shorter and less complicated.
func inlnode(np **Node) { // The result of inlnode MUST be assigned back to n, e.g.
if *np == nil { // n.Left = inlnode(n.Left)
return func inlnode(n *Node) *Node {
if n == nil {
return n
} }
n := *np
switch n.Op { switch n.Op {
// inhibit inlining of their argument // inhibit inlining of their argument
case ODEFER, OPROC: case ODEFER, OPROC:
...@@ -348,7 +349,7 @@ func inlnode(np **Node) { ...@@ -348,7 +349,7 @@ func inlnode(np **Node) {
// TODO do them here (or earlier), // TODO do them here (or earlier),
// so escape analysis can avoid more heapmoves. // so escape analysis can avoid more heapmoves.
case OCLOSURE: case OCLOSURE:
return return n
} }
lno := setlineno(n) lno := setlineno(n)
...@@ -360,17 +361,17 @@ func inlnode(np **Node) { ...@@ -360,17 +361,17 @@ func inlnode(np **Node) {
} }
} }
inlnode(&n.Left) n.Left = inlnode(n.Left)
if n.Left != nil && n.Left.Op == OINLCALL { 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.Right != nil && n.Right.Op == OINLCALL {
if n.Op == OFOR { if n.Op == OFOR {
inlconv2stmt(n.Right) inlconv2stmt(n.Right)
} else { } else {
inlconv2expr(&n.Right) n.Right = inlconv2expr(n.Right)
} }
} }
...@@ -401,7 +402,7 @@ func inlnode(np **Node) { ...@@ -401,7 +402,7 @@ func inlnode(np **Node) {
s := n.List.Slice() s := n.List.Slice()
for i1, n1 := range s { for i1, n1 := range s {
if n1.Op == OINLCALL { if n1.Op == OINLCALL {
inlconv2expr(&s[i1]) s[i1] = inlconv2expr(s[i1])
} }
} }
} }
...@@ -413,7 +414,7 @@ func inlnode(np **Node) { ...@@ -413,7 +414,7 @@ func inlnode(np **Node) {
n.Rlist.Set(inlconv2list(n.Rlist.First())) n.Rlist.Set(inlconv2list(n.Rlist.First()))
n.Op = OAS2 n.Op = OAS2
n.Typecheck = 0 n.Typecheck = 0
typecheck(np, Etop) n = typecheck(n, Etop)
break break
} }
fallthrough fallthrough
...@@ -425,7 +426,7 @@ func inlnode(np **Node) { ...@@ -425,7 +426,7 @@ func inlnode(np **Node) {
if n.Op == OIF { if n.Op == OIF {
inlconv2stmt(n1) inlconv2stmt(n1)
} else { } else {
inlconv2expr(&s[i1]) s[i1] = inlconv2expr(s[i1])
} }
} }
} }
...@@ -445,7 +446,7 @@ func inlnode(np **Node) { ...@@ -445,7 +446,7 @@ func inlnode(np **Node) {
case OCALLFUNC, OCALLMETH: case OCALLFUNC, OCALLMETH:
// TODO(marvin): Fix Node.EType type union. // TODO(marvin): Fix Node.EType type union.
if n.Etype == EType(OPROC) || n.Etype == EType(ODEFER) { if n.Etype == EType(OPROC) || n.Etype == EType(ODEFER) {
return return n
} }
} }
...@@ -455,10 +456,10 @@ func inlnode(np **Node) { ...@@ -455,10 +456,10 @@ func inlnode(np **Node) {
fmt.Printf("%v:call to func %v\n", n.Line(), Nconv(n.Left, FmtSign)) 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 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 } 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 { 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) { ...@@ -476,13 +477,16 @@ func inlnode(np **Node) {
Fatalf("no function definition for [%p] %v\n", n.Left.Type, Tconv(n.Left.Type, FmtSign)) 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 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 save_safemode := safemode
// imported functions may refer to unsafe as long as the // imported functions may refer to unsafe as long as the
...@@ -492,8 +496,9 @@ func mkinlcall(np **Node, fn *Node, isddd bool) { ...@@ -492,8 +496,9 @@ func mkinlcall(np **Node, fn *Node, isddd bool) {
if pkg != localpkg && pkg != nil { if pkg != localpkg && pkg != nil {
safemode = 0 safemode = 0
} }
mkinlcall1(np, fn, isddd) n = mkinlcall1(n, fn, isddd)
safemode = save_safemode safemode = save_safemode
return n
} }
func tinlvar(t *Field) *Node { func tinlvar(t *Field) *Node {
...@@ -504,7 +509,7 @@ func tinlvar(t *Field) *Node { ...@@ -504,7 +509,7 @@ func tinlvar(t *Field) *Node {
return t.Nname.Name.Inlvar return t.Nname.Name.Inlvar
} }
typecheck(&nblank, Erv|Easgn) nblank = typecheck(nblank, Erv|Easgn)
return nblank return nblank
} }
...@@ -514,22 +519,22 @@ var inlgen int ...@@ -514,22 +519,22 @@ var inlgen int
// On return ninit has the parameter assignments, the nbody is the // On return ninit has the parameter assignments, the nbody is the
// inlined function body and list, rlist contain the input, output // inlined function body and list, rlist contain the input, output
// parameters. // 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. // For variadic fn.
if len(fn.Func.Inl.Slice()) == 0 { if len(fn.Func.Inl.Slice()) == 0 {
return return n
} }
if fn == Curfn || fn.Name.Defn == Curfn { if fn == Curfn || fn.Name.Defn == Curfn {
return return n
} }
if Debug['l'] < 2 { if Debug['l'] < 2 {
typecheckinl(fn) typecheckinl(fn)
} }
n := *np
// Bingo, we have a function node, and it has an inlineable body // Bingo, we have a function node, and it has an inlineable body
if Debug['m'] > 1 { 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)) 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) { ...@@ -566,7 +571,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
ln.Name.Inlvar = inlvar(ln) ln.Name.Inlvar = inlvar(ln)
// Typecheck because inlvar is not necessarily a function parameter. // 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 { if ln.Class&^PHEAP != PAUTO {
ninit.Append(Nod(ODCL, ln.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs 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) { ...@@ -579,7 +584,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
for _, t := range fn.Type.Results().Fields().Slice() { for _, t := range fn.Type.Results().Fields().Slice() {
if t != nil && t.Nname != nil && !isblank(t.Nname) { if t != nil && t.Nname != nil && !isblank(t.Nname) {
m = inlvar(t.Nname) m = inlvar(t.Nname)
typecheck(&m, Erv) m = typecheck(m, Erv)
t.Nname.Name.Inlvar = m t.Nname.Name.Inlvar = m
} else { } else {
// anonymous return values, synthesize names for use in assignment that replaces return // anonymous return values, synthesize names for use in assignment that replaces return
...@@ -607,7 +612,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -607,7 +612,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
} }
as := Nod(OAS, tinlvar(t), n.Left.Left) as := Nod(OAS, tinlvar(t), n.Left.Left)
if as != nil { if as != nil {
typecheck(&as, Etop) as = typecheck(as, Etop)
ninit.Append(as) ninit.Append(as)
} }
} }
...@@ -734,7 +739,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -734,7 +739,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
} }
if as.Rlist.Len() != 0 { if as.Rlist.Len() != 0 {
typecheck(&as, Etop) as = typecheck(as, Etop)
ninit.Append(as) ninit.Append(as)
} }
...@@ -754,14 +759,14 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -754,14 +759,14 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil)) as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil))
} }
typecheck(&as, Etop) as = typecheck(as, Etop)
ninit.Append(as) ninit.Append(as)
} }
// zero the outparams // zero the outparams
for _, n := range retvars { for _, n := range retvars {
as = Nod(OAS, n, nil) as = Nod(OAS, n, nil)
typecheck(&as, Etop) as = typecheck(as, Etop)
ninit.Append(as) ninit.Append(as)
} }
...@@ -801,7 +806,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -801,7 +806,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
//dumplist("call body", body); //dumplist("call body", body);
*np = call n = call
// transitive inlining // transitive inlining
// might be nice to do this before exporting the body, // might be nice to do this before exporting the body,
...@@ -820,8 +825,10 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -820,8 +825,10 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
fn.Func.Inl.Set(body) fn.Func.Inl.Set(body)
if Debug['m'] > 2 { 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, // Every time we expand a function we generate a new set of tmpnames,
...@@ -945,12 +952,12 @@ func (subst *inlsubst) node(n *Node) *Node { ...@@ -945,12 +952,12 @@ func (subst *inlsubst) node(n *Node) *Node {
as.List.Append(n) as.List.Append(n)
} }
as.Rlist.Set(subst.list(n.List)) as.Rlist.Set(subst.list(n.List))
typecheck(&as, Etop) as = typecheck(as, Etop)
m.Ninit.Append(as) m.Ninit.Append(as)
} }
typecheckslice(m.Ninit.Slice(), Etop) typecheckslice(m.Ninit.Slice(), Etop)
typecheck(&m, Etop) m = typecheck(m, Etop)
// dump("Return after substitution", m); // dump("Return after substitution", m);
return m return m
......
...@@ -371,7 +371,7 @@ func Main() { ...@@ -371,7 +371,7 @@ func Main() {
// Don't use range--typecheck can add closures to xtop. // Don't use range--typecheck can add closures to xtop.
for i := 0; i < len(xtop); i++ { for i := 0; i < len(xtop); i++ {
if xtop[i].Op != ODCL && xtop[i].Op != OAS && xtop[i].Op != OAS2 { 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() { ...@@ -381,7 +381,7 @@ func Main() {
// Don't use range--typecheck can add closures to xtop. // Don't use range--typecheck can add closures to xtop.
for i := 0; i < len(xtop); i++ { for i := 0; i < len(xtop); i++ {
if xtop[i].Op == ODCL || xtop[i].Op == OAS || xtop[i].Op == OAS2 { if xtop[i].Op == ODCL || xtop[i].Op == OAS || xtop[i].Op == OAS2 {
typecheck(&xtop[i], Etop) xtop[i] = typecheck(xtop[i], Etop)
} }
} }
resumecheckwidth() resumecheckwidth()
...@@ -488,7 +488,7 @@ func Main() { ...@@ -488,7 +488,7 @@ func Main() {
// Phase 9: Check external declarations. // Phase 9: Check external declarations.
for i, n := range externdcl { for i, n := range externdcl {
if n.Op == ONAME { 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 { ...@@ -63,7 +63,7 @@ func ordertemp(t *Type, order *Order, clear bool) *Node {
var_ := temp(t) var_ := temp(t)
if clear { if clear {
a := Nod(OAS, var_, nil) a := Nod(OAS, var_, nil)
typecheck(&a, Etop) a = typecheck(a, Etop)
order.out = append(order.out, a) order.out = append(order.out, a)
} }
...@@ -86,7 +86,7 @@ func ordertemp(t *Type, order *Order, clear bool) *Node { ...@@ -86,7 +86,7 @@ func ordertemp(t *Type, order *Order, clear bool) *Node {
func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node { func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node {
var_ := ordertemp(t, order, clear != 0) var_ := ordertemp(t, order, clear != 0)
a := Nod(OAS, var_, n) a := Nod(OAS, var_, n)
typecheck(&a, Etop) a = typecheck(a, Etop)
order.out = append(order.out, a) order.out = append(order.out, a)
return var_ return var_
} }
...@@ -111,7 +111,7 @@ func ordercheapexpr(n *Node, order *Order) *Node { ...@@ -111,7 +111,7 @@ func ordercheapexpr(n *Node, order *Order) *Node {
*a = *n *a = *n
a.Orig = a a.Orig = a
a.Left = l a.Left = l
typecheck(&a, Erv) a = typecheck(a, Erv)
return a return a
} }
...@@ -139,7 +139,7 @@ func ordersafeexpr(n *Node, order *Order) *Node { ...@@ -139,7 +139,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
*a = *n *a = *n
a.Orig = a a.Orig = a
a.Left = l a.Left = l
typecheck(&a, Erv) a = typecheck(a, Erv)
return a return a
case ODOTPTR, OIND: case ODOTPTR, OIND:
...@@ -151,7 +151,7 @@ func ordersafeexpr(n *Node, order *Order) *Node { ...@@ -151,7 +151,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
*a = *n *a = *n
a.Orig = a a.Orig = a
a.Left = l a.Left = l
typecheck(&a, Erv) a = typecheck(a, Erv)
return a return a
case OINDEX, OINDEXMAP: case OINDEX, OINDEXMAP:
...@@ -170,7 +170,7 @@ func ordersafeexpr(n *Node, order *Order) *Node { ...@@ -170,7 +170,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
a.Orig = a a.Orig = a
a.Left = l a.Left = l
a.Right = r a.Right = r
typecheck(&a, Erv) a = typecheck(a, Erv)
return a return a
} }
...@@ -199,12 +199,11 @@ func isaddrokay(n *Node) bool { ...@@ -199,12 +199,11 @@ func isaddrokay(n *Node) bool {
// Orderaddrtemp ensures that *np is okay to pass by address to runtime routines. // 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 // If the original argument *np is not okay, orderaddrtemp creates a tmp, emits
// tmp = *np, and then sets *np to the tmp variable. // tmp = *np, and then sets *np to the tmp variable.
func orderaddrtemp(np **Node, order *Order) { func orderaddrtemp(n *Node, order *Order) *Node {
n := *np
if isaddrokay(n) { if isaddrokay(n) {
return return n
} }
*np = ordercopyexpr(n, n.Type, order, 0) return ordercopyexpr(n, n.Type, order, 0)
} }
type ordermarker int type ordermarker int
...@@ -232,11 +231,11 @@ func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) { ...@@ -232,11 +231,11 @@ func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) {
n.Name.Keepalive = false n.Name.Keepalive = false
n.Addrtaken = true // ensure SSA keeps the n variable n.Addrtaken = true // ensure SSA keeps the n variable
kill = Nod(OVARLIVE, n, nil) kill = Nod(OVARLIVE, n, nil)
typecheck(&kill, Etop) kill = typecheck(kill, Etop)
*out = append(*out, kill) *out = append(*out, kill)
} }
kill = Nod(OVARKILL, n, nil) kill = Nod(OVARKILL, n, nil)
typecheck(&kill, Etop) kill = typecheck(kill, Etop)
*out = append(*out, kill) *out = append(*out, kill)
} }
} }
...@@ -277,28 +276,29 @@ func orderblockNodes(n *Nodes) { ...@@ -277,28 +276,29 @@ func orderblockNodes(n *Nodes) {
// Orderexprinplace orders the side effects in *np and // Orderexprinplace orders the side effects in *np and
// leaves them as the init list of the final *np. // leaves them as the init list of the final *np.
func orderexprinplace(np **Node, outer *Order) { // The result of orderexprinplace MUST be assigned back to n, e.g.
n := *np // n.Left = orderexprinplace(n.Left, outer)
func orderexprinplace(n *Node, outer *Order) *Node {
var order Order var order Order
orderexpr(&n, &order, nil) n = orderexpr(n, &order, nil)
addinit(&n, order.out) n = addinit(n, order.out)
// insert new temporaries from order // insert new temporaries from order
// at head of outer list. // at head of outer list.
outer.temp = append(outer.temp, order.temp...) outer.temp = append(outer.temp, order.temp...)
return n
*np = n
} }
// Orderstmtinplace orders the side effects of the single statement *np // Orderstmtinplace orders the side effects of the single statement *np
// and replaces it with the resulting statement list. // and replaces it with the resulting statement list.
func orderstmtinplace(np **Node) { // The result of orderstmtinplace MUST be assigned back to n, e.g.
n := *np // n.Left = orderstmtinplace(n.Left)
func orderstmtinplace(n *Node) *Node {
var order Order var order Order
mark := marktemp(&order) mark := marktemp(&order)
orderstmt(n, &order) orderstmt(n, &order)
cleantemp(mark, &order) cleantemp(mark, &order)
*np = liststmt(order.out) return liststmt(order.out)
} }
// Orderinit moves n's init list to order->out. // Orderinit moves n's init list to order->out.
...@@ -347,7 +347,7 @@ func copyret(n *Node, order *Order) []*Node { ...@@ -347,7 +347,7 @@ func copyret(n *Node, order *Order) []*Node {
as := Nod(OAS2, nil, nil) as := Nod(OAS2, nil, nil)
as.List.Set(l1) as.List.Set(l1)
as.Rlist.Set1(n) as.Rlist.Set1(n)
typecheck(&as, Etop) as = typecheck(as, Etop)
orderstmt(as, order) orderstmt(as, order)
return l2 return l2
...@@ -366,8 +366,8 @@ func ordercallargs(l *Nodes, order *Order) { ...@@ -366,8 +366,8 @@ func ordercallargs(l *Nodes, order *Order) {
// Ordercall orders the call expression n. // Ordercall orders the call expression n.
// n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY. // n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
func ordercall(n *Node, order *Order) { func ordercall(n *Node, order *Order) {
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right, order, nil) // ODDDARG temp n.Right = orderexpr(n.Right, order, nil) // ODDDARG temp
ordercallargs(&n.List, order) ordercallargs(&n.List, order)
if n.Op == OCALLFUNC { if n.Op == OCALLFUNC {
...@@ -434,7 +434,7 @@ func ordermapassign(n *Node, order *Order) { ...@@ -434,7 +434,7 @@ func ordermapassign(n *Node, order *Order) {
m := n.Left m := n.Left
n.Left = ordertemp(m.Type, order, false) n.Left = ordertemp(m.Type, order, false)
a := Nod(OAS, m, n.Left) a := Nod(OAS, m, n.Left)
typecheck(&a, Etop) a = typecheck(a, Etop)
order.out = append(order.out, a) order.out = append(order.out, a)
} }
...@@ -453,14 +453,14 @@ func ordermapassign(n *Node, order *Order) { ...@@ -453,14 +453,14 @@ func ordermapassign(n *Node, order *Order) {
} }
n.List.SetIndex(i1, ordertemp(m.Type, order, false)) n.List.SetIndex(i1, ordertemp(m.Type, order, false))
a = Nod(OAS, m, n.List.Index(i1)) a = Nod(OAS, m, n.List.Index(i1))
typecheck(&a, Etop) a = typecheck(a, Etop)
post = append(post, a) post = append(post, a)
} else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Index(i1)) { } else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Index(i1)) {
m = n.List.Index(i1) m = n.List.Index(i1)
t := ordertemp(m.Type, order, false) t := ordertemp(m.Type, order, false)
n.List.SetIndex(i1, t) n.List.SetIndex(i1, t)
a = Nod(OAS, m, t) a = Nod(OAS, m, t)
typecheck(&a, Etop) a = typecheck(a, Etop)
post = append(post, a) post = append(post, a)
} }
} }
...@@ -491,8 +491,8 @@ func orderstmt(n *Node, order *Order) { ...@@ -491,8 +491,8 @@ func orderstmt(n *Node, order *Order) {
case OAS: case OAS:
t := marktemp(order) t := marktemp(order)
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right, order, n.Left) n.Right = orderexpr(n.Right, order, n.Left)
ordermapassign(n, order) ordermapassign(n, order)
cleantemp(t, order) cleantemp(t, order)
...@@ -504,8 +504,8 @@ func orderstmt(n *Node, order *Order) { ...@@ -504,8 +504,8 @@ func orderstmt(n *Node, order *Order) {
ORECOVER, ORECOVER,
ORECV: ORECV:
t := marktemp(order) t := marktemp(order)
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right, order, nil) n.Right = orderexpr(n.Right, order, nil)
orderexprlist(n.List, order) orderexprlist(n.List, order)
orderexprlist(n.Rlist, order) orderexprlist(n.Rlist, order)
switch n.Op { switch n.Op {
...@@ -524,7 +524,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -524,7 +524,7 @@ func orderstmt(n *Node, order *Order) {
// a map index expression. // a map index expression.
t := marktemp(order) t := marktemp(order)
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
n.Left = ordersafeexpr(n.Left, order) n.Left = ordersafeexpr(n.Left, order)
tmp1 := treecopy(n.Left, 0) tmp1 := treecopy(n.Left, 0)
if tmp1.Op == OINDEXMAP { if tmp1.Op == OINDEXMAP {
...@@ -533,8 +533,8 @@ func orderstmt(n *Node, order *Order) { ...@@ -533,8 +533,8 @@ func orderstmt(n *Node, order *Order) {
tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0) tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
// TODO(marvin): Fix Node.EType type union. // TODO(marvin): Fix Node.EType type union.
n.Right = Nod(Op(n.Etype), tmp1, n.Right) n.Right = Nod(Op(n.Etype), tmp1, n.Right)
typecheck(&n.Right, Erv) n.Right = typecheck(n.Right, Erv)
orderexpr(&n.Right, order, nil) n.Right = orderexpr(n.Right, order, nil)
n.Etype = 0 n.Etype = 0
n.Op = OAS n.Op = OAS
ordermapassign(n, order) ordermapassign(n, order)
...@@ -547,14 +547,14 @@ func orderstmt(n *Node, order *Order) { ...@@ -547,14 +547,14 @@ func orderstmt(n *Node, order *Order) {
orderexprlist(n.List, order) orderexprlist(n.List, order)
r := n.Rlist.First() r := n.Rlist.First()
orderexpr(&r.Left, order, nil) r.Left = orderexpr(r.Left, order, nil)
orderexpr(&r.Right, order, nil) r.Right = orderexpr(r.Right, order, nil)
// See case OINDEXMAP below. // See case OINDEXMAP below.
if r.Right.Op == OARRAYBYTESTR { if r.Right.Op == OARRAYBYTESTR {
r.Right.Op = OARRAYBYTESTRTMP r.Right.Op = OARRAYBYTESTRTMP
} }
orderaddrtemp(&r.Right, order) r.Right = orderaddrtemp(r.Right, order)
ordermapassign(n, order) ordermapassign(n, order)
cleantemp(t, order) cleantemp(t, order)
...@@ -574,7 +574,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -574,7 +574,7 @@ func orderstmt(n *Node, order *Order) {
t := marktemp(order) t := marktemp(order)
orderexprlist(n.List, 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()) { if isblank(n.List.First()) {
order.out = append(order.out, n) order.out = append(order.out, n)
} else { } else {
...@@ -582,7 +582,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -582,7 +582,7 @@ func orderstmt(n *Node, order *Order) {
tmp1 := ordertemp(typ, order, haspointers(typ)) tmp1 := ordertemp(typ, order, haspointers(typ))
order.out = append(order.out, n) order.out = append(order.out, n)
r := Nod(OAS, n.List.First(), tmp1) r := Nod(OAS, n.List.First(), tmp1)
typecheck(&r, Etop) r = typecheck(r, Etop)
ordermapassign(r, order) ordermapassign(r, order)
n.List.Set([]*Node{tmp1, n.List.Second()}) n.List.Set([]*Node{tmp1, n.List.Second()})
} }
...@@ -595,7 +595,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -595,7 +595,7 @@ func orderstmt(n *Node, order *Order) {
t := marktemp(order) t := marktemp(order)
orderexprlist(n.List, 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 ch := n.Rlist.First().Left.Type
tmp1 := ordertemp(ch.Type, order, haspointers(ch.Type)) tmp1 := ordertemp(ch.Type, order, haspointers(ch.Type))
var tmp2 *Node var tmp2 *Node
...@@ -606,10 +606,10 @@ func orderstmt(n *Node, order *Order) { ...@@ -606,10 +606,10 @@ func orderstmt(n *Node, order *Order) {
} }
order.out = append(order.out, n) order.out = append(order.out, n)
r := Nod(OAS, n.List.First(), tmp1) r := Nod(OAS, n.List.First(), tmp1)
typecheck(&r, Etop) r = typecheck(r, Etop)
ordermapassign(r, order) ordermapassign(r, order)
r = Nod(OAS, n.List.Second(), tmp2) r = Nod(OAS, n.List.Second(), tmp2)
typecheck(&r, Etop) r = typecheck(r, Etop)
ordermapassign(r, order) ordermapassign(r, order)
n.List.Set([]*Node{tmp1, tmp2}) n.List.Set([]*Node{tmp1, tmp2})
cleantemp(t, order) cleantemp(t, order)
...@@ -664,9 +664,9 @@ func orderstmt(n *Node, order *Order) { ...@@ -664,9 +664,9 @@ func orderstmt(n *Node, order *Order) {
case ODELETE: case ODELETE:
t := marktemp(order) t := marktemp(order)
orderexpr(n.List.Addr(0), order, nil) n.List.SetIndex(0, orderexpr(n.List.Index(0), order, nil))
orderexpr(n.List.Addr(1), order, nil) n.List.SetIndex(1, orderexpr(n.List.Index(1), order, nil))
orderaddrtemp(n.List.Addr(1), order) // map key n.List.SetIndex(1, orderaddrtemp(n.List.Index(1), order)) // map key
order.out = append(order.out, n) order.out = append(order.out, n)
cleantemp(t, order) cleantemp(t, order)
...@@ -675,12 +675,12 @@ func orderstmt(n *Node, order *Order) { ...@@ -675,12 +675,12 @@ func orderstmt(n *Node, order *Order) {
case OFOR: case OFOR:
t := marktemp(order) t := marktemp(order)
orderexprinplace(&n.Left, order) n.Left = orderexprinplace(n.Left, order)
var l []*Node var l []*Node
cleantempnopop(t, order, &l) cleantempnopop(t, order, &l)
n.Nbody.Set(append(l, n.Nbody.Slice()...)) n.Nbody.Set(append(l, n.Nbody.Slice()...))
orderblockNodes(&n.Nbody) orderblockNodes(&n.Nbody)
orderstmtinplace(&n.Right) n.Right = orderstmtinplace(n.Right)
order.out = append(order.out, n) order.out = append(order.out, n)
cleantemp(t, order) cleantemp(t, order)
...@@ -689,7 +689,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -689,7 +689,7 @@ func orderstmt(n *Node, order *Order) {
case OIF: case OIF:
t := marktemp(order) t := marktemp(order)
orderexprinplace(&n.Left, order) n.Left = orderexprinplace(n.Left, order)
var l []*Node var l []*Node
cleantempnopop(t, order, &l) cleantempnopop(t, order, &l)
n.Nbody.Set(append(l, n.Nbody.Slice()...)) n.Nbody.Set(append(l, n.Nbody.Slice()...))
...@@ -706,9 +706,9 @@ func orderstmt(n *Node, order *Order) { ...@@ -706,9 +706,9 @@ func orderstmt(n *Node, order *Order) {
case OPANIC: case OPANIC:
t := marktemp(order) t := marktemp(order)
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
if !Isinter(n.Left.Type) { if !Isinter(n.Left.Type) {
orderaddrtemp(&n.Left, order) n.Left = orderaddrtemp(n.Left, order)
} }
order.out = append(order.out, n) order.out = append(order.out, n)
cleantemp(t, order) cleantemp(t, order)
...@@ -724,7 +724,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -724,7 +724,7 @@ func orderstmt(n *Node, order *Order) {
case ORANGE: case ORANGE:
t := marktemp(order) t := marktemp(order)
orderexpr(&n.Right, order, nil) n.Right = orderexpr(n.Right, order, nil)
switch n.Type.Etype { switch n.Type.Etype {
default: default:
Fatalf("orderstmt range %v", n.Type) Fatalf("orderstmt range %v", n.Type)
...@@ -751,7 +751,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -751,7 +751,7 @@ func orderstmt(n *Node, order *Order) {
if r.Type.Etype == TSTRING && r.Type != Types[TSTRING] { if r.Type.Etype == TSTRING && r.Type != Types[TSTRING] {
r = Nod(OCONV, r, nil) r = Nod(OCONV, r, nil)
r.Type = Types[TSTRING] r.Type = Types[TSTRING]
typecheck(&r, Erv) r = typecheck(r, Erv)
} }
n.Right = ordercopyexpr(r, r.Type, order, 0) n.Right = ordercopyexpr(r, r.Type, order, 0)
...@@ -768,7 +768,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -768,7 +768,7 @@ func orderstmt(n *Node, order *Order) {
prealloc[n] = ordertemp(Types[TUINT8], order, true) prealloc[n] = ordertemp(Types[TUINT8], order, true)
} }
for i := range n.List.Slice() { 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) orderblockNodes(&n.Nbody)
order.out = append(order.out, n) order.out = append(order.out, n)
...@@ -839,7 +839,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -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 is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
// r->left == N means 'case <-c'. // r->left == N means 'case <-c'.
// c is always evaluated; x and ok are only evaluated when assigned. // 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 { if r.Right.Left.Op != ONAME {
r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0) r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0)
...@@ -862,13 +862,13 @@ func orderstmt(n *Node, order *Order) { ...@@ -862,13 +862,13 @@ func orderstmt(n *Node, order *Order) {
if r.Colas { if r.Colas {
tmp2 = Nod(ODCL, tmp1, nil) tmp2 = Nod(ODCL, tmp1, nil)
typecheck(&tmp2, Etop) tmp2 = typecheck(tmp2, Etop)
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
r.Left = ordertemp(r.Right.Left.Type.Type, order, haspointers(r.Right.Left.Type.Type)) r.Left = ordertemp(r.Right.Left.Type.Type, order, haspointers(r.Right.Left.Type.Type))
tmp2 = Nod(OAS, tmp1, r.Left) tmp2 = Nod(OAS, tmp1, r.Left)
typecheck(&tmp2, Etop) tmp2 = typecheck(tmp2, Etop)
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
...@@ -879,13 +879,13 @@ func orderstmt(n *Node, order *Order) { ...@@ -879,13 +879,13 @@ func orderstmt(n *Node, order *Order) {
tmp1 = r.List.First() tmp1 = r.List.First()
if r.Colas { if r.Colas {
tmp2 = Nod(ODCL, tmp1, nil) tmp2 = Nod(ODCL, tmp1, nil)
typecheck(&tmp2, Etop) tmp2 = typecheck(tmp2, Etop)
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
r.List.Set1(ordertemp(tmp1.Type, order, false)) r.List.Set1(ordertemp(tmp1.Type, order, false))
tmp2 = Nod(OAS, tmp1, r.List.First()) tmp2 = Nod(OAS, tmp1, r.List.First())
typecheck(&tmp2, Etop) tmp2 = typecheck(tmp2, Etop)
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
n2.Ninit.Set(orderblock(n2.Ninit)) n2.Ninit.Set(orderblock(n2.Ninit))
...@@ -898,12 +898,12 @@ func orderstmt(n *Node, order *Order) { ...@@ -898,12 +898,12 @@ func orderstmt(n *Node, order *Order) {
// case c <- x // case c <- x
// r->left is c, r->right is x, both are always evaluated. // 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) { if !istemp(r.Left) {
r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0) 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) { if !istemp(r.Right) {
r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0) r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0)
} }
...@@ -929,9 +929,9 @@ func orderstmt(n *Node, order *Order) { ...@@ -929,9 +929,9 @@ func orderstmt(n *Node, order *Order) {
case OSEND: case OSEND:
t := marktemp(order) t := marktemp(order)
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right, order, nil) n.Right = orderexpr(n.Right, order, nil)
orderaddrtemp(&n.Right, order) n.Right = orderaddrtemp(n.Right, order)
order.out = append(order.out, n) order.out = append(order.out, n)
cleantemp(t, order) cleantemp(t, order)
...@@ -945,7 +945,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -945,7 +945,7 @@ func orderstmt(n *Node, order *Order) {
case OSWITCH: case OSWITCH:
t := marktemp(order) t := marktemp(order)
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
for _, n4 := range n.List.Slice() { for _, n4 := range n.List.Slice() {
if n4.Op != OXCASE { if n4.Op != OXCASE {
Fatalf("order switch case %v", Oconv(n4.Op, 0)) Fatalf("order switch case %v", Oconv(n4.Op, 0))
...@@ -965,7 +965,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -965,7 +965,7 @@ func orderstmt(n *Node, order *Order) {
func orderexprlist(l Nodes, order *Order) { func orderexprlist(l Nodes, order *Order) {
s := l.Slice() s := l.Slice()
for i := range s { 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) { ...@@ -974,7 +974,7 @@ func orderexprlist(l Nodes, order *Order) {
func orderexprlistinplace(l Nodes, order *Order) { func orderexprlistinplace(l Nodes, order *Order) {
s := l.Slice() s := l.Slice()
for i := range s { for i := range s {
orderexprinplace(&s[i], order) s[i] = orderexprinplace(s[i], order)
} }
} }
...@@ -986,10 +986,11 @@ var prealloc = map[*Node]*Node{} ...@@ -986,10 +986,11 @@ var prealloc = map[*Node]*Node{}
// If this is part of an assignment lhs = *np, lhs is given. // If this is part of an assignment lhs = *np, lhs is given.
// Otherwise lhs == nil. (When lhs != nil it may be possible // Otherwise lhs == nil. (When lhs != nil it may be possible
// to avoid copying the result of the expression to a temporary.) // to avoid copying the result of the expression to a temporary.)
func orderexpr(np **Node, order *Order, lhs *Node) { // The result of orderexpr MUST be assigned back to n, e.g.
n := *np // n.Left = orderexpr(n.Left, order, lhs)
func orderexpr(n *Node, order *Order, lhs *Node) *Node {
if n == nil { if n == nil {
return return n
} }
lno := setlineno(n) lno := setlineno(n)
...@@ -997,8 +998,8 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -997,8 +998,8 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
switch n.Op { switch n.Op {
default: default:
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right, order, nil) n.Right = orderexpr(n.Right, order, nil)
orderexprlist(n.List, order) orderexprlist(n.List, order)
orderexprlist(n.Rlist, order) orderexprlist(n.Rlist, order)
...@@ -1039,8 +1040,8 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1039,8 +1040,8 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
} }
case OCMPSTR: case OCMPSTR:
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right, order, nil) n.Right = orderexpr(n.Right, order, nil)
// Mark string(byteSlice) arguments to reuse byteSlice backing // Mark string(byteSlice) arguments to reuse byteSlice backing
// buffer during conversion. String comparison does not // buffer during conversion. String comparison does not
...@@ -1054,9 +1055,9 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1054,9 +1055,9 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
// key must be addressable // key must be addressable
case OINDEXMAP: 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 // For x = m[string(k)] where k is []byte, the allocation of
// backing bytes for the string can be avoided by reusing // backing bytes for the string can be avoided by reusing
...@@ -1072,7 +1073,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1072,7 +1073,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
n.Right.Op = OARRAYBYTESTRTMP n.Right.Op = OARRAYBYTESTRTMP
} }
orderaddrtemp(&n.Right, order) n.Right = orderaddrtemp(n.Right, order)
if n.Etype == 0 { if n.Etype == 0 {
// use of value (not being assigned); // use of value (not being assigned);
// make copy in temporary. // make copy in temporary.
...@@ -1082,15 +1083,15 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1082,15 +1083,15 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
// concrete type (not interface) argument must be addressable // concrete type (not interface) argument must be addressable
// temporary to pass to runtime. // temporary to pass to runtime.
case OCONVIFACE: case OCONVIFACE:
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
if !Isinter(n.Left.Type) { if !Isinter(n.Left.Type) {
orderaddrtemp(&n.Left, order) n.Left = orderaddrtemp(n.Left, order)
} }
case OANDAND, OOROR: case OANDAND, OOROR:
mark := marktemp(order) mark := marktemp(order)
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
// Clean temporaries from first branch at beginning of second. // Clean temporaries from first branch at beginning of second.
// Leave them on the stack so that they can be killed in the outer // 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) { ...@@ -1099,7 +1100,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
cleantempnopop(mark, order, &s) cleantempnopop(mark, order, &s)
n.Right.Ninit.Set(append(s, n.Right.Ninit.Slice()...)) n.Right.Ninit.Set(append(s, n.Right.Ninit.Slice()...))
orderexprinplace(&n.Right, order) n.Right = orderexprinplace(n.Right, order)
case OCALLFUNC, case OCALLFUNC,
OCALLINTER, OCALLINTER,
...@@ -1130,22 +1131,22 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1130,22 +1131,22 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
} }
case OSLICE, OSLICEARR, OSLICESTR: case OSLICE, OSLICEARR, OSLICESTR:
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right.Left, order, nil) n.Right.Left = orderexpr(n.Right.Left, order, nil)
n.Right.Left = ordercheapexpr(n.Right.Left, order) 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) n.Right.Right = ordercheapexpr(n.Right.Right, order)
if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) { if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
n = ordercopyexpr(n, n.Type, order, 0) n = ordercopyexpr(n, n.Type, order, 0)
} }
case OSLICE3, OSLICE3ARR: case OSLICE3, OSLICE3ARR:
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right.Left, order, nil) n.Right.Left = orderexpr(n.Right.Left, order, nil)
n.Right.Left = ordercheapexpr(n.Right.Left, order) 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) 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) n.Right.Right.Right = ordercheapexpr(n.Right.Right.Right, order)
if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) { if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
n = ordercopyexpr(n, n.Type, order, 0) n = ordercopyexpr(n, n.Type, order, 0)
...@@ -1157,8 +1158,8 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1157,8 +1158,8 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
} }
case OARRAYLIT, OCALLPART: case OARRAYLIT, OCALLPART:
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right, order, nil) n.Right = orderexpr(n.Right, order, nil)
orderexprlist(n.List, order) orderexprlist(n.List, order)
orderexprlist(n.Rlist, order) orderexprlist(n.Rlist, order)
if n.Noescape { if n.Noescape {
...@@ -1175,7 +1176,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1175,7 +1176,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
} }
case ODOTTYPE, ODOTTYPE2: 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. // TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
// It needs to be removed in all three places. // It needs to be removed in all three places.
// That would allow inlining x.(struct{*int}) the same as x.(*int). // That would allow inlining x.(struct{*int}) the same as x.(*int).
...@@ -1184,22 +1185,21 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1184,22 +1185,21 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
} }
case ORECV: case ORECV:
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
n = ordercopyexpr(n, n.Type, order, 1) n = ordercopyexpr(n, n.Type, order, 1)
case OEQ, ONE: case OEQ, ONE:
orderexpr(&n.Left, order, nil) n.Left = orderexpr(n.Left, order, nil)
orderexpr(&n.Right, order, nil) n.Right = orderexpr(n.Right, order, nil)
t := n.Left.Type t := n.Left.Type
if t.Etype == TSTRUCT || Isfixedarray(t) { if t.Etype == TSTRUCT || Isfixedarray(t) {
// for complex comparisons, we need both args to be // for complex comparisons, we need both args to be
// addressable so we can pass them to the runtime. // addressable so we can pass them to the runtime.
orderaddrtemp(&n.Left, order) n.Left = orderaddrtemp(n.Left, order)
orderaddrtemp(&n.Right, order) n.Right = orderaddrtemp(n.Right, order)
} }
} }
lineno = lno lineno = lno
return n
*np = n
} }
...@@ -380,7 +380,7 @@ func compile(fn *Node) { ...@@ -380,7 +380,7 @@ func compile(fn *Node) {
for _, t := range Curfn.Type.Results().Fields().Slice() { for _, t := range Curfn.Type.Results().Fields().Slice() {
if t.Nname != nil { if t.Nname != nil {
n := Nod(OAS, 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()...)) Curfn.Nbody.Set(append([]*Node{n}, Curfn.Nbody.Slice()...))
} }
} }
......
...@@ -228,7 +228,7 @@ func instrumentnode(np **Node, init *Nodes, wr int, skip int) { ...@@ -228,7 +228,7 @@ func instrumentnode(np **Node, init *Nodes, wr int, skip int) {
n1 := Nod(OCONVNOP, n.Left, nil) n1 := Nod(OCONVNOP, n.Left, nil)
n1.Type = Ptrto(Types[TUINT8]) n1.Type = Ptrto(Types[TUINT8])
n1 = Nod(OIND, n1, nil) n1 = Nod(OIND, n1, nil)
typecheck(&n1, Erv) n1 = typecheck(n1, Erv)
callinstr(&n1, init, 0, skip) callinstr(&n1, init, 0, skip)
} }
...@@ -581,12 +581,12 @@ func detachexpr(n *Node, init *Nodes) *Node { ...@@ -581,12 +581,12 @@ func detachexpr(n *Node, init *Nodes) *Node {
addr := Nod(OADDR, n, nil) addr := Nod(OADDR, n, nil)
l := temp(Ptrto(n.Type)) l := temp(Ptrto(n.Type))
as := Nod(OAS, l, addr) as := Nod(OAS, l, addr)
typecheck(&as, Etop) as = typecheck(as, Etop)
walkexpr(&as, init) as = walkexpr(as, init)
init.Append(as) init.Append(as)
ind := Nod(OIND, l, nil) ind := Nod(OIND, l, nil)
typecheck(&ind, Erv) ind = typecheck(ind, Erv)
walkexpr(&ind, init) ind = walkexpr(ind, init)
return ind return ind
} }
......
...@@ -24,7 +24,7 @@ func typecheckrange(n *Node) { ...@@ -24,7 +24,7 @@ func typecheckrange(n *Node) {
// 3. typecheck body. // 3. typecheck body.
// 4. decldepth--. // 4. decldepth--.
typecheck(&n.Right, Erv) n.Right = typecheck(n.Right, Erv)
t := n.Right.Type t := n.Right.Type
if t == nil { if t == nil {
...@@ -34,7 +34,7 @@ func typecheckrange(n *Node) { ...@@ -34,7 +34,7 @@ func typecheckrange(n *Node) {
ls = n.List.Slice() ls = n.List.Slice()
for i1, n1 := range ls { for i1, n1 := range ls {
if n1.Name == nil || n1.Name.Defn != n { 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: ...@@ -122,7 +122,7 @@ out:
ls = n.List.Slice() ls = n.List.Slice()
for i1, n1 := range ls { for i1, n1 := range ls {
if n1.Typecheck == 0 { if n1.Typecheck == 0 {
typecheck(&ls[i1], Erv|Easgn) ls[i1] = typecheck(ls[i1], Erv|Easgn)
} }
} }
...@@ -213,7 +213,7 @@ func walkrange(n *Node) { ...@@ -213,7 +213,7 @@ func walkrange(n *Node) {
tmp.Right.Type = Types[Tptr] tmp.Right.Type = Types[Tptr]
tmp.Right.Typecheck = 1 tmp.Right.Typecheck = 1
a = Nod(OAS, hp, tmp) a = Nod(OAS, hp, tmp)
typecheck(&a, Etop) a = typecheck(a, Etop)
n.Right.Ninit.Set1(a) n.Right.Ninit.Set1(a)
} }
...@@ -231,12 +231,12 @@ func walkrange(n *Node) { ...@@ -231,12 +231,12 @@ func walkrange(n *Node) {
fn := syslook("mapiterinit") 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))) init = append(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
n.Left = Nod(ONE, NodSym(ODOT, hit, keysym), nodnil()) n.Left = Nod(ONE, NodSym(ODOT, hit, keysym), nodnil())
fn = syslook("mapiternext") fn = syslook("mapiternext")
substArgTypes(&fn, th) fn = substArgTypes(fn, th)
n.Right = mkcall1(fn, nil, nil, Nod(OADDR, hit, nil)) n.Right = mkcall1(fn, nil, nil, Nod(OADDR, hit, nil))
key := NodSym(ODOT, hit, keysym) key := NodSym(ODOT, hit, keysym)
...@@ -316,11 +316,11 @@ func walkrange(n *Node) { ...@@ -316,11 +316,11 @@ func walkrange(n *Node) {
typecheckslice(init, Etop) typecheckslice(init, Etop)
n.Ninit.Append(init...) n.Ninit.Append(init...)
typecheckslice(n.Left.Ninit.Slice(), Etop) typecheckslice(n.Left.Ninit.Slice(), Etop)
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
typecheck(&n.Right, Etop) n.Right = typecheck(n.Right, Etop)
typecheckslice(body, Etop) typecheckslice(body, Etop)
n.Nbody.Set(append(body, n.Nbody.Slice()...)) n.Nbody.Set(append(body, n.Nbody.Slice()...))
walkstmt(&n) n = walkstmt(n)
lineno = lno lineno = lno
} }
...@@ -398,8 +398,8 @@ func memclrrange(n, v1, v2, a *Node) bool { ...@@ -398,8 +398,8 @@ func memclrrange(n, v1, v2, a *Node) bool {
n.Nbody.Append(v1) n.Nbody.Append(v1)
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
typecheckslice(n.Nbody.Slice(), Etop) typecheckslice(n.Nbody.Slice(), Etop)
walkstmt(&n) n = walkstmt(n)
return true return true
} }
...@@ -31,7 +31,8 @@ func typecheckselect(sel *Node) { ...@@ -31,7 +31,8 @@ func typecheckselect(sel *Node) {
} else if ncase.List.Len() > 1 { } else if ncase.List.Len() > 1 {
Yyerror("select cases cannot be lists") Yyerror("select cases cannot be lists")
} else { } 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.Left = n
ncase.List.Set(nil) ncase.List.Set(nil)
setlineno(n) setlineno(n)
...@@ -137,7 +138,7 @@ func walkselect(sel *Node) { ...@@ -137,7 +138,7 @@ func walkselect(sel *Node) {
} }
if n.Left == nil { if n.Left == nil {
typecheck(&nblank, Erv|Easgn) nblank = typecheck(nblank, Erv|Easgn)
n.Left = nblank n.Left = nblank
} }
...@@ -147,7 +148,7 @@ func walkselect(sel *Node) { ...@@ -147,7 +148,7 @@ func walkselect(sel *Node) {
n.Right = nil n.Right = nil
n.Left = nil n.Left = nil
n.Typecheck = 0 n.Typecheck = 0
typecheck(&n, Etop) n = typecheck(n, Etop)
} }
// if ch == nil { block() }; n; // if ch == nil { block() }; n;
...@@ -158,7 +159,7 @@ func walkselect(sel *Node) { ...@@ -158,7 +159,7 @@ func walkselect(sel *Node) {
ln.Set(l) ln.Set(l)
a.Nbody.Set1(mkcall("block", nil, &ln)) a.Nbody.Set1(mkcall("block", nil, &ln))
l = ln.Slice() l = ln.Slice()
typecheck(&a, Etop) a = typecheck(a, Etop)
l = append(l, a) l = append(l, a)
l = append(l, n) l = append(l, n)
} }
...@@ -179,7 +180,7 @@ func walkselect(sel *Node) { ...@@ -179,7 +180,7 @@ func walkselect(sel *Node) {
switch n.Op { switch n.Op {
case OSEND: case OSEND:
n.Right = Nod(OADDR, n.Right, nil) n.Right = Nod(OADDR, n.Right, nil)
typecheck(&n.Right, Erv) n.Right = typecheck(n.Right, Erv)
case OSELRECV, OSELRECV2: case OSELRECV, OSELRECV2:
if n.Op == OSELRECV2 && n.List.Len() == 0 { if n.Op == OSELRECV2 && n.List.Len() == 0 {
...@@ -187,14 +188,14 @@ func walkselect(sel *Node) { ...@@ -187,14 +188,14 @@ func walkselect(sel *Node) {
} }
if n.Op == OSELRECV2 { if n.Op == OSELRECV2 {
n.List.SetIndex(0, Nod(OADDR, n.List.First(), nil)) 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 { if n.Left == nil {
n.Left = nodnil() n.Left = nodnil()
} else { } else {
n.Left = Nod(OADDR, n.Left, nil) 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) { ...@@ -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) 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.Nbody.Set(cas.Nbody.Slice())
r.Rlist.Set(append(dflt.Ninit.Slice(), dflt.Nbody.Slice()...)) r.Rlist.Set(append(dflt.Ninit.Slice(), dflt.Nbody.Slice()...))
sel.Nbody.Set1(r) sel.Nbody.Set1(r)
...@@ -257,11 +258,11 @@ func walkselect(sel *Node) { ...@@ -257,11 +258,11 @@ func walkselect(sel *Node) {
selv = temp(selecttype(int32(sel.Xoffset))) selv = temp(selecttype(int32(sel.Xoffset)))
r = Nod(OAS, selv, nil) r = Nod(OAS, selv, nil)
typecheck(&r, Etop) r = typecheck(r, Etop)
init = append(init, r) init = append(init, r)
var_ = conv(conv(Nod(OADDR, selv, nil), Types[TUNSAFEPTR]), Ptrto(Types[TUINT8])) 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)) r = mkcall("newselect", nil, nil, var_, Nodintconst(selv.Type.Width), Nodintconst(sel.Xoffset))
typecheck(&r, Etop) r = typecheck(r, Etop)
init = append(init, r) init = append(init, r)
// register cases // register cases
for _, cas := range sel.List.Slice() { for _, cas := range sel.List.Slice() {
...@@ -330,7 +331,7 @@ func selecttype(size int32) *Type { ...@@ -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("so")), typenod(Types[TUINT16])))
scase.List.Append(Nod(ODCLFIELD, newname(Lookup("receivedp")), typenod(Ptrto(Types[TUINT8])))) scase.List.Append(Nod(ODCLFIELD, newname(Lookup("receivedp")), typenod(Ptrto(Types[TUINT8]))))
scase.List.Append(Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64]))) scase.List.Append(Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64])))
typecheck(&scase, Etype) scase = typecheck(scase, Etype)
scase.Type.Noalg = true scase.Type.Noalg = true
scase.Type.Local = true scase.Type.Local = true
...@@ -345,7 +346,7 @@ func selecttype(size int32) *Type { ...@@ -345,7 +346,7 @@ func selecttype(size int32) *Type {
sel.List.Append(Nod(ODCLFIELD, newname(Lookup("lockorderarr")), arr)) sel.List.Append(Nod(ODCLFIELD, newname(Lookup("lockorderarr")), arr))
arr = Nod(OTARRAY, Nodintconst(int64(size)), typenod(Types[TUINT16])) arr = Nod(OTARRAY, Nodintconst(int64(size)), typenod(Types[TUINT16]))
sel.List.Append(Nod(ODCLFIELD, newname(Lookup("pollorderarr")), arr)) sel.List.Append(Nod(ODCLFIELD, newname(Lookup("pollorderarr")), arr))
typecheck(&sel, Etype) sel = typecheck(sel, Etype)
sel.Type.Noalg = true sel.Type.Noalg = true
sel.Type.Local = true sel.Type.Local = true
......
...@@ -520,8 +520,8 @@ func (n *Node) isSimpleName() bool { ...@@ -520,8 +520,8 @@ func (n *Node) isSimpleName() bool {
func litas(l *Node, r *Node, init *Nodes) { func litas(l *Node, r *Node, init *Nodes) {
a := Nod(OAS, l, r) a := Nod(OAS, l, r)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
init.Append(a) init.Append(a)
} }
...@@ -608,16 +608,16 @@ func structlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { ...@@ -608,16 +608,16 @@ func structlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
a = NodSym(ODOT, var_, index.Sym) a = NodSym(ODOT, var_, index.Sym)
a = Nod(OAS, a, value) a = Nod(OAS, a, value)
typecheck(&a, Etop) a = typecheck(a, Etop)
if pass == 1 { 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 { if a.Op != OAS {
Fatalf("structlit: not as") Fatalf("structlit: not as")
} }
a.Dodata = 2 a.Dodata = 2
} else { } else {
orderstmtinplace(&a) a = orderstmtinplace(a)
walkstmt(&a) a = walkstmt(a)
} }
init.Append(a) init.Append(a)
...@@ -672,16 +672,16 @@ func arraylit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { ...@@ -672,16 +672,16 @@ func arraylit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
a = Nod(OINDEX, var_, index) a = Nod(OINDEX, var_, index)
a = Nod(OAS, a, value) a = Nod(OAS, a, value)
typecheck(&a, Etop) a = typecheck(a, Etop)
if pass == 1 { if pass == 1 {
walkexpr(&a, init) a = walkexpr(a, init)
if a.Op != OAS { if a.Op != OAS {
Fatalf("arraylit: not as") Fatalf("arraylit: not as")
} }
a.Dodata = 2 a.Dodata = 2
} else { } else {
orderstmtinplace(&a) a = orderstmtinplace(a)
walkstmt(&a) a = walkstmt(a)
} }
init.Append(a) init.Append(a)
...@@ -708,7 +708,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -708,7 +708,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
a := Nod(OSLICE, vstat, Nod(OKEY, nil, nil)) a := Nod(OSLICE, vstat, Nod(OKEY, nil, nil))
a = Nod(OAS, var_, a) a = Nod(OAS, var_, a)
typecheck(&a, Etop) a = typecheck(a, Etop)
a.Dodata = 2 a.Dodata = 2
init.Append(a) init.Append(a)
return return
...@@ -754,7 +754,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -754,7 +754,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
if vstat == nil { if vstat == nil {
a = Nod(OAS, x, nil) a = Nod(OAS, x, nil)
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) // zero new temp init.Append(a) // zero new temp
} }
...@@ -763,7 +763,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -763,7 +763,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
a = temp(t) a = temp(t)
if vstat == nil { if vstat == nil {
a = Nod(OAS, temp(t), nil) a = Nod(OAS, temp(t), nil)
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) // zero new temp init.Append(a) // zero new temp
a = a.Left a = a.Left
} }
...@@ -775,8 +775,8 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -775,8 +775,8 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
} }
a = Nod(OAS, vauto, a) a = Nod(OAS, vauto, a)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
init.Append(a) init.Append(a)
if vstat != nil { if vstat != nil {
...@@ -784,17 +784,17 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -784,17 +784,17 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
a = Nod(OIND, vauto, nil) a = Nod(OIND, vauto, nil)
a = Nod(OAS, a, vstat) a = Nod(OAS, a, vstat)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
init.Append(a) init.Append(a)
} }
// make slice out of heap (5) // make slice out of heap (5)
a = Nod(OAS, var_, Nod(OSLICE, vauto, Nod(OKEY, nil, nil))) a = Nod(OAS, var_, Nod(OSLICE, vauto, Nod(OKEY, nil, nil)))
typecheck(&a, Etop) a = typecheck(a, Etop)
orderstmtinplace(&a) a = orderstmtinplace(a)
walkstmt(&a) a = walkstmt(a)
init.Append(a) init.Append(a)
// put dynamics into slice (6) // put dynamics into slice (6)
for _, r := range n.List.Slice() { for _, r := range n.List.Slice() {
...@@ -829,9 +829,9 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -829,9 +829,9 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) {
setlineno(value) setlineno(value)
a = Nod(OAS, a, value) a = Nod(OAS, a, value)
typecheck(&a, Etop) a = typecheck(a, Etop)
orderstmtinplace(&a) a = orderstmtinplace(a)
walkstmt(&a) a = walkstmt(a)
init.Append(a) init.Append(a)
} }
} }
...@@ -906,8 +906,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -906,8 +906,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
a = Nod(OINDEX, vstat, a) a = Nod(OINDEX, vstat, a)
a = NodSym(ODOT, a, syma) a = NodSym(ODOT, a, syma)
a = Nod(OAS, a, index) a = Nod(OAS, a, index)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
a.Dodata = 2 a.Dodata = 2
init.Append(a) init.Append(a)
...@@ -918,8 +918,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -918,8 +918,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
a = Nod(OINDEX, vstat, a) a = Nod(OINDEX, vstat, a)
a = NodSym(ODOT, a, symb) a = NodSym(ODOT, a, symb)
a = Nod(OAS, a, value) a = Nod(OAS, a, value)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
a.Dodata = 2 a.Dodata = 2
init.Append(a) init.Append(a)
...@@ -951,8 +951,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -951,8 +951,8 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
a.Left = Nod(OLT, index, Nodintconst(tarr.Bound)) a.Left = Nod(OLT, index, Nodintconst(tarr.Bound))
a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1))) a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
typecheck(&a, Etop) a = typecheck(a, Etop)
walkstmt(&a) a = walkstmt(a)
init.Append(a) init.Append(a)
} }
...@@ -978,19 +978,19 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -978,19 +978,19 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
setlineno(r.Left) setlineno(r.Left)
a = Nod(OAS, key, r.Left) a = Nod(OAS, key, r.Left)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkstmt(&a) a = walkstmt(a)
init.Append(a) init.Append(a)
setlineno(r.Right) setlineno(r.Right)
a = Nod(OAS, val, r.Right) a = Nod(OAS, val, r.Right)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkstmt(&a) a = walkstmt(a)
init.Append(a) init.Append(a)
setlineno(val) setlineno(val)
a = Nod(OAS, Nod(OINDEX, var_, key), val) a = Nod(OAS, Nod(OINDEX, var_, key), val)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkstmt(&a) a = walkstmt(a)
init.Append(a) init.Append(a)
if nerr != nerrors { if nerr != nerrors {
...@@ -1000,10 +1000,10 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1000,10 +1000,10 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
if key != nil { if key != nil {
a = Nod(OVARKILL, key, nil) a = Nod(OVARKILL, key, nil)
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) init.Append(a)
a = Nod(OVARKILL, val, nil) a = Nod(OVARKILL, val, nil)
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) init.Append(a)
} }
} }
...@@ -1022,7 +1022,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1022,7 +1022,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
var r *Node var r *Node
if n.Right != nil { if n.Right != nil {
r = Nod(OADDR, n.Right, nil) r = Nod(OADDR, n.Right, nil)
typecheck(&r, Erv) r = typecheck(r, Erv)
} else { } else {
r = Nod(ONEW, nil, nil) r = Nod(ONEW, nil, nil)
r.Typecheck = 1 r.Typecheck = 1
...@@ -1030,14 +1030,14 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1030,14 +1030,14 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
r.Esc = n.Esc r.Esc = n.Esc
} }
walkexpr(&r, init) r = walkexpr(r, init)
a := Nod(OAS, var_, r) a := Nod(OAS, var_, r)
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) init.Append(a)
var_ = Nod(OIND, var_, nil) var_ = Nod(OIND, var_, nil)
typecheck(&var_, Erv|Easgn) var_ = typecheck(var_, Erv|Easgn)
anylit(ctxt, n.Left, var_, init) anylit(ctxt, n.Left, var_, init)
case OSTRUCTLIT: case OSTRUCTLIT:
...@@ -1055,8 +1055,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1055,8 +1055,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
// copy static to var // copy static to var
a := Nod(OAS, var_, vstat) a := Nod(OAS, var_, vstat)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
init.Append(a) init.Append(a)
// add expressions to automatic // add expressions to automatic
...@@ -1073,8 +1073,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1073,8 +1073,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
// initialize of not completely specified // initialize of not completely specified
if var_.isSimpleName() || n.List.Len() < t.NumFields() { if var_.isSimpleName() || n.List.Len() < t.NumFields() {
a := Nod(OAS, var_, nil) a := Nod(OAS, var_, nil)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
init.Append(a) init.Append(a)
} }
...@@ -1099,8 +1099,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1099,8 +1099,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
// copy static to automatic // copy static to automatic
a := Nod(OAS, var_, vstat) a := Nod(OAS, var_, vstat)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
init.Append(a) init.Append(a)
// add expressions to automatic // add expressions to automatic
...@@ -1117,8 +1117,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1117,8 +1117,8 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
// initialize of not completely specified // initialize of not completely specified
if var_.isSimpleName() || int64(n.List.Len()) < t.Bound { if var_.isSimpleName() || int64(n.List.Len()) < t.Bound {
a := Nod(OAS, var_, nil) a := Nod(OAS, var_, nil)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
init.Append(a) init.Append(a)
} }
......
...@@ -484,7 +484,7 @@ func Nodbool(b bool) *Node { ...@@ -484,7 +484,7 @@ func Nodbool(b bool) *Node {
func aindex(b *Node, t *Type) *Type { func aindex(b *Node, t *Type) *Type {
bound := int64(-1) // open bound bound := int64(-1) // open bound
typecheck(&b, Erv) b = typecheck(b, Erv)
if b != nil { if b != nil {
switch consttype(b) { switch consttype(b) {
default: default:
...@@ -1042,7 +1042,7 @@ func assignconvfn(n *Node, t *Type, context func() string) *Node { ...@@ -1042,7 +1042,7 @@ func assignconvfn(n *Node, t *Type, context func() string) *Node {
old := n old := n
old.Diag++ // silence errors about n; we'll issue one below old.Diag++ // silence errors about n; we'll issue one below
defaultlit(&n, t) n = defaultlit(n, t)
old.Diag-- old.Diag--
if t.Etype == TBLANK { if t.Etype == TBLANK {
return n return n
...@@ -1082,10 +1082,11 @@ func assignconvfn(n *Node, t *Type, context func() string) *Node { ...@@ -1082,10 +1082,11 @@ func assignconvfn(n *Node, t *Type, context func() string) *Node {
// substArgTypes substitutes the given list of types for // substArgTypes substitutes the given list of types for
// successive occurrences of the "any" placeholder in the // successive occurrences of the "any" placeholder in the
// type syntax expression n.Type. // type syntax expression n.Type.
func substArgTypes(np **Node, types ...*Type) { // The result of substArgTypes MUST be assigned back to old, e.g.
n := Nod(0, nil, nil) // n.Left = substArgTypes(n.Left, t1, t2)
*n = **np func substArgTypes(old *Node, types ...*Type) *Node {
*np = n n := Nod(OXXX, nil, nil)
*n = *old // make shallow copy
for _, t := range types { for _, t := range types {
dowidth(t) dowidth(t)
...@@ -1094,6 +1095,7 @@ func substArgTypes(np **Node, types ...*Type) { ...@@ -1094,6 +1095,7 @@ func substArgTypes(np **Node, types ...*Type) {
if len(types) > 0 { if len(types) > 0 {
Fatalf("substArgTypes: too many argument types") Fatalf("substArgTypes: too many argument types")
} }
return n
} }
// substAny walks t, replacing instances of "any" with successive // substAny walks t, replacing instances of "any" with successive
...@@ -1478,8 +1480,8 @@ func safeexpr(n *Node, init *Nodes) *Node { ...@@ -1478,8 +1480,8 @@ func safeexpr(n *Node, init *Nodes) *Node {
r := Nod(OXXX, nil, nil) r := Nod(OXXX, nil, nil)
*r = *n *r = *n
r.Left = l r.Left = l
typecheck(&r, Erv) r = typecheck(r, Erv)
walkexpr(&r, init) r = walkexpr(r, init)
return r return r
case ODOTPTR, OIND: case ODOTPTR, OIND:
...@@ -1490,7 +1492,7 @@ func safeexpr(n *Node, init *Nodes) *Node { ...@@ -1490,7 +1492,7 @@ func safeexpr(n *Node, init *Nodes) *Node {
a := Nod(OXXX, nil, nil) a := Nod(OXXX, nil, nil)
*a = *n *a = *n
a.Left = l a.Left = l
walkexpr(&a, init) a = walkexpr(a, init)
return a return a
case OINDEX, OINDEXMAP: case OINDEX, OINDEXMAP:
...@@ -1503,7 +1505,7 @@ func safeexpr(n *Node, init *Nodes) *Node { ...@@ -1503,7 +1505,7 @@ func safeexpr(n *Node, init *Nodes) *Node {
*a = *n *a = *n
a.Left = l a.Left = l
a.Right = r a.Right = r
walkexpr(&a, init) a = walkexpr(a, init)
return a return a
} }
...@@ -1517,8 +1519,8 @@ func safeexpr(n *Node, init *Nodes) *Node { ...@@ -1517,8 +1519,8 @@ func safeexpr(n *Node, init *Nodes) *Node {
func copyexpr(n *Node, t *Type, init *Nodes) *Node { func copyexpr(n *Node, t *Type, init *Nodes) *Node {
l := temp(t) l := temp(t)
a := Nod(OAS, l, n) a := Nod(OAS, l, n)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
init.Append(a) init.Append(a)
return l return l
} }
...@@ -1684,7 +1686,7 @@ func dotpath(s *Sym, t *Type, save **Field, ignorecase bool) (path []Dlist, ambi ...@@ -1684,7 +1686,7 @@ func dotpath(s *Sym, t *Type, save **Field, ignorecase bool) (path []Dlist, ambi
// will give shortest unique addressing. // will give shortest unique addressing.
// modify the tree with missing type names. // modify the tree with missing type names.
func adddot(n *Node) *Node { func adddot(n *Node) *Node {
typecheck(&n.Left, Etype|Erv) n.Left = typecheck(n.Left, Etype|Erv)
n.Diag |= n.Left.Diag n.Diag |= n.Left.Diag
t := n.Left.Type t := n.Left.Type
if t == nil { if t == nil {
...@@ -2018,7 +2020,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) { ...@@ -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 { if rcvr.Etype == TSTRUCT || rcvr.Etype == TINTER || Isptr[rcvr.Etype] && rcvr.Type.Etype == TSTRUCT {
fn.Func.Dupok = true fn.Func.Dupok = true
} }
typecheck(&fn, Etop) fn = typecheck(fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop) typecheckslice(fn.Nbody.Slice(), Etop)
inlcalls(fn) inlcalls(fn)
...@@ -2038,7 +2040,7 @@ func hashmem(t *Type) *Node { ...@@ -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.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]))) tfn.Rlist.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
typecheck(&tfn, Etype) tfn = typecheck(tfn, Etype)
n.Type = tfn.Type n.Type = tfn.Type
return n return n
} }
...@@ -2305,25 +2307,25 @@ func mkpkg(path string) *Pkg { ...@@ -2305,25 +2307,25 @@ func mkpkg(path string) *Pkg {
return p 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 { if len(init) == 0 {
return return n
} }
n := *np
switch n.Op { switch n.Op {
// There may be multiple refs to this node; // There may be multiple refs to this node;
// introduce OCONVNOP to hold init list. // introduce OCONVNOP to hold init list.
case ONAME, OLITERAL: case ONAME, OLITERAL:
n = Nod(OCONVNOP, n, nil) n = Nod(OCONVNOP, n, nil)
n.Type = n.Left.Type n.Type = n.Left.Type
n.Typecheck = 1 n.Typecheck = 1
*np = n
} }
n.Ninit.Set(append(init, n.Ninit.Slice()...)) n.Ninit.Set(append(init, n.Ninit.Slice()...))
n.Ullman = UINF n.Ullman = UINF
return n
} }
var reservedimports = []string{ var reservedimports = []string{
...@@ -2377,7 +2379,7 @@ func isbadimport(path string) bool { ...@@ -2377,7 +2379,7 @@ func isbadimport(path string) bool {
func checknil(x *Node, init *Nodes) { func checknil(x *Node, init *Nodes) {
if Isinter(x.Type) { if Isinter(x.Type) {
x = Nod(OITAB, x, nil) x = Nod(OITAB, x, nil)
typecheck(&x, Erv) x = typecheck(x, Erv)
} }
n := Nod(OCHECKNIL, x, nil) n := Nod(OCHECKNIL, x, nil)
......
...@@ -67,7 +67,7 @@ func typecheckswitch(n *Node) { ...@@ -67,7 +67,7 @@ func typecheckswitch(n *Node) {
if n.Left != nil && n.Left.Op == OTYPESW { if n.Left != nil && n.Left.Op == OTYPESW {
// type switch // type switch
top = Etype top = Etype
typecheck(&n.Left.Right, Erv) n.Left.Right = typecheck(n.Left.Right, Erv)
t = n.Left.Right.Type t = n.Left.Right.Type
if t != nil && t.Etype != TINTER { if t != nil && t.Etype != TINTER {
Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, FmtLong)) Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, FmtLong))
...@@ -76,8 +76,8 @@ func typecheckswitch(n *Node) { ...@@ -76,8 +76,8 @@ func typecheckswitch(n *Node) {
// expression switch // expression switch
top = Erv top = Erv
if n.Left != nil { if n.Left != nil {
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
t = n.Left.Type t = n.Left.Type
} else { } else {
t = Types[TBOOL] t = Types[TBOOL]
...@@ -117,7 +117,7 @@ func typecheckswitch(n *Node) { ...@@ -117,7 +117,7 @@ func typecheckswitch(n *Node) {
ls := ncase.List.Slice() ls := ncase.List.Slice()
for i1, n1 := range ls { for i1, n1 := range ls {
setlineno(n1) setlineno(n1)
typecheck(&ls[i1], Erv|Etype) ls[i1] = typecheck(ls[i1], Erv|Etype)
n1 = ls[i1] n1 = ls[i1]
if n1.Type == nil || t == nil { if n1.Type == nil || t == nil {
continue continue
...@@ -126,7 +126,7 @@ func typecheckswitch(n *Node) { ...@@ -126,7 +126,7 @@ func typecheckswitch(n *Node) {
switch top { switch top {
// expression switch // expression switch
case Erv: case Erv:
defaultlit(&ls[i1], t) ls[i1] = defaultlit(ls[i1], t)
n1 = ls[i1] n1 = ls[i1]
switch { switch {
case n1.Op == OTYPE: case n1.Op == OTYPE:
...@@ -177,7 +177,7 @@ func typecheckswitch(n *Node) { ...@@ -177,7 +177,7 @@ func typecheckswitch(n *Node) {
nvar.Name.Param.Ntype = typenod(n.Type) nvar.Name.Param.Ntype = typenod(n.Type)
} }
typecheck(&nvar, Erv|Easgn) nvar = typecheck(nvar, Erv|Easgn)
ncase.Rlist.SetIndex(0, nvar) ncase.Rlist.SetIndex(0, nvar)
} }
} }
...@@ -193,7 +193,7 @@ func walkswitch(sw *Node) { ...@@ -193,7 +193,7 @@ func walkswitch(sw *Node) {
// convert switch {...} to switch true {...} // convert switch {...} to switch true {...}
if sw.Left == nil { if sw.Left == nil {
sw.Left = Nodbool(true) sw.Left = Nodbool(true)
typecheck(&sw.Left, Erv) sw.Left = typecheck(sw.Left, Erv)
} }
if sw.Left.Op == OTYPESW { if sw.Left.Op == OTYPESW {
...@@ -224,7 +224,7 @@ func (s *exprSwitch) walk(sw *Node) { ...@@ -224,7 +224,7 @@ func (s *exprSwitch) walk(sw *Node) {
} }
} }
walkexpr(&cond, &sw.Ninit) cond = walkexpr(cond, &sw.Ninit)
t := sw.Type t := sw.Type
if t == nil { if t == nil {
return return
...@@ -296,13 +296,13 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node { ...@@ -296,13 +296,13 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
a := Nod(OIF, nil, nil) 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 { 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 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 { } else if s.kind == switchKindTrue {
a.Left = n.Left // if val a.Left = n.Left // if val
} else { } else {
// s.kind == switchKindFalse // s.kind == switchKindFalse
a.Left = Nod(ONOT, n.Left, nil) // if !val 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 a.Nbody.Set1(n.Right) // goto l
...@@ -325,7 +325,7 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node { ...@@ -325,7 +325,7 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
} else { } else {
a.Left = le a.Left = le
} }
typecheck(&a.Left, Erv) a.Left = typecheck(a.Left, Erv)
a.Nbody.Set1(s.walkCases(cc[:half])) a.Nbody.Set1(s.walkCases(cc[:half]))
a.Rlist.Set1(s.walkCases(cc[half:])) a.Rlist.Set1(s.walkCases(cc[half:]))
return a return a
...@@ -526,7 +526,7 @@ func (s *typeSwitch) walk(sw *Node) { ...@@ -526,7 +526,7 @@ func (s *typeSwitch) walk(sw *Node) {
return return
} }
walkexpr(&cond.Right, &sw.Ninit) cond.Right = walkexpr(cond.Right, &sw.Ninit)
if !Istype(cond.Right.Type, TINTER) { if !Istype(cond.Right.Type, TINTER) {
Yyerror("type switch must be on an interface") Yyerror("type switch must be on an interface")
return return
...@@ -538,14 +538,14 @@ func (s *typeSwitch) walk(sw *Node) { ...@@ -538,14 +538,14 @@ func (s *typeSwitch) walk(sw *Node) {
s.facename = temp(cond.Right.Type) s.facename = temp(cond.Right.Type)
a := Nod(OAS, s.facename, cond.Right) a := Nod(OAS, s.facename, cond.Right)
typecheck(&a, Etop) a = typecheck(a, Etop)
cas = append(cas, a) cas = append(cas, a)
s.okname = temp(Types[TBOOL]) s.okname = temp(Types[TBOOL])
typecheck(&s.okname, Erv) s.okname = typecheck(s.okname, Erv)
s.hashname = temp(Types[TUINT32]) s.hashname = temp(Types[TUINT32])
typecheck(&s.hashname, Erv) s.hashname = typecheck(s.hashname, Erv)
// set up labels and jumps // set up labels and jumps
casebody(sw, s.facename) casebody(sw, s.facename)
...@@ -590,7 +590,7 @@ func (s *typeSwitch) walk(sw *Node) { ...@@ -590,7 +590,7 @@ func (s *typeSwitch) walk(sw *Node) {
blk.List.Set([]*Node{Nod(OLABEL, lbl, nil), def}) blk.List.Set([]*Node{Nod(OLABEL, lbl, nil), def})
def = blk def = blk
} }
typecheck(&i.Left, Erv) i.Left = typecheck(i.Left, Erv)
cas = append(cas, i) cas = append(cas, i)
if !isnilinter(cond.Right.Type) { if !isnilinter(cond.Right.Type) {
...@@ -608,7 +608,7 @@ func (s *typeSwitch) walk(sw *Node) { ...@@ -608,7 +608,7 @@ func (s *typeSwitch) walk(sw *Node) {
h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type
h.Bounded = true // guaranteed not to fault h.Bounded = true // guaranteed not to fault
a = Nod(OAS, s.hashname, h) a = Nod(OAS, s.hashname, h)
typecheck(&a, Etop) a = typecheck(a, Etop)
cas = append(cas, a) cas = append(cas, a)
// insert type equality check into each case block // insert type equality check into each case block
...@@ -680,12 +680,12 @@ func (s *typeSwitch) typeone(t *Node) *Node { ...@@ -680,12 +680,12 @@ func (s *typeSwitch) typeone(t *Node) *Node {
var init []*Node var init []*Node
if t.Rlist.Len() == 0 { if t.Rlist.Len() == 0 {
name = nblank name = nblank
typecheck(&nblank, Erv|Easgn) nblank = typecheck(nblank, Erv|Easgn)
} else { } else {
name = t.Rlist.First() name = t.Rlist.First()
init = []*Node{Nod(ODCL, name, nil)} init = []*Node{Nod(ODCL, name, nil)}
a := Nod(OAS, name, nil) a := Nod(OAS, name, nil)
typecheck(&a, Etop) a = typecheck(a, Etop)
init = append(init, a) init = append(init, a)
} }
...@@ -694,7 +694,7 @@ func (s *typeSwitch) typeone(t *Node) *Node { ...@@ -694,7 +694,7 @@ func (s *typeSwitch) typeone(t *Node) *Node {
b := Nod(ODOTTYPE, s.facename, nil) b := Nod(ODOTTYPE, s.facename, nil)
b.Type = t.Left.Type // interface.(type) b.Type = t.Left.Type // interface.(type)
a.Rlist.Set1(b) a.Rlist.Set1(b)
typecheck(&a, Etop) a = typecheck(a, Etop)
init = append(init, a) init = append(init, a)
c := Nod(OIF, nil, nil) c := Nod(OIF, nil, nil)
...@@ -715,7 +715,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node { ...@@ -715,7 +715,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
} }
a := Nod(OIF, nil, nil) a := Nod(OIF, nil, nil)
a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash))) 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) a.Nbody.Set1(n.Right)
cas = append(cas, a) cas = append(cas, a)
} }
...@@ -726,7 +726,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node { ...@@ -726,7 +726,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
half := len(cc) / 2 half := len(cc) / 2
a := Nod(OIF, nil, nil) a := Nod(OIF, nil, nil)
a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash))) 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.Nbody.Set1(s.walkCases(cc[:half]))
a.Rlist.Set1(s.walkCases(cc[half:])) a.Rlist.Set1(s.walkCases(cc[half:]))
return a return a
......
...@@ -36,7 +36,7 @@ func resolve(n *Node) *Node { ...@@ -36,7 +36,7 @@ func resolve(n *Node) *Node {
func typecheckslice(l []*Node, top int) { func typecheckslice(l []*Node, top int) {
for i := range l { for i := range l {
typecheck(&l[i], top) l[i] = typecheck(l[i], top)
} }
} }
...@@ -102,16 +102,15 @@ func sprint_depchain(fmt_ *string, stack []*Node, cur *Node, first *Node) { ...@@ -102,16 +102,15 @@ func sprint_depchain(fmt_ *string, stack []*Node, cur *Node, first *Node) {
var typecheck_tcstack []*Node var typecheck_tcstack []*Node
// typecheck type checks node *np. // typecheck type checks node n.
// It replaces *np with a new pointer in some cases. // The result of typecheck MUST be assigned back to n, e.g.
// It returns the final value of *np as a convenience. // n.Left = typecheck(n.Left, top)
func typecheck(np **Node, top int) *Node { func typecheck(n *Node, top int) *Node {
// cannot type check until all the source has been parsed // cannot type check until all the source has been parsed
if !typecheckok { if !typecheckok {
Fatalf("early typecheck") Fatalf("early typecheck")
} }
n := *np
if n == nil { if n == nil {
return nil return nil
} }
...@@ -126,8 +125,6 @@ func typecheck(np **Node, top int) *Node { ...@@ -126,8 +125,6 @@ func typecheck(np **Node, top int) *Node {
// Resolve definition of name and value of iota lazily. // Resolve definition of name and value of iota lazily.
n = resolve(n) n = resolve(n)
*np = n
// Skip typecheck if already done. // Skip typecheck if already done.
// But re-typecheck ONAME/OTYPE/OLITERAL/OPACK node in case context has changed. // But re-typecheck ONAME/OTYPE/OLITERAL/OPACK node in case context has changed.
if n.Typecheck == 1 { if n.Typecheck == 1 {
...@@ -177,8 +174,7 @@ func typecheck(np **Node, top int) *Node { ...@@ -177,8 +174,7 @@ func typecheck(np **Node, top int) *Node {
n.Typecheck = 2 n.Typecheck = 2
typecheck_tcstack = append(typecheck_tcstack, n) typecheck_tcstack = append(typecheck_tcstack, n)
typecheck1(&n, top) n = typecheck1(n, top)
*np = n
n.Typecheck = 1 n.Typecheck = 1
...@@ -227,25 +223,24 @@ func callrecvlist(l Nodes) bool { ...@@ -227,25 +223,24 @@ func callrecvlist(l Nodes) bool {
// array/slice indexes. It is equivalent to defaultlit // array/slice indexes. It is equivalent to defaultlit
// except for constants of numerical kind, which are acceptable // except for constants of numerical kind, which are acceptable
// whenever they can be represented by a value of type int. // whenever they can be represented by a value of type int.
func indexlit(np **Node) { // The result of indexlit MUST be assigned back to n, e.g.
n := *np // n.Left = indexlit(n.Left)
func indexlit(n *Node) *Node {
if n == nil || !isideal(n.Type) { if n == nil || !isideal(n.Type) {
return return n
} }
switch consttype(n) { switch consttype(n) {
case CTINT, CTRUNE, CTFLT, CTCPLX: case CTINT, CTRUNE, CTFLT, CTCPLX:
defaultlit(np, Types[TINT]) n = defaultlit(n, Types[TINT])
} }
defaultlit(np, nil) n = defaultlit(n, nil)
return n
} }
func typecheck1(np **Node, top int) { // The result of typecheck1 MUST be assigned back to n, e.g.
n := *np // n.Left = typecheck1(n.Left, top)
defer func() { func typecheck1(n *Node, top int) *Node {
*np = n
}()
switch n.Op { switch n.Op {
case OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER: case OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER:
// n.Sym is a field/method name, not a variable. // n.Sym is a field/method name, not a variable.
...@@ -254,13 +249,13 @@ func typecheck1(np **Node, top int) { ...@@ -254,13 +249,13 @@ func typecheck1(np **Node, top int) {
if n.Op == ONAME && n.Etype != 0 && top&Ecall == 0 { if n.Op == ONAME && n.Etype != 0 && top&Ecall == 0 {
Yyerror("use of builtin %v not in function call", n.Sym) Yyerror("use of builtin %v not in function call", n.Sym)
n.Type = nil n.Type = nil
return return n
} }
typecheckdef(n) typecheckdef(n)
if n.Op == ONONAME { if n.Op == ONONAME {
n.Type = nil n.Type = nil
return return n
} }
} }
} }
...@@ -301,7 +296,7 @@ OpSwitch: ...@@ -301,7 +296,7 @@ OpSwitch:
if isblank(n) { if isblank(n) {
Yyerror("cannot use _ as value") Yyerror("cannot use _ as value")
n.Type = nil n.Type = nil
return return n
} }
n.Used = true n.Used = true
...@@ -310,7 +305,7 @@ OpSwitch: ...@@ -310,7 +305,7 @@ OpSwitch:
if top&Ecall == 0 && isunsafebuiltin(n) { if top&Ecall == 0 && isunsafebuiltin(n) {
Yyerror("%v is not an expression, must be called", n) Yyerror("%v is not an expression, must be called", n)
n.Type = nil n.Type = nil
return return n
} }
ok |= Erv ok |= Erv
...@@ -319,7 +314,7 @@ OpSwitch: ...@@ -319,7 +314,7 @@ OpSwitch:
case OPACK: case OPACK:
Yyerror("use of package %v without selector", n.Sym) Yyerror("use of package %v without selector", n.Sym)
n.Type = nil n.Type = nil
return return n
case ODDD: case ODDD:
break break
...@@ -330,7 +325,7 @@ OpSwitch: ...@@ -330,7 +325,7 @@ OpSwitch:
if n.Type == nil { if n.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
case OTARRAY: case OTARRAY:
...@@ -348,7 +343,8 @@ OpSwitch: ...@@ -348,7 +343,8 @@ OpSwitch:
Yyerror("use of [...] array outside of array literal") Yyerror("use of [...] array outside of array literal")
} }
} else { } else {
l := typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
l := n.Left
var v Val var v Val
switch consttype(l) { switch consttype(l) {
case CTINT, CTRUNE: case CTINT, CTRUNE:
...@@ -364,25 +360,25 @@ OpSwitch: ...@@ -364,25 +360,25 @@ OpSwitch:
Yyerror("invalid array bound %v", l) Yyerror("invalid array bound %v", l)
} }
n.Type = nil n.Type = nil
return return n
} }
t.Bound = v.U.(*Mpint).Int64() t.Bound = v.U.(*Mpint).Int64()
if doesoverflow(v, Types[TINT]) { if doesoverflow(v, Types[TINT]) {
Yyerror("array bound is too large") Yyerror("array bound is too large")
n.Type = nil n.Type = nil
return return n
} else if t.Bound < 0 { } else if t.Bound < 0 {
Yyerror("array bound must be non-negative") Yyerror("array bound must be non-negative")
n.Type = nil n.Type = nil
return return n
} }
} }
typecheck(&r, Etype) r = typecheck(r, Etype)
if r.Type == nil { if r.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
t.Type = r.Type t.Type = r.Type
n.Op = OTYPE n.Op = OTYPE
...@@ -395,11 +391,13 @@ OpSwitch: ...@@ -395,11 +391,13 @@ OpSwitch:
case OTMAP: case OTMAP:
ok |= Etype ok |= Etype
l := typecheck(&n.Left, Etype) n.Left = typecheck(n.Left, Etype)
r := typecheck(&n.Right, Etype) n.Right = typecheck(n.Right, Etype)
l := n.Left
r := n.Right
if l.Type == nil || r.Type == nil { if l.Type == nil || r.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
n.Op = OTYPE n.Op = OTYPE
n.Type = maptype(l.Type, r.Type) n.Type = maptype(l.Type, r.Type)
...@@ -408,10 +406,11 @@ OpSwitch: ...@@ -408,10 +406,11 @@ OpSwitch:
case OTCHAN: case OTCHAN:
ok |= Etype ok |= Etype
l := typecheck(&n.Left, Etype) n.Left = typecheck(n.Left, Etype)
l := n.Left
if l.Type == nil { if l.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
t := typ(TCHAN) t := typ(TCHAN)
t.Type = l.Type t.Type = l.Type
...@@ -428,7 +427,7 @@ OpSwitch: ...@@ -428,7 +427,7 @@ OpSwitch:
n.Type = tostruct(n.List.Slice()) n.Type = tostruct(n.List.Slice())
if n.Type == nil || n.Type.Broke { if n.Type == nil || n.Type.Broke {
n.Type = nil n.Type = nil
return return n
} }
n.List.Set(nil) n.List.Set(nil)
...@@ -438,7 +437,7 @@ OpSwitch: ...@@ -438,7 +437,7 @@ OpSwitch:
n.Type = tointerface(n.List.Slice()) n.Type = tointerface(n.List.Slice())
if n.Type == nil { if n.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
case OTFUNC: case OTFUNC:
...@@ -447,7 +446,7 @@ OpSwitch: ...@@ -447,7 +446,7 @@ OpSwitch:
n.Type = functype(n.Left, n.List.Slice(), n.Rlist.Slice()) n.Type = functype(n.Left, n.List.Slice(), n.Rlist.Slice())
if n.Type == nil { if n.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
// type or expr // type or expr
...@@ -458,11 +457,12 @@ OpSwitch: ...@@ -458,11 +457,12 @@ OpSwitch:
ntop |= Eindir ntop |= Eindir
} }
ntop |= top & Ecomplit ntop |= top & Ecomplit
l := typecheck(&n.Left, ntop) n.Left = typecheck(n.Left, ntop)
l := n.Left
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if l.Op == OTYPE { if l.Op == OTYPE {
ok |= Etype ok |= Etype
...@@ -476,7 +476,7 @@ OpSwitch: ...@@ -476,7 +476,7 @@ OpSwitch:
if top&(Erv|Etop) != 0 { if top&(Erv|Etop) != 0 {
Yyerror("invalid indirect of %v", Nconv(n.Left, FmtLong)) Yyerror("invalid indirect of %v", Nconv(n.Left, FmtLong))
n.Type = nil n.Type = nil
return return n
} }
break OpSwitch break OpSwitch
...@@ -513,45 +513,49 @@ OpSwitch: ...@@ -513,45 +513,49 @@ OpSwitch:
var r *Node var r *Node
if n.Op == OASOP { if n.Op == OASOP {
ok |= Etop ok |= Etop
l = typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
r = typecheck(&n.Right, Erv) n.Right = typecheck(n.Right, Erv)
l = n.Left
r = n.Right
checkassign(n, n.Left) checkassign(n, n.Left)
if l.Type == nil || r.Type == nil { if l.Type == nil || r.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
if n.Implicit && !okforarith[l.Type.Etype] { if n.Implicit && !okforarith[l.Type.Etype] {
Yyerror("invalid operation: %v (non-numeric type %v)", n, l.Type) Yyerror("invalid operation: %v (non-numeric type %v)", n, l.Type)
n.Type = nil n.Type = nil
return return n
} }
// TODO(marvin): Fix Node.EType type union. // TODO(marvin): Fix Node.EType type union.
op = Op(n.Etype) op = Op(n.Etype)
} else { } else {
ok |= Erv ok |= Erv
l = typecheck(&n.Left, Erv|top&Eiota) n.Left = typecheck(n.Left, Erv|top&Eiota)
r = typecheck(&n.Right, Erv|top&Eiota) n.Right = typecheck(n.Right, Erv|top&Eiota)
l = n.Left
r = n.Right
if l.Type == nil || r.Type == nil { if l.Type == nil || r.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
op = n.Op op = n.Op
} }
if op == OLSH || op == ORSH { if op == OLSH || op == ORSH {
defaultlit(&r, Types[TUINT]) r = defaultlit(r, Types[TUINT])
n.Right = r n.Right = r
t := r.Type t := r.Type
if !Isint[t.Etype] || Issigned[t.Etype] { if !Isint[t.Etype] || Issigned[t.Etype] {
Yyerror("invalid operation: %v (shift count type %v, must be unsigned integer)", n, r.Type) Yyerror("invalid operation: %v (shift count type %v, must be unsigned integer)", n, r.Type)
n.Type = nil n.Type = nil
return return n
} }
t = l.Type t = l.Type
if t != nil && t.Etype != TIDEAL && !Isint[t.Etype] { if t != nil && t.Etype != TIDEAL && !Isint[t.Etype] {
Yyerror("invalid operation: %v (shift of type %v)", n, t) Yyerror("invalid operation: %v (shift of type %v)", n, t)
n.Type = nil n.Type = nil
return return n
} }
// no defaultlit for left // no defaultlit for left
...@@ -562,13 +566,13 @@ OpSwitch: ...@@ -562,13 +566,13 @@ OpSwitch:
} }
// ideal mixed with non-ideal // ideal mixed with non-ideal
defaultlit2(&l, &r, false) l, r = defaultlit2(l, r, false)
n.Left = l n.Left = l
n.Right = r n.Right = r
if l.Type == nil || r.Type == nil { if l.Type == nil || r.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
t := l.Type t := l.Type
if t.Etype == TIDEAL { if t.Etype == TIDEAL {
...@@ -593,7 +597,7 @@ OpSwitch: ...@@ -593,7 +597,7 @@ OpSwitch:
if Isinter(r.Type) && !Isinter(l.Type) && algtype1(l.Type, nil) == ANOEQ { if Isinter(r.Type) && !Isinter(l.Type) && algtype1(l.Type, nil) == ANOEQ {
Yyerror("invalid operation: %v (operator %v not defined on %s)", n, Oconv(op, 0), typekind(l.Type)) Yyerror("invalid operation: %v (operator %v not defined on %s)", n, Oconv(op, 0), typekind(l.Type))
n.Type = nil n.Type = nil
return return n
} }
dowidth(l.Type) dowidth(l.Type)
...@@ -615,7 +619,7 @@ OpSwitch: ...@@ -615,7 +619,7 @@ OpSwitch:
if Isinter(l.Type) && !Isinter(r.Type) && algtype1(r.Type, nil) == ANOEQ { if Isinter(l.Type) && !Isinter(r.Type) && algtype1(r.Type, nil) == ANOEQ {
Yyerror("invalid operation: %v (operator %v not defined on %s)", n, Oconv(op, 0), typekind(r.Type)) Yyerror("invalid operation: %v (operator %v not defined on %s)", n, Oconv(op, 0), typekind(r.Type))
n.Type = nil n.Type = nil
return return n
} }
dowidth(r.Type) dowidth(r.Type)
...@@ -635,18 +639,18 @@ OpSwitch: ...@@ -635,18 +639,18 @@ OpSwitch:
} }
if t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) { if t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
defaultlit2(&l, &r, true) l, r = defaultlit2(l, r, true)
if Isinter(r.Type) == Isinter(l.Type) || aop == 0 { if Isinter(r.Type) == Isinter(l.Type) || aop == 0 {
Yyerror("invalid operation: %v (mismatched types %v and %v)", n, l.Type, r.Type) Yyerror("invalid operation: %v (mismatched types %v and %v)", n, l.Type, r.Type)
n.Type = nil n.Type = nil
return return n
} }
} }
if !okfor[op][et] { if !okfor[op][et] {
Yyerror("invalid operation: %v (operator %v not defined on %s)", n, Oconv(op, 0), typekind(t)) Yyerror("invalid operation: %v (operator %v not defined on %s)", n, Oconv(op, 0), typekind(t))
n.Type = nil n.Type = nil
return return n
} }
// okfor allows any array == array, map == map, func == func. // okfor allows any array == array, map == map, func == func.
...@@ -654,32 +658,32 @@ OpSwitch: ...@@ -654,32 +658,32 @@ OpSwitch:
if Isfixedarray(l.Type) && algtype1(l.Type, nil) == ANOEQ { if Isfixedarray(l.Type) && algtype1(l.Type, nil) == ANOEQ {
Yyerror("invalid operation: %v (%v cannot be compared)", n, l.Type) Yyerror("invalid operation: %v (%v cannot be compared)", n, l.Type)
n.Type = nil n.Type = nil
return return n
} }
if Isslice(l.Type) && !isnil(l) && !isnil(r) { if Isslice(l.Type) && !isnil(l) && !isnil(r) {
Yyerror("invalid operation: %v (slice can only be compared to nil)", n) Yyerror("invalid operation: %v (slice can only be compared to nil)", n)
n.Type = nil n.Type = nil
return return n
} }
if l.Type.Etype == TMAP && !isnil(l) && !isnil(r) { if l.Type.Etype == TMAP && !isnil(l) && !isnil(r) {
Yyerror("invalid operation: %v (map can only be compared to nil)", n) Yyerror("invalid operation: %v (map can only be compared to nil)", n)
n.Type = nil n.Type = nil
return return n
} }
if l.Type.Etype == TFUNC && !isnil(l) && !isnil(r) { if l.Type.Etype == TFUNC && !isnil(l) && !isnil(r) {
Yyerror("invalid operation: %v (func can only be compared to nil)", n) Yyerror("invalid operation: %v (func can only be compared to nil)", n)
n.Type = nil n.Type = nil
return return n
} }
var badtype *Type var badtype *Type
if l.Type.Etype == TSTRUCT && algtype1(l.Type, &badtype) == ANOEQ { if l.Type.Etype == TSTRUCT && algtype1(l.Type, &badtype) == ANOEQ {
Yyerror("invalid operation: %v (struct containing %v cannot be compared)", n, badtype) Yyerror("invalid operation: %v (struct containing %v cannot be compared)", n, badtype)
n.Type = nil n.Type = nil
return return n
} }
t = l.Type t = l.Type
...@@ -687,7 +691,7 @@ OpSwitch: ...@@ -687,7 +691,7 @@ OpSwitch:
evconst(n) evconst(n)
t = idealbool t = idealbool
if n.Op != OLITERAL { if n.Op != OLITERAL {
defaultlit2(&l, &r, true) l, r = defaultlit2(l, r, true)
n.Left = l n.Left = l
n.Right = r n.Right = r
} }
...@@ -736,7 +740,7 @@ OpSwitch: ...@@ -736,7 +740,7 @@ OpSwitch:
if r.Val().U.(*Mpint).CmpInt64(0) == 0 { if r.Val().U.(*Mpint).CmpInt64(0) == 0 {
Yyerror("division by zero") Yyerror("division by zero")
n.Type = nil n.Type = nil
return return n
} }
} }
...@@ -745,16 +749,17 @@ OpSwitch: ...@@ -745,16 +749,17 @@ OpSwitch:
case OCOM, OMINUS, ONOT, OPLUS: case OCOM, OMINUS, ONOT, OPLUS:
ok |= Erv ok |= Erv
l := typecheck(&n.Left, Erv|top&Eiota) n.Left = typecheck(n.Left, Erv|top&Eiota)
l := n.Left
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if !okfor[n.Op][t.Etype] { if !okfor[n.Op][t.Etype] {
Yyerror("invalid operation: %v %v", Oconv(n.Op, 0), t) Yyerror("invalid operation: %v %v", Oconv(n.Op, 0), t)
n.Type = nil n.Type = nil
return return n
} }
n.Type = t n.Type = t
...@@ -764,10 +769,10 @@ OpSwitch: ...@@ -764,10 +769,10 @@ OpSwitch:
case OADDR: case OADDR:
ok |= Erv ok |= Erv
typecheck(&n.Left, Erv|Eaddr) n.Left = typecheck(n.Left, Erv|Eaddr)
if n.Left.Type == nil { if n.Left.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
checklvalue(n.Left, "take the address of") checklvalue(n.Left, "take the address of")
r := outervalue(n.Left) r := outervalue(n.Left)
...@@ -786,22 +791,22 @@ OpSwitch: ...@@ -786,22 +791,22 @@ OpSwitch:
if l.Name != nil && l.Name.Param != nil && l.Name.Param.Closure != nil { if l.Name != nil && l.Name.Param != nil && l.Name.Param.Closure != nil {
l.Name.Param.Closure.Addrtaken = true l.Name.Param.Closure.Addrtaken = true
} }
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
l = n.Left l = n.Left
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
n.Type = Ptrto(t) n.Type = Ptrto(t)
break OpSwitch break OpSwitch
case OCOMPLIT: case OCOMPLIT:
ok |= Erv ok |= Erv
typecheckcomplit(&n) n = typecheckcomplit(n)
if n.Type == nil { if n.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
break OpSwitch break OpSwitch
...@@ -811,19 +816,19 @@ OpSwitch: ...@@ -811,19 +816,19 @@ OpSwitch:
n.Op = ODOT n.Op = ODOT
if n.Left == nil { if n.Left == nil {
n.Type = nil n.Type = nil
return return n
} }
} }
typecheck(&n.Left, Erv|Etype) n.Left = typecheck(n.Left, Erv|Etype)
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
t := n.Left.Type t := n.Left.Type
if t == nil { if t == nil {
adderrorname(n) adderrorname(n)
n.Type = nil n.Type = nil
return return n
} }
s := n.Sym s := n.Sym
...@@ -836,14 +841,14 @@ OpSwitch: ...@@ -836,14 +841,14 @@ OpSwitch:
Yyerror("%v undefined (type %v has no method %v)", n, t, n.Sym) Yyerror("%v undefined (type %v has no method %v)", n, t, n.Sym)
} }
n.Type = nil n.Type = nil
return return n
} }
if n.Type.Etype != TFUNC || n.Type.Recv() == nil { if n.Type.Etype != TFUNC || n.Type.Recv() == nil {
Yyerror("type %v has no method %v", n.Left.Type, Sconv(n.Right.Sym, FmtShort)) Yyerror("type %v has no method %v", n.Left.Type, Sconv(n.Right.Sym, FmtShort))
n.Type = nil n.Type = nil
n.Type = nil n.Type = nil
return return n
} }
n.Op = ONAME n.Op = ONAME
...@@ -862,7 +867,7 @@ OpSwitch: ...@@ -862,7 +867,7 @@ OpSwitch:
t = t.Type t = t.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
n.Op = ODOTPTR n.Op = ODOTPTR
checkwidth(t) checkwidth(t)
...@@ -871,7 +876,7 @@ OpSwitch: ...@@ -871,7 +876,7 @@ OpSwitch:
if isblanksym(n.Sym) { if isblanksym(n.Sym) {
Yyerror("cannot refer to blank field or method") Yyerror("cannot refer to blank field or method")
n.Type = nil n.Type = nil
return return n
} }
if lookdot(n, t, 0) == nil { if lookdot(n, t, 0) == nil {
...@@ -896,7 +901,7 @@ OpSwitch: ...@@ -896,7 +901,7 @@ OpSwitch:
} }
} }
n.Type = nil n.Type = nil
return return n
} }
switch n.Op { switch n.Op {
...@@ -916,26 +921,26 @@ OpSwitch: ...@@ -916,26 +921,26 @@ OpSwitch:
case ODOTTYPE: case ODOTTYPE:
ok |= Erv ok |= Erv
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
l := n.Left l := n.Left
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if !Isinter(t) { if !Isinter(t) {
Yyerror("invalid type assertion: %v (non-interface type %v on left)", n, t) Yyerror("invalid type assertion: %v (non-interface type %v on left)", n, t)
n.Type = nil n.Type = nil
return return n
} }
if n.Right != nil { if n.Right != nil {
typecheck(&n.Right, Etype) n.Right = typecheck(n.Right, Etype)
n.Type = n.Right.Type n.Type = n.Right.Type
n.Right = nil n.Right = nil
if n.Type == nil { if n.Type == nil {
return return n
} }
} }
...@@ -953,7 +958,7 @@ OpSwitch: ...@@ -953,7 +958,7 @@ OpSwitch:
Yyerror("impossible type assertion:\n\t%v does not implement %v (missing %v method)", n.Type, t, missing.Sym) Yyerror("impossible type assertion:\n\t%v does not implement %v (missing %v method)", n.Type, t, missing.Sym)
} }
n.Type = nil n.Type = nil
return return n
} }
} }
...@@ -961,25 +966,25 @@ OpSwitch: ...@@ -961,25 +966,25 @@ OpSwitch:
case OINDEX: case OINDEX:
ok |= Erv ok |= Erv
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
implicitstar(&n.Left) n.Left = implicitstar(n.Left)
l := n.Left l := n.Left
typecheck(&n.Right, Erv) n.Right = typecheck(n.Right, Erv)
r := n.Right r := n.Right
t := l.Type t := l.Type
if t == nil || r.Type == nil { if t == nil || r.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
switch t.Etype { switch t.Etype {
default: default:
Yyerror("invalid operation: %v (type %v does not support indexing)", n, t) Yyerror("invalid operation: %v (type %v does not support indexing)", n, t)
n.Type = nil n.Type = nil
return return n
case TSTRING, TARRAY: case TSTRING, TARRAY:
indexlit(&n.Right) n.Right = indexlit(n.Right)
if t.Etype == TSTRING { if t.Etype == TSTRING {
n.Type = bytetype n.Type = bytetype
} else { } else {
...@@ -1014,7 +1019,7 @@ OpSwitch: ...@@ -1014,7 +1019,7 @@ OpSwitch:
case TMAP: case TMAP:
n.Etype = 0 n.Etype = 0
defaultlit(&n.Right, t.Key()) n.Right = defaultlit(n.Right, t.Key())
if n.Right.Type != nil { if n.Right.Type != nil {
n.Right = assignconv(n.Right, t.Key(), "map index") n.Right = assignconv(n.Right, t.Key(), "map index")
} }
...@@ -1026,24 +1031,24 @@ OpSwitch: ...@@ -1026,24 +1031,24 @@ OpSwitch:
case ORECV: case ORECV:
ok |= Etop | Erv ok |= Etop | Erv
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
l := n.Left l := n.Left
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if t.Etype != TCHAN { if t.Etype != TCHAN {
Yyerror("invalid operation: %v (receive from non-chan type %v)", n, t) Yyerror("invalid operation: %v (receive from non-chan type %v)", n, t)
n.Type = nil n.Type = nil
return return n
} }
if t.Chan&Crecv == 0 { if t.Chan&Crecv == 0 {
Yyerror("invalid operation: %v (receive from send-only type %v)", n, t) Yyerror("invalid operation: %v (receive from send-only type %v)", n, t)
n.Type = nil n.Type = nil
return return n
} }
n.Type = t.Type n.Type = t.Type
...@@ -1051,32 +1056,33 @@ OpSwitch: ...@@ -1051,32 +1056,33 @@ OpSwitch:
case OSEND: case OSEND:
ok |= Etop ok |= Etop
l := typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
typecheck(&n.Right, Erv) l := n.Left
defaultlit(&n.Left, nil) n.Right = typecheck(n.Right, Erv)
n.Left = defaultlit(n.Left, nil)
l = n.Left l = n.Left
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if t.Etype != TCHAN { if t.Etype != TCHAN {
Yyerror("invalid operation: %v (send to non-chan type %v)", n, t) Yyerror("invalid operation: %v (send to non-chan type %v)", n, t)
n.Type = nil n.Type = nil
return return n
} }
if t.Chan&Csend == 0 { if t.Chan&Csend == 0 {
Yyerror("invalid operation: %v (send to receive-only type %v)", n, t) Yyerror("invalid operation: %v (send to receive-only type %v)", n, t)
n.Type = nil n.Type = nil
return return n
} }
defaultlit(&n.Right, t.Type) n.Right = defaultlit(n.Right, t.Type)
r := n.Right r := n.Right
if r.Type == nil { if r.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
n.Right = assignconv(r, l.Type.Type, "send") n.Right = assignconv(r, l.Type.Type, "send")
...@@ -1088,30 +1094,30 @@ OpSwitch: ...@@ -1088,30 +1094,30 @@ OpSwitch:
case OSLICE: case OSLICE:
ok |= Erv ok |= Erv
typecheck(&n.Left, top) n.Left = typecheck(n.Left, top)
typecheck(&n.Right.Left, Erv) n.Right.Left = typecheck(n.Right.Left, Erv)
typecheck(&n.Right.Right, Erv) n.Right.Right = typecheck(n.Right.Right, Erv)
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
indexlit(&n.Right.Left) n.Right.Left = indexlit(n.Right.Left)
indexlit(&n.Right.Right) n.Right.Right = indexlit(n.Right.Right)
l := n.Left l := n.Left
if Isfixedarray(l.Type) { if Isfixedarray(l.Type) {
if !islvalue(n.Left) { if !islvalue(n.Left) {
Yyerror("invalid operation %v (slice of unaddressable value)", n) Yyerror("invalid operation %v (slice of unaddressable value)", n)
n.Type = nil n.Type = nil
return return n
} }
n.Left = Nod(OADDR, n.Left, nil) n.Left = Nod(OADDR, n.Left, nil)
n.Left.Implicit = true n.Left.Implicit = true
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
l = n.Left l = n.Left
} }
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
var tp *Type var tp *Type
if Istype(t, TSTRING) { if Istype(t, TSTRING) {
...@@ -1129,58 +1135,58 @@ OpSwitch: ...@@ -1129,58 +1135,58 @@ OpSwitch:
} else { } else {
Yyerror("cannot slice %v (type %v)", l, t) Yyerror("cannot slice %v (type %v)", l, t)
n.Type = nil n.Type = nil
return return n
} }
lo := n.Right.Left lo := n.Right.Left
if lo != nil && !checksliceindex(l, lo, tp) { if lo != nil && !checksliceindex(l, lo, tp) {
n.Type = nil n.Type = nil
return return n
} }
hi := n.Right.Right hi := n.Right.Right
if hi != nil && !checksliceindex(l, hi, tp) { if hi != nil && !checksliceindex(l, hi, tp) {
n.Type = nil n.Type = nil
return return n
} }
if !checksliceconst(lo, hi) { if !checksliceconst(lo, hi) {
n.Type = nil n.Type = nil
return return n
} }
break OpSwitch break OpSwitch
case OSLICE3: case OSLICE3:
ok |= Erv ok |= Erv
typecheck(&n.Left, top) n.Left = typecheck(n.Left, top)
typecheck(&n.Right.Left, Erv) n.Right.Left = typecheck(n.Right.Left, Erv)
typecheck(&n.Right.Right.Left, Erv) n.Right.Right.Left = typecheck(n.Right.Right.Left, Erv)
typecheck(&n.Right.Right.Right, Erv) n.Right.Right.Right = typecheck(n.Right.Right.Right, Erv)
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
indexlit(&n.Right.Left) n.Right.Left = indexlit(n.Right.Left)
indexlit(&n.Right.Right.Left) n.Right.Right.Left = indexlit(n.Right.Right.Left)
indexlit(&n.Right.Right.Right) n.Right.Right.Right = indexlit(n.Right.Right.Right)
l := n.Left l := n.Left
if Isfixedarray(l.Type) { if Isfixedarray(l.Type) {
if !islvalue(n.Left) { if !islvalue(n.Left) {
Yyerror("invalid operation %v (slice of unaddressable value)", n) Yyerror("invalid operation %v (slice of unaddressable value)", n)
n.Type = nil n.Type = nil
return return n
} }
n.Left = Nod(OADDR, n.Left, nil) n.Left = Nod(OADDR, n.Left, nil)
n.Left.Implicit = true n.Left.Implicit = true
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
l = n.Left l = n.Left
} }
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if Istype(t, TSTRING) { if Istype(t, TSTRING) {
Yyerror("invalid operation %v (3-index slice of string)", n) Yyerror("invalid operation %v (3-index slice of string)", n)
n.Type = nil n.Type = nil
return return n
} }
var tp *Type var tp *Type
...@@ -1196,27 +1202,27 @@ OpSwitch: ...@@ -1196,27 +1202,27 @@ OpSwitch:
} else { } else {
Yyerror("cannot slice %v (type %v)", l, t) Yyerror("cannot slice %v (type %v)", l, t)
n.Type = nil n.Type = nil
return return n
} }
lo := n.Right.Left lo := n.Right.Left
if lo != nil && !checksliceindex(l, lo, tp) { if lo != nil && !checksliceindex(l, lo, tp) {
n.Type = nil n.Type = nil
return return n
} }
mid := n.Right.Right.Left mid := n.Right.Right.Left
if mid != nil && !checksliceindex(l, mid, tp) { if mid != nil && !checksliceindex(l, mid, tp) {
n.Type = nil n.Type = nil
return return n
} }
hi := n.Right.Right.Right hi := n.Right.Right.Right
if hi != nil && !checksliceindex(l, hi, tp) { if hi != nil && !checksliceindex(l, hi, tp) {
n.Type = nil n.Type = nil
return return n
} }
if !checksliceconst(lo, hi) || !checksliceconst(lo, mid) || !checksliceconst(mid, hi) { if !checksliceconst(lo, hi) || !checksliceconst(lo, mid) || !checksliceconst(mid, hi) {
n.Type = nil n.Type = nil
return return n
} }
break OpSwitch break OpSwitch
...@@ -1231,12 +1237,12 @@ OpSwitch: ...@@ -1231,12 +1237,12 @@ OpSwitch:
Yyerror("invalid use of ... with builtin %v", l) Yyerror("invalid use of ... with builtin %v", l)
} }
n = r n = r
typecheck1(&n, top) n = typecheck1(n, top)
return return n
} }
} }
typecheck(&n.Left, Erv|Etype|Ecall|top&Eproc) n.Left = typecheck(n.Left, Erv|Etype|Ecall|top&Eproc)
n.Diag |= n.Left.Diag n.Diag |= n.Left.Diag
l = n.Left l = n.Left
if l.Op == ONAME && l.Etype != 0 { if l.Op == ONAME && l.Etype != 0 {
...@@ -1251,11 +1257,11 @@ OpSwitch: ...@@ -1251,11 +1257,11 @@ OpSwitch:
n.Left = n.Right n.Left = n.Right
n.Right = nil n.Right = nil
typecheck1(&n, top) n = typecheck1(n, top)
return return n
} }
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
l = n.Left l = n.Left
if l.Op == OTYPE { if l.Op == OTYPE {
if n.Isddd || l.Type.Bound == -100 { if n.Isddd || l.Type.Bound == -100 {
...@@ -1275,21 +1281,21 @@ OpSwitch: ...@@ -1275,21 +1281,21 @@ OpSwitch:
n.Type = l.Type n.Type = l.Type
if !onearg(n, "conversion to %v", l.Type) { if !onearg(n, "conversion to %v", l.Type) {
n.Type = nil n.Type = nil
return return n
} }
typecheck1(&n, top) n = typecheck1(n, top)
return return n
} }
if n.List.Len() == 1 && !n.Isddd { if n.List.Len() == 1 && !n.Isddd {
typecheck(n.List.Addr(0), Erv|Efnstruct) n.List.SetIndex(0, typecheck(n.List.Index(0), Erv|Efnstruct))
} else { } else {
typecheckslice(n.List.Slice(), Erv) typecheckslice(n.List.Slice(), Erv)
} }
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
checkwidth(t) checkwidth(t)
...@@ -1315,7 +1321,7 @@ OpSwitch: ...@@ -1315,7 +1321,7 @@ OpSwitch:
if t.Etype != TFUNC { if t.Etype != TFUNC {
Yyerror("cannot call non-function %v (type %v)", l, t) Yyerror("cannot call non-function %v (type %v)", l, t)
n.Type = nil n.Type = nil
return return n
} }
} }
...@@ -1355,16 +1361,16 @@ OpSwitch: ...@@ -1355,16 +1361,16 @@ OpSwitch:
ok |= Erv ok |= Erv
if !onearg(n, "%v", Oconv(n.Op, 0)) { if !onearg(n, "%v", Oconv(n.Op, 0)) {
n.Type = nil n.Type = nil
return return n
} }
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
implicitstar(&n.Left) n.Left = implicitstar(n.Left)
l := n.Left l := n.Left
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
switch n.Op { switch n.Op {
case OCAP: case OCAP:
...@@ -1424,7 +1430,7 @@ OpSwitch: ...@@ -1424,7 +1430,7 @@ OpSwitch:
badcall1: badcall1:
Yyerror("invalid argument %v for %v", Nconv(n.Left, FmtLong), Oconv(n.Op, 0)) Yyerror("invalid argument %v for %v", Nconv(n.Left, FmtLong), Oconv(n.Op, 0))
n.Type = nil n.Type = nil
return return n
case OCOMPLEX: case OCOMPLEX:
ok |= Erv ok |= Erv
...@@ -1435,14 +1441,14 @@ OpSwitch: ...@@ -1435,14 +1441,14 @@ OpSwitch:
if n.List.First().Op != OCALLFUNC && n.List.First().Op != OCALLMETH { if n.List.First().Op != OCALLFUNC && n.List.First().Op != OCALLMETH {
Yyerror("invalid operation: complex expects two arguments") Yyerror("invalid operation: complex expects two arguments")
n.Type = nil n.Type = nil
return return n
} }
t := n.List.First().Left.Type t := n.List.First().Left.Type
if t.Results().NumFields() != 2 { if t.Results().NumFields() != 2 {
Yyerror("invalid operation: complex expects two arguments, %v returns %d results", n.List.First(), t.Results().NumFields()) Yyerror("invalid operation: complex expects two arguments, %v returns %d results", n.List.First(), t.Results().NumFields())
n.Type = nil n.Type = nil
return return n
} }
t = n.List.First().Type t = n.List.First().Type
...@@ -1451,18 +1457,20 @@ OpSwitch: ...@@ -1451,18 +1457,20 @@ OpSwitch:
} else { } else {
if !twoarg(n) { if !twoarg(n) {
n.Type = nil n.Type = nil
return return n
} }
l = typecheck(&n.Left, Erv|top&Eiota) n.Left = typecheck(n.Left, Erv|top&Eiota)
r = typecheck(&n.Right, Erv|top&Eiota) n.Right = typecheck(n.Right, Erv|top&Eiota)
l = n.Left
r = n.Right
if l.Type == nil || r.Type == nil { if l.Type == nil || r.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
defaultlit2(&l, &r, false) l, r = defaultlit2(l, r, false)
if l.Type == nil || r.Type == nil { if l.Type == nil || r.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
n.Left = l n.Left = l
n.Right = r n.Right = r
...@@ -1471,7 +1479,7 @@ OpSwitch: ...@@ -1471,7 +1479,7 @@ OpSwitch:
if !Eqtype(l.Type, r.Type) { if !Eqtype(l.Type, r.Type) {
Yyerror("invalid operation: %v (mismatched types %v and %v)", n, l.Type, r.Type) Yyerror("invalid operation: %v (mismatched types %v and %v)", n, l.Type, r.Type)
n.Type = nil n.Type = nil
return return n
} }
var t *Type var t *Type
...@@ -1479,7 +1487,7 @@ OpSwitch: ...@@ -1479,7 +1487,7 @@ OpSwitch:
default: default:
Yyerror("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type) Yyerror("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type)
n.Type = nil n.Type = nil
return return n
case TIDEAL: case TIDEAL:
t = Types[TIDEAL] t = Types[TIDEAL]
...@@ -1505,26 +1513,26 @@ OpSwitch: ...@@ -1505,26 +1513,26 @@ OpSwitch:
case OCLOSE: case OCLOSE:
if !onearg(n, "%v", Oconv(n.Op, 0)) { if !onearg(n, "%v", Oconv(n.Op, 0)) {
n.Type = nil n.Type = nil
return return n
} }
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
l := n.Left l := n.Left
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if t.Etype != TCHAN { if t.Etype != TCHAN {
Yyerror("invalid operation: %v (non-chan type %v)", n, t) Yyerror("invalid operation: %v (non-chan type %v)", n, t)
n.Type = nil n.Type = nil
return return n
} }
if t.Chan&Csend == 0 { if t.Chan&Csend == 0 {
Yyerror("invalid operation: %v (cannot close receive-only channel)", n) Yyerror("invalid operation: %v (cannot close receive-only channel)", n)
n.Type = nil n.Type = nil
return return n
} }
ok |= Etop ok |= Etop
...@@ -1535,19 +1543,19 @@ OpSwitch: ...@@ -1535,19 +1543,19 @@ OpSwitch:
if args.Len() == 0 { if args.Len() == 0 {
Yyerror("missing arguments to delete") Yyerror("missing arguments to delete")
n.Type = nil n.Type = nil
return return n
} }
if args.Len() == 1 { if args.Len() == 1 {
Yyerror("missing second (key) argument to delete") Yyerror("missing second (key) argument to delete")
n.Type = nil n.Type = nil
return return n
} }
if args.Len() != 2 { if args.Len() != 2 {
Yyerror("too many arguments to delete") Yyerror("too many arguments to delete")
n.Type = nil n.Type = nil
return return n
} }
ok |= Etop ok |= Etop
...@@ -1557,7 +1565,7 @@ OpSwitch: ...@@ -1557,7 +1565,7 @@ OpSwitch:
if l.Type != nil && l.Type.Etype != TMAP { if l.Type != nil && l.Type.Etype != TMAP {
Yyerror("first argument to delete must be map; have %v", Tconv(l.Type, FmtLong)) Yyerror("first argument to delete must be map; have %v", Tconv(l.Type, FmtLong))
n.Type = nil n.Type = nil
return return n
} }
args.SetIndex(1, assignconv(r, l.Type.Key(), "delete")) args.SetIndex(1, assignconv(r, l.Type.Key(), "delete"))
...@@ -1569,11 +1577,11 @@ OpSwitch: ...@@ -1569,11 +1577,11 @@ OpSwitch:
if args.Len() == 0 { if args.Len() == 0 {
Yyerror("missing arguments to append") Yyerror("missing arguments to append")
n.Type = nil n.Type = nil
return return n
} }
if args.Len() == 1 && !n.Isddd { if args.Len() == 1 && !n.Isddd {
typecheck(args.Addr(0), Erv|Efnstruct) args.SetIndex(0, typecheck(args.Index(0), Erv|Efnstruct))
} else { } else {
typecheckslice(args.Slice(), Erv) typecheckslice(args.Slice(), Erv)
} }
...@@ -1581,7 +1589,7 @@ OpSwitch: ...@@ -1581,7 +1589,7 @@ OpSwitch:
t := args.First().Type t := args.First().Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
// Unpack multiple-return result before type-checking. // Unpack multiple-return result before type-checking.
...@@ -1596,29 +1604,29 @@ OpSwitch: ...@@ -1596,29 +1604,29 @@ OpSwitch:
if Isconst(args.First(), CTNIL) { if Isconst(args.First(), CTNIL) {
Yyerror("first argument to append must be typed slice; have untyped nil") Yyerror("first argument to append must be typed slice; have untyped nil")
n.Type = nil n.Type = nil
return return n
} }
Yyerror("first argument to append must be slice; have %v", Tconv(t, FmtLong)) Yyerror("first argument to append must be slice; have %v", Tconv(t, FmtLong))
n.Type = nil n.Type = nil
return return n
} }
if n.Isddd { if n.Isddd {
if args.Len() == 1 { if args.Len() == 1 {
Yyerror("cannot use ... on first argument to append") Yyerror("cannot use ... on first argument to append")
n.Type = nil n.Type = nil
return return n
} }
if args.Len() != 2 { if args.Len() != 2 {
Yyerror("too many arguments to append") Yyerror("too many arguments to append")
n.Type = nil n.Type = nil
return return n
} }
if Istype(t.Type, TUINT8) && Istype(args.Second().Type, TSTRING) { if Istype(t.Type, TUINT8) && Istype(args.Second().Type, TSTRING) {
defaultlit(args.Addr(1), Types[TSTRING]) args.SetIndex(1, defaultlit(args.Index(1), Types[TSTRING]))
break OpSwitch break OpSwitch
} }
...@@ -1651,30 +1659,30 @@ OpSwitch: ...@@ -1651,30 +1659,30 @@ OpSwitch:
if args.Len() < 2 { if args.Len() < 2 {
Yyerror("missing arguments to copy") Yyerror("missing arguments to copy")
n.Type = nil n.Type = nil
return return n
} }
if args.Len() > 2 { if args.Len() > 2 {
Yyerror("too many arguments to copy") Yyerror("too many arguments to copy")
n.Type = nil n.Type = nil
return return n
} }
n.Left = args.First() n.Left = args.First()
n.Right = args.Second() n.Right = args.Second()
n.List.Set(nil) n.List.Set(nil)
n.Type = Types[TINT] n.Type = Types[TINT]
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
typecheck(&n.Right, Erv) n.Right = typecheck(n.Right, Erv)
if n.Left.Type == nil || n.Right.Type == nil { if n.Left.Type == nil || n.Right.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
defaultlit(&n.Left, nil) n.Left = defaultlit(n.Left, nil)
defaultlit(&n.Right, nil) n.Right = defaultlit(n.Right, nil)
if n.Left.Type == nil || n.Right.Type == nil { if n.Left.Type == nil || n.Right.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
// copy([]byte, string) // copy([]byte, string)
...@@ -1684,7 +1692,7 @@ OpSwitch: ...@@ -1684,7 +1692,7 @@ OpSwitch:
} }
Yyerror("arguments to copy have different element types: %v and string", Tconv(n.Left.Type, FmtLong)) Yyerror("arguments to copy have different element types: %v and string", Tconv(n.Left.Type, FmtLong))
n.Type = nil n.Type = nil
return return n
} }
if !Isslice(n.Left.Type) || !Isslice(n.Right.Type) { if !Isslice(n.Left.Type) || !Isslice(n.Right.Type) {
...@@ -1696,13 +1704,13 @@ OpSwitch: ...@@ -1696,13 +1704,13 @@ OpSwitch:
Yyerror("second argument to copy should be slice or string; have %v", Tconv(n.Right.Type, FmtLong)) Yyerror("second argument to copy should be slice or string; have %v", Tconv(n.Right.Type, FmtLong))
} }
n.Type = nil n.Type = nil
return return n
} }
if !Eqtype(n.Left.Type.Type, n.Right.Type.Type) { if !Eqtype(n.Left.Type.Type, n.Right.Type.Type) {
Yyerror("arguments to copy have different element types: %v and %v", Tconv(n.Left.Type, FmtLong), Tconv(n.Right.Type, FmtLong)) Yyerror("arguments to copy have different element types: %v and %v", Tconv(n.Left.Type, FmtLong), Tconv(n.Right.Type, FmtLong))
n.Type = nil n.Type = nil
return return n
} }
break OpSwitch break OpSwitch
...@@ -1710,12 +1718,12 @@ OpSwitch: ...@@ -1710,12 +1718,12 @@ OpSwitch:
case OCONV: case OCONV:
ok |= Erv ok |= Erv
saveorignode(n) saveorignode(n)
typecheck(&n.Left, Erv|top&(Eindir|Eiota)) n.Left = typecheck(n.Left, Erv|top&(Eindir|Eiota))
convlit1(&n.Left, n.Type, true) n.Left = convlit1(n.Left, n.Type, true)
t := n.Left.Type t := n.Left.Type
if t == nil || n.Type == nil { if t == nil || n.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
var why string var why string
n.Op = convertop(t, n.Type, &why) n.Op = convertop(t, n.Type, &why)
...@@ -1746,7 +1754,7 @@ OpSwitch: ...@@ -1746,7 +1754,7 @@ OpSwitch:
case OSTRARRAYRUNE: case OSTRARRAYRUNE:
if n.Left.Op == OLITERAL { if n.Left.Op == OLITERAL {
stringtoarraylit(&n) n = stringtoarraylit(n)
} }
} }
...@@ -1758,16 +1766,16 @@ OpSwitch: ...@@ -1758,16 +1766,16 @@ OpSwitch:
if len(args) == 0 { if len(args) == 0 {
Yyerror("missing argument to make") Yyerror("missing argument to make")
n.Type = nil n.Type = nil
return return n
} }
n.List.Set(nil) n.List.Set(nil)
l := args[0] l := args[0]
typecheck(&l, Etype) l = typecheck(l, Etype)
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
i := 1 i := 1
...@@ -1775,43 +1783,43 @@ OpSwitch: ...@@ -1775,43 +1783,43 @@ OpSwitch:
default: default:
Yyerror("cannot make type %v", t) Yyerror("cannot make type %v", t)
n.Type = nil n.Type = nil
return return n
case TARRAY: case TARRAY:
if !Isslice(t) { if !Isslice(t) {
Yyerror("cannot make type %v", t) Yyerror("cannot make type %v", t)
n.Type = nil n.Type = nil
return return n
} }
if i >= len(args) { if i >= len(args) {
Yyerror("missing len argument to make(%v)", t) Yyerror("missing len argument to make(%v)", t)
n.Type = nil n.Type = nil
return return n
} }
l = args[i] l = args[i]
i++ i++
typecheck(&l, Erv) l = typecheck(l, Erv)
var r *Node var r *Node
if i < len(args) { if i < len(args) {
r = args[i] r = args[i]
i++ i++
typecheck(&r, Erv) r = typecheck(r, Erv)
} }
if l.Type == nil || (r != nil && r.Type == nil) { if l.Type == nil || (r != nil && r.Type == nil) {
n.Type = nil n.Type = nil
return return n
} }
if !checkmake(t, "len", l) || r != nil && !checkmake(t, "cap", r) { if !checkmake(t, "len", l) || r != nil && !checkmake(t, "cap", r) {
n.Type = nil n.Type = nil
return return n
} }
if Isconst(l, CTINT) && r != nil && Isconst(r, CTINT) && l.Val().U.(*Mpint).Cmp(r.Val().U.(*Mpint)) > 0 { if Isconst(l, CTINT) && r != nil && Isconst(r, CTINT) && l.Val().U.(*Mpint).Cmp(r.Val().U.(*Mpint)) > 0 {
Yyerror("len larger than cap in make(%v)", t) Yyerror("len larger than cap in make(%v)", t)
n.Type = nil n.Type = nil
return return n
} }
n.Left = l n.Left = l
...@@ -1822,15 +1830,15 @@ OpSwitch: ...@@ -1822,15 +1830,15 @@ OpSwitch:
if i < len(args) { if i < len(args) {
l = args[i] l = args[i]
i++ i++
typecheck(&l, Erv) l = typecheck(l, Erv)
defaultlit(&l, Types[TINT]) l = defaultlit(l, Types[TINT])
if l.Type == nil { if l.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
if !checkmake(t, "size", l) { if !checkmake(t, "size", l) {
n.Type = nil n.Type = nil
return return n
} }
n.Left = l n.Left = l
} else { } else {
...@@ -1843,15 +1851,15 @@ OpSwitch: ...@@ -1843,15 +1851,15 @@ OpSwitch:
if i < len(args) { if i < len(args) {
l = args[i] l = args[i]
i++ i++
typecheck(&l, Erv) l = typecheck(l, Erv)
defaultlit(&l, Types[TINT]) l = defaultlit(l, Types[TINT])
if l.Type == nil { if l.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
if !checkmake(t, "buffer", l) { if !checkmake(t, "buffer", l) {
n.Type = nil n.Type = nil
return return n
} }
n.Left = l n.Left = l
} else { } else {
...@@ -1864,7 +1872,7 @@ OpSwitch: ...@@ -1864,7 +1872,7 @@ OpSwitch:
Yyerror("too many arguments to make(%v)", t) Yyerror("too many arguments to make(%v)", t)
n.Op = OMAKE n.Op = OMAKE
n.Type = nil n.Type = nil
return return n
} }
n.Type = t n.Type = t
...@@ -1876,20 +1884,20 @@ OpSwitch: ...@@ -1876,20 +1884,20 @@ OpSwitch:
if args.Len() == 0 { if args.Len() == 0 {
Yyerror("missing argument to new") Yyerror("missing argument to new")
n.Type = nil n.Type = nil
return return n
} }
l := args.First() l := args.First()
typecheck(&l, Etype) l = typecheck(l, Etype)
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if args.Len() > 1 { if args.Len() > 1 {
Yyerror("too many arguments to new(%v)", t) Yyerror("too many arguments to new(%v)", t)
n.Type = nil n.Type = nil
return return n
} }
n.Left = l n.Left = l
...@@ -1903,9 +1911,9 @@ OpSwitch: ...@@ -1903,9 +1911,9 @@ OpSwitch:
for i1, n1 := range ls { for i1, n1 := range ls {
// Special case for print: int constant is int64, not int. // Special case for print: int constant is int64, not int.
if Isconst(n1, CTINT) { if Isconst(n1, CTINT) {
defaultlit(&ls[i1], Types[TINT64]) ls[i1] = defaultlit(ls[i1], Types[TINT64])
} else { } else {
defaultlit(&ls[i1], nil) ls[i1] = defaultlit(ls[i1], nil)
} }
} }
...@@ -1915,13 +1923,13 @@ OpSwitch: ...@@ -1915,13 +1923,13 @@ OpSwitch:
ok |= Etop ok |= Etop
if !onearg(n, "panic") { if !onearg(n, "panic") {
n.Type = nil n.Type = nil
return return n
} }
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
defaultlit(&n.Left, Types[TINTER]) n.Left = defaultlit(n.Left, Types[TINTER])
if n.Left.Type == nil { if n.Left.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
break OpSwitch break OpSwitch
...@@ -1930,7 +1938,7 @@ OpSwitch: ...@@ -1930,7 +1938,7 @@ OpSwitch:
if n.List.Len() != 0 { if n.List.Len() != 0 {
Yyerror("too many arguments to recover") Yyerror("too many arguments to recover")
n.Type = nil n.Type = nil
return return n
} }
n.Type = Types[TINTER] n.Type = Types[TINTER]
...@@ -1941,17 +1949,17 @@ OpSwitch: ...@@ -1941,17 +1949,17 @@ OpSwitch:
typecheckclosure(n, top) typecheckclosure(n, top)
if n.Type == nil { if n.Type == nil {
n.Type = nil n.Type = nil
return return n
} }
break OpSwitch break OpSwitch
case OITAB: case OITAB:
ok |= Erv ok |= Erv
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
t := n.Left.Type t := n.Left.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if t.Etype != TINTER { if t.Etype != TINTER {
Fatalf("OITAB of %v", t) Fatalf("OITAB of %v", t)
...@@ -1961,11 +1969,11 @@ OpSwitch: ...@@ -1961,11 +1969,11 @@ OpSwitch:
case OSPTR: case OSPTR:
ok |= Erv ok |= Erv
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
t := n.Left.Type t := n.Left.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
if !Isslice(t) && t.Etype != TSTRING { if !Isslice(t) && t.Etype != TSTRING {
Fatalf("OSPTR of %v", t) Fatalf("OSPTR of %v", t)
...@@ -1983,13 +1991,13 @@ OpSwitch: ...@@ -1983,13 +1991,13 @@ OpSwitch:
case OCFUNC: case OCFUNC:
ok |= Erv ok |= Erv
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
n.Type = Types[TUINTPTR] n.Type = Types[TUINTPTR]
break OpSwitch break OpSwitch
case OCONVNOP: case OCONVNOP:
ok |= Erv ok |= Erv
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
break OpSwitch break OpSwitch
// statements // statements
...@@ -2027,7 +2035,7 @@ OpSwitch: ...@@ -2027,7 +2035,7 @@ OpSwitch:
case ODEFER: case ODEFER:
ok |= Etop ok |= Etop
typecheck(&n.Left, Etop|Erv) n.Left = typecheck(n.Left, Etop|Erv)
if n.Left.Diag == 0 { if n.Left.Diag == 0 {
checkdefergo(n) checkdefergo(n)
} }
...@@ -2035,7 +2043,7 @@ OpSwitch: ...@@ -2035,7 +2043,7 @@ OpSwitch:
case OPROC: case OPROC:
ok |= Etop ok |= Etop
typecheck(&n.Left, Etop|Eproc|Erv) n.Left = typecheck(n.Left, Etop|Eproc|Erv)
checkdefergo(n) checkdefergo(n)
break OpSwitch break OpSwitch
...@@ -2043,14 +2051,14 @@ OpSwitch: ...@@ -2043,14 +2051,14 @@ OpSwitch:
ok |= Etop ok |= Etop
typecheckslice(n.Ninit.Slice(), Etop) typecheckslice(n.Ninit.Slice(), Etop)
decldepth++ decldepth++
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
if n.Left != nil { if n.Left != nil {
t := n.Left.Type t := n.Left.Type
if t != nil && t.Etype != TBOOL { if t != nil && t.Etype != TBOOL {
Yyerror("non-bool %v used as for condition", Nconv(n.Left, FmtLong)) Yyerror("non-bool %v used as for condition", Nconv(n.Left, FmtLong))
} }
} }
typecheck(&n.Right, Etop) n.Right = typecheck(n.Right, Etop)
typecheckslice(n.Nbody.Slice(), Etop) typecheckslice(n.Nbody.Slice(), Etop)
decldepth-- decldepth--
break OpSwitch break OpSwitch
...@@ -2058,7 +2066,7 @@ OpSwitch: ...@@ -2058,7 +2066,7 @@ OpSwitch:
case OIF: case OIF:
ok |= Etop ok |= Etop
typecheckslice(n.Ninit.Slice(), Etop) typecheckslice(n.Ninit.Slice(), Etop)
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
if n.Left != nil { if n.Left != nil {
t := n.Left.Type t := n.Left.Type
if t != nil && t.Etype != TBOOL { if t != nil && t.Etype != TBOOL {
...@@ -2079,7 +2087,7 @@ OpSwitch: ...@@ -2079,7 +2087,7 @@ OpSwitch:
if Curfn == nil { if Curfn == nil {
Yyerror("return outside function") Yyerror("return outside function")
n.Type = nil n.Type = nil
return return n
} }
if Curfn.Type.Outnamed && n.List.Len() == 0 { if Curfn.Type.Outnamed && n.List.Len() == 0 {
...@@ -2110,7 +2118,7 @@ OpSwitch: ...@@ -2110,7 +2118,7 @@ OpSwitch:
case OTYPESW: case OTYPESW:
Yyerror("use of .(type) outside type switch") Yyerror("use of .(type) outside type switch")
n.Type = nil n.Type = nil
return return n
case OXCASE: case OXCASE:
ok |= Etop ok |= Etop
...@@ -2125,12 +2133,12 @@ OpSwitch: ...@@ -2125,12 +2133,12 @@ OpSwitch:
case ODCLCONST: case ODCLCONST:
ok |= Etop ok |= Etop
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
break OpSwitch break OpSwitch
case ODCLTYPE: case ODCLTYPE:
ok |= Etop ok |= Etop
typecheck(&n.Left, Etype) n.Left = typecheck(n.Left, Etype)
if incannedimport == 0 { if incannedimport == 0 {
checkwidth(n.Left.Type) checkwidth(n.Left.Type)
} }
...@@ -2161,20 +2169,20 @@ OpSwitch: ...@@ -2161,20 +2169,20 @@ OpSwitch:
if n.Op == OTYPE && top&Etype == 0 { if n.Op == OTYPE && top&Etype == 0 {
Yyerror("type %v is not an expression", n.Type) Yyerror("type %v is not an expression", n.Type)
n.Type = nil n.Type = nil
return return n
} }
if top&(Erv|Etype) == Etype && n.Op != OTYPE { if top&(Erv|Etype) == Etype && n.Op != OTYPE {
Yyerror("%v is not a type", n) Yyerror("%v is not a type", n)
n.Type = nil n.Type = nil
return return n
} }
// TODO(rsc): simplify // TODO(rsc): simplify
if (top&(Ecall|Erv|Etype) != 0) && top&Etop == 0 && ok&(Erv|Etype|Ecall) == 0 { if (top&(Ecall|Erv|Etype) != 0) && top&Etop == 0 && ok&(Erv|Etype|Ecall) == 0 {
Yyerror("%v used as value", n) Yyerror("%v used as value", n)
n.Type = nil n.Type = nil
return return n
} }
if (top&Etop != 0) && top&(Ecall|Erv|Etype) == 0 && ok&Etop == 0 { if (top&Etop != 0) && top&(Ecall|Erv|Etype) == 0 && ok&Etop == 0 {
...@@ -2184,13 +2192,14 @@ OpSwitch: ...@@ -2184,13 +2192,14 @@ OpSwitch:
} }
n.Type = nil n.Type = nil
return return n
} }
/* TODO /* TODO
if(n->type == T) if(n->type == T)
fatal("typecheck nil type"); fatal("typecheck nil type");
*/ */
return n
} }
func checksliceindex(l *Node, r *Node, tp *Type) bool { func checksliceindex(l *Node, r *Node, tp *Type) bool {
...@@ -2285,25 +2294,25 @@ func checkdefergo(n *Node) { ...@@ -2285,25 +2294,25 @@ func checkdefergo(n *Node) {
} }
} }
func implicitstar(nn **Node) { // The result of implicitstar MUST be assigned back to n, e.g.
// n.Left = implicitstar(n.Left)
func implicitstar(n *Node) *Node {
// insert implicit * if needed for fixed array // insert implicit * if needed for fixed array
n := *nn
t := n.Type t := n.Type
if t == nil || !Isptr[t.Etype] { if t == nil || !Isptr[t.Etype] {
return return n
} }
t = t.Type t = t.Type
if t == nil { if t == nil {
return return n
} }
if !Isfixedarray(t) { if !Isfixedarray(t) {
return return n
} }
n = Nod(OIND, n, nil) n = Nod(OIND, n, nil)
n.Implicit = true n.Implicit = true
typecheck(&n, Erv) n = typecheck(n, Erv)
*nn = n return n
} }
func onearg(n *Node, f string, args ...interface{}) bool { func onearg(n *Node, f string, args ...interface{}) bool {
...@@ -2482,7 +2491,7 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Field { ...@@ -2482,7 +2491,7 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Field {
if Isptr[n.Left.Type.Etype] { if Isptr[n.Left.Type.Etype] {
n.Left = Nod(OIND, n.Left, nil) // implicitstar n.Left = Nod(OIND, n.Left, nil) // implicitstar
n.Left.Implicit = true n.Left.Implicit = true
typecheck(&n.Left, Erv) n.Left = typecheck(n.Left, Erv)
} }
n.Op = ODOTINTER n.Op = ODOTINTER
...@@ -2504,11 +2513,11 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Field { ...@@ -2504,11 +2513,11 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Field {
checklvalue(n.Left, "call pointer method on") checklvalue(n.Left, "call pointer method on")
n.Left = Nod(OADDR, n.Left, nil) n.Left = Nod(OADDR, n.Left, nil)
n.Left.Implicit = true n.Left.Implicit = true
typecheck(&n.Left, Etype|Erv) n.Left = typecheck(n.Left, Etype|Erv)
} else if tt.Etype == Tptr && rcvr.Etype != Tptr && Eqtype(tt.Type, rcvr) { } else if tt.Etype == Tptr && rcvr.Etype != Tptr && Eqtype(tt.Type, rcvr) {
n.Left = Nod(OIND, n.Left, nil) n.Left = Nod(OIND, n.Left, nil)
n.Left.Implicit = true n.Left.Implicit = true
typecheck(&n.Left, Etype|Erv) n.Left = typecheck(n.Left, Etype|Erv)
} else if tt.Etype == Tptr && tt.Type.Etype == Tptr && Eqtype(derefall(tt), derefall(rcvr)) { } else if tt.Etype == Tptr && tt.Type.Etype == Tptr && Eqtype(derefall(tt), derefall(rcvr)) {
Yyerror("calling method %v with receiver %v requires explicit dereference", n.Sym, Nconv(n.Left, FmtLong)) Yyerror("calling method %v with receiver %v requires explicit dereference", n.Sym, Nconv(n.Left, FmtLong))
for tt.Etype == Tptr { for tt.Etype == Tptr {
...@@ -2518,7 +2527,7 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Field { ...@@ -2518,7 +2527,7 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Field {
} }
n.Left = Nod(OIND, n.Left, nil) n.Left = Nod(OIND, n.Left, nil)
n.Left.Implicit = true n.Left.Implicit = true
typecheck(&n.Left, Etype|Erv) n.Left = typecheck(n.Left, Etype|Erv)
tt = tt.Type tt = tt.Type
} }
} else { } else {
...@@ -2867,7 +2876,7 @@ func pushtype(n *Node, t *Type) { ...@@ -2867,7 +2876,7 @@ func pushtype(n *Node, t *Type) {
n.Implicit = true // don't print n.Implicit = true // don't print
n.Right.Implicit = true // * is okay n.Right.Implicit = true // * is okay
} else if Debug['s'] != 0 { } else if Debug['s'] != 0 {
typecheck(&n.Right, Etype) n.Right = typecheck(n.Right, Etype)
if n.Right.Type != nil && Eqtype(n.Right.Type, t) { if n.Right.Type != nil && Eqtype(n.Right.Type, t) {
fmt.Printf("%v: redundant type: %v\n", n.Line(), t) fmt.Printf("%v: redundant type: %v\n", n.Line(), t)
} }
...@@ -2879,12 +2888,12 @@ func pushtype(n *Node, t *Type) { ...@@ -2879,12 +2888,12 @@ func pushtype(n *Node, t *Type) {
// TODO(mdempsky): Find a nicer solution. // TODO(mdempsky): Find a nicer solution.
var structkey = typ(Txxx) var structkey = typ(Txxx)
func typecheckcomplit(np **Node) { // The result of typecheckcomplit MUST be assigned back to n, e.g.
n := *np // n.Left = typecheckcomplit(n.Left)
func typecheckcomplit(n *Node) *Node {
lno := lineno lno := lineno
defer func() { defer func() {
lineno = lno lineno = lno
*np = n
}() }()
if n.Right == nil { if n.Right == nil {
...@@ -2893,7 +2902,7 @@ func typecheckcomplit(np **Node) { ...@@ -2893,7 +2902,7 @@ func typecheckcomplit(np **Node) {
} }
Yyerror("missing type in composite literal") Yyerror("missing type in composite literal")
n.Type = nil n.Type = nil
return return n
} }
// Save original node (including n->right) // Save original node (including n->right)
...@@ -2902,11 +2911,12 @@ func typecheckcomplit(np **Node) { ...@@ -2902,11 +2911,12 @@ func typecheckcomplit(np **Node) {
*norig = *n *norig = *n
setlineno(n.Right) setlineno(n.Right)
l := typecheck(&n.Right, Etype|Ecomplit) // sic n.Right = typecheck(n.Right, Etype|Ecomplit)
l := n.Right // sic
t := l.Type t := l.Type
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return return n
} }
nerr := nerrors nerr := nerrors
n.Type = t n.Type = t
...@@ -2917,14 +2927,14 @@ func typecheckcomplit(np **Node) { ...@@ -2917,14 +2927,14 @@ func typecheckcomplit(np **Node) {
if !n.Right.Implicit { if !n.Right.Implicit {
Yyerror("invalid pointer type %v for composite literal (use &%v instead)", t, t.Type) Yyerror("invalid pointer type %v for composite literal (use &%v instead)", t, t.Type)
n.Type = nil n.Type = nil
return return n
} }
// Also, the underlying type must be a struct, map, slice, or array. // Also, the underlying type must be a struct, map, slice, or array.
if !iscomptype(t) { if !iscomptype(t) {
Yyerror("invalid pointer type %v for composite literal", t) Yyerror("invalid pointer type %v for composite literal", t)
n.Type = nil n.Type = nil
return return n
} }
t = t.Type t = t.Type
...@@ -2957,7 +2967,7 @@ func typecheckcomplit(np **Node) { ...@@ -2957,7 +2967,7 @@ func typecheckcomplit(np **Node) {
n.List.SetIndex(i2, l) n.List.SetIndex(i2, l)
} }
typecheck(&l.Left, Erv) l.Left = typecheck(l.Left, Erv)
evconst(l.Left) evconst(l.Left)
i = nonnegconst(l.Left) i = nonnegconst(l.Left)
if i < 0 && l.Left.Diag == 0 { if i < 0 && l.Left.Diag == 0 {
...@@ -2981,8 +2991,8 @@ func typecheckcomplit(np **Node) { ...@@ -2981,8 +2991,8 @@ func typecheckcomplit(np **Node) {
r = l.Right r = l.Right
pushtype(r, t.Type) pushtype(r, t.Type)
typecheck(&r, Erv) r = typecheck(r, Erv)
defaultlit(&r, t.Type) r = defaultlit(r, t.Type)
l.Right = assignconv(r, t.Type, "array or slice literal") l.Right = assignconv(r, t.Type, "array or slice literal")
} }
...@@ -3001,15 +3011,15 @@ func typecheckcomplit(np **Node) { ...@@ -3001,15 +3011,15 @@ func typecheckcomplit(np **Node) {
l = n3 l = n3
setlineno(l) setlineno(l)
if l.Op != OKEY { if l.Op != OKEY {
typecheck(n.List.Addr(i3), Erv) n.List.SetIndex(i3, typecheck(n.List.Index(i3), Erv))
Yyerror("missing key in map literal") Yyerror("missing key in map literal")
continue continue
} }
r = l.Left r = l.Left
pushtype(r, t.Key()) pushtype(r, t.Key())
typecheck(&r, Erv) r = typecheck(r, Erv)
defaultlit(&r, t.Key()) r = defaultlit(r, t.Key())
l.Left = assignconv(r, t.Key(), "map key") l.Left = assignconv(r, t.Key(), "map key")
if l.Left.Op != OCONV { if l.Left.Op != OCONV {
keydup(l.Left, hash) keydup(l.Left, hash)
...@@ -3017,8 +3027,8 @@ func typecheckcomplit(np **Node) { ...@@ -3017,8 +3027,8 @@ func typecheckcomplit(np **Node) {
r = l.Right r = l.Right
pushtype(r, t.Type) pushtype(r, t.Type)
typecheck(&r, Erv) r = typecheck(r, Erv)
defaultlit(&r, t.Type) r = defaultlit(r, t.Type)
l.Right = assignconv(r, t.Type, "map value") l.Right = assignconv(r, t.Type, "map value")
} }
...@@ -3037,7 +3047,7 @@ func typecheckcomplit(np **Node) { ...@@ -3037,7 +3047,7 @@ func typecheckcomplit(np **Node) {
ls := n.List.Slice() ls := n.List.Slice()
for i1, n1 := range ls { for i1, n1 := range ls {
setlineno(n1) setlineno(n1)
typecheck(&ls[i1], Erv) ls[i1] = typecheck(ls[i1], Erv)
n1 = ls[i1] n1 = ls[i1]
if f == nil { if f == nil {
if bad == 0 { if bad == 0 {
...@@ -3076,14 +3086,14 @@ func typecheckcomplit(np **Node) { ...@@ -3076,14 +3086,14 @@ func typecheckcomplit(np **Node) {
Yyerror("mixture of field:value and value initializers") Yyerror("mixture of field:value and value initializers")
} }
bad++ bad++
typecheck(&ls[i], Erv) ls[i] = typecheck(ls[i], Erv)
continue continue
} }
s := l.Left.Sym s := l.Left.Sym
if s == nil { if s == nil {
Yyerror("invalid field name %v in struct initializer", l.Left) Yyerror("invalid field name %v in struct initializer", l.Left)
typecheck(&l.Right, Erv) l.Right = typecheck(l.Right, Erv)
continue continue
} }
...@@ -3112,7 +3122,7 @@ func typecheckcomplit(np **Node) { ...@@ -3112,7 +3122,7 @@ func typecheckcomplit(np **Node) {
r = l.Right r = l.Right
// No pushtype allowed here. Tried and rejected. // No pushtype allowed here. Tried and rejected.
typecheck(&r, Erv) r = typecheck(r, Erv)
l.Right = assignconv(r, f.Type, "field value") l.Right = assignconv(r, f.Type, "field value")
} }
...@@ -3123,7 +3133,7 @@ func typecheckcomplit(np **Node) { ...@@ -3123,7 +3133,7 @@ func typecheckcomplit(np **Node) {
if nerr != nerrors { if nerr != nerrors {
n.Type = nil n.Type = nil
return return n
} }
n.Orig = norig n.Orig = norig
...@@ -3136,7 +3146,7 @@ func typecheckcomplit(np **Node) { ...@@ -3136,7 +3146,7 @@ func typecheckcomplit(np **Node) {
} }
n.Orig = norig n.Orig = norig
return return n
} }
// lvalue etc // lvalue etc
...@@ -3252,10 +3262,10 @@ func typecheckas(n *Node) { ...@@ -3252,10 +3262,10 @@ func typecheckas(n *Node) {
n.Left = resolve(n.Left) n.Left = resolve(n.Left)
if n.Left.Name == nil || n.Left.Name.Defn != n || n.Left.Name.Param.Ntype != nil { if n.Left.Name == nil || n.Left.Name.Defn != n || n.Left.Name.Param.Ntype != nil {
typecheck(&n.Left, Erv|Easgn) n.Left = typecheck(n.Left, Erv|Easgn)
} }
typecheck(&n.Right, Erv) n.Right = typecheck(n.Right, Erv)
checkassign(n, n.Left) checkassign(n, n.Left)
if n.Right != nil && n.Right.Type != nil { if n.Right != nil && n.Right.Type != nil {
if n.Left.Type != nil { if n.Left.Type != nil {
...@@ -3264,7 +3274,7 @@ func typecheckas(n *Node) { ...@@ -3264,7 +3274,7 @@ func typecheckas(n *Node) {
} }
if n.Left.Name != nil && n.Left.Name.Defn == n && n.Left.Name.Param.Ntype == nil { if n.Left.Name != nil && n.Left.Name.Defn == n && n.Left.Name.Param.Ntype == nil {
defaultlit(&n.Right, nil) n.Right = defaultlit(n.Right, nil)
n.Left.Type = n.Right.Type n.Left.Type = n.Right.Type
} }
...@@ -3274,7 +3284,7 @@ func typecheckas(n *Node) { ...@@ -3274,7 +3284,7 @@ func typecheckas(n *Node) {
n.Typecheck = 1 n.Typecheck = 1
if n.Left.Typecheck == 0 { if n.Left.Typecheck == 0 {
typecheck(&n.Left, Erv|Easgn) n.Left = typecheck(n.Left, Erv|Easgn)
} }
} }
...@@ -3295,14 +3305,14 @@ func typecheckas2(n *Node) { ...@@ -3295,14 +3305,14 @@ func typecheckas2(n *Node) {
ls[i1] = n1 ls[i1] = n1
if n1.Name == nil || n1.Name.Defn != n || n1.Name.Param.Ntype != nil { if n1.Name == nil || n1.Name.Defn != n || n1.Name.Param.Ntype != nil {
typecheck(&ls[i1], Erv|Easgn) ls[i1] = typecheck(ls[i1], Erv|Easgn)
} }
} }
cl := n.List.Len() cl := n.List.Len()
cr := n.Rlist.Len() cr := n.Rlist.Len()
if cl > 1 && cr == 1 { if cl > 1 && cr == 1 {
typecheck(n.Rlist.Addr(0), Erv|Efnstruct) n.Rlist.SetIndex(0, typecheck(n.Rlist.Index(0), Erv|Efnstruct))
} else { } else {
typecheckslice(n.Rlist.Slice(), Erv) typecheckslice(n.Rlist.Slice(), Erv)
} }
...@@ -3320,7 +3330,7 @@ func typecheckas2(n *Node) { ...@@ -3320,7 +3330,7 @@ func typecheckas2(n *Node) {
rs[il] = assignconv(nr, nl.Type, "assignment") rs[il] = assignconv(nr, nl.Type, "assignment")
} }
if nl.Name != nil && nl.Name.Defn == n && nl.Name.Param.Ntype == nil { if nl.Name != nil && nl.Name.Defn == n && nl.Name.Param.Ntype == nil {
defaultlit(&rs[il], nil) rs[il] = defaultlit(rs[il], nil)
nl.Type = rs[il].Type nl.Type = rs[il].Type
} }
} }
...@@ -3406,14 +3416,14 @@ out: ...@@ -3406,14 +3416,14 @@ out:
ls = n.List.Slice() ls = n.List.Slice()
for i1, n1 := range ls { for i1, n1 := range ls {
if n1.Typecheck == 0 { if n1.Typecheck == 0 {
typecheck(&ls[i1], Erv|Easgn) ls[i1] = typecheck(ls[i1], Erv|Easgn)
} }
} }
} }
// type check function definition // type check function definition
func typecheckfunc(n *Node) { func typecheckfunc(n *Node) {
typecheck(&n.Func.Nname, Erv|Easgn) n.Func.Nname = typecheck(n.Func.Nname, Erv|Easgn)
t := n.Func.Nname.Type t := n.Func.Nname.Type
if t == nil { if t == nil {
return return
...@@ -3432,8 +3442,9 @@ func typecheckfunc(n *Node) { ...@@ -3432,8 +3442,9 @@ func typecheckfunc(n *Node) {
} }
} }
func stringtoarraylit(np **Node) { // The result of stringtoarraylit MUST be assigned back to n, e.g.
n := *np // n.Left = stringtoarraylit(n.Left)
func stringtoarraylit(n *Node) *Node {
if n.Left.Op != OLITERAL || n.Left.Val().Ctype() != CTSTR { if n.Left.Op != OLITERAL || n.Left.Val().Ctype() != CTSTR {
Fatalf("stringtoarraylit %v", n) Fatalf("stringtoarraylit %v", n)
} }
...@@ -3456,8 +3467,8 @@ func stringtoarraylit(np **Node) { ...@@ -3456,8 +3467,8 @@ func stringtoarraylit(np **Node) {
nn := Nod(OCOMPLIT, nil, typenod(n.Type)) nn := Nod(OCOMPLIT, nil, typenod(n.Type))
nn.List.Set(l) nn.List.Set(l)
typecheck(&nn, Erv) nn = typecheck(nn, Erv)
*np = nn return nn
} }
var ntypecheckdeftype int var ntypecheckdeftype int
...@@ -3466,7 +3477,7 @@ var methodqueue []*Node ...@@ -3466,7 +3477,7 @@ var methodqueue []*Node
func domethod(n *Node) { func domethod(n *Node) {
nt := n.Type.Nname nt := n.Type.Nname
typecheck(&nt, Etype) nt = typecheck(nt, Etype)
if nt.Type == nil { if nt.Type == nil {
// type check failed; leave empty func // type check failed; leave empty func
// TODO(mdempsky): Fix Type rekinding. // TODO(mdempsky): Fix Type rekinding.
...@@ -3555,7 +3566,7 @@ func typecheckdeftype(n *Node) { ...@@ -3555,7 +3566,7 @@ func typecheckdeftype(n *Node) {
setlineno(n) setlineno(n)
n.Type.Sym = n.Sym n.Type.Sym = n.Sym
n.Typecheck = 1 n.Typecheck = 1
typecheck(&n.Name.Param.Ntype, Etype) n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, Etype)
t := n.Name.Param.Ntype.Type t := n.Name.Param.Ntype.Type
if t == nil { if t == nil {
n.Diag = 1 n.Diag = 1
...@@ -3663,7 +3674,7 @@ func typecheckdef(n *Node) *Node { ...@@ -3663,7 +3674,7 @@ func typecheckdef(n *Node) *Node {
case OLITERAL: case OLITERAL:
if n.Name.Param.Ntype != nil { if n.Name.Param.Ntype != nil {
typecheck(&n.Name.Param.Ntype, Etype) n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, Etype)
n.Type = n.Name.Param.Ntype.Type n.Type = n.Name.Param.Ntype.Type
n.Name.Param.Ntype = nil n.Name.Param.Ntype = nil
if n.Type == nil { if n.Type == nil {
...@@ -3680,7 +3691,7 @@ func typecheckdef(n *Node) *Node { ...@@ -3680,7 +3691,7 @@ func typecheckdef(n *Node) *Node {
Yyerror("xxx") Yyerror("xxx")
} }
typecheck(&e, Erv|Eiota) e = typecheck(e, Erv|Eiota)
if Isconst(e, CTNIL) { if Isconst(e, CTNIL) {
Yyerror("const initializer cannot be nil") Yyerror("const initializer cannot be nil")
goto ret goto ret
...@@ -3707,7 +3718,7 @@ func typecheckdef(n *Node) *Node { ...@@ -3707,7 +3718,7 @@ func typecheckdef(n *Node) *Node {
goto ret goto ret
} }
convlit(&e, t) e = convlit(e, t)
} }
n.SetVal(e.Val()) n.SetVal(e.Val())
...@@ -3715,7 +3726,7 @@ func typecheckdef(n *Node) *Node { ...@@ -3715,7 +3726,7 @@ func typecheckdef(n *Node) *Node {
case ONAME: case ONAME:
if n.Name.Param.Ntype != nil { if n.Name.Param.Ntype != nil {
typecheck(&n.Name.Param.Ntype, Etype) n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, Etype)
n.Type = n.Name.Param.Ntype.Type n.Type = n.Name.Param.Ntype.Type
if n.Type == nil { if n.Type == nil {
n.Diag = 1 n.Diag = 1
...@@ -3742,12 +3753,12 @@ func typecheckdef(n *Node) *Node { ...@@ -3742,12 +3753,12 @@ func typecheckdef(n *Node) *Node {
} }
if n.Name.Defn.Op == ONAME { if n.Name.Defn.Op == ONAME {
typecheck(&n.Name.Defn, Erv) n.Name.Defn = typecheck(n.Name.Defn, Erv)
n.Type = n.Name.Defn.Type n.Type = n.Name.Defn.Type
break break
} }
typecheck(&n.Name.Defn, Etop) // fills in n->type n.Name.Defn = typecheck(n.Name.Defn, Etop) // fills in n->type
case OTYPE: case OTYPE:
if Curfn != nil { if Curfn != nil {
...@@ -3806,7 +3817,7 @@ func checkmake(t *Type, arg string, n *Node) bool { ...@@ -3806,7 +3817,7 @@ func checkmake(t *Type, arg string, n *Node) bool {
// Delay defaultlit until after we've checked range, to avoid // Delay defaultlit until after we've checked range, to avoid
// a redundant "constant NNN overflows int" error. // a redundant "constant NNN overflows int" error.
defaultlit(&n, Types[TINT]) n = defaultlit(n, Types[TINT])
return true return true
...@@ -3821,7 +3832,7 @@ func checkmake(t *Type, arg string, n *Node) bool { ...@@ -3821,7 +3832,7 @@ func checkmake(t *Type, arg string, n *Node) bool {
} }
// Defaultlit still necessary for non-constant: n might be 1<<k. // Defaultlit still necessary for non-constant: n might be 1<<k.
defaultlit(&n, Types[TINT]) n = defaultlit(n, Types[TINT])
return true return true
} }
......
...@@ -30,8 +30,8 @@ func unsafenmagic(nn *Node) *Node { ...@@ -30,8 +30,8 @@ func unsafenmagic(nn *Node) *Node {
var v int64 var v int64
switch s.Name { switch s.Name {
case "Alignof", "Sizeof": case "Alignof", "Sizeof":
typecheck(&r, Erv) r = typecheck(r, Erv)
defaultlit(&r, nil) r = defaultlit(r, nil)
tr := r.Type tr := r.Type
if tr == nil { if tr == nil {
goto bad goto bad
...@@ -52,10 +52,10 @@ func unsafenmagic(nn *Node) *Node { ...@@ -52,10 +52,10 @@ func unsafenmagic(nn *Node) *Node {
// Remember base of selector to find it back after dot insertion. // Remember base of selector to find it back after dot insertion.
// Since r->left may be mutated by typechecking, check it explicitly // Since r->left may be mutated by typechecking, check it explicitly
// first to track it correctly. // first to track it correctly.
typecheck(&r.Left, Erv) r.Left = typecheck(r.Left, Erv)
base := r.Left base := r.Left
typecheck(&r, Erv) r = typecheck(r, Erv)
switch r.Op { switch r.Op {
case ODOT, ODOTPTR: case ODOT, ODOTPTR:
break break
......
...@@ -29,7 +29,7 @@ func walk(fn *Node) { ...@@ -29,7 +29,7 @@ func walk(fn *Node) {
// It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below. // It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below.
for i, ln := range fn.Func.Dcl { for i, ln := range fn.Func.Dcl {
if ln.Op == ONAME && ln.Class&^PHEAP == PAUTO { if ln.Op == ONAME && ln.Class&^PHEAP == PAUTO {
typecheck(&ln, Erv|Easgn) ln = typecheck(ln, Erv|Easgn)
fn.Func.Dcl[i] = ln fn.Func.Dcl[i] = ln
} }
} }
...@@ -77,7 +77,7 @@ func walk(fn *Node) { ...@@ -77,7 +77,7 @@ func walk(fn *Node) {
func walkstmtlist(s []*Node) { func walkstmtlist(s []*Node) {
for i := range s { for i := range s {
walkstmt(&s[i]) s[i] = walkstmt(s[i])
} }
} }
...@@ -139,13 +139,14 @@ func adjustargs(n *Node, adjust int) { ...@@ -139,13 +139,14 @@ func adjustargs(n *Node, adjust int) {
} }
} }
func walkstmt(np **Node) { // The result of walkstmt MUST be assigned back to n, e.g.
n := *np // n.Left = walkstmt(n.Left)
func walkstmt(n *Node) *Node {
if n == nil { if n == nil {
return return n
} }
if n.Dodata == 2 { // don't walk, generated by anylit. if n.Dodata == 2 { // don't walk, generated by anylit.
return return n
} }
setlineno(n) setlineno(n)
...@@ -185,11 +186,12 @@ func walkstmt(np **Node) { ...@@ -185,11 +186,12 @@ func walkstmt(np **Node) {
if n.Typecheck == 0 { if n.Typecheck == 0 {
Fatalf("missing typecheck: %v", Nconv(n, FmtSign)) Fatalf("missing typecheck: %v", Nconv(n, FmtSign))
} }
wascopy := n.Op == OCOPY
init := n.Ninit init := n.Ninit
n.Ninit.Set(nil) n.Ninit.Set(nil)
walkexpr(&n, &init) n = walkexpr(n, &init)
addinit(&n, init.Slice()) n = addinit(n, init.Slice())
if (*np).Op == OCOPY && n.Op == OCONVNOP { if wascopy && n.Op == OCONVNOP {
n.Op = OEMPTY // don't leave plain values as statements. n.Op = OEMPTY // don't leave plain values as statements.
} }
...@@ -202,11 +204,11 @@ func walkstmt(np **Node) { ...@@ -202,11 +204,11 @@ func walkstmt(np **Node) {
init := n.Ninit init := n.Ninit
n.Ninit.Set(nil) n.Ninit.Set(nil)
walkexpr(&n.Left, &init) n.Left = walkexpr(n.Left, &init)
n = mkcall1(chanfn("chanrecv1", 2, n.Left.Type), nil, &init, typename(n.Left.Type), n.Left, nodnil()) n = mkcall1(chanfn("chanrecv1", 2, n.Left.Type), nil, &init, typename(n.Left.Type), n.Left, nodnil())
walkexpr(&n, &init) n = walkexpr(n, &init)
addinit(&n, init.Slice()) n = addinit(n, init.Slice())
case OBREAK, case OBREAK,
ODCL, ODCL,
...@@ -230,19 +232,19 @@ func walkstmt(np **Node) { ...@@ -230,19 +232,19 @@ func walkstmt(np **Node) {
fallthrough fallthrough
case OCASE: case OCASE:
walkstmt(&n.Right) n.Right = walkstmt(n.Right)
case ODEFER: case ODEFER:
hasdefer = true hasdefer = true
switch n.Left.Op { switch n.Left.Op {
case OPRINT, OPRINTN: case OPRINT, OPRINTN:
walkprintfunc(&n.Left, &n.Ninit) n.Left = walkprintfunc(n.Left, &n.Ninit)
case OCOPY: case OCOPY:
n.Left = copyany(n.Left, &n.Ninit, true) n.Left = copyany(n.Left, &n.Ninit, true)
default: default:
walkexpr(&n.Left, &n.Ninit) n.Left = walkexpr(n.Left, &n.Ninit)
} }
// make room for size & fn arguments. // make room for size & fn arguments.
...@@ -253,28 +255,28 @@ func walkstmt(np **Node) { ...@@ -253,28 +255,28 @@ func walkstmt(np **Node) {
walkstmtlist(n.Left.Ninit.Slice()) walkstmtlist(n.Left.Ninit.Slice())
init := n.Left.Ninit init := n.Left.Ninit
n.Left.Ninit.Set(nil) n.Left.Ninit.Set(nil)
walkexpr(&n.Left, &init) n.Left = walkexpr(n.Left, &init)
addinit(&n.Left, init.Slice()) n.Left = addinit(n.Left, init.Slice())
} }
walkstmt(&n.Right) n.Right = walkstmt(n.Right)
walkstmtlist(n.Nbody.Slice()) walkstmtlist(n.Nbody.Slice())
case OIF: case OIF:
walkexpr(&n.Left, &n.Ninit) n.Left = walkexpr(n.Left, &n.Ninit)
walkstmtlist(n.Nbody.Slice()) walkstmtlist(n.Nbody.Slice())
walkstmtlist(n.Rlist.Slice()) walkstmtlist(n.Rlist.Slice())
case OPROC: case OPROC:
switch n.Left.Op { switch n.Left.Op {
case OPRINT, OPRINTN: case OPRINT, OPRINTN:
walkprintfunc(&n.Left, &n.Ninit) n.Left = walkprintfunc(n.Left, &n.Ninit)
case OCOPY: case OCOPY:
n.Left = copyany(n.Left, &n.Ninit, true) n.Left = copyany(n.Left, &n.Ninit, true)
default: default:
walkexpr(&n.Left, &n.Ninit) n.Left = walkexpr(n.Left, &n.Ninit)
} }
// make room for size & fn arguments. // make room for size & fn arguments.
...@@ -349,8 +351,7 @@ func walkstmt(np **Node) { ...@@ -349,8 +351,7 @@ func walkstmt(np **Node) {
if n.Op == ONAME { if n.Op == ONAME {
Fatalf("walkstmt ended up with name: %v", Nconv(n, FmtSign)) Fatalf("walkstmt ended up with name: %v", Nconv(n, FmtSign))
} }
return n
*np = n
} }
func isSmallMakeSlice(n *Node) bool { func isSmallMakeSlice(n *Node) bool {
...@@ -374,21 +375,21 @@ func isSmallMakeSlice(n *Node) bool { ...@@ -374,21 +375,21 @@ func isSmallMakeSlice(n *Node) bool {
// complex side effects like statements are appended to init // complex side effects like statements are appended to init
func walkexprlist(s []*Node, init *Nodes) { func walkexprlist(s []*Node, init *Nodes) {
for i := range s { for i := range s {
walkexpr(&s[i], init) s[i] = walkexpr(s[i], init)
} }
} }
func walkexprlistsafe(s []*Node, init *Nodes) { func walkexprlistsafe(s []*Node, init *Nodes) {
for i, n := range s { for i, n := range s {
s[i] = safeexpr(n, init) s[i] = safeexpr(n, init)
walkexpr(&s[i], init) s[i] = walkexpr(s[i], init)
} }
} }
func walkexprlistcheap(s []*Node, init *Nodes) { func walkexprlistcheap(s []*Node, init *Nodes) {
for i, n := range s { for i, n := range s {
s[i] = cheapexpr(n, init) s[i] = cheapexpr(n, init)
walkexpr(&s[i], init) s[i] = walkexpr(s[i], init)
} }
} }
...@@ -449,11 +450,11 @@ func assertFuncName(from, to *Type, with2suffix bool) string { ...@@ -449,11 +450,11 @@ func assertFuncName(from, to *Type, with2suffix bool) string {
panic("unreachable") panic("unreachable")
} }
func walkexpr(np **Node, init *Nodes) { // The result of walkexpr MUST be assigned back to n, e.g.
n := *np // n.Left = walkexpr(n.Left, init)
func walkexpr(n *Node, init *Nodes) *Node {
if n == nil { if n == nil {
return return n
} }
if init == &n.Ninit { if init == &n.Ninit {
...@@ -470,9 +471,9 @@ func walkexpr(np **Node, init *Nodes) { ...@@ -470,9 +471,9 @@ func walkexpr(np **Node, init *Nodes) {
// annoying case - not typechecked // annoying case - not typechecked
if n.Op == OKEY { if n.Op == OKEY {
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
return return n
} }
lno := setlineno(n) lno := setlineno(n)
...@@ -506,14 +507,14 @@ opswitch: ...@@ -506,14 +507,14 @@ opswitch:
OIMAG, OIMAG,
ODOTMETH, ODOTMETH,
ODOTINTER: ODOTINTER:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
case OIND: case OIND:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
case ODOT: case ODOT:
usefield(n) usefield(n)
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
case ODOTPTR: case ODOTPTR:
usefield(n) usefield(n)
...@@ -524,17 +525,17 @@ opswitch: ...@@ -524,17 +525,17 @@ opswitch:
checknil(n.Left, init) checknil(n.Left, init)
} }
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
case OEFACE: case OEFACE:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
case OSPTR, OITAB: case OSPTR, OITAB:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
case OLEN, OCAP: case OLEN, OCAP:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
// replace len(*[10]int) with 10. // replace len(*[10]int) with 10.
// delayed until now to preserve side effects. // delayed until now to preserve side effects.
...@@ -550,8 +551,8 @@ opswitch: ...@@ -550,8 +551,8 @@ opswitch:
} }
case OLSH, ORSH: case OLSH, ORSH:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
t := n.Left.Type t := n.Left.Type
n.Bounded = bounded(n.Right, 8*t.Width) n.Bounded = bounded(n.Right, 8*t.Width)
if Debug['m'] != 0 && n.Etype != 0 && !Isconst(n.Right, CTINT) { if Debug['m'] != 0 && n.Etype != 0 && !Isconst(n.Right, CTINT) {
...@@ -574,17 +575,17 @@ opswitch: ...@@ -574,17 +575,17 @@ opswitch:
n.Right = n.List.Second() n.Right = n.List.Second()
} }
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
case OOR, OXOR: case OOR, OXOR:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
walkrotate(&n) n = walkrotate(n)
case OEQ, ONE: case OEQ, ONE:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
// Disable safemode while compiling this code: the code we // Disable safemode while compiling this code: the code we
// generate internally can refer to unsafe.Pointer. // generate internally can refer to unsafe.Pointer.
...@@ -594,19 +595,19 @@ opswitch: ...@@ -594,19 +595,19 @@ opswitch:
old_safemode := safemode old_safemode := safemode
safemode = 0 safemode = 0
walkcompare(&n, init) n = walkcompare(n, init)
safemode = old_safemode safemode = old_safemode
case OANDAND, OOROR: case OANDAND, OOROR:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
// cannot put side effects from n.Right on init, // cannot put side effects from n.Right on init,
// because they cannot run before n.Left is checked. // because they cannot run before n.Left is checked.
// save elsewhere and store on the eventual n.Right. // save elsewhere and store on the eventual n.Right.
var ll Nodes var ll Nodes
walkexpr(&n.Right, &ll) n.Right = walkexpr(n.Right, &ll)
addinit(&n.Right, ll.Slice()) n.Right = addinit(n.Right, ll.Slice())
case OPRINT, OPRINTN: case OPRINT, OPRINTN:
walkexprlist(n.List.Slice(), init) walkexprlist(n.List.Slice(), init)
...@@ -635,7 +636,7 @@ opswitch: ...@@ -635,7 +636,7 @@ opswitch:
if n.List.Len() != 0 && n.List.First().Op == OAS { if n.List.Len() != 0 && n.List.First().Op == OAS {
break break
} }
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexprlist(n.List.Slice(), init) walkexprlist(n.List.Slice(), init)
ll := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init) ll := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init)
n.List.Set(reorder1(ll)) n.List.Set(reorder1(ll))
...@@ -667,7 +668,7 @@ opswitch: ...@@ -667,7 +668,7 @@ opswitch:
break break
} }
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexprlist(n.List.Slice(), init) walkexprlist(n.List.Slice(), init)
if n.Left.Op == ONAME && n.Left.Sym.Name == "Sqrt" && n.Left.Sym.Pkg.Path == "math" { if n.Left.Op == ONAME && n.Left.Sym.Name == "Sqrt" && n.Left.Sym.Pkg.Path == "math" {
...@@ -688,7 +689,7 @@ opswitch: ...@@ -688,7 +689,7 @@ opswitch:
if n.List.Len() != 0 && n.List.First().Op == OAS { if n.List.Len() != 0 && n.List.First().Op == OAS {
break break
} }
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexprlist(n.List.Slice(), init) walkexprlist(n.List.Slice(), init)
ll := ascompatte(n.Op, n, false, t.Recvs(), []*Node{n.Left.Left}, 0, init) ll := ascompatte(n.Op, n, false, t.Recvs(), []*Node{n.Left.Left}, 0, init)
lr := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init) lr := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init)
...@@ -700,7 +701,7 @@ opswitch: ...@@ -700,7 +701,7 @@ opswitch:
case OAS: case OAS:
init.AppendNodes(&n.Ninit) init.AppendNodes(&n.Ninit)
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
n.Left = safeexpr(n.Left, init) n.Left = safeexpr(n.Left, init)
if oaslit(n, init) { if oaslit(n, init) {
...@@ -713,7 +714,7 @@ opswitch: ...@@ -713,7 +714,7 @@ opswitch:
switch n.Right.Op { switch n.Right.Op {
default: default:
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
case ODOTTYPE: case ODOTTYPE:
// TODO(rsc): The Isfat is for consistency with componentgen and orderexpr. // TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
...@@ -721,13 +722,13 @@ opswitch: ...@@ -721,13 +722,13 @@ opswitch:
// That would allow inlining x.(struct{*int}) the same as x.(*int). // That would allow inlining x.(struct{*int}) the same as x.(*int).
if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && !instrumenting { if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && !instrumenting {
// handled directly during cgen // handled directly during cgen
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
break break
} }
// x = i.(T); n.Left is x, n.Right.Left is i. // x = i.(T); n.Left is x, n.Right.Left is i.
// orderstmt made sure x is addressable. // orderstmt made sure x is addressable.
walkexpr(&n.Right.Left, init) n.Right.Left = walkexpr(n.Right.Left, init)
n1 := Nod(OADDR, n.Left, nil) n1 := Nod(OADDR, n.Left, nil)
r := n.Right // i.(T) r := n.Right // i.(T)
...@@ -737,21 +738,21 @@ opswitch: ...@@ -737,21 +738,21 @@ opswitch:
} }
fn := syslook(assertFuncName(r.Left.Type, r.Type, false)) fn := syslook(assertFuncName(r.Left.Type, r.Type, false))
substArgTypes(&fn, r.Left.Type, r.Type) fn = substArgTypes(fn, r.Left.Type, r.Type)
n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1) n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1)
walkexpr(&n, init) n = walkexpr(n, init)
break opswitch break opswitch
case ORECV: case ORECV:
// x = <-c; n.Left is x, n.Right.Left is c. // x = <-c; n.Left is x, n.Right.Left is c.
// orderstmt made sure x is addressable. // orderstmt made sure x is addressable.
walkexpr(&n.Right.Left, init) n.Right.Left = walkexpr(n.Right.Left, init)
n1 := Nod(OADDR, n.Left, nil) n1 := Nod(OADDR, n.Left, nil)
r := n.Right.Left // the channel r := n.Right.Left // the channel
n = mkcall1(chanfn("chanrecv1", 2, r.Type), nil, init, typename(r.Type), r, n1) n = mkcall1(chanfn("chanrecv1", 2, r.Type), nil, init, typename(r.Type), r, n1)
walkexpr(&n, init) n = walkexpr(n, init)
break opswitch break opswitch
case OAPPEND: case OAPPEND:
...@@ -796,7 +797,7 @@ opswitch: ...@@ -796,7 +797,7 @@ opswitch:
r := n.Rlist.First() r := n.Rlist.First()
walkexprlistsafe(n.List.Slice(), init) walkexprlistsafe(n.List.Slice(), init)
walkexpr(&r, init) r = walkexpr(r, init)
ll := ascompatet(n.Op, n.List, r.Type, 0, init) ll := ascompatet(n.Op, n.List, r.Type, 0, init)
for i, n := range ll { for i, n := range ll {
...@@ -811,7 +812,7 @@ opswitch: ...@@ -811,7 +812,7 @@ opswitch:
r := n.Rlist.First() r := n.Rlist.First()
walkexprlistsafe(n.List.Slice(), init) walkexprlistsafe(n.List.Slice(), init)
walkexpr(&r.Left, init) r.Left = walkexpr(r.Left, init)
var n1 *Node var n1 *Node
if isblank(n.List.First()) { if isblank(n.List.First()) {
n1 = nodnil() n1 = nodnil()
...@@ -822,7 +823,7 @@ opswitch: ...@@ -822,7 +823,7 @@ opswitch:
fn := chanfn("chanrecv2", 2, r.Left.Type) fn := chanfn("chanrecv2", 2, r.Left.Type)
r = mkcall1(fn, n.List.Second().Type, init, typename(r.Left.Type), r.Left, n1) r = mkcall1(fn, n.List.Second().Type, init, typename(r.Left.Type), r.Left, n1)
n = Nod(OAS, n.List.Second(), r) n = Nod(OAS, n.List.Second(), r)
typecheck(&n, Etop) n = typecheck(n, Etop)
// a,b = m[i]; // a,b = m[i];
case OAS2MAPR: case OAS2MAPR:
...@@ -830,8 +831,8 @@ opswitch: ...@@ -830,8 +831,8 @@ opswitch:
r := n.Rlist.First() r := n.Rlist.First()
walkexprlistsafe(n.List.Slice(), init) walkexprlistsafe(n.List.Slice(), init)
walkexpr(&r.Left, init) r.Left = walkexpr(r.Left, init)
walkexpr(&r.Right, init) r.Right = walkexpr(r.Right, init)
t := r.Left.Type t := r.Left.Type
p := "" p := ""
if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing. if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
...@@ -881,13 +882,13 @@ opswitch: ...@@ -881,13 +882,13 @@ opswitch:
var_ := temp(Ptrto(t.Type)) var_ := temp(Ptrto(t.Type))
var_.Typecheck = 1 var_.Typecheck = 1
n.List.SetIndex(0, var_) n.List.SetIndex(0, var_)
walkexpr(&n, init) n = walkexpr(n, init)
init.Append(n) init.Append(n)
n = Nod(OAS, a, Nod(OIND, var_, nil)) n = Nod(OAS, a, Nod(OIND, var_, nil))
} }
typecheck(&n, Etop) n = typecheck(n, Etop)
walkexpr(&n, init) n = walkexpr(n, init)
// TODO: ptr is always non-nil, so disable nil check for this OIND op. // TODO: ptr is always non-nil, so disable nil check for this OIND op.
...@@ -895,8 +896,8 @@ opswitch: ...@@ -895,8 +896,8 @@ opswitch:
init.AppendNodes(&n.Ninit) init.AppendNodes(&n.Ninit)
map_ := n.List.First() map_ := n.List.First()
key := n.List.Second() key := n.List.Second()
walkexpr(&map_, init) map_ = walkexpr(map_, init)
walkexpr(&key, init) key = walkexpr(key, init)
// orderstmt made sure key is addressable. // orderstmt made sure key is addressable.
key = Nod(OADDR, key, nil) key = Nod(OADDR, key, nil)
...@@ -912,7 +913,7 @@ opswitch: ...@@ -912,7 +913,7 @@ opswitch:
if isdirectiface(e.Type) && !Isfat(e.Type) && !instrumenting { if isdirectiface(e.Type) && !Isfat(e.Type) && !instrumenting {
// handled directly during gen. // handled directly during gen.
walkexprlistsafe(n.List.Slice(), init) walkexprlistsafe(n.List.Slice(), init)
walkexpr(&e.Left, init) e.Left = walkexpr(e.Left, init)
break break
} }
...@@ -921,7 +922,7 @@ opswitch: ...@@ -921,7 +922,7 @@ opswitch:
init.AppendNodes(&n.Ninit) init.AppendNodes(&n.Ninit)
walkexprlistsafe(n.List.Slice(), init) walkexprlistsafe(n.List.Slice(), init)
walkexpr(&e.Left, init) e.Left = walkexpr(e.Left, init)
t := e.Type // T t := e.Type // T
from := e.Left // i from := e.Left // i
...@@ -955,7 +956,7 @@ opswitch: ...@@ -955,7 +956,7 @@ opswitch:
Warn("type assertion (ok only) inlined") Warn("type assertion (ok only) inlined")
} }
n = Nod(OAS, ok, fast) n = Nod(OAS, ok, fast)
typecheck(&n, Etop) n = typecheck(n, Etop)
break break
} }
} }
...@@ -972,19 +973,19 @@ opswitch: ...@@ -972,19 +973,19 @@ opswitch:
Warn("type assertion not inlined") Warn("type assertion not inlined")
} }
fn := syslook(assertFuncName(from.Type, t, true)) fn := syslook(assertFuncName(from.Type, t, true))
substArgTypes(&fn, from.Type, t) fn = substArgTypes(fn, from.Type, t)
call := mkcall1(fn, oktype, init, typename(t), from, resptr) call := mkcall1(fn, oktype, init, typename(t), from, resptr)
n = Nod(OAS, ok, call) n = Nod(OAS, ok, call)
typecheck(&n, Etop) n = typecheck(n, Etop)
case ODOTTYPE, ODOTTYPE2: case ODOTTYPE, ODOTTYPE2:
if !isdirectiface(n.Type) || Isfat(n.Type) { if !isdirectiface(n.Type) || Isfat(n.Type) {
Fatalf("walkexpr ODOTTYPE") // should see inside OAS only Fatalf("walkexpr ODOTTYPE") // should see inside OAS only
} }
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
case OCONVIFACE: case OCONVIFACE:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
// Optimize convT2E as a two-word copy when T is pointer-shaped. // Optimize convT2E as a two-word copy when T is pointer-shaped.
if isnilinter(n.Type) && isdirectiface(n.Left.Type) { if isnilinter(n.Type) && isdirectiface(n.Left.Type) {
...@@ -1032,20 +1033,20 @@ opswitch: ...@@ -1032,20 +1033,20 @@ opswitch:
l := temp(Ptrto(Types[TUINT8])) l := temp(Ptrto(Types[TUINT8]))
n1 := Nod(OAS, l, sym.Def) n1 := Nod(OAS, l, sym.Def)
typecheck(&n1, Etop) n1 = typecheck(n1, Etop)
init.Append(n1) init.Append(n1)
fn := syslook("typ2Itab") fn := syslook("typ2Itab")
n1 = Nod(OCALL, fn, nil) n1 = Nod(OCALL, fn, nil)
n1.List.Set(ll) n1.List.Set(ll)
typecheck(&n1, Erv) n1 = typecheck(n1, Erv)
walkexpr(&n1, init) n1 = walkexpr(n1, init)
n2 := Nod(OIF, nil, nil) n2 := Nod(OIF, nil, nil)
n2.Left = Nod(OEQ, l, nodnil()) n2.Left = Nod(OEQ, l, nodnil())
n2.Nbody.Set1(Nod(OAS, l, n1)) n2.Nbody.Set1(Nod(OAS, l, n1))
n2.Likely = -1 n2.Likely = -1
typecheck(&n2, Etop) n2 = typecheck(n2, Etop)
init.Append(n2) init.Append(n2)
l = Nod(OEFACE, l, n.Left) l = Nod(OEFACE, l, n.Left)
...@@ -1076,25 +1077,25 @@ opswitch: ...@@ -1076,25 +1077,25 @@ opswitch:
// Allocate stack buffer for value stored in interface. // Allocate stack buffer for value stored in interface.
r = temp(n.Left.Type) r = temp(n.Left.Type)
r = Nod(OAS, r, nil) // zero temp r = Nod(OAS, r, nil) // zero temp
typecheck(&r, Etop) r = typecheck(r, Etop)
init.Append(r) init.Append(r)
r = Nod(OADDR, r.Left, nil) r = Nod(OADDR, r.Left, nil)
typecheck(&r, Erv) r = typecheck(r, Erv)
} }
ll = append(ll, r) ll = append(ll, r)
} }
fn := syslook(convFuncName(n.Left.Type, n.Type)) fn := syslook(convFuncName(n.Left.Type, n.Type))
if !Isinter(n.Left.Type) { if !Isinter(n.Left.Type) {
substArgTypes(&fn, n.Left.Type, n.Left.Type, n.Type) fn = substArgTypes(fn, n.Left.Type, n.Left.Type, n.Type)
} else { } else {
substArgTypes(&fn, n.Left.Type, n.Type) fn = substArgTypes(fn, n.Left.Type, n.Type)
} }
dowidth(fn.Type) dowidth(fn.Type)
n = Nod(OCALL, fn, nil) n = Nod(OCALL, fn, nil)
n.List.Set(ll) n.List.Set(ll)
typecheck(&n, Erv) n = typecheck(n, Erv)
walkexpr(&n, init) n = walkexpr(n, init)
case OCONV, OCONVNOP: case OCONV, OCONVNOP:
if Thearch.Thechar == '5' { if Thearch.Thechar == '5' {
...@@ -1123,23 +1124,23 @@ opswitch: ...@@ -1123,23 +1124,23 @@ opswitch:
} }
} }
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
case OANDNOT: case OANDNOT:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
n.Op = OAND n.Op = OAND
n.Right = Nod(OCOM, n.Right, nil) n.Right = Nod(OCOM, n.Right, nil)
typecheck(&n.Right, Erv) n.Right = typecheck(n.Right, Erv)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
case OMUL: case OMUL:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
walkmul(&n, init) n = walkmul(n, init)
case ODIV, OMOD: case ODIV, OMOD:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
// rewrite complex div into function call. // rewrite complex div into function call.
et := n.Left.Type.Etype et := n.Left.Type.Etype
...@@ -1157,7 +1158,7 @@ opswitch: ...@@ -1157,7 +1158,7 @@ opswitch:
} }
// Try rewriting as shifts or magic multiplies. // Try rewriting as shifts or magic multiplies.
walkdiv(&n, init) n = walkdiv(n, init)
// rewrite 64-bit div and mod into function calls // rewrite 64-bit div and mod into function calls
// on 32-bit architectures. // on 32-bit architectures.
...@@ -1181,13 +1182,13 @@ opswitch: ...@@ -1181,13 +1182,13 @@ opswitch:
} }
case OINDEX: case OINDEX:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
// save the original node for bounds checking elision. // save the original node for bounds checking elision.
// If it was a ODIV/OMOD walk might rewrite it. // If it was a ODIV/OMOD walk might rewrite it.
r := n.Right r := n.Right
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
// if range of type cannot exceed static array bound, // if range of type cannot exceed static array bound,
// disable bounds check. // disable bounds check.
...@@ -1236,8 +1237,8 @@ opswitch: ...@@ -1236,8 +1237,8 @@ opswitch:
if n.Etype == 1 { if n.Etype == 1 {
break break
} }
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
t := n.Left.Type t := n.Left.Type
p := "" p := ""
...@@ -1273,24 +1274,24 @@ opswitch: ...@@ -1273,24 +1274,24 @@ opswitch:
Fatalf("walkexpr ORECV") // should see inside OAS only Fatalf("walkexpr ORECV") // should see inside OAS only
case OSLICE, OSLICEARR, OSLICESTR: case OSLICE, OSLICEARR, OSLICESTR:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right.Left, init) n.Right.Left = walkexpr(n.Right.Left, init)
if n.Right.Left != nil && iszero(n.Right.Left) { if n.Right.Left != nil && iszero(n.Right.Left) {
// Reduce x[0:j] to x[:j]. // Reduce x[0:j] to x[:j].
n.Right.Left = nil n.Right.Left = nil
} }
walkexpr(&n.Right.Right, init) n.Right.Right = walkexpr(n.Right.Right, init)
n = reduceSlice(n) n = reduceSlice(n)
case OSLICE3, OSLICE3ARR: case OSLICE3, OSLICE3ARR:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right.Left, init) n.Right.Left = walkexpr(n.Right.Left, init)
if n.Right.Left != nil && iszero(n.Right.Left) { if n.Right.Left != nil && iszero(n.Right.Left) {
// Reduce x[0:j:k] to x[:j:k]. // Reduce x[0:j:k] to x[:j:k].
n.Right.Left = nil n.Right.Left = nil
} }
walkexpr(&n.Right.Right.Left, init) n.Right.Right.Left = walkexpr(n.Right.Right.Left, init)
walkexpr(&n.Right.Right.Right, init) n.Right.Right.Right = walkexpr(n.Right.Right.Right, init)
r := n.Right.Right.Right r := n.Right.Right.Right
if r != nil && r.Op == OCAP && samesafeexpr(n.Left, r.Left) { if r != nil && r.Op == OCAP && samesafeexpr(n.Left, r.Left) {
...@@ -1305,7 +1306,7 @@ opswitch: ...@@ -1305,7 +1306,7 @@ opswitch:
} }
case OADDR: case OADDR:
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
case ONEW: case ONEW:
if n.Esc == EscNone { if n.Esc == EscNone {
...@@ -1314,10 +1315,10 @@ opswitch: ...@@ -1314,10 +1315,10 @@ opswitch:
} }
r := temp(n.Type.Type) r := temp(n.Type.Type)
r = Nod(OAS, r, nil) // zero temp r = Nod(OAS, r, nil) // zero temp
typecheck(&r, Etop) r = typecheck(r, Etop)
init.Append(r) init.Append(r)
r = Nod(OADDR, r.Left, nil) r = Nod(OADDR, r.Left, nil)
typecheck(&r, Erv) r = typecheck(r, Erv)
n = r n = r
} else { } else {
n = callnew(n.Type.Type) n = callnew(n.Type.Type)
...@@ -1330,8 +1331,8 @@ opswitch: ...@@ -1330,8 +1331,8 @@ opswitch:
if (Isconst(n.Left, CTSTR) && len(n.Left.Val().U.(string)) == 0) || (Isconst(n.Right, CTSTR) && len(n.Right.Val().U.(string)) == 0) { if (Isconst(n.Left, CTSTR) && len(n.Left.Val().U.(string)) == 0) || (Isconst(n.Right, CTSTR) && len(n.Right.Val().U.(string)) == 0) {
// TODO(marvin): Fix Node.EType type union. // TODO(marvin): Fix Node.EType type union.
r := Nod(Op(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil)) r := Nod(Op(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
typecheck(&r, Erv) r = typecheck(r, Erv)
walkexpr(&r, init) r = walkexpr(r, init)
r.Type = n.Type r.Type = n.Type
n = r n = r
break break
...@@ -1341,8 +1342,8 @@ opswitch: ...@@ -1341,8 +1342,8 @@ opswitch:
if (Op(n.Etype) == OEQ || Op(n.Etype) == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && n.Left.List.Len() == 2 && Isconst(n.Left.List.Second(), CTSTR) && strlit(n.Right) == strlit(n.Left.List.Second()) { if (Op(n.Etype) == OEQ || Op(n.Etype) == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && n.Left.List.Len() == 2 && Isconst(n.Left.List.Second(), CTSTR) && strlit(n.Right) == strlit(n.Left.List.Second()) {
// TODO(marvin): Fix Node.EType type union. // TODO(marvin): Fix Node.EType type union.
r := Nod(Op(n.Etype), Nod(OLEN, n.Left.List.First(), nil), Nodintconst(0)) r := Nod(Op(n.Etype), Nod(OLEN, n.Left.List.First(), nil), Nodintconst(0))
typecheck(&r, Erv) r = typecheck(r, Erv)
walkexpr(&r, init) r = walkexpr(r, init)
r.Type = n.Type r.Type = n.Type
n = r n = r
break break
...@@ -1371,8 +1372,8 @@ opswitch: ...@@ -1371,8 +1372,8 @@ opswitch:
r = Nod(OOROR, Nod(ONE, Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil)), r) r = Nod(OOROR, Nod(ONE, Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil)), r)
} }
typecheck(&r, Erv) r = typecheck(r, Erv)
walkexpr(&r, nil) r = walkexpr(r, nil)
} else { } else {
// sys_cmpstring(s1, s2) :: 0 // sys_cmpstring(s1, s2) :: 0
r = mkcall("cmpstring", Types[TINT], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING])) r = mkcall("cmpstring", Types[TINT], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING]))
...@@ -1381,7 +1382,7 @@ opswitch: ...@@ -1381,7 +1382,7 @@ opswitch:
r = Nod(Op(n.Etype), r, Nodintconst(0)) r = Nod(Op(n.Etype), r, Nodintconst(0))
} }
typecheck(&r, Erv) r = typecheck(r, Erv)
if n.Type.Etype != TBOOL { if n.Type.Etype != TBOOL {
Fatalf("cmp %v", n.Type) Fatalf("cmp %v", n.Type)
} }
...@@ -1402,7 +1403,7 @@ opswitch: ...@@ -1402,7 +1403,7 @@ opswitch:
case OCLOSE: case OCLOSE:
fn := syslook("closechan") fn := syslook("closechan")
substArgTypes(&fn, n.Left.Type) fn = substArgTypes(fn, n.Left.Type)
n = mkcall1(fn, nil, init, n.Left) n = mkcall1(fn, nil, init, n.Left)
case OMAKECHAN: case OMAKECHAN:
...@@ -1418,7 +1419,7 @@ opswitch: ...@@ -1418,7 +1419,7 @@ opswitch:
var_ := temp(hmap(t)) var_ := temp(hmap(t))
a = Nod(OAS, var_, nil) // zero temp a = Nod(OAS, var_, nil) // zero temp
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) init.Append(a)
a = Nod(OADDR, var_, nil) a = Nod(OADDR, var_, nil)
...@@ -1428,13 +1429,13 @@ opswitch: ...@@ -1428,13 +1429,13 @@ opswitch:
var_ = temp(mapbucket(t)) var_ = temp(mapbucket(t))
r = Nod(OAS, var_, nil) // zero temp r = Nod(OAS, var_, nil) // zero temp
typecheck(&r, Etop) r = typecheck(r, Etop)
init.Append(r) init.Append(r)
r = Nod(OADDR, var_, nil) r = Nod(OADDR, var_, nil)
} }
fn := syslook("makemap") fn := syslook("makemap")
substArgTypes(&fn, hmap(t), mapbucket(t), t.Key(), t.Type) fn = substArgTypes(fn, hmap(t), mapbucket(t), t.Key(), t.Type)
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r) n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
case OMAKESLICE: case OMAKESLICE:
...@@ -1454,18 +1455,18 @@ opswitch: ...@@ -1454,18 +1455,18 @@ opswitch:
t = aindex(r, t.Type) // [r]T t = aindex(r, t.Type) // [r]T
var_ := temp(t) var_ := temp(t)
a := Nod(OAS, var_, nil) // zero temp a := Nod(OAS, var_, nil) // zero temp
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) init.Append(a)
r := Nod(OSLICE, var_, Nod(OKEY, nil, l)) // arr[:l] r := Nod(OSLICE, var_, Nod(OKEY, nil, l)) // arr[:l]
r = conv(r, n.Type) // in case n.Type is named. r = conv(r, n.Type) // in case n.Type is named.
typecheck(&r, Erv) r = typecheck(r, Erv)
walkexpr(&r, init) r = walkexpr(r, init)
n = r n = r
} else { } else {
// makeslice(t *Type, nel int64, max int64) (ary []any) // makeslice(t *Type, nel int64, max int64) (ary []any)
fn := syslook("makeslice") fn := syslook("makeslice")
substArgTypes(&fn, t.Type) // any-1 fn = substArgTypes(fn, t.Type) // any-1
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(l, Types[TINT64]), conv(r, Types[TINT64])) n = mkcall1(fn, n.Type, init, typename(n.Type), conv(l, Types[TINT64]), conv(r, Types[TINT64]))
} }
...@@ -1553,7 +1554,7 @@ opswitch: ...@@ -1553,7 +1554,7 @@ opswitch:
n.Right = cheapexpr(n.Right, init) n.Right = cheapexpr(n.Right, init)
n.Left = cheapexpr(n.Left, init) n.Left = cheapexpr(n.Left, init)
substArgTypes(&fn, n.Right.Type, n.Left.Type) fn = substArgTypes(fn, n.Right.Type, n.Left.Type)
r := mkcall1(fn, n.Type, init, n.Left, n.Right) r := mkcall1(fn, n.Type, init, n.Left, n.Right)
// TODO(marvin): Fix Node.EType type union. // TODO(marvin): Fix Node.EType type union.
if Op(n.Etype) == ONE { if Op(n.Etype) == ONE {
...@@ -1567,8 +1568,8 @@ opswitch: ...@@ -1567,8 +1568,8 @@ opswitch:
} else { } else {
r = Nod(OOROR, Nod(ONE, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r) r = Nod(OOROR, Nod(ONE, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
} }
typecheck(&r, Erv) r = typecheck(r, Erv)
walkexpr(&r, init) r = walkexpr(r, init)
r.Type = n.Type r.Type = n.Type
n = r n = r
...@@ -1580,7 +1581,7 @@ opswitch: ...@@ -1580,7 +1581,7 @@ opswitch:
case OSEND: case OSEND:
n1 := n.Right n1 := n.Right
n1 = assignconv(n1, n.Left.Type.Type, "chan send") n1 = assignconv(n1, n.Left.Type.Type, "chan send")
walkexpr(&n1, init) n1 = walkexpr(n1, init)
n1 = Nod(OADDR, n1, nil) n1 = Nod(OADDR, n1, nil)
n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, typename(n.Left.Type), n.Left, n1) n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, typename(n.Left.Type), n.Left, n1)
...@@ -1601,7 +1602,7 @@ opswitch: ...@@ -1601,7 +1602,7 @@ opswitch:
evconst(n) evconst(n)
n.Type = t n.Type = t
if n.Op == OLITERAL { if n.Op == OLITERAL {
typecheck(&n, Erv) n = typecheck(n, Erv)
} }
ullmancalc(n) ullmancalc(n)
...@@ -1611,7 +1612,7 @@ opswitch: ...@@ -1611,7 +1612,7 @@ opswitch:
} }
lineno = lno lineno = lno
*np = n return n
} }
func reduceSlice(n *Node) *Node { func reduceSlice(n *Node) *Node {
...@@ -1720,7 +1721,7 @@ func ascompatet(op Op, nl Nodes, nr *Type, fp int, init *Nodes) []*Node { ...@@ -1720,7 +1721,7 @@ func ascompatet(op Op, nl Nodes, nr *Type, fp int, init *Nodes) []*Node {
// have been pulled from the output arguments // have been pulled from the output arguments
if fncall(l, r.Type) { if fncall(l, r.Type) {
tmp := temp(r.Type) tmp := temp(r.Type)
typecheck(&tmp, Erv) tmp = typecheck(tmp, Erv)
a := Nod(OAS, l, tmp) a := Nod(OAS, l, tmp)
a = convas(a, init) a = convas(a, init)
mm = append(mm, a) mm = append(mm, a)
...@@ -1771,11 +1772,11 @@ func mkdotargslice(lr0, nn []*Node, l *Field, fp int, init *Nodes, ddd *Node) [] ...@@ -1771,11 +1772,11 @@ func mkdotargslice(lr0, nn []*Node, l *Field, fp int, init *Nodes, ddd *Node) []
} }
n.List.Set(lr0) n.List.Set(lr0)
n.Esc = esc n.Esc = esc
typecheck(&n, Erv) n = typecheck(n, Erv)
if n.Type == nil { if n.Type == nil {
Fatalf("mkdotargslice: typecheck failed") Fatalf("mkdotargslice: typecheck failed")
} }
walkexpr(&n, init) n = walkexpr(n, init)
} }
a := Nod(OAS, nodarg(l, fp), n) a := Nod(OAS, nodarg(l, fp), n)
...@@ -1848,8 +1849,8 @@ func ascompatte(op Op, call *Node, isddd bool, nl *Type, lr []*Node, fp int, ini ...@@ -1848,8 +1849,8 @@ func ascompatte(op Op, call *Node, isddd bool, nl *Type, lr []*Node, fp int, ini
a := Nod(OAS2, nil, nil) a := Nod(OAS2, nil, nil)
a.List.Set(alist) a.List.Set(alist)
a.Rlist.Set(lr) a.Rlist.Set(lr)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkstmt(&a) a = walkstmt(a)
init.Append(a) init.Append(a)
lr = alist lr = alist
r = lr[0] r = lr[0]
...@@ -1945,20 +1946,20 @@ func walkprint(nn *Node, init *Nodes) *Node { ...@@ -1945,20 +1946,20 @@ func walkprint(nn *Node, init *Nodes) *Node {
if n.Op == OLITERAL { if n.Op == OLITERAL {
switch n.Val().Ctype() { switch n.Val().Ctype() {
case CTRUNE: case CTRUNE:
defaultlit(&n, runetype) n = defaultlit(n, runetype)
case CTINT: case CTINT:
defaultlit(&n, Types[TINT64]) n = defaultlit(n, Types[TINT64])
case CTFLT: case CTFLT:
defaultlit(&n, Types[TFLOAT64]) n = defaultlit(n, Types[TFLOAT64])
} }
} }
if n.Op != OLITERAL && n.Type != nil && n.Type.Etype == TIDEAL { if n.Op != OLITERAL && n.Type != nil && n.Type.Etype == TIDEAL {
defaultlit(&n, Types[TINT64]) n = defaultlit(n, Types[TINT64])
} }
defaultlit(&n, nil) n = defaultlit(n, nil)
all.SetIndex(i1, n) all.SetIndex(i1, n)
if n.Type == nil || n.Type.Etype == TFORW { if n.Type == nil || n.Type.Etype == TFORW {
continue continue
...@@ -1972,13 +1973,13 @@ func walkprint(nn *Node, init *Nodes) *Node { ...@@ -1972,13 +1973,13 @@ func walkprint(nn *Node, init *Nodes) *Node {
} else { } else {
on = syslook("printiface") on = syslook("printiface")
} }
substArgTypes(&on, n.Type) // any-1 on = substArgTypes(on, n.Type) // any-1
} else if Isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR { } else if Isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR {
on = syslook("printpointer") on = syslook("printpointer")
substArgTypes(&on, n.Type) // any-1 on = substArgTypes(on, n.Type) // any-1
} else if Isslice(n.Type) { } else if Isslice(n.Type) {
on = syslook("printslice") on = syslook("printslice")
substArgTypes(&on, n.Type) // any-1 on = substArgTypes(on, n.Type) // any-1
} else if Isint[et] { } else if Isint[et] {
if et == TUINT64 { if et == TUINT64 {
if (t.Sym.Pkg == Runtimepkg || compiling_runtime != 0) && t.Sym.Name == "hex" { if (t.Sym.Pkg == Runtimepkg || compiling_runtime != 0) && t.Sym.Name == "hex" {
...@@ -2024,8 +2025,8 @@ func walkprint(nn *Node, init *Nodes) *Node { ...@@ -2024,8 +2025,8 @@ func walkprint(nn *Node, init *Nodes) *Node {
walkexprlist(calls, init) walkexprlist(calls, init)
r = Nod(OEMPTY, nil, nil) r = Nod(OEMPTY, nil, nil)
typecheck(&r, Etop) r = typecheck(r, Etop)
walkexpr(&r, init) r = walkexpr(r, init)
r.Ninit.Set(calls) r.Ninit.Set(calls)
return r return r
} }
...@@ -2033,7 +2034,7 @@ func walkprint(nn *Node, init *Nodes) *Node { ...@@ -2033,7 +2034,7 @@ func walkprint(nn *Node, init *Nodes) *Node {
func callnew(t *Type) *Node { func callnew(t *Type) *Node {
dowidth(t) dowidth(t)
fn := syslook("newobject") fn := syslook("newobject")
substArgTypes(&fn, t) fn = substArgTypes(fn, t)
return mkcall1(fn, Ptrto(t), nil, typename(t)) return mkcall1(fn, Ptrto(t), nil, typename(t))
} }
...@@ -2181,7 +2182,7 @@ func convas(n *Node, init *Nodes) *Node { ...@@ -2181,7 +2182,7 @@ func convas(n *Node, init *Nodes) *Node {
} }
if isblank(n.Left) { if isblank(n.Left) {
defaultlit(&n.Right, nil) n.Right = defaultlit(n.Right, nil)
goto out goto out
} }
...@@ -2189,9 +2190,9 @@ func convas(n *Node, init *Nodes) *Node { ...@@ -2189,9 +2190,9 @@ func convas(n *Node, init *Nodes) *Node {
map_ := n.Left.Left map_ := n.Left.Left
key := n.Left.Right key := n.Left.Right
val := n.Right val := n.Right
walkexpr(&map_, init) map_ = walkexpr(map_, init)
walkexpr(&key, init) key = walkexpr(key, init)
walkexpr(&val, init) val = walkexpr(val, init)
// orderexpr made sure key and val are addressable. // orderexpr made sure key and val are addressable.
key = Nod(OADDR, key, nil) key = Nod(OADDR, key, nil)
...@@ -2203,7 +2204,7 @@ func convas(n *Node, init *Nodes) *Node { ...@@ -2203,7 +2204,7 @@ func convas(n *Node, init *Nodes) *Node {
if !Eqtype(lt, rt) { if !Eqtype(lt, rt) {
n.Right = assignconv(n.Right, lt, "assignment") n.Right = assignconv(n.Right, lt, "assignment")
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
} }
out: out:
...@@ -2296,7 +2297,7 @@ func reorder3(all []*Node) []*Node { ...@@ -2296,7 +2297,7 @@ func reorder3(all []*Node) []*Node {
} }
if l.Op == OINDEX && Isfixedarray(l.Left.Type) { if l.Op == OINDEX && Isfixedarray(l.Left.Type) {
reorder3save(&l.Right, all, i, &early) l.Right = reorder3save(l.Right, all, i, &early)
l = l.Left l = l.Left
continue continue
} }
...@@ -2312,18 +2313,18 @@ func reorder3(all []*Node) []*Node { ...@@ -2312,18 +2313,18 @@ func reorder3(all []*Node) []*Node {
break break
case OINDEX, OINDEXMAP: case OINDEX, OINDEXMAP:
reorder3save(&l.Left, all, i, &early) l.Left = reorder3save(l.Left, all, i, &early)
reorder3save(&l.Right, all, i, &early) l.Right = reorder3save(l.Right, all, i, &early)
if l.Op == OINDEXMAP { if l.Op == OINDEXMAP {
all[i] = convas(all[i], &mapinit) all[i] = convas(all[i], &mapinit)
} }
case OIND, ODOTPTR: case OIND, ODOTPTR:
reorder3save(&l.Left, all, i, &early) l.Left = reorder3save(l.Left, all, i, &early)
} }
// Save expression on right side. // Save expression on right side.
reorder3save(&all[i].Right, all, i, &early) all[i].Right = reorder3save(all[i].Right, all, i, &early)
} }
early = append(mapinit.Slice(), early...) early = append(mapinit.Slice(), early...)
...@@ -2334,17 +2335,18 @@ func reorder3(all []*Node) []*Node { ...@@ -2334,17 +2335,18 @@ func reorder3(all []*Node) []*Node {
// assignments in all up to but not including the ith assignment, // assignments in all up to but not including the ith assignment,
// copy into a temporary during *early and // copy into a temporary during *early and
// replace *np with that temp. // replace *np with that temp.
func reorder3save(np **Node, all []*Node, i int, early *[]*Node) { // The result of reorder3save MUST be assigned back to n, e.g.
n := *np // n.Left = reorder3save(n.Left, all, i, early)
func reorder3save(n *Node, all []*Node, i int, early *[]*Node) *Node {
if !aliased(n, all, i) { if !aliased(n, all, i) {
return return n
} }
q := temp(n.Type) q := temp(n.Type)
q = Nod(OAS, q, n) q = Nod(OAS, q, n)
typecheck(&q, Etop) q = typecheck(q, Etop)
*early = append(*early, q) *early = append(*early, q)
*np = q.Left return q.Left
} }
// what's the outer value that a write to n affects? // what's the outer value that a write to n affects?
...@@ -2590,7 +2592,7 @@ func paramstoheap(params *Type, out bool) []*Node { ...@@ -2590,7 +2592,7 @@ func paramstoheap(params *Type, out bool) []*Node {
if v.Class&^PHEAP != PPARAMOUT { if v.Class&^PHEAP != PPARAMOUT {
as := Nod(OAS, v, v.Name.Param.Stackparam) as := Nod(OAS, v, v.Name.Param.Stackparam)
v.Name.Param.Stackparam.Typecheck = 1 v.Name.Param.Stackparam.Typecheck = 1
typecheck(&as, Etop) as = typecheck(as, Etop)
as = applywritebarrier(as) as = applywritebarrier(as)
nn = append(nn, as) nn = append(nn, as)
} }
...@@ -2639,11 +2641,11 @@ func vmkcall(fn *Node, t *Type, init *Nodes, va []*Node) *Node { ...@@ -2639,11 +2641,11 @@ func vmkcall(fn *Node, t *Type, init *Nodes, va []*Node) *Node {
r := Nod(OCALL, fn, nil) r := Nod(OCALL, fn, nil)
r.List.Set(va[:n]) r.List.Set(va[:n])
if fn.Type.Results().NumFields() > 0 { if fn.Type.Results().NumFields() > 0 {
typecheck(&r, Erv|Efnstruct) r = typecheck(r, Erv|Efnstruct)
} else { } else {
typecheck(&r, Etop) r = typecheck(r, Etop)
} }
walkexpr(&r, init) r = walkexpr(r, init)
r.Type = t r.Type = t
return r return r
} }
...@@ -2662,7 +2664,7 @@ func conv(n *Node, t *Type) *Node { ...@@ -2662,7 +2664,7 @@ func conv(n *Node, t *Type) *Node {
} }
n = Nod(OCONV, n, nil) n = Nod(OCONV, n, nil)
n.Type = t n.Type = t
typecheck(&n, Erv) n = typecheck(n, Erv)
return n return n
} }
...@@ -2675,9 +2677,9 @@ func chanfn(name string, n int, t *Type) *Node { ...@@ -2675,9 +2677,9 @@ func chanfn(name string, n int, t *Type) *Node {
default: default:
Fatalf("chanfn %d", n) Fatalf("chanfn %d", n)
case 1: case 1:
substArgTypes(&fn, t.Type) fn = substArgTypes(fn, t.Type)
case 2: case 2:
substArgTypes(&fn, t.Type, t.Type) fn = substArgTypes(fn, t.Type, t.Type)
} }
return fn return fn
} }
...@@ -2687,7 +2689,7 @@ func mapfn(name string, t *Type) *Node { ...@@ -2687,7 +2689,7 @@ func mapfn(name string, t *Type) *Node {
Fatalf("mapfn %v", t) Fatalf("mapfn %v", t)
} }
fn := syslook(name) fn := syslook(name)
substArgTypes(&fn, t.Key(), t.Type, t.Key(), t.Type) fn = substArgTypes(fn, t.Key(), t.Type, t.Key(), t.Type)
return fn return fn
} }
...@@ -2696,13 +2698,13 @@ func mapfndel(name string, t *Type) *Node { ...@@ -2696,13 +2698,13 @@ func mapfndel(name string, t *Type) *Node {
Fatalf("mapfn %v", t) Fatalf("mapfn %v", t)
} }
fn := syslook(name) fn := syslook(name)
substArgTypes(&fn, t.Key(), t.Type, t.Key()) fn = substArgTypes(fn, t.Key(), t.Type, t.Key())
return fn return fn
} }
func writebarrierfn(name string, l *Type, r *Type) *Node { func writebarrierfn(name string, l *Type, r *Type) *Node {
fn := syslook(name) fn := syslook(name)
substArgTypes(&fn, l, r) fn = substArgTypes(fn, l, r)
return fn return fn
} }
...@@ -2763,8 +2765,8 @@ func addstr(n *Node, init *Nodes) *Node { ...@@ -2763,8 +2765,8 @@ func addstr(n *Node, init *Nodes) *Node {
cat := syslook(fn) cat := syslook(fn)
r := Nod(OCALL, cat, nil) r := Nod(OCALL, cat, nil)
r.List.Set(args) r.List.Set(args)
typecheck(&r, Erv) r = typecheck(r, Erv)
walkexpr(&r, init) r = walkexpr(r, init)
r.Type = n.Type r.Type = n.Type
return r return r
...@@ -2816,7 +2818,7 @@ func appendslice(n *Node, init *Nodes) *Node { ...@@ -2816,7 +2818,7 @@ func appendslice(n *Node, init *Nodes) *Node {
// instantiate growslice(Type*, []any, int) []any // instantiate growslice(Type*, []any, int) []any
fn := syslook("growslice") fn := syslook("growslice")
substArgTypes(&fn, s.Type.Type, s.Type.Type) fn = substArgTypes(fn, s.Type.Type, s.Type.Type)
// s = growslice(T, s, n) // s = growslice(T, s, n)
nif.Nbody.Set1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nn))) nif.Nbody.Set1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nn)))
...@@ -2834,7 +2836,7 @@ func appendslice(n *Node, init *Nodes) *Node { ...@@ -2834,7 +2836,7 @@ func appendslice(n *Node, init *Nodes) *Node {
nptr1.Etype = 1 nptr1.Etype = 1
nptr2 := l2 nptr2 := l2
fn := syslook("typedslicecopy") fn := syslook("typedslicecopy")
substArgTypes(&fn, l1.Type, l2.Type) fn = substArgTypes(fn, l1.Type, l2.Type)
var ln Nodes var ln Nodes
ln.Set(l) ln.Set(l)
nt := mkcall1(fn, Types[TINT], &ln, typename(l1.Type.Type), nptr1, nptr2) nt := mkcall1(fn, Types[TINT], &ln, typename(l1.Type.Type), nptr1, nptr2)
...@@ -2852,7 +2854,7 @@ func appendslice(n *Node, init *Nodes) *Node { ...@@ -2852,7 +2854,7 @@ func appendslice(n *Node, init *Nodes) *Node {
} else { } else {
fn = syslook("slicecopy") fn = syslook("slicecopy")
} }
substArgTypes(&fn, l1.Type, l2.Type) fn = substArgTypes(fn, l1.Type, l2.Type)
var ln Nodes var ln Nodes
ln.Set(l) ln.Set(l)
nt := mkcall1(fn, Types[TINT], &ln, nptr1, nptr2, Nodintconst(s.Type.Type.Width)) nt := mkcall1(fn, Types[TINT], &ln, nptr1, nptr2, Nodintconst(s.Type.Type.Width))
...@@ -2867,7 +2869,7 @@ func appendslice(n *Node, init *Nodes) *Node { ...@@ -2867,7 +2869,7 @@ func appendslice(n *Node, init *Nodes) *Node {
nptr2 := Nod(OSPTR, l2, nil) nptr2 := Nod(OSPTR, l2, nil)
fn := syslook("memmove") fn := syslook("memmove")
substArgTypes(&fn, s.Type.Type, s.Type.Type) fn = substArgTypes(fn, s.Type.Type, s.Type.Type)
var ln Nodes var ln Nodes
ln.Set(l) ln.Set(l)
...@@ -2908,7 +2910,7 @@ func appendslice(n *Node, init *Nodes) *Node { ...@@ -2908,7 +2910,7 @@ func appendslice(n *Node, init *Nodes) *Node {
func walkappend(n *Node, init *Nodes, dst *Node) *Node { func walkappend(n *Node, init *Nodes, dst *Node) *Node {
if !samesafeexpr(dst, n.List.First()) { if !samesafeexpr(dst, n.List.First()) {
n.List.SetIndex(0, safeexpr(n.List.Index(0), init)) n.List.SetIndex(0, safeexpr(n.List.Index(0), init))
walkexpr(n.List.Addr(0), init) n.List.SetIndex(0, walkexpr(n.List.Index(0), init))
} }
walkexprlistsafe(n.List.Slice()[1:], init) walkexprlistsafe(n.List.Slice()[1:], init)
...@@ -2950,7 +2952,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node { ...@@ -2950,7 +2952,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
nx.Left = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na) nx.Left = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na)
fn := syslook("growslice") // growslice(<type>, old []T, mincap int) (ret []T) fn := syslook("growslice") // growslice(<type>, old []T, mincap int) (ret []T)
substArgTypes(&fn, ns.Type.Type, ns.Type.Type) fn = substArgTypes(fn, ns.Type.Type, ns.Type.Type)
nx.Nbody.Set1(Nod(OAS, ns, nx.Nbody.Set1(Nod(OAS, ns,
mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns, mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns,
...@@ -3005,12 +3007,12 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node { ...@@ -3005,12 +3007,12 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node {
} else { } else {
fn = syslook("slicecopy") fn = syslook("slicecopy")
} }
substArgTypes(&fn, n.Left.Type, n.Right.Type) fn = substArgTypes(fn, n.Left.Type, n.Right.Type)
return mkcall1(fn, n.Type, init, n.Left, n.Right, Nodintconst(n.Left.Type.Type.Width)) return mkcall1(fn, n.Type, init, n.Left, n.Right, Nodintconst(n.Left.Type.Type.Width))
} }
walkexpr(&n.Left, init) n.Left = walkexpr(n.Left, init)
walkexpr(&n.Right, init) n.Right = walkexpr(n.Right, init)
nl := temp(n.Left.Type) nl := temp(n.Left.Type)
nr := temp(n.Right.Type) nr := temp(n.Right.Type)
var l []*Node var l []*Node
...@@ -3035,7 +3037,7 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node { ...@@ -3035,7 +3037,7 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node {
// Call memmove. // Call memmove.
fn := syslook("memmove") fn := syslook("memmove")
substArgTypes(&fn, nl.Type.Type, nl.Type.Type) fn = substArgTypes(fn, nl.Type.Type, nl.Type.Type)
nwid := temp(Types[TUINTPTR]) nwid := temp(Types[TUINTPTR])
l = append(l, Nod(OAS, nwid, conv(nlen, Types[TUINTPTR]))) l = append(l, Nod(OAS, nwid, conv(nlen, Types[TUINTPTR])))
nwid = Nod(OMUL, nwid, Nodintconst(nl.Type.Type.Width)) nwid = Nod(OMUL, nwid, Nodintconst(nl.Type.Type.Width))
...@@ -3060,7 +3062,7 @@ func eqfor(t *Type, needsize *int) *Node { ...@@ -3060,7 +3062,7 @@ func eqfor(t *Type, needsize *int) *Node {
if a == AMEM { if a == AMEM {
n := syslook("memequal") n := syslook("memequal")
substArgTypes(&n, t, t) n = substArgTypes(n, t, t)
*needsize = 1 *needsize = 1
return n return n
} }
...@@ -3072,15 +3074,15 @@ func eqfor(t *Type, needsize *int) *Node { ...@@ -3072,15 +3074,15 @@ func eqfor(t *Type, needsize *int) *Node {
ntype.List.Append(Nod(ODCLFIELD, nil, typenod(Ptrto(t)))) ntype.List.Append(Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
ntype.List.Append(Nod(ODCLFIELD, nil, typenod(Ptrto(t)))) ntype.List.Append(Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
ntype.Rlist.Append(Nod(ODCLFIELD, nil, typenod(Types[TBOOL]))) ntype.Rlist.Append(Nod(ODCLFIELD, nil, typenod(Types[TBOOL])))
typecheck(&ntype, Etype) ntype = typecheck(ntype, Etype)
n.Type = ntype.Type n.Type = ntype.Type
*needsize = 0 *needsize = 0
return n return n
} }
func walkcompare(np **Node, init *Nodes) { // The result of walkcompare MUST be assigned back to n, e.g.
n := *np // n.Left = walkcompare(n.Left, init)
func walkcompare(n *Node, init *Nodes) *Node {
// Given interface value l and concrete value r, rewrite // Given interface value l and concrete value r, rewrite
// l == r // l == r
// to // to
...@@ -3103,7 +3105,7 @@ func walkcompare(np **Node, init *Nodes) { ...@@ -3103,7 +3105,7 @@ func walkcompare(np **Node, init *Nodes) {
x := temp(r.Type) x := temp(r.Type)
if haspointers(r.Type) { if haspointers(r.Type) {
a := Nod(OAS, x, nil) a := Nod(OAS, x, nil)
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) init.Append(a)
} }
ok := temp(Types[TBOOL]) ok := temp(Types[TBOOL])
...@@ -3119,8 +3121,8 @@ func walkcompare(np **Node, init *Nodes) { ...@@ -3119,8 +3121,8 @@ func walkcompare(np **Node, init *Nodes) {
expr.List.Append(x) expr.List.Append(x)
expr.List.Append(ok) expr.List.Append(ok)
expr.Rlist.Append(a) expr.Rlist.Append(a)
typecheck(&expr, Etop) expr = typecheck(expr, Etop)
walkexpr(&expr, init) expr = walkexpr(expr, init)
if n.Op == OEQ { if n.Op == OEQ {
r = Nod(OANDAND, ok, Nod(OEQ, x, r)) r = Nod(OANDAND, ok, Nod(OEQ, x, r))
...@@ -3128,8 +3130,8 @@ func walkcompare(np **Node, init *Nodes) { ...@@ -3128,8 +3130,8 @@ func walkcompare(np **Node, init *Nodes) {
r = Nod(OOROR, Nod(ONOT, ok, nil), Nod(ONE, x, r)) r = Nod(OOROR, Nod(ONOT, ok, nil), Nod(ONE, x, r))
} }
init.Append(expr) init.Append(expr)
finishcompare(np, n, r, init) n = finishcompare(n, n, r, init)
return return n
} }
// Must be comparison of array or struct. // Must be comparison of array or struct.
...@@ -3138,11 +3140,11 @@ func walkcompare(np **Node, init *Nodes) { ...@@ -3138,11 +3140,11 @@ func walkcompare(np **Node, init *Nodes) {
switch t.Etype { switch t.Etype {
default: default:
return return n
case TARRAY: case TARRAY:
if Isslice(t) { if Isslice(t) {
return return n
} }
case TSTRUCT: case TSTRUCT:
...@@ -3165,13 +3167,13 @@ func walkcompare(np **Node, init *Nodes) { ...@@ -3165,13 +3167,13 @@ func walkcompare(np **Node, init *Nodes) {
l = temp(Ptrto(t)) l = temp(Ptrto(t))
a := Nod(OAS, l, Nod(OADDR, cmpl, nil)) a := Nod(OAS, l, Nod(OADDR, cmpl, nil))
a.Right.Etype = 1 // addr does not escape a.Right.Etype = 1 // addr does not escape
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) init.Append(a)
r = temp(Ptrto(t)) r = temp(Ptrto(t))
a = Nod(OAS, r, Nod(OADDR, cmpr, nil)) a = Nod(OAS, r, Nod(OADDR, cmpr, nil))
a.Right.Etype = 1 // addr does not escape a.Right.Etype = 1 // addr does not escape
typecheck(&a, Etop) a = typecheck(a, Etop)
init.Append(a) init.Append(a)
var andor Op = OANDAND var andor Op = OANDAND
...@@ -3199,22 +3201,22 @@ func walkcompare(np **Node, init *Nodes) { ...@@ -3199,22 +3201,22 @@ func walkcompare(np **Node, init *Nodes) {
if expr == nil { if expr == nil {
expr = Nodbool(n.Op == OEQ) expr = Nodbool(n.Op == OEQ)
} }
finishcompare(np, n, expr, init) n = finishcompare(n, n, expr, init)
return return n
} }
if t.Etype == TARRAY { if t.Etype == TARRAY {
// Zero- or single-element array, of any type. // Zero- or single-element array, of any type.
switch t.Bound { switch t.Bound {
case 0: case 0:
finishcompare(np, n, Nodbool(n.Op == OEQ), init) n = finishcompare(n, n, Nodbool(n.Op == OEQ), init)
return return n
case 1: case 1:
l0 := Nod(OINDEX, l, Nodintconst(0)) l0 := Nod(OINDEX, l, Nodintconst(0))
r0 := Nod(OINDEX, r, Nodintconst(0)) r0 := Nod(OINDEX, r, Nodintconst(0))
a := Nod(n.Op, l0, r0) a := Nod(n.Op, l0, r0)
finishcompare(np, n, a, init) n = finishcompare(n, n, a, init)
return return n
} }
} }
...@@ -3240,8 +3242,8 @@ func walkcompare(np **Node, init *Nodes) { ...@@ -3240,8 +3242,8 @@ func walkcompare(np **Node, init *Nodes) {
if expr == nil { if expr == nil {
expr = Nodbool(n.Op == OEQ) expr = Nodbool(n.Op == OEQ)
} }
finishcompare(np, n, expr, init) n = finishcompare(n, n, expr, init)
return return n
} }
// Chose not to inline. Call equality function directly. // Chose not to inline. Call equality function directly.
...@@ -3258,22 +3260,25 @@ func walkcompare(np **Node, init *Nodes) { ...@@ -3258,22 +3260,25 @@ func walkcompare(np **Node, init *Nodes) {
r = Nod(ONOT, r, nil) r = Nod(ONOT, r, nil)
} }
finishcompare(np, n, r, init) n = finishcompare(n, n, r, init)
return return n
} }
func finishcompare(np **Node, n, r *Node, init *Nodes) { // The result of finishcompare MUST be assigned back to nn, e.g.
// Using np here to avoid passing &r to typecheck. // n.Left = finishcompare(n.Left, x, r, init)
*np = r func finishcompare(nn *Node, n, r *Node, init *Nodes) *Node {
typecheck(np, Erv) // Use nn here to avoid passing r to typecheck.
walkexpr(np, init) nn = r
r = *np nn = typecheck(nn, Erv)
nn = walkexpr(nn, init)
r = nn
if r.Type != n.Type { if r.Type != n.Type {
r = Nod(OCONVNOP, r, nil) r = Nod(OCONVNOP, r, nil)
r.Type = n.Type r.Type = n.Type
r.Typecheck = 1 r.Typecheck = 1
*np = r nn = r
} }
return nn
} }
func samecheap(a *Node, b *Node) bool { func samecheap(a *Node, b *Node) bool {
...@@ -3307,24 +3312,24 @@ func samecheap(a *Node, b *Node) bool { ...@@ -3307,24 +3312,24 @@ func samecheap(a *Node, b *Node) bool {
return false return false
} }
func walkrotate(np **Node) { // The result of walkrotate MUST be assigned back to n, e.g.
// n.Left = walkrotate(n.Left)
func walkrotate(n *Node) *Node {
if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' { if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
return return n
} }
n := *np
// Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value. // Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value.
l := n.Left l := n.Left
r := n.Right r := n.Right
if (n.Op != OOR && n.Op != OXOR) || (l.Op != OLSH && l.Op != ORSH) || (r.Op != OLSH && r.Op != ORSH) || n.Type == nil || Issigned[n.Type.Etype] || l.Op == r.Op { if (n.Op != OOR && n.Op != OXOR) || (l.Op != OLSH && l.Op != ORSH) || (r.Op != OLSH && r.Op != ORSH) || n.Type == nil || Issigned[n.Type.Etype] || l.Op == r.Op {
return return n
} }
// Want same, side effect-free expression on lhs of both shifts. // Want same, side effect-free expression on lhs of both shifts.
if !samecheap(l.Left, r.Left) { if !samecheap(l.Left, r.Left) {
return return n
} }
// Constants adding to width? // Constants adding to width?
...@@ -3349,23 +3354,22 @@ func walkrotate(np **Node) { ...@@ -3349,23 +3354,22 @@ func walkrotate(np **Node) {
if s == 0 || s == w { if s == 0 || s == w {
n = n.Left n = n.Left
} }
return n
*np = n
return
} }
} }
return return n
} }
// TODO: Could allow s and 32-s if s is bounded (maybe s&31 and 32-s&31). // TODO: Could allow s and 32-s if s is bounded (maybe s&31 and 32-s&31).
return return n
} }
// walkmul rewrites integer multiplication by powers of two as shifts. // walkmul rewrites integer multiplication by powers of two as shifts.
func walkmul(np **Node, init *Nodes) { // The result of walkmul MUST be assigned back to n, e.g.
n := *np // n.Left = walkmul(n.Left, init)
func walkmul(n *Node, init *Nodes) *Node {
if !Isint[n.Type.Etype] { if !Isint[n.Type.Etype] {
return return n
} }
var nr *Node var nr *Node
...@@ -3377,7 +3381,7 @@ func walkmul(np **Node, init *Nodes) { ...@@ -3377,7 +3381,7 @@ func walkmul(np **Node, init *Nodes) {
nl = n.Right nl = n.Right
nr = n.Left nr = n.Left
} else { } else {
return return n
} }
neg := 0 neg := 0
...@@ -3395,7 +3399,7 @@ func walkmul(np **Node, init *Nodes) { ...@@ -3395,7 +3399,7 @@ func walkmul(np **Node, init *Nodes) {
pow = powtwo(nr) pow = powtwo(nr)
if pow < 0 { if pow < 0 {
return return n
} }
if pow >= 1000 { if pow >= 1000 {
// negative power of 2, like -16 // negative power of 2, like -16
...@@ -3406,7 +3410,7 @@ func walkmul(np **Node, init *Nodes) { ...@@ -3406,7 +3410,7 @@ func walkmul(np **Node, init *Nodes) {
w = int(nl.Type.Width * 8) w = int(nl.Type.Width * 8)
if pow+1 >= w { // too big, shouldn't happen if pow+1 >= w { // too big, shouldn't happen
return return n
} }
nl = cheapexpr(nl, init) nl = cheapexpr(nl, init)
...@@ -3425,24 +3429,25 @@ ret: ...@@ -3425,24 +3429,25 @@ ret:
n = Nod(OMINUS, n, nil) n = Nod(OMINUS, n, nil)
} }
typecheck(&n, Erv) n = typecheck(n, Erv)
walkexpr(&n, init) n = walkexpr(n, init)
*np = n return n
} }
// walkdiv rewrites division by a constant as less expensive // walkdiv rewrites division by a constant as less expensive
// operations. // operations.
func walkdiv(np **Node, init *Nodes) { // The result of walkdiv MUST be assigned back to n, e.g.
// n.Left = walkdiv(n.Left, init)
func walkdiv(n *Node, init *Nodes) *Node {
// if >= 0, nr is 1<<pow // 1 if nr is negative. // if >= 0, nr is 1<<pow // 1 if nr is negative.
// TODO(minux) // TODO(minux)
if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' { if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
return return n
} }
n := *np
if n.Right.Op != OLITERAL { if n.Right.Op != OLITERAL {
return return n
} }
// nr is a constant. // nr is a constant.
...@@ -3465,7 +3470,7 @@ func walkdiv(np **Node, init *Nodes) { ...@@ -3465,7 +3470,7 @@ func walkdiv(np **Node, init *Nodes) {
if pow+1 >= w { if pow+1 >= w {
// divisor too large. // divisor too large.
return return n
} }
if pow < 0 { if pow < 0 {
...@@ -3484,7 +3489,7 @@ func walkdiv(np **Node, init *Nodes) { ...@@ -3484,7 +3489,7 @@ func walkdiv(np **Node, init *Nodes) {
} }
if m.Bad != 0 { if m.Bad != 0 {
return return n
} }
// We have a quick division method so use it // We have a quick division method so use it
...@@ -3500,7 +3505,7 @@ func walkdiv(np **Node, init *Nodes) { ...@@ -3500,7 +3505,7 @@ func walkdiv(np **Node, init *Nodes) {
switch Simtype[nl.Type.Etype] { switch Simtype[nl.Type.Etype] {
default: default:
return return n
// n1 = nl * magic >> w (HMUL) // n1 = nl * magic >> w (HMUL)
case TUINT8, TUINT16, TUINT32: case TUINT8, TUINT16, TUINT32:
...@@ -3508,13 +3513,13 @@ func walkdiv(np **Node, init *Nodes) { ...@@ -3508,13 +3513,13 @@ func walkdiv(np **Node, init *Nodes) {
Nodconst(nc, nl.Type, int64(m.Um)) Nodconst(nc, nl.Type, int64(m.Um))
n1 := Nod(OHMUL, nl, nc) n1 := Nod(OHMUL, nl, nc)
typecheck(&n1, Erv) n1 = typecheck(n1, Erv)
if m.Ua != 0 { if m.Ua != 0 {
// Select a Go type with (at least) twice the width. // Select a Go type with (at least) twice the width.
var twide *Type var twide *Type
switch Simtype[nl.Type.Etype] { switch Simtype[nl.Type.Etype] {
default: default:
return return n
case TUINT8, TUINT16: case TUINT8, TUINT16:
twide = Types[TUINT32] twide = Types[TUINT32]
...@@ -3552,7 +3557,7 @@ func walkdiv(np **Node, init *Nodes) { ...@@ -3552,7 +3557,7 @@ func walkdiv(np **Node, init *Nodes) {
Nodconst(nc, nl.Type, m.Sm) Nodconst(nc, nl.Type, m.Sm)
n1 := Nod(OHMUL, nl, nc) n1 := Nod(OHMUL, nl, nc)
typecheck(&n1, Erv) n1 = typecheck(n1, Erv)
if m.Sm < 0 { if m.Sm < 0 {
// add the numerator. // add the numerator.
n1 = Nod(OADD, n1, nl) n1 = Nod(OADD, n1, nl)
...@@ -3606,7 +3611,7 @@ func walkdiv(np **Node, init *Nodes) { ...@@ -3606,7 +3611,7 @@ func walkdiv(np **Node, init *Nodes) {
Nodconst(nc, Types[Simtype[TUINT]], int64(w)-1) Nodconst(nc, Types[Simtype[TUINT]], int64(w)-1)
n1 := Nod(ORSH, nl, nc) // n1 = -1 iff nl < 0. n1 := Nod(ORSH, nl, nc) // n1 = -1 iff nl < 0.
if pow == 1 { if pow == 1 {
typecheck(&n1, Erv) n1 = typecheck(n1, Erv)
n1 = cheapexpr(n1, init) n1 = cheapexpr(n1, init)
// n = (nl+ε)&1 -ε where ε=1 iff nl<0. // n = (nl+ε)&1 -ε where ε=1 iff nl<0.
...@@ -3622,7 +3627,7 @@ func walkdiv(np **Node, init *Nodes) { ...@@ -3622,7 +3627,7 @@ func walkdiv(np **Node, init *Nodes) {
Nodconst(nc, nl.Type, (1<<uint(pow))-1) Nodconst(nc, nl.Type, (1<<uint(pow))-1)
n2 := Nod(OAND, n1, nc) // n2 = 2^pow-1 iff nl<0. n2 := Nod(OAND, n1, nc) // n2 = 2^pow-1 iff nl<0.
typecheck(&n2, Erv) n2 = typecheck(n2, Erv)
n2 = cheapexpr(n2, init) n2 = cheapexpr(n2, init)
n3 := Nod(OADD, nl, n2) n3 := Nod(OADD, nl, n2)
...@@ -3686,9 +3691,9 @@ func walkdiv(np **Node, init *Nodes) { ...@@ -3686,9 +3691,9 @@ func walkdiv(np **Node, init *Nodes) {
goto ret goto ret
ret: ret:
typecheck(&n, Erv) n = typecheck(n, Erv)
walkexpr(&n, init) n = walkexpr(n, init)
*np = n return n
} }
// return 1 if integer n must be in range [0, max), 0 otherwise // return 1 if integer n must be in range [0, max), 0 otherwise
...@@ -3954,9 +3959,9 @@ func candiscard(n *Node) bool { ...@@ -3954,9 +3959,9 @@ func candiscard(n *Node) bool {
var walkprintfunc_prgen int var walkprintfunc_prgen int
func walkprintfunc(np **Node, init *Nodes) { // The result of walkprintfunc MUST be assigned back to n, e.g.
n := *np // n.Left = walkprintfunc(n.Left, init)
func walkprintfunc(n *Node, init *Nodes) *Node {
if n.Ninit.Len() != 0 { if n.Ninit.Len() != 0 {
walkstmtlist(n.Ninit.Slice()) walkstmtlist(n.Ninit.Slice())
init.AppendNodes(&n.Ninit) init.AppendNodes(&n.Ninit)
...@@ -3989,14 +3994,14 @@ func walkprintfunc(np **Node, init *Nodes) { ...@@ -3989,14 +3994,14 @@ func walkprintfunc(np **Node, init *Nodes) {
a = Nod(n.Op, nil, nil) a = Nod(n.Op, nil, nil)
a.List.Set(printargs) a.List.Set(printargs)
typecheck(&a, Etop) a = typecheck(a, Etop)
walkstmt(&a) a = walkstmt(a)
fn.Nbody.Set1(a) fn.Nbody.Set1(a)
funcbody(fn) funcbody(fn)
typecheck(&fn, Etop) fn = typecheck(fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop) typecheckslice(fn.Nbody.Slice(), Etop)
xtop = append(xtop, fn) xtop = append(xtop, fn)
Curfn = oldfn Curfn = oldfn
...@@ -4004,7 +4009,7 @@ func walkprintfunc(np **Node, init *Nodes) { ...@@ -4004,7 +4009,7 @@ func walkprintfunc(np **Node, init *Nodes) {
a = Nod(OCALL, nil, nil) a = Nod(OCALL, nil, nil)
a.Left = fn.Func.Nname a.Left = fn.Func.Nname
a.List.Set(n.List.Slice()) a.List.Set(n.List.Slice())
typecheck(&a, Etop) a = typecheck(a, Etop)
walkexpr(&a, init) a = walkexpr(a, init)
*np = a return a
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment