1 #include "limbo.h" 2 3 static void disbig(long, Long); 4 static void disbyte(long, int); 5 static void disbytes(long, void*, int); 6 static void disdatum(long, Node*); 7 static void disflush(int, long, long); 8 static void disint(long, long); 9 static void disreal(long, Real); 10 static void disstring(long, Sym*); 11 12 static uchar *cache; 13 static int ncached; 14 static int ndatum; 15 static int startoff; 16 static int lastoff; 17 static int lastkind; 18 static int lencache; 19 20 void 21 discon(long val) 22 { 23 if(val >= -64 && val <= 63) { 24 Bputc(bout, val & ~0x80); 25 return; 26 } 27 if(val >= -8192 && val <= 8191) { 28 Bputc(bout, ((val>>8) & ~0xC0) | 0x80); 29 Bputc(bout, val); 30 return; 31 } 32 if(val < 0 && ((val >> 29) & 0x7) != 7 33 || val > 0 && (val >> 29) != 0) 34 fatal("overflow in constant 0x%lux\n", val); 35 Bputc(bout, (val>>24) | 0xC0); 36 Bputc(bout, val>>16); 37 Bputc(bout, val>>8); 38 Bputc(bout, val); 39 } 40 41 void 42 disword(long w) 43 { 44 Bputc(bout, w >> 24); 45 Bputc(bout, w >> 16); 46 Bputc(bout, w >> 8); 47 Bputc(bout, w); 48 } 49 50 void 51 disdata(int kind, long n) 52 { 53 if(n < DMAX && n != 0) 54 Bputc(bout, DBYTE(kind, n)); 55 else{ 56 Bputc(bout, DBYTE(kind, 0)); 57 discon(n); 58 } 59 } 60 61 #define NAMELEN 64 62 63 void 64 dismod(Decl *m) 65 { 66 char name[8*NAMELEN]; 67 vlong fileoff; 68 69 fileoff = Boffset(bout); 70 strncpy(name, m->sym->name, NAMELEN); 71 name[NAMELEN-1] = '\0'; 72 Bwrite(bout, name, strlen(name)+1); 73 for(m = m->ty->tof->ids; m != nil; m = m->next){ 74 switch(m->store){ 75 case Dglobal: 76 discon(-1); 77 discon(-1); 78 disword(sign(m)); 79 Bprint(bout, ".mp"); 80 Bputc(bout, '\0'); 81 break; 82 case Dfn: 83 if(debug['v']) print("Dfn: %s %d %p\n", m->sym->name, m->refs, m); 84 discon(m->pc->pc); 85 discon(m->desc->id); 86 disword(sign(m)); 87 if(m->dot->ty->kind == Tadt) 88 Bprint(bout, "%s.", m->dot->sym->name); 89 Bprint(bout, "%s", m->sym->name); 90 Bputc(bout, '\0'); 91 break; 92 default: 93 fatal("unknown kind %K in dismod", m); 94 break; 95 } 96 } 97 if(debug['s']) 98 print("%lld linkage bytes start %lld\n", Boffset(bout) - fileoff, fileoff); 99 } 100 101 void 102 dispath(void) 103 { 104 char name[8*NAMELEN], *sp; 105 106 sp = srcpath(name, 8*NAMELEN); 107 Bwrite(bout, sp, strlen(sp)+1); 108 } 109 110 void 111 disentry(Decl *e) 112 { 113 if(e == nil){ 114 discon(-1); 115 discon(-1); 116 return; 117 } 118 discon(e->pc->pc); 119 discon(e->desc->id); 120 } 121 122 void 123 disdesc(Desc *d) 124 { 125 vlong fileoff; 126 127 fileoff = Boffset(bout); 128 for(; d != nil; d = d->next){ 129 discon(d->id); 130 discon(d->size); 131 discon(d->nmap); 132 Bwrite(bout, d->map, d->nmap); 133 } 134 if(debug['s']) 135 print("%lld type descriptor bytes start %lld\n", Boffset(bout) - fileoff, fileoff); 136 } 137 138 void 139 disvar(long size, Decl *d) 140 { 141 vlong fileoff; 142 143 fileoff = Boffset(bout); 144 USED(size); 145 146 lastkind = -1; 147 ncached = 0; 148 ndatum = 0; 149 150 for(; d != nil; d = d->next) 151 if(d->store == Dglobal && d->init != nil) 152 disdatum(d->offset, d->init); 153 154 disflush(-1, -1, 0); 155 156 Bputc(bout, 0); 157 158 if(debug['s']) 159 print("%lld data bytes start %lld\n", Boffset(bout) - fileoff, fileoff); 160 } 161 162 void 163 disldt(long size, Decl *ds) 164 { 165 int m; 166 Decl *d, *id; 167 Sym *s; 168 Node *n; 169 170 if(0){ 171 discon(size); 172 disvar(size, ds); 173 return; 174 } 175 176 m = 0; 177 for(d = ds; d != nil; d = d->next) 178 if(d->store == Dglobal && d->init != nil) 179 m++; 180 discon(m); 181 for(d = ds; d != nil; d = d->next){ 182 if(d->store == Dglobal && d->init != nil){ 183 n = d->init; 184 if(n->ty->kind != Tiface) 185 nerror(n, "disldt: not Tiface"); 186 discon(n->val); 187 for(id = n->decl->ty->ids; id != nil; id = id->next){ 188 disword(sign(id)); 189 if(id->dot->ty->kind == Tadt){ 190 s = id->dot->sym; 191 Bprint(bout, "%s", s->name); 192 Bputc(bout, '.'); 193 } 194 s = id->sym; 195 Bprint(bout, "%s", s->name); 196 Bputc(bout, 0); 197 } 198 } 199 } 200 discon(0); 201 } 202 203 static void 204 disdatum(long offset, Node *n) 205 { 206 Node *elem, *wild; 207 Case *c; 208 Label *lab; 209 Decl *id; 210 Sym *s; 211 long e, last, esz; 212 int i; 213 214 switch(n->ty->kind){ 215 case Tbyte: 216 disbyte(offset, n->val); 217 break; 218 case Tint: 219 case Tfix: 220 disint(offset, n->val); 221 break; 222 case Tbig: 223 disbig(offset, n->val); 224 break; 225 case Tstring: 226 disstring(offset, n->decl->sym); 227 break; 228 case Treal: 229 disreal(offset, n->rval); 230 break; 231 case Tadt: 232 case Tadtpick: 233 case Ttuple: 234 id = n->ty->ids; 235 for(n = n->left; n != nil; n = n->right){ 236 disdatum(offset + id->offset, n->left); 237 id = id->next; 238 } 239 break; 240 case Tany: 241 break; 242 case Tcase: 243 c = n->ty->cse; 244 disint(offset, c->nlab); 245 offset += IBY2WD; 246 for(i = 0; i < c->nlab; i++){ 247 lab = &c->labs[i]; 248 disint(offset, lab->start->val); 249 offset += IBY2WD; 250 disint(offset, lab->stop->val+1); 251 offset += IBY2WD; 252 disint(offset, lab->inst->pc); 253 offset += IBY2WD; 254 } 255 disint(offset, c->iwild ? c->iwild->pc : -1); 256 break; 257 case Tcasel: 258 c = n->ty->cse; 259 disint(offset, c->nlab); 260 offset += 2*IBY2WD; 261 for(i = 0; i < c->nlab; i++){ 262 lab = &c->labs[i]; 263 disbig(offset, lab->start->val); 264 offset += IBY2LG; 265 disbig(offset, lab->stop->val+1); 266 offset += IBY2LG; 267 disint(offset, lab->inst->pc); 268 offset += 2*IBY2WD; 269 } 270 disint(offset, c->iwild ? c->iwild->pc : -1); 271 break; 272 case Tcasec: 273 c = n->ty->cse; 274 disint(offset, c->nlab); 275 offset += IBY2WD; 276 for(i = 0; i < c->nlab; i++){ 277 lab = &c->labs[i]; 278 disstring(offset, lab->start->decl->sym); 279 offset += IBY2WD; 280 if(lab->stop != lab->start) 281 disstring(offset, lab->stop->decl->sym); 282 offset += IBY2WD; 283 disint(offset, lab->inst->pc); 284 offset += IBY2WD; 285 } 286 disint(offset, c->iwild ? c->iwild->pc : -1); 287 break; 288 case Tgoto: 289 c = n->ty->cse; 290 disint(offset, n->ty->size/IBY2WD-1); 291 offset += IBY2WD; 292 for(i = 0; i < c->nlab; i++){ 293 disint(offset, c->labs[i].inst->pc); 294 offset += IBY2WD; 295 } 296 if(c->iwild != nil) 297 disint(offset, c->iwild->pc); 298 break; 299 case Tarray: 300 disflush(-1, -1, 0); 301 disdata(DEFA, 1); /* 1 is ignored */ 302 discon(offset); 303 disword(n->ty->tof->decl->desc->id); 304 disword(n->left->val); 305 306 if(n->right == nil) 307 break; 308 309 disdata(DIND, 1); /* 1 is ignored */ 310 discon(offset); 311 disword(0); 312 313 c = n->right->ty->cse; 314 wild = nil; 315 if(c->wild != nil) 316 wild = c->wild->right; 317 last = 0; 318 esz = n->ty->tof->size; 319 for(i = 0; i < c->nlab; i++){ 320 e = c->labs[i].start->val; 321 if(wild != nil){ 322 for(; last < e; last++) 323 disdatum(esz * last, wild); 324 } 325 last = e; 326 e = c->labs[i].stop->val; 327 elem = c->labs[i].node->right; 328 for(; last <= e; last++) 329 disdatum(esz * last, elem); 330 } 331 if(wild != nil) 332 for(e = n->left->val; last < e; last++) 333 disdatum(esz * last, wild); 334 335 disflush(-1, -1, 0); 336 disdata(DAPOP, 1); /* 1 is ignored */ 337 discon(0); 338 339 break; 340 case Tiface: 341 disint(offset, n->val); 342 offset += IBY2WD; 343 for(id = n->decl->ty->ids; id != nil; id = id->next){ 344 offset = align(offset, IBY2WD); 345 disint(offset, sign(id)); 346 offset += IBY2WD; 347 348 if(id->dot->ty->kind == Tadt){ 349 s = id->dot->sym; 350 disbytes(offset, s->name, s->len); 351 offset += s->len; 352 disbyte(offset, '.'); 353 offset++; 354 } 355 s = id->sym; 356 disbytes(offset, s->name, s->len); 357 offset += s->len; 358 disbyte(offset, 0); 359 offset++; 360 } 361 break; 362 default: 363 nerror(n, "can't dis global %n", n); 364 break; 365 } 366 } 367 368 void 369 disexc(Except *es) 370 { 371 int i, n; 372 Decl *d; 373 Except *e; 374 Case *c; 375 Label *lab; 376 377 n = 0; 378 for(e = es; e != nil; e = e->next) 379 if(e->p1->reach || e->p2->reach) 380 n++; 381 discon(n); 382 for(e = es; e != nil; e = e->next){ 383 if(!e->p1->reach && !e->p2->reach) 384 continue; 385 c = e->c; 386 discon(e->d->offset); 387 discon(getpc(e->p1)); 388 discon(getpc(e->p2)); 389 if(e->desc) 390 discon(e->desc->id); 391 else 392 discon(-1); 393 discon(c->nlab|(e->ne<<16)); 394 for(i = 0; i < c->nlab; i++){ 395 lab = &c->labs[i]; 396 d = lab->start->decl; 397 if(lab->start->ty->kind == Texception) 398 d = d->init->decl; 399 Bprint(bout, "%s", d->sym->name); 400 Bputc(bout, '\0'); 401 discon(lab->inst->pc); 402 } 403 if(c->iwild == nil) 404 discon(-1); 405 else 406 discon(c->iwild->pc); 407 } 408 discon(0); 409 } 410 411 static void 412 disbyte(long off, int v) 413 { 414 disflush(DEFB, off, 1); 415 cache[ncached++] = v; 416 ndatum++; 417 } 418 419 static void 420 disbytes(long off, void *v, int n) 421 { 422 disflush(DEFB, off, n); 423 memmove(&cache[ncached], v, n); 424 ncached += n; 425 ndatum += n; 426 } 427 428 static void 429 disint(long off, long v) 430 { 431 disflush(DEFW, off, IBY2WD); 432 cache[ncached++] = v >> 24; 433 cache[ncached++] = v >> 16; 434 cache[ncached++] = v >> 8; 435 cache[ncached++] = v; 436 ndatum++; 437 } 438 439 static void 440 disbig(long off, Long v) 441 { 442 ulong iv; 443 444 disflush(DEFL, off, IBY2LG); 445 iv = v >> 32; 446 cache[ncached++] = iv >> 24; 447 cache[ncached++] = iv >> 16; 448 cache[ncached++] = iv >> 8; 449 cache[ncached++] = iv; 450 iv = v; 451 cache[ncached++] = iv >> 24; 452 cache[ncached++] = iv >> 16; 453 cache[ncached++] = iv >> 8; 454 cache[ncached++] = iv; 455 ndatum++; 456 } 457 458 static void 459 disreal(long off, Real v) 460 { 461 ulong bv[2]; 462 ulong iv; 463 464 disflush(DEFF, off, IBY2LG); 465 dtocanon(v, bv); 466 iv = bv[0]; 467 cache[ncached++] = iv >> 24; 468 cache[ncached++] = iv >> 16; 469 cache[ncached++] = iv >> 8; 470 cache[ncached++] = iv; 471 iv = bv[1]; 472 cache[ncached++] = iv >> 24; 473 cache[ncached++] = iv >> 16; 474 cache[ncached++] = iv >> 8; 475 cache[ncached++] = iv; 476 ndatum++; 477 } 478 479 static void 480 disstring(long offset, Sym *sym) 481 { 482 disflush(-1, -1, 0); 483 disdata(DEFS, sym->len); 484 discon(offset); 485 Bwrite(bout, sym->name, sym->len); 486 } 487 488 static void 489 disflush(int kind, long off, long size) 490 { 491 if(kind != lastkind || off != lastoff){ 492 if(lastkind != -1 && ncached){ 493 disdata(lastkind, ndatum); 494 discon(startoff); 495 Bwrite(bout, cache, ncached); 496 } 497 startoff = off; 498 lastkind = kind; 499 ncached = 0; 500 ndatum = 0; 501 } 502 lastoff = off + size; 503 while(kind >= 0 && ncached + size >= lencache){ 504 lencache = ncached+1024; 505 cache = reallocmem(cache, lencache); 506 } 507 } 508 509 static int dismode[Aend] = { 510 /* Aimm */ AIMM, 511 /* Amp */ AMP, 512 /* Ampind */ AMP|AIND, 513 /* Afp */ AFP, 514 /* Afpind */ AFP|AIND, 515 /* Apc */ AIMM, 516 /* Adesc */ AIMM, 517 /* Aoff */ AIMM, 518 /* Anoff */ AIMM, 519 /* Aerr */ AXXX, 520 /* Anone */ AXXX, 521 /* Aldt */ AIMM, 522 }; 523 524 static int disregmode[Aend] = { 525 /* Aimm */ AXIMM, 526 /* Amp */ AXINM, 527 /* Ampind */ AXNON, 528 /* Afp */ AXINF, 529 /* Afpind */ AXNON, 530 /* Apc */ AXIMM, 531 /* Adesc */ AXIMM, 532 /* Aoff */ AXIMM, 533 /* Anoff */ AXIMM, 534 /* Aerr */ AXNON, 535 /* Anone */ AXNON, 536 /* Aldt */ AXIMM, 537 }; 538 539 enum 540 { 541 MAXCON = 4, 542 MAXADDR = 2*MAXCON, 543 MAXINST = 3*MAXADDR+2, 544 NIBUF = 1024 545 }; 546 547 static uchar *ibuf; 548 static int nibuf; 549 550 void 551 disinst(Inst *in) 552 { 553 vlong fileoff; 554 555 fileoff = Boffset(bout); 556 ibuf = allocmem(NIBUF); 557 nibuf = 0; 558 for(; in != nil; in = in->next){ 559 if(in->op == INOOP) 560 continue; 561 if(nibuf >= NIBUF-MAXINST){ 562 Bwrite(bout, ibuf, nibuf); 563 nibuf = 0; 564 } 565 ibuf[nibuf++] = in->op; 566 ibuf[nibuf++] = SRC(dismode[in->sm]) | DST(dismode[in->dm]) | disregmode[in->mm]; 567 if(in->mm != Anone) 568 disaddr(in->mm, &in->m); 569 if(in->sm != Anone) 570 disaddr(in->sm, &in->s); 571 if(in->dm != Anone) 572 disaddr(in->dm, &in->d); 573 } 574 if(nibuf > 0) 575 Bwrite(bout, ibuf, nibuf); 576 free(ibuf); 577 ibuf = nil; 578 579 if(debug['s']) 580 print("%lld instruction bytes start %lld\n", Boffset(bout) - fileoff, fileoff); 581 } 582 583 void 584 disaddr(int m, Addr *a) 585 { 586 long val; 587 588 val = 0; 589 switch(m){ 590 case Anone: 591 case Aerr: 592 default: 593 break; 594 case Aimm: 595 case Apc: 596 case Adesc: 597 val = a->offset; 598 break; 599 case Aoff: 600 val = a->decl->iface->offset; 601 break; 602 case Anoff: 603 val = -(a->decl->iface->offset+1); 604 break; 605 case Afp: 606 case Amp: 607 case Aldt: 608 val = a->reg; 609 break; 610 case Afpind: 611 case Ampind: 612 disbcon(a->reg); 613 val = a->offset; 614 break; 615 } 616 disbcon(val); 617 } 618 619 void 620 disbcon(long val) 621 { 622 if(val >= -64 && val <= 63){ 623 ibuf[nibuf++] = val & ~0x80; 624 return; 625 } 626 if(val >= -8192 && val <= 8191){ 627 ibuf[nibuf++] = val>>8 & ~0xC0 | 0x80; 628 ibuf[nibuf++] = val; 629 return; 630 } 631 if(val < 0 && ((val >> 29) & 7) != 7 632 || val > 0 && (val >> 29) != 0) 633 fatal("overflow in constant 16r%lux", val); 634 ibuf[nibuf++] = val>>24 | 0xC0; 635 ibuf[nibuf++] = val>>16; 636 ibuf[nibuf++] = val>>8; 637 ibuf[nibuf++] = val; 638 } 639