aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/analyzer.zc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/analyzer.zc')
-rw-r--r--src/compiler/analyzer.zc63
1 files changed, 10 insertions, 53 deletions
diff --git a/src/compiler/analyzer.zc b/src/compiler/analyzer.zc
index 1822fe5..c2ea867 100644
--- a/src/compiler/analyzer.zc
+++ b/src/compiler/analyzer.zc
@@ -772,72 +772,29 @@ int xc_reason(int ix, int arr) {
}
return XC_NOT_LOOP;
}
-// one character of the unit's source
-int xc_byte(int k) { return (xc_src[k >> 2] >> ((k & 3) * 8)) & 255; }
-// the column (from 1) of the source offset o
-int xc_col(int o) {
- int k = o;
- while (k > 0 && xc_byte(k - 1) != 10) k--;
- return o - k + 1;
-}
-// a json string
-int xc_str(char* s) {
- int i = 0, ch;
- rt.put_c(34);
- while (s[i]) {
- ch = s[i] & 255;
- if (ch == 34 || ch == 92) rt.put_c(92);
- if (ch < 32) rt.put_c(32); else rt.put_c(ch);
- i++;
- }
- rt.put_c(34);
- return 0;
-}
-int xc_field(char* name) { rt.put_c(44); xc_str(name); rt.put_c(58); return 0; }
// the record of one kept check: kind 0 index, 1 pointer; the place of its [
-// and, as the end, the token just read (its ])
+// and, as the end, the token just read (its ]). src/lib/explain.zc writes it.
int xc_note(int kind, int why, int place) {
- int o1, o2, d = 0, k = loopbase;
- if (!xc_on || dry || cmode || incdepth > 0 || !xc_src || chbase != xc_src) return 0;
+ int o1, o2, d = 0, k = loopbase, f;
+ if (!xc_on || dry || cmode || incdepth > 0 || !xc_src || chbase != xc_src || !xc_hook) return 0;
o1 = ((place >> 40) & 0x1FFFFF) - 1; o2 = tpend;
if (o1 < 0 || o2 < o1) return 0;
while (k < lsp) { if (R_LOOP[k * 8] != 0 - 1) d++; k++; }
- rt.put_s("{\"file\":"); xc_str(xc_file);
- xc_field("line"); rt.put_n(place & 0xFFFFFF);
- xc_field("col"); rt.put_n(xc_col(o1));
- xc_field("end_line"); rt.put_n(tpline);
- xc_field("end_col"); rt.put_n(xc_col(o2));
- xc_field("fn"); xc_str(xc_fn);
- xc_field("kind"); if (kind) xc_str("pointer"); else xc_str("index");
- xc_field("loop_depth"); rt.put_n(d);
- xc_field("reason");
- if (why == XC_NOT_LOOP) xc_str("index-not-loop-variable");
- else if (why == XC_NOT_INVARIANT) xc_str("bound-not-invariant");
- else if (why == XC_NOT_LEN) xc_str("index-not-len-derived");
- else if (why == XC_SIZE) xc_str("size-unknown");
- else if (why == XC_PACKED) xc_str("packed-elements");
- else if (why == XC_MAYFREE) xc_str("pointer-may-be-freed");
- else xc_str("hoisted-to-loop-entry");
- xc_field("fix");
- if (why == XC_NOT_LOOP) xc_str("index with the variable of a loop for (i = 0; i < bound; i++), or mark the code unbounded if the index is known to be in range");
- else if (why == XC_NOT_INVARIANT) xc_str("the loop body changes the index, the bound or the array, takes an address or makes a closure; keep them fixed inside the loop");
- else if (why == XC_NOT_LEN) xc_str("bound the loop with len() of the array, or with a constant no larger than its length");
- else if (why == XC_SIZE) xc_str("the compiler does not know the size of the block; allocate it here with a constant size, or index a fixed array");
- else if (why == XC_PACKED) xc_str("packed elements are checked by the runtime on every access");
- else if (why == XC_MAYFREE) xc_str("the loop body calls something that might free or resize the block; move the call out of the loop");
- else xc_str("checked once when the loop starts, and on every access only if that check fails; nothing to do");
- rt.put_c(125); rt.put_c(10);
+ f = xc_hook; f(xc_src, kind, why, place & 0xFFFFFF, o1, tpline, o2, d, xc_fn, xc_file);
return 0;
}
-// is argument 1 --explain-checks? the file name for the records is argument 2
+// is argument 1 --explain-checks? the file name for the records is argument 2.
+// then src/lib/explain.zc is compiled, and its note becomes the hook.
int xc_init() {
- int n = rt.syscall(rt.SYS_ARGC, 0, 0, 0), k; word b;
+ int n = rt.syscall(rt.SYS_ARGC, 0, 0, 0), k, s, f; word b;
if (n < 2) return 0;
b = chk_resize(0, 0, 32);
if (rt.syscall(rt.SYS_ARG, 1, b, 31) < 0 || !rt.eq_w(b, "--explain-checks")) return 0;
xc_on = 1;
if (n > 2) { k = rt.syscall(rt.SYS_ARG, 2, 0, 0); if (k >= 0) { b = chk_resize(0, 0, k + 1); rt.syscall(rt.SYS_ARG, 2, b, k + 1); xc_file = b; } }
- rt.put_s("{\"version\":1}"); rt.put_c(10);
+ inc_compile(bstr_text(explain_source()), "tinyvm:explain.zc", 0);
+ s = lookup(intern("explain.note")); if (s >= 0) xc_hook = sval[s];
+ s = lookup(intern("explain.version")); if (s >= 0) { f = sval[s]; f(); }
return 0;
}
// is the constant index xcval known to be inside the allocation f? the same