github.com/hongwozai/go-src-1.4.3@v0.0.0-20191127132709-dc3fce3dbccb/src/cmd/dist/buildruntime.c (about) 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 7 /* 8 * Helpers for building runtime. 9 */ 10 11 // mkzversion writes zversion.go: 12 // 13 // package runtime 14 // const defaultGoroot = <goroot> 15 // const theVersion = <version> 16 // 17 void 18 mkzversion(char *dir, char *file) 19 { 20 Buf b, out; 21 22 USED(dir); 23 24 binit(&b); 25 binit(&out); 26 27 bwritestr(&out, bprintf(&b, 28 "// auto generated by go tool dist\n" 29 "\n" 30 "package runtime\n" 31 "\n" 32 "const defaultGoroot = `%s`\n" 33 "const theVersion = `%s`\n" 34 "var buildVersion = theVersion\n", goroot_final, goversion)); 35 36 writefile(&out, file, 0); 37 38 bfree(&b); 39 bfree(&out); 40 } 41 42 // mkzexperiment writes zaexperiment.h (sic): 43 // 44 // #define GOEXPERIMENT "experiment string" 45 // 46 void 47 mkzexperiment(char *dir, char *file) 48 { 49 Buf b, out, exp; 50 51 USED(dir); 52 53 binit(&b); 54 binit(&out); 55 binit(&exp); 56 57 xgetenv(&exp, "GOEXPERIMENT"); 58 bwritestr(&out, bprintf(&b, 59 "// auto generated by go tool dist\n" 60 "\n" 61 "#define GOEXPERIMENT \"%s\"\n", bstr(&exp))); 62 63 writefile(&out, file, 0); 64 65 bfree(&b); 66 bfree(&out); 67 bfree(&exp); 68 } 69 70 // mkzgoarch writes zgoarch_$GOARCH.go: 71 // 72 // package runtime 73 // const theGoarch = <goarch> 74 // 75 void 76 mkzgoarch(char *dir, char *file) 77 { 78 Buf b, out; 79 80 USED(dir); 81 82 binit(&b); 83 binit(&out); 84 85 bwritestr(&out, bprintf(&b, 86 "// auto generated by go tool dist\n" 87 "\n" 88 "package runtime\n" 89 "\n" 90 "const theGoarch = `%s`\n", goarch)); 91 92 writefile(&out, file, 0); 93 94 bfree(&b); 95 bfree(&out); 96 } 97 98 // mkzgoos writes zgoos_$GOOS.go: 99 // 100 // package runtime 101 // const theGoos = <goos> 102 // 103 void 104 mkzgoos(char *dir, char *file) 105 { 106 Buf b, out; 107 108 USED(dir); 109 110 binit(&b); 111 binit(&out); 112 113 bwritestr(&out, "// auto generated by go tool dist\n\n"); 114 115 if(streq(goos, "linux")) { 116 bwritestr(&out, "// +build !android\n\n"); 117 } 118 119 bwritestr(&out, bprintf(&b, 120 "package runtime\n" 121 "\n" 122 "const theGoos = `%s`\n", goos)); 123 124 writefile(&out, file, 0); 125 126 bfree(&b); 127 bfree(&out); 128 } 129 130 static struct { 131 char *goarch; 132 char *goos; 133 char *hdr; 134 } zasmhdr[] = { 135 {"386", "", 136 "#define get_tls(r) MOVL TLS, r\n" 137 "#define g(r) 0(r)(TLS*1)\n" 138 }, 139 {"amd64p32", "", 140 "#define get_tls(r) MOVL TLS, r\n" 141 "#define g(r) 0(r)(TLS*1)\n" 142 }, 143 {"amd64", "", 144 "#define get_tls(r) MOVQ TLS, r\n" 145 "#define g(r) 0(r)(TLS*1)\n" 146 }, 147 148 {"arm", "", 149 "#define LR R14\n" 150 }, 151 }; 152 153 #define MAXWINCB 2000 /* maximum number of windows callbacks allowed */ 154 155 // mkzasm writes zasm_$GOOS_$GOARCH.h, 156 // which contains struct offsets for use by 157 // assembly files. It also writes a copy to the work space 158 // under the name zasm_GOOS_GOARCH.h (no expansion). 159 // 160 void 161 mkzasm(char *dir, char *file) 162 { 163 int i, n; 164 char *aggr, *p; 165 Buf in, b, b1, out, exp; 166 Vec argv, lines, fields; 167 168 binit(&in); 169 binit(&b); 170 binit(&b1); 171 binit(&out); 172 binit(&exp); 173 vinit(&argv); 174 vinit(&lines); 175 vinit(&fields); 176 177 bwritestr(&out, "// auto generated by go tool dist\n\n"); 178 if(streq(goos, "linux")) { 179 bwritestr(&out, "// +build !android\n\n"); 180 } 181 182 for(i=0; i<nelem(zasmhdr); i++) { 183 if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) { 184 bwritestr(&out, zasmhdr[i].hdr); 185 goto ok; 186 } 187 } 188 fatal("unknown $GOOS/$GOARCH in mkzasm"); 189 ok: 190 191 copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch), 192 bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0); 193 194 // Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a -n -o workdir/proc.acid proc.c 195 // to get acid [sic] output. Run once without the -a -o workdir/proc.acid in order to 196 // report compilation failures (the -o redirects all messages, unfortunately). 197 vreset(&argv); 198 vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar)); 199 vadd(&argv, "-D"); 200 vadd(&argv, bprintf(&b, "GOOS_%s", goos)); 201 vadd(&argv, "-D"); 202 vadd(&argv, bprintf(&b, "GOARCH_%s", goarch)); 203 vadd(&argv, "-I"); 204 vadd(&argv, bprintf(&b, "%s", workdir)); 205 vadd(&argv, "-I"); 206 vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch)); 207 vadd(&argv, "-n"); 208 vadd(&argv, "-a"); 209 vadd(&argv, "-o"); 210 vadd(&argv, bpathf(&b, "%s/proc.acid", workdir)); 211 vadd(&argv, "proc.c"); 212 runv(nil, dir, CheckExit, &argv); 213 readfile(&in, bpathf(&b, "%s/proc.acid", workdir)); 214 215 // Convert input like 216 // aggr G 217 // { 218 // Gobuf 24 sched; 219 // 'Y' 48 stack0; 220 // } 221 // StackMin = 128; 222 // into output like 223 // #define g_sched 24 224 // #define g_stack0 48 225 // #define const_StackMin 128 226 aggr = nil; 227 splitlines(&lines, bstr(&in)); 228 for(i=0; i<lines.len; i++) { 229 splitfields(&fields, lines.p[i]); 230 if(fields.len == 2 && streq(fields.p[0], "aggr")) { 231 if(streq(fields.p[1], "G")) 232 aggr = "g"; 233 else if(streq(fields.p[1], "M")) 234 aggr = "m"; 235 else if(streq(fields.p[1], "P")) 236 aggr = "p"; 237 else if(streq(fields.p[1], "Gobuf")) 238 aggr = "gobuf"; 239 else if(streq(fields.p[1], "LibCall")) 240 aggr = "libcall"; 241 else if(streq(fields.p[1], "WinCallbackContext")) 242 aggr = "cbctxt"; 243 else if(streq(fields.p[1], "SEH")) 244 aggr = "seh"; 245 else if(streq(fields.p[1], "Alg")) 246 aggr = "alg"; 247 else if(streq(fields.p[1], "Panic")) 248 aggr = "panic"; 249 else if(streq(fields.p[1], "Stack")) 250 aggr = "stack"; 251 } 252 if(hasprefix(lines.p[i], "}")) 253 aggr = nil; 254 if(aggr && hasprefix(lines.p[i], "\t") && fields.len >= 2) { 255 n = fields.len; 256 p = fields.p[n-1]; 257 if(p[xstrlen(p)-1] == ';') 258 p[xstrlen(p)-1] = '\0'; 259 bwritestr(&out, bprintf(&b, "#define %s_%s %s\n", aggr, fields.p[n-1], fields.p[n-2])); 260 } 261 if(fields.len == 3 && streq(fields.p[1], "=")) { // generated from enumerated constants 262 p = fields.p[2]; 263 if(p[xstrlen(p)-1] == ';') 264 p[xstrlen(p)-1] = '\0'; 265 bwritestr(&out, bprintf(&b, "#define const_%s %s\n", fields.p[0], p)); 266 } 267 } 268 269 // Some #defines that are used for .c files. 270 if(streq(goos, "windows")) { 271 bwritestr(&out, bprintf(&b, "#define cb_max %d\n", MAXWINCB)); 272 } 273 274 xgetenv(&exp, "GOEXPERIMENT"); 275 bwritestr(&out, bprintf(&b, "#define GOEXPERIMENT \"%s\"\n", bstr(&exp))); 276 277 // Write both to file and to workdir/zasm_GOOS_GOARCH.h. 278 writefile(&out, file, 0); 279 writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0); 280 281 bfree(&in); 282 bfree(&b); 283 bfree(&b1); 284 bfree(&out); 285 bfree(&exp); 286 vfree(&argv); 287 vfree(&lines); 288 vfree(&fields); 289 } 290 291 // mkzsys writes zsys_$GOOS_$GOARCH.s, 292 // which contains arch or os specific asm code. 293 // 294 void 295 mkzsys(char *dir, char *file) 296 { 297 int i; 298 Buf out; 299 300 USED(dir); 301 302 binit(&out); 303 304 bwritestr(&out, "// auto generated by go tool dist\n\n"); 305 if(streq(goos, "linux")) { 306 bwritestr(&out, "// +build !android\n\n"); 307 } 308 309 if(streq(goos, "windows")) { 310 bwritef(&out, 311 "// runtime·callbackasm is called by external code to\n" 312 "// execute Go implemented callback function. It is not\n" 313 "// called from the start, instead runtime·compilecallback\n" 314 "// always returns address into runtime·callbackasm offset\n" 315 "// appropriately so different callbacks start with different\n" 316 "// CALL instruction in runtime·callbackasm. This determines\n" 317 "// which Go callback function is executed later on.\n" 318 "TEXT runtime·callbackasm(SB),7,$0\n"); 319 for(i=0; i<MAXWINCB; i++) { 320 bwritef(&out, "\tCALL\truntime·callbackasm1(SB)\n"); 321 } 322 bwritef(&out, "\tRET\n"); 323 } 324 325 writefile(&out, file, 0); 326 327 bfree(&out); 328 } 329 330 static char *runtimedefs[] = { 331 "defs.c", 332 "malloc.c", 333 "mcache.c", 334 "mgc0.c", 335 "proc.c", 336 "parfor.c", 337 "stack.c", 338 }; 339 340 // mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h, 341 // which contains Go struct definitions equivalent to the C ones. 342 // Mostly we just write the output of 6c -q to the file. 343 // However, we run it on multiple files, so we have to delete 344 // the duplicated definitions, and we don't care about the funcs, 345 // so we delete those too. 346 // 347 void 348 mkzruntimedefs(char *dir, char *file) 349 { 350 int i, skip; 351 char *p; 352 Buf in, b, b1, out; 353 Vec argv, lines, fields, seen; 354 355 binit(&in); 356 binit(&b); 357 binit(&b1); 358 binit(&out); 359 vinit(&argv); 360 vinit(&lines); 361 vinit(&fields); 362 vinit(&seen); 363 364 bwritestr(&out, "// auto generated by go tool dist\n" 365 "\n"); 366 367 if(streq(goos, "linux")) { 368 bwritestr(&out, "// +build !android\n\n"); 369 } 370 371 bwritestr(&out, 372 "package runtime\n" 373 "import \"unsafe\"\n" 374 "var _ unsafe.Pointer\n" 375 "\n" 376 ); 377 378 // Do not emit definitions for these. 379 vadd(&seen, "true"); 380 vadd(&seen, "false"); 381 vadd(&seen, "raceenabled"); 382 vadd(&seen, "allgs"); 383 384 // Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -q -n -o workdir/runtimedefs 385 // on each of the runtimedefs C files. 386 vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar)); 387 vadd(&argv, "-D"); 388 vadd(&argv, bprintf(&b, "GOOS_%s", goos)); 389 vadd(&argv, "-D"); 390 vadd(&argv, bprintf(&b, "GOARCH_%s", goarch)); 391 vadd(&argv, "-I"); 392 vadd(&argv, bprintf(&b, "%s", workdir)); 393 vadd(&argv, "-I"); 394 vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch)); 395 vadd(&argv, "-q"); 396 vadd(&argv, "-n"); 397 vadd(&argv, "-o"); 398 vadd(&argv, bpathf(&b, "%s/runtimedefs", workdir)); 399 vadd(&argv, ""); 400 p = argv.p[argv.len-1]; 401 for(i=0; i<nelem(runtimedefs); i++) { 402 argv.p[argv.len-1] = runtimedefs[i]; 403 runv(nil, dir, CheckExit, &argv); 404 readfile(&b, bpathf(&b1, "%s/runtimedefs", workdir)); 405 bwriteb(&in, &b); 406 } 407 argv.p[argv.len-1] = p; 408 409 // Process the aggregate output. 410 skip = 0; 411 splitlines(&lines, bstr(&in)); 412 for(i=0; i<lines.len; i++) { 413 p = lines.p[i]; 414 // Drop comment and func lines. 415 if(hasprefix(p, "//") || hasprefix(p, "func")) 416 continue; 417 418 // Note beginning of type or var decl, which can be multiline. 419 // Remove duplicates. The linear check of seen here makes the 420 // whole processing quadratic in aggregate, but there are only 421 // about 100 declarations, so this is okay (and simple). 422 if(hasprefix(p, "type ") || hasprefix(p, "var ") || hasprefix(p, "const ")) { 423 splitfields(&fields, p); 424 if(fields.len < 2) 425 continue; 426 if(find(fields.p[1], seen.p, seen.len) >= 0) { 427 if(streq(fields.p[fields.len-1], "{")) 428 skip = 1; // skip until } 429 continue; 430 } 431 vadd(&seen, fields.p[1]); 432 } 433 434 // Const lines are printed in original case (usually upper). Add a leading _ as needed. 435 if(hasprefix(p, "const ")) { 436 if('A' <= p[6] && p[6] <= 'Z') 437 bwritestr(&out, "const _"); 438 else 439 bwritestr(&out, "const "); 440 bwritestr(&out, p+6); 441 continue; 442 } 443 444 if(skip) { 445 if(hasprefix(p, "}")) 446 skip = 0; 447 continue; 448 } 449 450 bwritestr(&out, p); 451 } 452 453 // Some windows specific const. 454 if(streq(goos, "windows")) { 455 bwritestr(&out, bprintf(&b, "const cb_max = %d\n", MAXWINCB)); 456 } 457 458 writefile(&out, file, 0); 459 460 bfree(&in); 461 bfree(&b); 462 bfree(&b1); 463 bfree(&out); 464 vfree(&argv); 465 vfree(&lines); 466 vfree(&fields); 467 vfree(&seen); 468 }