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