aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/expr.zc
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-14 18:22:04 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-14 20:03:38 +0330
commit459b7661aaa0d65d01be064bd4b9976c4f045a5c (patch)
treeeccb0738631fc52e5116fb238c2f7f961784ff36 /src/compiler/expr.zc
parentzy: nonzero exit on compile errors (diff)
bounds: body scan, loop-entry hoisting, pointer proofs from requested size, --explain-checks v1 (non-o3 code)
Diffstat (limited to 'src/compiler/expr.zc')
-rw-r--r--src/compiler/expr.zc33
1 files changed, 26 insertions, 7 deletions
diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc
index a548f8d..8768658 100644
--- a/src/compiler/expr.zc
+++ b/src/compiler/expr.zc
@@ -647,6 +647,7 @@ word closure_layout(int closure_index, int count) {
// variable in. ctx_push / ctx_pop save and restore the enclosing function's
// compiler state around the body.
int closure() {
+ char* xcf;
int np = 0; char*[24] pn; word[24] pty; int hop, entry, i, t, envl, ncap, c, result, declared = 0, tags = 0, tag, lt, lfl = tline; word[24] ptags;
word expected = closure_expected; closure_expected = 0;
reserve_closures(nclo + 1);
@@ -679,6 +680,7 @@ int closure() {
hop = hole(); op(O_JMP);
entry = here;
fn_begin(1, 0); fbnd = ctx_bnd();
+ xcf = xc_fn; xc_fn = "<closure>";
lt = lt_begin(entry, "<closure>", lfl);
if (declared) fty = declared;
prologue(); borrow_prologue();
@@ -700,7 +702,7 @@ int closure() {
if (result <= 0 || live) result = tword;
if (declared) result = declared;
epilogue();
- lt_end(lt, here);
+ lt_end(lt, here); xc_fn = xcf;
nclo--;
c = nclo;
ncap = clo_n[c];
@@ -1363,7 +1365,7 @@ int ptr_chk(int sz) {
// through rt.bchk, which only knows the size of a heap block's first word.
int postfix() { return postfix_tail(primary()); }
int postfix_tail(int c) {
- int b, n, t, et; word ft; word[8] bs; int k, ci, was, al, ix, enh, cz, cj, place, offset, temporary, call_owner, readonly, ub, bl, ic, inr; word storage, storage_mask, call_origins;
+ int b, n, t, et; word ft; word[8] bs; int k, ci, was, al, ix, enh, cz, cj, place, offset, temporary, call_owner, readonly, ub, bl, ic, inr, hg, pn; word storage, storage_mask, call_origins;
while (1) {
if (tk == T_ID && tv == s_as) { // e as T: same bits, another type
next(); t = ptype(); rval(); if (!xaf || xaf[2] != 5) xaf = 0; vf_coerce(t, 0);
@@ -1415,7 +1417,7 @@ int postfix_tail(int c) {
op(O_SWAP); lit(2); op(O_ADD); op(O_LD); lit(8); op(15); op(O_SWAP);
if (tbytes(et) != 1) { lit(tbytes(et)); op(15); }
op(O_ADD);
- } else callname(intern("datb"));
+ } else { callname(intern("datb")); xc_note(0, XC_PACKED, place); }
et = tpk(et);
} else if (xty[0] == TY_DYN) { // a growable array: bounds-checked, through the runtime
et = xty[4];
@@ -1468,7 +1470,7 @@ int postfix_tail(int c) {
setlit(k, here);
op(O_SWAP); lit(2); op(O_ADD); op(O_LD); op(O_SWAP);
mulsz(et); op(O_ADD);
- } else callname(s_dat);
+ } else { callname(s_dat); xc_note(0, xc_reason(ix, al), place); }
} else {
tcneed(isptr(xty) || xty == tword, "only pointers and arrays can be indexed", xty);
et = telem(xty);
@@ -1490,9 +1492,26 @@ int postfix_tail(int c) {
tcneed(isnum(xty) || xty == tword, "an index has to be a number", xty);
expect(s_rk);
if (!ub && !inr) {
- if (n >= 0) { if (!ic && !(ix >= 0 && proven_n(ix, n))) fixed_chk(n); }
- else if (tbytes(et)) ptr_chk(0 - tbytes(et));
- else ptr_chk(tsz(et));
+ if (n >= 0) {
+ if (!ic && !(ix >= 0 && proven_n(ix, n))) {
+ hg = hoist_guard(ix, n, 0 - 1);
+ fixed_chk(n);
+ if (hg >= 0) { setlit(hg, here); xc_note(0, XC_HOISTED, place); }
+ else xc_note(0, xc_reason(ix, 0 - 1), place);
+ }
+ } else {
+ pn = ptr_elems(storage, et, bl);
+ if (pn < 0) pn = ptr_elems(entry_fact(ix, bl), et, bl); // the loop top forgot the fact; the body leaves the pointer alone (hoist_guard and proven_p check)
+ if (pn >= 0 && ix >= 0 && proven_p(ix, pn, bl)) pn = pn; // the loop test proved it
+ else {
+ hg = 0 - 1; if (pn >= 0) hg = hoist_guard(ix, pn, bl);
+ if (tbytes(et)) ptr_chk(0 - tbytes(et));
+ else ptr_chk(tsz(et));
+ if (hg >= 0) { setlit(hg, here); xc_note(1, XC_HOISTED, place); }
+ else if (pn < 0) xc_note(1, XC_SIZE, place);
+ else xc_note(1, xc_reason(ix, bl), place);
+ }
+ }
}
if (tbytes(et)) { // packed: byte address = base * 8 + index * bytes
if (tbytes(et) != 1) { lit(tbytes(et)); op(15); }