diff options
Diffstat (limited to 'src/compiler/expr.zc')
| -rw-r--r-- | src/compiler/expr.zc | 28 |
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; |
