aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/image.zc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/image.zc')
-rw-r--r--src/compiler/image.zc95
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;
+}
+