// backingArrayPtrLen extracts the pointer and length from a slice or string.
// This constructs two nodes referring to n, so n must be a cheapexpr.
-func backingArrayPtrLen(n ir.Node) (ptr, len ir.Node) {
+func backingArrayPtrLen(n ir.Node) (ptr, length ir.Node) {
var init ir.Nodes
c := cheapexpr(n, &init)
if c != n || init.Len() != 0 {
} else {
ptr.SetType(n.Type().Elem().PtrTo())
}
- len = ir.Nod(ir.OLEN, n, nil)
- len.SetType(types.Types[types.TINT])
- return ptr, len
+ length = ir.Nod(ir.OLEN, n, nil)
+ length.SetType(types.Types[types.TINT])
+ return ptr, length
}
func syslook(name string) ir.Node {
}
switch n.Op() {
+ default:
+ base.Fatalf("calcHasCall %+v", n)
+ panic("unreachable")
+
case ir.OLITERAL, ir.ONIL, ir.ONAME, ir.OTYPE:
if n.HasCall() {
base.Fatalf("OLITERAL/ONAME/OTYPE should never have calls: %+v", n)
if instrumenting {
return true
}
+ return n.Left().HasCall() || n.Right().HasCall()
case ir.OINDEX, ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR,
ir.ODEREF, ir.ODOTPTR, ir.ODOTTYPE, ir.ODIV, ir.OMOD:
// These ops might panic, make sure they are done
// When using soft-float, these ops might be rewritten to function calls
// so we ensure they are evaluated first.
- case ir.OADD, ir.OSUB, ir.ONEG, ir.OMUL:
+ case ir.OADD, ir.OSUB, ir.OMUL:
+ if thearch.SoftFloat && (isFloat[n.Type().Kind()] || isComplex[n.Type().Kind()]) {
+ return true
+ }
+ return n.Left().HasCall() || n.Right().HasCall()
+ case ir.ONEG:
if thearch.SoftFloat && (isFloat[n.Type().Kind()] || isComplex[n.Type().Kind()]) {
return true
}
+ return n.Left().HasCall()
case ir.OLT, ir.OEQ, ir.ONE, ir.OLE, ir.OGE, ir.OGT:
if thearch.SoftFloat && (isFloat[n.Left().Type().Kind()] || isComplex[n.Left().Type().Kind()]) {
return true
}
+ return n.Left().HasCall() || n.Right().HasCall()
case ir.OCONV:
if thearch.SoftFloat && ((isFloat[n.Type().Kind()] || isComplex[n.Type().Kind()]) || (isFloat[n.Left().Type().Kind()] || isComplex[n.Left().Type().Kind()])) {
return true
}
- }
+ return n.Left().HasCall()
- if n.Left() != nil && n.Left().HasCall() {
- return true
- }
- if n.Right() != nil && n.Right().HasCall() {
- return true
+ case ir.OAND, ir.OANDNOT, ir.OLSH, ir.OOR, ir.ORSH, ir.OXOR, ir.OCOPY, ir.OCOMPLEX, ir.OEFACE:
+ return n.Left().HasCall() || n.Right().HasCall()
+
+ case ir.OAS:
+ return n.Left().HasCall() || n.Right() != nil && n.Right().HasCall()
+
+ case ir.OADDR:
+ return n.Left().HasCall()
+ case ir.OPAREN:
+ return n.Left().HasCall()
+ case ir.OBITNOT, ir.ONOT, ir.OPLUS, ir.ORECV,
+ ir.OALIGNOF, ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.ONEW,
+ ir.OOFFSETOF, ir.OPANIC, ir.OREAL, ir.OSIZEOF,
+ ir.OCHECKNIL, ir.OCFUNC, ir.OIDATA, ir.OITAB, ir.ONEWOBJ, ir.OSPTR, ir.OVARDEF, ir.OVARKILL, ir.OVARLIVE:
+ return n.Left().HasCall()
+ case ir.ODOT, ir.ODOTMETH, ir.ODOTINTER:
+ return n.Left().HasCall()
+
+ case ir.OGETG, ir.OCLOSUREREAD, ir.OMETHEXPR:
+ return false
+
+ // TODO(rsc): These look wrong in various ways but are what calcHasCall has always done.
+ case ir.OADDSTR:
+ // TODO(rsc): This used to check left and right, which are not part of OADDSTR.
+ return false
+ case ir.OBLOCK:
+ // TODO(rsc): Surely the block's statements matter.
+ return false
+ case ir.OCONVIFACE, ir.OCONVNOP, ir.OBYTES2STR, ir.OBYTES2STRTMP, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2BYTESTMP, ir.OSTR2RUNES, ir.ORUNESTR:
+ // TODO(rsc): Some conversions are themselves calls, no?
+ return n.Left().HasCall()
+ case ir.ODOTTYPE2:
+ // TODO(rsc): Shouldn't this be up with ODOTTYPE above?
+ return n.Left().HasCall()
+ case ir.OSLICEHEADER:
+ // TODO(rsc): What about len and cap?
+ return n.Left().HasCall()
+ case ir.OAS2DOTTYPE, ir.OAS2FUNC:
+ // TODO(rsc): Surely we need to check List and Rlist.
+ return false
}
- return false
}
func badtype(op ir.Op, tl, tr *types.Type) {
case ir.ONAME, ir.OLITERAL, ir.ONIL:
return n
- case ir.ODOT, ir.OLEN, ir.OCAP:
+ case ir.OLEN, ir.OCAP:
+ l := safeexpr(n.Left(), init)
+ if l == n.Left() {
+ return n
+ }
+ a := ir.Copy(n).(*ir.UnaryExpr)
+ a.SetLeft(l)
+ return walkexpr(typecheck(a, ctxExpr), init)
+
+ case ir.ODOT, ir.ODOTPTR:
l := safeexpr(n.Left(), init)
if l == n.Left() {
return n
}
- r := ir.Copy(n)
- r.SetLeft(l)
- r = typecheck(r, ctxExpr)
- r = walkexpr(r, init)
- return r
+ a := ir.Copy(n).(*ir.SelectorExpr)
+ a.SetLeft(l)
+ return walkexpr(typecheck(a, ctxExpr), init)
- case ir.ODOTPTR, ir.ODEREF:
+ case ir.ODEREF:
l := safeexpr(n.Left(), init)
if l == n.Left() {
return n
}
- a := ir.Copy(n)
+ a := ir.Copy(n).(*ir.StarExpr)
a.SetLeft(l)
- a = walkexpr(a, init)
- return a
+ return walkexpr(typecheck(a, ctxExpr), init)
case ir.OINDEX, ir.OINDEXMAP:
l := safeexpr(n.Left(), init)
if l == n.Left() && r == n.Right() {
return n
}
- a := ir.Copy(n)
+ a := ir.Copy(n).(*ir.IndexExpr)
a.SetLeft(l)
a.SetRight(r)
- a = walkexpr(a, init)
- return a
+ return walkexpr(typecheck(a, ctxExpr), init)
case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT:
if isStaticCompositeLiteral(n) {
// find missing fields that
// will give shortest unique addressing.
// modify the tree with missing type names.
-func adddot(n ir.Node) ir.Node {
+func adddot(n *ir.SelectorExpr) *ir.SelectorExpr {
n.SetLeft(typecheck(n.Left(), ctxType|ctxExpr))
if n.Left().Diag() {
n.SetDiag(true)
case path != nil:
// rebuild elided dots
for c := len(path) - 1; c >= 0; c-- {
- n.SetLeft(nodSym(ir.ODOT, n.Left(), path[c].field.Sym))
- n.Left().SetImplicit(true)
+ dot := nodSym(ir.ODOT, n.Left(), path[c].field.Sym)
+ dot.SetImplicit(true)
+ n.SetLeft(dot)
}
case ambig:
base.Errorf("ambiguous selector %v", n)
// value for that function.
if !instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !isifacemethod(method.Type) && !(thearch.LinkArch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) {
// generate tail call: adjust pointer receiver and jump to embedded method.
- dot = dot.Left() // skip final .M
+ left := dot.Left() // skip final .M
// TODO(mdempsky): Remove dependency on dotlist.
if !dotlist[0].field.Type.IsPtr() {
- dot = nodAddr(dot)
+ left = ir.Nod(ir.OADDR, left, nil)
}
- as := ir.Nod(ir.OAS, nthis, convnop(dot, rcvr))
+ as := ir.Nod(ir.OAS, nthis, convnop(left, rcvr))
fn.PtrBody().Append(as)
fn.PtrBody().Append(nodSym(ir.ORETJMP, nil, methodSym(methodrcvr, method.Sym)))
} else {
}
if ir.MayBeShared(n) {
// Introduce OCONVNOP to hold init list.
- n = ir.Nod(ir.OCONVNOP, n, nil)
- n.SetType(n.Left().Type())
+ old := n
+ n = ir.Nod(ir.OCONVNOP, old, nil)
+ n.SetType(old.Type())
n.SetTypecheck(1)
}