scc

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

commit c5e7306640964bd19c1a83adc33d2ea7856fc910
parent a2411fb7e6bab7a76d3b0fe5fd74433f976e6f8d
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 23 Jun 2016 15:27:57 +0200

[cc2-qbe] Begin the rewrite of cgen()

This function was known to be wrong, because we do not
control when we are generating code for a lhs or for a rhs.
This commits cleans the full cgen.c file, but it copies it
to cgen.c.old

Diffstat:
Mcc2/arch/qbe/cgen.c | 499++-----------------------------------------------------------------------------
Ccc2/arch/qbe/cgen.c -> cc2/arch/qbe/cgen.c.old | 0
2 files changed, 7 insertions(+), 492 deletions(-)

diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c @@ -6,509 +6,24 @@ #include "../../cc2.h" #include "../../../inc/sizes.h" -enum lflags { - FORCE = 1 << 0, - LOADL = 1 << 1, - LOADR = 1 << 2 -}; - -enum sflags { - ISTMP = 1, - ISCONS = 2 -}; - -static char opasmw[] = { - [OADD] = ASADDW, - [OSUB] = ASSUBW, - [OMUL] = ASMULW, - [OMOD] = ASMODW, - [ODIV] = ASDIVW, - [OSHL] = ASSHLW, - [OSHR] = ASSHRW, - [OLT] = ASLTW, - [OGT] = ASGTW, - [OLE] = ASLEW, - [OGE] = ASGEW, - [OEQ] = ASEQW, - [ONE] = ASNEW, - [OBAND] = ASBANDW, - [OBOR] = ASBORW, - [OBXOR] = ASBXORW, - [OCPL] = ASCPLW -}; - -static char opasml[] = { - [OADD] = ASADDL, - [OSUB] = ASSUBL, - [OMUL] = ASMULL, - [OMOD] = ASMODL, - [ODIV] = ASDIVL, - [OSHL] = ASSHLL, - [OSHR] = ASSHRL, - [OLT] = ASLTL, - [OGT] = ASGTL, - [OLE] = ASLEL, - [OGE] = ASGEL, - [OEQ] = ASEQL, - [ONE] = ASNEL, - [OBAND] = ASBANDL, - [OBOR] = ASBORL, - [OBXOR] = ASBXORL, - [OCPL] = ASCPLL -}; - -static char opasms[] = { - [OADD] = ASADDS, - [OSUB] = ASSUBS, - [OMUL] = ASMULS, - [OMOD] = ASMODS, - [ODIV] = ASDIVS, - [OSHL] = ASSHLS, - [OSHR] = ASSHRS, - [OLT] = ASLTS, - [OGT] = ASGTS, - [OLE] = ASLES, - [OGE] = ASGES, - [OEQ] = ASEQS, - [ONE] = ASNES, - [OBAND] = ASBANDS, - [OBOR] = ASBORS, - [OBXOR] = ASBXORS, - [OCPL] = ASCPLS -}; - -static char opasmd[] = { - [OADD] = ASADDD, - [OSUB] = ASSUBD, - [OMUL] = ASMULD, - [OMOD] = ASMODD, - [ODIV] = ASDIVD, - [OSHL] = ASSHLD, - [OSHR] = ASSHRD, - [OLT] = ASLTD, - [OGT] = ASGTD, - [OLE] = ASLED, - [OGE] = ASGED, - [OEQ] = ASEQD, - [ONE] = ASNED, - [OBAND] = ASBANDD, - [OBOR] = ASBORD, - [OBXOR] = ASBXORD, - [OCPL] = ASCPLD -}; - -static Node * -tmpnode(Node *np) +Node +rhs(Node *np) { - Symbol *sym; - - sym = getsym(TMPSYM); - sym->type = np->type; - sym->kind = STMP; - np->u.sym = sym; - np->op = OTMP; - np->flags |= ISTMP; - 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, int flags) +Node +lhs(Node *np) { - int op; - Type *tp; - Node *child; - - child = (flags & LOADL) ? np->left : np->right; - if (!child) - return NULL; - tp = &child->type; - - if ((flags & FORCE) || !(child->flags & (ISTMP|ISCONS))) { - Node *new = tmpnode(newnode(OTMP)); - 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; - } - - return (flags & LOADL) ? (np->left = child) : (np->right = child); } -static Node * -cast(Node *nd) +Node +expr(Node *np) { - Type *ts, *td; - Node *tmp, *ns; - int op, disint, sisint; - extern Type uint32type, int32type; - - ns = load(nd, LOADL); - td = &nd->type; - ts = &ns->type; - disint = (td->flags & INTF) != 0; - sisint = (ts->flags & INTF) != 0; - - if (disint && sisint) { - if (td->size <= ts->size) - return nd; - assert(td->size == 4 || td->size == 8); - switch (ts->size) { - case 1: - op = (td->size == 4) ? ASEXTBW : ASEXTBL; - break; - case 2: - op = (td->size == 4) ? ASEXTHW : ASEXTHL; - break; - case 4: - op = ASEXTWL; - break; - default: - abort(); - } - /* - * unsigned version of operations are always +1 the - * signed version - */ - op += (td->flags & SIGNF) == 0; - } else if (disint) { - /* conversion from float to int */ - switch (ts->size) { - case 4: - op = (td->size == 8) ? ASSTOL : ASSTOW; - break; - case 8: - op = (td->size == 8) ? ASDTOL : ASDTOW; - break; - default: - abort(); - } - /* TODO: Add signess */ - } else if (sisint) { - /* conversion from int to float */ - switch (ts->size) { - case 1: - case 2: - tmp = tmpnode(newnode(ONOP)); - tmp->type = (ts->flags&SIGNF) ? int32type : uint32type; - tmp->left = ns; - nd->left = ns = cast(tmp); - case 4: - op = (td->size == 8) ? ASSWTOD : ASSWTOS; - break; - case 8: - op = (td->size == 8) ? ASSLTOD : ASSLTOS; - break; - default: - abort(); - } - /* TODO: Add signess */ - } else { - /* conversion from float to float */ - op = (td->size == 4) ? ASEXTS : ASTRUNCD; - } - code(op, tmpnode(nd), ns, NULL); - return nd; } -static Node * -call(Node *np) -{ - int n, op; - Type *tp = &np->type; - Node **q, *tmp, *p, *pars[NR_FUNPARAM]; - - for (n = 0, p = np->right; p; p = p->right) { - cgen(p->left); - pars[n++] = load(p, LOADL); - } - - switch (tp->size) { - case 0: - np->left = tmpnode(newnode(OTMP)); - op = ASCALLW; - break; - case 1: - op = ASCALLB; - break; - case 2: - op = ASCALLH; - break; - case 4: - op = (tp->flags & INTF) ? ASCALLW : ASCALLS; - break; - case 8: - op = (tp->flags & INTF) ? ASCALLL : ASCALLD; - break; - default: - abort(); - } - code(op, tmpnode(np), np->left, NULL); - - for (q = pars; q < &pars[n]; ++q) { - op = (q == &pars[n-1]) ? ASPARE : ASPAR; - p = newnode(OTMP); - p->type = (*q)->type; - code(op, NULL, *q, tmpnode(p)); - } - code(ASCALL, NULL, NULL, NULL); - - return np; -} - -static Node * -abbrev(Node *np) -{ - Node *tmp; - - if (np->u.subop == 0) - return np->right; - tmp = newnode(np->u.subop); - tmp->type = np->type; - tmp->right = np->right; - tmp->left = np->left; - return np->right = cgen(tmp); -} - -static Node * -assign(Node *to, Node *from) -{ - Type *tp = &to->type; - int op; - - switch (tp->size) { - case 1: - op = ASSTB; - break; - case 2: - op = ASSTH; - break; - case 4: - op = (tp->flags & INTF) ? ASSTW : ASSTS; - break; - case 8: - op = (tp->flags & INTF) ? ASSTL : ASSTD; - break; - default: - abort(); - } - code(op, to, from, NULL); - return from; -} - -static Node * -ternary(Node *np) -{ - Symbol *yes, *no, *phi; - Node *ifyes, *ifno, *phinode, *colon; - - tmpnode(np); - phi = newlabel(); - yes = newlabel(); - no = newlabel(); - - ifyes = label2node(yes); - ifno = label2node(no); - phinode = label2node(phi); - - colon = np->right; - cgen(np->left); - code(ASBRANCH, load(np, LOADL), ifyes, ifno); - - setlabel(yes); - cgen(colon->left); - assign(np, load(colon, LOADL)); - code(ASJMP, NULL, phinode, NULL); - - setlabel(no); - cgen(colon->right); - assign(np, load(colon, LOADR)); - setlabel(phi); - - deltree(ifyes); - deltree(ifno); - deltree(phinode); - - return np; -} - -static Node * -function(void) -{ - Symbol *p; - - /* allocate stack space for parameters */ - for (p = locals; p && (p->type.flags & PARF) != 0; p = p->next) - code(ASALLOC, label2node(p), NULL, NULL); - - /* allocate stack space for local variables) */ - for ( ; p && p->id != TMPSYM; p = p->next) { - if (p->kind != SAUTO) - continue; - code(ASALLOC, label2node(p), NULL, NULL); - } - /* store formal parameters in parameters */ - for (p = locals; p; p = p->next) { - if ((p->type.flags & PARF) == 0) - break; - code(ASFORM, label2node(p), NULL, NULL); - } - return NULL; -} - -/* TODO: Fix "memory leaks" */ Node * cgen(Node *np) { - Node *ifyes, *ifno, *next; - Symbol *sym; - Type *tp; - int op, off; - char *tbl; - - if (!np) - return NULL; - - setlabel(np->label); - if (np->op != OCALL && np->op != OASK) { - np->left = cgen(np->left); - np->right = cgen(np->right); - } - tp = &np->type; - - switch (np->op) { - case OSTRING: - abort(); - case OBFUN: - return function(); - case OEFUN: - return NULL; - case OCONST: - case OLABEL: - np->flags |= ISCONS; - case OMEM: - case OAUTO: - return np; - case OSHR: - case OMOD: - case ODIV: - case OLT: - case OGT: - case OLE: - case OGE: - /* - * unsigned version of operations are always +1 the - * signed version - */ - off = (tp->flags & SIGNF) == 0; - goto binary; - case OADD: - case OSUB: - case OMUL: - case OSHL: - case OBAND: - case OBOR: - case OBXOR: - case OEQ: - case ONE: - off = 0; - binary: - switch (tp->size) { - case 4: - tbl = (tp->flags & INTF) ? opasmw : opasms; - break; - case 8: - tbl = (tp->flags & INTF) ? opasml : opasmd; - break; - default: - abort(); - } - op = tbl[np->op] + off; - 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); - case OADDR: - np->flags |= ISTMP; - np->op = OTMP; - np->u.sym = np->left->u.sym; - return np; - case OPTR: - load(np, LOADL); - load(np, LOADL|FORCE); - return np->left; - case OCPL: - case ONEG: - case OINC: - case ODEC: - abort(); - case OASSIG: - abbrev(np); - return assign(np->left, load(np, LOADR)); - case OCOMMA: - return np->right; - case OCALL: - return call(np); - case OFIELD: - case OAND: - case OOR: - abort(); - case OASK: - return ternary(np); - case OBRANCH: - next = np->next; - load(np, LOADL); - if (!next->label) - next->label = newlabel(); - ifyes = label2node(np->u.sym); - ifno = label2node(next->label); - op = ASBRANCH; - np = np->left; - goto emit_jump; - case OJMP: - ifyes = label2node(np->u.sym); - op = ASJMP; - np = ifno = NULL; - emit_jump: - code(op, np, ifyes, ifno); - deltree(ifyes); - deltree(ifno); - return NULL; - case ORET: - code(ASRET, NULL, load(np, LOADL), NULL); - return NULL; - case OCASE: - case ODEFAULT: - case OESWITCH: - case OBSWITCH: - default: - abort(); - } } /* @@ -521,7 +36,7 @@ cgen(Node *np) * CONST => 11 $value * These values of addressability are not used in the code generation. * They are only used to calculate the Sethi-Ullman numbers. Since - * QBE is AMD64 targered we could do a better job here, and try to + * QBE is AMD64 targered we could do a better job there, and try to * detect some of the complex addressing modes of these processors. */ Node * diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c.old