2012-02-03 18:16:42 -05:00
|
|
|
// Copyright 2012 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
#include "a.h"
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Helpers for building pkg/runtime.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// mkzversion writes zversion.go:
|
|
|
|
|
//
|
|
|
|
|
// package runtime
|
|
|
|
|
// const defaultGoroot = <goroot>
|
|
|
|
|
// const theVersion = <version>
|
|
|
|
|
//
|
|
|
|
|
void
|
|
|
|
|
mkzversion(char *dir, char *file)
|
|
|
|
|
{
|
|
|
|
|
Buf b, out;
|
|
|
|
|
|
2012-05-01 22:32:46 -07:00
|
|
|
USED(dir);
|
|
|
|
|
|
2012-02-03 18:16:42 -05:00
|
|
|
binit(&b);
|
|
|
|
|
binit(&out);
|
|
|
|
|
|
|
|
|
|
bwritestr(&out, bprintf(&b,
|
|
|
|
|
"// auto generated by go tool dist\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"package runtime\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"const defaultGoroot = `%s`\n"
|
2012-02-09 20:47:12 -02:00
|
|
|
"const theVersion = `%s`\n", goroot_final, goversion));
|
2012-02-03 18:16:42 -05:00
|
|
|
|
2012-02-21 16:49:30 -05:00
|
|
|
writefile(&out, file, 0);
|
2012-02-03 18:16:42 -05:00
|
|
|
|
|
|
|
|
bfree(&b);
|
|
|
|
|
bfree(&out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mkzgoarch writes zgoarch_$GOARCH.go:
|
|
|
|
|
//
|
|
|
|
|
// package runtime
|
|
|
|
|
// const theGoarch = <goarch>
|
|
|
|
|
//
|
|
|
|
|
void
|
|
|
|
|
mkzgoarch(char *dir, char *file)
|
|
|
|
|
{
|
|
|
|
|
Buf b, out;
|
2012-05-01 22:32:46 -07:00
|
|
|
|
|
|
|
|
USED(dir);
|
2012-02-03 18:16:42 -05:00
|
|
|
|
|
|
|
|
binit(&b);
|
|
|
|
|
binit(&out);
|
|
|
|
|
|
|
|
|
|
bwritestr(&out, bprintf(&b,
|
|
|
|
|
"// auto generated by go tool dist\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"package runtime\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"const theGoarch = `%s`\n", goarch));
|
|
|
|
|
|
2012-02-21 16:49:30 -05:00
|
|
|
writefile(&out, file, 0);
|
2012-02-03 18:16:42 -05:00
|
|
|
|
|
|
|
|
bfree(&b);
|
|
|
|
|
bfree(&out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mkzgoos writes zgoos_$GOOS.go:
|
|
|
|
|
//
|
|
|
|
|
// package runtime
|
|
|
|
|
// const theGoos = <goos>
|
|
|
|
|
//
|
|
|
|
|
void
|
|
|
|
|
mkzgoos(char *dir, char *file)
|
|
|
|
|
{
|
|
|
|
|
Buf b, out;
|
2012-05-01 22:32:46 -07:00
|
|
|
|
|
|
|
|
USED(dir);
|
2012-02-03 18:16:42 -05:00
|
|
|
|
|
|
|
|
binit(&b);
|
|
|
|
|
binit(&out);
|
|
|
|
|
|
|
|
|
|
bwritestr(&out, bprintf(&b,
|
|
|
|
|
"// auto generated by go tool dist\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"package runtime\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"const theGoos = `%s`\n", goos));
|
|
|
|
|
|
2012-02-21 16:49:30 -05:00
|
|
|
writefile(&out, file, 0);
|
2012-02-03 18:16:42 -05:00
|
|
|
|
|
|
|
|
bfree(&b);
|
|
|
|
|
bfree(&out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
|
char *goarch;
|
|
|
|
|
char *goos;
|
|
|
|
|
char *hdr;
|
|
|
|
|
} zasmhdr[] = {
|
|
|
|
|
{"386", "windows",
|
|
|
|
|
"#define get_tls(r) MOVL 0x14(FS), r\n"
|
|
|
|
|
"#define g(r) 0(r)\n"
|
|
|
|
|
"#define m(r) 4(r)\n"
|
|
|
|
|
},
|
|
|
|
|
{"386", "plan9",
|
|
|
|
|
"#define get_tls(r) MOVL _tos(SB), r \n"
|
|
|
|
|
"#define g(r) -8(r)\n"
|
|
|
|
|
"#define m(r) -4(r)\n"
|
|
|
|
|
},
|
|
|
|
|
{"386", "linux",
|
|
|
|
|
"// On Linux systems, what we call 0(GS) and 4(GS) for g and m\n"
|
|
|
|
|
"// turn into %gs:-8 and %gs:-4 (using gcc syntax to denote\n"
|
|
|
|
|
"// what the machine sees as opposed to 8l input).\n"
|
|
|
|
|
"// 8l rewrites 0(GS) and 4(GS) into these.\n"
|
|
|
|
|
"//\n"
|
|
|
|
|
"// On Linux Xen, it is not allowed to use %gs:-8 and %gs:-4\n"
|
|
|
|
|
"// directly. Instead, we have to store %gs:0 into a temporary\n"
|
|
|
|
|
"// register and then use -8(%reg) and -4(%reg). This kind\n"
|
|
|
|
|
"// of addressing is correct even when not running Xen.\n"
|
|
|
|
|
"//\n"
|
|
|
|
|
"// 8l can rewrite MOVL 0(GS), CX into the appropriate pair\n"
|
|
|
|
|
"// of mov instructions, using CX as the intermediate register\n"
|
|
|
|
|
"// (safe because CX is about to be written to anyway).\n"
|
|
|
|
|
"// But 8l cannot handle other instructions, like storing into 0(GS),\n"
|
|
|
|
|
"// which is where these macros come into play.\n"
|
|
|
|
|
"// get_tls sets up the temporary and then g and r use it.\n"
|
|
|
|
|
"//\n"
|
|
|
|
|
"// The final wrinkle is that get_tls needs to read from %gs:0,\n"
|
|
|
|
|
"// but in 8l input it's called 8(GS), because 8l is going to\n"
|
|
|
|
|
"// subtract 8 from all the offsets, as described above.\n"
|
|
|
|
|
"#define get_tls(r) MOVL 8(GS), r\n"
|
|
|
|
|
"#define g(r) -8(r)\n"
|
|
|
|
|
"#define m(r) -4(r)\n"
|
|
|
|
|
},
|
|
|
|
|
{"386", "",
|
|
|
|
|
"#define get_tls(r)\n"
|
|
|
|
|
"#define g(r) 0(GS)\n"
|
|
|
|
|
"#define m(r) 4(GS)\n"
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{"amd64", "windows",
|
|
|
|
|
"#define get_tls(r) MOVQ 0x28(GS), r\n"
|
|
|
|
|
"#define g(r) 0(r)\n"
|
|
|
|
|
"#define m(r) 8(r)\n"
|
|
|
|
|
},
|
2012-09-24 12:24:45 -04:00
|
|
|
{"amd64", "plan9",
|
|
|
|
|
"#define get_tls(r)\n"
|
|
|
|
|
"#define g(r) 0(GS)\n"
|
|
|
|
|
"#define m(r) 8(GS)\n"
|
|
|
|
|
"#define procid(r) 16(GS)\n"
|
|
|
|
|
},
|
2012-02-03 18:16:42 -05:00
|
|
|
{"amd64", "",
|
|
|
|
|
"// The offsets 0 and 8 are known to:\n"
|
|
|
|
|
"// ../../cmd/6l/pass.c:/D_GS\n"
|
|
|
|
|
"// cgo/gcc_linux_amd64.c:/^threadentry\n"
|
|
|
|
|
"// cgo/gcc_darwin_amd64.c:/^threadentry\n"
|
|
|
|
|
"//\n"
|
|
|
|
|
"#define get_tls(r)\n"
|
|
|
|
|
"#define g(r) 0(GS)\n"
|
|
|
|
|
"#define m(r) 8(GS)\n"
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{"arm", "",
|
|
|
|
|
"#define g R10\n"
|
|
|
|
|
"#define m R9\n"
|
|
|
|
|
"#define LR R14\n"
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// mkzasm writes zasm_$GOOS_$GOARCH.h,
|
|
|
|
|
// which contains struct offsets for use by
|
|
|
|
|
// assembly files. It also writes a copy to the work space
|
|
|
|
|
// under the name zasm_GOOS_GOARCH.h (no expansion).
|
|
|
|
|
//
|
|
|
|
|
void
|
|
|
|
|
mkzasm(char *dir, char *file)
|
|
|
|
|
{
|
|
|
|
|
int i, n;
|
|
|
|
|
char *aggr, *p;
|
|
|
|
|
Buf in, b, out;
|
|
|
|
|
Vec argv, lines, fields;
|
|
|
|
|
|
|
|
|
|
binit(&in);
|
|
|
|
|
binit(&b);
|
|
|
|
|
binit(&out);
|
|
|
|
|
vinit(&argv);
|
|
|
|
|
vinit(&lines);
|
|
|
|
|
vinit(&fields);
|
|
|
|
|
|
|
|
|
|
bwritestr(&out, "// auto generated by go tool dist\n\n");
|
|
|
|
|
for(i=0; i<nelem(zasmhdr); i++) {
|
|
|
|
|
if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) {
|
|
|
|
|
bwritestr(&out, zasmhdr[i].hdr);
|
|
|
|
|
goto ok;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fatal("unknown $GOOS/$GOARCH in mkzasm");
|
|
|
|
|
ok:
|
|
|
|
|
|
|
|
|
|
// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -a proc.c
|
|
|
|
|
// to get acid [sic] output.
|
|
|
|
|
vreset(&argv);
|
2012-02-13 22:31:51 -05:00
|
|
|
vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
|
2012-02-03 18:16:42 -05:00
|
|
|
vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
|
|
|
|
|
vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
|
|
|
|
|
vadd(&argv, bprintf(&b, "-I%s", workdir));
|
|
|
|
|
vadd(&argv, "-a");
|
|
|
|
|
vadd(&argv, "proc.c");
|
|
|
|
|
runv(&in, dir, CheckExit, &argv);
|
|
|
|
|
|
|
|
|
|
// Convert input like
|
|
|
|
|
// aggr G
|
|
|
|
|
// {
|
|
|
|
|
// Gobuf 24 sched;
|
|
|
|
|
// 'Y' 48 stack0;
|
|
|
|
|
// }
|
|
|
|
|
// into output like
|
|
|
|
|
// #define g_sched 24
|
|
|
|
|
// #define g_stack0 48
|
|
|
|
|
//
|
|
|
|
|
aggr = nil;
|
|
|
|
|
splitlines(&lines, bstr(&in));
|
|
|
|
|
for(i=0; i<lines.len; i++) {
|
|
|
|
|
splitfields(&fields, lines.p[i]);
|
|
|
|
|
if(fields.len == 2 && streq(fields.p[0], "aggr")) {
|
|
|
|
|
if(streq(fields.p[1], "G"))
|
|
|
|
|
aggr = "g";
|
|
|
|
|
else if(streq(fields.p[1], "M"))
|
|
|
|
|
aggr = "m";
|
|
|
|
|
else if(streq(fields.p[1], "Gobuf"))
|
|
|
|
|
aggr = "gobuf";
|
|
|
|
|
else if(streq(fields.p[1], "WinCall"))
|
|
|
|
|
aggr = "wincall";
|
2012-05-30 15:10:54 +10:00
|
|
|
else if(streq(fields.p[1], "SEH"))
|
|
|
|
|
aggr = "seh";
|
2012-02-03 18:16:42 -05:00
|
|
|
}
|
|
|
|
|
if(hasprefix(lines.p[i], "}"))
|
|
|
|
|
aggr = nil;
|
|
|
|
|
if(aggr && hasprefix(lines.p[i], "\t") && fields.len >= 2) {
|
|
|
|
|
n = fields.len;
|
|
|
|
|
p = fields.p[n-1];
|
|
|
|
|
if(p[xstrlen(p)-1] == ';')
|
|
|
|
|
p[xstrlen(p)-1] = '\0';
|
|
|
|
|
bwritestr(&out, bprintf(&b, "#define %s_%s %s\n", aggr, fields.p[n-1], fields.p[n-2]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write both to file and to workdir/zasm_GOOS_GOARCH.h.
|
2012-02-21 16:49:30 -05:00
|
|
|
writefile(&out, file, 0);
|
|
|
|
|
writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0);
|
2012-02-03 18:16:42 -05:00
|
|
|
|
|
|
|
|
bfree(&in);
|
|
|
|
|
bfree(&b);
|
|
|
|
|
bfree(&out);
|
|
|
|
|
vfree(&argv);
|
|
|
|
|
vfree(&lines);
|
|
|
|
|
vfree(&fields);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *runtimedefs[] = {
|
|
|
|
|
"proc.c",
|
|
|
|
|
"iface.c",
|
|
|
|
|
"hashmap.c",
|
|
|
|
|
"chan.c",
|
2012-05-11 10:50:03 +04:00
|
|
|
"parfor.c",
|
2012-02-03 18:16:42 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h,
|
|
|
|
|
// which contains Go struct definitions equivalent to the C ones.
|
|
|
|
|
// Mostly we just write the output of 6c -q to the file.
|
|
|
|
|
// However, we run it on multiple files, so we have to delete
|
|
|
|
|
// the duplicated definitions, and we don't care about the funcs
|
|
|
|
|
// and consts, so we delete those too.
|
|
|
|
|
//
|
|
|
|
|
void
|
|
|
|
|
mkzruntimedefs(char *dir, char *file)
|
|
|
|
|
{
|
|
|
|
|
int i, skip;
|
|
|
|
|
char *p;
|
|
|
|
|
Buf in, b, out;
|
|
|
|
|
Vec argv, lines, fields, seen;
|
|
|
|
|
|
|
|
|
|
binit(&in);
|
|
|
|
|
binit(&b);
|
|
|
|
|
binit(&out);
|
|
|
|
|
vinit(&argv);
|
|
|
|
|
vinit(&lines);
|
|
|
|
|
vinit(&fields);
|
|
|
|
|
vinit(&seen);
|
|
|
|
|
|
|
|
|
|
bwritestr(&out, "// auto generated by go tool dist\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"package runtime\n"
|
|
|
|
|
"import \"unsafe\"\n"
|
|
|
|
|
"var _ unsafe.Pointer\n"
|
|
|
|
|
"\n"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -q
|
|
|
|
|
// on each of the runtimedefs C files.
|
2012-02-13 22:31:51 -05:00
|
|
|
vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
|
2012-02-03 18:16:42 -05:00
|
|
|
vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
|
|
|
|
|
vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
|
|
|
|
|
vadd(&argv, bprintf(&b, "-I%s", workdir));
|
|
|
|
|
vadd(&argv, "-q");
|
|
|
|
|
vadd(&argv, "");
|
|
|
|
|
p = argv.p[argv.len-1];
|
|
|
|
|
for(i=0; i<nelem(runtimedefs); i++) {
|
|
|
|
|
argv.p[argv.len-1] = runtimedefs[i];
|
|
|
|
|
runv(&b, dir, CheckExit, &argv);
|
|
|
|
|
bwriteb(&in, &b);
|
|
|
|
|
}
|
|
|
|
|
argv.p[argv.len-1] = p;
|
|
|
|
|
|
|
|
|
|
// Process the aggregate output.
|
|
|
|
|
skip = 0;
|
|
|
|
|
splitlines(&lines, bstr(&in));
|
|
|
|
|
for(i=0; i<lines.len; i++) {
|
|
|
|
|
p = lines.p[i];
|
|
|
|
|
// Drop comment, func, and const lines.
|
|
|
|
|
if(hasprefix(p, "//") || hasprefix(p, "const") || hasprefix(p, "func"))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Note beginning of type or var decl, which can be multiline.
|
|
|
|
|
// Remove duplicates. The linear check of seen here makes the
|
|
|
|
|
// whole processing quadratic in aggregate, but there are only
|
|
|
|
|
// about 100 declarations, so this is okay (and simple).
|
|
|
|
|
if(hasprefix(p, "type ") || hasprefix(p, "var ")) {
|
|
|
|
|
splitfields(&fields, p);
|
|
|
|
|
if(fields.len < 2)
|
|
|
|
|
continue;
|
|
|
|
|
if(find(fields.p[1], seen.p, seen.len) >= 0) {
|
|
|
|
|
if(streq(fields.p[fields.len-1], "{"))
|
|
|
|
|
skip = 1; // skip until }
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
vadd(&seen, fields.p[1]);
|
|
|
|
|
}
|
|
|
|
|
if(skip) {
|
|
|
|
|
if(hasprefix(p, "}"))
|
|
|
|
|
skip = 0;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bwritestr(&out, p);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-21 16:49:30 -05:00
|
|
|
writefile(&out, file, 0);
|
2012-02-03 18:16:42 -05:00
|
|
|
|
|
|
|
|
bfree(&in);
|
|
|
|
|
bfree(&b);
|
|
|
|
|
bfree(&out);
|
|
|
|
|
vfree(&argv);
|
|
|
|
|
vfree(&lines);
|
|
|
|
|
vfree(&fields);
|
|
|
|
|
vfree(&seen);
|
|
|
|
|
}
|