diff options
| -rw-r--r-- | sys/src/cmd/cc/dcl.c | 100 |
1 files changed, 59 insertions, 41 deletions
diff --git a/sys/src/cmd/cc/dcl.c b/sys/src/cmd/cc/dcl.c index 2984feec8..f6c567669 100644 --- a/sys/src/cmd/cc/dcl.c +++ b/sys/src/cmd/cc/dcl.c @@ -1542,6 +1542,48 @@ symadjust(Sym *s, Node *n, long del) } } +static int +covered1(long o, Node *n) +{ + if(n->op == OLIST) + return covered1(o, n->left) || covered1(o, n->right); + if(n->op == OASI) + return covered1(o, n->left); + if(n->op != ONAME) + return 0; + return o >= n->xoffset && o < n->xoffset+n->type->width; +} + +static int +covered(long o, long w, Node *n) +{ + while(w > 0 && covered1(o, n)) { + o++; + w--; + } + return w == 0; +} + +static Node* +initz(Node *q, Type *t, long o, Node *n) +{ + Node *p; + + if(covered(o, t->width, n)) + return n; + + p = new(ONAME, Z, Z); + *p = *q; + p->type = t; + p->xoffset = o; + + q = new(OCONST, Z, Z); + q->vconst = 0; + q->type = t; + + return new(OLIST, new(OASI, p, q), n); +} + Node* contig(Sym *s, Node *n, long v) { @@ -1573,12 +1615,6 @@ contig(Sym *s, Node *n, long v) } if(n->op == OAS) diag(Z, "oops in contig"); -/*ZZZ this appears incorrect -need to check if the list completely covers the data. -if not, bail - */ - if(n->op == OLIST) - goto no; if(n->op == OASI) if(n->left->type) if(n->left->type->width == w) @@ -1589,47 +1625,29 @@ if not, bail v = s->offset; - /* unaligned front */ - while(w > 0 && (v % ewidth[TIND]) != 0){ - p = new(ONAME, Z, Z); - *p = *q; - + /* unaligned front */ + while(w > 0 && (v % ewidth[TIND]) != 0) { + zt = types[TCHAR]; if(w >= ewidth[TLONG] && (v % ewidth[TLONG]) == 0) - p->type = types[TLONG]; - else - p->type = types[TCHAR]; - - p->xoffset = v; - v += p->type->width; - w -= p->type->width; - - m = new(OCONST, Z, Z); - m->vconst = 0; - m->type = p->type; + zt = types[TLONG]; + n = initz(q, zt, v, n); + v += zt->width; + w -= zt->width; + } - r = new(OAS, p, m); - n = new(OLIST, r, n); + /* skip initialized words */ + while(w >= ewidth[TIND] && covered(v, ewidth[TIND], n)) { + v += ewidth[TIND]; + w -= ewidth[TIND]; } /* unaligned (or small) back */ - while(w > 0 && ((w % ewidth[TIND]) != 0 || w <= 16)){ - p = new(ONAME, Z, Z); - *p = *q; - + while(w > 0 && ((w % ewidth[TIND]) != 0 || w <= 16)) { + zt = types[TCHAR]; if(w >= ewidth[TLONG] && (w % ewidth[TLONG]) == 0) - p->type = types[TLONG]; - else - p->type = types[TCHAR]; - - w -= p->type->width; - p->xoffset = v + w; - - m = new(OCONST, Z, Z); - m->vconst = 0; - m->type = p->type; - - r = new(OAS, p, m); - n = new(OLIST, r, n); + zt = types[TLONG]; + w -= zt->width; + n = initz(q, zt, v + w, n); } if(w == 0) |
