scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

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:
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); } }