// 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" #include /* * Helpers for building pkg/runtime. */ // mkzversion writes zversion.go: // // package runtime // const defaultGoroot = // const theVersion = // void mkzversion(char *dir, char *file) { Buf b, out; binit(&b); binit(&out); bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n" "\n" "package runtime\n" "\n" "const defaultGoroot = `%s`\n" "const theVersion = `%s`\n", goroot_final, goversion)); writefile(&out, file, 0); bfree(&b); bfree(&out); } // mkzgoarch writes zgoarch_$GOARCH.go: // // package runtime // const theGoarch = // void mkzgoarch(char *dir, char *file) { Buf b, out; 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)); writefile(&out, file, 0); bfree(&b); bfree(&out); } // mkzgoos writes zgoos_$GOOS.go: // // package runtime // const theGoos = // void mkzgoos(char *dir, char *file) { Buf b, out; 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)); writefile(&out, file, 0); 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" }, {"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= 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. writefile(&out, file, 0); writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0); bfree(&in); bfree(&b); bfree(&out); vfree(&argv); vfree(&lines); vfree(&fields); } static char *runtimedefs[] = { "proc.c", "iface.c", "hashmap.c", "chan.c", }; // 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. vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar)); 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= 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); } writefile(&out, file, 0); bfree(&in); bfree(&b); bfree(&out); vfree(&argv); vfree(&lines); vfree(&fields); vfree(&seen); }