mirror of
https://github.com/golang/go.git
synced 2025-11-01 17:20:56 +00:00
cmd/compile: remove Node.Ntest, Node.Stkdelta
$ sizeof -p cmd/compile/internal/gc Node Node 272 $ Change-Id: I3d9b67eebfc0be0a4b9768d3de3dc76300abd89c Reviewed-on: https://go-review.googlesource.com/10521 Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
ffef180f82
commit
66be1481df
20 changed files with 207 additions and 269 deletions
|
|
@ -134,7 +134,6 @@ func (v *bottomUpVisitor) visitcode(n *Node, min uint32) uint32 {
|
||||||
min = v.visitcode(n.Left, min)
|
min = v.visitcode(n.Left, min)
|
||||||
min = v.visitcode(n.Right, min)
|
min = v.visitcode(n.Right, min)
|
||||||
min = v.visitcodelist(n.List, min)
|
min = v.visitcodelist(n.List, min)
|
||||||
min = v.visitcode(n.Ntest, min)
|
|
||||||
min = v.visitcodelist(n.Nbody, min)
|
min = v.visitcodelist(n.Nbody, min)
|
||||||
min = v.visitcodelist(n.Rlist, min)
|
min = v.visitcodelist(n.Rlist, min)
|
||||||
|
|
||||||
|
|
@ -543,7 +542,6 @@ func escloopdepth(e *EscState, n *Node) {
|
||||||
escloopdepth(e, n.Left)
|
escloopdepth(e, n.Left)
|
||||||
escloopdepth(e, n.Right)
|
escloopdepth(e, n.Right)
|
||||||
escloopdepthlist(e, n.List)
|
escloopdepthlist(e, n.List)
|
||||||
escloopdepth(e, n.Ntest)
|
|
||||||
escloopdepthlist(e, n.Nbody)
|
escloopdepthlist(e, n.Nbody)
|
||||||
escloopdepthlist(e, n.Rlist)
|
escloopdepthlist(e, n.Rlist)
|
||||||
}
|
}
|
||||||
|
|
@ -572,7 +570,7 @@ func esc(e *EscState, n *Node, up *Node) {
|
||||||
// process type switch as declaration.
|
// process type switch as declaration.
|
||||||
// must happen before processing of switch body,
|
// must happen before processing of switch body,
|
||||||
// so before recursion.
|
// so before recursion.
|
||||||
if n.Op == OSWITCH && n.Ntest != nil && n.Ntest.Op == OTYPESW {
|
if n.Op == OSWITCH && n.Left != nil && n.Left.Op == OTYPESW {
|
||||||
for ll := n.List; ll != nil; ll = ll.Next { // cases
|
for ll := n.List; ll != nil; ll = ll.Next { // cases
|
||||||
|
|
||||||
// ll->n->nname is the variable per case
|
// ll->n->nname is the variable per case
|
||||||
|
|
@ -597,7 +595,6 @@ func esc(e *EscState, n *Node, up *Node) {
|
||||||
|
|
||||||
esc(e, n.Left, n)
|
esc(e, n.Left, n)
|
||||||
esc(e, n.Right, n)
|
esc(e, n.Right, n)
|
||||||
esc(e, n.Ntest, n)
|
|
||||||
esclist(e, n.Nbody, n)
|
esclist(e, n.Nbody, n)
|
||||||
esclist(e, n.List, n)
|
esclist(e, n.List, n)
|
||||||
esclist(e, n.Rlist, n)
|
esclist(e, n.Rlist, n)
|
||||||
|
|
@ -646,12 +643,12 @@ func esc(e *EscState, n *Node, up *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case OSWITCH:
|
case OSWITCH:
|
||||||
if n.Ntest != nil && n.Ntest.Op == OTYPESW {
|
if n.Left != nil && n.Left.Op == OTYPESW {
|
||||||
for ll := n.List; ll != nil; ll = ll.Next { // cases
|
for ll := n.List; ll != nil; ll = ll.Next {
|
||||||
|
// cases
|
||||||
// ntest->right is the argument of the .(type),
|
// ntest->right is the argument of the .(type),
|
||||||
// ll->n->nname is the variable per case
|
// ll->n->nname is the variable per case
|
||||||
escassign(e, ll.N.Nname, n.Ntest.Right)
|
escassign(e, ll.N.Nname, n.Left.Right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,6 @@ func reexportdep(n *Node) {
|
||||||
reexportdeplist(n.List)
|
reexportdeplist(n.List)
|
||||||
reexportdeplist(n.Rlist)
|
reexportdeplist(n.Rlist)
|
||||||
reexportdeplist(n.Ninit)
|
reexportdeplist(n.Ninit)
|
||||||
reexportdep(n.Ntest)
|
|
||||||
reexportdeplist(n.Nbody)
|
reexportdeplist(n.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,7 @@ func Jconv(n *Node, flag int) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c == 0 && n.Xoffset != BADWIDTH {
|
if c == 0 && n.Xoffset != BADWIDTH {
|
||||||
fmt.Fprintf(&buf, " x(%d%+d)", n.Xoffset, n.Stkdelta)
|
fmt.Fprintf(&buf, " x(%d%+d)", n.Xoffset, stkdelta[n])
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Class != 0 {
|
if n.Class != 0 {
|
||||||
|
|
@ -863,9 +863,9 @@ func stmtfmt(n *Node) string {
|
||||||
|
|
||||||
case OIF:
|
case OIF:
|
||||||
if simpleinit {
|
if simpleinit {
|
||||||
f += fmt.Sprintf("if %v; %v { %v }", n.Ninit.N, n.Ntest, n.Nbody)
|
f += fmt.Sprintf("if %v; %v { %v }", n.Ninit.N, n.Left, n.Nbody)
|
||||||
} else {
|
} else {
|
||||||
f += fmt.Sprintf("if %v { %v }", n.Ntest, n.Nbody)
|
f += fmt.Sprintf("if %v { %v }", n.Left, n.Nbody)
|
||||||
}
|
}
|
||||||
if n.Rlist != nil {
|
if n.Rlist != nil {
|
||||||
f += fmt.Sprintf(" else { %v }", n.Rlist)
|
f += fmt.Sprintf(" else { %v }", n.Rlist)
|
||||||
|
|
@ -884,8 +884,8 @@ func stmtfmt(n *Node) string {
|
||||||
f += " ;"
|
f += " ;"
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Ntest != nil {
|
if n.Left != nil {
|
||||||
f += fmt.Sprintf(" %v", n.Ntest)
|
f += fmt.Sprintf(" %v", n.Left)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Right != nil {
|
if n.Right != nil {
|
||||||
|
|
@ -919,8 +919,8 @@ func stmtfmt(n *Node) string {
|
||||||
if simpleinit {
|
if simpleinit {
|
||||||
f += fmt.Sprintf(" %v;", n.Ninit.N)
|
f += fmt.Sprintf(" %v;", n.Ninit.N)
|
||||||
}
|
}
|
||||||
if n.Ntest != nil {
|
if n.Left != nil {
|
||||||
f += Nconv(n.Ntest, 0)
|
f += Nconv(n.Left, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
f += fmt.Sprintf(" { %v }", n.List)
|
f += fmt.Sprintf(" { %v }", n.List)
|
||||||
|
|
@ -1562,11 +1562,6 @@ func nodedump(n *Node, flag int) string {
|
||||||
fmt.Fprintf(&buf, "%v-rlist%v", Oconv(int(n.Op), 0), n.Rlist)
|
fmt.Fprintf(&buf, "%v-rlist%v", Oconv(int(n.Op), 0), n.Rlist)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Ntest != nil {
|
|
||||||
indent(&buf)
|
|
||||||
fmt.Fprintf(&buf, "%v-test%v", Oconv(int(n.Op), 0), n.Ntest)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Nbody != nil {
|
if n.Nbody != nil {
|
||||||
indent(&buf)
|
indent(&buf)
|
||||||
fmt.Fprintf(&buf, "%v-body%v", Oconv(int(n.Op), 0), n.Nbody)
|
fmt.Fprintf(&buf, "%v-body%v", Oconv(int(n.Op), 0), n.Nbody)
|
||||||
|
|
|
||||||
|
|
@ -788,10 +788,10 @@ func gen(n *Node) {
|
||||||
lab.Continpc = continpc
|
lab.Continpc = continpc
|
||||||
}
|
}
|
||||||
|
|
||||||
gen(n.Right) // contin: incr
|
gen(n.Right) // contin: incr
|
||||||
Patch(p1, Pc) // test:
|
Patch(p1, Pc) // test:
|
||||||
Bgen(n.Ntest, false, -1, breakpc) // if(!test) goto break
|
Bgen(n.Left, false, -1, breakpc) // if(!test) goto break
|
||||||
Genlist(n.Nbody) // body
|
Genlist(n.Nbody) // body
|
||||||
gjmp(continpc)
|
gjmp(continpc)
|
||||||
Patch(breakpc, Pc) // done:
|
Patch(breakpc, Pc) // done:
|
||||||
continpc = scontin
|
continpc = scontin
|
||||||
|
|
@ -802,15 +802,15 @@ func gen(n *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case OIF:
|
case OIF:
|
||||||
p1 := gjmp(nil) // goto test
|
p1 := gjmp(nil) // goto test
|
||||||
p2 := gjmp(nil) // p2: goto else
|
p2 := gjmp(nil) // p2: goto else
|
||||||
Patch(p1, Pc) // test:
|
Patch(p1, Pc) // test:
|
||||||
Bgen(n.Ntest, false, int(-n.Likely), p2) // if(!test) goto p2
|
Bgen(n.Left, false, int(-n.Likely), p2) // if(!test) goto p2
|
||||||
Genlist(n.Nbody) // then
|
Genlist(n.Nbody) // then
|
||||||
p3 := gjmp(nil) // goto done
|
p3 := gjmp(nil) // goto done
|
||||||
Patch(p2, Pc) // else:
|
Patch(p2, Pc) // else:
|
||||||
Genlist(n.Rlist) // else
|
Genlist(n.Rlist) // else
|
||||||
Patch(p3, Pc) // done:
|
Patch(p3, Pc) // done:
|
||||||
|
|
||||||
case OSWITCH:
|
case OSWITCH:
|
||||||
sbreak := breakpc
|
sbreak := breakpc
|
||||||
|
|
|
||||||
|
|
@ -700,14 +700,14 @@ for_header:
|
||||||
if $1 != nil {
|
if $1 != nil {
|
||||||
$$.Ninit = list1($1);
|
$$.Ninit = list1($1);
|
||||||
}
|
}
|
||||||
$$.Ntest = $3;
|
$$.Left = $3;
|
||||||
$$.Right = $5;
|
$$.Right = $5;
|
||||||
}
|
}
|
||||||
| osimple_stmt
|
| osimple_stmt
|
||||||
{
|
{
|
||||||
// normal test
|
// normal test
|
||||||
$$ = Nod(OFOR, nil, nil);
|
$$ = Nod(OFOR, nil, nil);
|
||||||
$$.Ntest = $1;
|
$$.Left = $1;
|
||||||
}
|
}
|
||||||
| range_stmt
|
| range_stmt
|
||||||
|
|
||||||
|
|
@ -734,7 +734,7 @@ if_header:
|
||||||
{
|
{
|
||||||
// test
|
// test
|
||||||
$$ = Nod(OIF, nil, nil);
|
$$ = Nod(OIF, nil, nil);
|
||||||
$$.Ntest = $1;
|
$$.Left = $1;
|
||||||
}
|
}
|
||||||
| osimple_stmt ';' osimple_stmt
|
| osimple_stmt ';' osimple_stmt
|
||||||
{
|
{
|
||||||
|
|
@ -743,7 +743,7 @@ if_header:
|
||||||
if $1 != nil {
|
if $1 != nil {
|
||||||
$$.Ninit = list1($1);
|
$$.Ninit = list1($1);
|
||||||
}
|
}
|
||||||
$$.Ntest = $3;
|
$$.Left = $3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IF cond body (ELSE IF cond body)* (ELSE block)? */
|
/* IF cond body (ELSE IF cond body)* (ELSE block)? */
|
||||||
|
|
@ -754,7 +754,7 @@ if_stmt:
|
||||||
}
|
}
|
||||||
if_header
|
if_header
|
||||||
{
|
{
|
||||||
if $3.Ntest == nil {
|
if $3.Left == nil {
|
||||||
Yyerror("missing condition in if statement");
|
Yyerror("missing condition in if statement");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -786,7 +786,7 @@ elseif:
|
||||||
}
|
}
|
||||||
if_header loop_body
|
if_header loop_body
|
||||||
{
|
{
|
||||||
if $4.Ntest == nil {
|
if $4.Left == nil {
|
||||||
Yyerror("missing condition in if statement");
|
Yyerror("missing condition in if statement");
|
||||||
}
|
}
|
||||||
$4.Nbody = $5;
|
$4.Nbody = $5;
|
||||||
|
|
@ -821,7 +821,7 @@ switch_stmt:
|
||||||
if_header
|
if_header
|
||||||
{
|
{
|
||||||
var n *Node
|
var n *Node
|
||||||
n = $3.Ntest;
|
n = $3.Left;
|
||||||
if n != nil && n.Op != OTYPESW {
|
if n != nil && n.Op != OTYPESW {
|
||||||
n = nil;
|
n = nil;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -196,11 +196,11 @@ func fixautoused(p *obj.Prog) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.From.Name == obj.NAME_AUTO && p.From.Node != nil {
|
if p.From.Name == obj.NAME_AUTO && p.From.Node != nil {
|
||||||
p.From.Offset += ((p.From.Node).(*Node)).Stkdelta
|
p.From.Offset += stkdelta[p.From.Node.(*Node)]
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.To.Name == obj.NAME_AUTO && p.To.Node != nil {
|
if p.To.Name == obj.NAME_AUTO && p.To.Node != nil {
|
||||||
p.To.Offset += ((p.To.Node).(*Node)).Stkdelta
|
p.To.Offset += stkdelta[p.To.Node.(*Node)]
|
||||||
}
|
}
|
||||||
|
|
||||||
lp = &p.Link
|
lp = &p.Link
|
||||||
|
|
|
||||||
|
|
@ -123,13 +123,13 @@ func fninit(n *NodeList) {
|
||||||
// (3)
|
// (3)
|
||||||
a := Nod(OIF, nil, nil)
|
a := Nod(OIF, nil, nil)
|
||||||
|
|
||||||
a.Ntest = Nod(ONE, gatevar, Nodintconst(0))
|
a.Left = Nod(ONE, gatevar, Nodintconst(0))
|
||||||
r = list(r, a)
|
r = list(r, a)
|
||||||
|
|
||||||
// (4)
|
// (4)
|
||||||
b := Nod(OIF, nil, nil)
|
b := Nod(OIF, nil, nil)
|
||||||
|
|
||||||
b.Ntest = Nod(OEQ, gatevar, Nodintconst(2))
|
b.Left = Nod(OEQ, gatevar, Nodintconst(2))
|
||||||
b.Nbody = list1(Nod(ORETURN, nil, nil))
|
b.Nbody = list1(Nod(ORETURN, nil, nil))
|
||||||
a.Nbody = list1(b)
|
a.Nbody = list1(b)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ func ishairy(n *Node, budget *int) bool {
|
||||||
|
|
||||||
(*budget)--
|
(*budget)--
|
||||||
|
|
||||||
return *budget < 0 || ishairy(n.Left, budget) || ishairy(n.Right, budget) || ishairylist(n.List, budget) || ishairylist(n.Rlist, budget) || ishairylist(n.Ninit, budget) || ishairy(n.Ntest, budget) || ishairylist(n.Nbody, budget)
|
return *budget < 0 || ishairy(n.Left, budget) || ishairy(n.Right, budget) || ishairylist(n.List, budget) || ishairylist(n.Rlist, budget) || ishairylist(n.Ninit, budget) || ishairylist(n.Nbody, budget)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inlcopy and inlcopylist recursively copy the body of a function.
|
// Inlcopy and inlcopylist recursively copy the body of a function.
|
||||||
|
|
@ -265,7 +265,6 @@ func inlcopy(n *Node) *Node {
|
||||||
m.List = inlcopylist(n.List)
|
m.List = inlcopylist(n.List)
|
||||||
m.Rlist = inlcopylist(n.Rlist)
|
m.Rlist = inlcopylist(n.Rlist)
|
||||||
m.Ninit = inlcopylist(n.Ninit)
|
m.Ninit = inlcopylist(n.Ninit)
|
||||||
m.Ntest = inlcopy(n.Ntest)
|
|
||||||
m.Nbody = inlcopylist(n.Nbody)
|
m.Nbody = inlcopylist(n.Nbody)
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
@ -434,11 +433,6 @@ func inlnode(np **Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inlnode(&n.Ntest)
|
|
||||||
if n.Ntest != nil && n.Ntest.Op == OINLCALL {
|
|
||||||
inlconv2expr(&n.Ntest)
|
|
||||||
}
|
|
||||||
|
|
||||||
inlnodelist(n.Nbody)
|
inlnodelist(n.Nbody)
|
||||||
for l := n.Nbody; l != nil; l = l.Next {
|
for l := n.Nbody; l != nil; l = l.Next {
|
||||||
if l.N.Op == OINLCALL {
|
if l.N.Op == OINLCALL {
|
||||||
|
|
@ -965,7 +959,6 @@ func inlsubst(n *Node) *Node {
|
||||||
m.List = inlsubstlist(n.List)
|
m.List = inlsubstlist(n.List)
|
||||||
m.Rlist = inlsubstlist(n.Rlist)
|
m.Rlist = inlsubstlist(n.Rlist)
|
||||||
m.Ninit = concat(m.Ninit, inlsubstlist(n.Ninit))
|
m.Ninit = concat(m.Ninit, inlsubstlist(n.Ninit))
|
||||||
m.Ntest = inlsubst(n.Ntest)
|
|
||||||
m.Nbody = inlsubstlist(n.Nbody)
|
m.Nbody = inlsubstlist(n.Nbody)
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
@ -993,6 +986,5 @@ func setlno(n *Node, lno int) {
|
||||||
setlnolist(n.List, lno)
|
setlnolist(n.List, lno)
|
||||||
setlnolist(n.Rlist, lno)
|
setlnolist(n.Rlist, lno)
|
||||||
setlnolist(n.Ninit, lno)
|
setlnolist(n.Ninit, lno)
|
||||||
setlno(n.Ntest, lno)
|
|
||||||
setlnolist(n.Nbody, lno)
|
setlnolist(n.Nbody, lno)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -646,7 +646,7 @@ func orderstmt(n *Node, order *Order) {
|
||||||
case OFOR:
|
case OFOR:
|
||||||
t := marktemp(order)
|
t := marktemp(order)
|
||||||
|
|
||||||
orderexprinplace(&n.Ntest, order)
|
orderexprinplace(&n.Left, order)
|
||||||
var l *NodeList
|
var l *NodeList
|
||||||
cleantempnopop(t, order, &l)
|
cleantempnopop(t, order, &l)
|
||||||
n.Nbody = concat(l, n.Nbody)
|
n.Nbody = concat(l, n.Nbody)
|
||||||
|
|
@ -660,7 +660,7 @@ func orderstmt(n *Node, order *Order) {
|
||||||
case OIF:
|
case OIF:
|
||||||
t := marktemp(order)
|
t := marktemp(order)
|
||||||
|
|
||||||
orderexprinplace(&n.Ntest, order)
|
orderexprinplace(&n.Left, order)
|
||||||
var l *NodeList
|
var l *NodeList
|
||||||
cleantempnopop(t, order, &l)
|
cleantempnopop(t, order, &l)
|
||||||
n.Nbody = concat(l, n.Nbody)
|
n.Nbody = concat(l, n.Nbody)
|
||||||
|
|
@ -793,7 +793,7 @@ func orderstmt(n *Node, order *Order) {
|
||||||
if t != nil && t.N.Op == ODCL && t.N.Left == r.Left {
|
if t != nil && t.N.Op == ODCL && t.N.Left == r.Left {
|
||||||
t = t.Next
|
t = t.Next
|
||||||
}
|
}
|
||||||
if t != nil && t.N.Op == ODCL && t.N.Left == r.Ntest {
|
if t != nil && t.N.Op == ODCL && r.List != nil && t.N.Left == r.List.N {
|
||||||
t = t.Next
|
t = t.Next
|
||||||
}
|
}
|
||||||
if t == nil {
|
if t == nil {
|
||||||
|
|
@ -844,19 +844,19 @@ func orderstmt(n *Node, order *Order) {
|
||||||
l.N.Ninit = list(l.N.Ninit, tmp2)
|
l.N.Ninit = list(l.N.Ninit, tmp2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Ntest != nil && isblank(r.Ntest) {
|
if r.List != nil && isblank(r.List.N) {
|
||||||
r.Ntest = nil
|
r.List = nil
|
||||||
}
|
}
|
||||||
if r.Ntest != nil {
|
if r.List != nil {
|
||||||
tmp1 = r.Ntest
|
tmp1 = r.List.N
|
||||||
if r.Colas {
|
if r.Colas {
|
||||||
tmp2 = Nod(ODCL, tmp1, nil)
|
tmp2 = Nod(ODCL, tmp1, nil)
|
||||||
typecheck(&tmp2, Etop)
|
typecheck(&tmp2, Etop)
|
||||||
l.N.Ninit = list(l.N.Ninit, tmp2)
|
l.N.Ninit = list(l.N.Ninit, tmp2)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Ntest = ordertemp(tmp1.Type, order, false)
|
r.List = list1(ordertemp(tmp1.Type, order, false))
|
||||||
tmp2 = Nod(OAS, tmp1, r.Ntest)
|
tmp2 = Nod(OAS, tmp1, r.List.N)
|
||||||
typecheck(&tmp2, Etop)
|
typecheck(&tmp2, Etop)
|
||||||
l.N.Ninit = list(l.N.Ninit, tmp2)
|
l.N.Ninit = list(l.N.Ninit, tmp2)
|
||||||
}
|
}
|
||||||
|
|
@ -918,7 +918,7 @@ func orderstmt(n *Node, order *Order) {
|
||||||
case OSWITCH:
|
case OSWITCH:
|
||||||
t := marktemp(order)
|
t := marktemp(order)
|
||||||
|
|
||||||
orderexpr(&n.Ntest, order, nil)
|
orderexpr(&n.Left, order, nil)
|
||||||
for l := n.List; l != nil; l = l.Next {
|
for l := n.List; l != nil; l = l.Next {
|
||||||
if l.N.Op != OXCASE {
|
if l.N.Op != OXCASE {
|
||||||
Fatal("order switch case %v", Oconv(int(l.N.Op), 0))
|
Fatal("order switch case %v", Oconv(int(l.N.Op), 0))
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,11 @@ func cmpstackvar(a *Node, b *Node) int {
|
||||||
return stringsCompare(a.Sym.Name, b.Sym.Name)
|
return stringsCompare(a.Sym.Name, b.Sym.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stkdelta records the stack offset delta for a node
|
||||||
|
// during the compaction of the stack frame to remove
|
||||||
|
// unused stack slots.
|
||||||
|
var stkdelta = map[*Node]int64{}
|
||||||
|
|
||||||
// TODO(lvd) find out where the PAUTO/OLITERAL nodes come from.
|
// TODO(lvd) find out where the PAUTO/OLITERAL nodes come from.
|
||||||
func allocauto(ptxt *obj.Prog) {
|
func allocauto(ptxt *obj.Prog) {
|
||||||
Stksize = 0
|
Stksize = 0
|
||||||
|
|
@ -283,7 +288,7 @@ func allocauto(ptxt *obj.Prog) {
|
||||||
Yyerror("stack frame too large (>2GB)")
|
Yyerror("stack frame too large (>2GB)")
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Stkdelta = -Stksize - n.Xoffset
|
stkdelta[n] = -Stksize - n.Xoffset
|
||||||
}
|
}
|
||||||
|
|
||||||
Stksize = Rnd(Stksize, int64(Widthreg))
|
Stksize = Rnd(Stksize, int64(Widthreg))
|
||||||
|
|
@ -296,8 +301,8 @@ func allocauto(ptxt *obj.Prog) {
|
||||||
if ll.N.Class != PAUTO || ll.N.Op != ONAME {
|
if ll.N.Class != PAUTO || ll.N.Op != ONAME {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ll.N.Xoffset += ll.N.Stkdelta
|
ll.N.Xoffset += stkdelta[ll.N]
|
||||||
ll.N.Stkdelta = 0
|
delete(stkdelta, ll.N)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -371,18 +371,25 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
|
||||||
Yyerror("racewalk: OGETG can happen only in runtime which we don't instrument")
|
Yyerror("racewalk: OGETG can happen only in runtime which we don't instrument")
|
||||||
goto ret
|
goto ret
|
||||||
|
|
||||||
// just do generic traversal
|
|
||||||
case OFOR:
|
case OFOR:
|
||||||
|
if n.Left != nil {
|
||||||
|
racewalknode(&n.Left, &n.Left.Ninit, 0, 0)
|
||||||
|
}
|
||||||
if n.Right != nil {
|
if n.Right != nil {
|
||||||
racewalknode(&n.Right, &n.Right.Ninit, 0, 0)
|
racewalknode(&n.Right, &n.Right.Ninit, 0, 0)
|
||||||
}
|
}
|
||||||
goto ret
|
goto ret
|
||||||
|
|
||||||
case OIF,
|
case OIF, OSWITCH:
|
||||||
OCALLMETH,
|
if n.Left != nil {
|
||||||
|
racewalknode(&n.Left, &n.Left.Ninit, 0, 0)
|
||||||
|
}
|
||||||
|
goto ret
|
||||||
|
|
||||||
|
// just do generic traversal
|
||||||
|
case OCALLMETH,
|
||||||
ORETURN,
|
ORETURN,
|
||||||
ORETJMP,
|
ORETJMP,
|
||||||
OSWITCH,
|
|
||||||
OSELECT,
|
OSELECT,
|
||||||
OEMPTY,
|
OEMPTY,
|
||||||
OBREAK,
|
OBREAK,
|
||||||
|
|
@ -415,9 +422,6 @@ ret:
|
||||||
if n.Op != OBLOCK { // OBLOCK is handled above in a special way.
|
if n.Op != OBLOCK { // OBLOCK is handled above in a special way.
|
||||||
racewalklist(n.List, init)
|
racewalklist(n.List, init)
|
||||||
}
|
}
|
||||||
if n.Ntest != nil {
|
|
||||||
racewalknode(&n.Ntest, &n.Ntest.Ninit, 0, 0)
|
|
||||||
}
|
|
||||||
racewalklist(n.Nbody, nil)
|
racewalklist(n.Nbody, nil)
|
||||||
racewalklist(n.Rlist, nil)
|
racewalklist(n.Rlist, nil)
|
||||||
*np = n
|
*np = n
|
||||||
|
|
@ -577,7 +581,6 @@ func foreach(n *Node, f func(*Node, interface{}), c interface{}) {
|
||||||
foreachnode(n.Left, f, c)
|
foreachnode(n.Left, f, c)
|
||||||
foreachnode(n.Right, f, c)
|
foreachnode(n.Right, f, c)
|
||||||
foreachlist(n.List, f, c)
|
foreachlist(n.List, f, c)
|
||||||
foreachnode(n.Ntest, f, c)
|
|
||||||
foreachlist(n.Nbody, f, c)
|
foreachlist(n.Nbody, f, c)
|
||||||
foreachlist(n.Rlist, f, c)
|
foreachlist(n.Rlist, f, c)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ func walkrange(n *Node) {
|
||||||
n.Op = OIF
|
n.Op = OIF
|
||||||
|
|
||||||
n.Nbody = nil
|
n.Nbody = nil
|
||||||
n.Ntest = Nod(ONE, Nod(OLEN, a, nil), Nodintconst(0))
|
n.Left = Nod(ONE, Nod(OLEN, a, nil), Nodintconst(0))
|
||||||
|
|
||||||
// hp = &a[0]
|
// hp = &a[0]
|
||||||
hp := temp(Ptrto(Types[TUINT8]))
|
hp := temp(Ptrto(Types[TUINT8]))
|
||||||
|
|
@ -231,7 +231,7 @@ func walkrange(n *Node) {
|
||||||
|
|
||||||
n.Nbody = list(n.Nbody, v1)
|
n.Nbody = list(n.Nbody, v1)
|
||||||
|
|
||||||
typecheck(&n.Ntest, Erv)
|
typecheck(&n.Left, Erv)
|
||||||
typechecklist(n.Nbody, Etop)
|
typechecklist(n.Nbody, Etop)
|
||||||
walkstmt(&n)
|
walkstmt(&n)
|
||||||
lineno = int32(lno)
|
lineno = int32(lno)
|
||||||
|
|
@ -266,7 +266,7 @@ func walkrange(n *Node) {
|
||||||
init = list(init, Nod(OAS, hp, Nod(OADDR, tmp, nil)))
|
init = list(init, Nod(OAS, hp, Nod(OADDR, tmp, nil)))
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Ntest = Nod(OLT, hv1, hn)
|
n.Left = Nod(OLT, hv1, hn)
|
||||||
n.Right = Nod(OAS, hv1, Nod(OADD, hv1, Nodintconst(1)))
|
n.Right = Nod(OAS, hv1, Nod(OADD, hv1, Nodintconst(1)))
|
||||||
if v1 == nil {
|
if v1 == nil {
|
||||||
body = nil
|
body = nil
|
||||||
|
|
@ -313,7 +313,7 @@ func walkrange(n *Node) {
|
||||||
|
|
||||||
substArgTypes(fn, t.Down, t.Type, th)
|
substArgTypes(fn, t.Down, t.Type, th)
|
||||||
init = list(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
|
init = list(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
|
||||||
n.Ntest = Nod(ONE, Nod(ODOT, hit, keyname), nodnil())
|
n.Left = Nod(ONE, Nod(ODOT, hit, keyname), nodnil())
|
||||||
|
|
||||||
fn = syslook("mapiternext", 1)
|
fn = syslook("mapiternext", 1)
|
||||||
substArgTypes(fn, th)
|
substArgTypes(fn, th)
|
||||||
|
|
@ -338,7 +338,7 @@ func walkrange(n *Node) {
|
||||||
case TCHAN:
|
case TCHAN:
|
||||||
ha := a
|
ha := a
|
||||||
|
|
||||||
n.Ntest = nil
|
n.Left = nil
|
||||||
|
|
||||||
hv1 := temp(t.Type)
|
hv1 := temp(t.Type)
|
||||||
hv1.Typecheck = 1
|
hv1.Typecheck = 1
|
||||||
|
|
@ -347,12 +347,12 @@ func walkrange(n *Node) {
|
||||||
}
|
}
|
||||||
hb := temp(Types[TBOOL])
|
hb := temp(Types[TBOOL])
|
||||||
|
|
||||||
n.Ntest = Nod(ONE, hb, Nodbool(false))
|
n.Left = Nod(ONE, hb, Nodbool(false))
|
||||||
a := Nod(OAS2RECV, nil, nil)
|
a := Nod(OAS2RECV, nil, nil)
|
||||||
a.Typecheck = 1
|
a.Typecheck = 1
|
||||||
a.List = list(list1(hv1), hb)
|
a.List = list(list1(hv1), hb)
|
||||||
a.Rlist = list1(Nod(ORECV, ha, nil))
|
a.Rlist = list1(Nod(ORECV, ha, nil))
|
||||||
n.Ntest.Ninit = list1(a)
|
n.Left.Ninit = list1(a)
|
||||||
if v1 == nil {
|
if v1 == nil {
|
||||||
body = nil
|
body = nil
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -380,8 +380,8 @@ func walkrange(n *Node) {
|
||||||
a.Rlist = list1(mkcall1(fn, getoutargx(fn.Type), nil, ha, hv1))
|
a.Rlist = list1(mkcall1(fn, getoutargx(fn.Type), nil, ha, hv1))
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Ntest = Nod(ONE, hv1, Nodintconst(0))
|
n.Left = Nod(ONE, hv1, Nodintconst(0))
|
||||||
n.Ntest.Ninit = list(list1(Nod(OAS, ohv1, hv1)), a)
|
n.Left.Ninit = list(list1(Nod(OAS, ohv1, hv1)), a)
|
||||||
|
|
||||||
body = nil
|
body = nil
|
||||||
if v1 != nil {
|
if v1 != nil {
|
||||||
|
|
@ -395,8 +395,8 @@ func walkrange(n *Node) {
|
||||||
n.Op = OFOR
|
n.Op = OFOR
|
||||||
typechecklist(init, Etop)
|
typechecklist(init, Etop)
|
||||||
n.Ninit = concat(n.Ninit, init)
|
n.Ninit = concat(n.Ninit, init)
|
||||||
typechecklist(n.Ntest.Ninit, Etop)
|
typechecklist(n.Left.Ninit, Etop)
|
||||||
typecheck(&n.Ntest, Erv)
|
typecheck(&n.Left, Erv)
|
||||||
typecheck(&n.Right, Etop)
|
typecheck(&n.Right, Etop)
|
||||||
typechecklist(body, Etop)
|
typechecklist(body, Etop)
|
||||||
n.Nbody = concat(body, n.Nbody)
|
n.Nbody = concat(body, n.Nbody)
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,7 @@ func typecheckselect(sel *Node) {
|
||||||
|
|
||||||
n.Op = OSELRECV2
|
n.Op = OSELRECV2
|
||||||
n.Left = n.List.N
|
n.Left = n.List.N
|
||||||
n.Ntest = n.List.Next.N
|
n.List = list1(n.List.Next.N)
|
||||||
n.List = nil
|
|
||||||
n.Right = n.Rlist.N
|
n.Right = n.Rlist.N
|
||||||
n.Rlist = nil
|
n.Rlist = nil
|
||||||
|
|
||||||
|
|
@ -131,7 +130,7 @@ func walkselect(sel *Node) {
|
||||||
|
|
||||||
case OSELRECV, OSELRECV2:
|
case OSELRECV, OSELRECV2:
|
||||||
ch = n.Right.Left
|
ch = n.Right.Left
|
||||||
if n.Op == OSELRECV || n.Ntest == nil {
|
if n.Op == OSELRECV || n.List == nil {
|
||||||
if n.Left == nil {
|
if n.Left == nil {
|
||||||
n = n.Right
|
n = n.Right
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -146,11 +145,10 @@ func walkselect(sel *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Op = OAS2
|
n.Op = OAS2
|
||||||
n.List = list(list1(n.Left), n.Ntest)
|
n.List = concat(list1(n.Left), n.List)
|
||||||
n.Rlist = list1(n.Right)
|
n.Rlist = list1(n.Right)
|
||||||
n.Right = nil
|
n.Right = nil
|
||||||
n.Left = nil
|
n.Left = nil
|
||||||
n.Ntest = nil
|
|
||||||
n.Typecheck = 0
|
n.Typecheck = 0
|
||||||
typecheck(&n, Etop)
|
typecheck(&n, Etop)
|
||||||
}
|
}
|
||||||
|
|
@ -158,7 +156,7 @@ func walkselect(sel *Node) {
|
||||||
// if ch == nil { block() }; n;
|
// if ch == nil { block() }; n;
|
||||||
a := Nod(OIF, nil, nil)
|
a := Nod(OIF, nil, nil)
|
||||||
|
|
||||||
a.Ntest = Nod(OEQ, ch, nodnil())
|
a.Left = Nod(OEQ, ch, nodnil())
|
||||||
a.Nbody = list1(mkcall("block", nil, &l))
|
a.Nbody = list1(mkcall("block", nil, &l))
|
||||||
typecheck(&a, Etop)
|
typecheck(&a, Etop)
|
||||||
l = list(l, a)
|
l = list(l, a)
|
||||||
|
|
@ -185,12 +183,12 @@ func walkselect(sel *Node) {
|
||||||
typecheck(&n.Right, Erv)
|
typecheck(&n.Right, Erv)
|
||||||
|
|
||||||
case OSELRECV, OSELRECV2:
|
case OSELRECV, OSELRECV2:
|
||||||
if n.Op == OSELRECV2 && n.Ntest == nil {
|
if n.Op == OSELRECV2 && n.List == nil {
|
||||||
n.Op = OSELRECV
|
n.Op = OSELRECV
|
||||||
}
|
}
|
||||||
if n.Op == OSELRECV2 {
|
if n.Op == OSELRECV2 {
|
||||||
n.Ntest = Nod(OADDR, n.Ntest, nil)
|
n.List.N = Nod(OADDR, n.List.N, nil)
|
||||||
typecheck(&n.Ntest, Erv)
|
typecheck(&n.List.N, Erv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Left == nil {
|
if n.Left == nil {
|
||||||
|
|
@ -226,7 +224,7 @@ func walkselect(sel *Node) {
|
||||||
case OSEND:
|
case OSEND:
|
||||||
ch := n.Left
|
ch := n.Left
|
||||||
|
|
||||||
r.Ntest = mkcall1(chanfn("selectnbsend", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), ch, n.Right)
|
r.Left = mkcall1(chanfn("selectnbsend", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), ch, n.Right)
|
||||||
|
|
||||||
// if c != nil && selectnbrecv(&v, c) { body } else { default body }
|
// if c != nil && selectnbrecv(&v, c) { body } else { default body }
|
||||||
case OSELRECV:
|
case OSELRECV:
|
||||||
|
|
@ -234,7 +232,7 @@ func walkselect(sel *Node) {
|
||||||
|
|
||||||
r.Ninit = cas.Ninit
|
r.Ninit = cas.Ninit
|
||||||
ch := n.Right.Left
|
ch := n.Right.Left
|
||||||
r.Ntest = mkcall1(chanfn("selectnbrecv", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, ch)
|
r.Left = mkcall1(chanfn("selectnbrecv", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, ch)
|
||||||
|
|
||||||
// if c != nil && selectnbrecv2(&v, c) { body } else { default body }
|
// if c != nil && selectnbrecv2(&v, c) { body } else { default body }
|
||||||
case OSELRECV2:
|
case OSELRECV2:
|
||||||
|
|
@ -242,10 +240,10 @@ func walkselect(sel *Node) {
|
||||||
|
|
||||||
r.Ninit = cas.Ninit
|
r.Ninit = cas.Ninit
|
||||||
ch := n.Right.Left
|
ch := n.Right.Left
|
||||||
r.Ntest = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, n.Ntest, ch)
|
r.Left = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, n.List.N, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
typecheck(&r.Ntest, Erv)
|
typecheck(&r.Left, Erv)
|
||||||
r.Nbody = cas.Nbody
|
r.Nbody = cas.Nbody
|
||||||
r.Rlist = concat(dflt.Ninit, dflt.Nbody)
|
r.Rlist = concat(dflt.Ninit, dflt.Nbody)
|
||||||
sel.Nbody = list1(r)
|
sel.Nbody = list1(r)
|
||||||
|
|
@ -282,7 +280,7 @@ func walkselect(sel *Node) {
|
||||||
|
|
||||||
if n == nil {
|
if n == nil {
|
||||||
// selectdefault(sel *byte);
|
// selectdefault(sel *byte);
|
||||||
r.Ntest = mkcall("selectdefault", Types[TBOOL], &r.Ninit, var_)
|
r.Left = mkcall("selectdefault", Types[TBOOL], &r.Ninit, var_)
|
||||||
} else {
|
} else {
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
default:
|
default:
|
||||||
|
|
@ -290,15 +288,15 @@ func walkselect(sel *Node) {
|
||||||
|
|
||||||
// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
|
// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
|
||||||
case OSEND:
|
case OSEND:
|
||||||
r.Ntest = mkcall1(chanfn("selectsend", 2, n.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Left, n.Right)
|
r.Left = mkcall1(chanfn("selectsend", 2, n.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Left, n.Right)
|
||||||
|
|
||||||
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
||||||
case OSELRECV:
|
case OSELRECV:
|
||||||
r.Ntest = mkcall1(chanfn("selectrecv", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left)
|
r.Left = mkcall1(chanfn("selectrecv", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left)
|
||||||
|
|
||||||
// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
|
// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
|
||||||
case OSELRECV2:
|
case OSELRECV2:
|
||||||
r.Ntest = mkcall1(chanfn("selectrecv2", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left, n.Ntest)
|
r.Left = mkcall1(chanfn("selectrecv2", 2, n.Right.Left.Type), Types[TBOOL], &r.Ninit, var_, n.Right.Left, n.Left, n.List.N)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,6 @@ func init2(n *Node, out **NodeList) {
|
||||||
init1(n, out)
|
init1(n, out)
|
||||||
init2(n.Left, out)
|
init2(n.Left, out)
|
||||||
init2(n.Right, out)
|
init2(n.Right, out)
|
||||||
init2(n.Ntest, out)
|
|
||||||
init2list(n.Ninit, out)
|
init2list(n.Ninit, out)
|
||||||
init2list(n.List, out)
|
init2list(n.List, out)
|
||||||
init2list(n.Rlist, out)
|
init2list(n.Rlist, out)
|
||||||
|
|
@ -996,7 +995,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
|
||||||
a.Nbody = list1(r)
|
a.Nbody = list1(r)
|
||||||
|
|
||||||
a.Ninit = list1(Nod(OAS, index, Nodintconst(0)))
|
a.Ninit = list1(Nod(OAS, index, Nodintconst(0)))
|
||||||
a.Ntest = Nod(OLT, index, Nodintconst(t.Bound))
|
a.Left = Nod(OLT, index, Nodintconst(t.Bound))
|
||||||
a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
|
a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
|
||||||
|
|
||||||
typecheck(&a, Etop)
|
typecheck(&a, Etop)
|
||||||
|
|
@ -1221,6 +1220,7 @@ func oaslit(n *Node, init **NodeList) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Op = OEMPTY
|
n.Op = OEMPTY
|
||||||
|
n.Right = nil
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2421,7 +2421,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
|
||||||
// generating wrapper from *T to T.
|
// generating wrapper from *T to T.
|
||||||
n := Nod(OIF, nil, nil)
|
n := Nod(OIF, nil, nil)
|
||||||
|
|
||||||
n.Ntest = Nod(OEQ, this.Left, nodnil())
|
n.Left = Nod(OEQ, this.Left, nodnil())
|
||||||
|
|
||||||
// these strings are already in the reflect tables,
|
// these strings are already in the reflect tables,
|
||||||
// so no space cost to use them here.
|
// so no space cost to use them here.
|
||||||
|
|
@ -2757,7 +2757,7 @@ func eqfield(p *Node, q *Node, field *Node) *Node {
|
||||||
nx := Nod(OXDOT, p, field)
|
nx := Nod(OXDOT, p, field)
|
||||||
ny := Nod(OXDOT, q, field)
|
ny := Nod(OXDOT, q, field)
|
||||||
nif := Nod(OIF, nil, nil)
|
nif := Nod(OIF, nil, nil)
|
||||||
nif.Ntest = Nod(ONE, nx, ny)
|
nif.Left = Nod(ONE, nx, ny)
|
||||||
r := Nod(ORETURN, nil, nil)
|
r := Nod(ORETURN, nil, nil)
|
||||||
r.List = list(r.List, Nodbool(false))
|
r.List = list(r.List, Nodbool(false))
|
||||||
nif.Nbody = list(nif.Nbody, r)
|
nif.Nbody = list(nif.Nbody, r)
|
||||||
|
|
@ -2802,7 +2802,7 @@ func eqmem(p *Node, q *Node, field *Node, size int64) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
nif := Nod(OIF, nil, nil)
|
nif := Nod(OIF, nil, nil)
|
||||||
nif.Ntest = Nod(ONOT, call, nil)
|
nif.Left = Nod(ONOT, call, nil)
|
||||||
r := Nod(ORETURN, nil, nil)
|
r := Nod(ORETURN, nil, nil)
|
||||||
r.List = list(r.List, Nodbool(false))
|
r.List = list(r.List, Nodbool(false))
|
||||||
nif.Nbody = list(nif.Nbody, r)
|
nif.Nbody = list(nif.Nbody, r)
|
||||||
|
|
@ -2874,7 +2874,7 @@ func geneq(sym *Sym, t *Type) {
|
||||||
ny.Bounded = true
|
ny.Bounded = true
|
||||||
|
|
||||||
nif := Nod(OIF, nil, nil)
|
nif := Nod(OIF, nil, nil)
|
||||||
nif.Ntest = Nod(ONE, nx, ny)
|
nif.Left = Nod(ONE, nx, ny)
|
||||||
r := Nod(ORETURN, nil, nil)
|
r := Nod(ORETURN, nil, nil)
|
||||||
r.List = list(r.List, Nodbool(false))
|
r.List = list(r.List, Nodbool(false))
|
||||||
nif.Nbody = list(nif.Nbody, r)
|
nif.Nbody = list(nif.Nbody, r)
|
||||||
|
|
|
||||||
|
|
@ -66,21 +66,21 @@ func typecheckswitch(n *Node) {
|
||||||
var top int
|
var top int
|
||||||
var t *Type
|
var t *Type
|
||||||
|
|
||||||
if n.Ntest != nil && n.Ntest.Op == OTYPESW {
|
if n.Left != nil && n.Left.Op == OTYPESW {
|
||||||
// type switch
|
// type switch
|
||||||
top = Etype
|
top = Etype
|
||||||
typecheck(&n.Ntest.Right, Erv)
|
typecheck(&n.Left.Right, Erv)
|
||||||
t = n.Ntest.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.Ntest.Right, obj.FmtLong))
|
Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, obj.FmtLong))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// expression switch
|
// expression switch
|
||||||
top = Erv
|
top = Erv
|
||||||
if n.Ntest != nil {
|
if n.Left != nil {
|
||||||
typecheck(&n.Ntest, Erv)
|
typecheck(&n.Left, Erv)
|
||||||
defaultlit(&n.Ntest, nil)
|
defaultlit(&n.Left, nil)
|
||||||
t = n.Ntest.Type
|
t = n.Left.Type
|
||||||
} else {
|
} else {
|
||||||
t = Types[TBOOL]
|
t = Types[TBOOL]
|
||||||
}
|
}
|
||||||
|
|
@ -88,13 +88,13 @@ func typecheckswitch(n *Node) {
|
||||||
var badtype *Type
|
var badtype *Type
|
||||||
switch {
|
switch {
|
||||||
case !okforeq[t.Etype]:
|
case !okforeq[t.Etype]:
|
||||||
Yyerror("cannot switch on %v", Nconv(n.Ntest, obj.FmtLong))
|
Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong))
|
||||||
case t.Etype == TARRAY && !Isfixedarray(t):
|
case t.Etype == TARRAY && !Isfixedarray(t):
|
||||||
nilonly = "slice"
|
nilonly = "slice"
|
||||||
case t.Etype == TARRAY && Isfixedarray(t) && algtype1(t, nil) == ANOEQ:
|
case t.Etype == TARRAY && Isfixedarray(t) && algtype1(t, nil) == ANOEQ:
|
||||||
Yyerror("cannot switch on %v", Nconv(n.Ntest, obj.FmtLong))
|
Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong))
|
||||||
case t.Etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ:
|
case t.Etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ:
|
||||||
Yyerror("cannot switch on %v (struct containing %v cannot be compared)", Nconv(n.Ntest, obj.FmtLong), badtype)
|
Yyerror("cannot switch on %v (struct containing %v cannot be compared)", Nconv(n.Left, obj.FmtLong), badtype)
|
||||||
case t.Etype == TFUNC:
|
case t.Etype == TFUNC:
|
||||||
nilonly = "func"
|
nilonly = "func"
|
||||||
case t.Etype == TMAP:
|
case t.Etype == TMAP:
|
||||||
|
|
@ -133,13 +133,13 @@ func typecheckswitch(n *Node) {
|
||||||
case ll.N.Op == OTYPE:
|
case ll.N.Op == OTYPE:
|
||||||
Yyerror("type %v is not an expression", ll.N.Type)
|
Yyerror("type %v is not an expression", ll.N.Type)
|
||||||
case ll.N.Type != nil && assignop(ll.N.Type, t, nil) == 0 && assignop(t, ll.N.Type, nil) == 0:
|
case ll.N.Type != nil && assignop(ll.N.Type, t, nil) == 0 && assignop(t, ll.N.Type, nil) == 0:
|
||||||
if n.Ntest != nil {
|
if n.Left != nil {
|
||||||
Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ll.N, n.Ntest, ll.N.Type, t)
|
Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ll.N, n.Left, ll.N.Type, t)
|
||||||
} else {
|
} else {
|
||||||
Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type)
|
Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type)
|
||||||
}
|
}
|
||||||
case nilonly != "" && !Isconst(ll.N, CTNIL):
|
case nilonly != "" && !Isconst(ll.N, CTNIL):
|
||||||
Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Ntest)
|
Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Left)
|
||||||
}
|
}
|
||||||
|
|
||||||
// type switch
|
// type switch
|
||||||
|
|
@ -151,12 +151,12 @@ func typecheckswitch(n *Node) {
|
||||||
case ll.N.Op != OTYPE && ll.N.Type != nil: // should this be ||?
|
case ll.N.Op != OTYPE && ll.N.Type != nil: // should this be ||?
|
||||||
Yyerror("%v is not a type", Nconv(ll.N, obj.FmtLong))
|
Yyerror("%v is not a type", Nconv(ll.N, obj.FmtLong))
|
||||||
// reset to original type
|
// reset to original type
|
||||||
ll.N = n.Ntest.Right
|
ll.N = n.Left.Right
|
||||||
case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr):
|
case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr):
|
||||||
if have != nil && missing.Broke == 0 && have.Broke == 0 {
|
if have != nil && missing.Broke == 0 && have.Broke == 0 {
|
||||||
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Ntest.Right, obj.FmtLong), ll.N.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
|
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
|
||||||
} else if missing.Broke == 0 {
|
} else if missing.Broke == 0 {
|
||||||
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Ntest.Right, obj.FmtLong), ll.N.Type, missing.Sym)
|
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -189,22 +189,18 @@ func typecheckswitch(n *Node) {
|
||||||
// walkswitch walks a switch statement.
|
// walkswitch walks a switch statement.
|
||||||
func walkswitch(sw *Node) {
|
func walkswitch(sw *Node) {
|
||||||
// convert switch {...} to switch true {...}
|
// convert switch {...} to switch true {...}
|
||||||
if sw.Ntest == nil {
|
if sw.Left == nil {
|
||||||
sw.Ntest = Nodbool(true)
|
sw.Left = Nodbool(true)
|
||||||
typecheck(&sw.Ntest, Erv)
|
typecheck(&sw.Left, Erv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sw.Ntest.Op == OTYPESW {
|
if sw.Left.Op == OTYPESW {
|
||||||
var s typeSwitch
|
var s typeSwitch
|
||||||
s.walk(sw)
|
s.walk(sw)
|
||||||
} else {
|
} else {
|
||||||
var s exprSwitch
|
var s exprSwitch
|
||||||
s.walk(sw)
|
s.walk(sw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard old AST elements. They can confuse racewalk.
|
|
||||||
sw.Ntest = nil
|
|
||||||
sw.List = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk generates an AST implementing sw.
|
// walk generates an AST implementing sw.
|
||||||
|
|
@ -215,15 +211,18 @@ func walkswitch(sw *Node) {
|
||||||
func (s *exprSwitch) walk(sw *Node) {
|
func (s *exprSwitch) walk(sw *Node) {
|
||||||
casebody(sw, nil)
|
casebody(sw, nil)
|
||||||
|
|
||||||
|
cond := sw.Left
|
||||||
|
sw.Left = nil
|
||||||
|
|
||||||
s.kind = switchKindExpr
|
s.kind = switchKindExpr
|
||||||
if Isconst(sw.Ntest, CTBOOL) {
|
if Isconst(cond, CTBOOL) {
|
||||||
s.kind = switchKindTrue
|
s.kind = switchKindTrue
|
||||||
if !sw.Ntest.Val.U.(bool) {
|
if !cond.Val.U.(bool) {
|
||||||
s.kind = switchKindFalse
|
s.kind = switchKindFalse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
walkexpr(&sw.Ntest, &sw.Ninit)
|
walkexpr(&cond, &sw.Ninit)
|
||||||
t := sw.Type
|
t := sw.Type
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return
|
return
|
||||||
|
|
@ -233,17 +232,18 @@ func (s *exprSwitch) walk(sw *Node) {
|
||||||
var cas *NodeList
|
var cas *NodeList
|
||||||
if s.kind == switchKindTrue || s.kind == switchKindFalse {
|
if s.kind == switchKindTrue || s.kind == switchKindFalse {
|
||||||
s.exprname = Nodbool(s.kind == switchKindTrue)
|
s.exprname = Nodbool(s.kind == switchKindTrue)
|
||||||
} else if consttype(sw.Ntest) >= 0 {
|
} else if consttype(cond) >= 0 {
|
||||||
// leave constants to enable dead code elimination (issue 9608)
|
// leave constants to enable dead code elimination (issue 9608)
|
||||||
s.exprname = sw.Ntest
|
s.exprname = cond
|
||||||
} else {
|
} else {
|
||||||
s.exprname = temp(sw.Ntest.Type)
|
s.exprname = temp(cond.Type)
|
||||||
cas = list1(Nod(OAS, s.exprname, sw.Ntest))
|
cas = list1(Nod(OAS, s.exprname, cond))
|
||||||
typechecklist(cas, Etop)
|
typechecklist(cas, Etop)
|
||||||
}
|
}
|
||||||
|
|
||||||
// enumerate the cases, and lop off the default case
|
// enumerate the cases, and lop off the default case
|
||||||
cc := caseClauses(sw, s.kind)
|
cc := caseClauses(sw, s.kind)
|
||||||
|
sw.List = nil
|
||||||
var def *Node
|
var def *Node
|
||||||
if len(cc) > 0 && cc[0].typ == caseKindDefault {
|
if len(cc) > 0 && cc[0].typ == caseKindDefault {
|
||||||
def = cc[0].node.Right
|
def = cc[0].node.Right
|
||||||
|
|
@ -278,9 +278,9 @@ func (s *exprSwitch) walk(sw *Node) {
|
||||||
if nerrors == 0 {
|
if nerrors == 0 {
|
||||||
cas = list(cas, def)
|
cas = list(cas, def)
|
||||||
sw.Nbody = concat(cas, sw.Nbody)
|
sw.Nbody = concat(cas, sw.Nbody)
|
||||||
sw.List = nil
|
|
||||||
walkstmtlist(sw.Nbody)
|
walkstmtlist(sw.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// walkCases generates an AST implementing the cases in cc.
|
// walkCases generates an AST implementing the cases in cc.
|
||||||
|
|
@ -294,14 +294,14 @@ 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.Ntest = Nod(OEQ, s.exprname, n.Left) // if name == val
|
a.Left = Nod(OEQ, s.exprname, n.Left) // if name == val
|
||||||
typecheck(&a.Ntest, Erv)
|
typecheck(&a.Left, Erv)
|
||||||
} else if s.kind == switchKindTrue {
|
} else if s.kind == switchKindTrue {
|
||||||
a.Ntest = n.Left // if val
|
a.Left = n.Left // if val
|
||||||
} else {
|
} else {
|
||||||
// s.kind == switchKindFalse
|
// s.kind == switchKindFalse
|
||||||
a.Ntest = Nod(ONOT, n.Left, nil) // if !val
|
a.Left = Nod(ONOT, n.Left, nil) // if !val
|
||||||
typecheck(&a.Ntest, Erv)
|
typecheck(&a.Left, Erv)
|
||||||
}
|
}
|
||||||
a.Nbody = list1(n.Right) // goto l
|
a.Nbody = list1(n.Right) // goto l
|
||||||
|
|
||||||
|
|
@ -320,11 +320,11 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
|
||||||
// Search by length and then by value; see exprcmp.
|
// Search by length and then by value; see exprcmp.
|
||||||
lenlt := Nod(OLT, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
|
lenlt := Nod(OLT, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
|
||||||
leneq := Nod(OEQ, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
|
leneq := Nod(OEQ, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
|
||||||
a.Ntest = Nod(OOROR, lenlt, Nod(OANDAND, leneq, le))
|
a.Left = Nod(OOROR, lenlt, Nod(OANDAND, leneq, le))
|
||||||
} else {
|
} else {
|
||||||
a.Ntest = le
|
a.Left = le
|
||||||
}
|
}
|
||||||
typecheck(&a.Ntest, Erv)
|
typecheck(&a.Left, Erv)
|
||||||
a.Nbody = list1(s.walkCases(cc[:half]))
|
a.Nbody = list1(s.walkCases(cc[:half]))
|
||||||
a.Rlist = list1(s.walkCases(cc[half:]))
|
a.Rlist = list1(s.walkCases(cc[half:]))
|
||||||
return a
|
return a
|
||||||
|
|
@ -512,17 +512,21 @@ func caseClauses(sw *Node, kind int) []*caseClause {
|
||||||
// search using if..goto, although binary search
|
// search using if..goto, although binary search
|
||||||
// is used with long runs of concrete types.
|
// is used with long runs of concrete types.
|
||||||
func (s *typeSwitch) walk(sw *Node) {
|
func (s *typeSwitch) walk(sw *Node) {
|
||||||
if sw.Ntest == nil {
|
cond := sw.Left
|
||||||
|
sw.Left = nil
|
||||||
|
|
||||||
|
if cond == nil {
|
||||||
|
sw.List = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sw.Ntest.Right == nil {
|
if cond.Right == nil {
|
||||||
setlineno(sw)
|
setlineno(sw)
|
||||||
Yyerror("type switch must have an assignment")
|
Yyerror("type switch must have an assignment")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
walkexpr(&sw.Ntest.Right, &sw.Ninit)
|
walkexpr(&cond.Right, &sw.Ninit)
|
||||||
if !Istype(sw.Ntest.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
|
||||||
}
|
}
|
||||||
|
|
@ -530,9 +534,9 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
var cas *NodeList
|
var cas *NodeList
|
||||||
|
|
||||||
// predeclare temporary variables and the boolean var
|
// predeclare temporary variables and the boolean var
|
||||||
s.facename = temp(sw.Ntest.Right.Type)
|
s.facename = temp(cond.Right.Type)
|
||||||
|
|
||||||
a := Nod(OAS, s.facename, sw.Ntest.Right)
|
a := Nod(OAS, s.facename, cond.Right)
|
||||||
typecheck(&a, Etop)
|
typecheck(&a, Etop)
|
||||||
cas = list(cas, a)
|
cas = list(cas, a)
|
||||||
|
|
||||||
|
|
@ -546,7 +550,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
casebody(sw, s.facename)
|
casebody(sw, s.facename)
|
||||||
|
|
||||||
// calculate type hash
|
// calculate type hash
|
||||||
t := sw.Ntest.Right.Type
|
t := cond.Right.Type
|
||||||
if isnilinter(t) {
|
if isnilinter(t) {
|
||||||
a = syslook("efacethash", 1)
|
a = syslook("efacethash", 1)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -560,6 +564,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
cas = list(cas, a)
|
cas = list(cas, a)
|
||||||
|
|
||||||
cc := caseClauses(sw, switchKindType)
|
cc := caseClauses(sw, switchKindType)
|
||||||
|
sw.List = nil
|
||||||
var def *Node
|
var def *Node
|
||||||
if len(cc) > 0 && cc[0].typ == caseKindDefault {
|
if len(cc) > 0 && cc[0].typ == caseKindDefault {
|
||||||
def = cc[0].node.Right
|
def = cc[0].node.Right
|
||||||
|
|
@ -576,8 +581,8 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
var v Val
|
var v Val
|
||||||
v.Ctype = CTNIL
|
v.Ctype = CTNIL
|
||||||
a = Nod(OIF, nil, nil)
|
a = Nod(OIF, nil, nil)
|
||||||
a.Ntest = Nod(OEQ, s.facename, nodlit(v))
|
a.Left = Nod(OEQ, s.facename, nodlit(v))
|
||||||
typecheck(&a.Ntest, Erv)
|
typecheck(&a.Left, Erv)
|
||||||
a.Nbody = list1(n.Right) // if i==nil { goto l }
|
a.Nbody = list1(n.Right) // if i==nil { goto l }
|
||||||
n.Right = a
|
n.Right = a
|
||||||
|
|
||||||
|
|
@ -658,7 +663,7 @@ func (s *typeSwitch) typeone(t *Node) *Node {
|
||||||
init = list(init, a)
|
init = list(init, a)
|
||||||
|
|
||||||
c := Nod(OIF, nil, nil)
|
c := Nod(OIF, nil, nil)
|
||||||
c.Ntest = s.okname
|
c.Left = s.okname
|
||||||
c.Nbody = list1(t.Right) // if ok { goto l }
|
c.Nbody = list1(t.Right) // if ok { goto l }
|
||||||
|
|
||||||
return liststmt(list(init, c))
|
return liststmt(list(init, c))
|
||||||
|
|
@ -674,8 +679,8 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
|
||||||
Fatal("typeSwitch walkCases")
|
Fatal("typeSwitch walkCases")
|
||||||
}
|
}
|
||||||
a := Nod(OIF, nil, nil)
|
a := Nod(OIF, nil, nil)
|
||||||
a.Ntest = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash)))
|
a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash)))
|
||||||
typecheck(&a.Ntest, Erv)
|
typecheck(&a.Left, Erv)
|
||||||
a.Nbody = list1(n.Right)
|
a.Nbody = list1(n.Right)
|
||||||
cas = list(cas, a)
|
cas = list(cas, a)
|
||||||
}
|
}
|
||||||
|
|
@ -685,8 +690,8 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
|
||||||
// find the middle and recur
|
// find the middle and recur
|
||||||
half := len(cc) / 2
|
half := len(cc) / 2
|
||||||
a := Nod(OIF, nil, nil)
|
a := Nod(OIF, nil, nil)
|
||||||
a.Ntest = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
|
a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
|
||||||
typecheck(&a.Ntest, Erv)
|
typecheck(&a.Left, Erv)
|
||||||
a.Nbody = list1(s.walkCases(cc[:half]))
|
a.Nbody = list1(s.walkCases(cc[:half]))
|
||||||
a.Rlist = list1(s.walkCases(cc[half:]))
|
a.Rlist = list1(s.walkCases(cc[half:]))
|
||||||
return a
|
return a
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ type Node struct {
|
||||||
// Generic recursive walks should follow these fields.
|
// Generic recursive walks should follow these fields.
|
||||||
Left *Node
|
Left *Node
|
||||||
Right *Node
|
Right *Node
|
||||||
Ntest *Node
|
|
||||||
Ninit *NodeList
|
Ninit *NodeList
|
||||||
Nbody *NodeList
|
Nbody *NodeList
|
||||||
List *NodeList
|
List *NodeList
|
||||||
|
|
@ -54,8 +53,7 @@ type Node struct {
|
||||||
// OLITERAL
|
// OLITERAL
|
||||||
Val Val
|
Val Val
|
||||||
|
|
||||||
Xoffset int64
|
Xoffset int64
|
||||||
Stkdelta int64 // offset added by stack frame compaction phase.
|
|
||||||
|
|
||||||
// Escape analysis.
|
// Escape analysis.
|
||||||
Escloopdepth int32 // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
|
Escloopdepth int32 // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ func callrecv(n *Node) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return callrecv(n.Left) || callrecv(n.Right) || callrecv(n.Ntest) || callrecvlist(n.Ninit) || callrecvlist(n.Nbody) || callrecvlist(n.List) || callrecvlist(n.Rlist)
|
return callrecv(n.Left) || callrecv(n.Right) || callrecvlist(n.Ninit) || callrecvlist(n.Nbody) || callrecvlist(n.List) || callrecvlist(n.Rlist)
|
||||||
}
|
}
|
||||||
|
|
||||||
func callrecvlist(l *NodeList) bool {
|
func callrecvlist(l *NodeList) bool {
|
||||||
|
|
@ -2097,11 +2097,11 @@ OpSwitch:
|
||||||
ok |= Etop
|
ok |= Etop
|
||||||
typechecklist(n.Ninit, Etop)
|
typechecklist(n.Ninit, Etop)
|
||||||
decldepth++
|
decldepth++
|
||||||
typecheck(&n.Ntest, Erv)
|
typecheck(&n.Left, Erv)
|
||||||
if n.Ntest != nil {
|
if n.Left != nil {
|
||||||
t := n.Ntest.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.Ntest, obj.FmtLong))
|
Yyerror("non-bool %v used as for condition", Nconv(n.Left, obj.FmtLong))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typecheck(&n.Right, Etop)
|
typecheck(&n.Right, Etop)
|
||||||
|
|
@ -2112,11 +2112,11 @@ OpSwitch:
|
||||||
case OIF:
|
case OIF:
|
||||||
ok |= Etop
|
ok |= Etop
|
||||||
typechecklist(n.Ninit, Etop)
|
typechecklist(n.Ninit, Etop)
|
||||||
typecheck(&n.Ntest, Erv)
|
typecheck(&n.Left, Erv)
|
||||||
if n.Ntest != nil {
|
if n.Left != nil {
|
||||||
t := n.Ntest.Type
|
t := n.Left.Type
|
||||||
if t != nil && t.Etype != TBOOL {
|
if t != nil && t.Etype != TBOOL {
|
||||||
Yyerror("non-bool %v used as if condition", Nconv(n.Ntest, obj.FmtLong))
|
Yyerror("non-bool %v used as if condition", Nconv(n.Left, obj.FmtLong))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typechecklist(n.Nbody, Etop)
|
typechecklist(n.Nbody, Etop)
|
||||||
|
|
@ -2811,7 +2811,7 @@ func fielddup(n *Node, hash map[string]bool) {
|
||||||
hash[name] = true
|
hash[name] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func keydup(n *Node, hash []*Node) {
|
func keydup(n *Node, hash map[uint32][]*Node) {
|
||||||
orign := n
|
orign := n
|
||||||
if n.Op == OCONVIFACE {
|
if n.Op == OCONVIFACE {
|
||||||
n = n.Left
|
n = n.Left
|
||||||
|
|
@ -2846,9 +2846,8 @@ func keydup(n *Node, hash []*Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h := uint(b % uint32(len(hash)))
|
|
||||||
var cmp Node
|
var cmp Node
|
||||||
for a := hash[h]; a != nil; a = a.Ntest {
|
for _, a := range hash[b] {
|
||||||
cmp.Op = OEQ
|
cmp.Op = OEQ
|
||||||
cmp.Left = n
|
cmp.Left = n
|
||||||
b = 0
|
b = 0
|
||||||
|
|
@ -2870,75 +2869,20 @@ func keydup(n *Node, hash []*Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
orign.Ntest = hash[h]
|
hash[b] = append(hash[b], orign)
|
||||||
hash[h] = orign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexdup(n *Node, hash []*Node) {
|
func indexdup(n *Node, hash map[int64]*Node) {
|
||||||
if n.Op != OLITERAL {
|
if n.Op != OLITERAL {
|
||||||
Fatal("indexdup: not OLITERAL")
|
Fatal("indexdup: not OLITERAL")
|
||||||
}
|
}
|
||||||
|
|
||||||
b := uint32(Mpgetfix(n.Val.U.(*Mpint)))
|
v := Mpgetfix(n.Val.U.(*Mpint))
|
||||||
h := uint(b % uint32(len(hash)))
|
if hash[v] != nil {
|
||||||
var c uint32
|
Yyerror("duplicate index in array literal: %d", v)
|
||||||
for a := hash[h]; a != nil; a = a.Ntest {
|
return
|
||||||
c = uint32(Mpgetfix(a.Val.U.(*Mpint)))
|
|
||||||
if b == c {
|
|
||||||
Yyerror("duplicate index in array literal: %d", b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
hash[v] = n
|
||||||
n.Ntest = hash[h]
|
|
||||||
hash[h] = n
|
|
||||||
}
|
|
||||||
|
|
||||||
func prime(h uint32, sr uint32) bool {
|
|
||||||
for n := uint32(3); n <= sr; n += 2 {
|
|
||||||
if h%n == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func inithash(n *Node, autohash []*Node) []*Node {
|
|
||||||
// count the number of entries
|
|
||||||
h := uint32(0)
|
|
||||||
|
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
|
||||||
h++
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the auto hash table is
|
|
||||||
// large enough use it.
|
|
||||||
if h <= uint32(len(autohash)) {
|
|
||||||
for i := range autohash {
|
|
||||||
autohash[i] = nil
|
|
||||||
}
|
|
||||||
return autohash
|
|
||||||
}
|
|
||||||
|
|
||||||
// make hash size odd and 12% larger than entries
|
|
||||||
h += h / 8
|
|
||||||
|
|
||||||
h |= 1
|
|
||||||
|
|
||||||
// calculate sqrt of h
|
|
||||||
sr := h / 2
|
|
||||||
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
sr = (sr + h/sr) / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for primeality
|
|
||||||
for !prime(h, sr) {
|
|
||||||
h += 2
|
|
||||||
}
|
|
||||||
|
|
||||||
// build and return a throw-away hash table
|
|
||||||
return make([]*Node, h)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func iscomptype(t *Type) bool {
|
func iscomptype(t *Type) bool {
|
||||||
|
|
@ -3031,9 +2975,14 @@ func typecheckcomplit(np **Node) {
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
|
|
||||||
case TARRAY:
|
case TARRAY:
|
||||||
var autohash [101]*Node
|
// Only allocate hash if there are some key/value pairs.
|
||||||
hash := inithash(n, autohash[:])
|
var hash map[int64]*Node
|
||||||
|
for ll := n.List; ll != nil; ll = ll.Next {
|
||||||
|
if ll.N.Op == OKEY {
|
||||||
|
hash = make(map[int64]*Node)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
length := int64(0)
|
length := int64(0)
|
||||||
i := 0
|
i := 0
|
||||||
var l *Node
|
var l *Node
|
||||||
|
|
@ -3056,7 +3005,7 @@ func typecheckcomplit(np **Node) {
|
||||||
i = -(1 << 30) // stay negative for a while
|
i = -(1 << 30) // stay negative for a while
|
||||||
}
|
}
|
||||||
|
|
||||||
if i >= 0 {
|
if i >= 0 && hash != nil {
|
||||||
indexdup(l.Left, hash)
|
indexdup(l.Left, hash)
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
|
|
@ -3085,9 +3034,7 @@ func typecheckcomplit(np **Node) {
|
||||||
n.Op = OARRAYLIT
|
n.Op = OARRAYLIT
|
||||||
|
|
||||||
case TMAP:
|
case TMAP:
|
||||||
var autohash [101]*Node
|
hash := make(map[uint32][]*Node)
|
||||||
hash := inithash(n, autohash[:])
|
|
||||||
|
|
||||||
var l *Node
|
var l *Node
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
for ll := n.List; ll != nil; ll = ll.Next {
|
||||||
l = ll.N
|
l = ll.N
|
||||||
|
|
@ -3952,7 +3899,6 @@ func markbreak(n *Node, implicit *Node) {
|
||||||
markbreak(n.Left, implicit)
|
markbreak(n.Left, implicit)
|
||||||
|
|
||||||
markbreak(n.Right, implicit)
|
markbreak(n.Right, implicit)
|
||||||
markbreak(n.Ntest, implicit)
|
|
||||||
markbreaklist(n.Ninit, implicit)
|
markbreaklist(n.Ninit, implicit)
|
||||||
markbreaklist(n.Nbody, implicit)
|
markbreaklist(n.Nbody, implicit)
|
||||||
markbreaklist(n.List, implicit)
|
markbreaklist(n.List, implicit)
|
||||||
|
|
@ -4024,7 +3970,7 @@ func isterminating(l *NodeList, top int) bool {
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case OFOR:
|
case OFOR:
|
||||||
if n.Ntest != nil {
|
if n.Left != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if n.Hasbreak {
|
if n.Hasbreak {
|
||||||
|
|
|
||||||
|
|
@ -247,19 +247,19 @@ func walkstmt(np **Node) {
|
||||||
adjustargs(n, 2*Widthptr)
|
adjustargs(n, 2*Widthptr)
|
||||||
|
|
||||||
case OFOR:
|
case OFOR:
|
||||||
if n.Ntest != nil {
|
if n.Left != nil {
|
||||||
walkstmtlist(n.Ntest.Ninit)
|
walkstmtlist(n.Left.Ninit)
|
||||||
init := n.Ntest.Ninit
|
init := n.Left.Ninit
|
||||||
n.Ntest.Ninit = nil
|
n.Left.Ninit = nil
|
||||||
walkexpr(&n.Ntest, &init)
|
walkexpr(&n.Left, &init)
|
||||||
addinit(&n.Ntest, init)
|
addinit(&n.Left, init)
|
||||||
}
|
}
|
||||||
|
|
||||||
walkstmt(&n.Right)
|
walkstmt(&n.Right)
|
||||||
walkstmtlist(n.Nbody)
|
walkstmtlist(n.Nbody)
|
||||||
|
|
||||||
case OIF:
|
case OIF:
|
||||||
walkexpr(&n.Ntest, &n.Ninit)
|
walkexpr(&n.Left, &n.Ninit)
|
||||||
walkstmtlist(n.Nbody)
|
walkstmtlist(n.Nbody)
|
||||||
walkstmtlist(n.Rlist)
|
walkstmtlist(n.Rlist)
|
||||||
|
|
||||||
|
|
@ -1043,7 +1043,7 @@ func walkexpr(np **Node, init **NodeList) {
|
||||||
walkexpr(&n1, init)
|
walkexpr(&n1, init)
|
||||||
|
|
||||||
n2 := Nod(OIF, nil, nil)
|
n2 := Nod(OIF, nil, nil)
|
||||||
n2.Ntest = Nod(OEQ, l, nodnil())
|
n2.Left = Nod(OEQ, l, nodnil())
|
||||||
n2.Nbody = list1(Nod(OAS, l, n1))
|
n2.Nbody = list1(Nod(OAS, l, n1))
|
||||||
n2.Likely = -1
|
n2.Likely = -1
|
||||||
typecheck(&n2, Etop)
|
typecheck(&n2, Etop)
|
||||||
|
|
@ -2914,7 +2914,7 @@ func appendslice(n *Node, init **NodeList) *Node {
|
||||||
// n := len(s) + len(l2) - cap(s)
|
// n := len(s) + len(l2) - cap(s)
|
||||||
nif.Ninit = list1(Nod(OAS, nt, Nod(OSUB, Nod(OADD, Nod(OLEN, s, nil), Nod(OLEN, l2, nil)), Nod(OCAP, s, nil))))
|
nif.Ninit = list1(Nod(OAS, nt, Nod(OSUB, Nod(OADD, Nod(OLEN, s, nil), Nod(OLEN, l2, nil)), Nod(OCAP, s, nil))))
|
||||||
|
|
||||||
nif.Ntest = Nod(OGT, nt, Nodintconst(0))
|
nif.Left = Nod(OGT, nt, Nodintconst(0))
|
||||||
|
|
||||||
// instantiate growslice(Type*, []any, int) []any
|
// instantiate growslice(Type*, []any, int) []any
|
||||||
fn := syslook("growslice", 1) // growslice(<type>, old []T, n int64) (ret []T)
|
fn := syslook("growslice", 1) // growslice(<type>, old []T, n int64) (ret []T)
|
||||||
|
|
@ -3046,7 +3046,7 @@ func walkappend(n *Node, init **NodeList, dst *Node) *Node {
|
||||||
|
|
||||||
na := Nodintconst(int64(argc)) // const argc
|
na := Nodintconst(int64(argc)) // const argc
|
||||||
nx := Nod(OIF, nil, nil) // if cap(s) - len(s) < argc
|
nx := Nod(OIF, nil, nil) // if cap(s) - len(s) < argc
|
||||||
nx.Ntest = 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", 1) // growslice(<type>, old []T, n int) (ret []T)
|
fn := syslook("growslice", 1) // growslice(<type>, old []T, n int) (ret []T)
|
||||||
substArgTypes(fn, ns.Type.Type, ns.Type.Type)
|
substArgTypes(fn, ns.Type.Type, ns.Type.Type)
|
||||||
|
|
@ -3124,7 +3124,7 @@ func copyany(n *Node, init **NodeList, runtimecall int) *Node {
|
||||||
// if n > len(frm) { n = len(frm) }
|
// if n > len(frm) { n = len(frm) }
|
||||||
nif := Nod(OIF, nil, nil)
|
nif := Nod(OIF, nil, nil)
|
||||||
|
|
||||||
nif.Ntest = Nod(OGT, nlen, Nod(OLEN, nr, nil))
|
nif.Left = Nod(OGT, nlen, Nod(OLEN, nr, nil))
|
||||||
nif.Nbody = list(nif.Nbody, Nod(OAS, nlen, Nod(OLEN, nr, nil)))
|
nif.Nbody = list(nif.Nbody, Nod(OAS, nlen, Nod(OLEN, nr, nil)))
|
||||||
l = list(l, nif)
|
l = list(l, nif)
|
||||||
|
|
||||||
|
|
@ -3982,7 +3982,7 @@ func candiscard(n *Node) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !candiscard(n.Left) || !candiscard(n.Right) || !candiscard(n.Ntest) || !candiscardlist(n.Ninit) || !candiscardlist(n.Nbody) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) {
|
if !candiscard(n.Left) || !candiscard(n.Right) || !candiscardlist(n.Ninit) || !candiscardlist(n.Nbody) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1788,7 +1788,7 @@ yydefault:
|
||||||
if yyDollar[1].node != nil {
|
if yyDollar[1].node != nil {
|
||||||
yyVAL.node.Ninit = list1(yyDollar[1].node)
|
yyVAL.node.Ninit = list1(yyDollar[1].node)
|
||||||
}
|
}
|
||||||
yyVAL.node.Ntest = yyDollar[3].node
|
yyVAL.node.Left = yyDollar[3].node
|
||||||
yyVAL.node.Right = yyDollar[5].node
|
yyVAL.node.Right = yyDollar[5].node
|
||||||
}
|
}
|
||||||
case 71:
|
case 71:
|
||||||
|
|
@ -1797,7 +1797,7 @@ yydefault:
|
||||||
{
|
{
|
||||||
// normal test
|
// normal test
|
||||||
yyVAL.node = Nod(OFOR, nil, nil)
|
yyVAL.node = Nod(OFOR, nil, nil)
|
||||||
yyVAL.node.Ntest = yyDollar[1].node
|
yyVAL.node.Left = yyDollar[1].node
|
||||||
}
|
}
|
||||||
case 73:
|
case 73:
|
||||||
yyDollar = yyS[yypt-2 : yypt+1]
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
|
@ -1825,7 +1825,7 @@ yydefault:
|
||||||
{
|
{
|
||||||
// test
|
// test
|
||||||
yyVAL.node = Nod(OIF, nil, nil)
|
yyVAL.node = Nod(OIF, nil, nil)
|
||||||
yyVAL.node.Ntest = yyDollar[1].node
|
yyVAL.node.Left = yyDollar[1].node
|
||||||
}
|
}
|
||||||
case 77:
|
case 77:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
|
|
@ -1836,7 +1836,7 @@ yydefault:
|
||||||
if yyDollar[1].node != nil {
|
if yyDollar[1].node != nil {
|
||||||
yyVAL.node.Ninit = list1(yyDollar[1].node)
|
yyVAL.node.Ninit = list1(yyDollar[1].node)
|
||||||
}
|
}
|
||||||
yyVAL.node.Ntest = yyDollar[3].node
|
yyVAL.node.Left = yyDollar[3].node
|
||||||
}
|
}
|
||||||
case 78:
|
case 78:
|
||||||
yyDollar = yyS[yypt-1 : yypt+1]
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
|
@ -1848,7 +1848,7 @@ yydefault:
|
||||||
yyDollar = yyS[yypt-3 : yypt+1]
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
//line go.y:756
|
//line go.y:756
|
||||||
{
|
{
|
||||||
if yyDollar[3].node.Ntest == nil {
|
if yyDollar[3].node.Left == nil {
|
||||||
Yyerror("missing condition in if statement")
|
Yyerror("missing condition in if statement")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1886,7 +1886,7 @@ yydefault:
|
||||||
yyDollar = yyS[yypt-5 : yypt+1]
|
yyDollar = yyS[yypt-5 : yypt+1]
|
||||||
//line go.y:788
|
//line go.y:788
|
||||||
{
|
{
|
||||||
if yyDollar[4].node.Ntest == nil {
|
if yyDollar[4].node.Left == nil {
|
||||||
Yyerror("missing condition in if statement")
|
Yyerror("missing condition in if statement")
|
||||||
}
|
}
|
||||||
yyDollar[4].node.Nbody = yyDollar[5].list
|
yyDollar[4].node.Nbody = yyDollar[5].list
|
||||||
|
|
@ -1929,7 +1929,7 @@ yydefault:
|
||||||
//line go.y:822
|
//line go.y:822
|
||||||
{
|
{
|
||||||
var n *Node
|
var n *Node
|
||||||
n = yyDollar[3].node.Ntest
|
n = yyDollar[3].node.Left
|
||||||
if n != nil && n.Op != OTYPESW {
|
if n != nil && n.Op != OTYPESW {
|
||||||
n = nil
|
n = nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue