github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/cmd/gc/pgen.c (about) 1 // Copyright 2011 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 // "Portable" code generation. 6 // Compiled separately for 5g, 6g, and 8g, so allowed to use gg.h, opt.h. 7 // Must code to the intersection of the three back ends. 8 9 #include <u.h> 10 #include <libc.h> 11 #include "md5.h" 12 #include "gg.h" 13 #include "opt.h" 14 #include "../../runtime/funcdata.h" 15 16 static void allocauto(Prog* p); 17 static void emitptrargsmap(void); 18 19 static Sym* 20 makefuncdatasym(char *namefmt, int64 funcdatakind) 21 { 22 Node nod; 23 Node *pnod; 24 Sym *sym; 25 static int32 nsym; 26 27 snprint(namebuf, sizeof(namebuf), namefmt, nsym++); 28 sym = lookup(namebuf); 29 pnod = newname(sym); 30 pnod->class = PEXTERN; 31 nodconst(&nod, types[TINT32], funcdatakind); 32 gins(AFUNCDATA, &nod, pnod); 33 return sym; 34 } 35 36 // gvardef inserts a VARDEF for n into the instruction stream. 37 // VARDEF is an annotation for the liveness analysis, marking a place 38 // where a complete initialization (definition) of a variable begins. 39 // Since the liveness analysis can see initialization of single-word 40 // variables quite easy, gvardef is usually only called for multi-word 41 // or 'fat' variables, those satisfying isfat(n->type). 42 // However, gvardef is also called when a non-fat variable is initialized 43 // via a block move; the only time this happens is when you have 44 // return f() 45 // for a function with multiple return values exactly matching the return 46 // types of the current function. 47 // 48 // A 'VARDEF x' annotation in the instruction stream tells the liveness 49 // analysis to behave as though the variable x is being initialized at that 50 // point in the instruction stream. The VARDEF must appear before the 51 // actual (multi-instruction) initialization, and it must also appear after 52 // any uses of the previous value, if any. For example, if compiling: 53 // 54 // x = x[1:] 55 // 56 // it is important to generate code like: 57 // 58 // base, len, cap = pieces of x[1:] 59 // VARDEF x 60 // x = {base, len, cap} 61 // 62 // If instead the generated code looked like: 63 // 64 // VARDEF x 65 // base, len, cap = pieces of x[1:] 66 // x = {base, len, cap} 67 // 68 // then the liveness analysis would decide the previous value of x was 69 // unnecessary even though it is about to be used by the x[1:] computation. 70 // Similarly, if the generated code looked like: 71 // 72 // base, len, cap = pieces of x[1:] 73 // x = {base, len, cap} 74 // VARDEF x 75 // 76 // then the liveness analysis will not preserve the new value of x, because 77 // the VARDEF appears to have "overwritten" it. 78 // 79 // VARDEF is a bit of a kludge to work around the fact that the instruction 80 // stream is working on single-word values but the liveness analysis 81 // wants to work on individual variables, which might be multi-word 82 // aggregates. It might make sense at some point to look into letting 83 // the liveness analysis work on single-word values as well, although 84 // there are complications around interface values, slices, and strings, 85 // all of which cannot be treated as individual words. 86 // 87 // VARKILL is the opposite of VARDEF: it marks a value as no longer needed, 88 // even if its address has been taken. That is, a VARKILL annotation asserts 89 // that its argument is certainly dead, for use when the liveness analysis 90 // would not otherwise be able to deduce that fact. 91 92 static void 93 gvardefx(Node *n, int as) 94 { 95 if(n == N) 96 fatal("gvardef nil"); 97 if(n->op != ONAME) { 98 yyerror("gvardef %#O; %N", n->op, n); 99 return; 100 } 101 switch(n->class) { 102 case PAUTO: 103 case PPARAM: 104 case PPARAMOUT: 105 gins(as, N, n); 106 } 107 } 108 109 void 110 gvardef(Node *n) 111 { 112 gvardefx(n, AVARDEF); 113 } 114 115 void 116 gvarkill(Node *n) 117 { 118 gvardefx(n, AVARKILL); 119 } 120 121 static void 122 removevardef(Prog *firstp) 123 { 124 Prog *p; 125 126 for(p = firstp; p != P; p = p->link) { 127 while(p->link != P && (p->link->as == AVARDEF || p->link->as == AVARKILL)) 128 p->link = p->link->link; 129 if(p->to.type == D_BRANCH) 130 while(p->to.u.branch != P && (p->to.u.branch->as == AVARDEF || p->to.u.branch->as == AVARKILL)) 131 p->to.u.branch = p->to.u.branch->link; 132 } 133 } 134 135 static void 136 gcsymdup(Sym *s) 137 { 138 LSym *ls; 139 uint64 lo, hi; 140 141 ls = linksym(s); 142 if(ls->nr > 0) 143 fatal("cannot rosymdup %s with relocations", ls->name); 144 MD5 d; 145 md5reset(&d); 146 md5write(&d, ls->p, ls->np); 147 lo = md5sum(&d, &hi); 148 ls->name = smprint("gclocals·%016llux%016llux", lo, hi); 149 ls->dupok = 1; 150 } 151 152 void 153 compile(Node *fn) 154 { 155 Plist *pl; 156 Node nod1, *n; 157 Prog *ptxt, *p; 158 int32 lno; 159 Type *t; 160 Iter save; 161 vlong oldstksize; 162 NodeList *l; 163 Sym *gcargs; 164 Sym *gclocals; 165 166 if(newproc == N) { 167 newproc = sysfunc("newproc"); 168 deferproc = sysfunc("deferproc"); 169 deferreturn = sysfunc("deferreturn"); 170 panicindex = sysfunc("panicindex"); 171 panicslice = sysfunc("panicslice"); 172 throwreturn = sysfunc("throwreturn"); 173 } 174 175 lno = setlineno(fn); 176 177 curfn = fn; 178 dowidth(curfn->type); 179 180 if(fn->nbody == nil) { 181 if(pure_go || strncmp(fn->nname->sym->name, "init·", 6) == 0) { 182 yyerror("missing function body", fn); 183 goto ret; 184 } 185 if(debug['A']) 186 goto ret; 187 emitptrargsmap(); 188 goto ret; 189 } 190 191 saveerrors(); 192 193 // set up domain for labels 194 clearlabels(); 195 196 if(curfn->type->outnamed) { 197 // add clearing of the output parameters 198 t = structfirst(&save, getoutarg(curfn->type)); 199 while(t != T) { 200 if(t->nname != N) { 201 n = nod(OAS, t->nname, N); 202 typecheck(&n, Etop); 203 curfn->nbody = concat(list1(n), curfn->nbody); 204 } 205 t = structnext(&save); 206 } 207 } 208 209 order(curfn); 210 if(nerrors != 0) 211 goto ret; 212 213 hasdefer = 0; 214 walk(curfn); 215 if(nerrors != 0) 216 goto ret; 217 if(flag_race) 218 racewalk(curfn); 219 if(nerrors != 0) 220 goto ret; 221 222 continpc = P; 223 breakpc = P; 224 225 pl = newplist(); 226 pl->name = linksym(curfn->nname->sym); 227 228 setlineno(curfn); 229 230 nodconst(&nod1, types[TINT32], 0); 231 ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1); 232 if(fn->dupok) 233 ptxt->TEXTFLAG |= DUPOK; 234 if(fn->wrapper) 235 ptxt->TEXTFLAG |= WRAPPER; 236 if(fn->needctxt) 237 ptxt->TEXTFLAG |= NEEDCTXT; 238 if(fn->nosplit) 239 ptxt->TEXTFLAG |= NOSPLIT; 240 241 // Clumsy but important. 242 // See test/recover.go for test cases and src/reflect/value.go 243 // for the actual functions being considered. 244 if(myimportpath != nil && strcmp(myimportpath, "reflect") == 0) { 245 if(strcmp(curfn->nname->sym->name, "callReflect") == 0 || strcmp(curfn->nname->sym->name, "callMethod") == 0) 246 ptxt->TEXTFLAG |= WRAPPER; 247 } 248 249 afunclit(&ptxt->from, curfn->nname); 250 251 ginit(); 252 253 gcargs = makefuncdatasym("gcargs·%d", FUNCDATA_ArgsPointerMaps); 254 gclocals = makefuncdatasym("gclocals·%d", FUNCDATA_LocalsPointerMaps); 255 256 for(t=curfn->paramfld; t; t=t->down) 257 gtrack(tracksym(t->type)); 258 259 for(l=fn->dcl; l; l=l->next) { 260 n = l->n; 261 if(n->op != ONAME) // might be OTYPE or OLITERAL 262 continue; 263 switch(n->class) { 264 case PAUTO: 265 case PPARAM: 266 case PPARAMOUT: 267 nodconst(&nod1, types[TUINTPTR], l->n->type->width); 268 p = gins(ATYPE, l->n, &nod1); 269 p->from.gotype = linksym(ngotype(l->n)); 270 break; 271 } 272 } 273 274 genlist(curfn->enter); 275 genlist(curfn->nbody); 276 gclean(); 277 checklabels(); 278 if(nerrors != 0) 279 goto ret; 280 if(curfn->endlineno) 281 lineno = curfn->endlineno; 282 283 if(curfn->type->outtuple != 0) 284 ginscall(throwreturn, 0); 285 286 ginit(); 287 // TODO: Determine when the final cgen_ret can be omitted. Perhaps always? 288 cgen_ret(nil); 289 if(hasdefer) { 290 // deferreturn pretends to have one uintptr argument. 291 // Reserve space for it so stack scanner is happy. 292 if(maxarg < widthptr) 293 maxarg = widthptr; 294 } 295 gclean(); 296 if(nerrors != 0) 297 goto ret; 298 299 pc->as = ARET; // overwrite AEND 300 pc->lineno = lineno; 301 302 fixjmp(ptxt); 303 if(!debug['N'] || debug['R'] || debug['P']) { 304 regopt(ptxt); 305 nilopt(ptxt); 306 } 307 expandchecks(ptxt); 308 309 oldstksize = stksize; 310 allocauto(ptxt); 311 312 if(0) 313 print("allocauto: %lld to %lld\n", oldstksize, (vlong)stksize); 314 USED(oldstksize); 315 316 setlineno(curfn); 317 if((int64)stksize+maxarg > (1ULL<<31)) { 318 yyerror("stack frame too large (>2GB)"); 319 goto ret; 320 } 321 322 // Emit garbage collection symbols. 323 liveness(curfn, ptxt, gcargs, gclocals); 324 gcsymdup(gcargs); 325 gcsymdup(gclocals); 326 327 defframe(ptxt); 328 329 if(0) 330 frame(0); 331 332 // Remove leftover instrumentation from the instruction stream. 333 removevardef(ptxt); 334 ret: 335 lineno = lno; 336 } 337 338 static void 339 emitptrargsmap(void) 340 { 341 int nptr, nbitmap, j, off; 342 vlong xoffset; 343 Bvec *bv; 344 Sym *sym; 345 346 sym = lookup(smprint("%s.args_stackmap", curfn->nname->sym->name)); 347 348 nptr = curfn->type->argwid / widthptr; 349 bv = bvalloc(nptr*2); 350 nbitmap = 1; 351 if(curfn->type->outtuple > 0) 352 nbitmap = 2; 353 off = duint32(sym, 0, nbitmap); 354 off = duint32(sym, off, bv->n); 355 if(curfn->type->thistuple > 0) { 356 xoffset = 0; 357 twobitwalktype1(getthisx(curfn->type), &xoffset, bv); 358 } 359 if(curfn->type->intuple > 0) { 360 xoffset = 0; 361 twobitwalktype1(getinargx(curfn->type), &xoffset, bv); 362 } 363 for(j = 0; j < bv->n; j += 32) 364 off = duint32(sym, off, bv->b[j/32]); 365 if(curfn->type->outtuple > 0) { 366 xoffset = 0; 367 twobitwalktype1(getoutargx(curfn->type), &xoffset, bv); 368 for(j = 0; j < bv->n; j += 32) 369 off = duint32(sym, off, bv->b[j/32]); 370 } 371 ggloblsym(sym, off, RODATA); 372 free(bv); 373 } 374 375 // Sort the list of stack variables. Autos after anything else, 376 // within autos, unused after used, within used, things with 377 // pointers first, zeroed things first, and then decreasing size. 378 // Because autos are laid out in decreasing addresses 379 // on the stack, pointers first, zeroed things first and decreasing size 380 // really means, in memory, things with pointers needing zeroing at 381 // the top of the stack and increasing in size. 382 // Non-autos sort on offset. 383 static int 384 cmpstackvar(Node *a, Node *b) 385 { 386 int ap, bp; 387 388 if (a->class != b->class) 389 return (a->class == PAUTO) ? +1 : -1; 390 if (a->class != PAUTO) { 391 if (a->xoffset < b->xoffset) 392 return -1; 393 if (a->xoffset > b->xoffset) 394 return +1; 395 return 0; 396 } 397 if ((a->used == 0) != (b->used == 0)) 398 return b->used - a->used; 399 400 ap = haspointers(a->type); 401 bp = haspointers(b->type); 402 if(ap != bp) 403 return bp - ap; 404 405 ap = a->needzero; 406 bp = b->needzero; 407 if(ap != bp) 408 return bp - ap; 409 410 if(a->type->width < b->type->width) 411 return +1; 412 if(a->type->width > b->type->width) 413 return -1; 414 415 return strcmp(a->sym->name, b->sym->name); 416 } 417 418 // TODO(lvd) find out where the PAUTO/OLITERAL nodes come from. 419 static void 420 allocauto(Prog* ptxt) 421 { 422 NodeList *ll; 423 Node* n; 424 vlong w; 425 426 stksize = 0; 427 stkptrsize = 0; 428 429 if(curfn->dcl == nil) 430 return; 431 432 // Mark the PAUTO's unused. 433 for(ll=curfn->dcl; ll != nil; ll=ll->next) 434 if (ll->n->class == PAUTO) 435 ll->n->used = 0; 436 437 markautoused(ptxt); 438 439 listsort(&curfn->dcl, cmpstackvar); 440 441 // Unused autos are at the end, chop 'em off. 442 ll = curfn->dcl; 443 n = ll->n; 444 if (n->class == PAUTO && n->op == ONAME && !n->used) { 445 // No locals used at all 446 curfn->dcl = nil; 447 fixautoused(ptxt); 448 return; 449 } 450 451 for(ll = curfn->dcl; ll->next != nil; ll=ll->next) { 452 n = ll->next->n; 453 if (n->class == PAUTO && n->op == ONAME && !n->used) { 454 ll->next = nil; 455 curfn->dcl->end = ll; 456 break; 457 } 458 } 459 460 // Reassign stack offsets of the locals that are still there. 461 for(ll = curfn->dcl; ll != nil; ll=ll->next) { 462 n = ll->n; 463 if (n->class != PAUTO || n->op != ONAME) 464 continue; 465 466 dowidth(n->type); 467 w = n->type->width; 468 if(w >= MAXWIDTH || w < 0) 469 fatal("bad width"); 470 stksize += w; 471 stksize = rnd(stksize, n->type->align); 472 if(haspointers(n->type)) 473 stkptrsize = stksize; 474 if(thechar == '5' || thechar == '9') 475 stksize = rnd(stksize, widthptr); 476 if(stksize >= (1ULL<<31)) { 477 setlineno(curfn); 478 yyerror("stack frame too large (>2GB)"); 479 } 480 n->stkdelta = -stksize - n->xoffset; 481 } 482 stksize = rnd(stksize, widthreg); 483 stkptrsize = rnd(stkptrsize, widthreg); 484 485 fixautoused(ptxt); 486 487 // The debug information needs accurate offsets on the symbols. 488 for(ll = curfn->dcl; ll != nil; ll=ll->next) { 489 if (ll->n->class != PAUTO || ll->n->op != ONAME) 490 continue; 491 ll->n->xoffset += ll->n->stkdelta; 492 ll->n->stkdelta = 0; 493 } 494 } 495 496 static void movelargefn(Node*); 497 498 void 499 movelarge(NodeList *l) 500 { 501 for(; l; l=l->next) 502 if(l->n->op == ODCLFUNC) 503 movelargefn(l->n); 504 } 505 506 static void 507 movelargefn(Node *fn) 508 { 509 NodeList *l; 510 Node *n; 511 512 for(l=fn->dcl; l != nil; l=l->next) { 513 n = l->n; 514 if(n->class == PAUTO && n->type != T && n->type->width > MaxStackVarSize) 515 addrescapes(n); 516 } 517 } 518 519 void 520 cgen_checknil(Node *n) 521 { 522 Node reg; 523 524 if(disable_checknil) 525 return; 526 // Ideally we wouldn't see any integer types here, but we do. 527 if(n->type == T || (!isptr[n->type->etype] && !isint[n->type->etype] && n->type->etype != TUNSAFEPTR)) { 528 dump("checknil", n); 529 fatal("bad checknil"); 530 } 531 if(((thechar == '5' || thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) { 532 regalloc(®, types[tptr], n); 533 cgen(n, ®); 534 gins(ACHECKNIL, ®, N); 535 regfree(®); 536 return; 537 } 538 gins(ACHECKNIL, n, N); 539 }