diff options
Diffstat (limited to 'ssa.c')
-rw-r--r-- | ssa.c | 2723 |
1 files changed, 2723 insertions, 0 deletions
@@ -0,0 +1,2723 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include "ast.h" +#include "ssa.h" +#include "mips.h" +#define NEW(type) ((type *)malloc(sizeof(type))) +#define DBLINK(from, to) ((from)->next = (to))->prev = (from) + +static CGraph cfg, dtree; +static CBlock_t blks[MAX_BLOCK]; +static COList_t raw_defs; /* defintion of all vars and tmps */ +static int bcnt; /* block counter */ +static int tcnt; /* temporary counter */ + +static int quiet; +static int gbbase; +static CBlock_t entry; +static COList_t defs; /* all defintions that have actual effects */ + +/* for code generation */ +CFuncIR_t func_ir; + +COpr_t copr_create(void) { + COpr_t opr = NEW(COpr); + opr->type = NULL; + opr->cval = NULL; + opr->range = NULL; + opr->same = opr; + opr->dep = 0; + opr->mod = 0; + opr->par = opr; + return opr; +} + +CInst_t cinst_create(void) { + CInst_t inst = NEW(CInst); + inst->dest = NULL; + inst->src1 = NULL; + inst->src2 = NULL; + inst->sysp = 0; + return inst; +} + +CBlock_t cblock_create(int inc) { + CBlock_t cblk = NEW(CBlock); + CInst_t dum = cinst_create(); + CPhi_t pdum = NEW(CPhi); + dum->prev = dum; + dum->next = dum; + pdum->prev = pdum; + pdum->next = pdum; + cblk->insts = dum; + cblk->phis = pdum; + cblk->next = NULL; + if (inc) + cblk->id = bcnt++; + cblk->ref = 0; + return cblk; +} + +void cblock_append(CBlock_t cblk, CInst_t inst) { + CInst_t head = cblk->insts; + (inst->prev = head->prev)->next = inst; + (inst->next = head)->prev = inst; +} + +void cblock_pushfront(CBlock_t cblk, CInst_t inst) { + CInst_t head = cblk->insts; + (inst->next = head->next)->prev = inst; + (inst->prev = head)->next = inst; +} + +void cblock_pappend(CBlock_t cblk, CPhi_t phi) { + CPhi_t head = cblk->phis; + (phi->prev = head->prev)->next = phi; + (phi->next = head)->prev = phi; +} + +void cblock_popback(CBlock_t cblk) { + CInst_t last = cblk->insts->prev; + last->next->prev = last->prev; + last->prev->next = last->next; +} + +void cblock_popfront(CBlock_t cblk) { + CInst_t first = cblk->insts->next; + first->next->prev = first->prev; + first->prev->next = first->next; +} + +CInst_t cblock_getback(CBlock_t cblk) { + CInst_t res = cblk->insts->prev; + return res != cblk->insts ? res : NULL; +} + +int cblock_isempty(CBlock_t cblk) { + return cblk->insts->prev == cblk->insts; +} + +CVar_t ctmp_create(void) { + static char buff[MAX_NAMELEN]; + sprintf(buff, "t%d", tcnt++); + return cvar_create(strdup(buff), NULL, NULL); +} + +void ctmp_destroy(CVar_t type) { + /* allocated dynamically */ + free(type->name); + free(type); +} + +void cfg_clear(void) { + int i; + for (i = 0; i < MAX_BLOCK; i++) + { + CEdge *p, *np; + for (p = cfg.head[i]; p; p = np) + { + np = p->next; + free(p); + } + cfg.head[i] = NULL; + for (p = cfg.rhead[i]; p; p = np) + { + np = p->next; + free(p); + } + cfg.rhead[i] = NULL; + } +} + +void dtree_clear(void) { + int i; + CEdge *p, *np; + for (i = 0; i < MAX_BLOCK; dtree.head[i++] = NULL) + for (p = dtree.head[i]; p; p = np) + { + np = p->next; + free(p); + } +} + +void cfg_add_edge(CBlock_t from, CBlock_t to) { + int fid = from->id, tid = to->id; +#ifdef CIBIC_DEBUG + fprintf(stderr, "%d -> %d\n", from->id, to->id); +#endif + CEdge *e = NEW(CEdge), *re = NEW(CEdge); + e->to = to; + e->next = cfg.head[fid]; + cfg.head[fid] = e; + + re->to = from; + re->next = cfg.rhead[tid]; + cfg.rhead[tid] = re; +} + +void dtree_add_edge(CBlock_t from, CBlock_t to) { +#ifdef CIBIC_DEBUG + fprintf(stderr, "%d d-> %d\n", from->id, to->id); +#endif + int id = from->id; + CEdge *e = NEW(CEdge); + e->to = to; + e->next = dtree.head[id]; + dtree.head[id] = e; +} + +void copr_print(FILE *f, COpr_t opr) { + switch (opr->kind) + { + case VAR: + fprintf(f, "%s_%d", opr->info.var->name, opr->sub); + break; + case TMP: fprintf(f, "%s", opr->info.var->name); + break; + case IMM: fprintf(f, "%d", opr->info.imm); + break; + case IMMS: fprintf(f, "\"%s\"", opr->info.cstr->str); + break; + case IMMF: fprintf(f, "%s", opr->info.str); + break; + } +} + +void cinst_print(FILE *f, CInst_t inst) { + switch (inst->op) + { + case LOAD: + fprintf(f, "load "); + copr_print(f, inst->dest); + break; + case MOVE: + copr_print(f, inst->dest); + fprintf(f, " = "); + copr_print(f, inst->src1); + break; + case BEQ: + fprintf(f, "if ("); + copr_print(f, inst->src1); + fprintf(f, " == "); + copr_print(f, inst->src2); + fprintf(f, ") goto _L"); + copr_print(f, inst->dest); + break; + case BNE: + fprintf(f, "if ("); + copr_print(f, inst->src1); + fprintf(f, " != "); + copr_print(f, inst->src2); + fprintf(f, ") goto _L"); + copr_print(f, inst->dest); + break; + case GOTO: + fprintf(f, "goto _L"); + copr_print(f, inst->dest); + break; + case ARR: + copr_print(f, inst->dest); + fprintf(f, " = "); + copr_print(f, inst->src1); + fprintf(f, "["); + copr_print(f, inst->src2); + fprintf(f, "]"); + break; + case NEG: + copr_print(f, inst->dest); + fprintf(f, " = -"); + copr_print(f, inst->src1); + break; + case WARR: + copr_print(f, inst->dest); + fprintf(f, "["); + copr_print(f, inst->src2); + fprintf(f, "] = "); + copr_print(f, inst->src1); + break; + case PUSH: + fprintf(f, "push "); + copr_print(f, inst->src1); + break; + case CALL: + copr_print(f, inst->dest); + fprintf(f, " = call "); + copr_print(f, inst->src1); + break; + case RET: + if (inst->src1) + { + fprintf(f, "return "); + copr_print(f, inst->src1); + } + else fprintf(f, "return"); + break; + case ADDR: + copr_print(f, inst->dest); + fprintf(f, " = addr "); + copr_print(f, inst->src1); + break; + default: + { + const char *op; + switch (inst->op) + { + case MUL: op = "*"; break; + case DIV: op = "/"; break; + case MOD: op = "%"; break; + case ADD: op = "+"; break; + case SUB: op = "-"; break; + case SHL: op = "<<"; break; + case SHR: op = ">>"; break; + case AND: op = "&"; break; + case XOR: op = "^"; break; + case OR: op = "|"; break; + case LT: op = "<"; break; + case GT: op = ">"; break; + case LE: op = "<="; break; + case GE: op = ">="; break; + case EQ: op = "=="; break; + case NE: op = "!="; break; + case NOR: op = "nor"; break; + default: ; + } + copr_print(f, inst->dest); + fprintf(f, " = "); + copr_print(f, inst->src1); + fprintf(f, " %s ", op); + copr_print(f, inst->src2); + } + } + fprintf(f, "\n"); +} + +void cphi_print(CPhi_t phi, CBlock_t blk) { + int i; + fprintf(stderr, "%s_%d = phi", phi->dest->info.var->name, + phi->dest->sub); + for (i = 0; i < blk->pred; i++) + fprintf(stderr, " %s_%d", phi->oprs[i]->info.var->name, + phi->oprs[i]->sub); + fprintf(stderr, "\n"); +} + +void cblock_print(CBlock_t blk) { + fprintf(stderr, "_L%d:\n", blk->id + gbbase); + { + CPhi_t p, sp = blk->phis; + for (p = sp->next; p != sp; p = p->next) + { + fprintf(stderr, "\t"); + cphi_print(p, blk); + } + } + { + CInst_t p, sp = blk->insts; + for (p = sp->next; p != sp; p = p->next) + { + fprintf(stderr, "%02d\t", p->id); + cinst_print(stderr, p); + } + } +} +void ssa_func_print(CBlock_t p) { + for (; p; p = p->next) + cblock_print(p); +} +void ssa_func(CType_t); +void ssa_generate(int quiet) { + CTList_t f; + CFuncIR_t cf; + func_ir = NULL; + for (f = funcs; f; f = f->next) + { + cf = NEW(CFuncIR); + ssa_func(cf->func = f->type); + cf->gbbase = gbbase; + cf->defs = defs; + cf->entry = entry; + cf->next = func_ir; + func_ir = cf; + gbbase += bcnt; + bcnt = 0; + } + if (!quiet) + { + for (cf = func_ir; cf; cf = cf->next) + { + fprintf(stderr, "%s:\n", cf->func->name); + ssa_func_print(cf->entry); + } + } +} + +#define POINTER_CONV(inst) \ +do { \ + if (rt->type == CARR) \ + { \ + /* convert to pointer type */ \ + CType_t a; \ + a = ctype_create("", CPTR, p); \ + a->rec.ref = rt->rec.arr.elem; \ + (inst)->op = ADD; \ + (inst)->dest->type = a; \ + } \ + else if (rt->type == CSTRUCT || rt->type == CUNION) \ + (inst)->op = ADD; \ + else (inst)->op = ARR; \ +} while (0) + + +COpr_t ssa_exp_(CNode *p, CBlock_t *, CInst_t, CBlock_t); +COpr_t ssa_postfix(CNode *p, CBlock_t *cur, CInst_t lval, CBlock_t succ) { + CNode *post = p->chd->next; + CType_t rt = p->ext.type; + CInst_t base = cinst_create(); + switch (post->rec.subtype) + { + case POSTFIX_ARR: + { + CInst_t off = cinst_create(); + off->dest = copr_create(); + off->dest->kind = TMP; + off->dest->info.var = ctmp_create(); + off->dest->type = post->chd->ext.type; + off->op = MUL; + off->src1 = ssa_exp_(post->chd, cur, NULL, succ); + off->src2 = copr_create(); + off->src2->kind = IMM; + off->src2->info.imm = calc_size(rt); + cblock_append(*cur, off); + + base->dest = copr_create(); + base->dest->kind = TMP; + base->dest->info.var = ctmp_create(); + base->dest->type = rt; + base->src1 = ssa_exp_(p->chd, cur, NULL, succ); + base->src2 = off->dest; + POINTER_CONV(base); + } + break; + case POSTFIX_DOT: + { + base->dest = copr_create(); + base->dest->kind = TMP; + base->dest->info.var = ctmp_create(); + base->dest->type = rt; + base->src1 = ssa_exp_(p->chd, cur, NULL, succ); + base->src2 = copr_create(); + base->src2->kind = IMM; + base->src2->info.imm = p->ext.offset; + POINTER_CONV(base); + } + break; + case POSTFIX_PTR: + { + base->dest = copr_create(); + base->dest->kind = TMP; + base->dest->info.var = ctmp_create(); + base->dest->type = rt; + base->src1 = ssa_exp_(p->chd, cur, NULL, succ); + base->src2 = copr_create(); + base->src2->kind = IMM; + base->src2->info.imm = p->ext.offset; + POINTER_CONV(base); + } + break; + case POSTFIX_CALL: + { + CNode *arg = post->chd->chd; + CInst h; + CInst_t t = &h, n; + base->op = CALL; + base->src1 = ssa_exp_(p->chd, cur, lval, succ); + base->dest = copr_create(); + base->dest->kind = TMP; + base->dest->info.var = ctmp_create(); + base->dest->type = rt; + for (; arg; arg = arg->next) + { + CInst_t pi = cinst_create(); + pi->op = PUSH; + pi->src1 = ssa_exp_(arg, cur, lval, succ); + t->next = pi; + t = pi; + } + t->next = NULL; + for (t = h.next; t; t = n) + { + n = t->next; + cblock_append(*cur, t); + } + } + break; + default: + { + CInst_t tins = cinst_create(); + ssa_exp_(p->chd, cur, tins, succ); + base->op = post->rec.subtype == OPT_INC ? ADD : SUB; + base->src2 = copr_create(); + base->src2->kind = IMM; + base->src2->info.imm = 1; + base->src1 = ssa_exp_(p->chd, cur, NULL, succ); + if (tins->op == MOVE) + { + base->dest = tins->dest; + cblock_append(succ, base); + free(tins); + } + else + { + CInst_t tins2 = cinst_create(); + base->dest = copr_create(); + base->dest->kind = TMP; + base->dest->info.var = ctmp_create(); + base->dest->type = rt; + tins->src1 = base->dest; + tins2->op = ARR; + tins2->src1 = tins->dest; + tins2->src2 = tins->src2; + tins2->dest = copr_create(); + tins2->dest->kind = TMP; + tins2->dest->info.var = ctmp_create(); + tins2->dest->type = rt; + + cblock_append(succ, base); + cblock_append(succ, tins); + cblock_append(succ, tins2); + } + return base->src1; + } + break; + } + + if (lval) + { + lval->op = WARR; + lval->dest = base->src1; + lval->src2 = base->src2; + lval->wtype = p->ext.type; + free(base); + return lval->dest; + } + cblock_append(*cur, base); + return base->dest; +} + +CInst_t compress_branch(COpr_t r, CBlock_t blk, int rev) { + int flag = -1; + CInst_t b; + if (r->kind == TMP) + { + b = cblock_getback(blk); + if (b) + { + assert(r == b->dest); + if (b->op == EQ) + flag = 0; + else if (b->op == NE) + flag = 1; + } + } + if (flag != -1) + b->op = flag ? BNE : BEQ; + else + { + b = cinst_create(); + b->op = BNE; + b->src1 = r; + b->src2 = copr_create(); + b->src2->kind = IMM; + b->src2->info.imm = 0; + cblock_append(blk, b); + } + b->op ^= rev; + b->dest = copr_create(); + b->dest->kind = IMM; + return b; +} + +static CNode *opt_if = NULL; +static CBlock_t opt_if_loop_exit = NULL; + +CBlock_t ssa_stmt(CNode *, CBlock_t, CBlock_t); +#define IS_PTR(tt) ((tt) == CPTR || (tt) == CARR) +COpr_t ssa_exp(CNode *, CBlock_t *, int); +COpr_t ssa_exp_(CNode *p, CBlock_t *cur, CInst_t lval, CBlock_t succ) {/*{{{*/ + COpr_t res; + CInst_t inst = cinst_create(); + switch (p->type) + { + case NOP: ; break; + case ID: + res = copr_create(); + res->kind = VAR; + res->info.var = p->ext.var; + res->type = p->ext.type; + { + CVar_t var = res->info.var; + CType_t type = var->type; + if (type->type == CPTR && + type->rec.ref->type == CFUNC) + { + char *name = type->rec.ref->name; + if (*name != '\0') + { + res->kind = IMMF; + res->info.str = name; + } + } + } + + if (lval) + { + lval->op = MOVE; + lval->dest = res; + } + break; + case STR: + res = copr_create(); + res->kind = IMMS; + res->info.cstr = (CSList_t)(p->ext.const_val); + break; + default: + if (p->ext.is_const) + { + res = copr_create(); + res->kind = IMM; + res->info.imm = p->ext.const_val; + } + else + { + int op = p->rec.subtype; + int rec = 1, auto_dest = 1; + + if (op == ',') + { + ssa_exp(p->chd, cur, 1); + return ssa_exp_(p->chd->next, cur, NULL, succ); + } + else if (op == '=') + { + inst->src1 = ssa_exp_(p->chd->next, cur, NULL, succ); + ssa_exp_(p->chd, cur, inst, succ); + if (inst->op == MOVE) + { + CInst_t last = cblock_getback(*cur); + if (last && last->dest->kind == TMP + && last->dest == inst->src1) + { + free(last->dest); + last->dest = inst->dest; + free(inst); + return last->dest; + } + else + { + cblock_append(*cur, inst); + return inst->dest; + } + } + else + { + CInst_t tins = cinst_create(); + cblock_append(*cur, inst); + tins->op = ARR; + tins->src1 = inst->dest; /* base */ + tins->src2 = inst->src2; /* displacement */ + tins->dest = copr_create(); + tins->dest->kind = TMP; + tins->dest->info.var = ctmp_create(); + tins->dest->type = p->ext.type; + cblock_append(*cur, tins); + return tins->dest; + } + } + else if (op == '*' && !p->chd->next) + { + if (lval) + { + lval->op = WARR; + lval->dest = ssa_exp_(p->chd, cur, NULL, succ); + lval->src2 = copr_create(); + lval->src2->kind = IMM; + lval->src2->info.imm = 0; + lval->wtype = p->ext.type; + return lval->dest; + } + else + { + CType_t rt = p->ext.type; + inst->src1 = ssa_exp_(p->chd, cur, NULL, succ); + inst->src2 = copr_create(); + inst->src2->kind = IMM; + inst->src2->info.imm = 0; + inst->dest = copr_create(); + inst->dest->kind = TMP; + inst->dest->info.var = ctmp_create(); + inst->dest->type = rt; + POINTER_CONV(inst); + cblock_append(*cur, inst); + return inst->dest; + } + } + else if (op == OPT_AND) + { + CBlock_t else_h = cblock_create(1), else_t = else_h, + one_h = cblock_create(1), one_t = one_h, + zero_h = cblock_create(1), zero_t = zero_h, + next_blk = cblock_create(1), sblk; + COpr_t r0, r1, ri; + CInst_t b, a0, a1; + CPhi_t m = NEW(CPhi); + CNode *t; + if (opt_if) + { + CNode *body1 = opt_if->chd->next, *body2 = body1->next; + one_t = ssa_stmt(body1, one_h, opt_if_loop_exit); + if (body2->type != NOP) + zero_t = ssa_stmt(body2, zero_h, opt_if_loop_exit); + opt_if = NULL; + } + else + { + /* constant opt */ + a0 = cinst_create(); + a0->op = MOVE; + a0->dest = copr_create(); + a0->dest->kind = TMP; + a0->dest->info.var = ctmp_create(); + a0->dest->type = p->ext.type; /* int */ + a0->src1 = copr_create(); + a0->src1->kind = IMM; + a0->src1->info.imm = 0; + cblock_append(zero_h, a0); + + a1 = cinst_create(); + a1->op = MOVE; + a1->dest = copr_create(); + a1->dest->kind = TMP; + a1->dest->info.var = ctmp_create(); + a1->dest->type = p->ext.type; + a1->src1 = copr_create(); + a1->src1->kind = IMM; + a1->src1->info.imm = 1; + cblock_append(one_h, a1); + + m->dest = copr_create(); + m->dest->kind = TMP; + m->dest->info.var = ctmp_create(); + m->dest->type = p->ext.type; + m->oprs = (COpr_t *)malloc(sizeof(COpr_t) * 2); + m->oprs[0] = a0->dest; + m->oprs[1] = a1->dest; + cblock_pappend(next_blk, m); + } + + r1 = ssa_exp_(p->chd->next, &else_t, NULL, succ); + compress_branch(r1, else_t, 1)->dest->info.imm = zero_h->id + gbbase; + zero_h->ref = 1; + + sblk = else_h; + for (t = p->chd; t->rec.subtype == OPT_AND; t = t->chd) + { + CBlock_t c_h = cblock_create(1), c_t = c_h; + ri = ssa_exp_(t->chd->next, &c_t, NULL, succ); + compress_branch(ri, c_t, 1)->dest->info.imm = zero_h->id + gbbase; + cfg_add_edge(c_t, zero_h); /* tail */ + DBLINK(c_t, sblk); + cfg_add_edge(c_t, sblk); /* connect to header */ + sblk = c_h; + } + + r0 = ssa_exp_(t, cur, NULL, succ); + compress_branch(r0, *cur, 1)->dest->info.imm = zero_h->id + gbbase; + cfg_add_edge(*cur, zero_h); + DBLINK(*cur, sblk); + cfg_add_edge(*cur, sblk); + + b = cinst_create(); + b->op = GOTO; + b->dest = copr_create(); + b->dest->kind = IMM; + b->dest->info.imm = next_blk->id + gbbase; + cblock_append(one_t, b); + next_blk->ref = 1; + + DBLINK(else_t, one_h); + DBLINK(one_t, zero_h); + DBLINK(zero_t, next_blk); + + cfg_add_edge(else_t, one_h); + cfg_add_edge(else_t, zero_h); + cfg_add_edge(one_t, next_blk); + cfg_add_edge(zero_t, next_blk); + + *cur = next_blk; + return m->dest; + } + else if (op == OPT_OR) + { + CBlock_t else_h = cblock_create(1), else_t = else_h, + one_h = cblock_create(1), one_t = one_h, + zero_h = cblock_create(1), zero_t = zero_h, + next_blk = cblock_create(1), sblk; + COpr_t r0, r1, ri; + CInst_t b, a0, a1; + CPhi_t m = NEW(CPhi); + CNode *t; + if (opt_if) + { + CNode *body1 = opt_if->chd->next, *body2 = body1->next; + one_t = ssa_stmt(body1, one_h, opt_if_loop_exit); + if (body2->type != NOP) + zero_t = ssa_stmt(body2, zero_h, opt_if_loop_exit); + opt_if = NULL; + } + else + { + /* constant opt */ + a0 = cinst_create(); + a0->op = MOVE; + a0->dest = copr_create(); + a0->dest->kind = TMP; + a0->dest->info.var = ctmp_create(); + a0->dest->type = p->ext.type; /* int */ + a0->src1 = copr_create(); + a0->src1->kind = IMM; + a0->src1->info.imm = 0; + cblock_append(zero_h, a0); + + a1 = cinst_create(); + a1->op = MOVE; + a1->dest = copr_create(); + a1->dest->kind = TMP; + a1->dest->info.var = ctmp_create(); + a1->dest->type = p->ext.type; + a1->src1 = copr_create(); + a1->src1->kind = IMM; + a1->src1->info.imm = 1; + cblock_append(one_h, a1); + + m->dest = copr_create(); + m->dest->kind = TMP; + m->dest->info.var = ctmp_create(); + m->dest->type = p->ext.type; + m->oprs = (COpr_t *)malloc(sizeof(COpr_t) * 2); + m->oprs[0] = a1->dest; + m->oprs[1] = a0->dest; + cblock_pappend(next_blk, m); + } + + r1 = ssa_exp_(p->chd->next, &else_t, NULL, succ); + compress_branch(r1, else_t, 0)->dest->info.imm = one_h->id + gbbase; + one_h->ref = 1; + + sblk = else_h; + for (t = p->chd; t->rec.subtype == OPT_OR; t = t->chd) + { + CBlock_t c_h = cblock_create(1), c_t = c_h; + ri = ssa_exp_(t->chd->next, &c_t, NULL, succ); + compress_branch(ri, c_t, 0)->dest->info.imm = one_h->id + gbbase; + cfg_add_edge(c_t, one_h); /* tail */ + DBLINK(c_t, sblk); + cfg_add_edge(c_t, sblk); /* connect to header */ + sblk = c_h; + } + + r0 = ssa_exp_(t, cur, NULL, succ); + compress_branch(r0, *cur, 0)->dest->info.imm = one_h->id + gbbase; + cfg_add_edge(*cur, one_h); + DBLINK(*cur, sblk); + cfg_add_edge(*cur, sblk); + + b = cinst_create(); + b->op = GOTO; + b->dest = copr_create(); + b->dest->kind = IMM; + b->dest->info.imm = next_blk->id + gbbase; + cblock_append(zero_t, b); + next_blk->ref = 1; + + DBLINK(else_t, zero_h); + DBLINK(zero_t, one_h); + DBLINK(one_t, next_blk); + + cfg_add_edge(else_t, zero_h); + cfg_add_edge(else_t, one_h); + cfg_add_edge(zero_t, next_blk); + cfg_add_edge(one_t, next_blk); + + *cur = next_blk; + return m->dest; + } + else if (op == '+' && IS_PTR(p->ext.type->type)) + { + COpr_t lhs = ssa_exp_(p->chd, cur, lval, succ), + rhs = ssa_exp_(p->chd->next, cur, lval, succ); + CInst_t index = cinst_create(); + CType_t et = p->chd->ext.type; + if (et->type == CPTR) + et = et->rec.ref; + else + et = et->rec.arr.elem; + index->op = MUL; + index->dest = copr_create(); + index->dest->kind = TMP; + index->dest->info.var = ctmp_create(); + index->dest->type = p->chd->next->ext.type; + index->src1 = rhs; + index->src2 = copr_create(); + index->src2->kind = IMM; + index->src2->info.imm = calc_size(et); + + inst->op = ADD; + inst->dest = copr_create(); + inst->dest->kind = TMP; + inst->dest->info.var = ctmp_create(); + inst->dest->type = p->ext.type; + inst->src1 = lhs; + inst->src2 = index->dest; + cblock_append(*cur, index); + cblock_append(*cur, inst); + return inst->dest; + } + else if (op == '-' && IS_PTR(p->chd->ext.type->type)) + { + CType_t nt = p->chd->next->ext.type; + CType_t et = p->chd->ext.type; + COpr_t lhs = ssa_exp_(p->chd, cur, lval, succ), + rhs = ssa_exp_(p->chd->next, cur, lval, succ); + CInst_t diff = cinst_create(); + + if (et->type == CPTR) + et = et->rec.ref; + else + et = et->rec.arr.elem; + + if (IS_PTR(nt->type)) + { + diff->op = SUB; + diff->dest = copr_create(); + diff->dest->kind = TMP; + diff->dest->info.var = ctmp_create(); + diff->dest->type = p->ext.type; + diff->src1 = lhs; + diff->src2 = rhs; + + inst->op = DIV; + inst->dest = copr_create(); + inst->dest->kind = TMP; + inst->dest->info.var = ctmp_create(); + inst->dest->type = p->ext.type; + inst->src1 = diff->dest; + inst->src2 = copr_create(); + inst->src2->kind = IMM; + inst->src2->info.imm = calc_size(et); + } + else + { + diff->op = MUL; + diff->dest = copr_create(); + diff->dest->kind = TMP; + diff->dest->info.var = ctmp_create(); + diff->dest->type = p->chd->next->ext.type; + diff->src1 = rhs; + diff->src2 = copr_create(); + diff->src2->kind = IMM; + diff->src2->info.imm = calc_size(et); + + inst->op = SUB; + inst->dest = copr_create(); + inst->dest->kind = TMP; + inst->dest->info.var = ctmp_create(); + inst->dest->type = p->ext.type; + inst->src1 = lhs; + inst->src2 = diff->dest; + } + cblock_append(*cur, diff); + cblock_append(*cur, inst); + return inst->dest; + } + else if (op == '&' && !p->chd->next) + { + ssa_exp_(p->chd, cur, inst, succ); + if (inst->op == MOVE) + { + inst->op = ADDR; + inst->src1 = inst->dest; + } + else + { + inst->op = ADD; + inst->src1 = inst->dest; + } + inst->dest = copr_create(); + inst->dest->kind = TMP; + inst->dest->info.var = ctmp_create(); + inst->dest->type = p->ext.type; + cblock_append(*cur, inst); + return inst->dest; + } + else + { + int unary = 0; + inst->op = (unsigned)-1; + switch (op) + { + case ASS_MUL: inst->op = MUL; break; + case ASS_DIV: inst->op = DIV; break; + case ASS_MOD: inst->op = MOD; break; |