mirror of
https://github.com/golang/go
synced 2024-10-03 00:21:22 -06:00
cmd/compile: fix Node.Etype overloading
Add helper methods that validate n.Op and convert to/from the appropriate type. Notably, there was a lot of code in walk.go that thought setting Etype=1 on an OADDR node affected escape analysis. Passes toolstash-check. TBR=marvin Change-Id: Ieae7c67225c1459c9719f9e6a748a25b975cf758 Reviewed-on: https://go-review.googlesource.com/99535 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
91102bf723
commit
e4de522c95
@ -233,7 +233,6 @@ func genhash(sym *types.Sym, t *types.Type) {
|
|||||||
nx := nod(OINDEX, np, ni)
|
nx := nod(OINDEX, np, ni)
|
||||||
nx.SetBounded(true)
|
nx.SetBounded(true)
|
||||||
na := nod(OADDR, nx, nil)
|
na := nod(OADDR, nx, nil)
|
||||||
na.Etype = 1 // no escape to heap
|
|
||||||
call.List.Append(na)
|
call.List.Append(na)
|
||||||
call.List.Append(nh)
|
call.List.Append(nh)
|
||||||
n.Nbody.Append(nod(OAS, nh, call))
|
n.Nbody.Append(nod(OAS, nh, call))
|
||||||
@ -258,7 +257,6 @@ func genhash(sym *types.Sym, t *types.Type) {
|
|||||||
call := nod(OCALL, hashel, nil)
|
call := nod(OCALL, hashel, nil)
|
||||||
nx := nodSym(OXDOT, np, f.Sym) // TODO: fields from other packages?
|
nx := nodSym(OXDOT, np, f.Sym) // TODO: fields from other packages?
|
||||||
na := nod(OADDR, nx, nil)
|
na := nod(OADDR, nx, nil)
|
||||||
na.Etype = 1 // no escape to heap
|
|
||||||
call.List.Append(na)
|
call.List.Append(na)
|
||||||
call.List.Append(nh)
|
call.List.Append(nh)
|
||||||
fn.Nbody.Append(nod(OAS, nh, call))
|
fn.Nbody.Append(nod(OAS, nh, call))
|
||||||
@ -274,7 +272,6 @@ func genhash(sym *types.Sym, t *types.Type) {
|
|||||||
call := nod(OCALL, hashel, nil)
|
call := nod(OCALL, hashel, nil)
|
||||||
nx := nodSym(OXDOT, np, f.Sym) // TODO: fields from other packages?
|
nx := nodSym(OXDOT, np, f.Sym) // TODO: fields from other packages?
|
||||||
na := nod(OADDR, nx, nil)
|
na := nod(OADDR, nx, nil)
|
||||||
na.Etype = 1 // no escape to heap
|
|
||||||
call.List.Append(na)
|
call.List.Append(na)
|
||||||
call.List.Append(nh)
|
call.List.Append(nh)
|
||||||
call.List.Append(nodintconst(size))
|
call.List.Append(nodintconst(size))
|
||||||
@ -518,9 +515,7 @@ func eqfield(p *Node, q *Node, field *types.Sym) *Node {
|
|||||||
// memequal(&p.field, &q.field [, size])
|
// memequal(&p.field, &q.field [, size])
|
||||||
func eqmem(p *Node, q *Node, field *types.Sym, size int64) *Node {
|
func eqmem(p *Node, q *Node, field *types.Sym, size int64) *Node {
|
||||||
nx := nod(OADDR, nodSym(OXDOT, p, field), nil)
|
nx := nod(OADDR, nodSym(OXDOT, p, field), nil)
|
||||||
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
|
|
||||||
nx = typecheck(nx, Erv)
|
nx = typecheck(nx, Erv)
|
||||||
ny = typecheck(ny, Erv)
|
ny = typecheck(ny, Erv)
|
||||||
|
|
||||||
|
@ -1461,7 +1461,7 @@ func (p *exporter) expr(n *Node) {
|
|||||||
p.exprList(n.List)
|
p.exprList(n.List)
|
||||||
|
|
||||||
case OCMPSTR, OCMPIFACE:
|
case OCMPSTR, OCMPIFACE:
|
||||||
p.op(Op(n.Etype))
|
p.op(n.SubOp())
|
||||||
p.pos(n)
|
p.pos(n)
|
||||||
p.expr(n.Left)
|
p.expr(n.Left)
|
||||||
p.expr(n.Right)
|
p.expr(n.Right)
|
||||||
@ -1527,7 +1527,7 @@ func (p *exporter) stmt(n *Node) {
|
|||||||
case OASOP:
|
case OASOP:
|
||||||
p.op(OASOP)
|
p.op(OASOP)
|
||||||
p.pos(n)
|
p.pos(n)
|
||||||
p.int(int(n.Etype))
|
p.op(n.SubOp())
|
||||||
p.expr(n.Left)
|
p.expr(n.Left)
|
||||||
if p.bool(!n.Implicit()) {
|
if p.bool(!n.Implicit()) {
|
||||||
p.expr(n.Right)
|
p.expr(n.Right)
|
||||||
|
@ -1124,7 +1124,7 @@ func (p *importer) node() *Node {
|
|||||||
|
|
||||||
case OASOP:
|
case OASOP:
|
||||||
n := nodl(p.pos(), OASOP, nil, nil)
|
n := nodl(p.pos(), OASOP, nil, nil)
|
||||||
n.Etype = types.EType(p.int())
|
n.SetSubOp(p.op())
|
||||||
n.Left = p.expr()
|
n.Left = p.expr()
|
||||||
if !p.bool() {
|
if !p.bool() {
|
||||||
n.Right = nodintconst(1)
|
n.Right = nodintconst(1)
|
||||||
|
@ -926,7 +926,7 @@ func (n *Node) stmtfmt(s fmt.State, mode fmtMode) {
|
|||||||
|
|
||||||
case OASOP:
|
case OASOP:
|
||||||
if n.Implicit() {
|
if n.Implicit() {
|
||||||
if Op(n.Etype) == OADD {
|
if n.SubOp() == OADD {
|
||||||
mode.Fprintf(s, "%v++", n.Left)
|
mode.Fprintf(s, "%v++", n.Left)
|
||||||
} else {
|
} else {
|
||||||
mode.Fprintf(s, "%v--", n.Left)
|
mode.Fprintf(s, "%v--", n.Left)
|
||||||
@ -934,7 +934,7 @@ func (n *Node) stmtfmt(s fmt.State, mode fmtMode) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
mode.Fprintf(s, "%v %#v= %v", n.Left, Op(n.Etype), n.Right)
|
mode.Fprintf(s, "%v %#v= %v", n.Left, n.SubOp(), n.Right)
|
||||||
|
|
||||||
case OAS2:
|
case OAS2:
|
||||||
if n.Colas() && !complexinit {
|
if n.Colas() && !complexinit {
|
||||||
@ -1274,7 +1274,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
|||||||
mode.Fprintf(s, "map[%v]%v", n.Left, n.Right)
|
mode.Fprintf(s, "map[%v]%v", n.Left, n.Right)
|
||||||
|
|
||||||
case OTCHAN:
|
case OTCHAN:
|
||||||
switch types.ChanDir(n.Etype) {
|
switch n.TChanDir() {
|
||||||
case types.Crecv:
|
case types.Crecv:
|
||||||
mode.Fprintf(s, "<-chan %v", n.Left)
|
mode.Fprintf(s, "<-chan %v", n.Left)
|
||||||
|
|
||||||
@ -1282,7 +1282,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
|||||||
mode.Fprintf(s, "chan<- %v", n.Left)
|
mode.Fprintf(s, "chan<- %v", n.Left)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && types.ChanDir(n.Left.Etype) == types.Crecv {
|
if n.Left != nil && n.Left.Op == OTCHAN && n.Left.Sym == nil && n.Left.TChanDir() == types.Crecv {
|
||||||
mode.Fprintf(s, "chan (%v)", n.Left)
|
mode.Fprintf(s, "chan (%v)", n.Left)
|
||||||
} else {
|
} else {
|
||||||
mode.Fprintf(s, "chan %v", n.Left)
|
mode.Fprintf(s, "chan %v", n.Left)
|
||||||
@ -1517,8 +1517,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
|||||||
|
|
||||||
case OCMPSTR, OCMPIFACE:
|
case OCMPSTR, OCMPIFACE:
|
||||||
n.Left.exprfmt(s, nprec, mode)
|
n.Left.exprfmt(s, nprec, mode)
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
mode.Fprintf(s, " %#v ", n.SubOp())
|
||||||
mode.Fprintf(s, " %#v ", Op(n.Etype))
|
|
||||||
n.Right.exprfmt(s, nprec+1, mode)
|
n.Right.exprfmt(s, nprec+1, mode)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1593,7 +1592,7 @@ func (n *Node) nodedump(s fmt.State, flag FmtFlag, mode fmtMode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case OASOP:
|
case OASOP:
|
||||||
mode.Fprintf(s, "%v-%v%j", n.Op, Op(n.Etype), n)
|
mode.Fprintf(s, "%v-%v%j", n.Op, n.SubOp(), n)
|
||||||
|
|
||||||
case OTYPE:
|
case OTYPE:
|
||||||
mode.Fprintf(s, "%v %v%j type=%v", n.Op, n.Sym, n, n.Type)
|
mode.Fprintf(s, "%v %v%j type=%v", n.Op, n.Sym, n, n.Type)
|
||||||
|
@ -1005,7 +1005,6 @@ func mkinlcall1(n, fn *Node, isddd bool) *Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
retlabel := autolabel(".i")
|
retlabel := autolabel(".i")
|
||||||
retlabel.Etype = 1 // flag 'safe' for escape analysis (no backjumps)
|
|
||||||
|
|
||||||
inlgen++
|
inlgen++
|
||||||
|
|
||||||
|
@ -654,7 +654,7 @@ func (p *noder) expr(expr syntax.Expr) *Node {
|
|||||||
return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value))
|
return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value))
|
||||||
case *syntax.ChanType:
|
case *syntax.ChanType:
|
||||||
n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil)
|
n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil)
|
||||||
n.Etype = types.EType(p.chanDir(expr.Dir))
|
n.SetTChanDir(p.chanDir(expr.Dir))
|
||||||
return n
|
return n
|
||||||
|
|
||||||
case *syntax.TypeSwitchGuard:
|
case *syntax.TypeSwitchGuard:
|
||||||
@ -902,7 +902,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node {
|
|||||||
if stmt.Op != 0 && stmt.Op != syntax.Def {
|
if stmt.Op != 0 && stmt.Op != syntax.Def {
|
||||||
n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs))
|
n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs))
|
||||||
n.SetImplicit(stmt.Rhs == syntax.ImplicitOne)
|
n.SetImplicit(stmt.Rhs == syntax.ImplicitOne)
|
||||||
n.Etype = types.EType(p.binOp(stmt.Op))
|
n.SetSubOp(p.binOp(stmt.Op))
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,15 +526,14 @@ func (o *Order) stmt(n *Node) {
|
|||||||
n.Left = o.safeExpr(n.Left)
|
n.Left = o.safeExpr(n.Left)
|
||||||
tmp1 := treecopy(n.Left, src.NoXPos)
|
tmp1 := treecopy(n.Left, src.NoXPos)
|
||||||
if tmp1.Op == OINDEXMAP {
|
if tmp1.Op == OINDEXMAP {
|
||||||
tmp1.Etype = 0 // now an rvalue not an lvalue
|
tmp1.SetIndexMapLValue(false)
|
||||||
}
|
}
|
||||||
tmp1 = o.copyExpr(tmp1, n.Left.Type, false)
|
tmp1 = o.copyExpr(tmp1, n.Left.Type, false)
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
n.Right = nod(n.SubOp(), tmp1, n.Right)
|
||||||
n.Right = nod(Op(n.Etype), tmp1, n.Right)
|
|
||||||
n.Right = typecheck(n.Right, Erv)
|
n.Right = typecheck(n.Right, Erv)
|
||||||
n.Right = o.expr(n.Right, nil)
|
n.Right = o.expr(n.Right, nil)
|
||||||
n.Etype = 0
|
|
||||||
n.Op = OAS
|
n.Op = OAS
|
||||||
|
n.ResetAux()
|
||||||
o.mapAssign(n)
|
o.mapAssign(n)
|
||||||
o.cleanTemp(t)
|
o.cleanTemp(t)
|
||||||
|
|
||||||
@ -1015,7 +1014,7 @@ func (o *Order) expr(n, lhs *Node) *Node {
|
|||||||
n.Right = o.expr(n.Right, nil)
|
n.Right = o.expr(n.Right, nil)
|
||||||
needCopy := false
|
needCopy := false
|
||||||
|
|
||||||
if n.Etype == 0 && instrumenting {
|
if !n.IndexMapLValue() && instrumenting {
|
||||||
// Race detector needs the copy so it can
|
// Race detector needs the copy so it can
|
||||||
// call treecopy on the result.
|
// call treecopy on the result.
|
||||||
needCopy = true
|
needCopy = true
|
||||||
@ -1031,7 +1030,7 @@ func (o *Order) expr(n, lhs *Node) *Node {
|
|||||||
// the map index, because the map access is going to
|
// the map index, because the map access is going to
|
||||||
// be forced to happen immediately following this
|
// be forced to happen immediately following this
|
||||||
// conversion (by the ordercopyexpr a few lines below).
|
// conversion (by the ordercopyexpr a few lines below).
|
||||||
if n.Etype == 0 && n.Right.Op == OARRAYBYTESTR {
|
if !n.IndexMapLValue() && n.Right.Op == OARRAYBYTESTR {
|
||||||
n.Right.Op = OARRAYBYTESTRTMP
|
n.Right.Op = OARRAYBYTESTRTMP
|
||||||
needCopy = true
|
needCopy = true
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,62 @@ type Node struct {
|
|||||||
|
|
||||||
Esc uint16 // EscXXX
|
Esc uint16 // EscXXX
|
||||||
|
|
||||||
Op Op
|
Op Op
|
||||||
Etype types.EType // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg, ChanDir for OTCHAN, for OINDEXMAP 1=LHS,0=RHS
|
aux uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) ResetAux() {
|
||||||
|
n.aux = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) SubOp() Op {
|
||||||
|
switch n.Op {
|
||||||
|
case OASOP, OCMPIFACE, OCMPSTR, ONAME:
|
||||||
|
default:
|
||||||
|
Fatalf("unexpected op: %v", n.Op)
|
||||||
|
}
|
||||||
|
return Op(n.aux)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) SetSubOp(op Op) {
|
||||||
|
switch n.Op {
|
||||||
|
case OASOP, OCMPIFACE, OCMPSTR, ONAME:
|
||||||
|
default:
|
||||||
|
Fatalf("unexpected op: %v", n.Op)
|
||||||
|
}
|
||||||
|
n.aux = uint8(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) IndexMapLValue() bool {
|
||||||
|
if n.Op != OINDEXMAP {
|
||||||
|
Fatalf("unexpected op: %v", n.Op)
|
||||||
|
}
|
||||||
|
return n.aux != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) SetIndexMapLValue(b bool) {
|
||||||
|
if n.Op != OINDEXMAP {
|
||||||
|
Fatalf("unexpected op: %v", n.Op)
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
n.aux = 1
|
||||||
|
} else {
|
||||||
|
n.aux = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) TChanDir() types.ChanDir {
|
||||||
|
if n.Op != OTCHAN {
|
||||||
|
Fatalf("unexpected op: %v", n.Op)
|
||||||
|
}
|
||||||
|
return types.ChanDir(n.aux)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) SetTChanDir(dir types.ChanDir) {
|
||||||
|
if n.Op != OTCHAN {
|
||||||
|
Fatalf("unexpected op: %v", n.Op)
|
||||||
|
}
|
||||||
|
n.aux = uint8(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) IsSynthetic() bool {
|
func (n *Node) IsSynthetic() bool {
|
||||||
|
@ -263,7 +263,7 @@ func typecheck1(n *Node, top int) *Node {
|
|||||||
// n.Sym is a field/method name, not a variable.
|
// n.Sym is a field/method name, not a variable.
|
||||||
default:
|
default:
|
||||||
if n.Sym != nil {
|
if n.Sym != nil {
|
||||||
if n.Op == ONAME && n.Etype != 0 && top&Ecall == 0 {
|
if n.Op == ONAME && n.SubOp() != 0 && top&Ecall == 0 {
|
||||||
yyerror("use of builtin %v not in function call", n.Sym)
|
yyerror("use of builtin %v not in function call", n.Sym)
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return n
|
return n
|
||||||
@ -300,7 +300,7 @@ func typecheck1(n *Node, top int) *Node {
|
|||||||
if n.Name.Decldepth == 0 {
|
if n.Name.Decldepth == 0 {
|
||||||
n.Name.Decldepth = decldepth
|
n.Name.Decldepth = decldepth
|
||||||
}
|
}
|
||||||
if n.Etype != 0 {
|
if n.SubOp() != 0 {
|
||||||
ok |= Ecall
|
ok |= Ecall
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -428,11 +428,11 @@ func typecheck1(n *Node, top int) *Node {
|
|||||||
if l.Type.NotInHeap() {
|
if l.Type.NotInHeap() {
|
||||||
yyerror("chan of go:notinheap type not allowed")
|
yyerror("chan of go:notinheap type not allowed")
|
||||||
}
|
}
|
||||||
t := types.NewChan(l.Type, types.ChanDir(n.Etype)) // TODO(marvin): Fix Node.EType type union.
|
t := types.NewChan(l.Type, n.TChanDir())
|
||||||
n.Op = OTYPE
|
n.Op = OTYPE
|
||||||
n.Type = t
|
n.Type = t
|
||||||
n.Left = nil
|
n.Left = nil
|
||||||
n.Etype = 0
|
n.ResetAux()
|
||||||
|
|
||||||
case OTSTRUCT:
|
case OTSTRUCT:
|
||||||
ok |= Etype
|
ok |= Etype
|
||||||
@ -540,7 +540,7 @@ func typecheck1(n *Node, top int) *Node {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
// TODO(marvin): Fix Node.EType type union.
|
||||||
op = Op(n.Etype)
|
op = n.SubOp()
|
||||||
} else {
|
} else {
|
||||||
ok |= Erv
|
ok |= Erv
|
||||||
n.Left = typecheck(n.Left, Erv)
|
n.Left = typecheck(n.Left, Erv)
|
||||||
@ -712,9 +712,9 @@ func typecheck1(n *Node, top int) *Node {
|
|||||||
|
|
||||||
if et == TSTRING {
|
if et == TSTRING {
|
||||||
if iscmp[n.Op] {
|
if iscmp[n.Op] {
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
ot := n.Op
|
||||||
n.Etype = types.EType(n.Op)
|
|
||||||
n.Op = OCMPSTR
|
n.Op = OCMPSTR
|
||||||
|
n.SetSubOp(ot)
|
||||||
} else if n.Op == OADD {
|
} else if n.Op == OADD {
|
||||||
// create OADDSTR node with list of strings in x + y + z + (w + v) + ...
|
// create OADDSTR node with list of strings in x + y + z + (w + v) + ...
|
||||||
n.Op = OADDSTR
|
n.Op = OADDSTR
|
||||||
@ -743,9 +743,9 @@ func typecheck1(n *Node, top int) *Node {
|
|||||||
} else if r.Op == OLITERAL && r.Val().Ctype() == CTNIL {
|
} else if r.Op == OLITERAL && r.Val().Ctype() == CTNIL {
|
||||||
} else // leave alone for back end
|
} else // leave alone for back end
|
||||||
if r.Type.IsInterface() == l.Type.IsInterface() {
|
if r.Type.IsInterface() == l.Type.IsInterface() {
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
ot := n.Op
|
||||||
n.Etype = types.EType(n.Op)
|
|
||||||
n.Op = OCMPIFACE
|
n.Op = OCMPIFACE
|
||||||
|
n.SetSubOp(ot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1026,13 +1026,13 @@ func typecheck1(n *Node, top int) *Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case TMAP:
|
case TMAP:
|
||||||
n.Etype = 0
|
|
||||||
n.Right = defaultlit(n.Right, t.Key())
|
n.Right = defaultlit(n.Right, t.Key())
|
||||||
if n.Right.Type != nil {
|
if n.Right.Type != nil {
|
||||||
n.Right = assignconv(n.Right, t.Key(), "map index")
|
n.Right = assignconv(n.Right, t.Key(), "map index")
|
||||||
}
|
}
|
||||||
n.Type = t.Val()
|
n.Type = t.Val()
|
||||||
n.Op = OINDEXMAP
|
n.Op = OINDEXMAP
|
||||||
|
n.ResetAux()
|
||||||
}
|
}
|
||||||
|
|
||||||
case ORECV:
|
case ORECV:
|
||||||
@ -1088,10 +1088,6 @@ func typecheck1(n *Node, top int) *Node {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
n.Right = assignconv(r, t.Elem(), "send")
|
n.Right = assignconv(r, t.Elem(), "send")
|
||||||
|
|
||||||
// TODO: more aggressive
|
|
||||||
n.Etype = 0
|
|
||||||
|
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
|
|
||||||
case OSLICE, OSLICE3:
|
case OSLICE, OSLICE3:
|
||||||
@ -1177,15 +1173,13 @@ func typecheck1(n *Node, top int) *Node {
|
|||||||
|
|
||||||
l := n.Left
|
l := n.Left
|
||||||
|
|
||||||
if l.Op == ONAME && l.Etype != 0 {
|
if l.Op == ONAME && l.SubOp() != 0 {
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
if n.Isddd() && l.SubOp() != OAPPEND {
|
||||||
if n.Isddd() && Op(l.Etype) != OAPPEND {
|
|
||||||
yyerror("invalid use of ... with builtin %v", l)
|
yyerror("invalid use of ... with builtin %v", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
// builtin: OLEN, OCAP, etc.
|
// builtin: OLEN, OCAP, etc.
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
n.Op = l.SubOp()
|
||||||
n.Op = Op(l.Etype)
|
|
||||||
n.Left = n.Right
|
n.Left = n.Right
|
||||||
n.Right = nil
|
n.Right = nil
|
||||||
n = typecheck1(n, top)
|
n = typecheck1(n, top)
|
||||||
@ -3214,7 +3208,7 @@ func checkassign(stmt *Node, n *Node) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n.Op == OINDEXMAP {
|
if n.Op == OINDEXMAP {
|
||||||
n.Etype = 1
|
n.SetIndexMapLValue(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3705,7 +3699,7 @@ func typecheckdef(n *Node) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if n.Name.Defn == nil {
|
if n.Name.Defn == nil {
|
||||||
if n.Etype != 0 { // like OPRINTN
|
if n.SubOp() != 0 { // like OPRINTN
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if nsavederrors+nerrors > 0 {
|
if nsavederrors+nerrors > 0 {
|
||||||
|
@ -114,16 +114,15 @@ func lexinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range builtinFuncs {
|
for _, s := range builtinFuncs {
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
|
||||||
s2 := builtinpkg.Lookup(s.name)
|
s2 := builtinpkg.Lookup(s.name)
|
||||||
s2.Def = asTypesNode(newname(s2))
|
s2.Def = asTypesNode(newname(s2))
|
||||||
asNode(s2.Def).Etype = types.EType(s.op)
|
asNode(s2.Def).SetSubOp(s.op)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range unsafeFuncs {
|
for _, s := range unsafeFuncs {
|
||||||
s2 := unsafepkg.Lookup(s.name)
|
s2 := unsafepkg.Lookup(s.name)
|
||||||
s2.Def = asTypesNode(newname(s2))
|
s2.Def = asTypesNode(newname(s2))
|
||||||
asNode(s2.Def).Etype = types.EType(s.op)
|
asNode(s2.Def).SetSubOp(s.op)
|
||||||
}
|
}
|
||||||
|
|
||||||
types.Idealstring = types.New(TSTRING)
|
types.Idealstring = types.New(TSTRING)
|
||||||
|
@ -557,7 +557,7 @@ opswitch:
|
|||||||
n.Right = walkexpr(n.Right, init)
|
n.Right = walkexpr(n.Right, init)
|
||||||
t := n.Left.Type
|
t := n.Left.Type
|
||||||
n.SetBounded(bounded(n.Right, 8*t.Width))
|
n.SetBounded(bounded(n.Right, 8*t.Width))
|
||||||
if Debug['m'] != 0 && n.Etype != 0 && !Isconst(n.Right, CTINT) {
|
if Debug['m'] != 0 && n.Bounded() && !Isconst(n.Right, CTINT) {
|
||||||
Warn("shift bounds check elided")
|
Warn("shift bounds check elided")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,7 +767,6 @@ opswitch:
|
|||||||
} else {
|
} else {
|
||||||
n1 = nod(OADDR, n.List.First(), nil)
|
n1 = nod(OADDR, n.List.First(), nil)
|
||||||
}
|
}
|
||||||
n1.Etype = 1 // addr does not escape
|
|
||||||
fn := chanfn("chanrecv2", 2, r.Left.Type)
|
fn := chanfn("chanrecv2", 2, r.Left.Type)
|
||||||
ok := n.List.Second()
|
ok := n.List.Second()
|
||||||
call := mkcall1(fn, ok.Type, init, r.Left, n1)
|
call := mkcall1(fn, ok.Type, init, r.Left, n1)
|
||||||
@ -1158,7 +1157,7 @@ opswitch:
|
|||||||
map_ := n.Left
|
map_ := n.Left
|
||||||
key := n.Right
|
key := n.Right
|
||||||
t := map_.Type
|
t := map_.Type
|
||||||
if n.Etype == 1 {
|
if n.IndexMapLValue() {
|
||||||
// This m[k] expression is on the left-hand side of an assignment.
|
// This m[k] expression is on the left-hand side of an assignment.
|
||||||
fast := mapfast(t)
|
fast := mapfast(t)
|
||||||
if fast == mapslow {
|
if fast == mapslow {
|
||||||
@ -1235,9 +1234,8 @@ opswitch:
|
|||||||
|
|
||||||
case OCMPSTR:
|
case OCMPSTR:
|
||||||
// s + "badgerbadgerbadger" == "badgerbadgerbadger"
|
// s + "badgerbadgerbadger" == "badgerbadgerbadger"
|
||||||
if (Op(n.Etype) == OEQ || Op(n.Etype) == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && n.Left.List.Len() == 2 && Isconst(n.Left.List.Second(), CTSTR) && strlit(n.Right) == strlit(n.Left.List.Second()) {
|
if (n.SubOp() == OEQ || n.SubOp() == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && n.Left.List.Len() == 2 && Isconst(n.Left.List.Second(), CTSTR) && strlit(n.Right) == strlit(n.Left.List.Second()) {
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
r := nod(n.SubOp(), nod(OLEN, n.Left.List.First(), nil), nodintconst(0))
|
||||||
r := nod(Op(n.Etype), nod(OLEN, n.Left.List.First(), nil), nodintconst(0))
|
|
||||||
n = finishcompare(n, r, init)
|
n = finishcompare(n, r, init)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1255,7 +1253,7 @@ opswitch:
|
|||||||
ncs = n.Left
|
ncs = n.Left
|
||||||
}
|
}
|
||||||
if cs != nil {
|
if cs != nil {
|
||||||
cmp := Op(n.Etype)
|
cmp := n.SubOp()
|
||||||
// maxRewriteLen was chosen empirically.
|
// maxRewriteLen was chosen empirically.
|
||||||
// It is the value that minimizes cmd/go file size
|
// It is the value that minimizes cmd/go file size
|
||||||
// across most architectures.
|
// across most architectures.
|
||||||
@ -1294,7 +1292,6 @@ opswitch:
|
|||||||
if len(s) > 0 {
|
if len(s) > 0 {
|
||||||
ncs = safeexpr(ncs, init)
|
ncs = safeexpr(ncs, init)
|
||||||
}
|
}
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
|
||||||
r := nod(cmp, nod(OLEN, ncs, nil), nodintconst(int64(len(s))))
|
r := nod(cmp, nod(OLEN, ncs, nil), nodintconst(int64(len(s))))
|
||||||
remains := len(s)
|
remains := len(s)
|
||||||
for i := 0; remains > 0; {
|
for i := 0; remains > 0; {
|
||||||
@ -1344,8 +1341,7 @@ opswitch:
|
|||||||
}
|
}
|
||||||
|
|
||||||
var r *Node
|
var r *Node
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
if n.SubOp() == OEQ || n.SubOp() == ONE {
|
||||||
if Op(n.Etype) == OEQ || Op(n.Etype) == ONE {
|
|
||||||
// prepare for rewrite below
|
// prepare for rewrite below
|
||||||
n.Left = cheapexpr(n.Left, init)
|
n.Left = cheapexpr(n.Left, init)
|
||||||
n.Right = cheapexpr(n.Right, init)
|
n.Right = cheapexpr(n.Right, init)
|
||||||
@ -1363,8 +1359,7 @@ opswitch:
|
|||||||
|
|
||||||
// quick check of len before full compare for == or !=.
|
// quick check of len before full compare for == or !=.
|
||||||
// memequal then tests equality up to length len.
|
// memequal then tests equality up to length len.
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
if n.SubOp() == OEQ {
|
||||||
if Op(n.Etype) == OEQ {
|
|
||||||
// len(left) == len(right) && memequal(left, right, len)
|
// len(left) == len(right) && memequal(left, right, len)
|
||||||
r = nod(OANDAND, nod(OEQ, llen, rlen), r)
|
r = nod(OANDAND, nod(OEQ, llen, rlen), r)
|
||||||
} else {
|
} else {
|
||||||
@ -1375,8 +1370,7 @@ opswitch:
|
|||||||
} else {
|
} else {
|
||||||
// sys_cmpstring(s1, s2) :: 0
|
// sys_cmpstring(s1, s2) :: 0
|
||||||
r = mkcall("cmpstring", types.Types[TINT], init, conv(n.Left, types.Types[TSTRING]), conv(n.Right, types.Types[TSTRING]))
|
r = mkcall("cmpstring", types.Types[TINT], init, conv(n.Left, types.Types[TSTRING]), conv(n.Right, types.Types[TSTRING]))
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
r = nod(n.SubOp(), r, nodintconst(0))
|
||||||
r = nod(Op(n.Etype), r, nodintconst(0))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n = finishcompare(n, r, init)
|
n = finishcompare(n, r, init)
|
||||||
@ -1677,9 +1671,8 @@ opswitch:
|
|||||||
|
|
||||||
// Check itable/type before full compare.
|
// Check itable/type before full compare.
|
||||||
// Note: short-circuited because order matters.
|
// Note: short-circuited because order matters.
|
||||||
// TODO(marvin): Fix Node.EType type union.
|
|
||||||
var cmp *Node
|
var cmp *Node
|
||||||
if Op(n.Etype) == OEQ {
|
if n.SubOp() == OEQ {
|
||||||
cmp = nod(OANDAND, nod(OEQ, lt, rt), call)
|
cmp = nod(OANDAND, nod(OEQ, lt, rt), call)
|
||||||
} else {
|
} else {
|
||||||
cmp = nod(OOROR, nod(ONE, lt, rt), nod(ONOT, call, nil))
|
cmp = nod(OOROR, nod(ONE, lt, rt), nod(ONOT, call, nil))
|
||||||
@ -2955,14 +2948,12 @@ func appendslice(n *Node, init *Nodes) *Node {
|
|||||||
// s = s[:n]
|
// s = s[:n]
|
||||||
nt := nod(OSLICE, s, nil)
|
nt := nod(OSLICE, s, nil)
|
||||||
nt.SetSliceBounds(nil, nn, nil)
|
nt.SetSliceBounds(nil, nn, nil)
|
||||||
nt.Etype = 1
|
|
||||||
l = append(l, nod(OAS, s, nt))
|
l = append(l, nod(OAS, s, nt))
|
||||||
|
|
||||||
if l1.Type.Elem().HasHeapPointer() {
|
if l1.Type.Elem().HasHeapPointer() {
|
||||||
// copy(s[len(l1):], l2)
|
// copy(s[len(l1):], l2)
|
||||||
nptr1 := nod(OSLICE, s, nil)
|
nptr1 := nod(OSLICE, s, nil)
|
||||||
nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil)
|
nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil)
|
||||||
nptr1.Etype = 1
|
|
||||||
nptr2 := l2
|
nptr2 := l2
|
||||||
Curfn.Func.setWBPos(n.Pos)
|
Curfn.Func.setWBPos(n.Pos)
|
||||||
fn := syslook("typedslicecopy")
|
fn := syslook("typedslicecopy")
|
||||||
@ -2976,7 +2967,6 @@ func appendslice(n *Node, init *Nodes) *Node {
|
|||||||
// copy(s[len(l1):], l2)
|
// copy(s[len(l1):], l2)
|
||||||
nptr1 := nod(OSLICE, s, nil)
|
nptr1 := nod(OSLICE, s, nil)
|
||||||
nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil)
|
nptr1.SetSliceBounds(nod(OLEN, l1, nil), nil, nil)
|
||||||
nptr1.Etype = 1
|
|
||||||
nptr2 := l2
|
nptr2 := l2
|
||||||
|
|
||||||
var ln Nodes
|
var ln Nodes
|
||||||
@ -3095,7 +3085,6 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
|
|||||||
|
|
||||||
nx = nod(OSLICE, ns, nil) // ...s[:n+argc]
|
nx = nod(OSLICE, ns, nil) // ...s[:n+argc]
|
||||||
nx.SetSliceBounds(nil, nod(OADD, nn, na), nil)
|
nx.SetSliceBounds(nil, nod(OADD, nn, na), nil)
|
||||||
nx.Etype = 1
|
|
||||||
l = append(l, nod(OAS, ns, nx)) // s = s[:n+argc]
|
l = append(l, nod(OAS, ns, nx)) // s = s[:n+argc]
|
||||||
|
|
||||||
ls = n.List.Slice()[1:]
|
ls = n.List.Slice()[1:]
|
||||||
@ -3320,13 +3309,11 @@ func walkcompare(n *Node, init *Nodes) *Node {
|
|||||||
// eq algs take pointers
|
// eq algs take pointers
|
||||||
pl := temp(types.NewPtr(t))
|
pl := temp(types.NewPtr(t))
|
||||||
al := nod(OAS, pl, nod(OADDR, cmpl, nil))
|
al := nod(OAS, pl, nod(OADDR, cmpl, nil))
|
||||||
al.Right.Etype = 1 // addr does not escape
|
|
||||||
al = typecheck(al, Etop)
|
al = typecheck(al, Etop)
|
||||||
init.Append(al)
|
init.Append(al)
|
||||||
|
|
||||||
pr := temp(types.NewPtr(t))
|
pr := temp(types.NewPtr(t))
|
||||||
ar := nod(OAS, pr, nod(OADDR, cmpr, nil))
|
ar := nod(OAS, pr, nod(OADDR, cmpr, nil))
|
||||||
ar.Right.Etype = 1 // addr does not escape
|
|
||||||
ar = typecheck(ar, Etop)
|
ar = typecheck(ar, Etop)
|
||||||
init.Append(ar)
|
init.Append(ar)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user