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)
} }
} }
......
This diff is collapsed.
...@@ -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
......
This diff is collapsed.
...@@ -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
......
This diff is collapsed.
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