diff options
| author | 2026-10-15 09:48:10 +0330 | |
|---|---|---|
| committer | 2026-10-15 09:48:10 +0330 | |
| commit | 0a87c4663fc52bf60f3d440200b3b3ad6b39bd3e (patch) | |
| tree | 40d88acb972080ed90d89c7a866247263c252cae /src/compiler/analyzer.zc | |
| parent | merge work/stdio: std.Io and one-level module completion (diff) | |
analyzer: use-after-end messages name the borrower, the owner and how the owner ended (freed, moved, .d parameter, push, global, reassignment), with fixtures
Diffstat (limited to 'src/compiler/analyzer.zc')
| -rw-r--r-- | src/compiler/analyzer.zc | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/src/compiler/analyzer.zc b/src/compiler/analyzer.zc index 42cb7b5..48debee 100644 --- a/src/compiler/analyzer.zc +++ b/src/compiler/analyzer.zc @@ -949,10 +949,16 @@ int lend_drop(int dep, int from) { return 0; } // retire existing aliases together with their owner. dead aliases do not keep later loop snapshots live. +// end_why and end_whom say how the next end_owner ends its owner, for the message +// of a later use: 0 transferred, 1 freed, 2 given to a .d parameter of end_whom, +// 3 moved into end_whom, 4 stored in a container, 5 returned, 6 stored in a global +// or untracked memory, 7 freed by reassigning it, 8 pushed into end_whom. +int end_why; char* end_whom; int end_owner(int i) { - int j = lbase; word info = talloc(3); + int j = lbase; word info = talloc(5); lend_check(i); - info[0] = lname[i]; info[1] = lpos[i]; info[2] = tpack(); + info[0] = lname[i]; info[1] = lpos[i]; info[2] = tpack(); info[3] = end_why; info[4] = end_whom; + end_why = 0; end_whom = 0; local_ended[i] = info[2]; local_end_info[i] = info; lstate[i] = S_DEAD; while (j < nloc) { if (j != i && isalias(j) && lroot(j) == i) { local_ended[j] = info[2]; local_end_info[j] = info; lstate[j] = S_DEAD; } @@ -1345,6 +1351,8 @@ int recast(int c, int t) { else lstate[i] = t; return c; } +// where the argument argcheck is looking at goes: 0 unknown, 1 a push, else the callee's symbol + 2 +int arg_site; // an argument for a parameter tagged t (0 plain, 1 m, 2 d) int argcheck(int c, int t) { int i, st; @@ -1373,7 +1381,12 @@ int argcheck(int c, int t) { touch(i); return 0; } - if (st == S_D || ((st == S_M || st == S_U) && lown[i])) { end_owner(i); luse(i); xgive = 1; ev_put(i, EV_DOWN, -1); return 0; } + if (st == S_D || ((st == S_M || st == S_U) && lown[i])) { + if (arg_site >= 2 && arg_site - 2 < ubase && (sname[arg_site - 2] == s_free || sname[arg_site - 2] == s_recycle)) end_why = 1; + else if (arg_site == 1) end_why = 8; + else if (arg_site >= 2) { end_why = 2; end_whom = sname[arg_site - 2]; } + end_owner(i); luse(i); xgive = 1; ev_put(i, EV_DOWN, -1); return 0; + } if (st == S_M) cerrn(i, "is m; write d*x to give it away"); else if (st == S_U) cerrn(i, "is u; write d*x to give it away instead of returning it"); else if (st == S_CHILD) cerrn(i, "belongs to a container and can't be given away alone"); @@ -1437,7 +1450,7 @@ int reassign_free(int i, int rc, int bor) { if (lleaf[i] && !dry && lookup(s_recycle_leaf) >= 0) { lit(lleaf[i]); lit(szclass(lnsz[i])); callname(s_recycle_leaf); } else callname(s_recycle); op(O_DROP); - end_owner(i); + end_why = 7; end_owner(i); if (local_dropset) local_dropset[i] = 0; lnsz[i] = 0; lleaf[i] = 0; xty = t; xaf = af; xstr = st; xfloat = fl; xbor = bor; @@ -1491,7 +1504,7 @@ int assigncheck(int k, int i, int rc) { lstate[i] = S_M; lused[i] = 0; lown[i] = 1; lnsz[i] = lnsz[j]; lleaf[i] = lleaf[j]; local_ended[i] = 0; local_end_info[i] = 0; - end_owner(j); luse(j); ev_put(j, EV_MOVE, i); + end_why = 3; end_whom = lname[i]; end_owner(j); luse(j); ev_put(j, EV_MOVE, i); if (ltag[i] & 15) lstate[i] = ltag[i] & 15; return C_PLAIN; } @@ -1499,7 +1512,7 @@ int assigncheck(int k, int i, int rc) { lstate[i] = S_M; lused[i] = 0; lown[i] = 1; - end_owner(j); + end_why = 3; end_whom = lname[i]; end_owner(j); luse(j); ev_put(j, EV_UP, i); if (ltag[i] & 15) lstate[i] = ltag[i] & 15; return C_PLAIN; @@ -1523,7 +1536,7 @@ int assigncheck(int k, int i, int rc) { if (js == S_U) { cerrn(j, "is u; it has to leave through the block above, not into a borrowed object"); } - else { end_owner(j); luse(j); ev_put(j, EV_STORE, i); emitown(i); } // storing it gives it away + else { end_why = 4; end_whom = lname[i]; end_owner(j); luse(j); ev_put(j, EV_STORE, i); emitown(i); } // storing it gives it away } else if (js != st) cerrn(j, "its tag doesn't match its container's (both have to be m, u or d)"); else if (lhome[j] < lhome[r]) cerrn(j, "lives in an outer block than the container it's stored into"); else { lstate[j] = S_CHILD; lowner[j] = i; luse(j); ev_put(j, EV_STORE, i); emitown(i); } @@ -1535,7 +1548,7 @@ int assigncheck(int k, int i, int rc) { if (j >= 0 && k == LV_GLOBAL && xlend == j && lstate[j] == S_M && lown[j]) { xlend = -1; touch(j); lend_add(i, j); return C_PLAIN; } xlend = -1; if (j >= 0) { - if (lstate[j] == S_D || lstate[j] == S_U || (lstate[j] == S_M && lown[j])) { ev_put(j, EV_GLOBAL, -1); end_owner(j); luse(j); } + if (lstate[j] == S_D || lstate[j] == S_U || (lstate[j] == S_M && lown[j])) { ev_put(j, EV_GLOBAL, -1); end_why = 6; end_owner(j); luse(j); } else cerrn(j, "is not an owner, so it can't be stored in a global or in untracked memory (the collector takes it over)"); } return C_PLAIN; @@ -1582,7 +1595,7 @@ int retcheck(int c) { } if (fret) { if (i >= 0) { - if (lstate[i] == S_U) { end_owner(i); luse(i); ev_put(i, EV_RETURN, -1); } + if (lstate[i] == S_U) { end_why = 5; end_owner(i); luse(i); ev_put(i, EV_RETURN, -1); } else cerrn(i, "has to be u to be returned"); } return 0; |
