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.zc31
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;