summaryrefslogtreecommitdiff
path: root/appl/cmd/limbo/sbl.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/limbo/sbl.b')
-rw-r--r--appl/cmd/limbo/sbl.b397
1 files changed, 397 insertions, 0 deletions
diff --git a/appl/cmd/limbo/sbl.b b/appl/cmd/limbo/sbl.b
new file mode 100644
index 00000000..0ae69d5f
--- /dev/null
+++ b/appl/cmd/limbo/sbl.b
@@ -0,0 +1,397 @@
+
+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;
+}