diff options
Diffstat (limited to 'src/tools/zc0.c')
| -rw-r--r-- | src/tools/zc0.c | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/src/tools/zc0.c b/src/tools/zc0.c index 040a4ea..5846e22 100644 --- a/src/tools/zc0.c +++ b/src/tools/zc0.c @@ -73,6 +73,13 @@ static int esc(void) switch (c) { case 'n': return 10; case 't': return 9; case 'r': return 13; case '0': return 0; case 'e': return 27; } return c; } +/* line tables, as the self-hosted compiler makes them with lines on (see rt.line_blocks in rt.zc). + they are off until a program says lines on; or a marker comment //:lines NAME comes by, which + src/tools/automap.sh puts in front of the program of a run-only image: it turns them on, names + the file, and counts the lines from the next one. */ +static int zl_on, zl_base, zl_head, zl_entry, zl_open, zl_fline, zl_file_at, zl_n, zl_cap; +static char zl_file[256] = "<stdin>", zl_file_done[256], zl_name[64]; +static int64_t *zl_pairs; /* doc comments, as the self-hosted compiler reads them with docs on: the // lines directly above a declaration, up to a blank line or any other text */ static char dbuf[2100], dsnap[2100], dnm[64]; static int dn, dlast, dline, dsn, docpending; @@ -82,7 +89,15 @@ static void doccomment(void) /* pos is on the first slash */ while (k >= 0 && (src[k] == ' ' || src[k] == '\t')) k--; bol = k < 0 || src[k] == '\n'; pos += 2; - if (src[pos] == ':') { dn = 0; dlast = cl; docpending = 0; while (src[pos] && src[pos] != '\n') pos++; return; } + if (src[pos] == ':') { + if (!strncmp(src + pos, ":lines ", 7)) { + int n = 0; + pos += 7; + while (src[pos] && src[pos] != '\n' && src[pos] != '\r' && n < 255) zl_file[n++] = src[pos++]; + zl_file[n] = 0; zl_on = 1; zl_base = cl; + } + dn = 0; dlast = cl; docpending = 0; while (src[pos] && src[pos] != '\n') pos++; return; + } if (!bol) { while (src[pos] && src[pos] != '\n') pos++; return; } if (dn && dlast != cl - 1) dn = 0; if (src[pos] == ' ') pos++; @@ -500,6 +515,42 @@ static int bstrwords(const unsigned char *b, long n) if ((n & 7) == 0) emit(0); return a; } +/* line tables. zl_begin starts recording the function whose code begins at entry, zl_stmt notes + that a statement starts at the current line, and zl_end puts the function's line block among + the code, as lt_end does in the resident compiler: [next, entry, end, name, file, count, then + count words of offset << 32 | line]. */ +static void zl_begin(int entry, const char *name, int fline) +{ + if (!zl_on) { zl_open = 0; return; } + zl_open = 1; zl_entry = entry; zl_n = 0; zl_fline = fline - zl_base; + strncpy(zl_name, name, 63); zl_name[63] = 0; + if (zl_n == zl_cap) { zl_cap = zl_cap ? zl_cap * 2 : 1024; zl_pairs = realloc(zl_pairs, (size_t)zl_cap * sizeof *zl_pairs); } + zl_pairs[zl_n++] = zl_fline; +} +static void zl_stmt(void) +{ + int off = here - zl_entry; + if (!zl_open) return; + if (zl_n == zl_cap) { zl_cap *= 2; zl_pairs = realloc(zl_pairs, (size_t)zl_cap * sizeof *zl_pairs); } + if (zl_n && (zl_pairs[zl_n - 1] >> 32) == off) zl_n--; + if (zl_n && (zl_pairs[zl_n - 1] & 0xffffffffLL) == line - zl_base) return; + zl_pairs[zl_n++] = (int64_t)off * 4294967296LL + (line - zl_base); +} +static void zl_end(void) +{ + int end = here, name, file, blk, i; + if (!zl_open) return; + zl_open = 0; + name = bstrwords((const unsigned char *)zl_name, (long)strlen(zl_name)); + if (!zl_file_at || strcmp(zl_file, zl_file_done)) { + zl_file_at = bstrwords((const unsigned char *)zl_file, (long)strlen(zl_file)); strcpy(zl_file_done, zl_file); + } + file = zl_file_at; + blk = here; + emit(zl_head); emit(zl_entry); emit(end); emit(name); emit(file); emit(zl_n); + for (i = 0; i < zl_n; i++) emit(zl_pairs[i]); + zl_head = blk; +} /* b"...": the words inline, jumped over, then the address pushed */ static void bstrlit(void) { @@ -691,6 +742,7 @@ static void patchbreaks(void) { int i; for (i = 0; i < nbrk[nloop]; i++) setlit( static void stmt(void) { int a, b, c, d; + zl_stmt(); if (accept(";")) return; if (is("{")) { block(); return; } { @@ -759,7 +811,7 @@ static void stmt(void) /* ---- top level ---- */ static void fndef(int ret, int rstr) /* rstr: the return type is bstr */ { - char *n = ident(); Sym *s; int np = 0, tags = 0, t, frame, i, helper, busy, done, check, node; + char *n = ident(); int zfl = line; Sym *s; int np = 0, tags = 0, t, frame, i, helper, busy, done, check, node; if (dsn && !dnm[0]) strcpy(dnm, n); char pn[16][64]; int pstr[16]; char full_name[256]; qualify(full_name, sizeof full_name, n); s = find_raw(full_name); @@ -794,6 +846,7 @@ static void fndef(int ret, int rstr) /* rstr: the return type is bstr */ } #endif nlo = 0; nslot = 0; nepi = 0; infn = 1; + zl_begin(here, s->name, zfl); for (i = 0; i < np; i++) { strcpy(lo[nlo].name, pn[i]); lo[nlo].arr = 0; lo[nlo].flt = 0; lo[nlo].dstr = lo[nlo].str = pstr[i & 15]; lo[nlo++].slot = nslot++; } /* retain the caller's pointer until the frame has its final segment. */ helper = !find("frame_busy") || !strcmp(s->name, "rt.frame_grow") || !strcmp(s->name, "rt.frame_leave"); @@ -823,6 +876,7 @@ static void fndef(int ret, int rstr) /* rstr: the return type is bstr */ op(O_RET); setlit(frame, nslot); infn = 0; + zl_end(); } /* enhance name(params) [-> n] micro "recipe"; or ... vm { asm }; emits the install descriptor; the booted genome installs it */ @@ -953,6 +1007,11 @@ static void top1(void) expect(";"); return; } if (accept("include")) { do { ident(); } while (accept(",")); expect(";"); return; } + if (is("lines")) { /* lines on; and lines off; (anything else is a name) */ + Lex L; lexsave(&L); next(); + if (is("on") || is("off")) { zl_on = is("on"); next(); expect(";"); return; } + lexrest(&L); + } if (accept("embed")) { embeddecl(0); return; } { if (accept("unchecked")) { top1(); return; } @@ -1088,6 +1147,8 @@ int main(int argc, char **argv) setlit(fx[i].at, s->val); } if (!(st = find("start")) || !st->defd) { fprintf(stderr, "zc0: no start\n"); return 1; } + /* the line tables are reached through rt.line_blocks, which starts out as the newest block */ + if (zl_head && (st = find_raw("rt.line_blocks"))) img[st->val - GORG] = zl_head; /* symbol blob: kind, value, sig, name chars, 0 ... then a 0 kind */ img[5] = here; for (i = 0; i < nsy; i++) { |
