From 0a8a719ded242be4d928ec77ff2169d1d9c1fa52 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 16 Apr 2014 13:59:42 -0400 Subject: [PATCH] cmd/5g, cmd/6g, cmd/8g: preserve wide values in large functions In large functions with many variables, the register optimizer may give up and choose not to track certain variables at all. In this case, the "nextinnode" information linking together all the words from a given variable will be incomplete, and the result may be that only some of a multiword value is preserved across a call. That confuses the garbage collector, so don't do that. Instead, mark those variables as having their address taken, so that they will be preserved at all calls. It's overkill, but correct. Tested by hand using the 6g -S output to see that it does fix the buggy generated code leading to the issue 7726 failure. There is no automated test because I managed to break the compiler while writing a test (see issue 7727). I will check in a test along with the fix to issue 7727. Fixes #7726. LGTM=khr R=khr, bradfitz, dave CC=golang-codereviews https://golang.org/cl/85200043 --- src/cmd/5g/reg.c | 10 ++++++++++ src/cmd/6g/reg.c | 10 ++++++++++ src/cmd/8g/reg.c | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index 47c2bedd7b..8350e4c50c 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -801,6 +801,16 @@ mkvar(Reg *r, Adr *a) if(nvar >= NVAR) { if(debug['w'] > 1 && node) fatal("variable not optimized: %D", a); + + // If we're not tracking a word in a variable, mark the rest as + // having its address taken, so that we keep the whole thing + // live at all calls. otherwise we might optimize away part of + // a variable but not all of it. + for(i=0; inode == node) + v->addr = 1; + } goto none; } diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index 3e5b1c5865..0c72d6c95c 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -659,6 +659,16 @@ mkvar(Reg *r, Adr *a) if(nvar >= NVAR) { if(debug['w'] > 1 && node != N) fatal("variable not optimized: %#N", node); + + // If we're not tracking a word in a variable, mark the rest as + // having its address taken, so that we keep the whole thing + // live at all calls. otherwise we might optimize away part of + // a variable but not all of it. + for(i=0; inode == node) + v->addr = 1; + } goto none; } diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c index e8e712495c..1e8a31dd62 100644 --- a/src/cmd/8g/reg.c +++ b/src/cmd/8g/reg.c @@ -625,6 +625,16 @@ mkvar(Reg *r, Adr *a) if(nvar >= NVAR) { if(debug['w'] > 1 && node != N) fatal("variable not optimized: %D", a); + + // If we're not tracking a word in a variable, mark the rest as + // having its address taken, so that we keep the whole thing + // live at all calls. otherwise we might optimize away part of + // a variable but not all of it. + for(i=0; inode == node) + v->addr = 1; + } goto none; } -- 2.51.0