2016-09-18 21:24:54 +00:00
|
|
|
#include "mcg.h"
|
|
|
|
|
|
|
|
static int next_id = 0;
|
|
|
|
|
|
|
|
struct ir* new_ir0(int opcode, int size)
|
|
|
|
{
|
|
|
|
struct ir* ir = calloc(sizeof(struct ir), 1);
|
|
|
|
ir->id = next_id++;
|
|
|
|
ir->opcode = opcode;
|
|
|
|
ir->size = size;
|
|
|
|
return ir;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ir* new_ir1(int opcode, int size,
|
2016-09-19 21:06:59 +00:00
|
|
|
struct ir* left)
|
2016-09-18 21:24:54 +00:00
|
|
|
{
|
|
|
|
struct ir* ir = new_ir0(opcode, size);
|
2016-09-19 21:06:59 +00:00
|
|
|
ir->left = left;
|
2016-09-18 21:24:54 +00:00
|
|
|
return ir;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ir* new_ir2(int opcode, int size,
|
2016-09-19 21:06:59 +00:00
|
|
|
struct ir* left, struct ir* right)
|
2016-09-18 21:24:54 +00:00
|
|
|
{
|
|
|
|
struct ir* ir = new_ir0(opcode, size);
|
2016-09-19 21:06:59 +00:00
|
|
|
ir->left = left;
|
|
|
|
ir->right = right;
|
2016-09-18 21:24:54 +00:00
|
|
|
return ir;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ir* new_labelir(const char* label)
|
|
|
|
{
|
|
|
|
struct ir* ir = new_ir0(IR_LABEL, EM_pointersize);
|
|
|
|
ir->u.lvalue = label;
|
|
|
|
return ir;
|
|
|
|
}
|
|
|
|
|
2016-09-21 22:15:48 +00:00
|
|
|
struct ir* new_constir(int size, arith value)
|
2016-09-18 21:24:54 +00:00
|
|
|
{
|
2016-09-21 22:15:48 +00:00
|
|
|
struct ir* ir = new_ir0(IR_CONST, size);
|
2016-09-18 21:24:54 +00:00
|
|
|
ir->u.ivalue = value;
|
|
|
|
return ir;
|
|
|
|
}
|
|
|
|
|
2016-09-21 22:15:48 +00:00
|
|
|
struct ir* new_wordir(arith value)
|
2016-09-18 21:24:54 +00:00
|
|
|
{
|
2016-09-21 22:15:48 +00:00
|
|
|
return new_constir(EM_wordsize, value);
|
2016-09-18 21:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ir* new_bbir(struct basicblock* bb)
|
|
|
|
{
|
|
|
|
struct ir* ir = new_ir0(IR_BLOCK, EM_pointersize);
|
|
|
|
ir->u.bvalue = bb;
|
|
|
|
return ir;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ir* new_anyir(int size)
|
|
|
|
{
|
|
|
|
return new_ir0(IR_ANY, size);
|
|
|
|
}
|
|
|
|
|
2016-09-21 22:15:48 +00:00
|
|
|
struct ir* new_localir(int offset)
|
2016-09-18 21:24:54 +00:00
|
|
|
{
|
2016-09-21 22:15:48 +00:00
|
|
|
struct ir* ir = new_ir0(IR_LOCAL, EM_pointersize);
|
|
|
|
ir->u.ivalue = offset;
|
|
|
|
return ir;
|
2016-09-18 21:24:54 +00:00
|
|
|
}
|
|
|
|
|
2016-09-23 21:59:15 +00:00
|
|
|
struct ir* ir_walk(struct ir* ir, ir_walker_t* cb, void* user)
|
2016-09-18 21:24:54 +00:00
|
|
|
{
|
2016-10-01 20:58:29 +00:00
|
|
|
assert(ir->root);
|
2016-09-23 21:59:15 +00:00
|
|
|
if (cb(ir, user))
|
2016-09-22 21:19:29 +00:00
|
|
|
return ir;
|
|
|
|
|
2016-10-01 20:58:29 +00:00
|
|
|
if (ir->left && (ir->left->root == ir->root))
|
2016-09-22 21:19:29 +00:00
|
|
|
{
|
2016-09-23 21:59:15 +00:00
|
|
|
struct ir* irr = ir_walk(ir->left, cb, user);
|
2016-09-22 21:19:29 +00:00
|
|
|
if (irr)
|
|
|
|
return irr;
|
|
|
|
}
|
|
|
|
|
2016-10-01 20:58:29 +00:00
|
|
|
if (ir->right && (ir->right->root == ir->root))
|
2016-09-22 21:19:29 +00:00
|
|
|
{
|
2016-09-23 21:59:15 +00:00
|
|
|
struct ir* irr = ir_walk(ir->right, cb, user);
|
2016-09-22 21:19:29 +00:00
|
|
|
if (irr)
|
|
|
|
return irr;
|
|
|
|
}
|
2016-09-21 22:15:48 +00:00
|
|
|
|
2016-09-22 21:19:29 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-09-23 21:59:15 +00:00
|
|
|
static bool finder_cb(struct ir* ir, void* user)
|
|
|
|
{
|
|
|
|
int opcode = *(int*)user;
|
|
|
|
if (ir->opcode == opcode)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ir* ir_find(struct ir* ir, int opcode)
|
|
|
|
{
|
|
|
|
return ir_walk(ir, finder_cb, &opcode);
|
|
|
|
}
|
|
|
|
|
2016-09-22 21:19:29 +00:00
|
|
|
static void print_expr(char k, const struct ir* ir)
|
|
|
|
{
|
2016-09-26 20:12:46 +00:00
|
|
|
tracef(k, "%s", ir_data[ir->opcode].name);
|
2016-10-22 21:04:13 +00:00
|
|
|
if (ir->type)
|
|
|
|
tracef(k, ".%c", ir->type);
|
|
|
|
else if (ir->size)
|
2016-09-21 22:15:48 +00:00
|
|
|
tracef(k, "%d", ir->size);
|
2016-10-02 15:50:34 +00:00
|
|
|
tracef(k, "(");
|
2016-09-18 21:24:54 +00:00
|
|
|
|
|
|
|
switch (ir->opcode)
|
|
|
|
{
|
2016-09-21 22:15:48 +00:00
|
|
|
case IR_CONST:
|
|
|
|
case IR_LOCAL:
|
|
|
|
tracef(k, "%d", ir->u.ivalue);
|
2016-09-18 21:24:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IR_LABEL:
|
2016-09-21 22:15:48 +00:00
|
|
|
tracef(k, "%s", ir->u.lvalue);
|
2016-09-18 21:24:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IR_BLOCK:
|
2016-09-21 22:15:48 +00:00
|
|
|
tracef(k, "%s", ir->u.bvalue->name);
|
2016-09-18 21:24:54 +00:00
|
|
|
break;
|
|
|
|
|
2016-10-01 20:58:29 +00:00
|
|
|
case IR_PHI:
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; i<ir->u.phivalue.count; i++)
|
|
|
|
{
|
|
|
|
if (i > 0)
|
|
|
|
tracef(k, ", ");
|
2016-10-07 22:21:23 +00:00
|
|
|
tracef(k, "%s=>$%d",
|
|
|
|
ir->u.phivalue.item[i].left->name,
|
|
|
|
ir->u.phivalue.item[i].right->id);
|
2016-10-01 20:58:29 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-09-18 21:24:54 +00:00
|
|
|
default:
|
2016-09-19 21:06:59 +00:00
|
|
|
if (ir->left)
|
2016-09-22 21:19:29 +00:00
|
|
|
{
|
2016-10-01 21:41:03 +00:00
|
|
|
if (ir->left->root != ir->root)
|
2016-09-22 21:19:29 +00:00
|
|
|
tracef(k, "$%d", ir->left->id);
|
|
|
|
else
|
|
|
|
print_expr(k, ir->left);
|
|
|
|
}
|
2016-09-19 21:06:59 +00:00
|
|
|
if (ir->right)
|
2016-09-22 21:19:29 +00:00
|
|
|
{
|
|
|
|
tracef(k, ", ");
|
2016-10-01 21:41:03 +00:00
|
|
|
if (ir->right->root != ir->root)
|
2016-09-22 21:19:29 +00:00
|
|
|
tracef(k, "$%d", ir->right->id);
|
|
|
|
else
|
|
|
|
print_expr(k, ir->right);
|
|
|
|
}
|
2016-09-18 21:24:54 +00:00
|
|
|
}
|
|
|
|
|
2016-09-22 21:19:29 +00:00
|
|
|
tracef(k, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
void ir_print(char k, const struct ir* ir)
|
|
|
|
{
|
|
|
|
tracef(k, "%c: $%d = ", k, ir->id);
|
|
|
|
print_expr(k, ir);
|
|
|
|
tracef(k, "\n");
|
2016-09-18 21:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* vim: set sw=4 ts=4 expandtab : */
|