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 case STEXT: 311 p->to.offset = s->value; 312 break; 313 case SUNDEF: 314 p->pcond = UP; 315 p->to.offset = 0; 316 break; 317 default: 318 diag("undefined: %s in %s", s->name, TNAME); 319 s->type = STEXT; 320 s->value = vexit; 321 } 322 p->to.type = D_BRANCH; 323 } 324 } 325 if(p->to.type != D_BRANCH || p->pcond == UP) 326 continue; 327 c = p->to.offset; 328 for(q = firstp; q != P;) { 329 if(q->forwd != P) 330 if(c >= q->forwd->pc) { 331 q = q->forwd; 332 continue; 333 } 334 if(c == q->pc) 335 break; 336 q = q->link; 337 } 338 if(q == P) { 339 diag("branch out of range in %s\n%P", TNAME, p); 340 p->to.type = D_NONE; 341 } 342 p->pcond = q; 343 } 344 345 for(p = firstp; p != P; p = p->link) { 346 if(p->as == ATEXT) 347 curtext = p; 348 p->mark = 0; /* initialization for follow */ 349 if(p->pcond != P && p->pcond != UP) { 350 p->pcond = brloop(p->pcond); 351 if(p->pcond != P) 352 if(p->to.type == D_BRANCH) 353 p->to.offset = p->pcond->pc; 354 } 355 } 356 } 357 358 #define LOG 5 359 void 360 mkfwd(void) 361 { 362 Prog *p; 363 int i; 364 long dwn[LOG], cnt[LOG]; 365 Prog *lst[LOG]; 366 367 for(i=0; i<LOG; i++) { 368 if(i == 0) 369 cnt[i] = 1; else 370 cnt[i] = LOG * cnt[i-1]; 371 dwn[i] = 1; 372 lst[i] = P; 373 } 374 i = 0; 375 for(p = firstp; p != P; p = p->link) { 376 if(p->as == ATEXT) 377 curtext = p; 378 i--; 379 if(i < 0) 380 i = LOG-1; 381 p->forwd = P; 382 dwn[i]--; 383 if(dwn[i] <= 0) { 384 dwn[i] = cnt[i]; 385 if(lst[i] != P) 386 lst[i]->forwd = p; 387 lst[i] = p; 388 } 389 } 390 } 391 392 Prog* 393 brloop(Prog *p) 394 { 395 int c; 396 Prog *q; 397 398 c = 0; 399 for(q = p; q != P; q = q->pcond) { 400 if(q->as != AJMP) 401 break; 402 c++; 403 if(c >= 5000) 404 return P; 405 } 406 return q; 407 } 408 409 void 410 dostkoff(void) 411 { 412 Prog *p, *q; 413 long autoffset, deltasp; 414 int a, f, curframe, curbecome, maxbecome; 415 416 curframe = 0; 417 curbecome = 0; 418 maxbecome = 0; 419 curtext = 0; 420 for(p = firstp; p != P; p = p->link) { 421 422 /* find out how much arg space is used in this TEXT */ 423 if(p->to.type == (D_INDIR+D_SP)) 424 if(p->to.offset > curframe) 425 curframe = p->to.offset; 426 427 switch(p->as) { 428 case ATEXT: 429 if(curtext && curtext->from.sym) { 430 curtext->from.sym->frame = curframe; 431 curtext->from.sym->become = curbecome; 432 if(curbecome > maxbecome) 433 maxbecome = curbecome; 434 } 435 curframe = 0; 436 curbecome = 0; 437 438 curtext = p; 439 break; 440 441 case ARET: 442 /* special form of RET is BECOME */ 443 if(p->from.type == D_CONST) 444 if(p->from.offset > curbecome) 445 curbecome = p->from.offset; 446 break; 447 } 448 } 449 if(curtext && curtext->from.sym) { 450 curtext->from.sym->frame = curframe; 451 curtext->from.sym->become = curbecome; 452 if(curbecome > maxbecome) 453 maxbecome = curbecome; 454 } 455 456 if(debug['b']) 457 print("max become = %d\n", maxbecome); 458 xdefine("ALEFbecome", STEXT, maxbecome); 459 460 curtext = 0; 461 for(p = firstp; p != P; p = p->link) { 462 switch(p->as) { 463 case ATEXT: 464 curtext = p; 465 break; 466 case ACALL: 467 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { 468 f = maxbecome - curtext->from.sym->frame; 469 if(f <= 0) 470 break; 471 /* calling a become or calling a variable */ 472 if(p->to.sym == S || p->to.sym->become) { 473 curtext->to.offset += f; 474 if(debug['b']) { 475 curp = p; 476 print("%D calling %D increase %d\n", 477 &curtext->from, &p->to, f); 478 } 479 } 480 } 481 break; 482 } 483 } 484 485 autoffset = 0; 486 deltasp = 0; 487 for(p = firstp; p != P; p = p->link) { 488 if(p->as == ATEXT) { 489 curtext = p; 490 autoffset = p->to.offset; 491 if(autoffset < 0) 492 autoffset = 0; 493 if(autoffset) { 494 p = appendp(p); 495 p->as = AADJSP; 496 p->from.type = D_CONST; 497 p->from.offset = autoffset; 498 } 499 deltasp = autoffset; 500 } 501 a = p->from.type; 502 if(a == D_AUTO) 503 p->from.offset += deltasp; 504 if(a == D_PARAM) 505 p->from.offset += deltasp + 4; 506 a = p->to.type; 507 if(a == D_AUTO) 508 p->to.offset += deltasp; 509 if(a == D_PARAM) 510 p->to.offset += deltasp + 4; 511 512 switch(p->as) { 513 default: 514 continue; 515 case APUSHL: 516 case APUSHFL: 517 deltasp += 4; 518 continue; 519 case APUSHW: 520 case APUSHFW: 521 deltasp += 2; 522 continue; 523 case APOPL: 524 case APOPFL: 525 deltasp -= 4; 526 continue; 527 case APOPW: 528 case APOPFW: 529 deltasp -= 2; 530 continue; 531 case ARET: 532 break; 533 } 534 535 if(autoffset != deltasp) 536 diag("unbalanced PUSH/POP"); 537 if(p->from.type == D_CONST) 538 goto become; 539 540 if(autoffset) { 541 q = p; 542 p = appendp(p); 543 p->as = ARET; 544 545 q->as = AADJSP; 546 q->from.type = D_CONST; 547 q->from.offset = -autoffset; 548 } 549 continue; 550 551 become: 552 q = p; 553 p = appendp(p); 554 p->as = AJMP; 555 p->to = q->to; 556 p->pcond = q->pcond; 557 558 q->as = AADJSP; 559 q->from = zprg.from; 560 q->from.type = D_CONST; 561 q->from.offset = -autoffset; 562 q->to = zprg.to; 563 continue; 564 } 565 } 566 567 long 568 atolwhex(char *s) 569 { 570 long n; 571 int f; 572 573 n = 0; 574 f = 0; 575 while(*s == ' ' || *s == '\t') 576 s++; 577 if(*s == '-' || *s == '+') { 578 if(*s++ == '-') 579 f = 1; 580 while(*s == ' ' || *s == '\t') 581 s++; 582 } 583 if(s[0]=='0' && s[1]){ 584 if(s[1]=='x' || s[1]=='X'){ 585 s += 2; 586 for(;;){ 587 if(*s >= '0' && *s <= '9') 588 n = n*16 + *s++ - '0'; 589 else if(*s >= 'a' && *s <= 'f') 590 n = n*16 + *s++ - 'a' + 10; 591 else if(*s >= 'A' && *s <= 'F') 592 n = n*16 + *s++ - 'A' + 10; 593 else 594 break; 595 } 596 } else 597 while(*s >= '0' && *s <= '7') 598 n = n*8 + *s++ - '0'; 599 } else 600 while(*s >= '0' && *s <= '9') 601 n = n*10 + *s++ - '0'; 602 if(f) 603 n = -n; 604 return n; 605 } 606 607 void 608 undef(void) 609 { 610 int i; 611 Sym *s; 612 613 for(i=0; i<NHASH; i++) 614 for(s = hash[i]; s != S; s = s->link) 615 if(s->type == SXREF) 616 diag("%s: not defined", s->name); 617 } 618