build: implement GOEXPERIMENT again in runtime, and add to liblink

For Austin's framepointer experiment.

Change-Id: I81b6f414943b3578924f853300b9193684f79bf4
Reviewed-on: https://go-review.googlesource.com/2994
Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
Russ Cox 2015-01-16 19:22:58 -05:00
parent 8bf6e09f4c
commit dba9eb3369
10 changed files with 94 additions and 109 deletions

View file

@ -586,6 +586,11 @@ void* emallocz(long n);
void* erealloc(void *p, long n);
char* estrdup(char *p);
char* expandpkg(char *t0, char *pkg);
void linksetexp(void);
char* expstring(void);
extern int fieldtrack_enabled;
extern int framepointer_enabled;
// ld.c
void addhist(Link *ctxt, int32 line, int type);
@ -656,6 +661,9 @@ extern LinkArch linkarm;
extern LinkArch linkppc64;
extern LinkArch linkppc64le;
extern int linkbasepointer;
extern void linksetexp(void);
#pragma varargck type "A" int
#pragma varargck type "E" uint
#pragma varargck type "D" Addr*

View file

@ -576,7 +576,6 @@ var deptab = []struct {
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/lib9.a",
}},
{"runtime", []string{
"zaexperiment.h",
"zversion.go",
}},
}
@ -601,7 +600,6 @@ var gentab = []struct {
{"anames9.c", mkanames},
{"zdefaultcc.go", mkzdefaultcc},
{"zversion.go", mkzversion},
{"zaexperiment.h", mkzexperiment},
// not generated anymore, but delete the file if we see it
{"enam.c", nil},
@ -937,8 +935,8 @@ func install(dir string) {
)
}
// gc/lex.c records the GOEXPERIMENT setting used during the build.
if name == "lex.c" {
// liblink/go.c records the GOEXPERIMENT setting used during the build.
if name == "go.c" {
compile = append(compile,
"-D", fmt.Sprintf("GOEXPERIMENT=%q", os.Getenv("GOEXPERIMENT")))
}

View file

@ -27,21 +27,8 @@ func mkzversion(dir, file string) {
"\n"+
"const defaultGoroot = `%s`\n"+
"const theVersion = `%s`\n"+
"\n"+
"var buildVersion = theVersion\n", goroot_final, goversion)
writefile(out, file, 0)
}
// mkzexperiment writes zaexperiment.h (sic):
//
// #define GOEXPERIMENT "experiment string"
//
func mkzexperiment(dir, file string) {
out := fmt.Sprintf(
"// auto generated by go tool dist\n"+
"\n"+
"#define GOEXPERIMENT \"%s\"\n", os.Getenv("GOEXPERIMENT"))
"const goexperiment = `%s`\n"+
"var buildVersion = theVersion\n", goroot_final, goversion, os.Getenv("GOEXPERIMENT"))
writefile(out, file, 0)
}

View file

@ -994,8 +994,6 @@ EXTERN int debuglive;
EXTERN Link* ctxt;
EXTERN int nointerface;
EXTERN int fieldtrack_enabled;
EXTERN int precisestack_enabled;
EXTERN int writearchive;
EXTERN Biobuf bstdout;

View file

@ -33,19 +33,6 @@ static char *goos, *goarch, *goroot;
#define BOM 0xFEFF
// Compiler experiments.
// These are controlled by the GOEXPERIMENT environment
// variable recorded when the compiler is built.
static struct {
char *name;
int *val;
} exper[] = {
// {"rune32", &rune32},
{"fieldtrack", &fieldtrack_enabled},
{"precisestack", &precisestack_enabled},
{nil, nil},
};
// Debug arguments.
// These can be specified with the -d flag, as in "-d nil"
// to set the debug_checknil variable. In general the list passed
@ -55,55 +42,8 @@ static struct {
int *val;
} debugtab[] = {
{"nil", &debug_checknil},
{nil, nil},
};
static void
addexp(char *s)
{
int i;
for(i=0; exper[i].name != nil; i++) {
if(strcmp(exper[i].name, s) == 0) {
*exper[i].val = 1;
return;
}
}
print("unknown experiment %s\n", s);
exits("unknown experiment");
}
static void
setexp(void)
{
char *f[20];
int i, nf;
precisestack_enabled = 1; // on by default
// cmd/dist #defines GOEXPERIMENT for us.
nf = getfields(GOEXPERIMENT, f, nelem(f), 1, ",");
for(i=0; i<nf; i++)
addexp(f[i]);
}
char*
expstring(void)
{
int i;
static char buf[512];
strcpy(buf, "X");
for(i=0; exper[i].name != nil; i++)
if(*exper[i].val)
seprint(buf+strlen(buf), buf+sizeof buf, ",%s", exper[i].name);
if(strlen(buf) == 1)
strcpy(buf, "X,none");
buf[1] = ':';
return buf;
}
// Our own isdigit, isspace, isalpha, isalnum that take care
// of EOF and other out of range arguments.
static int
@ -272,8 +212,6 @@ main(int argc, char *argv[])
if(nacl)
flag_largemodel = 1;
setexp();
fmtstrinit(&pragcgobuf);
quotefmtinstall();
@ -344,13 +282,14 @@ main(int argc, char *argv[])
nf = getfields(debugstr, f, nelem(f), 1, ",");
for(i=0; i<nf; i++) {
for(j=0; debugtab[j].name != nil; j++) {
for(j=0; j<nelem(debugtab); j++) {
if(strcmp(debugtab[j].name, f[i]) == 0) {
*debugtab[j].val = 1;
if(debugtab[j].val != nil)
*debugtab[j].val = 1;
break;
}
}
if(debugtab[j].name == nil)
if(j >= nelem(debugtab))
sysfatal("unknown debug information -d '%s'\n", f[i]);
}
}

View file

@ -1487,25 +1487,21 @@ livenessepilogue(Liveness *lv)
// Annotate ambiguously live variables so that they can
// be zeroed at function entry.
// livein and liveout are dead here and used as temporaries.
// For now, only enabled when using GOEXPERIMENT=precisestack
// during make.bash / all.bash.
if(precisestack_enabled) {
bvresetall(livein);
bvandnot(liveout, any, all);
if(!bvisempty(liveout)) {
for(pos = 0; pos < liveout->n; pos++) {
if(!bvget(liveout, pos))
continue;
bvset(all, pos); // silence future warnings in this block
n = *(Node**)arrayget(lv->vars, pos);
if(!n->needzero) {
n->needzero = 1;
if(debuglive >= 1)
warnl(p->lineno, "%N: %lN is ambiguously live", curfn->nname, n);
// Record in 'ambiguous' bitmap.
xoffset = n->xoffset + stkptrsize;
twobitwalktype1(n->type, &xoffset, ambig);
}
bvresetall(livein);
bvandnot(liveout, any, all);
if(!bvisempty(liveout)) {
for(pos = 0; pos < liveout->n; pos++) {
if(!bvget(liveout, pos))
continue;
bvset(all, pos); // silence future warnings in this block
n = *(Node**)arrayget(lv->vars, pos);
if(!n->needzero) {
n->needzero = 1;
if(debuglive >= 1)
warnl(p->lineno, "%N: %lN is ambiguously live", curfn->nname, n);
// Record in 'ambiguous' bitmap.
xoffset = n->xoffset + stkptrsize;
twobitwalktype1(n->type, &xoffset, ambig);
}
}
}

View file

@ -2521,9 +2521,9 @@ paramstoheap(Type **argin, int out)
v = t->nname;
if(v && v->sym && v->sym->name[0] == '~' && v->sym->name[1] == 'r') // unnamed result
v = N;
// In precisestack mode, the garbage collector assumes results
// For precise stacks, the garbage collector assumes results
// are always live, so zero them always.
if(out && (precisestack_enabled || (v == N && hasdefer))) {
if(out) {
// Defer might stop a panic and show the
// return values as they exist at the time of panic.
// Make sure to zero them on entry to the function.

View file

@ -9,6 +9,66 @@
#include <bio.h>
#include <link.h>
int framepointer_enabled;
int fieldtrack_enabled;
// Toolchain experiments.
// These are controlled by the GOEXPERIMENT environment
// variable recorded when the toolchain is built.
// This list is also known to cmd/gc.
static struct {
char *name;
int *val;
} exper[] = {
{"fieldtrack", &fieldtrack_enabled},
{"basepointer", &framepointer_enabled},
};
static void
addexp(char *s)
{
int i;
for(i=0; i < nelem(exper); i++ ) {
if(strcmp(exper[i].name, s) == 0) {
if(exper[i].val != nil)
*exper[i].val = 1;
return;
}
}
print("unknown experiment %s\n", s);
exits("unknown experiment");
}
void
linksetexp(void)
{
char *f[20];
int i, nf;
// cmd/dist #defines GOEXPERIMENT for us.
nf = getfields(GOEXPERIMENT, f, nelem(f), 1, ",");
for(i=0; i<nf; i++)
addexp(f[i]);
}
char*
expstring(void)
{
int i;
static char buf[512];
strcpy(buf, "X");
for(i=0; i<nelem(exper); i++)
if(*exper[i].val)
seprint(buf+strlen(buf), buf+sizeof buf, ",%s", exper[i].name);
if(strlen(buf) == 1)
strcpy(buf, "X,none");
buf[1] = ':';
return buf;
}
// replace all "". with pkg.
char*
expandpkg(char *t0, char *pkg)

View file

@ -90,6 +90,7 @@ linknew(LinkArch *arch)
char *p;
char buf[1024];
linksetexp();
nuxiinit(arch);
ctxt = emallocz(sizeof *ctxt);

View file

@ -3163,8 +3163,6 @@ func setMaxThreads(in int) (out int) {
return
}
var goexperiment string = "GOEXPERIMENT" // TODO: defined in zaexperiment.h
func haveexperiment(name string) bool {
x := goexperiment
for x != "" {