blob: 27ca1abf683f781689b7304f06bfdb0a0ae5d57a [file] [log] [blame]
/*---------------------------------------------------------------*/
/*--- ---*/
/*--- This file (ir_defs.c) is ---*/
/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
/*--- ---*/
/*---------------------------------------------------------------*/
#include <stdio.h>
#include <malloc.h>
#include "basictypes.h"
#include "ir_defs.h"
/*---------------------------------------------------------------*/
/*--- Printing the IR ---*/
/*---------------------------------------------------------------*/
void ppIRType ( FILE* f, IRType ty )
{
switch (ty) {
case Ity_Bit: fprintf(f, "Bit"); break;
case Ity_I8: fprintf(f, "I8"); break;
case Ity_I16: fprintf(f, "I16"); break;
case Ity_I32: fprintf(f, "I32"); break;
case Ity_I64: fprintf(f, "I64"); break;
default: panic("ppIRType");
}
}
void ppIRConst ( FILE* f, IRConst* con )
{
switch (con->tag) {
case Ico_U8: fprintf(f, "0x%x", (UInt)(con->Ico.U8)); break;
case Ico_U16: fprintf(f, "0x%x", (UInt)(con->Ico.U16)); break;
case Ico_U32: fprintf(f, "0x%x", (UInt)(con->Ico.U32)); break;
case Ico_U64: fprintf(f, "0x%llx", (ULong)(con->Ico.U64)); break;
default: panic("ppIRConst");
}
}
void ppIRTemp ( FILE* f, IRTemp tmp )
{
fprintf(f, "t%d", tmp);
}
void ppIROp ( FILE* f, IROp op )
{
switch (op) {
case Iop_Add32: fprintf(f, "Add32"); break;
case Iop_Sub32: fprintf(f, "Sub32"); break;
case Iop_Mul32: fprintf(f, "Mul32"); break;
case Iop_Or32: fprintf(f, "Or32"); break;
case Iop_And32: fprintf(f, "And32"); break;
case Iop_Xor32: fprintf(f, "Xor32"); break;
case Iop_Shl32: fprintf(f, "Shl32"); break;
case Iop_Shr32: fprintf(f, "Shr32"); break;
case Iop_Sar32: fprintf(f, "Sar32"); break;
case Iop_Not32: fprintf(f, "Not32"); break;
case Iop_Neg32: fprintf(f, "Neg32"); break;
default: panic("ppIROp");
}
}
void ppIRExpr ( FILE* f, IRExpr* e )
{
switch (e->tag) {
case Iex_Get:
fprintf(f, "GET(%d,%d)", e->Iex.Get.offset, e->Iex.Get.size);
break;
case Iex_Tmp:
ppIRTemp(f, e->Iex.Tmp.tmp);
break;
case Iex_Binop:
ppIROp(f, e->Iex.Binop.op);
fprintf(f, "(");
ppIRExpr(f, e->Iex.Binop.arg1);
fprintf(f, ",");
ppIRExpr(f, e->Iex.Binop.arg2);
fprintf(f, ")");
break;
case Iex_Unop:
ppIROp(f, e->Iex.Unop.op);
fprintf(f, "(");
ppIRExpr(f, e->Iex.Unop.arg);
fprintf(f, ")");
break;
case Iex_LDle:
fprintf(f, "LDle<");
ppIRType(f, e->Iex.LDle.ty);
fprintf(f,">(");
ppIRExpr(f, e->Iex.LDle.addr);
fprintf(f,")");
break;
case Iex_Const:
ppIRConst(f, e->Iex.Const.con);
break;
default:
panic("ppIExpr");
}
}
void ppIRStmt ( FILE* f, IRStmt* s )
{
switch (s->tag) {
case Ist_Put:
fprintf(f, "Put(%d,%d) = ", s->Ist.Put.offset, s->Ist.Put.size);
ppIRExpr(f, s->Ist.Put.expr);
break;
case Ist_Tmp:
ppIRTemp(f, s->Ist.Tmp.tmp);
fprintf(f," = ");
ppIRExpr(f, s->Ist.Tmp.expr);
break;
case Ist_STle:
fprintf(f, "STle(");
ppIRExpr(f, s->Ist.STle.addr);
fprintf(f, ") = ");
ppIRExpr(f, s->Ist.STle.data);
break;
default:
panic("ppIRStmt");
}
}
void ppIRNext ( FILE* f, IRNext* nx )
{
switch (nx->tag) {
case Inx_UJump:
fprintf(f, "UJump ");
ppIRConst(f, nx->Inx.UJump.dst);
break;
case Inx_CJump01:
fprintf(f,"CJump01 (");
ppIRExpr(f, nx->Inx.CJump01.cond);
fprintf(f, ") ");
ppIRConst(f, nx->Inx.CJump01.dst0);
fprintf(f, " ");
ppIRConst(f, nx->Inx.CJump01.dst1);
break;
case Inx_IJump:
fprintf(f, "IJump ");
ppIRExpr(f, nx->Inx.IJump.dst);
break;
default:
panic("ppIRNext");
}
}
void ppIRTypeEnv ( FILE* f, IRTypeEnv* env ) {
UInt i;
for (i = 0; i < env->map_used; i++) {
if (i % 8 == 0)
fprintf(f, " ");
ppIRTemp(f, env->map[i].name);
fprintf(f, ":");
ppIRType(f, env->map[i].type);
if (i % 8 == 7)
fprintf(f, "\n");
else
fprintf(f, " ");
}
if (env->map_used > 0 && env->map_used % 8 != 7)
fprintf(f, "\n");
}
void ppIRBB ( FILE* f, IRBB* bb )
{
IRStmt* s;
ppIRTypeEnv(f, bb->tyenv);
for (s = bb->stmts; s; s = s->link) {
fprintf(f, " ");
ppIRStmt(f, s);
fprintf(f, "\n");
}
fprintf(f, " ");
ppIRNext(f, bb->next);
fprintf(f, "\n");
}
/*---------------------------------------------------------------*/
/*--- Constructors ---*/
/*---------------------------------------------------------------*/
/* Constructors -- IRConst */
IRConst* IRConst_U8 ( UChar u8 )
{
IRConst* c = malloc(sizeof(IRConst));
c->tag = Ico_U8;
c->Ico.U8 = u8;
return c;
}
IRConst* IRConst_U16 ( UShort u16 )
{
IRConst* c = malloc(sizeof(IRConst));
c->tag = Ico_U16;
c->Ico.U16 = u16;
return c;
}
IRConst* IRConst_U32 ( UInt u32 )
{
IRConst* c = malloc(sizeof(IRConst));
c->tag = Ico_U32;
c->Ico.U32 = u32;
return c;
}
IRConst* IRConst_U64 ( ULong u64 )
{
IRConst* c = malloc(sizeof(IRConst));
c->tag = Ico_U64;
c->Ico.U64 = u64;
return c;
}
/* Constructors -- IRExpr */
IRExpr* IRExpr_Get ( Int off, Int sz ) {
IRExpr* e = malloc(sizeof(IRExpr));
e->tag = Iex_Get;
e->Iex.Get.offset = off;
e->Iex.Get.size = sz;
return e;
}
IRExpr* IRExpr_Tmp ( IRTemp tmp ) {
IRExpr* e = malloc(sizeof(IRExpr));
e->tag = Iex_Tmp;
e->Iex.Tmp.tmp = tmp;
return e;
}
IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 ) {
IRExpr* e = malloc(sizeof(IRExpr));
e->tag = Iex_Binop;
e->Iex.Binop.op = op;
e->Iex.Binop.arg1 = arg1;
e->Iex.Binop.arg2 = arg2;
return e;
}
IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg ) {
IRExpr* e = malloc(sizeof(IRExpr));
e->tag = Iex_Unop;
e->Iex.Unop.op = op;
e->Iex.Unop.arg = arg;
return e;
}
IRExpr* IRExpr_LDle ( IRType ty, IRExpr* addr ) {
IRExpr* e = malloc(sizeof(IRExpr));
e->tag = Iex_LDle;
e->Iex.LDle.ty = ty;
e->Iex.LDle.addr = addr;
return e;
}
IRExpr* IRExpr_Const ( IRConst* con ) {
IRExpr* e = malloc(sizeof(IRExpr));
e->tag = Iex_Const;
e->Iex.Const.con = con;
return e;
}
/* Constructors -- IRStmt */
IRStmt* IRStmt_Put ( Int off, Int sz, IRExpr* value ) {
IRStmt* s = malloc(sizeof(IRStmt));
s->tag = Ist_Put;
s->link = NULL;
s->Ist.Put.offset = off;
s->Ist.Put.size = sz;
s->Ist.Put.expr = value;
return s;
}
IRStmt* IRStmt_Tmp ( IRTemp tmp, IRExpr* expr ) {
IRStmt* s = malloc(sizeof(IRStmt));
s->tag = Ist_Tmp;
s->link = NULL;
s->Ist.Tmp.tmp = tmp;
s->Ist.Tmp.expr = expr;
return s;
}
IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* value ) {
IRStmt* s = malloc(sizeof(IRStmt));
s->tag = Ist_STle;
s->link = NULL;
s->Ist.STle.addr = addr;
s->Ist.STle.data = value;
return s;
}
/* Constructors -- IRNext */
IRNext* IRNext_UJump ( IRConst* dst ) {
IRNext* nx = malloc(sizeof(IRNext));
nx->tag = Inx_UJump;
nx->Inx.UJump.dst = dst;
return nx;
}
/* Constructors -- IRBB */
IRBB* mk_IRBB ( IRTypeEnv* env, IRStmt* stmts, IRNext* next ) {
IRBB* bb = malloc(sizeof(IRBB));
bb->tyenv = env;
bb->stmts = stmts;
bb->next = next;
return bb;
}
/*---------------------------------------------------------------*/
/*--- Helper functions for the IR ---*/
/*---------------------------------------------------------------*/
IRTypeEnv* newIRTypeEnv ( void )
{
IRTypeEnv* env = malloc(sizeof(IRTypeEnv));
env->map = NULL;
env->map_size = 0;
env->map_used = 0;
return env;
}
void addToIRTypeEnv ( IRTypeEnv* env, IRTemp tmp, IRType ty )
{
assert(env);
assert(env->map_used >= 0);
assert(env->map_size >= 0);
assert(env->map_used <= env->map_size);
if (env->map_used < env->map_size) {
env->map[env->map_used].name = tmp;
env->map[env->map_used].type = ty;
env->map_used++;
} else {
Int i;
Int new_size = env->map_size==0 ? 8 : 2*env->map_size;
IRTypeEnvMaplet* new_map = malloc(new_size * sizeof(IRTypeEnvMaplet));
for (i = 0; i < env->map_used; i++)
new_map[i] = env->map[i];
env->map = new_map;
env->map_size = new_size;
return addToIRTypeEnv(env, tmp, ty);
}
}
IRType lookupIRTypeEnv ( IRTypeEnv* env, IRTemp tmp )
{
Int i;
for (i = 0; i < env->map_used; i++)
if (env->map[i].name == tmp)
return env->map[i].type;
panic("lookupIRTypeEnv");
}
IRType typeOfIRExpr ( IRTypeEnv* tyenv, IRExpr* e )
{
switch (e->tag) {
case Iex_Tmp:
return lookupIRTypeEnv(tyenv, e->Iex.Tmp.tmp);
case Iex_Const:
switch (e->Iex.Const.con->tag) {
case Ico_U8: return Ity_I8;
case Ico_U16: return Ity_I16;
case Ico_U32: return Ity_I32;
case Ico_U64: return Ity_I64;
default: panic("typeOfIRExpr:Iex_Const");
}
break;
case Iex_Binop:
switch (e->Iex.Binop.op) {
case Iop_Add32: case Iop_Sub32: case Iop_Mul32:
case Iop_Or32: case Iop_And32: case Iop_Xor32:
case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
return Ity_I32;
default: break;
}
break;
default:
break;
}
ppIRExpr(stderr,e);
panic("typeOfIRExpr");
}