shithub: scc

Download patch

ref: f08eafe178160c3dea617d0dd28c50b04b998c8d
parent: dcbb7393e11a24768718b157462f5ab97ae6ed8e
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Jul 6 16:27:44 EDT 2017

[cc1] Emit constant auto initalizers

In the case of automatic variables of type struct or array
is better to instace a hidden element and memcpy it instead
of copying field by field. In the case of unions the best
option depends of the field initialized.

--- a/cc1/init.c
+++ b/cc1/init.c
@@ -289,6 +289,42 @@
 	return mkcompound(&in);
 }
 
+static void
+autoinit(Symbol *sym, Node *np)
+{
+	Symbol *hidden;
+	Type *tp = sym->type;
+	size_t n; /* FIXME: It should be SIZET */
+
+	if (!(np->flags & NCONST))
+		abort(); /* TODO: Implement not constant initializers */
+
+repeat:
+	switch (tp->op) {
+	case UNION:
+		n = tp->n.elem-1;
+		tp = tp->p.fields[n]->type;
+		np = np->sym->u.init[n];
+		goto repeat;
+	case ARY:
+	case STRUCT:
+		hidden = newsym(NS_IDEN, NULL);
+		hidden->type = sym->type;
+		hidden->flags |= SLOCAL | SHASINIT;
+		emit(ODECL, hidden);
+		emit(OINIT, np);
+		emit(ODECL, sym);
+		emit(OEXPR,
+		     node(OASSIGN, tp, varnode(sym), varnode(hidden)));
+		break;
+	default:
+		emit(ODECL, sym);
+		np = node(OASSIGN, tp, varnode(sym), np);
+		emit(OEXPR, np);
+		break;
+	}
+}
+
 void
 initializer(Symbol *sym, Type *tp)
 {
@@ -318,8 +354,6 @@
 		errorp("'%s' has both '%s' and initializer",
 		       sym->name, (flags&SEXTERN) ? "extern" : "typedef");
 	} else {
-		emit(ODECL, sym);
-		np = node(OASSIGN, tp, varnode(sym), np);
-		emit(OEXPR, np);
+		autoinit(sym, np);
 	}
 }