1 #include "l.h" 2 3 void 4 dodata(void) 5 { 6 int i; 7 Sym *s; 8 Prog *p; 9 long t, u; 10 11 if(debug['v']) 12 Bprint(&bso, "%5.2f dodata\n", cputime()); 13 Bflush(&bso); 14 for(p = datap; p != P; p = p->link) { 15 s = p->from.sym; 16 if(p->as == ADYNT || p->as == AINIT) 17 s->value = dtype; 18 if(s->type == SBSS) 19 s->type = SDATA; 20 if(s->type != SDATA) 21 diag("initialize non-data (%d): %s\n%P", 22 s->type, s->name, p); 23 t = p->from.offset + p->width; 24 if(t > s->value) 25 diag("initialize bounds (%ld): %s\n%P", 26 s->value, s->name, p); 27 } 28 /* allocate small guys */ 29 datsize = 0; 30 for(i=0; i<NHASH; i++) 31 for(s = hash[i]; s != S; s = s->link) { 32 if(s->type != SDATA) 33 if(s->type != SBSS) 34 continue; 35 t = s->value; 36 if(t == 0) { 37 diag("%s: no size", s->name); 38 t = 1; 39 } 40 t = rnd(t, 4);; 41 s->value = t; 42 if(t > MINSIZ) 43 continue; 44 s->value = datsize; 45 datsize += t; 46 s->type = SDATA1; 47 } 48 49 /* allocate the rest of the data */ 50 for(i=0; i<NHASH; i++) 51 for(s = hash[i]; s != S; s = s->link) { 52 if(s->type != SDATA) { 53 if(s->type == SDATA1) 54 s->type = SDATA; 55 continue; 56 } 57 t = s->value; 58 s->value = datsize; 59 datsize += t; 60 } 61 62 if(debug['j']) { 63 /* 64 * pad data with bss that fits up to next 65 * 8k boundary, then push data to 8k 66 */ 67 u = rnd(datsize, 8192); 68 u -= datsize; 69 for(i=0; i<NHASH; i++) 70 for(s = hash[i]; s != S; s = s->link) { 71 if(s->type != SBSS) 72 continue; 73 t = s->value; 74 if(t > u) 75 continue; 76 u -= t; 77 s->value = datsize; 78 s->type = SDATA; 79 datsize += t; 80 } 81 datsize += u; 82 } 83 84 /* now the bss */ 85 bsssize = 0; 86 for(i=0; i<NHASH; i++) 87 for(s = hash[i]; s != S; s = s->link) { 88 if(s->type != SBSS) 89 continue; 90 t = s->value; 91 s->value = bsssize + datsize; 92 bsssize += t; 93 } 94 xdefine("edata", SBSS, datsize); 95 xdefine("end", SBSS, bsssize + datsize); 96 } 97 98 Prog* 99 brchain(Prog *p) 100 { 101 int i; 102 103 for(i=0; i<20; i++) { 104 if(p == P || p->as != AJMP) 105 return p; 106 p = p->pcond; 107 } 108 return P; 109 } 110 111 void 112 follow(void) 113 { 114 115 if(debug['v']) 116 Bprint(&bso, "%5.2f follow\n", cputime()); 117 Bflush(&bso); 118 firstp = prg(); 119 lastp = firstp; 120 xfol(textp); 121 lastp->link = P; 122 firstp = firstp->link; 123 } 124 125 void 126 xfol(Prog *p) 127 { 128 Prog *q; 129 int i; 130 enum as a; 131 132 loop: 133 if(p == P) 134 return; 135 if(p->as == ATEXT) 136 curtext = p; 137 if(p->as == AJMP) 138 if((q = p->pcond) != P) { 139 p->mark = 1; 140 p = q; 141 if(p->mark == 0) 142 goto loop; 143 } 144 if(p->mark) { 145 /* copy up to 4 instructions to avoid branch */ 146 for(i=0,q=p; i<4; i++,q=q->link) { 147 if(q == P) 148 break; 149 if(q == lastp) 150 break; 151 a = q->as; 152 if(a == ANOP) { 153 i--; 154 continue; 155 } 156 switch(a) { 157 case AJMP: 158 case ARET: 159 case AIRETL: 160 161 case APUSHL: 162 case APUSHFL: 163 case APUSHW: 164 case APUSHFW: 165 case APOPL: 166 case APOPFL: 167 case APOPW: 168 case APOPFW: 169 goto brk; 170 } 171 if(q->pcond == P || q->pcond->mark) 172 continue; 173 if(a == ACALL || a == ALOOP) 174 continue; 175 for(;;) { 176 if(p->as == ANOP) { 177 p = p->link; 178 continue; 179 } 180 q = copyp(p); 181 p = p->link; 182 q->mark = 1; 183 lastp->link = q; 184 lastp = q; 185 if(q->as != a || q->pcond == P || q->pcond->mark) 186 continue; 187 188 q->as = relinv(q->as); 189 p = q->pcond; 190 q->pcond = q->link; 191 q->link = p; 192 xfol(q->link); 193 p = q->link; 194 if(p->mark) 195 return; 196 goto loop; 197 } 198 } /* */ 199 brk:; 200 q = prg(); 201 q->as = AJMP; 202 q->line = p->line; 203 q->to.type = D_BRANCH; 204 q->to.offset = p->pc; 205 q->pcond = p; 206 p = q; 207 } 208 p->mark = 1; 209 lastp->link = p; 210 lastp = p; 211 a = p->as; 212 if(a == AJMP || a == ARET || a == AIRETL) 213 return; 214 if(p->pcond != P) 215 if(a != ACALL) { 216 q = brchain(p->link); 217 if(q != P && q->mark) 218 if(a != ALOOP) { 219 p->as = relinv(a); 220 p->link = p->pcond; 221 p->pcond = q; 222 } 223 xfol(p->link); 224 q = brchain(p->pcond); 225 if(q->mark) { 226 p->pcond = q; 227 return; 228 } 229 p = q; 230 goto loop; 231 } 232 p = p->link; 233 goto loop; 234 } 235 236 int 237 relinv(int a) 238 { 239 240 switch(a) { 241 case AJEQ: return AJNE; 242 case AJNE: return AJEQ; 243 case AJLE: return AJGT; 244 case AJLS: return AJHI; 245 case AJLT: return AJGE; 246 case AJMI: return AJPL; 247 case AJGE: return AJLT; 248 case AJPL: return AJMI; 249 case AJGT: return AJLE; 250 case AJHI: return AJLS; 251 case AJCS: return AJCC; 252 case AJCC: return AJCS; 253 case AJPS: return AJPC; 254 case AJPC: return AJPS; 255 case AJOS: return AJOC; 256 case AJOC: return AJOS; 257 } 258 diag("unknown relation: %s in %s", anames[a], TNAME); 259 return a; 260 } 261 262 void 263 doinit(void) 264 { 265 Sym *s; 266 Prog *p; 267 int x; 268 269 for(p = datap; p != P; p = p->link) { 270 x = p->to.type; 271 if(x != D_EXTERN && x != D_STATIC) 272 continue; 273 s = p->to.sym; 274 if(s->type == 0 || s->type == SXREF) 275 diag("undefined %s initializer of %s", 276 s->name, p->from.sym->name); 277 p->to.offset += s->value; 278 p->to.type = D_CONST; 279 if(s->type == SDATA || s->type == SBSS) 280 p->to.offset += INITDAT; 281 } 282 } 283 284 void 285 patch(void) 286 { 287 long c; 288 Prog *p, *q; 289 Sym *s; 290 long vexit; 291 292 if(debug['v']) 293 Bprint(&bso, "%5.2f mkfwd\n", cputime()); 294 Bflush(&bso); 295 mkfwd(); 296 if(debug['v']) 297 Bprint(&bso, "%5.2f patch\n", cputime()); 298 Bflush(&bso); 299 s = lookup("exit", 0); 300 vexit = s->value; 301 for(p = firstp; p != P; p = p->link) { 302 if(p->as == ATEXT) 303 curtext = p; 304 if(p->as == ACALL || p->as == ARET) { 305 s = p->to.sym; 306 if(s) { 307 if(debug['c']) 308 Bprint(&bso, "%s calls %s\n", TNAME, s->name); 309 switch(s->type) { 310 default: 311 diag("undefined: %s in %s", s->name, TNAME); 312 s->type = STEXT; 313 s->value = vexit; 314 break; /* or fall through to set offset? */ 315 case STEXT: 316 p->to.offset = s->value; 317 break; 318 case SUNDEF: 319 p->pcond = UP; 320 p->to.offset = 0; 321 break; 322 } 323 p->to.type = D_BRANCH; 324 } 325 } 326 if(p->to.type != D_BRANCH || p->pcond == UP) 327 continue; 328 c = p->to.offset; 329 for(q = firstp; q != P;) { 330 if(q->forwd != P) 331 if(c >= q->forwd->pc) { 332 q = q->forwd; 333 continue; 334 } 335 if(c == q->pc) 336 break; 337 q = q->link; 338 } 339 if(q == P) { 340 diag("branch out of range in %s\n%P", TNAME, p); 341 p->to.type = D_NONE; 342 } 343 p->pcond = q; 344 } 345 346 for(p = firstp; p != P; p = p->link) { 347 if(p->as == ATEXT) 348 curtext = p; 349 p->mark = 0; /* initialization for follow */ 350 if(p->pcond != P && p->pcond != UP) { 351 p->pcond = brloop(p->pcond); 352 if(p->pcond != P) 353 if(p->to.type == D_BRANCH) 354 p->to.offset = p->pcond->pc; 355 } 356 } 357 } 358 359 #define LOG 5 360 void 361 mkfwd(void) 362 { 363 Prog *p; 364 int i; 365 long dwn[LOG], cnt[LOG]; 366 Prog *lst[LOG]; 367 368 for(i=0; i<LOG; i++) { 369 if(i == 0) 370 cnt[i] = 1; else 371 cnt[i] = LOG * cnt[i-1]; 372 dwn[i] = 1; 373 lst[i] = P; 374 } 375 i = 0; 376 for(p = firstp; p != P; p = p->link) { 377 if(p->as == ATEXT) 378 curtext = p; 379 i--; 380 if(i < 0) 381 i = LOG-1; 382 p->forwd = P; 383 dwn[i]--; 384 if(dwn[i] <= 0) { 385 dwn[i] = cnt[i]; 386 if(lst[i] != P) 387 lst[i]->forwd = p; 388 lst[i] = p; 389 } 390 } 391 } 392 393 Prog* 394 brloop(Prog *p) 395 { 396 int c; 397 Prog *q; 398 399 c = 0; 400 for(q = p; q != P; q = q->pcond) { 401 if(q->as != AJMP) 402 break; 403 c++; 404 if(c >= 5000) 405 return P; 406 } 407 return q; 408 } 409 410 void 411 dostkoff(void) 412 { 413 Prog *p, *q; 414 long autoffset, deltasp; 415 int a, f, curframe, curbecome, maxbecome; 416 417 curframe = 0; 418 curbecome = 0; 419 maxbecome = 0; 420 curtext = 0; 421 for(p = firstp; p != P; p = p->link) { 422 423 /* find out how much arg space is used in this TEXT */ 424 if(p->to.type == (D_INDIR+D_SP)) 425 if(p->to.offset > curframe) 426 curframe = p->to.offset; 427 428 switch(p->as) { 429 case ATEXT: 430 if(curtext && curtext->from.sym) { 431 curtext->from.sym->frame = curframe; 432 curtext->from.sym->become = curbecome; 433 if(curbecome > maxbecome) 434 maxbecome = curbecome; 435 } 436 curframe = 0; 437 curbecome = 0; 438 439 curtext = p; 440 break; 441 442 case ARET: 443 /* special form of RET is BECOME */ 444 if(p->from.type == D_CONST) 445 if(p->from.offset > curbecome) 446 curbecome = p->from.offset; 447 break; 448 } 449 } 450 if(curtext && curtext->from.sym) { 451 curtext->from.sym->frame = curframe; 452 curtext->from.sym->become = curbecome; 453 if(curbecome > maxbecome) 454 maxbecome = curbecome; 455 } 456 457 if(debug['b']) 458 print("max become = %d\n", maxbecome); 459 xdefine("ALEFbecome", STEXT, maxbecome); 460 461 curtext = 0; 462 for(p = firstp; p != P; p = p->link) { 463 switch(p->as) { 464 case ATEXT: 465 curtext = p; 466 break; 467 case ACALL: 468 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { 469 f = maxbecome - curtext->from.sym->frame; 470 if(f <= 0) 471 break; 472 /* calling a become or calling a variable */ 473 if(p->to.sym == S || p->to.sym->become) { 474 curtext->to.offset += f; 475 if(debug['b']) { 476 curp = p; 477 print("%D calling %D increase %d\n", 478 &curtext->from, &p->to, f); 479 } 480 } 481 } 482 break; 483 } 484 } 485 486 autoffset = 0; 487 deltasp = 0; 488 for(p = firstp; p != P; p = p->link) { 489 if(p->as == ATEXT) { 490 curtext = p; 491 autoffset = p->to.offset; 492 if(autoffset < 0) 493 autoffset = 0; 494 if(autoffset) { 495 p = appendp(p); 496 p->as = AADJSP; 497 p->from.type = D_CONST; 498 p->from.offset = autoffset; 499 } 500 deltasp = autoffset; 501 } 502 a = p->from.type; 503 if(a == D_AUTO) 504 p->from.offset += deltasp; 505 if(a == D_PARAM) 506 p->from.offset += deltasp + 4; 507 a = p->to.type; 508 if(a == D_AUTO) 509 p->to.offset += deltasp; 510 if(a == D_PARAM) 511 p->to.offset += deltasp + 4; 512 513 switch(p->as) { 514 default: 515 continue; 516 case APUSHL: 517 case APUSHFL: 518 deltasp += 4; 519 continue; 520 case APUSHW: 521 case APUSHFW: 522 deltasp += 2; 523 continue; 524 case APOPL: 525 case APOPFL: 526 deltasp -= 4; 527 continue; 528 case APOPW: 529 case APOPFW: 530 deltasp -= 2; 531 continue; 532 case ARET: 533 break; 534 } 535 536 if(autoffset != deltasp) 537 diag("unbalanced PUSH/POP"); 538 if(p->from.type == D_CONST) 539 goto become; 540 541 if(autoffset) { 542 q = p; 543 p = appendp(p); 544 p->as = ARET; 545 546 q->as = AADJSP; 547 q->from.type = D_CONST; 548 q->from.offset = -autoffset; 549 } 550 continue; 551 552 become: 553 q = p; 554 p = appendp(p); 555 p->as = AJMP; 556 p->to = q->to; 557 p->pcond = q->pcond; 558 559 q->as = AADJSP; 560 q->from = zprg.from; 561 q->from.type = D_CONST; 562 q->from.offset = -autoffset; 563 q->to = zprg.to; 564 continue; 565 } 566 } 567 568 long 569 atolwhex(char *s) 570 { 571 long n; 572 int f; 573 574 n = 0; 575 f = 0; 576 while(*s == ' ' || *s == '\t') 577 s++; 578 if(*s == '-' || *s == '+') { 579 if(*s++ == '-') 580 f = 1; 581 while(*s == ' ' || *s == '\t') 582 s++; 583 } 584 if(s[0]=='0' && s[1]){ 585 if(s[1]=='x' || s[1]=='X'){ 586 s += 2; 587 for(;;){ 588 if(*s >= '0' && *s <= '9') 589 n = n*16 + *s++ - '0'; 590 else if(*s >= 'a' && *s <= 'f') 591 n = n*16 + *s++ - 'a' + 10; 592 else if(*s >= 'A' && *s <= 'F') 593 n = n*16 + *s++ - 'A' + 10; 594 else 595 break; 596 } 597 } else 598 while(*s >= '0' && *s <= '7') 599 n = n*8 + *s++ - '0'; 600 } else 601 while(*s >= '0' && *s <= '9') 602 n = n*10 + *s++ - '0'; 603 if(f) 604 n = -n; 605 return n; 606 } 607 608 void 609 undef(void) 610 { 611 int i; 612 Sym *s; 613 614 for(i=0; i<NHASH; i++) 615 for(s = hash[i]; s != S; s = s->link) 616 if(s->type == SXREF) 617 diag("%s: not defined", s->name); 618 } 619 620 void 621 import(void) 622 { 623 int i; 624 Sym *s; 625 626 for(i = 0; i < NHASH; i++) 627 for(s = hash[i]; s != S; s = s->link) 628 if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){ 629 if(s->value != 0) 630 diag("value != 0 on SXREF"); 631 undefsym(s); 632 if(debug['X']) 633 Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value); 634 if(debug['S']) 635 s->sig = 0; 636 } 637 } 638 639 void 640 ckoff(Sym *s, long v) 641 { 642 if(v < 0 || v >= 1<<Roffset) 643 diag("relocation offset %ld for %s out of range", v, s->name); 644 } 645 646 static Prog* 647 newdata(Sym *s, int o, int w, int t) 648 { 649 Prog *p; 650 651 p = prg(); 652 if(edatap == P) 653 datap = p; 654 else 655 edatap->link = p; 656 edatap = p; 657 p->as = ADATA; 658 p->width = w; 659 p->from.scale = w; 660 p->from.type = t; 661 p->from.sym = s; 662 p->from.offset = o; 663 p->to.type = D_CONST; 664 return p; 665 } 666 667 void 668 export(void) 669 { 670 int i, j, n, off, nb, sv, ne; 671 Sym *s, *et, *str, **esyms; 672 Prog *p; 673 char buf[NSNAME], *t; 674 675 n = 0; 676 for(i = 0; i < NHASH; i++) 677 for(s = hash[i]; s != S; s = s->link) 678 if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport)) 679 n++; 680 esyms = malloc(n*sizeof(Sym*)); 681 ne = n; 682 n = 0; 683 for(i = 0; i < NHASH; i++) 684 for(s = hash[i]; s != S; s = s->link) 685 if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport)) 686 esyms[n++] = s; 687 for(i = 0; i < ne-1; i++) 688 for(j = i+1; j < ne; j++) 689 if(strcmp(esyms[i]->name, esyms[j]->name) > 0){ 690 s = esyms[i]; 691 esyms[i] = esyms[j]; 692 esyms[j] = s; 693 } 694 695 nb = 0; 696 off = 0; 697 et = lookup(EXPTAB, 0); 698 if(et->type != 0 && et->type != SXREF) 699 diag("%s already defined", EXPTAB); 700 et->type = SDATA; 701 str = lookup(".string", 0); 702 if(str->type == 0) 703 str->type = SDATA; 704 sv = str->value; 705 for(i = 0; i < ne; i++){ 706 s = esyms[i]; 707 if(debug['S']) 708 s->sig = 0; 709 /* Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); */ 710 711 /* signature */ 712 p = newdata(et, off, sizeof(long), D_EXTERN); 713 off += sizeof(long); 714 p->to.offset = s->sig; 715 716 /* address */ 717 p = newdata(et, off, sizeof(long), D_EXTERN); 718 off += sizeof(long); 719 p->to.type = D_ADDR; 720 p->to.index = D_EXTERN; 721 p->to.sym = s; 722 723 /* string */ 724 t = s->name; 725 n = strlen(t)+1; 726 for(;;){ 727 buf[nb++] = *t; 728 sv++; 729 if(nb >= NSNAME){ 730 p = newdata(str, sv-NSNAME, NSNAME, D_STATIC); 731 p->to.type = D_SCONST; 732 memmove(p->to.scon, buf, NSNAME); 733 nb = 0; 734 } 735 if(*t++ == 0) 736 break; 737 } 738 739 /* name */ 740 p = newdata(et, off, sizeof(long), D_EXTERN); 741 off += sizeof(long); 742 p->to.type = D_ADDR; 743 p->to.index = D_STATIC; 744 p->to.sym = str; 745 p->to.offset = sv-n; 746 } 747 748 if(nb > 0){ 749 p = newdata(str, sv-nb, nb, D_STATIC); 750 p->to.type = D_SCONST; 751 memmove(p->to.scon, buf, nb); 752 } 753 754 for(i = 0; i < 3; i++){ 755 newdata(et, off, sizeof(long), D_EXTERN); 756 off += sizeof(long); 757 } 758 et->value = off; 759 if(sv == 0) 760 sv = 1; 761 str->value = sv; 762 exports = ne; 763 free(esyms); 764 } 765