aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/expr.zc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/expr.zc')
-rw-r--r--src/compiler/expr.zc28
1 files changed, 20 insertions, 8 deletions
diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc
index ecbb24c..11ca8e1 100644
--- a/src/compiler/expr.zc
+++ b/src/compiler/expr.zc
@@ -36,7 +36,7 @@ int rval_do(int check) {
af_warning_end();
}
}
- if (lv && check && lvk == LV_ELEM && lvi >= 0) need_inited(lvi);
+ if (lv && check && lvk == LV_ELEM && lvi >= 0) { if (larr[lvi]) need_part(lvi, xpart); else need_inited(lvi); }
if (lv) {
if (ispk(xty)) pkld(xty);
else if (!isagg(xty)) { dbg_addr(); op(O_LD); }
@@ -1212,7 +1212,7 @@ int incdec(int post, int dlt) {
cerrn(lvi, "owns an object and can't be incremented");
}
if (lvk == LV_LOCAL) need_inited(lvi);
- else if (lvk == LV_ELEM && lvi >= 0) need_inited(lvi);
+ else if (lvk == LV_ELEM && lvi >= 0) { if (larr[lvi]) need_part(lvi, xpart); else need_inited(lvi); }
tcneed(isnum(xty) || xty[0] == TY_PTR || xty == tword, "++ and -- need a number or a pointer", xty);
if (lvk == LV_LOCAL) {
ltag[lvi] = ltag[lvi] | LASG;
@@ -1251,7 +1251,9 @@ word field(int c) {
if_value = 0;
int n, fieldoff, fieldpos, sv; word st;
word borrowed = xaf, base_mask = effect_mask(c); af_use(xaf, tpack(), c); xaf = 0; xvk = 0; int i, b = xbor, k = 0, scanned = 0, ms, de, pmatch = 0, base_local = -1;
- if (lv && lvk == LV_LOCAL) base_local = lvi;
+ int chained = 0;
+ if (lv && lvk == LV_LOCAL && larr[lvi]) base_local = lvi;
+ else if (lv && lvk == LV_ELEM && lvi >= 0 && larr[lvi]) { base_local = lvi; chained = 1; }
de = toff + toklen;
next();
// is the place asked about on this member name (or just after the dot, with none typed)
@@ -1296,6 +1298,7 @@ word field(int c) {
else if (st == tword || isnum(st)) { if (fieldscan(n) == 0) ms = methscan(n); }
if (ms == 0 - 2) { serrn(n, "is a method of more than one struct"); ms = 0 - 1; }
if (ms >= 0) {
+ if (base_local >= 0) mark_inited(base_local); // the method gets its address and may fill it
return methcall(ms, st, borrowed, b, base_mask);
}
}
@@ -1350,8 +1353,8 @@ word field(int c) {
effect_value = base_mask;
xprojection = af_project(borrowed, k, tsz(xty), tpack(), 0);
lv = 1; xzero = 0;
- if (b >= 0) { lvk = LV_ELEM; lvi = b; }
- else if (base_local >= 0) { lvk = LV_ELEM; lvi = base_local; }
+ if (base_local >= 0) { lvk = LV_ELEM; lvi = base_local; if (!chained) { xpart = i; xparts = st[3]; } }
+ else if (b >= 0) { lvk = LV_ELEM; lvi = b; }
else lvk = LV_OTHER;
return C_PLAIN;
}
@@ -1467,6 +1470,9 @@ int postfix_tail(int c) {
if (o3on && lv && lvk == LV_LOCAL && o3cache[lvi]) ci = o3cache[lvi];
ub = !fbnd || o3on || (lv && lvk == LV_LOCAL && (ltag[lvi] & 16)); // unbounded, or o3 code
bl = -1; if (lv && lvk == LV_LOCAL) bl = lvi;
+ int abase = -1, achain = 0; ic = 0;
+ if (lv && lvk == LV_LOCAL && larr[lvi]) abase = lvi;
+ else if (lv && lvk == LV_ELEM && lvi >= 0 && larr[lvi]) { abase = lvi; achain = 1; }
next();
rval_do(0); // indexing forms an element address; reading the element checks later
if (was) {
@@ -1615,8 +1621,11 @@ int postfix_tail(int c) {
lv = 1; xty = et; xzero = 0; xconst = 0; xvk = 0; xlenloc = -1; xstamp = 0;
if (isref(xty)) { if (b >= 0) xbor = lroot(b); }
else xbor = -1;
- if (b >= 0) { lvk = LV_ELEM; lvi = b; }
- else if (bl >= 0) { lvk = LV_ELEM; lvi = bl; }
+ if (abase >= 0) {
+ lvk = LV_ELEM; lvi = abase;
+ if (!achain) { xpart = -1; xparts = n; if (ic) { if (offset >= 0 && (n < 0 || offset < n)) xpart = offset; else xpart = 99; } }
+ }
+ else if (b >= 0) { lvk = LV_ELEM; lvi = b; }
else lvk = LV_OTHER;
c = C_PLAIN;
xfloat = 0; if (isfl(xty)) xfloat = 1; xstr = 0;
@@ -1739,6 +1748,7 @@ int unary() {
if (lv && ispk(xty)) serr("an element of a sized-integer array has no address; it is a byte inside a word");
if (lv && lvk == LV_LOCAL && (ltag[lvi] & 16)) serr("an o3 variable has no address");
if (lv && lvk == LV_LOCAL) { ltag[lvi] = ltag[lvi] | LREAD | LASG; mark_inited(lvi); }
+ else if (lv && lvk == LV_ELEM && lvi >= 0 && larr[lvi]) mark_inited(lvi); // the pointer reaches every element
if (c >= C_VAR) touch(c - C_VAR);
if (lvk == LV_ELEM && lvi >= 0) xbor = lroot(lvi);
lv = 0; lvk = LV_NONE; xzero = 0; xfloat = 0; xstr = 0;
@@ -1960,6 +1970,7 @@ int expr() {
if (tv == s_eq) {
if (!lv) die("this can't be assigned to");
k = lvk; i = lvi; lt = xty; require_mutable(lt);
+ int wpart = xpart, wparts = xparts;
if (isagg(lt)) serr("a whole struct or array can't be assigned; assign its fields");
next();
a = o3on && k == LV_LOCAL && (ltag[i] & 16) && !larr[i];
@@ -1989,6 +2000,7 @@ int expr() {
if (o3on && k != LV_ELEM && hasptr(lt)) { lit(lt); callname(s_fatten); } // o3 data going somewhere normal code can see
storekeep(lt);
}
+ if (k == LV_ELEM && i >= 0 && larr[i]) mark_part(i, wpart, wparts);
lv = 0; lvk = LV_NONE; xty = lt; xzero = 0;
return assigncheck(k, i, rc);
}
@@ -1999,7 +2011,7 @@ int expr() {
cerrn(lvi, "owns an object; compound assignment would lose it");
}
if (lvk == LV_LOCAL) need_inited(lvi);
- else if (lvk == LV_ELEM && lvi >= 0) need_inited(lvi);
+ else if (lvk == LV_ELEM && lvi >= 0) { if (larr[lvi]) need_part(lvi, xpart); else need_inited(lvi); }
lt = xty; require_mutable(lt);
fk = -1; lf = xfloat;
if (lvk == LV_LOCAL) fk = lvi;