1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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;
}
|