scc

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

commit e4c1557aa1292034f66d5e0e92061719e8a46c2e
parent e45801db8b29a92723d0f2ea0a1a1a77f3cc7d47
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat,  4 Jan 2025 00:29:20 +0100

cc2: Copy bool() to sethi()

The bool generator is going to be needed for every target, so it is
better to do this operation in sethi() that is shared between all
the backends. Also, moving these functions to sethi() would make
possible to apply liveness analysis to the tree code in the future.

A copy of bool() is still kept in qbe/cgen.c because it is used
when boolean operators are used in expressions that is something
to be expected moved to sethi() too in a near future.

Diffstat:
Msrc/cmd/scc-cc/cc2/cc2.h | 1+
Msrc/cmd/scc-cc/cc2/code.c | 13+++++++++++++
Msrc/cmd/scc-cc/cc2/parser.c | 3+--
Msrc/cmd/scc-cc/cc2/qbe/cgen.c | 65+++++++++++++++++++++++++----------------------------------------
Msrc/cmd/scc-cc/cc2/sethi.c | 59++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 98 insertions(+), 43 deletions(-)

diff --git a/src/cmd/scc-cc/cc2/cc2.h b/src/cmd/scc-cc/cc2/cc2.h @@ -282,6 +282,7 @@ extern void delcode(void); extern Symbol *newlabel(void); extern void pprint(char *s); extern void deftype(Type *); +extern Node *labelstmt(Node *, Symbol *); /* node.c */ extern void newfun(Symbol *, Node *); diff --git a/src/cmd/scc-cc/cc2/code.c b/src/cmd/scc-cc/cc2/code.c @@ -126,6 +126,19 @@ newlabel(void) } Node * +labelstmt(Node *np, Symbol *sym) +{ + if(!sym) + sym = newlabel(); + if (!np) + np = node(ONOP); + np->label = sym; + sym->u.stmt = np; + + return np; +} + +Node * label2node(Node *np, Symbol *sym) { if(!sym) diff --git a/src/cmd/scc-cc/cc2/parser.c b/src/cmd/scc-cc/cc2/parser.c @@ -683,8 +683,7 @@ labeldcl(void) np->op = ONOP; sym = np->u.sym; sym->kind = SLABEL; - sym->u.stmt = np; - np->label = sym; + labelstmt(np, sym); addstmt(np); } diff --git a/src/cmd/scc-cc/cc2/qbe/cgen.c b/src/cmd/scc-cc/cc2/qbe/cgen.c @@ -139,6 +139,7 @@ static unsigned char i2f_conv[4][4][2] = { Node * tsethi(Node *np) { + int op; Node *l, *r; l = np->left; @@ -159,6 +160,21 @@ tsethi(Node *np) np->op = OBXOR; r = constnode(NULL, ~(TUINT) 0, &np->type); goto binary; + case OEFUN: + /* + * In QBE we need at the end of a basic block + * a jump, so we have to ensure that the last + * statement of the function is a ret, a jmp + * or a branch. In the same way, QBE does + * not accept labels at the end of a function + * (ONOP is used for labels) so we have to add + * a ret there, and in the case of branches + * we need a label for the next statement + */ + op = np->prev->op; + if (op == ONOP || op == OBRANCH || (op != ORET && op != OJMP)) + addstmt(node(ORET)); + break; default: binary: l = sethi(l); @@ -368,7 +384,7 @@ static void bool(Node *np, Symbol *true, Symbol *false) { Node *l = np->left, *r = np->right; - Node ret, ifyes, ifno; + Node ifyes, ifno; Symbol *label; switch (np->op) { @@ -688,7 +704,7 @@ rhs(Node *np) static Node * cgen(Node *np) { - Node aux, *p, *next; + Node true, false, *p, *next; setlabel(np->label); switch (np->op) { @@ -700,14 +716,17 @@ cgen(Node *np) case OEFUN: break; case OJMP: - label2node(&aux, np->u.sym); - code(ASJMP, NULL, &aux, NULL); + label2node(&true, np->u.sym); + code(ASJMP, NULL, &true, NULL); break; case OBRANCH: next = np->next; if (!next->label) - next->label = newlabel(); - bool(np->left, np->u.sym, next->label); + labelstmt(next, NULL); + + label2node(&true, np->u.sym); + label2node(&false, np->next->label); + code(ASBRANCH, rhs(np->left), &true, &false); break; case ORET: p = (np->left) ? rhs(np->left) : NULL; @@ -720,42 +739,8 @@ cgen(Node *np) return NULL; } -static Node * -norm(Node *np) -{ - int op = np->op; - Node *p, *dst, *next = np->next; - Symbol *sym, *osym; - - switch (op) { - case OEFUN: - /* - * In QBE we need at the end of a basic block - * a jump, so we have to ensure that the last - * statement of the function is a ret, a jmp - * or a branch. In the same way, QBE does - * not accept labels at the end of a function - * (ONOP is used for labels) so we have to add - * a ret there, and in the case of branches - * we need a label for the next statement - */ - op = (np->prev) ? np->prev->op : 0; - if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP)) - addstmt(node(ORET)); - break; - case OBRANCH: - if (!next->label) { - sym = getsym(TMPSYM); - sym->kind = SLABEL; - next->label = sym; - } - } - return np; -} - void genasm(void) { - apply(norm); apply(cgen); } diff --git a/src/cmd/scc-cc/cc2/sethi.c b/src/cmd/scc-cc/cc2/sethi.c @@ -2,10 +2,52 @@ #include "cc2.h" +static Node * +bool(Node *np, Symbol *true, Symbol *false) +{ + Symbol *label; + Node *p, *l = np->left, *r = np->right; + + switch (np->op) { + case ONEG: + l = bool(l, false, true); + break; + case OAND: + label = newlabel(); + l = bool(l, label, false); + addstmt(labelstmt(NULL, label)); + r = bool(r, true, false); + break; + case OOR: + label = newlabel(); + l = bool(l, true, label); + addstmt(labelstmt(NULL, label)); + r = bool(r, true, false); + break; + default: + p = node(OBRANCH); + p->left = sethi(np); + p->u.sym = true; + true->refcnt++; + addstmt(p); + + p = node(OJMP); + p->u.sym = false; + false->refcnt++; + addstmt(p); + return NULL; + } + + np->left = l; + np->right = r; + return np; +} + Node * sethi(Node *np) { - Node *l, *r; + int op; + Node *next, *l, *r; if (!np) return np; @@ -17,8 +59,23 @@ sethi(Node *np) case OBSWITCH: np = swtch(np); break; + case OBRANCH: + next = np->next; + if (!next->label) + labelstmt(next, NULL); + + op = np->left->op; + if (op != ONEG && op != OOR && op != OAND) { + sethi(np->left); + return np; + } + + bool(np->left, np->u.sym, next->label); + np->u.sym->refcnt--; + return NULL; default: np = tsethi(np); + break; } l = np->left;