scc

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

commit 2f85abe8f705f3fe4b60a58f94b15c8bd0f314d3
parent 2c4ff80a5962f0f37abada47d2b3af2a5e58834f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon,  9 May 2016 11:32:51 +0200

[cc2-qbe] Ensure correctness of basic blocks

We have to take care of how basic blocks are built in QBE,
so we have to ensure that all the basic blocks of the program
are finalized with a jump of any type. We also need a label
in the next statement of a branch, because in branches in QBE
we have to use one label for true and another one for false.

Diffstat:
Mcc2/arch/qbe/optm.c | 31++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/cc2/arch/qbe/optm.c b/cc2/arch/qbe/optm.c @@ -7,12 +7,32 @@ Node * optm(Node *np) { + int op = np->op; Node *p, *dst, *next = np->next; Symbol *sym, *osym; - switch (np->op) { + if (!next) { + /* + * 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 + */ + if (op == ONOP || op == OBRANCH || (op != ORET && op != OJMP)) { + p = newnode(); + p->op = ORET; + addstmt(p, KEEPCUR); + } + next = np->next; + } + + switch (op) { case ONOP: - if (next && next->op == ONOP) { + if (next->op == ONOP) { sym = np->u.sym; osym = next->u.sym; osym->id = sym->id; @@ -21,8 +41,13 @@ optm(Node *np) return NULL; } break; - case OJMP: case OBRANCH: + if (!next->label) { + sym = getsym(TMPSYM); + sym->kind = SLABEL; + next->label = sym; + } + case OJMP: for (;;) { dst = np->u.sym->u.stmt; if (dst->op != OJMP)