OLD | NEW |
(Empty) | |
| 1 // Copyright 2012 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 #include "a.h" |
| 6 #include <stdio.h> |
| 7 |
| 8 /* |
| 9 * Helpers for building pkg/runtime. |
| 10 */ |
| 11 |
| 12 // mkzversion writes zversion.go: |
| 13 // |
| 14 // package runtime |
| 15 // const defaultGoroot = <goroot> |
| 16 // const theVersion = <version> |
| 17 // |
| 18 void |
| 19 mkzversion(char *dir, char *file) |
| 20 { |
| 21 Buf b, out; |
| 22 ········ |
| 23 binit(&b); |
| 24 binit(&out); |
| 25 ········ |
| 26 bwritestr(&out, bprintf(&b, |
| 27 "// auto generated by go tool dist\n" |
| 28 "\n" |
| 29 "package runtime\n" |
| 30 "\n" |
| 31 "const defaultGoroot = `%s`\n" |
| 32 "const theVersion = `%s`\n", goroot, goversion)); |
| 33 |
| 34 writefile(&out, file); |
| 35 ········ |
| 36 bfree(&b); |
| 37 bfree(&out); |
| 38 } |
| 39 |
| 40 // mkzgoarch writes zgoarch_$GOARCH.go: |
| 41 // |
| 42 // package runtime |
| 43 // const theGoarch = <goarch> |
| 44 // |
| 45 void |
| 46 mkzgoarch(char *dir, char *file) |
| 47 { |
| 48 Buf b, out; |
| 49 ········ |
| 50 binit(&b); |
| 51 binit(&out); |
| 52 ········ |
| 53 bwritestr(&out, bprintf(&b, |
| 54 "// auto generated by go tool dist\n" |
| 55 "\n" |
| 56 "package runtime\n" |
| 57 "\n" |
| 58 "const theGoarch = `%s`\n", goarch)); |
| 59 |
| 60 writefile(&out, file); |
| 61 ········ |
| 62 bfree(&b); |
| 63 bfree(&out); |
| 64 } |
| 65 |
| 66 // mkzgoos writes zgoos_$GOOS.go: |
| 67 // |
| 68 // package runtime |
| 69 // const theGoos = <goos> |
| 70 // |
| 71 void |
| 72 mkzgoos(char *dir, char *file) |
| 73 { |
| 74 Buf b, out; |
| 75 ········ |
| 76 binit(&b); |
| 77 binit(&out); |
| 78 ········ |
| 79 bwritestr(&out, bprintf(&b, |
| 80 "// auto generated by go tool dist\n" |
| 81 "\n" |
| 82 "package runtime\n" |
| 83 "\n" |
| 84 "const theGoos = `%s`\n", goos)); |
| 85 |
| 86 writefile(&out, file); |
| 87 ········ |
| 88 bfree(&b); |
| 89 bfree(&out); |
| 90 } |
| 91 |
| 92 static struct { |
| 93 char *goarch; |
| 94 char *goos; |
| 95 char *hdr; |
| 96 } zasmhdr[] = { |
| 97 {"386", "windows", |
| 98 "#define get_tls(r) MOVL 0x14(FS), r\n" |
| 99 "#define g(r) 0(r)\n" |
| 100 "#define m(r) 4(r)\n" |
| 101 }, |
| 102 {"386", "plan9", |
| 103 "#define get_tls(r) MOVL _tos(SB), r \n" |
| 104 "#define g(r) -8(r)\n" |
| 105 "#define m(r) -4(r)\n" |
| 106 }, |
| 107 {"386", "linux", |
| 108 "// On Linux systems, what we call 0(GS) and 4(GS) for g and m\n
" |
| 109 "// turn into %gs:-8 and %gs:-4 (using gcc syntax to denote\n" |
| 110 "// what the machine sees as opposed to 8l input).\n" |
| 111 "// 8l rewrites 0(GS) and 4(GS) into these.\n" |
| 112 "//\n" |
| 113 "// On Linux Xen, it is not allowed to use %gs:-8 and %gs:-4\n" |
| 114 "// directly. Instead, we have to store %gs:0 into a temporary\
n" |
| 115 "// register and then use -8(%reg) and -4(%reg). This kind\n" |
| 116 "// of addressing is correct even when not running Xen.\n" |
| 117 "//\n" |
| 118 "// 8l can rewrite MOVL 0(GS), CX into the appropriate pair\n" |
| 119 "// of mov instructions, using CX as the intermediate register\n
" |
| 120 "// (safe because CX is about to be written to anyway).\n" |
| 121 "// But 8l cannot handle other instructions, like storing into 0
(GS),\n" |
| 122 "// which is where these macros come into play.\n" |
| 123 "// get_tls sets up the temporary and then g and r use it.\n" |
| 124 "//\n" |
| 125 "// The final wrinkle is that get_tls needs to read from %gs:0,\
n" |
| 126 "// but in 8l input it's called 8(GS), because 8l is going to\n" |
| 127 "// subtract 8 from all the offsets, as described above.\n" |
| 128 "#define get_tls(r) MOVL 8(GS), r\n" |
| 129 "#define g(r) -8(r)\n" |
| 130 "#define m(r) -4(r)\n" |
| 131 }, |
| 132 {"386", "", |
| 133 "#define get_tls(r)\n" |
| 134 "#define g(r) 0(GS)\n" |
| 135 "#define m(r) 4(GS)\n" |
| 136 }, |
| 137 ········ |
| 138 {"amd64", "windows", |
| 139 "#define get_tls(r) MOVQ 0x28(GS), r\n" |
| 140 "#define g(r) 0(r)\n" |
| 141 "#define m(r) 8(r)\n" |
| 142 }, |
| 143 {"amd64", "", |
| 144 "// The offsets 0 and 8 are known to:\n" |
| 145 "// ../../cmd/6l/pass.c:/D_GS\n" |
| 146 "// cgo/gcc_linux_amd64.c:/^threadentry\n" |
| 147 "// cgo/gcc_darwin_amd64.c:/^threadentry\n" |
| 148 "//\n" |
| 149 "#define get_tls(r)\n" |
| 150 "#define g(r) 0(GS)\n" |
| 151 "#define m(r) 8(GS)\n" |
| 152 }, |
| 153 ········ |
| 154 {"arm", "", |
| 155 "#define g R10\n" |
| 156 "#define m R9\n" |
| 157 "#define LR R14\n" |
| 158 }, |
| 159 }; |
| 160 |
| 161 // mkzasm writes zasm_$GOOS_$GOARCH.h, |
| 162 // which contains struct offsets for use by |
| 163 // assembly files. It also writes a copy to the work space |
| 164 // under the name zasm_GOOS_GOARCH.h (no expansion). |
| 165 //· |
| 166 void |
| 167 mkzasm(char *dir, char *file) |
| 168 { |
| 169 int i, n; |
| 170 char *aggr, *p; |
| 171 Buf in, b, out; |
| 172 Vec argv, lines, fields; |
| 173 |
| 174 binit(&in); |
| 175 binit(&b); |
| 176 binit(&out); |
| 177 vinit(&argv); |
| 178 vinit(&lines); |
| 179 vinit(&fields); |
| 180 ········ |
| 181 bwritestr(&out, "// auto generated by go tool dist\n\n"); |
| 182 for(i=0; i<nelem(zasmhdr); i++) { |
| 183 if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmh
dr[i].goos)) { |
| 184 bwritestr(&out, zasmhdr[i].hdr); |
| 185 goto ok; |
| 186 } |
| 187 } |
| 188 fatal("unknown $GOOS/$GOARCH in mkzasm"); |
| 189 ok: |
| 190 |
| 191 // Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -a proc.c |
| 192 // to get acid [sic] output. |
| 193 vreset(&argv); |
| 194 vadd(&argv, bpathf(&b, "%s/bin/tool/%sc", goroot, gochar)); |
| 195 vadd(&argv, bprintf(&b, "-DGOOS_%s", goos)); |
| 196 vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch)); |
| 197 vadd(&argv, bprintf(&b, "-I%s", workdir)); |
| 198 vadd(&argv, "-a"); |
| 199 vadd(&argv, "proc.c"); |
| 200 runv(&in, dir, CheckExit, &argv); |
| 201 ········ |
| 202 // Convert input like |
| 203 // aggr G |
| 204 // { |
| 205 // Gobuf 24 sched; |
| 206 // 'Y' 48 stack0; |
| 207 // } |
| 208 // into output like |
| 209 // #define g_sched 24 |
| 210 // #define g_stack0 48 |
| 211 // |
| 212 aggr = nil; |
| 213 splitlines(&lines, bstr(&in)); |
| 214 for(i=0; i<lines.len; i++) { |
| 215 splitfields(&fields, lines.p[i]); |
| 216 if(fields.len == 2 && streq(fields.p[0], "aggr")) { |
| 217 if(streq(fields.p[1], "G")) |
| 218 aggr = "g"; |
| 219 else if(streq(fields.p[1], "M")) |
| 220 aggr = "m"; |
| 221 else if(streq(fields.p[1], "Gobuf")) |
| 222 aggr = "gobuf"; |
| 223 else if(streq(fields.p[1], "WinCall")) |
| 224 aggr = "wincall"; |
| 225 } |
| 226 if(hasprefix(lines.p[i], "}")) |
| 227 aggr = nil; |
| 228 if(aggr && hasprefix(lines.p[i], "\t") && fields.len >= 2) { |
| 229 n = fields.len; |
| 230 p = fields.p[n-1]; |
| 231 if(p[xstrlen(p)-1] == ';') |
| 232 p[xstrlen(p)-1] = '\0'; |
| 233 bwritestr(&out, bprintf(&b, "#define %s_%s %s\n", aggr,
fields.p[n-1], fields.p[n-2])); |
| 234 } |
| 235 } |
| 236 ········ |
| 237 // Write both to file and to workdir/zasm_GOOS_GOARCH.h. |
| 238 writefile(&out, file); |
| 239 writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir)); |
| 240 |
| 241 bfree(&in); |
| 242 bfree(&b); |
| 243 bfree(&out); |
| 244 vfree(&argv); |
| 245 vfree(&lines); |
| 246 vfree(&fields); |
| 247 } |
| 248 |
| 249 static char *runtimedefs[] = { |
| 250 "proc.c", |
| 251 "iface.c", |
| 252 "hashmap.c", |
| 253 "chan.c", |
| 254 }; |
| 255 |
| 256 // mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h, |
| 257 // which contains Go struct definitions equivalent to the C ones. |
| 258 // Mostly we just write the output of 6c -q to the file. |
| 259 // However, we run it on multiple files, so we have to delete |
| 260 // the duplicated definitions, and we don't care about the funcs |
| 261 // and consts, so we delete those too. |
| 262 //· |
| 263 void |
| 264 mkzruntimedefs(char *dir, char *file) |
| 265 { |
| 266 int i, skip; |
| 267 char *p; |
| 268 Buf in, b, out; |
| 269 Vec argv, lines, fields, seen; |
| 270 ········ |
| 271 binit(&in); |
| 272 binit(&b); |
| 273 binit(&out); |
| 274 vinit(&argv); |
| 275 vinit(&lines); |
| 276 vinit(&fields); |
| 277 vinit(&seen); |
| 278 ········ |
| 279 bwritestr(&out, "// auto generated by go tool dist\n" |
| 280 "\n" |
| 281 "package runtime\n" |
| 282 "import \"unsafe\"\n" |
| 283 "var _ unsafe.Pointer\n" |
| 284 "\n" |
| 285 ); |
| 286 |
| 287 ········ |
| 288 // Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -q |
| 289 // on each of the runtimedefs C files. |
| 290 vadd(&argv, bpathf(&b, "%s/bin/tool/%sc", goroot, gochar)); |
| 291 vadd(&argv, bprintf(&b, "-DGOOS_%s", goos)); |
| 292 vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch)); |
| 293 vadd(&argv, bprintf(&b, "-I%s", workdir)); |
| 294 vadd(&argv, "-q"); |
| 295 vadd(&argv, ""); |
| 296 p = argv.p[argv.len-1]; |
| 297 for(i=0; i<nelem(runtimedefs); i++) { |
| 298 argv.p[argv.len-1] = runtimedefs[i]; |
| 299 runv(&b, dir, CheckExit, &argv); |
| 300 bwriteb(&in, &b); |
| 301 } |
| 302 argv.p[argv.len-1] = p; |
| 303 ················ |
| 304 // Process the aggregate output. |
| 305 skip = 0; |
| 306 splitlines(&lines, bstr(&in)); |
| 307 for(i=0; i<lines.len; i++) { |
| 308 p = lines.p[i]; |
| 309 // Drop comment, func, and const lines. |
| 310 if(hasprefix(p, "//") || hasprefix(p, "const") || hasprefix(p, "
func")) |
| 311 continue; |
| 312 ················ |
| 313 // Note beginning of type or var decl, which can be multiline. |
| 314 // Remove duplicates. The linear check of seen here makes the |
| 315 // whole processing quadratic in aggregate, but there are only |
| 316 // about 100 declarations, so this is okay (and simple). |
| 317 if(hasprefix(p, "type ") || hasprefix(p, "var ")) { |
| 318 splitfields(&fields, p); |
| 319 if(fields.len < 2) |
| 320 continue; |
| 321 if(find(fields.p[1], seen.p, seen.len) >= 0) { |
| 322 if(streq(fields.p[fields.len-1], "{")) |
| 323 skip = 1; // skip until } |
| 324 continue; |
| 325 } |
| 326 vadd(&seen, fields.p[1]); |
| 327 } |
| 328 if(skip) { |
| 329 if(hasprefix(p, "}")) |
| 330 skip = 0; |
| 331 continue; |
| 332 } |
| 333 ················ |
| 334 bwritestr(&out, p); |
| 335 } |
| 336 ········ |
| 337 writefile(&out, file); |
| 338 |
| 339 bfree(&in); |
| 340 bfree(&b); |
| 341 bfree(&out); |
| 342 vfree(&argv); |
| 343 vfree(&lines); |
| 344 vfree(&fields); |
| 345 vfree(&seen); |
| 346 } |
OLD | NEW |