diff options
Diffstat (limited to 'appl/cmd/limbo/sbl.b')
| -rw-r--r-- | appl/cmd/limbo/sbl.b | 397 |
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; +} |
