commit 2393bf9e7136b037eb84221724721ff57af8b7d8
parent f05018e00e87781fe6bc927ba1b87ef8c8dc723f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Thu, 6 Jul 2017 20:27:44 +0200
[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.
Diffstat:
M | cc1/init.c | | | 40 | +++++++++++++++++++++++++++++++++++++--- |
1 file changed, 37 insertions(+), 3 deletions(-)
diff --git a/cc1/init.c b/cc1/init.c
@@ -289,6 +289,42 @@ initlist(Type *tp)
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 @@ initializer(Symbol *sym, Type *tp)
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);
}
}