diff options
| author | 2026-10-15 22:28:06 +0330 | |
|---|---|---|
| committer | 2026-10-15 22:28:06 +0330 | |
| commit | 5a4dc62a79af6135c7050e81a82dbfdfb0a7d4e0 (patch) | |
| tree | 805283b2d30b2cf0f53af42e5a3fc119af5e839f /src/compiler/analyzer.zc | |
| parent | definite assignment: reading a local before it is initialized is a compile er... (diff) | |
uninit: track aggregate fills per part, sticky computed-index fills, &a[k] and method calls set the aggregate; fix test/example hits; docs
Diffstat (limited to 'src/compiler/analyzer.zc')
| -rw-r--r-- | src/compiler/analyzer.zc | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/src/compiler/analyzer.zc b/src/compiler/analyzer.zc index 3802437..e68e165 100644 --- a/src/compiler/analyzer.zc +++ b/src/compiler/analyzer.zc @@ -440,7 +440,7 @@ int newloc(int n) { if (!local_ended) local_ended = chk_resize(0, 0, loccap); local_ended[i] = 0; if (!local_end_info) local_end_info = chk_resize(0, 0, loccap); local_end_info[i] = 0; if (!local_shadow) local_shadow = chk_resize(0, 0, loccap); local_shadow[i] = 0; - if (!linited) linited = chk_resize(0, 0, loccap); linited[i] = 0; + if (!linited) linited = chk_resize(0, 0, loccap); linited[i] = 0; if (!lfill) lfill = chk_resize(0, 0, loccap); lfill[i] = 0; lpos[i] = 0; lreadpos[i] = 0; lowner[i] = 0; @@ -1027,13 +1027,32 @@ int luse(int i) { } // definite assignment (spec 4.1.5): a local must be written on every path // before it is read. linited[i] is 1 once that is true for the current path. +// linited[i] is -1 when the whole local is set; an array or struct being filled +// part by part holds a bit per field or constant element written so far (parts +// 0..61). a join ands the paths' words, so a part counts only when every path set it. int mark_inited(int i) { - if (i >= 0 && linited) linited[i] = 1; + if (i >= 0 && linited) linited[i] = -1; return 0; } int need_inited(int i) { if (!fchk || panic || dry || i < 0 || !linited) return 0; - if (!linited[i]) serrn(lname[i], "used before it is initialized"); + if (linited[i] != -1 && !(lfill && lfill[i])) serrn(lname[i], "used before it is initialized"); + return 0; +} +// part k (or -1: unknown) of aggregate local i was written; n is how many parts it has +int mark_part(int i, int k, int n) { + if (i < 0 || !linited || linited[i] == -1) return 0; + if (k < 0 || k > 61 || n > 62) { linited[i] = -1; if (lfill) lfill[i] = 1; return 0; } // a computed index: a fill loop, taken as setting it all (on every path: loops may not run, so this is sticky) + linited[i] = linited[i] | (1 << k); + if (n > 0 && linited[i] == (1 << n) - 1) linited[i] = -1; + return 0; +} +// part k (or -1) of aggregate local i is read +int need_part(int i, int k) { + if (!fchk || panic || dry || i < 0 || !linited || linited[i] == -1 || (lfill && lfill[i])) return 0; + if (k > 61) return 0; // past the parts tracked (or out of range: the bounds check reports it) + if (k >= 0 && k <= 61 && ((linited[i] >> k) & 1)) return 0; + serrn(lname[i], "used before it is initialized"); return 0; } @@ -1212,7 +1231,7 @@ int snap_push() { p = R_SNAP + b; p[0] = lbase; p[1] = nloc; p = p + 2; - while (i < nloc) { p[0] = lstate[i]; p[1] = lowner[i]; p[2] = lhome[i]; if (linited) p[3] = linited[i]; else p[3] = 1; p = p + 4; i++; } + while (i < nloc) { p[0] = lstate[i]; p[1] = lowner[i]; p[2] = lhome[i]; if (linited) p[3] = linited[i]; else p[3] = -1; p = p + 4; i++; } snaptop = p - R_SNAP; return b; } @@ -1295,7 +1314,7 @@ word jow(word p, int i) { return p[3 + 4 * (i - p[0])]; } word jhm(word p, int i) { return p[4 + 4 * (i - p[0])]; } // definite-assignment bit for local i on path p (1 if missing from the snapshot). word jin(word p, int i) { - if (i >= p[1]) return 1; + if (i >= p[1]) return -1; return p[5 + 4 * (i - p[0])]; } // the states at a break, with the jump to patch: [site] then a snapshot @@ -1304,7 +1323,7 @@ word exit_rec(int site) { reserve_R_EXIT(extop + 3 + 4 * (nloc - lbase)); p = R_EXIT + extop; p[0] = site; p[1] = lbase; p[2] = nloc; q = p + 3; - while (i < nloc) { q[0] = lstate[i]; q[1] = lowner[i]; q[2] = lhome[i]; if (linited) q[3] = linited[i]; else q[3] = 1; q = q + 4; i++; } + while (i < nloc) { q[0] = lstate[i]; q[1] = lowner[i]; q[2] = lhome[i]; if (linited) q[3] = linited[i]; else q[3] = -1; q = q + 4; i++; } extop = q - R_EXIT; return p; } @@ -1360,8 +1379,8 @@ int join(int n0, int what) { } // definite assignment: only initialized if every reaching path assigned it if (linited) { - j = 0; s = 1; - while (j < njps) { if (!jin(jps[j], i)) s = 0; j++; } + j = 0; s = -1; + while (j < njps) { s = s & jin(jps[j], i); j++; } linited[i] = s; } i++; |
