ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/cmd/limbo/sbl.b/
sbltname := array[Tend] of
{
Tnone => byte 'n',
Tadt => byte 'a',
Tadtpick => byte 'a',
Tarray => byte 'A',
Tbig => byte 'B',
Tbyte => byte 'b',
Tchan => byte 'C',
Treal => byte 'f',
Tfn => byte 'F',
Tint => byte 'i',
Tlist => byte 'L',
Tmodule => byte 'm',
Tref => byte 'R',
Tstring => byte 's',
Ttuple => byte 't',
Texception => byte 't',
Tfix => byte 'i',
Tpoly => byte 'P',
Tainit => byte '?',
Talt => byte '?',
Tany => byte 'N',
Tarrow => byte '?',
Tcase => byte '?',
Tcasel => byte '?',
Tcasec => byte '?',
Tdot => byte '?',
Terror => byte '?',
Tgoto => byte '?',
Tid => byte '?',
Tiface => byte '?',
Texcept => byte '?',
Tinst => byte '?',
};
sbltadtpick: con byte 'p';
sfiles: ref Sym;
ftail: ref Sym;
nsfiles: int;
blockid: int;
lastf: int;
lastline: int;
MAXSBLINT: con 12;
MAXSBLSRC: con 6*(MAXSBLINT+1);
sblmod(m: ref Decl)
{
bsym.puts("limbo .sbl 2.1\n");
bsym.puts(m.sym.name);
bsym.putb(byte '\n');
blockid = 0;
nsfiles = 0;
sfiles = ftail = nil;
lastf = 0;
lastline = 0;
}
sblfile(name: string): int
{
i := 0;
for(s := sfiles; s != nil; s = s.next){
if(s.name == name)
return i;
i++;
}
s = ref Sym;
s.name = name;
s.next = nil;
if(sfiles == nil)
sfiles = s;
else
ftail.next = s;
ftail = s;
nsfiles = i + 1;
return i;
}
filename(s: string): string
{
(nil, file) := str->splitr(s, "/ \\");
return file;
}
sblfiles()
{
for(i := 0; i < nfiles; i++)
files[i].sbl = sblfile(files[i].name);
bsym.puts(string nsfiles);
bsym.putb(byte '\n');
for(s := sfiles; s != nil; s = s.next){
bsym.puts(filename(s.name));
bsym.putb(byte '\n');
}
}
sblint(buf: array of byte, off, v: int): int
{
if(v == 0){
buf[off++] = byte '0';
return off;
}
stop := off + MAXSBLINT;
if(v < 0){
buf[off++] = byte '-';
v = -v;
}
n := stop;
while(v > 0){
buf[n -= 1] = byte(v % 10 + '0');
v = v / 10;
}
while(n < stop)
buf[off++] = buf[n++];
return off;
}
sblsrcconvb(buf: array of byte, off: int, src: Src): int
{
(startf, startl) := fline(src.start >> PosBits);
(stopf, stopl) := fline(src.stop >> PosBits);
if(lastf != startf.sbl){
off = sblint(buf, off, startf.sbl);
buf[off++] = byte ':';
}
if(lastline != startl){
off = sblint(buf, off, startl);
buf[off++] = byte '.';
}
off = sblint(buf, off, (src.start & PosMask));
buf[off++] = byte ',';
if(startf.sbl != stopf.sbl){
off = sblint(buf, off, stopf.sbl);
buf[off++] = byte ':';
}
if(startl != stopl){
off = sblint(buf, off, stopl);
buf[off++] = byte '.';
}
off = sblint(buf, off, (src.stop & PosMask));
buf[off++] = byte ' ';
lastf = stopf.sbl;
lastline = stopl;
return off;
}
sblsrcconv(src: Src): string
{
s := "";
(startf, startl) := fline(src.start >> PosBits);
(stopf, stopl) := fline(src.stop >> PosBits);
if(lastf != startf.sbl){
s += string startf.sbl;
s[len s] = ':';
}
if(lastline != startl){
s += string startl;
s[len s] = '.';
}
s += string (src.start & PosMask);
s[len s] = ',';
if(startf.sbl != stopf.sbl){
s += string stopf.sbl;
s[len s] = ':';
}
if(startl != stopl){
s += string stopl;
s[len s] = '.';
}
s += string (src.stop & PosMask);
s[len s] = ' ';
lastf = stopf.sbl;
lastline = stopl;
return s;
}
isnilsrc(s: Src): int
{
return s.start == 0 && s.stop == 0;
}
isnilstopsrc(s: Src): int
{
return s.stop == 0;
}
sblinst(in: ref Inst, ninst: int)
{
src: Src;
MAXSBL: con 8*1024;
buf := array[MAXSBL] of byte;
n := 0;
bsym.puts(string ninst);
bsym.putb(byte '\n');
sblblocks := array[nblocks] of {* => -1};
for(; in != nil; in = in.next){
if(in.op == INOOP)
continue;
if(in.src.start < 0)
fatal("no file specified for "+instconv(in));
if(n >= (MAXSBL - MAXSBLSRC - MAXSBLINT - 1)){
bsym.write(buf, n);
n = 0;
}
if(isnilsrc(in.src))
in.src = src;
else if(isnilstopsrc(in.src)){ # how does this happen ?
in.src.stop = in.src.start;
in.src.stop++;
}
n = sblsrcconvb(buf, n, in.src);
src = in.src;
b := sblblocks[in.block];
if(b < 0)
sblblocks[in.block] = b = blockid++;
n = sblint(buf, n, b);
buf[n++] = byte '\n';
}
if(n > 0)
bsym.write(buf, n);
}
sblty(tys: array of ref Decl, ntys: int)
{
bsym.puts(string ntys);
bsym.putb(byte '\n');
for(i := 0; i < ntys; i++){
d := tys[i];
d.ty.sbl = i;
}
for(i = 0; i < ntys; i++){
d := tys[i];
sbltype(d.ty, 1);
}
}
sblfn(fns: array of ref Decl, nfns: int)
{
bsym.puts(string nfns);
bsym.putb(byte '\n');
for(i := 0; i < nfns; i++){
f := fns[i];
if(ispoly(f))
rmfnptrs(f);
bsym.puts(string f.pc.pc);
bsym.putb(byte ':');
if(f.dot != nil && f.dot.ty.kind == Tadt){
bsym.puts(f.dot.sym.name);
bsym.putb(byte '.');
}
bsym.puts(f.sym.name);
bsym.putb(byte '\n');
sbldecl(f.ty.ids, Darg);
sbldecl(f.locals, Dlocal);
sbltype(f.ty.tof, 0);
}
}
sblvar(vars: ref Decl)
{
sbldecl(vars, Dglobal);
}
isvis(id: ref Decl): int
{
if(!tattr[id.ty.kind].vis
|| id.sym == nil
|| id.sym.name == ""
|| id.sym.name[0] == '.')
return 0;
if(id.ty == tstring && id.init != nil && id.init.op == Oconst)
return 0;
if(id.src.start < 0 || id.src.stop < 0)
return 0;
return 1;
}
sbldecl(ids: ref Decl, store: int)
{
n := 0;
for(id := ids; id != nil; id = id.next){
if(id.store != store || !isvis(id))
continue;
n++;
}
bsym.puts(string n);
bsym.putb(byte '\n');
for(id = ids; id != nil; id = id.next){
if(id.store != store || !isvis(id))
continue;
bsym.puts(string id.offset);
bsym.putb(byte ':');
bsym.puts(id.sym.name);
bsym.putb(byte ':');
bsym.puts(sblsrcconv(id.src));
sbltype(id.ty, 0);
bsym.putb(byte '\n');
}
}
sbltype(t: ref Type, force: int)
{
if(t.kind == Tadtpick)
t = t.decl.dot.ty;
d := t.decl;
if(!force && d != nil && d.ty.sbl >= 0){
bsym.putb(byte '@');
bsym.puts(string d.ty.sbl);
bsym.putb(byte '\n');
return;
}
if(t.rec != byte 0)
fatal("recursive sbl type: "+typeconv(t));
t.rec = byte 1;
case t.kind{
* =>
fatal("bad type in sbltype: "+typeconv(t));
Tnone or
Tany or
Tint or
Tbig or
Tbyte or
Treal or
Tstring or
Tfix or
Tpoly =>
bsym.putb(sbltname[t.kind]);
Tfn =>
bsym.putb(sbltname[t.kind]);
sbldecl(t.ids, Darg);
sbltype(t.tof, 0);
Tarray or
Tlist or
Tchan or
Tref =>
bsym.putb(sbltname[t.kind]);
if(t.kind == Tref && t.tof.kind == Tfn){
tattr[Tany].vis = 1;
sbltype(tfnptr, 0);
tattr[Tany].vis = 0;
}
else
sbltype(t.tof, 0);
Ttuple or
Texception =>
bsym.putb(sbltname[t.kind]);
bsym.puts(string t.size);
bsym.putb(byte '.');
sbldecl(t.ids, Dfield);
Tadt =>
if(t.tags != nil)
bsym.putb(sbltadtpick);
else
bsym.putb(sbltname[t.kind]);
if(d.dot != nil && !isimpmod(d.dot.sym))
bsym.puts(d.dot.sym.name + "->");
bsym.puts(d.sym.name);
bsym.putb(byte ' ');
bsym.puts(sblsrcconv(d.src));
bsym.puts(string d.ty.size);
bsym.putb(byte '\n');
sbldecl(t.ids, Dfield);
if(t.tags != nil){
bsym.puts(string t.decl.tag);
bsym.putb(byte '\n');
lastt : ref Type = nil;
for(tg := t.tags; tg != nil; tg = tg.next){
bsym.puts(tg.sym.name);
bsym.putb(byte ':');
bsym.puts(sblsrcconv(tg.src));
if(lastt == tg.ty){
bsym.putb(byte '\n');
}else{
bsym.puts(string tg.ty.size);
bsym.putb(byte '\n');
sbldecl(tg.ty.ids, Dfield);
}
lastt = tg.ty;
}
}
Tmodule =>
bsym.putb(sbltname[t.kind]);
bsym.puts(d.sym.name);
bsym.putb(byte '\n');
bsym.puts(sblsrcconv(d.src));
sbldecl(t.ids, Dglobal);
}
t.rec = byte 0;
}