mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.regabi] cmd/compile: arrange for walkstmt, walkexpr, to return from switch cases
Ending them in a returning switch makes it safe for each case to do an appropriate type assertion. Passes buildall w/ toolstash -cmp. Change-Id: I55d8f0a555006104164d84d27822aa8c5ad68515 Reviewed-on: https://go-review.googlesource.com/c/go/+/275882 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
4090af83c5
commit
0c49440664
1 changed files with 209 additions and 191 deletions
|
|
@ -123,6 +123,7 @@ func walkstmt(n ir.Node) ir.Node {
|
||||||
base.Errorf("%v is not a top level statement", n.Op())
|
base.Errorf("%v is not a top level statement", n.Op())
|
||||||
}
|
}
|
||||||
ir.Dump("nottop", n)
|
ir.Dump("nottop", n)
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OAS,
|
case ir.OAS,
|
||||||
ir.OASOP,
|
ir.OASOP,
|
||||||
|
|
@ -166,6 +167,7 @@ func walkstmt(n ir.Node) ir.Node {
|
||||||
n = ir.NewBlockStmt(n.Pos(), init.Slice())
|
n = ir.NewBlockStmt(n.Pos(), init.Slice())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return n
|
||||||
|
|
||||||
// special case for a receive where we throw away
|
// special case for a receive where we throw away
|
||||||
// the value received.
|
// the value received.
|
||||||
|
|
@ -179,8 +181,7 @@ func walkstmt(n ir.Node) ir.Node {
|
||||||
n.SetLeft(walkexpr(n.Left(), &init))
|
n.SetLeft(walkexpr(n.Left(), &init))
|
||||||
n = mkcall1(chanfn("chanrecv1", 2, n.Left().Type()), nil, &init, n.Left(), nodnil())
|
n = mkcall1(chanfn("chanrecv1", 2, n.Left().Type()), nil, &init, n.Left(), nodnil())
|
||||||
n = walkexpr(n, &init)
|
n = walkexpr(n, &init)
|
||||||
|
return initExpr(init.Slice(), n)
|
||||||
n = initExpr(init.Slice(), n)
|
|
||||||
|
|
||||||
case ir.OBREAK,
|
case ir.OBREAK,
|
||||||
ir.OCONTINUE,
|
ir.OCONTINUE,
|
||||||
|
|
@ -193,7 +194,7 @@ func walkstmt(n ir.Node) ir.Node {
|
||||||
ir.OVARDEF,
|
ir.OVARDEF,
|
||||||
ir.OVARKILL,
|
ir.OVARKILL,
|
||||||
ir.OVARLIVE:
|
ir.OVARLIVE:
|
||||||
break
|
return n
|
||||||
|
|
||||||
case ir.ODCL:
|
case ir.ODCL:
|
||||||
v := n.Left()
|
v := n.Left()
|
||||||
|
|
@ -209,12 +210,15 @@ func walkstmt(n ir.Node) ir.Node {
|
||||||
nn = typecheck(nn, ctxStmt)
|
nn = typecheck(nn, ctxStmt)
|
||||||
return walkstmt(nn)
|
return walkstmt(nn)
|
||||||
}
|
}
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OBLOCK:
|
case ir.OBLOCK:
|
||||||
walkstmtlist(n.List().Slice())
|
walkstmtlist(n.List().Slice())
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OCASE:
|
case ir.OCASE:
|
||||||
base.Errorf("case statement out of place")
|
base.Errorf("case statement out of place")
|
||||||
|
panic("unreachable")
|
||||||
|
|
||||||
case ir.ODEFER:
|
case ir.ODEFER:
|
||||||
Curfn.SetHasDefer(true)
|
Curfn.SetHasDefer(true)
|
||||||
|
|
@ -261,6 +265,7 @@ func walkstmt(n ir.Node) ir.Node {
|
||||||
init.Append(n)
|
init.Append(n)
|
||||||
n = ir.NewBlockStmt(n.Pos(), init.Slice())
|
n = ir.NewBlockStmt(n.Pos(), init.Slice())
|
||||||
}
|
}
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OFOR, ir.OFORUNTIL:
|
case ir.OFOR, ir.OFORUNTIL:
|
||||||
if n.Left() != nil {
|
if n.Left() != nil {
|
||||||
|
|
@ -276,16 +281,18 @@ func walkstmt(n ir.Node) ir.Node {
|
||||||
walkstmtlist(n.List().Slice())
|
walkstmtlist(n.List().Slice())
|
||||||
}
|
}
|
||||||
walkstmtlist(n.Body().Slice())
|
walkstmtlist(n.Body().Slice())
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OIF:
|
case ir.OIF:
|
||||||
n.SetLeft(walkexpr(n.Left(), n.PtrInit()))
|
n.SetLeft(walkexpr(n.Left(), n.PtrInit()))
|
||||||
walkstmtlist(n.Body().Slice())
|
walkstmtlist(n.Body().Slice())
|
||||||
walkstmtlist(n.Rlist().Slice())
|
walkstmtlist(n.Rlist().Slice())
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.ORETURN:
|
case ir.ORETURN:
|
||||||
Curfn.NumReturns++
|
Curfn.NumReturns++
|
||||||
if n.List().Len() == 0 {
|
if n.List().Len() == 0 {
|
||||||
break
|
return n
|
||||||
}
|
}
|
||||||
if (hasNamedResults(Curfn) && n.List().Len() > 1) || paramoutheap(Curfn) {
|
if (hasNamedResults(Curfn) && n.List().Len() > 1) || paramoutheap(Curfn) {
|
||||||
// assign to the function out parameters,
|
// assign to the function out parameters,
|
||||||
|
|
@ -317,7 +324,7 @@ func walkstmt(n ir.Node) ir.Node {
|
||||||
|
|
||||||
ll := ascompatee(n.Op(), rl, n.List().Slice(), n.PtrInit())
|
ll := ascompatee(n.Op(), rl, n.List().Slice(), n.PtrInit())
|
||||||
n.PtrList().Set(reorder3(ll))
|
n.PtrList().Set(reorder3(ll))
|
||||||
break
|
return n
|
||||||
}
|
}
|
||||||
walkexprlist(n.List().Slice(), n.PtrInit())
|
walkexprlist(n.List().Slice(), n.PtrInit())
|
||||||
|
|
||||||
|
|
@ -334,27 +341,29 @@ func walkstmt(n ir.Node) ir.Node {
|
||||||
res[i] = convas(a, n.PtrInit())
|
res[i] = convas(a, n.PtrInit())
|
||||||
}
|
}
|
||||||
n.PtrList().Set(res)
|
n.PtrList().Set(res)
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.ORETJMP:
|
case ir.ORETJMP:
|
||||||
break
|
return n
|
||||||
|
|
||||||
case ir.OINLMARK:
|
case ir.OINLMARK:
|
||||||
break
|
return n
|
||||||
|
|
||||||
case ir.OSELECT:
|
case ir.OSELECT:
|
||||||
walkselect(n)
|
walkselect(n)
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OSWITCH:
|
case ir.OSWITCH:
|
||||||
walkswitch(n)
|
walkswitch(n)
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.ORANGE:
|
case ir.ORANGE:
|
||||||
n = walkrange(n)
|
return walkrange(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Op() == ir.ONAME {
|
// No return! Each case must return (or panic),
|
||||||
base.Fatalf("walkstmt ended up with name: %+v", n)
|
// to avoid confusion about what gets returned
|
||||||
}
|
// in the presence of type assertions.
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk the whole tree of the body of an
|
// walk the whole tree of the body of an
|
||||||
|
|
@ -477,31 +486,68 @@ func walkexpr(n ir.Node, init *ir.Nodes) ir.Node {
|
||||||
return nn
|
return nn
|
||||||
}
|
}
|
||||||
|
|
||||||
opswitch:
|
n = walkexpr1(n, init)
|
||||||
|
|
||||||
|
// Expressions that are constant at run time but not
|
||||||
|
// considered const by the language spec are not turned into
|
||||||
|
// constants until walk. For example, if n is y%1 == 0, the
|
||||||
|
// walk of y%1 may have replaced it by 0.
|
||||||
|
// Check whether n with its updated args is itself now a constant.
|
||||||
|
t := n.Type()
|
||||||
|
n = evalConst(n)
|
||||||
|
if n.Type() != t {
|
||||||
|
base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type())
|
||||||
|
}
|
||||||
|
if n.Op() == ir.OLITERAL {
|
||||||
|
n = typecheck(n, ctxExpr)
|
||||||
|
// Emit string symbol now to avoid emitting
|
||||||
|
// any concurrently during the backend.
|
||||||
|
if v := n.Val(); v.Kind() == constant.String {
|
||||||
|
_ = stringsym(n.Pos(), constant.StringVal(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHasCall(n)
|
||||||
|
|
||||||
|
if base.Flag.LowerW != 0 && n != nil {
|
||||||
|
ir.Dump("after walk expr", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Pos = lno
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func walkexpr1(n ir.Node, init *ir.Nodes) ir.Node {
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
default:
|
default:
|
||||||
ir.Dump("walk", n)
|
ir.Dump("walk", n)
|
||||||
base.Fatalf("walkexpr: switch 1 unknown op %+v", n.Op())
|
base.Fatalf("walkexpr: switch 1 unknown op %+v", n.Op())
|
||||||
|
panic("unreachable")
|
||||||
|
|
||||||
case ir.ONONAME, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR:
|
case ir.ONONAME, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR:
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL:
|
case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL:
|
||||||
// TODO(mdempsky): Just return n; see discussion on CL 38655.
|
// TODO(mdempsky): Just return n; see discussion on CL 38655.
|
||||||
// Perhaps refactor to use Node.mayBeShared for these instead.
|
// Perhaps refactor to use Node.mayBeShared for these instead.
|
||||||
// If these return early, make sure to still call
|
// If these return early, make sure to still call
|
||||||
// stringsym for constant strings.
|
// stringsym for constant strings.
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.ONOT, ir.ONEG, ir.OPLUS, ir.OBITNOT, ir.OREAL, ir.OIMAG, ir.ODOTMETH, ir.ODOTINTER,
|
case ir.ONOT, ir.ONEG, ir.OPLUS, ir.OBITNOT, ir.OREAL, ir.OIMAG, ir.ODOTMETH, ir.ODOTINTER,
|
||||||
ir.ODEREF, ir.OSPTR, ir.OITAB, ir.OIDATA, ir.OADDR:
|
ir.ODEREF, ir.OSPTR, ir.OITAB, ir.OIDATA, ir.OADDR:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OEFACE, ir.OAND, ir.OANDNOT, ir.OSUB, ir.OMUL, ir.OADD, ir.OOR, ir.OXOR, ir.OLSH, ir.ORSH:
|
case ir.OEFACE, ir.OAND, ir.OANDNOT, ir.OSUB, ir.OMUL, ir.OADD, ir.OOR, ir.OXOR, ir.OLSH, ir.ORSH:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
n.SetRight(walkexpr(n.Right(), init))
|
n.SetRight(walkexpr(n.Right(), init))
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.ODOT, ir.ODOTPTR:
|
case ir.ODOT, ir.ODOTPTR:
|
||||||
usefield(n)
|
usefield(n)
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.ODOTTYPE, ir.ODOTTYPE2:
|
case ir.ODOTTYPE, ir.ODOTTYPE2:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
|
@ -513,12 +559,12 @@ opswitch:
|
||||||
if !n.Type().IsInterface() && !n.Left().Type().IsEmptyInterface() {
|
if !n.Type().IsInterface() && !n.Left().Type().IsEmptyInterface() {
|
||||||
n.PtrList().Set1(itabname(n.Type(), n.Left().Type()))
|
n.PtrList().Set1(itabname(n.Type(), n.Left().Type()))
|
||||||
}
|
}
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OLEN, ir.OCAP:
|
case ir.OLEN, ir.OCAP:
|
||||||
if isRuneCount(n) {
|
if isRuneCount(n) {
|
||||||
// Replace len([]rune(string)) with runtime.countrunes(string).
|
// Replace len([]rune(string)) with runtime.countrunes(string).
|
||||||
n = mkcall("countrunes", n.Type(), init, conv(n.Left().Left(), types.Types[types.TSTRING]))
|
return mkcall("countrunes", n.Type(), init, conv(n.Left().Left(), types.Types[types.TSTRING]))
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
|
@ -535,6 +581,7 @@ opswitch:
|
||||||
n = origIntConst(n, t.NumElem())
|
n = origIntConst(n, t.NumElem())
|
||||||
n.SetTypecheck(1)
|
n.SetTypecheck(1)
|
||||||
}
|
}
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OCOMPLEX:
|
case ir.OCOMPLEX:
|
||||||
// Use results from call expression as arguments for complex.
|
// Use results from call expression as arguments for complex.
|
||||||
|
|
@ -544,9 +591,10 @@ opswitch:
|
||||||
}
|
}
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
n.SetRight(walkexpr(n.Right(), init))
|
n.SetRight(walkexpr(n.Right(), init))
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
|
case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
|
||||||
n = walkcompare(n, init)
|
return walkcompare(n, init)
|
||||||
|
|
||||||
case ir.OANDAND, ir.OOROR:
|
case ir.OANDAND, ir.OOROR:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
|
@ -558,17 +606,19 @@ opswitch:
|
||||||
|
|
||||||
n.SetRight(walkexpr(n.Right(), &ll))
|
n.SetRight(walkexpr(n.Right(), &ll))
|
||||||
n.SetRight(initExpr(ll.Slice(), n.Right()))
|
n.SetRight(initExpr(ll.Slice(), n.Right()))
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OPRINT, ir.OPRINTN:
|
case ir.OPRINT, ir.OPRINTN:
|
||||||
n = walkprint(n, init)
|
return walkprint(n, init)
|
||||||
|
|
||||||
case ir.OPANIC:
|
case ir.OPANIC:
|
||||||
n = mkcall("gopanic", nil, init, n.Left())
|
return mkcall("gopanic", nil, init, n.Left())
|
||||||
|
|
||||||
case ir.ORECOVER:
|
case ir.ORECOVER:
|
||||||
n = mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil))
|
return mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil))
|
||||||
|
|
||||||
case ir.OCLOSUREREAD, ir.OCFUNC:
|
case ir.OCLOSUREREAD, ir.OCFUNC:
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH:
|
case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH:
|
||||||
if n.Op() == ir.OCALLINTER {
|
if n.Op() == ir.OCALLINTER {
|
||||||
|
|
@ -597,6 +647,7 @@ opswitch:
|
||||||
}
|
}
|
||||||
|
|
||||||
walkCall(n, init)
|
walkCall(n, init)
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OAS, ir.OASOP:
|
case ir.OAS, ir.OASOP:
|
||||||
init.AppendNodes(n.PtrInit())
|
init.AppendNodes(n.PtrInit())
|
||||||
|
|
@ -622,17 +673,16 @@ opswitch:
|
||||||
}
|
}
|
||||||
|
|
||||||
if oaslit(n, init) {
|
if oaslit(n, init) {
|
||||||
n = ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil)
|
return ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Right() == nil {
|
if n.Right() == nil {
|
||||||
// TODO(austin): Check all "implicit zeroing"
|
// TODO(austin): Check all "implicit zeroing"
|
||||||
break
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
if !instrumenting && isZero(n.Right()) {
|
if !instrumenting && isZero(n.Right()) {
|
||||||
break
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
switch n.Right().Op() {
|
switch n.Right().Op() {
|
||||||
|
|
@ -646,9 +696,7 @@ opswitch:
|
||||||
|
|
||||||
n1 := ir.Nod(ir.OADDR, n.Left(), nil)
|
n1 := ir.Nod(ir.OADDR, n.Left(), nil)
|
||||||
r := n.Right().Left() // the channel
|
r := n.Right().Left() // the channel
|
||||||
n = mkcall1(chanfn("chanrecv1", 2, r.Type()), nil, init, r, n1)
|
return mkcall1(chanfn("chanrecv1", 2, r.Type()), nil, init, r, n1)
|
||||||
n = walkexpr(n, init)
|
|
||||||
break opswitch
|
|
||||||
|
|
||||||
case ir.OAPPEND:
|
case ir.OAPPEND:
|
||||||
// x = append(...)
|
// x = append(...)
|
||||||
|
|
@ -671,7 +719,7 @@ opswitch:
|
||||||
// Do not add a new write barrier.
|
// Do not add a new write barrier.
|
||||||
// Set up address of type for back end.
|
// Set up address of type for back end.
|
||||||
r.SetLeft(typename(r.Type().Elem()))
|
r.SetLeft(typename(r.Type().Elem()))
|
||||||
break opswitch
|
return n
|
||||||
}
|
}
|
||||||
// Otherwise, lowered for race detector.
|
// Otherwise, lowered for race detector.
|
||||||
// Treat as ordinary assignment.
|
// Treat as ordinary assignment.
|
||||||
|
|
@ -680,6 +728,7 @@ opswitch:
|
||||||
if n.Left() != nil && n.Right() != nil {
|
if n.Left() != nil && n.Right() != nil {
|
||||||
n = convas(n, init)
|
n = convas(n, init)
|
||||||
}
|
}
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OAS2:
|
case ir.OAS2:
|
||||||
init.AppendNodes(n.PtrInit())
|
init.AppendNodes(n.PtrInit())
|
||||||
|
|
@ -687,7 +736,7 @@ opswitch:
|
||||||
walkexprlistsafe(n.Rlist().Slice(), init)
|
walkexprlistsafe(n.Rlist().Slice(), init)
|
||||||
ll := ascompatee(ir.OAS, n.List().Slice(), n.Rlist().Slice(), init)
|
ll := ascompatee(ir.OAS, n.List().Slice(), n.Rlist().Slice(), init)
|
||||||
ll = reorder3(ll)
|
ll = reorder3(ll)
|
||||||
n = liststmt(ll)
|
return liststmt(ll)
|
||||||
|
|
||||||
// a,b,... = fn()
|
// a,b,... = fn()
|
||||||
case ir.OAS2FUNC:
|
case ir.OAS2FUNC:
|
||||||
|
|
@ -699,12 +748,12 @@ opswitch:
|
||||||
|
|
||||||
if isIntrinsicCall(r) {
|
if isIntrinsicCall(r) {
|
||||||
n.PtrRlist().Set1(r)
|
n.PtrRlist().Set1(r)
|
||||||
break
|
return n
|
||||||
}
|
}
|
||||||
init.Append(r)
|
init.Append(r)
|
||||||
|
|
||||||
ll := ascompatet(n.List(), r.Type())
|
ll := ascompatet(n.List(), r.Type())
|
||||||
n = liststmt(ll)
|
return liststmt(ll)
|
||||||
|
|
||||||
// x, y = <-c
|
// x, y = <-c
|
||||||
// order.stmt made sure x is addressable or blank.
|
// order.stmt made sure x is addressable or blank.
|
||||||
|
|
@ -724,7 +773,7 @@ opswitch:
|
||||||
ok := n.List().Second()
|
ok := n.List().Second()
|
||||||
call := mkcall1(fn, types.Types[types.TBOOL], init, r.Left(), n1)
|
call := mkcall1(fn, types.Types[types.TBOOL], init, r.Left(), n1)
|
||||||
n = ir.Nod(ir.OAS, ok, call)
|
n = ir.Nod(ir.OAS, ok, call)
|
||||||
n = typecheck(n, ctxStmt)
|
return typecheck(n, ctxStmt)
|
||||||
|
|
||||||
// a,b = m[i]
|
// a,b = m[i]
|
||||||
case ir.OAS2MAPR:
|
case ir.OAS2MAPR:
|
||||||
|
|
@ -784,7 +833,7 @@ opswitch:
|
||||||
}
|
}
|
||||||
|
|
||||||
n = typecheck(n, ctxStmt)
|
n = typecheck(n, ctxStmt)
|
||||||
n = walkexpr(n, init)
|
return walkexpr(n, init)
|
||||||
|
|
||||||
case ir.ODELETE:
|
case ir.ODELETE:
|
||||||
init.AppendNodes(n.PtrInit())
|
init.AppendNodes(n.PtrInit())
|
||||||
|
|
@ -799,11 +848,12 @@ opswitch:
|
||||||
// order.stmt made sure key is addressable.
|
// order.stmt made sure key is addressable.
|
||||||
key = ir.Nod(ir.OADDR, key, nil)
|
key = ir.Nod(ir.OADDR, key, nil)
|
||||||
}
|
}
|
||||||
n = mkcall1(mapfndel(mapdelete[fast], t), nil, init, typename(t), map_, key)
|
return mkcall1(mapfndel(mapdelete[fast], t), nil, init, typename(t), map_, key)
|
||||||
|
|
||||||
case ir.OAS2DOTTYPE:
|
case ir.OAS2DOTTYPE:
|
||||||
walkexprlistsafe(n.List().Slice(), init)
|
walkexprlistsafe(n.List().Slice(), init)
|
||||||
n.PtrRlist().SetIndex(0, walkexpr(n.Rlist().First(), init))
|
n.PtrRlist().SetIndex(0, walkexpr(n.Rlist().First(), init))
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OCONVIFACE:
|
case ir.OCONVIFACE:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
|
@ -828,8 +878,7 @@ opswitch:
|
||||||
l := ir.Nod(ir.OEFACE, typeword(), n.Left())
|
l := ir.Nod(ir.OEFACE, typeword(), n.Left())
|
||||||
l.SetType(toType)
|
l.SetType(toType)
|
||||||
l.SetTypecheck(n.Typecheck())
|
l.SetTypecheck(n.Typecheck())
|
||||||
n = l
|
return l
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if staticuint64s == nil {
|
if staticuint64s == nil {
|
||||||
|
|
@ -878,8 +927,7 @@ opswitch:
|
||||||
l := ir.Nod(ir.OEFACE, typeword(), typecheck(ir.Nod(ir.OADDR, value, nil), ctxExpr))
|
l := ir.Nod(ir.OEFACE, typeword(), typecheck(ir.Nod(ir.OADDR, value, nil), ctxExpr))
|
||||||
l.SetType(toType)
|
l.SetType(toType)
|
||||||
l.SetTypecheck(n.Typecheck())
|
l.SetTypecheck(n.Typecheck())
|
||||||
n = l
|
return l
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement interface to empty interface conversion.
|
// Implement interface to empty interface conversion.
|
||||||
|
|
@ -906,8 +954,7 @@ opswitch:
|
||||||
e := ir.Nod(ir.OEFACE, tmp, ifaceData(n.Pos(), c, types.NewPtr(types.Types[types.TUINT8])))
|
e := ir.Nod(ir.OEFACE, tmp, ifaceData(n.Pos(), c, types.NewPtr(types.Types[types.TUINT8])))
|
||||||
e.SetType(toType) // assign type manually, typecheck doesn't understand OEFACE.
|
e.SetType(toType) // assign type manually, typecheck doesn't understand OEFACE.
|
||||||
e.SetTypecheck(1)
|
e.SetTypecheck(1)
|
||||||
n = e
|
return e
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fnname, needsaddr := convFuncName(fromType, toType)
|
fnname, needsaddr := convFuncName(fromType, toType)
|
||||||
|
|
@ -928,8 +975,7 @@ opswitch:
|
||||||
e := ir.Nod(ir.OEFACE, typeword(), call)
|
e := ir.Nod(ir.OEFACE, typeword(), call)
|
||||||
e.SetType(toType)
|
e.SetType(toType)
|
||||||
e.SetTypecheck(1)
|
e.SetTypecheck(1)
|
||||||
n = e
|
return e
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var tab ir.Node
|
var tab ir.Node
|
||||||
|
|
@ -962,7 +1008,7 @@ opswitch:
|
||||||
n = ir.Nod(ir.OCALL, fn, nil)
|
n = ir.Nod(ir.OCALL, fn, nil)
|
||||||
n.PtrList().Set2(tab, v)
|
n.PtrList().Set2(tab, v)
|
||||||
n = typecheck(n, ctxExpr)
|
n = typecheck(n, ctxExpr)
|
||||||
n = walkexpr(n, init)
|
return walkexpr(n, init)
|
||||||
|
|
||||||
case ir.OCONV, ir.OCONVNOP:
|
case ir.OCONV, ir.OCONVNOP:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
|
@ -971,20 +1017,18 @@ opswitch:
|
||||||
}
|
}
|
||||||
if n.Op() == ir.OCONVNOP && checkPtr(Curfn, 1) {
|
if n.Op() == ir.OCONVNOP && checkPtr(Curfn, 1) {
|
||||||
if n.Type().IsPtr() && n.Left().Type().IsUnsafePtr() { // unsafe.Pointer to *T
|
if n.Type().IsPtr() && n.Left().Type().IsUnsafePtr() { // unsafe.Pointer to *T
|
||||||
n = walkCheckPtrAlignment(n, init, nil)
|
return walkCheckPtrAlignment(n, init, nil)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
if n.Type().IsUnsafePtr() && n.Left().Type().IsUintptr() { // uintptr to unsafe.Pointer
|
if n.Type().IsUnsafePtr() && n.Left().Type().IsUintptr() { // uintptr to unsafe.Pointer
|
||||||
n = walkCheckPtrArithmetic(n, init)
|
return walkCheckPtrArithmetic(n, init)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
param, result := rtconvfn(n.Left().Type(), n.Type())
|
param, result := rtconvfn(n.Left().Type(), n.Type())
|
||||||
if param == types.Txxx {
|
if param == types.Txxx {
|
||||||
break
|
return n
|
||||||
}
|
}
|
||||||
fn := types.BasicTypeNames[param] + "to" + types.BasicTypeNames[result]
|
fn := types.BasicTypeNames[param] + "to" + types.BasicTypeNames[result]
|
||||||
n = conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type())
|
return conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type())
|
||||||
|
|
||||||
case ir.ODIV, ir.OMOD:
|
case ir.ODIV, ir.OMOD:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
|
@ -996,13 +1040,12 @@ opswitch:
|
||||||
if isComplex[et] && n.Op() == ir.ODIV {
|
if isComplex[et] && n.Op() == ir.ODIV {
|
||||||
t := n.Type()
|
t := n.Type()
|
||||||
n = mkcall("complex128div", types.Types[types.TCOMPLEX128], init, conv(n.Left(), types.Types[types.TCOMPLEX128]), conv(n.Right(), types.Types[types.TCOMPLEX128]))
|
n = mkcall("complex128div", types.Types[types.TCOMPLEX128], init, conv(n.Left(), types.Types[types.TCOMPLEX128]), conv(n.Right(), types.Types[types.TCOMPLEX128]))
|
||||||
n = conv(n, t)
|
return conv(n, t)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to do for float divisions.
|
// Nothing to do for float divisions.
|
||||||
if isFloat[et] {
|
if isFloat[et] {
|
||||||
break
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewrite 64-bit div and mod on 32-bit architectures.
|
// rewrite 64-bit div and mod on 32-bit architectures.
|
||||||
|
|
@ -1019,15 +1062,15 @@ opswitch:
|
||||||
c = -c
|
c = -c
|
||||||
}
|
}
|
||||||
if c != 0 && c&(c-1) == 0 {
|
if c != 0 && c&(c-1) == 0 {
|
||||||
break opswitch
|
return n
|
||||||
}
|
}
|
||||||
case types.TUINT64:
|
case types.TUINT64:
|
||||||
c := ir.Uint64Val(n.Right())
|
c := ir.Uint64Val(n.Right())
|
||||||
if c < 1<<16 {
|
if c < 1<<16 {
|
||||||
break opswitch
|
return n
|
||||||
}
|
}
|
||||||
if c != 0 && c&(c-1) == 0 {
|
if c != 0 && c&(c-1) == 0 {
|
||||||
break opswitch
|
return n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1042,8 +1085,9 @@ opswitch:
|
||||||
} else {
|
} else {
|
||||||
fn += "mod"
|
fn += "mod"
|
||||||
}
|
}
|
||||||
n = mkcall(fn, n.Type(), init, conv(n.Left(), types.Types[et]), conv(n.Right(), types.Types[et]))
|
return mkcall(fn, n.Type(), init, conv(n.Left(), types.Types[et]), conv(n.Right(), types.Types[et]))
|
||||||
}
|
}
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OINDEX:
|
case ir.OINDEX:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
|
@ -1057,7 +1101,7 @@ opswitch:
|
||||||
// if range of type cannot exceed static array bound,
|
// if range of type cannot exceed static array bound,
|
||||||
// disable bounds check.
|
// disable bounds check.
|
||||||
if n.Bounded() {
|
if n.Bounded() {
|
||||||
break
|
return n
|
||||||
}
|
}
|
||||||
t := n.Left().Type()
|
t := n.Left().Type()
|
||||||
if t != nil && t.IsPtr() {
|
if t != nil && t.IsPtr() {
|
||||||
|
|
@ -1086,6 +1130,7 @@ opswitch:
|
||||||
base.Errorf("index out of bounds")
|
base.Errorf("index out of bounds")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OINDEXMAP:
|
case ir.OINDEXMAP:
|
||||||
// Replace m[k] with *map{access1,assign}(maptype, m, &k)
|
// Replace m[k] with *map{access1,assign}(maptype, m, &k)
|
||||||
|
|
@ -1124,14 +1169,17 @@ opswitch:
|
||||||
n = ir.Nod(ir.ODEREF, n, nil)
|
n = ir.Nod(ir.ODEREF, n, nil)
|
||||||
n.SetType(t.Elem())
|
n.SetType(t.Elem())
|
||||||
n.SetTypecheck(1)
|
n.SetTypecheck(1)
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.ORECV:
|
case ir.ORECV:
|
||||||
base.Fatalf("walkexpr ORECV") // should see inside OAS only
|
base.Fatalf("walkexpr ORECV") // should see inside OAS only
|
||||||
|
panic("unreachable")
|
||||||
|
|
||||||
case ir.OSLICEHEADER:
|
case ir.OSLICEHEADER:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
n.List().SetFirst(walkexpr(n.List().First(), init))
|
n.List().SetFirst(walkexpr(n.List().First(), init))
|
||||||
n.List().SetSecond(walkexpr(n.List().Second(), init))
|
n.List().SetSecond(walkexpr(n.List().Second(), init))
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
|
case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
|
||||||
checkSlice := checkPtr(Curfn, 1) && n.Op() == ir.OSLICE3ARR && n.Left().Op() == ir.OCONVNOP && n.Left().Left().Type().IsUnsafePtr()
|
checkSlice := checkPtr(Curfn, 1) && n.Op() == ir.OSLICE3ARR && n.Left().Op() == ir.OCONVNOP && n.Left().Left().Type().IsUnsafePtr()
|
||||||
|
|
@ -1160,11 +1208,11 @@ opswitch:
|
||||||
} else {
|
} else {
|
||||||
n.SetOp(ir.OSLICEARR)
|
n.SetOp(ir.OSLICEARR)
|
||||||
}
|
}
|
||||||
n = reduceSlice(n)
|
return reduceSlice(n)
|
||||||
}
|
}
|
||||||
} else {
|
return n
|
||||||
n = reduceSlice(n)
|
|
||||||
}
|
}
|
||||||
|
return reduceSlice(n)
|
||||||
|
|
||||||
case ir.ONEW:
|
case ir.ONEW:
|
||||||
if n.Type().Elem().NotInHeap() {
|
if n.Type().Elem().NotInHeap() {
|
||||||
|
|
@ -1179,28 +1227,26 @@ opswitch:
|
||||||
r = typecheck(r, ctxStmt)
|
r = typecheck(r, ctxStmt)
|
||||||
init.Append(r)
|
init.Append(r)
|
||||||
r = ir.Nod(ir.OADDR, r.Left(), nil)
|
r = ir.Nod(ir.OADDR, r.Left(), nil)
|
||||||
r = typecheck(r, ctxExpr)
|
return typecheck(r, ctxExpr)
|
||||||
n = r
|
|
||||||
} else {
|
|
||||||
n = callnew(n.Type().Elem())
|
|
||||||
}
|
}
|
||||||
|
return callnew(n.Type().Elem())
|
||||||
|
|
||||||
case ir.OADDSTR:
|
case ir.OADDSTR:
|
||||||
n = addstr(n, init)
|
return addstr(n, init)
|
||||||
|
|
||||||
case ir.OAPPEND:
|
case ir.OAPPEND:
|
||||||
// order should make sure we only see OAS(node, OAPPEND), which we handle above.
|
// order should make sure we only see OAS(node, OAPPEND), which we handle above.
|
||||||
base.Fatalf("append outside assignment")
|
base.Fatalf("append outside assignment")
|
||||||
|
panic("unreachable")
|
||||||
|
|
||||||
case ir.OCOPY:
|
case ir.OCOPY:
|
||||||
n = copyany(n, init, instrumenting && !base.Flag.CompilingRuntime)
|
return copyany(n, init, instrumenting && !base.Flag.CompilingRuntime)
|
||||||
|
|
||||||
// cannot use chanfn - closechan takes any, not chan any
|
|
||||||
case ir.OCLOSE:
|
case ir.OCLOSE:
|
||||||
|
// cannot use chanfn - closechan takes any, not chan any
|
||||||
fn := syslook("closechan")
|
fn := syslook("closechan")
|
||||||
|
|
||||||
fn = substArgTypes(fn, n.Left().Type())
|
fn = substArgTypes(fn, n.Left().Type())
|
||||||
n = mkcall1(fn, nil, init, n.Left())
|
return mkcall1(fn, nil, init, n.Left())
|
||||||
|
|
||||||
case ir.OMAKECHAN:
|
case ir.OMAKECHAN:
|
||||||
// When size fits into int, use makechan instead of
|
// When size fits into int, use makechan instead of
|
||||||
|
|
@ -1217,7 +1263,7 @@ opswitch:
|
||||||
argtype = types.Types[types.TINT]
|
argtype = types.Types[types.TINT]
|
||||||
}
|
}
|
||||||
|
|
||||||
n = mkcall1(chanfn(fnname, 1, n.Type()), n.Type(), init, typename(n.Type()), conv(size, argtype))
|
return mkcall1(chanfn(fnname, 1, n.Type()), n.Type(), init, typename(n.Type()), conv(size, argtype))
|
||||||
|
|
||||||
case ir.OMAKEMAP:
|
case ir.OMAKEMAP:
|
||||||
t := n.Type()
|
t := n.Type()
|
||||||
|
|
@ -1294,15 +1340,15 @@ opswitch:
|
||||||
a = typecheck(a, ctxStmt)
|
a = typecheck(a, ctxStmt)
|
||||||
a = walkexpr(a, init)
|
a = walkexpr(a, init)
|
||||||
init.Append(a)
|
init.Append(a)
|
||||||
n = convnop(h, t)
|
return convnop(h, t)
|
||||||
} else {
|
}
|
||||||
// Call runtime.makehmap to allocate an
|
// Call runtime.makehmap to allocate an
|
||||||
// hmap on the heap and initialize hmap's hash0 field.
|
// hmap on the heap and initialize hmap's hash0 field.
|
||||||
fn := syslook("makemap_small")
|
fn := syslook("makemap_small")
|
||||||
fn = substArgTypes(fn, t.Key(), t.Elem())
|
fn = substArgTypes(fn, t.Key(), t.Elem())
|
||||||
n = mkcall1(fn, n.Type(), init)
|
return mkcall1(fn, n.Type(), init)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if n.Esc() != EscNone {
|
if n.Esc() != EscNone {
|
||||||
h = nodnil()
|
h = nodnil()
|
||||||
}
|
}
|
||||||
|
|
@ -1327,8 +1373,7 @@ opswitch:
|
||||||
|
|
||||||
fn := syslook(fnname)
|
fn := syslook(fnname)
|
||||||
fn = substArgTypes(fn, hmapType, t.Key(), t.Elem())
|
fn = substArgTypes(fn, hmapType, t.Key(), t.Elem())
|
||||||
n = mkcall1(fn, n.Type(), init, typename(n.Type()), conv(hint, argtype), h)
|
return mkcall1(fn, n.Type(), init, typename(n.Type()), conv(hint, argtype), h)
|
||||||
}
|
|
||||||
|
|
||||||
case ir.OMAKESLICE:
|
case ir.OMAKESLICE:
|
||||||
l := n.Left()
|
l := n.Left()
|
||||||
|
|
@ -1376,8 +1421,9 @@ opswitch:
|
||||||
r = conv(r, n.Type()) // in case n.Type is named.
|
r = conv(r, n.Type()) // in case n.Type is named.
|
||||||
r = typecheck(r, ctxExpr)
|
r = typecheck(r, ctxExpr)
|
||||||
r = walkexpr(r, init)
|
r = walkexpr(r, init)
|
||||||
n = r
|
return r
|
||||||
} else {
|
}
|
||||||
|
|
||||||
// n escapes; set up a call to makeslice.
|
// n escapes; set up a call to makeslice.
|
||||||
// When len and cap can fit into int, use makeslice instead of
|
// When len and cap can fit into int, use makeslice instead of
|
||||||
// makeslice64, which is faster and shorter on 32 bit platforms.
|
// makeslice64, which is faster and shorter on 32 bit platforms.
|
||||||
|
|
@ -1406,8 +1452,7 @@ opswitch:
|
||||||
|
|
||||||
m = typecheck(m, ctxExpr)
|
m = typecheck(m, ctxExpr)
|
||||||
m = walkexpr(m, init)
|
m = walkexpr(m, init)
|
||||||
n = m
|
return m
|
||||||
}
|
|
||||||
|
|
||||||
case ir.OMAKESLICECOPY:
|
case ir.OMAKESLICECOPY:
|
||||||
if n.Esc() == EscNone {
|
if n.Esc() == EscNone {
|
||||||
|
|
@ -1453,8 +1498,9 @@ opswitch:
|
||||||
ncopy = walkexpr(ncopy, init)
|
ncopy = walkexpr(ncopy, init)
|
||||||
init.Append(ncopy)
|
init.Append(ncopy)
|
||||||
|
|
||||||
n = s
|
return s
|
||||||
} else { // Replace make+copy with runtime.makeslicecopy.
|
}
|
||||||
|
// Replace make+copy with runtime.makeslicecopy.
|
||||||
// instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
|
// instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
|
||||||
fn := syslook("makeslicecopy")
|
fn := syslook("makeslicecopy")
|
||||||
s := ir.Nod(ir.OSLICEHEADER, nil, nil)
|
s := ir.Nod(ir.OSLICEHEADER, nil, nil)
|
||||||
|
|
@ -1463,8 +1509,7 @@ opswitch:
|
||||||
s.PtrList().Set2(length, length)
|
s.PtrList().Set2(length, length)
|
||||||
s.SetType(t)
|
s.SetType(t)
|
||||||
n = typecheck(s, ctxExpr)
|
n = typecheck(s, ctxExpr)
|
||||||
n = walkexpr(n, init)
|
return walkexpr(n, init)
|
||||||
}
|
|
||||||
|
|
||||||
case ir.ORUNESTR:
|
case ir.ORUNESTR:
|
||||||
a := nodnil()
|
a := nodnil()
|
||||||
|
|
@ -1473,7 +1518,7 @@ opswitch:
|
||||||
a = ir.Nod(ir.OADDR, temp(t), nil)
|
a = ir.Nod(ir.OADDR, temp(t), nil)
|
||||||
}
|
}
|
||||||
// intstring(*[4]byte, rune)
|
// intstring(*[4]byte, rune)
|
||||||
n = mkcall("intstring", n.Type(), init, a, conv(n.Left(), types.Types[types.TINT64]))
|
return mkcall("intstring", n.Type(), init, a, conv(n.Left(), types.Types[types.TINT64]))
|
||||||
|
|
||||||
case ir.OBYTES2STR, ir.ORUNES2STR:
|
case ir.OBYTES2STR, ir.ORUNES2STR:
|
||||||
a := nodnil()
|
a := nodnil()
|
||||||
|
|
@ -1484,25 +1529,24 @@ opswitch:
|
||||||
}
|
}
|
||||||
if n.Op() == ir.ORUNES2STR {
|
if n.Op() == ir.ORUNES2STR {
|
||||||
// slicerunetostring(*[32]byte, []rune) string
|
// slicerunetostring(*[32]byte, []rune) string
|
||||||
n = mkcall("slicerunetostring", n.Type(), init, a, n.Left())
|
return mkcall("slicerunetostring", n.Type(), init, a, n.Left())
|
||||||
} else {
|
}
|
||||||
// slicebytetostring(*[32]byte, ptr *byte, n int) string
|
// slicebytetostring(*[32]byte, ptr *byte, n int) string
|
||||||
n.SetLeft(cheapexpr(n.Left(), init))
|
n.SetLeft(cheapexpr(n.Left(), init))
|
||||||
ptr, len := backingArrayPtrLen(n.Left())
|
ptr, len := backingArrayPtrLen(n.Left())
|
||||||
n = mkcall("slicebytetostring", n.Type(), init, a, ptr, len)
|
return mkcall("slicebytetostring", n.Type(), init, a, ptr, len)
|
||||||
}
|
|
||||||
|
|
||||||
case ir.OBYTES2STRTMP:
|
case ir.OBYTES2STRTMP:
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
if !instrumenting {
|
if !instrumenting {
|
||||||
// Let the backend handle OBYTES2STRTMP directly
|
// Let the backend handle OBYTES2STRTMP directly
|
||||||
// to avoid a function call to slicebytetostringtmp.
|
// to avoid a function call to slicebytetostringtmp.
|
||||||
break
|
return n
|
||||||
}
|
}
|
||||||
// slicebytetostringtmp(ptr *byte, n int) string
|
// slicebytetostringtmp(ptr *byte, n int) string
|
||||||
n.SetLeft(cheapexpr(n.Left(), init))
|
n.SetLeft(cheapexpr(n.Left(), init))
|
||||||
ptr, len := backingArrayPtrLen(n.Left())
|
ptr, len := backingArrayPtrLen(n.Left())
|
||||||
n = mkcall("slicebytetostringtmp", n.Type(), init, ptr, len)
|
return mkcall("slicebytetostringtmp", n.Type(), init, ptr, len)
|
||||||
|
|
||||||
case ir.OSTR2BYTES:
|
case ir.OSTR2BYTES:
|
||||||
s := n.Left()
|
s := n.Left()
|
||||||
|
|
@ -1534,8 +1578,7 @@ opswitch:
|
||||||
slice := ir.NodAt(n.Pos(), ir.OSLICEARR, p, nil)
|
slice := ir.NodAt(n.Pos(), ir.OSLICEARR, p, nil)
|
||||||
slice.SetType(n.Type())
|
slice.SetType(n.Type())
|
||||||
slice.SetTypecheck(1)
|
slice.SetTypecheck(1)
|
||||||
n = walkexpr(slice, init)
|
return walkexpr(slice, init)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a := nodnil()
|
a := nodnil()
|
||||||
|
|
@ -1545,7 +1588,7 @@ opswitch:
|
||||||
a = ir.Nod(ir.OADDR, temp(t), nil)
|
a = ir.Nod(ir.OADDR, temp(t), nil)
|
||||||
}
|
}
|
||||||
// stringtoslicebyte(*32[byte], string) []byte
|
// stringtoslicebyte(*32[byte], string) []byte
|
||||||
n = mkcall("stringtoslicebyte", n.Type(), init, a, conv(s, types.Types[types.TSTRING]))
|
return mkcall("stringtoslicebyte", n.Type(), init, a, conv(s, types.Types[types.TSTRING]))
|
||||||
|
|
||||||
case ir.OSTR2BYTESTMP:
|
case ir.OSTR2BYTESTMP:
|
||||||
// []byte(string) conversion that creates a slice
|
// []byte(string) conversion that creates a slice
|
||||||
|
|
@ -1556,6 +1599,7 @@ opswitch:
|
||||||
// The only such case today is:
|
// The only such case today is:
|
||||||
// for i, c := range []byte(string)
|
// for i, c := range []byte(string)
|
||||||
n.SetLeft(walkexpr(n.Left(), init))
|
n.SetLeft(walkexpr(n.Left(), init))
|
||||||
|
return n
|
||||||
|
|
||||||
case ir.OSTR2RUNES:
|
case ir.OSTR2RUNES:
|
||||||
a := nodnil()
|
a := nodnil()
|
||||||
|
|
@ -1565,7 +1609,7 @@ opswitch:
|
||||||
a = ir.Nod(ir.OADDR, temp(t), nil)
|
a = ir.Nod(ir.OADDR, temp(t), nil)
|
||||||
}
|
}
|
||||||
// stringtoslicerune(*[32]rune, string) []rune
|
// stringtoslicerune(*[32]rune, string) []rune
|
||||||
n = mkcall("stringtoslicerune", n.Type(), init, a, conv(n.Left(), types.Types[types.TSTRING]))
|
return mkcall("stringtoslicerune", n.Type(), init, a, conv(n.Left(), types.Types[types.TSTRING]))
|
||||||
|
|
||||||
case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT, ir.OPTRLIT:
|
case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT, ir.OPTRLIT:
|
||||||
if isStaticCompositeLiteral(n) && !canSSAType(n.Type()) {
|
if isStaticCompositeLiteral(n) && !canSSAType(n.Type()) {
|
||||||
|
|
@ -1573,55 +1617,29 @@ opswitch:
|
||||||
// Make direct reference to the static data. See issue 12841.
|
// Make direct reference to the static data. See issue 12841.
|
||||||
vstat := readonlystaticname(n.Type())
|
vstat := readonlystaticname(n.Type())
|
||||||
fixedlit(inInitFunction, initKindStatic, n, vstat, init)
|
fixedlit(inInitFunction, initKindStatic, n, vstat, init)
|
||||||
n = vstat
|
return typecheck(vstat, ctxExpr)
|
||||||
n = typecheck(n, ctxExpr)
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
var_ := temp(n.Type())
|
var_ := temp(n.Type())
|
||||||
anylit(n, var_, init)
|
anylit(n, var_, init)
|
||||||
n = var_
|
return var_
|
||||||
|
|
||||||
case ir.OSEND:
|
case ir.OSEND:
|
||||||
n1 := n.Right()
|
n1 := n.Right()
|
||||||
n1 = assignconv(n1, n.Left().Type().Elem(), "chan send")
|
n1 = assignconv(n1, n.Left().Type().Elem(), "chan send")
|
||||||
n1 = walkexpr(n1, init)
|
n1 = walkexpr(n1, init)
|
||||||
n1 = ir.Nod(ir.OADDR, n1, nil)
|
n1 = ir.Nod(ir.OADDR, n1, nil)
|
||||||
n = mkcall1(chanfn("chansend1", 2, n.Left().Type()), nil, init, n.Left(), n1)
|
return mkcall1(chanfn("chansend1", 2, n.Left().Type()), nil, init, n.Left(), n1)
|
||||||
|
|
||||||
case ir.OCLOSURE:
|
case ir.OCLOSURE:
|
||||||
n = walkclosure(n, init)
|
return walkclosure(n, init)
|
||||||
|
|
||||||
case ir.OCALLPART:
|
case ir.OCALLPART:
|
||||||
n = walkpartialcall(n.(*ir.CallPartExpr), init)
|
return walkpartialcall(n.(*ir.CallPartExpr), init)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expressions that are constant at run time but not
|
// No return! Each case must return (or panic),
|
||||||
// considered const by the language spec are not turned into
|
// to avoid confusion about what gets returned
|
||||||
// constants until walk. For example, if n is y%1 == 0, the
|
// in the presence of type assertions.
|
||||||
// walk of y%1 may have replaced it by 0.
|
|
||||||
// Check whether n with its updated args is itself now a constant.
|
|
||||||
t := n.Type()
|
|
||||||
n = evalConst(n)
|
|
||||||
if n.Type() != t {
|
|
||||||
base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type())
|
|
||||||
}
|
|
||||||
if n.Op() == ir.OLITERAL {
|
|
||||||
n = typecheck(n, ctxExpr)
|
|
||||||
// Emit string symbol now to avoid emitting
|
|
||||||
// any concurrently during the backend.
|
|
||||||
if v := n.Val(); v.Kind() == constant.String {
|
|
||||||
_ = stringsym(n.Pos(), constant.StringVal(v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateHasCall(n)
|
|
||||||
|
|
||||||
if base.Flag.LowerW != 0 && n != nil {
|
|
||||||
ir.Dump("after walk expr", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Pos = lno
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// markTypeUsedInInterface marks that type t is converted to an interface.
|
// markTypeUsedInInterface marks that type t is converted to an interface.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue