aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/analyzer.zc
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-15 22:28:06 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-15 22:28:06 +0330
commit5a4dc62a79af6135c7050e81a82dbfdfb0a7d4e0 (patch)
tree805283b2d30b2cf0f53af42e5a3fc119af5e839f /src/compiler/analyzer.zc
parentdefinite 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.zc35
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++;