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 prints TNAME first */ 312 diag("%s is undefined", s->name); 313 s->type = STEXT; 314 s->value = vexit; 315 break; /* or fall through to set offset? */ 316 case STEXT: 317 p->to.offset = s->value; 318 break; 319 case SUNDEF: 320 p->pcond = UP; 321 p->to.offset = 0; 322 break; 323 } 324 p->to.type = D_BRANCH; 325 } 326 } 327 if(p->to.type != D_BRANCH || p->pcond == UP) 328 continue; 329 c = p->to.offset; 330 for(q = firstp; q != P;) { 331 if(q->forwd != P) 332 if(c >= q->forwd->pc) { 333 q = q->forwd; 334 continue; 335 } 336 if(c == q->pc) 337 break; 338 q = q->link; 339 } 340 if(q == P) { 341 diag("branch out of range in %s\n%P", TNAME, p); 342 p->to.type = D_NONE; 343 } 344 p->pcond = q; 345 } 346 347 for(p = firstp; p != P; p = p->link) { 348 if(p->as == ATEXT) 349 curtext = p; 350 p->mark = 0; /* initialization for follow */ 351 if(p->pcond != P && p->pcond != UP) { 352 p->pcond = brloop(p->pcond); 353 if(p->pcond != P) 354 if(p->to.type == D_BRANCH) 355 p->to.offset = p->pcond->pc; 356 } 357 } 358 } 359 360 #define LOG 5 361 void 362 mkfwd(void) 363 { 364 Prog *p; 365 int i; 366 long dwn[LOG], cnt[LOG]; 367 Prog *lst[LOG]; 368 369 for(i=0; i<LOG; i++) { 370 if(i == 0) 371 cnt[i] = 1; else 372 cnt[i] = LOG * cnt[i-1]; 373 dwn[i] = 1; 374 lst[i] = P; 375 } 376 i = 0; 377 for(p = firstp; p != P; p = p->link) { 378 if(p->as == ATEXT) 379 curtext = p; 380 i--; 381 if(i < 0) 382 i = LOG-1; 383 p->forwd = P; 384 dwn[i]--; 385 if(dwn[i] <= 0) { 386 dwn[i] = cnt[i]; 387 if(lst[i] != P) 388 lst[i]->forwd = p; 389 lst[i] = p; 390 } 391 } 392 } 393 394 Prog* 395 brloop(Prog *p) 396 { 397 int c; 398 Prog *q; 399 400 c = 0; 401 for(q = p; q != P; q = q->pcond) { 402 if(q->as != AJMP) 403 break; 404 c++; 405 if(c >= 5000) 406 return P; 407 } 408 return q; 409 } 410 411 void 412 dostkoff(void) 413 { 414 Prog *p, *q; 415 long autoffset, deltasp; 416 int a, f, curframe, curbecome, maxbecome; 417 418 curframe = 0; 419 curbecome = 0; 420 maxbecome = 0; 421 curtext = 0; 422 for(p = firstp; p != P; p = p->link) { 423 424 /* find out how much arg space is used in this TEXT */ 425 if(p->to.type == (D_INDIR+D_SP)) 426 if(p->to.offset > curframe) 427 curframe = p->to.offset; 428 429 switch(p->as) { 430 case ATEXT: 431 if(curtext && curtext->from.sym) { 432 curtext->from.sym->frame = curframe; 433 curtext->from.sym->become = curbecome; 434 if(curbecome > maxbecome) 435 maxbecome = curbecome; 436 } 437 curframe = 0; 438 curbecome = 0; 439 440 curtext = p; 441 break; 442 443 case ARET: 444 /* special form of RET is BECOME */ 445 if(p->from.type == D_CONST) 446 if(p->from.offset > curbecome) 447 curbecome = p->from.offset; 448 break; 449 } 450 } 451 if(curtext && curtext->from.sym) { 452 curtext->from.sym->frame = curframe; 453 curtext->from.sym->become = curbecome; 454 if(curbecome > maxbecome) 455 maxbecome = curbecome; 456 } 457 458 if(debug['b']) 459 print("max become = %d\n", maxbecome); 460 xdefine("ALEFbecome", STEXT, maxbecome); 461 462 curtext = 0; 463 for(p = firstp; p != P; p = p->link) { 464 switch(p->as) { 465 case ATEXT: 466 curtext = p; 467 break; 468 case ACALL: 469 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { 470 f = maxbecome - curtext->from.sym->frame; 471 if(f <= 0) 472 break; 473 /* calling a become or calling a variable */ 474 if(p->to.sym == S || p->to.sym->become) { 475 curtext->to.offset += f; 476 if(debug['b']) { 477 curp = p; 478 print("%D calling %D increase %d\n", 479 &curtext->from, &p->to, f); 480 } 481 } 482 } 483 break; 484 } 485 } 486 487 autoffset = 0; 488 deltasp = 0; 489 for(p = firstp; p != P; p = p->link) { 490 if(p->as == ATEXT) { 491 curtext = p; 492 autoffset = p->to.offset; 493 if(autoffset < 0) 494 autoffset = 0; 495 if(autoffset) { 496 p = appendp(p); 497 p->as = AADJSP; 498 p->from.type = D_CONST; 499 p->from.offset = autoffset; 500 } 501 deltasp = autoffset; 502 } 503 a = p->from.type; 504 if(a == D_AUTO) 505 p->from.offset += deltasp; 506 if(a == D_PARAM) 507 p->from.offset += deltasp + 4; 508 a = p->to.type; 509 if(a == D_AUTO) 510 p->to.offset += deltasp; 511 if(a == D_PARAM) 512 p->to.offset += deltasp + 4; 513 514 switch(p->as) { 515 default: 516 continue; 517 case APUSHL: 518 case APUSHFL: 519 deltasp += 4; 520 continue; 521 case APUSHW: 522 case APUSHFW: 523 deltasp += 2; 524 continue; 525 case APOPL: 526 case APOPFL: 527 deltasp -= 4; 528 continue; 529 case APOPW: 530 case APOPFW: 531 deltasp -= 2; 532 continue; 533 case ARET: 534 break; 535 } 536 537 if(autoffset != deltasp) 538 diag("unbalanced PUSH/POP"); 539 if(p->from.type == D_CONST) 540 goto become; 541 542 if(autoffset) { 543 q = p; 544 p = appendp(p); 545 p->as = ARET; 546 547 q->as = AADJSP; 548 q->from.type = D_CONST; 549 q->from.offset = -autoffset; 550 } 551 continue; 552 553 become: 554 q = p; 555 p = appendp(p); 556 p->as = AJMP; 557 p->to = q->to; 558 p->pcond = q->pcond; 559 560 q->as = AADJSP; 561 q->from = zprg.from; 562 q->from.type = D_CONST; 563 q->from.offset = -autoffset; 564 q->to = zprg.to; 565 continue; 566 } 567 } 568 569 long 570 atolwhex(char *s) 571 { 572 long n; 573 int f; 574 575 n = 0; 576 f = 0; 577 while(*s == ' ' || *s == '\t') 578 s++; 579 if(*s == '-' || *s == '+') { 580 if(*s++ == '-') 581 f = 1; 582 while(*s == ' ' || *s == '\t') 583 s++; 584 } 585 if(s[0]=='0' && s[1]){ 586 if(s[1]=='x' || s[1]=='X'){ 587 s += 2; 588 for(;;){ 589 if(*s >= '0' && *s <= '9') 590 n = n*16 + *s++ - '0'; 591 else if(*s >= 'a' && *s <= 'f') 592 n = n*16 + *s++ - 'a' + 10; 593 else if(*s >= 'A' && *s <= 'F') 594 n = n*16 + *s++ - 'A' + 10; 595 else 596 break; 597 } 598 } else 599 while(*s >= '0' && *s <= '7') 600 n = n*8 + *s++ - '0'; 601 } else 602 while(*s >= '0' && *s <= '9') 603 n = n*10 + *s++ - '0'; 604 if(f) 605 n = -n; 606 return n; 607 } 608 609 void 610 undef(void) 611 { 612 int i; 613 Sym *s; 614 615 for(i=0; i<NHASH; i++) 616 for(s = hash[i]; s != S; s = s->link) 617 if(s->type == SXREF) 618 diag("%s: not defined", s->name); 619 } 620 621 void 622 import(void) 623 { 624 int i; 625 Sym *s; 626 627 for(i = 0; i < NHASH; i++) 628 for(s = hash[i]; s != S; s = s->link) 629 if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){ 630 if(s->value != 0) 631 diag("value != 0 on SXREF"); 632 undefsym(s); 633 if(debug['X']) 634 Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value); 635 if(debug['S']) 636 s->sig = 0; 637 } 638 } 639 640 void 641 ckoff(Sym *s, long v) 642 { 643 if(v < 0 || v >= 1<<Roffset) 644 diag("relocation offset %ld for %s out of range", v, s->name); 645 } 646 647 static Prog* 648 newdata(Sym *s, int o, int w, int t) 649 { 650 Prog *p; 651 652 p = prg(); 653 if(edatap == P) 654 datap = p; 655 else 656 edatap->link = p; 657 edatap = p; 658 p->as = ADATA; 659 p->width = w; 660 p->from.scale = w; 661 p->from.type = t; 662 p->from.sym = s; 663 p->from.offset = o; 664 p->to.type = D_CONST; 665 return p; 666 } 667 668 void 669 export(void) 670 { 671 int i, j, n, off, nb, sv, ne; 672 Sym *s, *et, *str, **esyms; 673 Prog *p; 674 char buf[NSNAME], *t; 675 676 n = 0; 677 for(i = 0; i < NHASH; i++) 678 for(s = hash[i]; s != S; s = s->link) 679 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT)) 680 n++; 681 esyms = malloc(n*sizeof(Sym*)); 682 ne = n; 683 n = 0; 684 for(i = 0; i < NHASH; i++) 685 for(s = hash[i]; s != S; s = s->link) 686 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT)) 687 esyms[n++] = s; 688 for(i = 0; i < ne-1; i++) 689 for(j = i+1; j < ne; j++) 690 if(strcmp(esyms[i]->name, esyms[j]->name) > 0){ 691 s = esyms[i]; 692 esyms[i] = esyms[j]; 693 esyms[j] = s; 694 } 695 696 nb = 0; 697 off = 0; 698 et = lookup(EXPTAB, 0); 699 if(et->type != 0 && et->type != SXREF) 700 diag("%s already defined", EXPTAB); 701 et->type = SDATA; 702 str = lookup(".string", 0); 703 if(str->type == 0) 704 str->type = SDATA; 705 sv = str->value; 706 for(i = 0; i < ne; i++){ 707 s = esyms[i]; 708 if(debug['S']) 709 s->sig = 0; 710 /* Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); */ 711 712 /* signature */ 713 p = newdata(et, off, sizeof(long), D_EXTERN); 714 off += sizeof(long); 715 p->to.offset = s->sig; 716 717 /* address */ 718 p = newdata(et, off, sizeof(long), D_EXTERN); 719 off += sizeof(long); 720 p->to.type = D_ADDR; 721 p->to.index = D_EXTERN; 722 p->to.sym = s; 723 724 /* string */ 725 t = s->name; 726 n = strlen(t)+1; 727 for(;;){ 728 buf[nb++] = *t; 729 sv++; 730 if(nb >= NSNAME){ 731 p = newdata(str, sv-NSNAME, NSNAME, D_STATIC); 732 p->to.type = D_SCONST; 733 memmove(p->to.scon, buf, NSNAME); 734 nb = 0; 735 } 736 if(*t++ == 0) 737 break; 738 } 739 740 /* name */ 741 p = newdata(et, off, sizeof(long), D_EXTERN); 742 off += sizeof(long); 743 p->to.type = D_ADDR; 744 p->to.index = D_STATIC; 745 p->to.sym = str; 746 p->to.offset = sv-n; 747 } 748 749 if(nb > 0){ 750 p = newdata(str, sv-nb, nb, D_STATIC); 751 p->to.type = D_SCONST; 752 memmove(p->to.scon, buf, nb); 753 } 754 755 for(i = 0; i < 3; i++){ 756 newdata(et, off, sizeof(long), D_EXTERN); 757 off += sizeof(long); 758 } 759 et->value = off; 760 if(sv == 0) 761 sv = 1; 762 str->value = sv; 763 exports = ne; 764 free(esyms); 765 } 766