code: plan9front

Download patch

ref: 0d87019a9b5479ed2d5ce13b9bfe774c395b9669
parent: c727d2ae8a3a828649e34c71aa45b6665b1a8328
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun May 24 21:57:18 EDT 2015

cc: handle unaligned data in = {0} local initializer

the emited code that initializes local variables did not handle
unaligned data causing stack corruption, affecting code like:

void main(void)
{
	char a[9] = {0};
}

this change will emit code that does byte stores for the unaligned
bytes and also handles small objects (<= 16 bytes) without branches.

--- a/sys/src/cmd/cc/dcl.c
+++ b/sys/src/cmd/cc/dcl.c
@@ -1571,8 +1571,6 @@
 		stkoff = maxround(stkoff, autoffset);
 		symadjust(s, n, v - s->offset);
 	}
-	if(w <= ewidth[TIND])
-		goto no;
 	if(n->op == OAS)
 		diag(Z, "oops in contig");
 /*ZZZ this appears incorrect
@@ -1585,8 +1583,58 @@
 		if(n->left->type)
 		if(n->left->type->width == w)
 			goto no;
-	while(w & (ewidth[TIND]-1))
-		w++;
+
+	for(q=n; q->op != ONAME; q=q->left)
+		;
+
+	v = s->offset;
+
+	/* unaligned front */ 
+	while(w > 0 && (v % ewidth[TIND]) != 0){
+		p = new(ONAME, Z, Z);
+		*p = *q;
+
+		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;
+
+		r = new(OAS, p, m);
+		n = new(OLIST, r, n);
+	}
+
+	/* unaligned (or small) back */
+	while(w > 0 && ((w % ewidth[TIND]) != 0 || w <= 16)){
+		p = new(ONAME, Z, Z);
+		*p = *q;
+
+		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);
+	}
+
+	if(w == 0)
+		goto no;
+
 /*
  * insert the following code, where long becomes vlong if pointers are fat
  *
@@ -1597,15 +1645,12 @@
 	} while(*(long**)&X);
  */
 
-	for(q=n; q->op != ONAME; q=q->left)
-		;
-
 	zt = ewidth[TIND] > ewidth[TLONG]? types[TVLONG]: types[TLONG];
 
 	p = new(ONAME, Z, Z);
 	*p = *q;
 	p->type = typ(TIND, zt);
-	p->xoffset = s->offset;
+	p->xoffset = v;
 
 	r = new(ONAME, Z, Z);
 	*r = *p;