#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "ast.h"
#include "ssa.h"
#define NEW(type) ((type *)malloc(sizeof(type)))
#define DBLINK(from, to) ((from)->next = (to))->prev = (from)
static CGraph cfg;
static CBlock_t blks[MAX_BLOCK];
static int bcnt; /* block counter */
static int tcnt; /* temporary counter */
static int gbbase;
CBlock_t cblock_create() {
CBlock_t cblk = NEW(CBlock);
CInst_t dummy = NEW(CInst);
dummy->prev = dummy;
dummy->next = dummy;
cblk->insts = dummy;
cblk->next = NULL;
cblk->id = (bcnt++) + gbbase;
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_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(CType_t type) {
static char buff[MAX_NAMELEN];
sprintf(buff, "t%d", tcnt++);
return cvar_create(strdup(buff), type, NULL);
}
void ctmp_destroy(CVar_t type) {
free(type->name); /* allocated dynamically */
free(type);
}
void cfg_clear() {
int i;
for (i = 0; i < MAX_BLOCK; i++)
if (cfg.head[i])
{
CEdge *p, *np;
for (p = cfg.head[i]; p; p = np)
{
np = p->next;
free(p);
}
cfg.head[i] = NULL;
}
}
void cfg_add_edge(CBlock_t from, CBlock_t to) {
int id = from->id;
CEdge *e = NEW(CEdge);
e->to = to;
e->next = cfg.head[id];
cfg.head[id] = e;
}
void copr_print(COpr_t opr) {
switch (opr->kind)
{
case VAR:
case TMP: fprintf(stderr, "%s", opr->info.var->name);
break;
case IMM: fprintf(stderr, "%d", opr->info.imm);
break;
case IMMS: fprintf(stderr, "\"%s\"", opr->info.str);
break;
}
}
void cinst_print(CInst_t inst) {
switch (inst->op)
{
case MOVE:
copr_print(inst->dest);
fprintf(stderr, " = ");
copr_print(inst->src1);
break;
case BEQZ:
fprintf(stderr, "if not (");
copr_print(inst->src1);
fprintf(stderr, ") goto _L");
copr_print(inst->dest);
break;
case BNEZ:
fprintf(stderr, "if (");
copr_print(inst->src1);
fprintf(stderr, ") goto _L");
copr_print(inst->dest);
break;
case GOTO:
fprintf(stderr, "goto _L");
copr_print(inst->dest);
break;
case ARR:
copr_print(inst->dest);
fprintf(stderr, " = ");
copr_print(inst->src1);
fprintf(stderr, "[");
copr_print(inst->src2);
fprintf(stderr, "]");
break;
case NEG:
copr_print(inst->dest);
fprintf(stderr, " = -");
copr_print(inst->src1);
break;
case WARR:
copr_print(inst->dest);
fprintf(stderr, "[");
copr_print(inst->src2);
fprintf(stderr, "] = ");
copr_print(inst->src1);
break;
case PUSH:
fprintf(stderr, "push ");
copr_print(inst->src1);
break;
case CALL:
copr_print(inst->dest);
fprintf(stderr, " = call ");
copr_print(inst->src1);
break;
case RET:
fprintf(stderr, "return ");
copr_print(inst->src1);
break;
default:
{
const char *op;
switch (inst->op)
{
case MUL: op = "*"; break;
case DIV: op = "/"; break;
case MOD: op