scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 0d701eb4c740238b1b6ac629f4a57004a251e3ab
parent 48b664b106b3aadb1b8b2db95bfb1da0fe7daa0b
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 11 Jan 2023 13:09:00 +0100

cc1: Collapse field operations combined with &

Using the operator field (.) in the context of an address (&)
operator does not imply to actually use the value in the
struct because it basicaly only implies to add an offset to
te base address of the struct.

Diffstat:
Msrc/cmd/cc/cc1/cc1.h | 1+
Msrc/cmd/cc/cc1/code.c | 15+++++++++++++++
Msrc/cmd/cc/cc1/fold.c | 29++++++++++++++++++++++++++++-
3 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/src/cmd/cc/cc1/cc1.h b/src/cmd/cc/cc1/cc1.h @@ -482,6 +482,7 @@ extern Node *node(int op, Type *tp, Node *left, Node *rigth); extern Node *varnode(Symbol *sym); extern Node *constnode(Symbol *sym); extern Node *sizeofnode(Type *tp); +extern Node *offsetnode(Symbol *, Type *); extern void freetree(Node *np); extern void icode(void); #define BTYPE(np) ((np)->type->op) diff --git a/src/cmd/cc/cc1/code.c b/src/cmd/cc/cc1/code.c @@ -1,3 +1,4 @@ +#include <assert.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> @@ -580,3 +581,17 @@ sizeofnode(Type *tp) DBG("EXPR sizeof %llu", sym->u.u); return constnode(sym); } + +Node * +offsetnode(Symbol *field, Type *tp) +{ + Symbol *sym; + + assert(field->flags & SFIELD); + sym = newsym(NS_IDEN, NULL); + sym->type = tp; + sym->flags |= SCONSTANT; + sym->u.u = field->u.u; + + return constnode(sym); +} diff --git a/src/cmd/cc/cc1/fold.c b/src/cmd/cc/cc1/fold.c @@ -372,7 +372,7 @@ static Node * foldunary(Node *np) { Node *l = np->left; - Node *aux; + Node *aux, *aux2;; int op = l->op; switch (np->op) { @@ -397,6 +397,33 @@ foldunary(Node *np) return np; break; case OADDR: + /* &(*s).f -> s + offsetof(typeof(*s), f) */ + if (op == OFIELD && l->left->op == OPTR) { + DBG("FOLD collapse '&(*s).f' %d", np->op); + aux = offsetnode(l->right->sym, np->type); + aux = node(OADD, np->type, l->left->left, aux); + + if (aux->left->flags & NCONST) + aux->flags |= NCONST; + l->left->left = NULL; + freetree(np); + return aux; + } + + /* &s.f -> &s + offsetof(typeof(s), f) */ + if (op == OFIELD) { + DBG("FOLD collapse '&s.f' %d", np->op); + aux = offsetnode(l->right->sym, np->type); + aux2 = node(OADDR, np->type, l->left, NULL); + aux = node(OADD, np->type, aux2, aux); + + if (l->flags & NCONST) + aux->flags |= NCONST; + l->left = NULL; + freetree(np); + return aux; + } + if (op != OPTR) return np; break;