diff options
Diffstat (limited to 'src/compiler/image.zc')
| -rw-r--r-- | src/compiler/image.zc | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/compiler/image.zc b/src/compiler/image.zc new file mode 100644 index 0000000..dfe5f77 --- /dev/null +++ b/src/compiler/image.zc @@ -0,0 +1,95 @@ +// ---- symbol blob ---- + +// an image ends with its own symbol table so the genome knows its names: +// kind, value, signature, name chars, 0 ... then a 0 kind. +// emit the names defined since symbol index from (functions, globals, +// constants, enhancements) as the image's trailing symbol table +int blob_emit(int from) { + int i = from, table, words = 1; word p; int b, k; + while (i < nsym) { + if (skind[i] == K_DOC) { b = sval[i]; words = words + 2 + (b[0] >> 3); } + if ((skind[i] >= K_FN && skind[i] <= K_CONST) || skind[i] == K_ENH || skind[i] == K_DOC) words = words + 4 + rt.len_w(sname[i]); + i++; + } + reserve_code(words); i = from; + // the docs first: each one's bytes go in the image here, and its symbol + // takes their address (the bytes come after the code, so no code moves) + while (i < nsym) { + if (skind[i] == K_DOC) { + b = sval[i]; + sval[i] = here; + emit(b[0]); + k = 0; + while (k < ((b[0] + 7) >> 3)) { emit(b[1 + k]); k++; } + if (!(b[0] & 7)) emit(0); + } + i++; + } + table = here; i = from; + while (i < nsym) { + if ((skind[i] >= K_FN && skind[i] <= K_CONST) || skind[i] == K_ENH || skind[i] == K_DOC) { + emit(skind[i]); emit(sval[i]); emit(ssig[i]); + p = sname[i]; + while (*p) { emit(*p); p++; } + emit(0); + } + i++; + } + emit(0); + return table; +} +// the reverse: read a blob and define its names, so a running genome knows its +// own functions by name +// hide: leave out the language server's names. functions are entered before +// constants and globals in the blob, so the server's functions come after +// chk_mark but the runtime's constants and globals come after it too: the +// cut is by name, the functions after chk_mark, and everything from the +// server's marker const (LSP_SERVER, the first thing src/lsp/server.zc declares) +int blob_load(word p, int hide) { + int s, n, past = 0, after = 0, skip, mkn = intern("run.chk_mark"), srvn = intern("lsp.LSP_SERVER"); + while (*p) { + n = intern(p + 3); + if (hide && n == srvn) after = 1; + skip = 0; + if (hide && n == mkn) past = 1; + if (!skip) { + s = addsym(n, p[0], p[1]); + ssig[s] = p[2]; + sflag[s] = F_DEF | F_SIG; + if (p[0] == K_ENH) { if (p[1] >= nenh) nenh = p[1] + 1; rt.install(p[2] >> 8); } + } + p = p + 3 + rt.len_w(p + 3) + 1; + } + return 0; +} +// compile the rest of stdin for org into a growing output buffer. the image's +// addresses remain logical addresses at org while its temporary storage grows. +// image_words and image_size expose the finished image; initial is its first +// buffer reservation. the matching host layout must still fit the finished image. +int build_image_grow(int org, int initial) { + int sh = here, sd = hdelta, sl = hlimit, sub = ubase, svl = vislo, sns = nsym, sen = nenh, n; + word saved_buffer = image_buffer; int saved_active = image_active, saved_org = image_org, saved_capacity = image_capacity; + if (org < 0 || initial < 7 || initial > 0x7fffffff - org) fatal("bad image reservation"); + image_buffer = chk_resize(0, 0, initial); image_active = 1; image_org = org; image_capacity = initial; + ubase = nsym; vislo = nsym; nenh = 0; + here = org; hdelta = image_buffer - org; hlimit = org + initial; + lit(rt.FTOP); lit(rt.ZFP); op(O_ST); fnref(fwdfn(s_start)); op(O_JMP); emit(0); emit(0); + unit_stdin(); + n = blob_emit(ubase); + image_buffer[5] = n; + image_buffer[6] = here; + n = here - org; image_words = image_buffer; image_size = n; + popsyms(sns); + ubase = sub; vislo = svl; here = sh; hdelta = sd; hlimit = sl; nenh = sen; + image_buffer = saved_buffer; image_active = saved_active; image_org = saved_org; image_capacity = saved_capacity; + return n; +} +// retain the explicit destination interface for callers that already own storage. +// use build_image_grow and image_words when the output must grow independently. +int build_image(int org, int dst) { + int n = build_image_grow(org, 4096), words = rt.syscall(9, 0, 0, 0); + if (dst < 0 || n > words - dst) fatal("image destination too small"); + rt.copy_w(dst, image_words, n); + return n; +} + |
