Commit 9e902f0f authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/compile: generalize racewalk to instrument (naming change)

This is mechanical change that is a step toward reusing the racewalk
pass for a more general instrumentation pass.  The first use will be to
add support for the memory sanitizer.

Change-Id: I75b93b814ac60c1db1660e0b9a9a7d7977d86939
Reviewed-on: https://go-review.googlesource.com/16105Reviewed-by: 's avatarHyang-Ah Hana Kim <hyangah@gmail.com>
Reviewed-by: 's avatarDavid Crawshaw <crawshaw@golang.org>
parent 76dcedc9
...@@ -647,6 +647,10 @@ var flag_race int ...@@ -647,6 +647,10 @@ var flag_race int
var flag_largemodel int var flag_largemodel int
// Whether we are adding any sort of code instrumentation, such as
// when the race detector is enabled.
var instrumenting bool
// Pending annotations for next func declaration. // Pending annotations for next func declaration.
var ( var (
noescape bool noescape bool
......
...@@ -124,13 +124,13 @@ func caninl(fn *Node) { ...@@ -124,13 +124,13 @@ func caninl(fn *Node) {
} }
} }
// Runtime package must not be race instrumented. // Runtime package must not be instrumented.
// Racewalk skips runtime package. However, some runtime code can be // Instrument skips runtime package. However, some runtime code can be
// inlined into other packages and instrumented there. To avoid this, // inlined into other packages and instrumented there. To avoid this,
// we disable inlining of runtime functions in race mode. // we disable inlining of runtime functions when instrumenting.
// The example that we observed is inlining of LockOSThread, // The example that we observed is inlining of LockOSThread,
// which lead to false race reports on m contents. // which lead to false race reports on m contents.
if flag_race != 0 && myimportpath == "runtime" { if instrumenting && myimportpath == "runtime" {
return return
} }
......
...@@ -249,6 +249,7 @@ func Main() { ...@@ -249,6 +249,7 @@ func Main() {
if flag_race != 0 { if flag_race != 0 {
racepkg = mkpkg("runtime/race") racepkg = mkpkg("runtime/race")
racepkg.Name = "race" racepkg.Name = "race"
instrumenting = true
} }
// parse -d argument // parse -d argument
......
...@@ -434,7 +434,7 @@ func ordermapassign(n *Node, order *Order) { ...@@ -434,7 +434,7 @@ func ordermapassign(n *Node, order *Order) {
a = Nod(OAS, m, l.N) a = Nod(OAS, m, l.N)
typecheck(&a, Etop) typecheck(&a, Etop)
post = list(post, a) post = list(post, a)
} else if flag_race != 0 && n.Op == OAS2FUNC && !isblank(l.N) { } else if instrumenting && n.Op == OAS2FUNC && !isblank(l.N) {
m = l.N m = l.N
l.N = ordertemp(m.Type, order, false) l.N = ordertemp(m.Type, order, false)
a = Nod(OAS, m, l.N) a = Nod(OAS, m, l.N)
...@@ -1093,7 +1093,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1093,7 +1093,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
OREAL, OREAL,
ORECOVER: ORECOVER:
ordercall(n, order) ordercall(n, order)
if lhs == nil || lhs.Op != ONAME || flag_race != 0 { if lhs == nil || lhs.Op != ONAME || instrumenting {
n = ordercopyexpr(n, n.Type, order, 0) n = ordercopyexpr(n, n.Type, order, 0)
} }
...@@ -1153,7 +1153,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) { ...@@ -1153,7 +1153,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
// TODO(rsc): The Isfat is for consistency with componentgen and walkexpr. // TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
// It needs to be removed in all three places. // It needs to be removed in all three places.
// That would allow inlining x.(struct{*int}) the same as x.(*int). // That would allow inlining x.(struct{*int}) the same as x.(*int).
if !isdirectiface(n.Type) || Isfat(n.Type) || flag_race != 0 { if !isdirectiface(n.Type) || Isfat(n.Type) || instrumenting {
n = ordercopyexpr(n, n.Type, order, 1) n = ordercopyexpr(n, n.Type, order, 1)
} }
......
...@@ -399,8 +399,8 @@ func compile(fn *Node) { ...@@ -399,8 +399,8 @@ func compile(fn *Node) {
if nerrors != 0 { if nerrors != 0 {
goto ret goto ret
} }
if flag_race != 0 { if instrumenting {
racewalk(Curfn) instrument(Curfn)
} }
if nerrors != 0 { if nerrors != 0 {
goto ret goto ret
......
...@@ -9,7 +9,9 @@ import ( ...@@ -9,7 +9,9 @@ import (
"strings" "strings"
) )
// The racewalk pass modifies the code tree for the function as follows: // The instrument pass modifies the code tree for instrumentation.
//
// For flag_race it modifies the function as follows:
// //
// 1. It inserts a call to racefuncenter at the beginning of each function. // 1. It inserts a call to racefuncenter at the beginning of each function.
// 2. It inserts a call to racefuncexit at the end of each function. // 2. It inserts a call to racefuncexit at the end of each function.
...@@ -42,16 +44,16 @@ func ispkgin(pkgs []string) bool { ...@@ -42,16 +44,16 @@ func ispkgin(pkgs []string) bool {
return false return false
} }
func racewalk(fn *Node) { func instrument(fn *Node) {
if ispkgin(omit_pkgs) || fn.Func.Norace { if ispkgin(omit_pkgs) || fn.Func.Norace {
return return
} }
if !ispkgin(noinst_pkgs) { if !ispkgin(noinst_pkgs) {
racewalklist(fn.Nbody, nil) instrumentlist(fn.Nbody, nil)
// nothing interesting for race detector in fn->enter // nothing interesting for race detector in fn->enter
racewalklist(fn.Func.Exit, nil) instrumentlist(fn.Func.Exit, nil)
} }
// nodpc is the PC of the caller as extracted by // nodpc is the PC of the caller as extracted by
...@@ -68,7 +70,7 @@ func racewalk(fn *Node) { ...@@ -68,7 +70,7 @@ func racewalk(fn *Node) {
fn.Func.Exit = list(fn.Func.Exit, nd) fn.Func.Exit = list(fn.Func.Exit, nd)
if Debug['W'] != 0 { if Debug['W'] != 0 {
s := fmt.Sprintf("after racewalk %v", fn.Func.Nname.Sym) s := fmt.Sprintf("after instrument %v", fn.Func.Nname.Sym)
dumplist(s, fn.Nbody) dumplist(s, fn.Nbody)
s = fmt.Sprintf("enter %v", fn.Func.Nname.Sym) s = fmt.Sprintf("enter %v", fn.Func.Nname.Sym)
dumplist(s, fn.Func.Enter) dumplist(s, fn.Func.Enter)
...@@ -77,12 +79,12 @@ func racewalk(fn *Node) { ...@@ -77,12 +79,12 @@ func racewalk(fn *Node) {
} }
} }
func racewalklist(l *NodeList, init **NodeList) { func instrumentlist(l *NodeList, init **NodeList) {
var instr *NodeList var instr *NodeList
for ; l != nil; l = l.Next { for ; l != nil; l = l.Next {
instr = nil instr = nil
racewalknode(&l.N, &instr, 0, 0) instrumentnode(&l.N, &instr, 0, 0)
if init == nil { if init == nil {
l.N.Ninit = concat(l.N.Ninit, instr) l.N.Ninit = concat(l.N.Ninit, instr)
} else { } else {
...@@ -94,7 +96,7 @@ func racewalklist(l *NodeList, init **NodeList) { ...@@ -94,7 +96,7 @@ func racewalklist(l *NodeList, init **NodeList) {
// walkexpr and walkstmt combined // walkexpr and walkstmt combined
// walks the tree and adds calls to the // walks the tree and adds calls to the
// instrumentation code to top-level (statement) nodes' init // instrumentation code to top-level (statement) nodes' init
func racewalknode(np **Node, init **NodeList, wr int, skip int) { func instrumentnode(np **Node, init **NodeList, wr int, skip int) {
n := *np n := *np
if n == nil { if n == nil {
...@@ -102,35 +104,35 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) { ...@@ -102,35 +104,35 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
} }
if Debug['w'] > 1 { if Debug['w'] > 1 {
Dump("racewalk-before", n) Dump("instrument-before", n)
} }
setlineno(n) setlineno(n)
if init == nil { if init == nil {
Fatalf("racewalk: bad init list") Fatalf("instrument: bad init list")
} }
if init == &n.Ninit { if init == &n.Ninit {
// If init == &n->ninit and n->ninit is non-nil, // If init == &n->ninit and n->ninit is non-nil,
// racewalknode might append it to itself. // instrumentnode might append it to itself.
// nil it out and handle it separately before putting it back. // nil it out and handle it separately before putting it back.
l := n.Ninit l := n.Ninit
n.Ninit = nil n.Ninit = nil
racewalklist(l, nil) instrumentlist(l, nil)
racewalknode(&n, &l, wr, skip) // recurse with nil n->ninit instrumentnode(&n, &l, wr, skip) // recurse with nil n->ninit
appendinit(&n, l) appendinit(&n, l)
*np = n *np = n
return return
} }
racewalklist(n.Ninit, nil) instrumentlist(n.Ninit, nil)
switch n.Op { switch n.Op {
default: default:
Fatalf("racewalk: unknown node type %v", Oconv(int(n.Op), 0)) Fatalf("instrument: unknown node type %v", Oconv(int(n.Op), 0))
case OAS, OASWB, OAS2FUNC: case OAS, OASWB, OAS2FUNC:
racewalknode(&n.Left, init, 1, 0) instrumentnode(&n.Left, init, 1, 0)
racewalknode(&n.Right, init, 0, 0) instrumentnode(&n.Right, init, 0, 0)
goto ret goto ret
// can't matter // can't matter
...@@ -142,7 +144,7 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) { ...@@ -142,7 +144,7 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
for l := n.List; l != nil; l = l.Next { for l := n.List; l != nil; l = l.Next {
switch l.N.Op { switch l.N.Op {
case OCALLFUNC, OCALLMETH, OCALLINTER: case OCALLFUNC, OCALLMETH, OCALLINTER:
racewalknode(&l.N, &out, 0, 0) instrumentnode(&l.N, &out, 0, 0)
out = list(out, l.N) out = list(out, l.N)
// Scan past OAS nodes copying results off stack. // Scan past OAS nodes copying results off stack.
// Those must not be instrumented, because the // Those must not be instrumented, because the
...@@ -154,7 +156,7 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) { ...@@ -154,7 +156,7 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
out = list(out, l.N) out = list(out, l.N)
} }
default: default:
racewalknode(&l.N, &out, 0, 0) instrumentnode(&l.N, &out, 0, 0)
out = list(out, l.N) out = list(out, l.N)
} }
} }
...@@ -162,22 +164,22 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) { ...@@ -162,22 +164,22 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
goto ret goto ret
case ODEFER: case ODEFER:
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
goto ret goto ret
case OPROC: case OPROC:
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
goto ret goto ret
case OCALLINTER: case OCALLINTER:
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
goto ret goto ret
// Instrument dst argument of runtime.writebarrier* calls // Instrument dst argument of runtime.writebarrier* calls
// as we do not instrument runtime code. // as we do not instrument runtime code.
// typedslicecopy is instrumented in runtime. // typedslicecopy is instrumented in runtime.
case OCALLFUNC: case OCALLFUNC:
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
goto ret goto ret
case ONOT, case ONOT,
...@@ -187,32 +189,32 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) { ...@@ -187,32 +189,32 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
OIMAG, OIMAG,
OCOM, OCOM,
OSQRT: OSQRT:
racewalknode(&n.Left, init, wr, 0) instrumentnode(&n.Left, init, wr, 0)
goto ret goto ret
case ODOTINTER: case ODOTINTER:
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
goto ret goto ret
case ODOT: case ODOT:
racewalknode(&n.Left, init, 0, 1) instrumentnode(&n.Left, init, 0, 1)
callinstr(&n, init, wr, skip) callinstr(&n, init, wr, skip)
goto ret goto ret
case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
callinstr(&n, init, wr, skip) callinstr(&n, init, wr, skip)
goto ret goto ret
case OIND: // *p case OIND: // *p
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
callinstr(&n, init, wr, skip) callinstr(&n, init, wr, skip)
goto ret goto ret
case OSPTR, OLEN, OCAP: case OSPTR, OLEN, OCAP:
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
if Istype(n.Left.Type, TMAP) { if Istype(n.Left.Type, TMAP) {
n1 := Nod(OCONVNOP, n.Left, nil) n1 := Nod(OCONVNOP, n.Left, nil)
n1.Type = Ptrto(Types[TUINT8]) n1.Type = Ptrto(Types[TUINT8])
...@@ -241,18 +243,18 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) { ...@@ -241,18 +243,18 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
OGT, OGT,
OADD, OADD,
OCOMPLEX: OCOMPLEX:
racewalknode(&n.Left, init, wr, 0) instrumentnode(&n.Left, init, wr, 0)
racewalknode(&n.Right, init, wr, 0) instrumentnode(&n.Right, init, wr, 0)
goto ret goto ret
case OANDAND, OOROR: case OANDAND, OOROR:
racewalknode(&n.Left, init, wr, 0) instrumentnode(&n.Left, init, wr, 0)
// walk has ensured the node has moved to a location where // walk has ensured the node has moved to a location where
// side effects are safe. // side effects are safe.
// n->right may not be executed, // n->right may not be executed,
// so instrumentation goes to n->right->ninit, not init. // so instrumentation goes to n->right->ninit, not init.
racewalknode(&n.Right, &n.Right.Ninit, wr, 0) instrumentnode(&n.Right, &n.Right.Ninit, wr, 0)
goto ret goto ret
...@@ -261,57 +263,57 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) { ...@@ -261,57 +263,57 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
goto ret goto ret
case OCONV: case OCONV:
racewalknode(&n.Left, init, wr, 0) instrumentnode(&n.Left, init, wr, 0)
goto ret goto ret
case OCONVNOP: case OCONVNOP:
racewalknode(&n.Left, init, wr, 0) instrumentnode(&n.Left, init, wr, 0)
goto ret goto ret
case ODIV, OMOD: case ODIV, OMOD:
racewalknode(&n.Left, init, wr, 0) instrumentnode(&n.Left, init, wr, 0)
racewalknode(&n.Right, init, wr, 0) instrumentnode(&n.Right, init, wr, 0)
goto ret goto ret
case OINDEX: case OINDEX:
if !Isfixedarray(n.Left.Type) { if !Isfixedarray(n.Left.Type) {
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
} else if !islvalue(n.Left) { } else if !islvalue(n.Left) {
// index of unaddressable array, like Map[k][i]. // index of unaddressable array, like Map[k][i].
racewalknode(&n.Left, init, wr, 0) instrumentnode(&n.Left, init, wr, 0)
racewalknode(&n.Right, init, 0, 0) instrumentnode(&n.Right, init, 0, 0)
goto ret goto ret
} }
racewalknode(&n.Right, init, 0, 0) instrumentnode(&n.Right, init, 0, 0)
if n.Left.Type.Etype != TSTRING { if n.Left.Type.Etype != TSTRING {
callinstr(&n, init, wr, skip) callinstr(&n, init, wr, skip)
} }
goto ret goto ret
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR: case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR:
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
racewalknode(&n.Right, init, 0, 0) instrumentnode(&n.Right, init, 0, 0)
goto ret goto ret
case OKEY: case OKEY:
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
racewalknode(&n.Right, init, 0, 0) instrumentnode(&n.Right, init, 0, 0)
goto ret goto ret
case OADDR: case OADDR:
racewalknode(&n.Left, init, 0, 1) instrumentnode(&n.Left, init, 0, 1)
goto ret goto ret
// n->left is Type* which is not interesting. // n->left is Type* which is not interesting.
case OEFACE: case OEFACE:
racewalknode(&n.Right, init, 0, 0) instrumentnode(&n.Right, init, 0, 0)
goto ret goto ret
case OITAB: case OITAB:
racewalknode(&n.Left, init, 0, 0) instrumentnode(&n.Left, init, 0, 0)
goto ret goto ret
// should not appear in AST by now // should not appear in AST by now
...@@ -355,31 +357,31 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) { ...@@ -355,31 +357,31 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
OAS2RECV, OAS2RECV,
OAS2MAPR, OAS2MAPR,
OASOP: OASOP:
Yyerror("racewalk: %v must be lowered by now", Oconv(int(n.Op), 0)) Yyerror("instrument: %v must be lowered by now", Oconv(int(n.Op), 0))
goto ret goto ret
// impossible nodes: only appear in backend. // impossible nodes: only appear in backend.
case ORROTC, OEXTEND: case ORROTC, OEXTEND:
Yyerror("racewalk: %v cannot exist now", Oconv(int(n.Op), 0)) Yyerror("instrument: %v cannot exist now", Oconv(int(n.Op), 0))
goto ret goto ret
case OGETG: case OGETG:
Yyerror("racewalk: OGETG can happen only in runtime which we don't instrument") Yyerror("instrument: OGETG can happen only in runtime which we don't instrument")
goto ret goto ret
case OFOR: case OFOR:
if n.Left != nil { if n.Left != nil {
racewalknode(&n.Left, &n.Left.Ninit, 0, 0) instrumentnode(&n.Left, &n.Left.Ninit, 0, 0)
} }
if n.Right != nil { if n.Right != nil {
racewalknode(&n.Right, &n.Right.Ninit, 0, 0) instrumentnode(&n.Right, &n.Right.Ninit, 0, 0)
} }
goto ret goto ret
case OIF, OSWITCH: case OIF, OSWITCH:
if n.Left != nil { if n.Left != nil {
racewalknode(&n.Left, &n.Left.Ninit, 0, 0) instrumentnode(&n.Left, &n.Left.Ninit, 0, 0)
} }
goto ret goto ret
...@@ -416,10 +418,10 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) { ...@@ -416,10 +418,10 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
ret: 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) instrumentlist(n.List, init)
} }
racewalklist(n.Nbody, nil) instrumentlist(n.Nbody, nil)
racewalklist(n.Rlist, nil) instrumentlist(n.Rlist, nil)
*np = n *np = n
} }
......
...@@ -340,7 +340,7 @@ func walkrange(n *Node) { ...@@ -340,7 +340,7 @@ func walkrange(n *Node) {
// //
// Parameters are as in walkrange: "for v1, v2 = range a". // Parameters are as in walkrange: "for v1, v2 = range a".
func memclrrange(n, v1, v2, a *Node) bool { func memclrrange(n, v1, v2, a *Node) bool {
if Debug['N'] != 0 || flag_race != 0 { if Debug['N'] != 0 || instrumenting {
return false return false
} }
if v1 == nil || v2 != nil { if v1 == nil || v2 != nil {
......
...@@ -1645,7 +1645,7 @@ func ullmancalc(n *Node) { ...@@ -1645,7 +1645,7 @@ func ullmancalc(n *Node) {
// hard with race detector // hard with race detector
case OANDAND, OOROR: case OANDAND, OOROR:
if flag_race != 0 { if instrumenting {
ul = UINF ul = UINF
goto out goto out
} }
...@@ -2405,7 +2405,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) { ...@@ -2405,7 +2405,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
dot := adddot(Nod(OXDOT, this.Left, newname(method.Sym))) dot := adddot(Nod(OXDOT, this.Left, newname(method.Sym)))
// generate call // generate call
if flag_race == 0 && Isptr[rcvr.Etype] && Isptr[methodrcvr.Etype] && method.Embedded != 0 && !isifacemethod(method.Type) { if !instrumenting && Isptr[rcvr.Etype] && Isptr[methodrcvr.Etype] && method.Embedded != 0 && !isifacemethod(method.Type) {
// generate tail call: adjust pointer receiver and jump to embedded method. // generate tail call: adjust pointer receiver and jump to embedded method.
dot = dot.Left // skip final .M dot = dot.Left // skip final .M
if !Isptr[dotlist[0].field.Type.Etype] { if !Isptr[dotlist[0].field.Type.Etype] {
......
...@@ -237,7 +237,7 @@ func walkstmt(np **Node) { ...@@ -237,7 +237,7 @@ func walkstmt(np **Node) {
walkprintfunc(&n.Left, &n.Ninit) walkprintfunc(&n.Left, &n.Ninit)
case OCOPY: case OCOPY:
n.Left = copyany(n.Left, &n.Ninit, 1) n.Left = copyany(n.Left, &n.Ninit, true)
default: default:
walkexpr(&n.Left, &n.Ninit) walkexpr(&n.Left, &n.Ninit)
...@@ -269,7 +269,7 @@ func walkstmt(np **Node) { ...@@ -269,7 +269,7 @@ func walkstmt(np **Node) {
walkprintfunc(&n.Left, &n.Ninit) walkprintfunc(&n.Left, &n.Ninit)
case OCOPY: case OCOPY:
n.Left = copyany(n.Left, &n.Ninit, 1) n.Left = copyany(n.Left, &n.Ninit, true)
default: default:
walkexpr(&n.Left, &n.Ninit) walkexpr(&n.Left, &n.Ninit)
...@@ -678,7 +678,7 @@ func walkexpr(np **Node, init **NodeList) { ...@@ -678,7 +678,7 @@ func walkexpr(np **Node, init **NodeList) {
goto ret goto ret
} }
if n.Right == nil || iszero(n.Right) && flag_race == 0 { if n.Right == nil || iszero(n.Right) && !instrumenting {
goto ret goto ret
} }
...@@ -690,7 +690,7 @@ func walkexpr(np **Node, init **NodeList) { ...@@ -690,7 +690,7 @@ func walkexpr(np **Node, init **NodeList) {
// TODO(rsc): The Isfat is for consistency with componentgen and orderexpr. // TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
// It needs to be removed in all three places. // It needs to be removed in all three places.
// That would allow inlining x.(struct{*int}) the same as x.(*int). // That would allow inlining x.(struct{*int}) the same as x.(*int).
if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && flag_race == 0 { if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && !instrumenting {
// handled directly during cgen // handled directly during cgen
walkexpr(&n.Right, init) walkexpr(&n.Right, init)
break break
...@@ -895,7 +895,7 @@ func walkexpr(np **Node, init **NodeList) { ...@@ -895,7 +895,7 @@ func walkexpr(np **Node, init **NodeList) {
// TODO(rsc): The Isfat is for consistency with componentgen and orderexpr. // TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
// It needs to be removed in all three places. // It needs to be removed in all three places.
// That would allow inlining x.(struct{*int}) the same as x.(*int). // That would allow inlining x.(struct{*int}) the same as x.(*int).
if isdirectiface(e.Type) && !Isfat(e.Type) && flag_race == 0 { if isdirectiface(e.Type) && !Isfat(e.Type) && !instrumenting {
// handled directly during gen. // handled directly during gen.
walkexprlistsafe(n.List, init) walkexprlistsafe(n.List, init)
walkexpr(&e.Left, init) walkexpr(&e.Left, init)
...@@ -1412,7 +1412,7 @@ func walkexpr(np **Node, init **NodeList) { ...@@ -1412,7 +1412,7 @@ func walkexpr(np **Node, init **NodeList) {
Fatalf("append outside assignment") Fatalf("append outside assignment")
case OCOPY: case OCOPY:
n = copyany(n, init, flag_race) n = copyany(n, init, instrumenting)
goto ret goto ret
// cannot use chanfn - closechan takes any, not chan any // cannot use chanfn - closechan takes any, not chan any
...@@ -2938,7 +2938,7 @@ func appendslice(n *Node, init **NodeList) *Node { ...@@ -2938,7 +2938,7 @@ func appendslice(n *Node, init **NodeList) *Node {
substArgTypes(fn, l1.Type, l2.Type) substArgTypes(fn, l1.Type, l2.Type)
nt := mkcall1(fn, Types[TINT], &l, typename(l1.Type.Type), nptr1, nptr2) nt := mkcall1(fn, Types[TINT], &l, typename(l1.Type.Type), nptr1, nptr2)
l = list(l, nt) l = list(l, nt)
} else if flag_race != 0 { } else if instrumenting {
// rely on runtime to instrument copy. // rely on runtime to instrument copy.
// copy(s[len(l1):len(l1)+len(l2)], l2) // copy(s[len(l1):len(l1)+len(l2)], l2)
nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil)))) nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil))))
...@@ -3038,7 +3038,7 @@ func walkappend(n *Node, init **NodeList, dst *Node) *Node { ...@@ -3038,7 +3038,7 @@ func walkappend(n *Node, init **NodeList, dst *Node) *Node {
// General case, with no function calls left as arguments. // General case, with no function calls left as arguments.
// Leave for gen, except that race detector requires old form // Leave for gen, except that race detector requires old form
if flag_race == 0 { if !instrumenting {
return n return n
} }
...@@ -3091,13 +3091,13 @@ func walkappend(n *Node, init **NodeList, dst *Node) *Node { ...@@ -3091,13 +3091,13 @@ func walkappend(n *Node, init **NodeList, dst *Node) *Node {
// //
// Also works if b is a string. // Also works if b is a string.
// //
func copyany(n *Node, init **NodeList, runtimecall int) *Node { func copyany(n *Node, init **NodeList, runtimecall bool) *Node {
if haspointers(n.Left.Type.Type) { if haspointers(n.Left.Type.Type) {
fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type) fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type)
return mkcall1(fn, n.Type, init, typename(n.Left.Type.Type), n.Left, n.Right) return mkcall1(fn, n.Type, init, typename(n.Left.Type.Type), n.Left, n.Right)
} }
if runtimecall != 0 { if runtimecall {
var fn *Node var fn *Node
if n.Right.Type.Etype == TSTRING { if n.Right.Type.Etype == TSTRING {
fn = syslook("slicestringcopy", 1) fn = syslook("slicestringcopy", 1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment