ihead: ref Inst; # first instruction generated for .class fileitail: ref Inst; # last instruction (for appending to list) cache: array of byte; # module data cachencached: int; # number of bytes in cachendatum: int; # number of non-string basic datums in cachestartoff: int; # offset of first datum in cachelastoff: int; # 1 past last byte offset in cachelastkind: int = -1; # last kind of datum put in cachelencache: int; # capacity of cache ## Generate Dis object file (.dis).# discon(val: int){ if(val >= -64 && val <= 63) { bout.putb(byte(val & ~16r80)); return; } if(val >= -8192 && val <= 8191) { bout.putb(byte(((val>>8) & ~16rC0) | 16r80)); bout.putb(byte val); return; } if(notimmable(val)) fatal("discon: overflow 16r" + hex(val, 0)); bout.putb(byte((val>>24) | 16rC0)); bout.putb(byte(val>>16)); bout.putb(byte(val>>8)); bout.putb(byte val);} disword(w: int){ bout.putb(byte(w >> 24)); bout.putb(byte(w >> 16)); bout.putb(byte(w >> 8)); bout.putb(byte w);} disdata(kind: int, n: int){ if(n < DMAX && n != 0) bout.putb(byte((kind << DBYTE) | n)); else{ bout.putb(byte(kind << DBYTE)); discon(n); }} disflush(kind: int, off: int, size: int){ if(kind != lastkind || off != lastoff){ if(lastkind != -1 && ncached){ disdata(lastkind, ndatum); discon(startoff); bout.write(cache, ncached); } startoff = off; lastkind = kind; ncached = 0; ndatum = 0; } lastoff = off + size; while(kind >= 0 && ncached + size >= len cache){ c := array[ncached + 1024] of byte; c[0:] = cache; cache = c; }} disbyte(off: int, v: byte){ disflush(DEFB, off, 1); cache[ncached++] = v; ndatum++;} disint(off: int, v: int){ disflush(DEFW, off, IBY2WD); cache[ncached++] = byte(v >> 24); cache[ncached++] = byte(v >> 16); cache[ncached++] = byte(v >> 8); cache[ncached++] = byte v; ndatum++;} dislong(off: int, v: big){ iv: int; disflush(DEFL, off, IBY2LG); iv = int(v >> 32); cache[ncached++] = byte(iv >> 24); cache[ncached++] = byte(iv >> 16); cache[ncached++] = byte(iv >> 8); cache[ncached++] = byte iv; iv = int v; cache[ncached++] = byte(iv >> 24); cache[ncached++] = byte(iv >> 16); cache[ncached++] = byte(iv >> 8); cache[ncached++] = byte iv; ndatum++;} disreal(off: int, v: real){ disflush(DEFF, off, IBY2LG); bv := math->realbits64(v); iv := int(bv >> 32); cache[ncached++] = byte(iv >> 24); cache[ncached++] = byte(iv >> 16); cache[ncached++] = byte(iv >> 8); cache[ncached++] = byte(iv); iv = int bv; cache[ncached++] = byte(iv >> 24); cache[ncached++] = byte(iv >> 16); cache[ncached++] = byte(iv >> 8); cache[ncached++] = byte(iv); ndatum++;} disstring(offset: int, s: string){ disflush(-1, -1, 0); d := array of byte s; disdata(DEFS, len d); discon(offset); bout.write(d, len d);} ## Begin an array initializer.# disarray(off: int, tid: int, nelt: int){ disflush(-1, -1, 0); disdata(DEFA, 1); # 1 is ignored discon(off); disword(tid); disword(nelt); disdata(DIND, 1); # 1 is ignored discon(off); disword(0);} ## Terminate an array initializer.# disapop(){ disflush(-1, -1, 0); disdata(DAPOP, 1); # 1 is ignored discon(0);} ## Put number of instructions into .dis Header.# disninst(){ i: int; if(itail != nil) i = itail.pc + 1; else i = 0; discon(i);} dismode := array [int Aend] of { byte AXXX, # Anone byte AIMM, # Aimm byte AMP, # Amp byte (AMP|AIND), # Ampind byte AFP, # Afp byte (AFP|AIND) # Afpind}; disregmode := array [int Aend] of { byte AXNON, # Anone byte AXIMM, # Aimm byte AXINM, # Amp byte AXNON, # Ampind byte AXINF, # Afp byte AXNON # Afpind}; MAXCON: con 4;MAXADDR: con 2*MAXCON;MAXINST: con 3*MAXCON+2;NIBUF: con 1024; ibuf: array of byte;nibuf: int; disbcon(val: int){ if(val >= -64 && val <= 63){ ibuf[nibuf++] = byte(val & ~16r80); return; } if(val >= -8192 && val <= 8191){ ibuf[nibuf++] = byte(val>>8 & ~16rC0 | 16r80); ibuf[nibuf++] = byte val; return; } if(notimmable(val)) fatal("disbcon: overflow 16r" + hex(val, 0)); ibuf[nibuf++] = byte(val>>24 | 16rC0); ibuf[nibuf++] = byte(val>>16); ibuf[nibuf++] = byte(val>>8); ibuf[nibuf++] = byte val;} disaddr(a: ref Addr){ val: int; val = 0; case int a.mode { int Aimm => val = a.ival; int Afp or int Amp => val = a.offset; int Afpind or int Ampind => disbcon(a.ival); val = a.offset; } disbcon(val);} disinst(){ i: ref Inst; ibuf = array [NIBUF] of byte; nibuf = 0; for(i = ihead; i != nil; i = i.next){ if(nibuf >= NIBUF-MAXINST){ bout.write(ibuf, nibuf); nibuf = 0; } ibuf[nibuf++] = i.op; o := dismode[int i.s.mode] << SRC; o |= dismode[int i.d.mode] << DST; o |= disregmode[int i.m.mode]; ibuf[nibuf++] = o; if(i.m.mode != Anone) disaddr(i.m); if(i.s.mode != Anone) disaddr(i.s); if(i.d.mode != Anone) disaddr(i.d); } if(nibuf > 0) bout.write(ibuf, nibuf); ibuf = nil;} disstr(s: string){ a := array of byte s; for (i := 0; i < len a; i++) bout.putb(a[i]); discon(0);} dishandlers(){ discon(len class.handlers); for (it := class.handlers; it != nil; it = tl it) { h := hd it; discon(EXSTR); # exception string offset in fp discon(h.start_pc); # from start_pc discon(h.end_pc); # up to, but not including end_pc discon(-1); # type to destroy, -1 means nothing discon(1); # number of exception handlers disstr("*"); # handle any ex, we will later rethrow if not handled discon(h.handler_pc); # pc to jump to when exception occurs discon(-1); }} disout(){ discon(XMAGIC); flags := DONTCOMPILE; discon(DONTCOMPILE | HASEXCEPT); # dis flags disstackext(); # minimum stack extent size disninst(); disnvar(); disndesc(); disnlinks(); disentry(); disinst(); disdesc(); disvar(); dismod(); dislinks(); dishandlers();}
ihead: ref Inst; # first instruction generated for .class file
itail: ref Inst; # last instruction (for appending to list)
cache: array of byte; # module data cache
ncached: int; # number of bytes in cache
ndatum: int; # number of non-string basic datums in cache
startoff: int; # offset of first datum in cache
lastoff: int; # 1 past last byte offset in cache
lastkind: int = -1; # last kind of datum put in cache
lencache: int; # capacity of cache
#
# Generate Dis object file (.dis).
#
discon(val: int)
{
if(val >= -64 && val <= 63) {
bout.putb(byte(val & ~16r80));
return;
}
if(val >= -8192 && val <= 8191) {
bout.putb(byte(((val>>8) & ~16rC0) | 16r80));
bout.putb(byte val);
return;
}
if(notimmable(val))
fatal("discon: overflow 16r" + hex(val, 0));
bout.putb(byte((val>>24) | 16rC0));
bout.putb(byte(val>>16));
bout.putb(byte(val>>8));
bout.putb(byte val);
}
disword(w: int)
{
bout.putb(byte(w >> 24));
bout.putb(byte(w >> 16));
bout.putb(byte(w >> 8));
bout.putb(byte w);
}
disdata(kind: int, n: int)
{
if(n < DMAX && n != 0)
bout.putb(byte((kind << DBYTE) | n));
else{
bout.putb(byte(kind << DBYTE));
discon(n);
}
}
disflush(kind: int, off: int, size: int)
{
if(kind != lastkind || off != lastoff){
if(lastkind != -1 && ncached){
disdata(lastkind, ndatum);
discon(startoff);
bout.write(cache, ncached);
}
startoff = off;
lastkind = kind;
ncached = 0;
ndatum = 0;
}
lastoff = off + size;
while(kind >= 0 && ncached + size >= len cache){
c := array[ncached + 1024] of byte;
c[0:] = cache;
cache = c;
}
}
disbyte(off: int, v: byte)
{
disflush(DEFB, off, 1);
cache[ncached++] = v;
ndatum++;
}
disint(off: int, v: int)
{
disflush(DEFW, off, IBY2WD);
cache[ncached++] = byte(v >> 24);
cache[ncached++] = byte(v >> 16);
cache[ncached++] = byte(v >> 8);
cache[ncached++] = byte v;
ndatum++;
}
dislong(off: int, v: big)
{
iv: int;
disflush(DEFL, off, IBY2LG);
iv = int(v >> 32);
cache[ncached++] = byte(iv >> 24);
cache[ncached++] = byte(iv >> 16);
cache[ncached++] = byte(iv >> 8);
cache[ncached++] = byte iv;
iv = int v;
cache[ncached++] = byte(iv >> 24);
cache[ncached++] = byte(iv >> 16);
cache[ncached++] = byte(iv >> 8);
cache[ncached++] = byte iv;
ndatum++;
}
disreal(off: int, v: real)
{
disflush(DEFF, off, IBY2LG);
bv := math->realbits64(v);
iv := int(bv >> 32);
cache[ncached++] = byte(iv >> 24);
cache[ncached++] = byte(iv >> 16);
cache[ncached++] = byte(iv >> 8);
cache[ncached++] = byte(iv);
iv = int bv;
cache[ncached++] = byte(iv >> 24);
cache[ncached++] = byte(iv >> 16);
cache[ncached++] = byte(iv >> 8);
cache[ncached++] = byte(iv);
ndatum++;
}
disstring(offset: int, s: string)
{
disflush(-1, -1, 0);
d := array of byte s;
disdata(DEFS, len d);
discon(offset);
bout.write(d, len d);
}
#
# Begin an array initializer.
#
disarray(off: int, tid: int, nelt: int)
{
disflush(-1, -1, 0);
disdata(DEFA, 1); # 1 is ignored
discon(off);
disword(tid);
disword(nelt);
disdata(DIND, 1); # 1 is ignored
discon(off);
disword(0);
}
#
# Terminate an array initializer.
#
disapop()
{
disflush(-1, -1, 0);
disdata(DAPOP, 1); # 1 is ignored
discon(0);
}
#
# Put number of instructions into .dis Header.
#
disninst()
{
i: int;
if(itail != nil)
i = itail.pc + 1;
else
i = 0;
discon(i);
}
dismode := array [int Aend] of {
byte AXXX, # Anone
byte AIMM, # Aimm
byte AMP, # Amp
byte (AMP|AIND), # Ampind
byte AFP, # Afp
byte (AFP|AIND) # Afpind
};
disregmode := array [int Aend] of {
byte AXNON, # Anone
byte AXIMM, # Aimm
byte AXINM, # Amp
byte AXNON, # Ampind
byte AXINF, # Afp
byte AXNON # Afpind
};
MAXCON: con 4;
MAXADDR: con 2*MAXCON;
MAXINST: con 3*MAXCON+2;
NIBUF: con 1024;
ibuf: array of byte;
nibuf: int;
disbcon(val: int)
{
if(val >= -64 && val <= 63){
ibuf[nibuf++] = byte(val & ~16r80);
return;
}
if(val >= -8192 && val <= 8191){
ibuf[nibuf++] = byte(val>>8 & ~16rC0 | 16r80);
ibuf[nibuf++] = byte val;
return;
}
if(notimmable(val))
fatal("disbcon: overflow 16r" + hex(val, 0));
ibuf[nibuf++] = byte(val>>24 | 16rC0);
ibuf[nibuf++] = byte(val>>16);
ibuf[nibuf++] = byte(val>>8);
ibuf[nibuf++] = byte val;
}
disaddr(a: ref Addr)
{
val: int;
val = 0;
case int a.mode {
int Aimm =>
val = a.ival;
int Afp or
int Amp =>
val = a.offset;
int Afpind or
int Ampind =>
disbcon(a.ival);
val = a.offset;
}
disbcon(val);
}
disinst()
{
i: ref Inst;
ibuf = array [NIBUF] of byte;
nibuf = 0;
for(i = ihead; i != nil; i = i.next){
if(nibuf >= NIBUF-MAXINST){
bout.write(ibuf, nibuf);
nibuf = 0;
}
ibuf[nibuf++] = i.op;
o := dismode[int i.s.mode] << SRC;
o |= dismode[int i.d.mode] << DST;
o |= disregmode[int i.m.mode];
ibuf[nibuf++] = o;
if(i.m.mode != Anone)
disaddr(i.m);
if(i.s.mode != Anone)
disaddr(i.s);
if(i.d.mode != Anone)
disaddr(i.d);
}
if(nibuf > 0)
bout.write(ibuf, nibuf);
ibuf = nil;
}
disstr(s: string)
{
a := array of byte s;
for (i := 0; i < len a; i++)
bout.putb(a[i]);
discon(0);
}
dishandlers()
{
discon(len class.handlers);
for (it := class.handlers; it != nil; it = tl it) {
h := hd it;
discon(EXSTR); # exception string offset in fp
discon(h.start_pc); # from start_pc
discon(h.end_pc); # up to, but not including end_pc
discon(-1); # type to destroy, -1 means nothing
discon(1); # number of exception handlers
disstr("*"); # handle any ex, we will later rethrow if not handled
discon(h.handler_pc); # pc to jump to when exception occurs
discon(-1);
}
}
disout()
{
discon(XMAGIC);
flags := DONTCOMPILE;
discon(DONTCOMPILE | HASEXCEPT); # dis flags
disstackext(); # minimum stack extent size
disninst();
disnvar();
disndesc();
disnlinks();
disentry();
disinst();
disdesc();
disvar();
dismod();
dislinks();
dishandlers();
}