scc

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

commit 93ad4b36a9dec103d7851d117f4d6e1717a74d46
parent 809d26d10849761118aefc680c9ae7d01b813c4a
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon,  9 May 2016 16:44:44 +0200

[cc2-qbe] Improve load()

This function was a bit low level function, and it was generating
a lot of code in every call. This new version has an interface
that is a bit ugly, but the result code is far better.

Diffstat:
Mcc2/arch/qbe/cgen.c | 91++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 51 insertions(+), 40 deletions(-)

diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c @@ -5,6 +5,12 @@ #include "arch.h" #include "../../cc2.h" +enum lflags { + FORCE = 1 << 0, + LOADL = 1 << 1, + LOADR = 1 << 2 +}; + enum sflags { ISTMP = 1, ISCONS = 2 @@ -104,48 +110,58 @@ tmpnode(Node *np) return np; } +/* + * load() load the address passed in a child of np in a temporary + * if it is not already in a temporay. It can be forced to load + * using the FORCE flag + */ static Node * -load(Node *np) +load(Node *np, int flags) { - Node *new; int op; - Type *tp = &np->type; + Type *tp; + Node *child; - new = tmpnode(newnode()); - new->left = np; - new->type = *tp; + child = (flags & LOADL) ? np->left : np->right; + tp = &child->type; - switch (tp->size) { - case 1: - op = ASLDB; - break; - case 2: - op = ASLDH; - break; - case 4: - op = (tp->flags & INTF) ? ASLDW : ASLDS; - break; - case 8: - op = (tp->flags & INTF) ? ASLDL : ASLDD; - break; - default: - abort(); + if ((flags & FORCE) || !(child->flags & (ISTMP|ISCONS))) { + Node *new = tmpnode(newnode()); + new->type = *tp; + new->left = child; + + switch (tp->size) { + case 1: + op = ASLDB; + break; + case 2: + op = ASLDH; + break; + case 4: + op = (tp->flags & INTF) ? ASLDW : ASLDS; + break; + case 8: + op = (tp->flags & INTF) ? ASLDL : ASLDD; + break; + default: + abort(); + } + code(op, new, child, NULL); + child = new; } - code(op, new, np, NULL); - return new; + return (flags & LOADL) ? (np->left = child) : (np->right = child); } static Node * -cast(Node *nd, Node *ns) +cast(Node *nd) { Type *ts, *td; - Node *tmp; + Node *tmp, *ns; int op, disint, sisint; extern Type uint32type, int32type; - if ((ns->flags & (ISTMP|ISCONS)) == 0) - ns = nd->left = load(ns); + ns = load(nd, LOADL); td = &nd->type; ts = &ns->type; disint = (td->flags & INTF) != 0; @@ -194,7 +210,7 @@ cast(Node *nd, Node *ns) tmp = tmpnode(newnode()); tmp->type = (ts->flags&SIGNF) ? int32type : uint32type; tmp->left = ns; - nd->left = ns = cast(tmp, ns); + nd->left = ns = cast(tmp); case 4: op = (td->size == 8) ? ASSWTOD : ASSWTOS; break; @@ -274,25 +290,23 @@ cgen(Node *np) abort(); } op = tbl[np->op] + off; - if ((l->flags & (ISTMP|ISCONS)) == 0) - l = np->left = load(l); - if ((r->flags & (ISTMP|ISCONS)) == 0) - r = np->right = load(r); - code(op, tmpnode(np), l, r); + code(op, tmpnode(np), load(np, LOADL), load(np, LOADR)); return np; case ONOP: case OBLOOP: case OELOOP: return NULL; case OCAST: - return cast(np, l); + return cast(np); case OADDR: np->flags |= ISTMP; np->op = OTMP; np->u.sym = l->u.sym; return np; case OPTR: - np->left = load(load(l)); + load(np, LOADL); + /* FIXME: The type of the loaded value is not np->type */ + load(np, LOADL|FORCE); return tmpnode(np); case OCPL: case OPAR: @@ -328,9 +342,8 @@ cgen(Node *np) case OOR: abort(); case OBRANCH: - if (l && (l->flags & (ISTMP|ISCONS)) == 0) - l = np->left = load(l); next = np->next; + l = load(np, LOADL); if (next->label) { sym = getsym(TMPSYM); sym->kind = SLABEL; @@ -351,9 +364,7 @@ cgen(Node *np) deltree(ifno); return NULL; case ORET: - if (l && (l->flags & (ISTMP|ISCONS)) == 0) - l = np->left = load(l); - code(ASRET, l, NULL, NULL); + code(ASRET, load(np, LOADL), NULL, NULL); return NULL; case OCASE: case ODEFAULT: