summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
authorR?my Oudompheng <oudomphe@phare.normalesup.org>2013-05-15 01:25:20 +0200
committerR?my Oudompheng <oudomphe@phare.normalesup.org>2013-05-15 01:25:20 +0200
commit8cb79df02c89fa0f4f61676cea10c52a8c589790 (patch)
tree6c509c2c68093de5dc04031a778f19766f8f48d4 /src/cmd/gc
parent056860f354e679ffd332269e6184523259c8fe70 (diff)
downloadgo-8cb79df02c89fa0f4f61676cea10c52a8c589790.tar.gz
cmd/gc: fix race instrumentation of selectors T(v).Field
Fixes issue 5424. R=golang-dev, daniel.morsing, dvyukov, r CC=golang-dev https://codereview.appspot.com/9033048
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/racewalk.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c
index 5d4f62e76..790c7efd7 100644
--- a/src/cmd/gc/racewalk.c
+++ b/src/cmd/gc/racewalk.c
@@ -23,6 +23,7 @@ static void racewalklist(NodeList *l, NodeList **init);
static void racewalknode(Node **np, NodeList **init, int wr, int skip);
static int callinstr(Node **n, NodeList **init, int wr, int skip);
static Node* uintptraddr(Node *n);
+static void makeaddable(Node *n);
static Node* basenod(Node *n);
static void foreach(Node *n, void(*f)(Node*, void*), void *c);
static void hascallspred(Node *n, void *c);
@@ -489,6 +490,7 @@ callinstr(Node **np, NodeList **init, int wr, int skip)
*np = n;
}
n = treecopy(n);
+ makeaddable(n);
f = mkcall(wr ? "racewrite" : "raceread", T, init, uintptraddr(n));
*init = list(*init, f);
return 1;
@@ -496,6 +498,37 @@ callinstr(Node **np, NodeList **init, int wr, int skip)
return 0;
}
+// makeaddable returns a node whose memory location is the
+// same as n, but which is addressable in the Go language
+// sense.
+// This is different from functions like cheapexpr that may make
+// a copy of their argument.
+static void
+makeaddable(Node *n)
+{
+ // The arguments to uintptraddr technically have an address but
+ // may not be addressable in the Go sense: for example, in the case
+ // of T(v).Field where T is a struct type and v is
+ // an addressable value.
+ switch(n->op) {
+ case OINDEX:
+ if(isfixedarray(n->left->type))
+ makeaddable(n->left);
+ break;
+ case ODOT:
+ case OXDOT:
+ // Turn T(v).Field into v.Field
+ if(n->left->op == OCONVNOP)
+ n->left = n->left->left;
+ makeaddable(n->left);
+ break;
+ case ODOTPTR:
+ default:
+ // nothing to do
+ break;
+ }
+}
+
static Node*
uintptraddr(Node *n)
{