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