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