github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/cmd/6l/pass.c (about) 1 // Inferno utils/6l/pass.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 // Code and data passes. 32 33 #include "l.h" 34 #include "../ld/lib.h" 35 #include "../../pkg/runtime/stack.h" 36 37 static void xfol(Prog*, Prog**); 38 39 Prog* 40 brchain(Prog *p) 41 { 42 int i; 43 44 for(i=0; i<20; i++) { 45 if(p == P || p->as != AJMP) 46 return p; 47 p = p->pcond; 48 } 49 return P; 50 } 51 52 void 53 follow(void) 54 { 55 Prog *firstp, *lastp; 56 57 if(debug['v']) 58 Bprint(&bso, "%5.2f follow\n", cputime()); 59 Bflush(&bso); 60 61 for(cursym = textp; cursym != nil; cursym = cursym->next) { 62 firstp = prg(); 63 lastp = firstp; 64 xfol(cursym->text, &lastp); 65 lastp->link = nil; 66 cursym->text = firstp->link; 67 } 68 } 69 70 static int 71 nofollow(int a) 72 { 73 switch(a) { 74 case AJMP: 75 case ARET: 76 case AIRETL: 77 case AIRETQ: 78 case AIRETW: 79 case ARETFL: 80 case ARETFQ: 81 case ARETFW: 82 case AUNDEF: 83 return 1; 84 } 85 return 0; 86 } 87 88 static int 89 pushpop(int a) 90 { 91 switch(a) { 92 case APUSHL: 93 case APUSHFL: 94 case APUSHQ: 95 case APUSHFQ: 96 case APUSHW: 97 case APUSHFW: 98 case APOPL: 99 case APOPFL: 100 case APOPQ: 101 case APOPFQ: 102 case APOPW: 103 case APOPFW: 104 return 1; 105 } 106 return 0; 107 } 108 109 static void 110 xfol(Prog *p, Prog **last) 111 { 112 Prog *q; 113 int i; 114 enum as a; 115 116 loop: 117 if(p == P) 118 return; 119 if(p->as == AJMP) 120 if((q = p->pcond) != P && q->as != ATEXT) { 121 /* mark instruction as done and continue layout at target of jump */ 122 p->mark = 1; 123 p = q; 124 if(p->mark == 0) 125 goto loop; 126 } 127 if(p->mark) { 128 /* 129 * p goes here, but already used it elsewhere. 130 * copy up to 4 instructions or else branch to other copy. 131 */ 132 for(i=0,q=p; i<4; i++,q=q->link) { 133 if(q == P) 134 break; 135 if(q == *last) 136 break; 137 a = q->as; 138 if(a == ANOP) { 139 i--; 140 continue; 141 } 142 if(nofollow(a) || pushpop(a)) 143 break; // NOTE(rsc): arm does goto copy 144 if(q->pcond == P || q->pcond->mark) 145 continue; 146 if(a == ACALL || a == ALOOP) 147 continue; 148 for(;;) { 149 if(p->as == ANOP) { 150 p = p->link; 151 continue; 152 } 153 q = copyp(p); 154 p = p->link; 155 q->mark = 1; 156 (*last)->link = q; 157 *last = q; 158 if(q->as != a || q->pcond == P || q->pcond->mark) 159 continue; 160 161 q->as = relinv(q->as); 162 p = q->pcond; 163 q->pcond = q->link; 164 q->link = p; 165 xfol(q->link, last); 166 p = q->link; 167 if(p->mark) 168 return; 169 goto loop; 170 } 171 } /* */ 172 q = prg(); 173 q->as = AJMP; 174 q->line = p->line; 175 q->to.type = D_BRANCH; 176 q->to.offset = p->pc; 177 q->pcond = p; 178 p = q; 179 } 180 181 /* emit p */ 182 p->mark = 1; 183 (*last)->link = p; 184 *last = p; 185 a = p->as; 186 187 /* continue loop with what comes after p */ 188 if(nofollow(a)) 189 return; 190 if(p->pcond != P && a != ACALL) { 191 /* 192 * some kind of conditional branch. 193 * recurse to follow one path. 194 * continue loop on the other. 195 */ 196 if((q = brchain(p->pcond)) != P) 197 p->pcond = q; 198 if((q = brchain(p->link)) != P) 199 p->link = q; 200 if(p->from.type == D_CONST) { 201 if(p->from.offset == 1) { 202 /* 203 * expect conditional jump to be taken. 204 * rewrite so that's the fall-through case. 205 */ 206 p->as = relinv(a); 207 q = p->link; 208 p->link = p->pcond; 209 p->pcond = q; 210 } 211 } else { 212 q = p->link; 213 if(q->mark) 214 if(a != ALOOP) { 215 p->as = relinv(a); 216 p->link = p->pcond; 217 p->pcond = q; 218 } 219 } 220 xfol(p->link, last); 221 if(p->pcond->mark) 222 return; 223 p = p->pcond; 224 goto loop; 225 } 226 p = p->link; 227 goto loop; 228 } 229 230 Prog* 231 byteq(int v) 232 { 233 Prog *p; 234 235 p = prg(); 236 p->as = ABYTE; 237 p->from.type = D_CONST; 238 p->from.offset = v&0xff; 239 return p; 240 } 241 242 int 243 relinv(int a) 244 { 245 246 switch(a) { 247 case AJEQ: return AJNE; 248 case AJNE: return AJEQ; 249 case AJLE: return AJGT; 250 case AJLS: return AJHI; 251 case AJLT: return AJGE; 252 case AJMI: return AJPL; 253 case AJGE: return AJLT; 254 case AJPL: return AJMI; 255 case AJGT: return AJLE; 256 case AJHI: return AJLS; 257 case AJCS: return AJCC; 258 case AJCC: return AJCS; 259 case AJPS: return AJPC; 260 case AJPC: return AJPS; 261 case AJOS: return AJOC; 262 case AJOC: return AJOS; 263 } 264 diag("unknown relation: %s in %s", anames[a], TNAME); 265 errorexit(); 266 return a; 267 } 268 269 void 270 patch(void) 271 { 272 int32 c; 273 Prog *p, *q; 274 Sym *s, *gmsym; 275 int32 vexit; 276 277 if(debug['v']) 278 Bprint(&bso, "%5.2f mkfwd\n", cputime()); 279 Bflush(&bso); 280 mkfwd(); 281 if(debug['v']) 282 Bprint(&bso, "%5.2f patch\n", cputime()); 283 Bflush(&bso); 284 285 if(flag_shared) { 286 s = lookup("init_array", 0); 287 s->type = SINITARR; 288 s->reachable = 1; 289 s->hide = 1; 290 addaddr(s, lookup(INITENTRY, 0)); 291 } 292 293 gmsym = lookup("runtime.tlsgm", 0); 294 if(linkmode != LinkExternal) 295 gmsym->reachable = 0; 296 s = lookup("exit", 0); 297 vexit = s->value; 298 for(cursym = textp; cursym != nil; cursym = cursym->next) 299 for(p = cursym->text; p != P; p = p->link) { 300 if(HEADTYPE == Hwindows) { 301 // Windows 302 // Convert 303 // op n(GS), reg 304 // to 305 // MOVL 0x28(GS), reg 306 // op n(reg), reg 307 // The purpose of this patch is to fix some accesses 308 // to extern register variables (TLS) on Windows, as 309 // a different method is used to access them. 310 if(p->from.type == D_INDIR+D_GS 311 && p->to.type >= D_AX && p->to.type <= D_DI 312 && p->from.offset <= 8) { 313 q = appendp(p); 314 q->from = p->from; 315 q->from.type = D_INDIR + p->to.type; 316 q->to = p->to; 317 q->as = p->as; 318 p->as = AMOVQ; 319 p->from.type = D_INDIR+D_GS; 320 p->from.offset = 0x28; 321 } 322 } 323 if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd 324 || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd 325 || HEADTYPE == Hplan9x64 || HEADTYPE == Hdragonfly) { 326 // ELF uses FS instead of GS. 327 if(p->from.type == D_INDIR+D_GS) 328 p->from.type = D_INDIR+D_FS; 329 if(p->to.type == D_INDIR+D_GS) 330 p->to.type = D_INDIR+D_FS; 331 if(p->from.index == D_GS) 332 p->from.index = D_FS; 333 if(p->to.index == D_GS) 334 p->to.index = D_FS; 335 } 336 if(!flag_shared) { 337 // Convert g() or m() accesses of the form 338 // op n(reg)(GS*1), reg 339 // to 340 // op n(GS*1), reg 341 if(p->from.index == D_FS || p->from.index == D_GS) { 342 p->from.type = D_INDIR + p->from.index; 343 p->from.index = D_NONE; 344 } 345 // Convert g() or m() accesses of the form 346 // op reg, n(reg)(GS*1) 347 // to 348 // op reg, n(GS*1) 349 if(p->to.index == D_FS || p->to.index == D_GS) { 350 p->to.type = D_INDIR + p->to.index; 351 p->to.index = D_NONE; 352 } 353 // Convert get_tls access of the form 354 // op runtime.tlsgm(SB), reg 355 // to 356 // NOP 357 if(gmsym != S && p->from.sym == gmsym) { 358 p->as = ANOP; 359 p->from.type = D_NONE; 360 p->to.type = D_NONE; 361 p->from.sym = nil; 362 p->to.sym = nil; 363 continue; 364 } 365 } else { 366 // Convert TLS reads of the form 367 // op n(GS), reg 368 // to 369 // MOVQ $runtime.tlsgm(SB), reg 370 // op n(reg)(GS*1), reg 371 if((p->from.type == D_INDIR+D_FS || p->from.type == D_INDIR + D_GS) && p->to.type >= D_AX && p->to.type <= D_DI) { 372 q = appendp(p); 373 q->to = p->to; 374 q->as = p->as; 375 q->from.type = D_INDIR+p->to.type; 376 q->from.index = p->from.type - D_INDIR; 377 q->from.scale = 1; 378 q->from.offset = p->from.offset; 379 p->as = AMOVQ; 380 p->from.type = D_EXTERN; 381 p->from.sym = gmsym; 382 p->from.offset = 0; 383 } 384 } 385 if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH) || (p->as == ARET && p->to.sym != nil)) { 386 s = p->to.sym; 387 if(s) { 388 if(debug['c']) 389 Bprint(&bso, "%s calls %s\n", TNAME, s->name); 390 if((s->type&SMASK) != STEXT) { 391 /* diag prints TNAME first */ 392 diag("undefined: %s", s->name); 393 s->type = STEXT; 394 s->value = vexit; 395 continue; // avoid more error messages 396 } 397 if(s->text == nil) 398 continue; 399 p->to.type = D_BRANCH; 400 p->to.offset = s->text->pc; 401 p->pcond = s->text; 402 continue; 403 } 404 } 405 if(p->to.type != D_BRANCH) 406 continue; 407 c = p->to.offset; 408 for(q = cursym->text; q != P;) { 409 if(c == q->pc) 410 break; 411 if(q->forwd != P && c >= q->forwd->pc) 412 q = q->forwd; 413 else 414 q = q->link; 415 } 416 if(q == P) { 417 diag("branch out of range in %s (%#ux)\n%P [%s]", 418 TNAME, c, p, p->to.sym ? p->to.sym->name : "<nil>"); 419 p->to.type = D_NONE; 420 } 421 p->pcond = q; 422 } 423 424 for(cursym = textp; cursym != nil; cursym = cursym->next) 425 for(p = cursym->text; p != P; p = p->link) { 426 p->mark = 0; /* initialization for follow */ 427 if(p->pcond != P) { 428 p->pcond = brloop(p->pcond); 429 if(p->pcond != P) 430 if(p->to.type == D_BRANCH) 431 p->to.offset = p->pcond->pc; 432 } 433 } 434 } 435 436 Prog* 437 brloop(Prog *p) 438 { 439 int c; 440 Prog *q; 441 442 c = 0; 443 for(q = p; q != P; q = q->pcond) { 444 if(q->as != AJMP) 445 break; 446 c++; 447 if(c >= 5000) 448 return P; 449 } 450 return q; 451 } 452 453 static char* 454 morename[] = 455 { 456 "runtime.morestack00", 457 "runtime.morestack10", 458 "runtime.morestack01", 459 "runtime.morestack11", 460 461 "runtime.morestack8", 462 "runtime.morestack16", 463 "runtime.morestack24", 464 "runtime.morestack32", 465 "runtime.morestack40", 466 "runtime.morestack48", 467 }; 468 Prog* pmorestack[nelem(morename)]; 469 Sym* symmorestack[nelem(morename)]; 470 471 void 472 dostkoff(void) 473 { 474 Prog *p, *q, *q1; 475 int32 autoffset, deltasp; 476 int a, pcsize; 477 uint32 moreconst1, moreconst2, i; 478 Sym *gmsym; 479 480 481 gmsym = lookup("runtime.tlsgm", 0); 482 for(i=0; i<nelem(morename); i++) { 483 symmorestack[i] = lookup(morename[i], 0); 484 if(symmorestack[i]->type != STEXT) 485 diag("morestack trampoline not defined - %s", morename[i]); 486 pmorestack[i] = symmorestack[i]->text; 487 } 488 489 for(cursym = textp; cursym != nil; cursym = cursym->next) { 490 if(cursym->text == nil || cursym->text->link == nil) 491 continue; 492 493 p = cursym->text; 494 parsetextconst(p->to.offset); 495 autoffset = textstksiz; 496 if(autoffset < 0) 497 autoffset = 0; 498 499 if(autoffset < StackSmall && !(p->from.scale & NOSPLIT)) { 500 for(q = p; q != P; q = q->link) 501 if(q->as == ACALL) 502 goto noleaf; 503 p->from.scale |= NOSPLIT; 504 noleaf:; 505 } 506 507 q = P; 508 q1 = P; 509 if((p->from.scale & NOSPLIT) && autoffset >= StackSmall) 510 diag("nosplit func likely to overflow stack"); 511 512 if(!(p->from.scale & NOSPLIT)) { 513 if(flag_shared) { 514 // Load TLS offset with MOVQ $runtime.tlsgm(SB), CX 515 p = appendp(p); 516 p->as = AMOVQ; 517 p->from.type = D_EXTERN; 518 p->from.sym = gmsym; 519 p->to.type = D_CX; 520 } 521 p = appendp(p); // load g into CX 522 p->as = AMOVQ; 523 if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd 524 || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd 525 || HEADTYPE == Hplan9x64 || HEADTYPE == Hdragonfly) 526 // ELF uses FS 527 p->from.type = D_INDIR+D_FS; 528 else 529 p->from.type = D_INDIR+D_GS; 530 if(flag_shared) { 531 // Add TLS offset stored in CX 532 p->from.index = p->from.type - D_INDIR; 533 p->from.type = D_INDIR + D_CX; 534 } 535 p->from.offset = tlsoffset+0; 536 p->to.type = D_CX; 537 if(HEADTYPE == Hwindows) { 538 // movq %gs:0x28, %rcx 539 // movq (%rcx), %rcx 540 p->as = AMOVQ; 541 p->from.type = D_INDIR+D_GS; 542 p->from.offset = 0x28; 543 p->to.type = D_CX; 544 545 546 p = appendp(p); 547 p->as = AMOVQ; 548 p->from.type = D_INDIR+D_CX; 549 p->from.offset = 0; 550 p->to.type = D_CX; 551 } 552 553 if(debug['K']) { 554 // 6l -K means check not only for stack 555 // overflow but stack underflow. 556 // On underflow, INT 3 (breakpoint). 557 // Underflow itself is rare but this also 558 // catches out-of-sync stack guard info 559 560 p = appendp(p); 561 p->as = ACMPQ; 562 p->from.type = D_INDIR+D_CX; 563 p->from.offset = 8; 564 p->to.type = D_SP; 565 566 p = appendp(p); 567 p->as = AJHI; 568 p->to.type = D_BRANCH; 569 p->to.offset = 4; 570 q1 = p; 571 572 p = appendp(p); 573 p->as = AINT; 574 p->from.type = D_CONST; 575 p->from.offset = 3; 576 577 p = appendp(p); 578 p->as = ANOP; 579 q1->pcond = p; 580 } 581 582 q1 = P; 583 if(autoffset <= StackSmall) { 584 // small stack: SP <= stackguard 585 // CMPQ SP, stackguard 586 p = appendp(p); 587 p->as = ACMPQ; 588 p->from.type = D_SP; 589 p->to.type = D_INDIR+D_CX; 590 } else if(autoffset <= StackBig) { 591 // large stack: SP-framesize <= stackguard-StackSmall 592 // LEAQ -xxx(SP), AX 593 // CMPQ AX, stackguard 594 p = appendp(p); 595 p->as = ALEAQ; 596 p->from.type = D_INDIR+D_SP; 597 p->from.offset = -(autoffset-StackSmall); 598 p->to.type = D_AX; 599 600 p = appendp(p); 601 p->as = ACMPQ; 602 p->from.type = D_AX; 603 p->to.type = D_INDIR+D_CX; 604 } else { 605 // Such a large stack we need to protect against wraparound. 606 // If SP is close to zero: 607 // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall) 608 // The +StackGuard on both sides is required to keep the left side positive: 609 // SP is allowed to be slightly below stackguard. See stack.h. 610 // 611 // Preemption sets stackguard to StackPreempt, a very large value. 612 // That breaks the math above, so we have to check for that explicitly. 613 // MOVQ stackguard, CX 614 // CMPQ CX, $StackPreempt 615 // JEQ label-of-call-to-morestack 616 // LEAQ StackGuard(SP), AX 617 // SUBQ CX, AX 618 // CMPQ AX, $(autoffset+(StackGuard-StackSmall)) 619 620 p = appendp(p); 621 p->as = AMOVQ; 622 p->from.type = D_INDIR+D_CX; 623 p->from.offset = 0; 624 p->to.type = D_SI; 625 626 p = appendp(p); 627 p->as = ACMPQ; 628 p->from.type = D_SI; 629 p->to.type = D_CONST; 630 p->to.offset = StackPreempt; 631 632 p = appendp(p); 633 p->as = AJEQ; 634 p->to.type = D_BRANCH; 635 q1 = p; 636 637 p = appendp(p); 638 p->as = ALEAQ; 639 p->from.type = D_INDIR+D_SP; 640 p->from.offset = StackGuard; 641 p->to.type = D_AX; 642 643 p = appendp(p); 644 p->as = ASUBQ; 645 p->from.type = D_SI; 646 p->to.type = D_AX; 647 648 p = appendp(p); 649 p->as = ACMPQ; 650 p->from.type = D_AX; 651 p->to.type = D_CONST; 652 p->to.offset = autoffset+(StackGuard-StackSmall); 653 } 654 655 // common 656 p = appendp(p); 657 p->as = AJHI; 658 p->to.type = D_BRANCH; 659 q = p; 660 661 // If we ask for more stack, we'll get a minimum of StackMin bytes. 662 // We need a stack frame large enough to hold the top-of-stack data, 663 // the function arguments+results, our caller's PC, our frame, 664 // a word for the return PC of the next call, and then the StackLimit bytes 665 // that must be available on entry to any function called from a function 666 // that did a stack check. If StackMin is enough, don't ask for a specific 667 // amount: then we can use the custom functions and save a few 668 // instructions. 669 moreconst1 = 0; 670 if(StackTop + textarg + PtrSize + autoffset + PtrSize + StackLimit >= StackMin) 671 moreconst1 = autoffset; 672 moreconst2 = textarg; 673 if(moreconst2 == 1) // special marker 674 moreconst2 = 0; 675 if((moreconst2&7) != 0) 676 diag("misaligned argument size in stack split"); 677 // 4 varieties varieties (const1==0 cross const2==0) 678 // and 6 subvarieties of (const1==0 and const2!=0) 679 p = appendp(p); 680 if(moreconst1 == 0 && moreconst2 == 0) { 681 p->as = ACALL; 682 p->to.type = D_BRANCH; 683 p->pcond = pmorestack[0]; 684 p->to.sym = symmorestack[0]; 685 } else 686 if(moreconst1 != 0 && moreconst2 == 0) { 687 p->as = AMOVL; 688 p->from.type = D_CONST; 689 p->from.offset = moreconst1; 690 p->to.type = D_AX; 691 692 p = appendp(p); 693 p->as = ACALL; 694 p->to.type = D_BRANCH; 695 p->pcond = pmorestack[1]; 696 p->to.sym = symmorestack[1]; 697 } else 698 if(moreconst1 == 0 && moreconst2 <= 48 && moreconst2%8 == 0) { 699 i = moreconst2/8 + 3; 700 p->as = ACALL; 701 p->to.type = D_BRANCH; 702 p->pcond = pmorestack[i]; 703 p->to.sym = symmorestack[i]; 704 } else 705 if(moreconst1 == 0 && moreconst2 != 0) { 706 p->as = AMOVL; 707 p->from.type = D_CONST; 708 p->from.offset = moreconst2; 709 p->to.type = D_AX; 710 711 p = appendp(p); 712 p->as = ACALL; 713 p->to.type = D_BRANCH; 714 p->pcond = pmorestack[2]; 715 p->to.sym = symmorestack[2]; 716 } else { 717 p->as = AMOVQ; 718 p->from.type = D_CONST; 719 p->from.offset = (uint64)moreconst2 << 32; 720 p->from.offset |= moreconst1; 721 p->to.type = D_AX; 722 723 p = appendp(p); 724 p->as = ACALL; 725 p->to.type = D_BRANCH; 726 p->pcond = pmorestack[3]; 727 p->to.sym = symmorestack[3]; 728 } 729 730 p = appendp(p); 731 p->as = AJMP; 732 p->to.type = D_BRANCH; 733 p->pcond = cursym->text->link; 734 } 735 736 if(q != P) 737 q->pcond = p->link; 738 if(q1 != P) 739 q1->pcond = q->link; 740 741 if(autoffset) { 742 p = appendp(p); 743 p->as = AADJSP; 744 p->from.type = D_CONST; 745 p->from.offset = autoffset; 746 p->spadj = autoffset; 747 if(q != P) 748 q->pcond = p; 749 } else { 750 // zero-byte stack adjustment. 751 // Insert a fake non-zero adjustment so that stkcheck can 752 // recognize the end of the stack-splitting prolog. 753 p = appendp(p); 754 p->as = ANOP; 755 p->spadj = -PtrSize; 756 p = appendp(p); 757 p->as = ANOP; 758 p->spadj = PtrSize; 759 } 760 deltasp = autoffset; 761 762 if(debug['K'] > 1 && autoffset) { 763 // 6l -KK means double-check for stack overflow 764 // even after calling morestack and even if the 765 // function is marked as nosplit. 766 p = appendp(p); 767 p->as = AMOVQ; 768 p->from.type = D_INDIR+D_CX; 769 p->from.offset = 0; 770 p->to.type = D_BX; 771 772 p = appendp(p); 773 p->as = ASUBQ; 774 p->from.type = D_CONST; 775 p->from.offset = StackSmall+32; 776 p->to.type = D_BX; 777 778 p = appendp(p); 779 p->as = ACMPQ; 780 p->from.type = D_SP; 781 p->to.type = D_BX; 782 783 p = appendp(p); 784 p->as = AJHI; 785 p->to.type = D_BRANCH; 786 q1 = p; 787 788 p = appendp(p); 789 p->as = AINT; 790 p->from.type = D_CONST; 791 p->from.offset = 3; 792 793 p = appendp(p); 794 p->as = ANOP; 795 q1->pcond = p; 796 } 797 798 if(debug['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) { 799 // 6l -Z means zero the stack frame on entry. 800 // This slows down function calls but can help avoid 801 // false positives in garbage collection. 802 p = appendp(p); 803 p->as = AMOVQ; 804 p->from.type = D_SP; 805 p->to.type = D_DI; 806 807 p = appendp(p); 808 p->as = AMOVQ; 809 p->from.type = D_CONST; 810 p->from.offset = autoffset/8; 811 p->to.type = D_CX; 812 813 p = appendp(p); 814 p->as = AMOVQ; 815 p->from.type = D_CONST; 816 p->from.offset = 0; 817 p->to.type = D_AX; 818 819 p = appendp(p); 820 p->as = AREP; 821 822 p = appendp(p); 823 p->as = ASTOSQ; 824 } 825 826 for(; p != P; p = p->link) { 827 pcsize = p->mode/8; 828 a = p->from.type; 829 if(a == D_AUTO) 830 p->from.offset += deltasp; 831 if(a == D_PARAM) 832 p->from.offset += deltasp + pcsize; 833 a = p->to.type; 834 if(a == D_AUTO) 835 p->to.offset += deltasp; 836 if(a == D_PARAM) 837 p->to.offset += deltasp + pcsize; 838 839 switch(p->as) { 840 default: 841 continue; 842 case APUSHL: 843 case APUSHFL: 844 deltasp += 4; 845 p->spadj = 4; 846 continue; 847 case APUSHQ: 848 case APUSHFQ: 849 deltasp += 8; 850 p->spadj = 8; 851 continue; 852 case APUSHW: 853 case APUSHFW: 854 deltasp += 2; 855 p->spadj = 2; 856 continue; 857 case APOPL: 858 case APOPFL: 859 deltasp -= 4; 860 p->spadj = -4; 861 continue; 862 case APOPQ: 863 case APOPFQ: 864 deltasp -= 8; 865 p->spadj = -8; 866 continue; 867 case APOPW: 868 case APOPFW: 869 deltasp -= 2; 870 p->spadj = -2; 871 continue; 872 case ARET: 873 break; 874 } 875 876 if(autoffset != deltasp) 877 diag("unbalanced PUSH/POP"); 878 879 if(autoffset) { 880 p->as = AADJSP; 881 p->from.type = D_CONST; 882 p->from.offset = -autoffset; 883 p->spadj = -autoffset; 884 p = appendp(p); 885 p->as = ARET; 886 // If there are instructions following 887 // this ARET, they come from a branch 888 // with the same stackframe, so undo 889 // the cleanup. 890 p->spadj = +autoffset; 891 } 892 if(p->to.sym) // retjmp 893 p->as = AJMP; 894 } 895 } 896 } 897 898 vlong 899 atolwhex(char *s) 900 { 901 vlong n; 902 int f; 903 904 n = 0; 905 f = 0; 906 while(*s == ' ' || *s == '\t') 907 s++; 908 if(*s == '-' || *s == '+') { 909 if(*s++ == '-') 910 f = 1; 911 while(*s == ' ' || *s == '\t') 912 s++; 913 } 914 if(s[0]=='0' && s[1]){ 915 if(s[1]=='x' || s[1]=='X'){ 916 s += 2; 917 for(;;){ 918 if(*s >= '0' && *s <= '9') 919 n = n*16 + *s++ - '0'; 920 else if(*s >= 'a' && *s <= 'f') 921 n = n*16 + *s++ - 'a' + 10; 922 else if(*s >= 'A' && *s <= 'F') 923 n = n*16 + *s++ - 'A' + 10; 924 else 925 break; 926 } 927 } else 928 while(*s >= '0' && *s <= '7') 929 n = n*8 + *s++ - '0'; 930 } else 931 while(*s >= '0' && *s <= '9') 932 n = n*10 + *s++ - '0'; 933 if(f) 934 n = -n; 935 return n; 936 }