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