summaryrefslogtreecommitdiff
path: root/sys/src/cmd/cc
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2015-05-26 19:25:06 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2015-05-26 19:25:06 +0200
commitd6a91e0ae47b4e1df9a9783c49666e2a7357e277 (patch)
tree85f75641c07fbbcd156e5660a9506909a175e860 /sys/src/cmd/cc
parentcfafa676408057a7434ec81e5dc15ae0ffba91f2 (diff)
cc: set unspecified elements to zero in local variable initializers
the compiler used to skip zero initialization when initializer list was given not covering unspecified elements. now we zero all non explicitely initialized elements. for example: typedef struct F F; struct F { int a; int b; int c; }; void main(void) { char a[16] = { 1, 2, 3 }; /* a[3..15] initialized to zero */ F f = { .b = 1 }; /* f.a, f.c initialized to zero */ }
Diffstat (limited to 'sys/src/cmd/cc')
-rw-r--r--sys/src/cmd/cc/dcl.c100
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)