aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/expr.zc
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-15 09:56:19 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-15 09:56:19 +0330
commit6bbac2edf7c50dac4d755a364b6dfd16471284d7 (patch)
treee83b493f55ed07287cd2ab4e3a940c04871d9a14 /src/compiler/expr.zc
parentanalyzer: use-after-end messages name the borrower, the owner and how the own... (diff)
analyzer: check borrow returns of forward-called functions at the unit's end; borrows clause for prototypes, definitions, externs and function types, checked against the body
Diffstat (limited to 'src/compiler/expr.zc')
-rw-r--r--src/compiler/expr.zc18
1 files changed, 12 insertions, 6 deletions
diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc
index d9c91d6..a6cc55c 100644
--- a/src/compiler/expr.zc
+++ b/src/compiler/expr.zc
@@ -63,7 +63,7 @@ int stmtonly() {
// fat asks for every pointer argument to be fattened first, for o3 code
// calling code that is not o3.)
int args(int tags, word ft, int bs, int fat) {
- int np = 0, c, pt, t, cs = ifcall, freeing = 0, harmless = 0; word first = 0; int origin = -1, anytemp = 0, current, tag, place, parameter_base = effect_argument_base, owner = -1, current_owner, owner_seen = 0, aliases; word origins = 0, current_mask, owner_fact = 0;
+ int np = 0, c, pt, t, cs = ifcall, freeing = 0, harmless = 0; word first = 0; int origin = -1, anytemp = 0, current, tag, place, parameter_base = effect_argument_base, owner = -1, current_owner, owner_seen = 0, aliases; word origins = 0, current_mask, owner_fact = 0; int owner_mask = 0, borrowed = callee_borrows(cs, ft);
if (cs >= 0 && cs < ubase) {
freeing = sname[cs] == s_free || sname[cs] == s_recycle;
harmless = sname[cs] == s_put_s || rt.eq_w(sname[cs], "rt.put_n") || rt.eq_w(sname[cs], "rt.put_c") || rt.eq_w(sname[cs], "len") || rt.eq_w(sname[cs], "cap");
@@ -88,9 +88,11 @@ int args(int tags, word ft, int bs, int fat) {
if (c >= C_VAR && tracked(c - C_VAR)) current_owner = lroot(c - C_VAR);
if (tag <= 1 && current_owner >= 0 && tracked(current_owner)) effect_require_mode(cs, np + parameter_base, place, 1);
aliases = effect_get(cs, np + parameter_base);
+ if (borrowed) { aliases = 0; if (np + parameter_base < 12 && ((borrowed >> (np + parameter_base)) & 1)) aliases = EF_ALIAS; }
if (aliases & (EF_ALIAS | EF_IDENTITY | EF_UNKNOWN)) {
- if (!owner_seen) { owner = current_owner; owner_fact = xaf; owner_seen = 1; }
+ if (!owner_seen) { owner = current_owner; owner_fact = xaf; owner_seen = 1; owner_mask = 0; }
else if (owner != current_owner) { owner = -1; owner_fact = 0; }
+ if (owner >= 0 && owner == current_owner && np + parameter_base < 24) owner_mask = owner_mask | (1 << (np + parameter_base));
}
if (fchk && c == C_FRESH && tag != 2) {
if (!(cs < 0 && tag == 1)) effect_require(cs, np + parameter_base, place); emit_borrow_hold(); c = C_PLAIN; anytemp = 1;
@@ -127,7 +129,7 @@ int args(int tags, word ft, int bs, int fat) {
}
}
expect(s_rp);
- argfact = first; argorigin = origin; argorigin_mask = origins; argtemporary = anytemp; argowner = owner; argowner_fact = owner_fact; xaf = 0; vf_effect();
+ argfact = first; argorigin = origin; argorigin_mask = origins; argtemporary = anytemp; argowner = owner; argowner_mask = owner_mask; argowner_fact = owner_fact; xaf = 0; vf_effect();
return np;
}
// memdebug records the source line on the next new, via the runtime global
@@ -487,13 +489,16 @@ int call(int s) {
xlenloc = -1; xstamp = 0;
if (o3on && (sflag[s] & F_O3) && ft && hasptr(xty)) xstamp = 1;
borrow_depth--; effect_value = 0;
- if (!ret && (isptr(xty) || xty == tword)) {
+ if (!ret && (isptr(xty) || xty == tword || callee_borrows(original, ft))) {
effect_value = origins;
- if (owner >= 0 && (isptr(xty) || (effect_get(original, 0) & EF_IDENTITY))) xbor = owner;
+ if (owner >= 0 && (isptr(xty) || (effect_get(original, 0) & EF_IDENTITY) || callee_borrows(original, ft))) xbor = owner;
if (owner_fact && (effect_get(original, 0) & EF_IDENTITY)) xaf = owner_fact;
if (origin >= 0 && owner < 0) { int oi = lbase; while (oi < nloc) { if (lrskind[oi] == RS_PARAM && oi - lbase == origin) { xbor = oi; break; } oi++; } }
if (temporary) { int ai = 0, aliases = 0; while (ai < np) { aliases = aliases | effect_get(original, ai); ai++; } if (aliases & (EF_ALIAS | EF_UNKNOWN)) xaf = af_new(-1, 5, cp); }
}
+ // a result from a function whose body comes later is checked once the body is read
+ xshadow = 0;
+ if (!ret && xbor < 0 && owner >= 0 && original >= ubase && !(sflag[original] & (F_DEF | F_EXT)) && tracked(owner) && (isptr(xty) || xty == tword)) xshadow = shadow_new(original, argowner_mask, owner);
if_value = 0;
if (ifs && !dry) {
word result_node = if_get(original);
@@ -1009,6 +1014,7 @@ int primary() {
if (i >= 0) {
if (if_local) if_value = if_local[i];
lreadpos[i] = tpack();
+ if (local_shadow && local_shadow[i]) shadow_use(i);
luse(i); effect_note_mask(effect_mask(C_VAR + i), EF_READ);
rs_note(lrskind[i], lrsoff[i]); os_at(toff, i);
xaf = lafact[i]; af_record(toff, xaf);
@@ -1588,7 +1594,7 @@ int postfix_tail(int c) {
xty = tword;
if (ft) xty = subst(ft[4], bs);
if (ft && (ft[5] & 1)) c = C_FRESH;
- else if (isptr(xty) || xty == tword) { effect_value = call_origins; if (isptr(xty)) xbor = call_owner; if (temporary) xaf = af_new(-1, 5, place); }
+ else if (isptr(xty) || xty == tword) { effect_value = call_origins; if (isptr(xty) || (ft && sig_borrows(ft[5]))) xbor = call_owner; if (temporary) xaf = af_new(-1, 5, place); }
xfloat = 0; if (isfl(xty)) xfloat = 1; xstr = 0;
continue;
}