123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- #include "limbo.h"
- static void disbig(long, Long);
- static void disbyte(long, int);
- static void disbytes(long, void*, int);
- static void disdatum(long, Node*);
- static void disflush(int, long, long);
- static void disint(long, long);
- static void disreal(long, Real);
- static void disstring(long, Sym*);
- static uchar *cache;
- static int ncached;
- static int ndatum;
- static int startoff;
- static int lastoff;
- static int lastkind;
- static int lencache;
- void
- discon(long val)
- {
- if(val >= -64 && val <= 63) {
- Bputc(bout, val & ~0x80);
- return;
- }
- if(val >= -8192 && val <= 8191) {
- Bputc(bout, ((val>>8) & ~0xC0) | 0x80);
- Bputc(bout, val);
- return;
- }
- if(val < 0 && ((val >> 29) & 0x7) != 7
- || val > 0 && (val >> 29) != 0)
- fatal("overflow in constant 0x%lux\n", val);
- Bputc(bout, (val>>24) | 0xC0);
- Bputc(bout, val>>16);
- Bputc(bout, val>>8);
- Bputc(bout, val);
- }
- void
- disword(long w)
- {
- Bputc(bout, w >> 24);
- Bputc(bout, w >> 16);
- Bputc(bout, w >> 8);
- Bputc(bout, w);
- }
- void
- disdata(int kind, long n)
- {
- if(n < DMAX && n != 0)
- Bputc(bout, DBYTE(kind, n));
- else{
- Bputc(bout, DBYTE(kind, 0));
- discon(n);
- }
- }
- #define NAMELEN 64
- void
- dismod(Decl *m)
- {
- char name[8*NAMELEN];
- vlong fileoff;
- fileoff = Boffset(bout);
- strncpy(name, m->sym->name, NAMELEN);
- name[NAMELEN-1] = '\0';
- Bwrite(bout, name, strlen(name)+1);
- for(m = m->ty->tof->ids; m != nil; m = m->next){
- switch(m->store){
- case Dglobal:
- discon(-1);
- discon(-1);
- disword(sign(m));
- Bprint(bout, ".mp");
- Bputc(bout, '\0');
- break;
- case Dfn:
- if(debug['v']) print("Dfn: %s %d %p\n", m->sym->name, m->refs, m);
- discon(m->pc->pc);
- discon(m->desc->id);
- disword(sign(m));
- if(m->dot->ty->kind == Tadt)
- Bprint(bout, "%s.", m->dot->sym->name);
- Bprint(bout, "%s", m->sym->name);
- Bputc(bout, '\0');
- break;
- default:
- fatal("unknown kind %K in dismod", m);
- break;
- }
- }
- if(debug['s'])
- print("%lld linkage bytes start %lld\n", Boffset(bout) - fileoff, fileoff);
- }
- void
- dispath(void)
- {
- char name[8*NAMELEN], *sp;
- sp = srcpath(name, 8*NAMELEN);
- Bwrite(bout, sp, strlen(sp)+1);
- }
- void
- disentry(Decl *e)
- {
- if(e == nil){
- discon(-1);
- discon(-1);
- return;
- }
- discon(e->pc->pc);
- discon(e->desc->id);
- }
- void
- disdesc(Desc *d)
- {
- vlong fileoff;
- fileoff = Boffset(bout);
- for(; d != nil; d = d->next){
- discon(d->id);
- discon(d->size);
- discon(d->nmap);
- Bwrite(bout, d->map, d->nmap);
- }
- if(debug['s'])
- print("%lld type descriptor bytes start %lld\n", Boffset(bout) - fileoff, fileoff);
- }
- void
- disvar(long size, Decl *d)
- {
- vlong fileoff;
- fileoff = Boffset(bout);
- USED(size);
- lastkind = -1;
- ncached = 0;
- ndatum = 0;
- for(; d != nil; d = d->next)
- if(d->store == Dglobal && d->init != nil)
- disdatum(d->offset, d->init);
- disflush(-1, -1, 0);
- Bputc(bout, 0);
- if(debug['s'])
- print("%lld data bytes start %lld\n", Boffset(bout) - fileoff, fileoff);
- }
- void
- disldt(long size, Decl *ds)
- {
- int m;
- Decl *d, *id;
- Sym *s;
- Node *n;
- if(0){
- discon(size);
- disvar(size, ds);
- return;
- }
- m = 0;
- for(d = ds; d != nil; d = d->next)
- if(d->store == Dglobal && d->init != nil)
- m++;
- discon(m);
- for(d = ds; d != nil; d = d->next){
- if(d->store == Dglobal && d->init != nil){
- n = d->init;
- if(n->ty->kind != Tiface)
- nerror(n, "disldt: not Tiface");
- discon(n->val);
- for(id = n->decl->ty->ids; id != nil; id = id->next){
- disword(sign(id));
- if(id->dot->ty->kind == Tadt){
- s = id->dot->sym;
- Bprint(bout, "%s", s->name);
- Bputc(bout, '.');
- }
- s = id->sym;
- Bprint(bout, "%s", s->name);
- Bputc(bout, 0);
- }
- }
- }
- discon(0);
- }
- static void
- disdatum(long offset, Node *n)
- {
- Node *elem, *wild;
- Case *c;
- Label *lab;
- Decl *id;
- Sym *s;
- long e, last, esz;
- int i;
- switch(n->ty->kind){
- case Tbyte:
- disbyte(offset, n->val);
- break;
- case Tint:
- case Tfix:
- disint(offset, n->val);
- break;
- case Tbig:
- disbig(offset, n->val);
- break;
- case Tstring:
- disstring(offset, n->decl->sym);
- break;
- case Treal:
- disreal(offset, n->rval);
- break;
- case Tadt:
- case Tadtpick:
- case Ttuple:
- id = n->ty->ids;
- for(n = n->left; n != nil; n = n->right){
- disdatum(offset + id->offset, n->left);
- id = id->next;
- }
- break;
- case Tany:
- break;
- case Tcase:
- c = n->ty->cse;
- disint(offset, c->nlab);
- offset += IBY2WD;
- for(i = 0; i < c->nlab; i++){
- lab = &c->labs[i];
- disint(offset, lab->start->val);
- offset += IBY2WD;
- disint(offset, lab->stop->val+1);
- offset += IBY2WD;
- disint(offset, lab->inst->pc);
- offset += IBY2WD;
- }
- disint(offset, c->iwild ? c->iwild->pc : -1);
- break;
- case Tcasel:
- c = n->ty->cse;
- disint(offset, c->nlab);
- offset += 2*IBY2WD;
- for(i = 0; i < c->nlab; i++){
- lab = &c->labs[i];
- disbig(offset, lab->start->val);
- offset += IBY2LG;
- disbig(offset, lab->stop->val+1);
- offset += IBY2LG;
- disint(offset, lab->inst->pc);
- offset += 2*IBY2WD;
- }
- disint(offset, c->iwild ? c->iwild->pc : -1);
- break;
- case Tcasec:
- c = n->ty->cse;
- disint(offset, c->nlab);
- offset += IBY2WD;
- for(i = 0; i < c->nlab; i++){
- lab = &c->labs[i];
- disstring(offset, lab->start->decl->sym);
- offset += IBY2WD;
- if(lab->stop != lab->start)
- disstring(offset, lab->stop->decl->sym);
- offset += IBY2WD;
- disint(offset, lab->inst->pc);
- offset += IBY2WD;
- }
- disint(offset, c->iwild ? c->iwild->pc : -1);
- break;
- case Tgoto:
- c = n->ty->cse;
- disint(offset, n->ty->size/IBY2WD-1);
- offset += IBY2WD;
- for(i = 0; i < c->nlab; i++){
- disint(offset, c->labs[i].inst->pc);
- offset += IBY2WD;
- }
- if(c->iwild != nil)
- disint(offset, c->iwild->pc);
- break;
- case Tarray:
- disflush(-1, -1, 0);
- disdata(DEFA, 1); /* 1 is ignored */
- discon(offset);
- disword(n->ty->tof->decl->desc->id);
- disword(n->left->val);
- if(n->right == nil)
- break;
- disdata(DIND, 1); /* 1 is ignored */
- discon(offset);
- disword(0);
- c = n->right->ty->cse;
- wild = nil;
- if(c->wild != nil)
- wild = c->wild->right;
- last = 0;
- esz = n->ty->tof->size;
- for(i = 0; i < c->nlab; i++){
- e = c->labs[i].start->val;
- if(wild != nil){
- for(; last < e; last++)
- disdatum(esz * last, wild);
- }
- last = e;
- e = c->labs[i].stop->val;
- elem = c->labs[i].node->right;
- for(; last <= e; last++)
- disdatum(esz * last, elem);
- }
- if(wild != nil)
- for(e = n->left->val; last < e; last++)
- disdatum(esz * last, wild);
- disflush(-1, -1, 0);
- disdata(DAPOP, 1); /* 1 is ignored */
- discon(0);
- break;
- case Tiface:
- disint(offset, n->val);
- offset += IBY2WD;
- for(id = n->decl->ty->ids; id != nil; id = id->next){
- offset = align(offset, IBY2WD);
- disint(offset, sign(id));
- offset += IBY2WD;
- if(id->dot->ty->kind == Tadt){
- s = id->dot->sym;
- disbytes(offset, s->name, s->len);
- offset += s->len;
- disbyte(offset, '.');
- offset++;
- }
- s = id->sym;
- disbytes(offset, s->name, s->len);
- offset += s->len;
- disbyte(offset, 0);
- offset++;
- }
- break;
- default:
- nerror(n, "can't dis global %n", n);
- break;
- }
- }
- void
- disexc(Except *es)
- {
- int i, n;
- Decl *d;
- Except *e;
- Case *c;
- Label *lab;
- n = 0;
- for(e = es; e != nil; e = e->next)
- if(e->p1->reach || e->p2->reach)
- n++;
- discon(n);
- for(e = es; e != nil; e = e->next){
- if(!e->p1->reach && !e->p2->reach)
- continue;
- c = e->c;
- discon(e->d->offset);
- discon(getpc(e->p1));
- discon(getpc(e->p2));
- if(e->desc)
- discon(e->desc->id);
- else
- discon(-1);
- discon(c->nlab|(e->ne<<16));
- for(i = 0; i < c->nlab; i++){
- lab = &c->labs[i];
- d = lab->start->decl;
- if(lab->start->ty->kind == Texception)
- d = d->init->decl;
- Bprint(bout, "%s", d->sym->name);
- Bputc(bout, '\0');
- discon(lab->inst->pc);
- }
- if(c->iwild == nil)
- discon(-1);
- else
- discon(c->iwild->pc);
- }
- discon(0);
- }
- static void
- disbyte(long off, int v)
- {
- disflush(DEFB, off, 1);
- cache[ncached++] = v;
- ndatum++;
- }
- static void
- disbytes(long off, void *v, int n)
- {
- disflush(DEFB, off, n);
- memmove(&cache[ncached], v, n);
- ncached += n;
- ndatum += n;
- }
- static void
- disint(long off, long v)
- {
- disflush(DEFW, off, IBY2WD);
- cache[ncached++] = v >> 24;
- cache[ncached++] = v >> 16;
- cache[ncached++] = v >> 8;
- cache[ncached++] = v;
- ndatum++;
- }
- static void
- disbig(long off, Long v)
- {
- ulong iv;
- disflush(DEFL, off, IBY2LG);
- iv = v >> 32;
- cache[ncached++] = iv >> 24;
- cache[ncached++] = iv >> 16;
- cache[ncached++] = iv >> 8;
- cache[ncached++] = iv;
- iv = v;
- cache[ncached++] = iv >> 24;
- cache[ncached++] = iv >> 16;
- cache[ncached++] = iv >> 8;
- cache[ncached++] = iv;
- ndatum++;
- }
- static void
- disreal(long off, Real v)
- {
- ulong bv[2];
- ulong iv;
- disflush(DEFF, off, IBY2LG);
- dtocanon(v, bv);
- iv = bv[0];
- cache[ncached++] = iv >> 24;
- cache[ncached++] = iv >> 16;
- cache[ncached++] = iv >> 8;
- cache[ncached++] = iv;
- iv = bv[1];
- cache[ncached++] = iv >> 24;
- cache[ncached++] = iv >> 16;
- cache[ncached++] = iv >> 8;
- cache[ncached++] = iv;
- ndatum++;
- }
- static void
- disstring(long offset, Sym *sym)
- {
- disflush(-1, -1, 0);
- disdata(DEFS, sym->len);
- discon(offset);
- Bwrite(bout, sym->name, sym->len);
- }
- static void
- disflush(int kind, long off, long size)
- {
- if(kind != lastkind || off != lastoff){
- if(lastkind != -1 && ncached){
- disdata(lastkind, ndatum);
- discon(startoff);
- Bwrite(bout, cache, ncached);
- }
- startoff = off;
- lastkind = kind;
- ncached = 0;
- ndatum = 0;
- }
- lastoff = off + size;
- while(kind >= 0 && ncached + size >= lencache){
- lencache = ncached+1024;
- cache = reallocmem(cache, lencache);
- }
- }
- static int dismode[Aend] = {
- /* Aimm */ AIMM,
- /* Amp */ AMP,
- /* Ampind */ AMP|AIND,
- /* Afp */ AFP,
- /* Afpind */ AFP|AIND,
- /* Apc */ AIMM,
- /* Adesc */ AIMM,
- /* Aoff */ AIMM,
- /* Anoff */ AIMM,
- /* Aerr */ AXXX,
- /* Anone */ AXXX,
- /* Aldt */ AIMM,
- };
- static int disregmode[Aend] = {
- /* Aimm */ AXIMM,
- /* Amp */ AXINM,
- /* Ampind */ AXNON,
- /* Afp */ AXINF,
- /* Afpind */ AXNON,
- /* Apc */ AXIMM,
- /* Adesc */ AXIMM,
- /* Aoff */ AXIMM,
- /* Anoff */ AXIMM,
- /* Aerr */ AXNON,
- /* Anone */ AXNON,
- /* Aldt */ AXIMM,
- };
- enum
- {
- MAXCON = 4,
- MAXADDR = 2*MAXCON,
- MAXINST = 3*MAXADDR+2,
- NIBUF = 1024
- };
- static uchar *ibuf;
- static int nibuf;
- void
- disinst(Inst *in)
- {
- vlong fileoff;
- fileoff = Boffset(bout);
- ibuf = allocmem(NIBUF);
- nibuf = 0;
- for(; in != nil; in = in->next){
- if(in->op == INOOP)
- continue;
- if(nibuf >= NIBUF-MAXINST){
- Bwrite(bout, ibuf, nibuf);
- nibuf = 0;
- }
- ibuf[nibuf++] = in->op;
- ibuf[nibuf++] = SRC(dismode[in->sm]) | DST(dismode[in->dm]) | disregmode[in->mm];
- if(in->mm != Anone)
- disaddr(in->mm, &in->m);
- if(in->sm != Anone)
- disaddr(in->sm, &in->s);
- if(in->dm != Anone)
- disaddr(in->dm, &in->d);
- }
- if(nibuf > 0)
- Bwrite(bout, ibuf, nibuf);
- free(ibuf);
- ibuf = nil;
- if(debug['s'])
- print("%lld instruction bytes start %lld\n", Boffset(bout) - fileoff, fileoff);
- }
- void
- disaddr(int m, Addr *a)
- {
- long val;
- val = 0;
- switch(m){
- case Anone:
- case Aerr:
- default:
- break;
- case Aimm:
- case Apc:
- case Adesc:
- val = a->offset;
- break;
- case Aoff:
- val = a->decl->iface->offset;
- break;
- case Anoff:
- val = -(a->decl->iface->offset+1);
- break;
- case Afp:
- case Amp:
- case Aldt:
- val = a->reg;
- break;
- case Afpind:
- case Ampind:
- disbcon(a->reg);
- val = a->offset;
- break;
- }
- disbcon(val);
- }
- void
- disbcon(long val)
- {
- if(val >= -64 && val <= 63){
- ibuf[nibuf++] = val & ~0x80;
- return;
- }
- if(val >= -8192 && val <= 8191){
- ibuf[nibuf++] = val>>8 & ~0xC0 | 0x80;
- ibuf[nibuf++] = val;
- return;
- }
- if(val < 0 && ((val >> 29) & 7) != 7
- || val > 0 && (val >> 29) != 0)
- fatal("overflow in constant 16r%lux", val);
- ibuf[nibuf++] = val>>24 | 0xC0;
- ibuf[nibuf++] = val>>16;
- ibuf[nibuf++] = val>>8;
- ibuf[nibuf++] = val;
- }
|