blob: 732b733c06f8263bb839900d720488acbf824135 [file] [log] [blame]
sewardjec6ad592004-06-20 12:26:53 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
sewardjc0ee2ed2004-07-27 10:29:41 +00004/*--- This file (ir/irdefs.c) is ---*/
sewardjec6ad592004-06-20 12:26:53 +00005/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
sewardj887a11a2004-07-05 17:26:47 +00009#include "libvex_basictypes.h"
10#include "libvex_ir.h"
11#include "libvex.h"
sewardjec6ad592004-06-20 12:26:53 +000012
sewardjc0ee2ed2004-07-27 10:29:41 +000013#include "main/vex_util.h"
14
sewardjec6ad592004-06-20 12:26:53 +000015
16/*---------------------------------------------------------------*/
17/*--- Printing the IR ---*/
18/*---------------------------------------------------------------*/
19
sewardj35421a32004-07-05 13:12:34 +000020void ppIRType ( IRType ty )
sewardjec6ad592004-06-20 12:26:53 +000021{
sewardje3d0d2e2004-06-27 10:42:44 +000022 switch (ty) {
sewardj6efd4a12004-07-15 03:54:23 +000023 case Ity_INVALID: vex_printf("Ity_INVALID"); break;
24 case Ity_Bit: vex_printf( "Bit"); break;
25 case Ity_I8: vex_printf( "I8"); break;
26 case Ity_I16: vex_printf( "I16"); break;
27 case Ity_I32: vex_printf( "I32"); break;
28 case Ity_I64: vex_printf( "I64"); break;
sewardjd1725d12004-08-12 20:46:53 +000029 case Ity_F32: vex_printf( "F32"); break;
30 case Ity_F64: vex_printf( "F64"); break;
sewardj6d2638e2004-07-15 09:38:27 +000031 default: vex_printf("ty = 0x%x\n", (Int)ty);
32 vpanic("ppIRType");
sewardjec6ad592004-06-20 12:26:53 +000033 }
34}
35
sewardj35421a32004-07-05 13:12:34 +000036void ppIRConst ( IRConst* con )
sewardjec6ad592004-06-20 12:26:53 +000037{
sewardje3d0d2e2004-06-27 10:42:44 +000038 switch (con->tag) {
sewardj207557a2004-08-27 12:00:18 +000039 case Ico_Bit: vex_printf( "%d:Bit", con->Ico.Bit ? 1 : 0); break;
40 case Ico_U8: vex_printf( "0x%x:I8", (UInt)(con->Ico.U8)); break;
41 case Ico_U16: vex_printf( "0x%x:I16", (UInt)(con->Ico.U16)); break;
42 case Ico_U32: vex_printf( "0x%x:I32", (UInt)(con->Ico.U32)); break;
43 case Ico_U64: vex_printf( "0x%llx:I64", (ULong)(con->Ico.U64)); break;
44 case Ico_F64: vex_printf( "(f64 value)"); break;
45 case Ico_NaN64: vex_printf( "NaN:F64"); break;
sewardj35421a32004-07-05 13:12:34 +000046 default: vpanic("ppIRConst");
sewardje3d0d2e2004-06-27 10:42:44 +000047 }
48}
49
sewardj35421a32004-07-05 13:12:34 +000050void ppIRTemp ( IRTemp tmp )
sewardje3d0d2e2004-06-27 10:42:44 +000051{
sewardjfbcaf332004-07-08 01:46:01 +000052 if (tmp == INVALID_IRTEMP)
53 vex_printf("INVALID_IRTEMP");
54 else
sewardj41f43bc2004-07-08 14:23:22 +000055 vex_printf( "t%d", (Int)tmp);
sewardje3d0d2e2004-06-27 10:42:44 +000056}
57
sewardj35421a32004-07-05 13:12:34 +000058void ppIROp ( IROp op )
sewardje3d0d2e2004-06-27 10:42:44 +000059{
sewardj41f43bc2004-07-08 14:23:22 +000060 Char* str;
61 IROp base;
62 switch (op) {
63 case Iop_Add8 ... Iop_Add64:
64 str = "Add"; base = Iop_Add8; break;
65 case Iop_Sub8 ... Iop_Sub64:
66 str = "Sub"; base = Iop_Sub8; break;
67 case Iop_Mul8 ... Iop_Mul64:
68 str = "Mul"; base = Iop_Mul8; break;
69 case Iop_Or8 ... Iop_Or64:
70 str = "Or"; base = Iop_Or8; break;
71 case Iop_And8 ... Iop_And64:
72 str = "And"; base = Iop_And8; break;
73 case Iop_Xor8 ... Iop_Xor64:
74 str = "Xor"; base = Iop_Xor8; break;
75 case Iop_Shl8 ... Iop_Shl64:
76 str = "Shl"; base = Iop_Shl8; break;
77 case Iop_Shr8 ... Iop_Shr64:
78 str = "Shr"; base = Iop_Shr8; break;
79 case Iop_Sar8 ... Iop_Sar64:
80 str = "Sar"; base = Iop_Sar8; break;
sewardje90ad6a2004-07-10 19:02:10 +000081 case Iop_CmpEQ8 ... Iop_CmpEQ64:
82 str = "CmpEQ"; base = Iop_CmpEQ8; break;
83 case Iop_CmpNE8 ... Iop_CmpNE64:
84 str = "CmpNE"; base = Iop_CmpNE8; break;
sewardj41f43bc2004-07-08 14:23:22 +000085 case Iop_Neg8 ... Iop_Neg64:
86 str = "Neg"; base = Iop_Neg8; break;
87 case Iop_Not8 ... Iop_Not64:
88 str = "Not"; base = Iop_Not8; break;
89 /* other cases must explicitly "return;" */
sewardj9690d922004-07-14 01:39:17 +000090 case Iop_8Uto16: vex_printf("8Uto16"); return;
91 case Iop_8Uto32: vex_printf("8Uto32"); return;
92 case Iop_16Uto32: vex_printf("16Uto32"); return;
93 case Iop_8Sto16: vex_printf("8Sto16"); return;
94 case Iop_8Sto32: vex_printf("8Sto32"); return;
95 case Iop_16Sto32: vex_printf("16Sto32"); return;
sewardjbb53f8c2004-08-14 11:50:01 +000096 case Iop_32Sto64: vex_printf("32Sto64"); return;
sewardja2384712004-07-29 14:36:40 +000097 case Iop_32to8: vex_printf("32to8"); return;
sewardj9690d922004-07-14 01:39:17 +000098 case Iop_32to1: vex_printf("32to1"); return;
99 case Iop_1Uto8: vex_printf("1Uto8"); return;
sewardj84ff0652004-08-23 16:16:08 +0000100 case Iop_1Uto32: vex_printf("1Uto32"); return;
sewardj9690d922004-07-14 01:39:17 +0000101
102 case Iop_MullS8: vex_printf("MullS8"); return;
103 case Iop_MullS16: vex_printf("MullS16"); return;
104 case Iop_MullS32: vex_printf("MullS32"); return;
105 case Iop_MullU8: vex_printf("MullU8"); return;
106 case Iop_MullU16: vex_printf("MullU16"); return;
107 case Iop_MullU32: vex_printf("MullU32"); return;
108
sewardjce646f22004-08-31 23:55:54 +0000109 case Iop_Clz32: vex_printf("Clz32"); return;
110 case Iop_Ctz32: vex_printf("Ctz32"); return;
111
sewardj84ff0652004-08-23 16:16:08 +0000112 case Iop_CmpLT32S: vex_printf("CmpLT32S"); return;
113 case Iop_CmpLE32S: vex_printf("CmpLE32S"); return;
114 case Iop_CmpLT32U: vex_printf("CmpLT32U"); return;
115 case Iop_CmpLE32U: vex_printf("CmpLE32U"); return;
116
sewardj9690d922004-07-14 01:39:17 +0000117 case Iop_DivModU64to32: vex_printf("DivModU64to32"); return;
118 case Iop_DivModS64to32: vex_printf("DivModS64to32"); return;
119
sewardjb81f8b32004-07-30 10:17:50 +0000120 case Iop_16HIto8: vex_printf("16HIto8"); return;
121 case Iop_16to8: vex_printf("16to8"); return;
122 case Iop_8HLto16: vex_printf("8HLto16"); return;
123
sewardj8c7f1ab2004-07-29 20:31:09 +0000124 case Iop_32HIto16: vex_printf("32HIto16"); return;
125 case Iop_32to16: vex_printf("32to16"); return;
126 case Iop_16HLto32: vex_printf("16HLto32"); return;
127
sewardj9690d922004-07-14 01:39:17 +0000128 case Iop_64HIto32: vex_printf("64HIto32"); return;
sewardj8c7f1ab2004-07-29 20:31:09 +0000129 case Iop_64to32: vex_printf("64to32"); return;
sewardj9690d922004-07-14 01:39:17 +0000130 case Iop_32HLto64: vex_printf("32HLto64"); return;
131
sewardja58ea662004-08-15 03:12:41 +0000132 case Iop_AddF64: vex_printf("AddF64"); return;
sewardjce646f22004-08-31 23:55:54 +0000133 case Iop_SubF64: vex_printf("SubF64"); return;
sewardjbb53f8c2004-08-14 11:50:01 +0000134 case Iop_MulF64: vex_printf("MulF64"); return;
sewardjce646f22004-08-31 23:55:54 +0000135 case Iop_DivF64: vex_printf("DivF64"); return;
sewardjbdc7d212004-09-09 02:46:40 +0000136 case Iop_CmpF64: vex_printf("CmpF64"); return;
137
sewardj89cd0932004-09-08 18:23:25 +0000138 case Iop_I32toF64: vex_printf("I32toF64"); return;
sewardjbdc7d212004-09-09 02:46:40 +0000139 case Iop_I64toF64: vex_printf("I64toF64"); return;
140
sewardj89cd0932004-09-08 18:23:25 +0000141 case Iop_F64toI32: vex_printf("F64toI32"); return;
142 case Iop_F64toI16: vex_printf("F64toI16"); return;
143 case Iop_F32toF64: vex_printf("F32toF64"); return;
144 case Iop_F64toF32: vex_printf("F64toF32"); return;
sewardjbb53f8c2004-08-14 11:50:01 +0000145
sewardj9690d922004-07-14 01:39:17 +0000146 default: vpanic("ppIROp(1)");
sewardj41f43bc2004-07-08 14:23:22 +0000147 }
148
149 switch (op - base) {
150 case 0: vex_printf(str); vex_printf("8"); break;
151 case 1: vex_printf(str); vex_printf("16"); break;
152 case 2: vex_printf(str); vex_printf("32"); break;
153 case 3: vex_printf(str); vex_printf("64"); break;
154 default: vpanic("ppIROp(2)");
155 }
sewardje3d0d2e2004-06-27 10:42:44 +0000156}
157
sewardj35421a32004-07-05 13:12:34 +0000158void ppIRExpr ( IRExpr* e )
sewardje3d0d2e2004-06-27 10:42:44 +0000159{
sewardje87b4842004-07-10 12:23:30 +0000160 Int i;
sewardje3d0d2e2004-06-27 10:42:44 +0000161 switch (e->tag) {
sewardj443cd9d2004-07-18 23:06:45 +0000162 case Iex_Binder:
163 vex_printf("BIND-%d", e->Iex.Binder.binder);
164 break;
sewardje3d0d2e2004-06-27 10:42:44 +0000165 case Iex_Get:
sewardjfbcaf332004-07-08 01:46:01 +0000166 vex_printf( "GET(%d,", e->Iex.Get.offset);
167 ppIRType(e->Iex.Get.ty);
168 vex_printf(")");
sewardjec6ad592004-06-20 12:26:53 +0000169 break;
sewardjbb53f8c2004-08-14 11:50:01 +0000170 case Iex_GetI:
171 vex_printf( "GETI[%d,%d](", e->Iex.GetI.minoff, e->Iex.GetI.maxoff);
172 ppIRExpr(e->Iex.GetI.offset);
173 vex_printf("):");
174 ppIRType(e->Iex.GetI.ty);
175 break;
sewardje3d0d2e2004-06-27 10:42:44 +0000176 case Iex_Tmp:
sewardj35421a32004-07-05 13:12:34 +0000177 ppIRTemp(e->Iex.Tmp.tmp);
sewardjec6ad592004-06-20 12:26:53 +0000178 break;
sewardje3d0d2e2004-06-27 10:42:44 +0000179 case Iex_Binop:
sewardj35421a32004-07-05 13:12:34 +0000180 ppIROp(e->Iex.Binop.op);
181 vex_printf( "(" );
182 ppIRExpr(e->Iex.Binop.arg1);
183 vex_printf( "," );
184 ppIRExpr(e->Iex.Binop.arg2);
185 vex_printf( ")" );
sewardjec6ad592004-06-20 12:26:53 +0000186 break;
sewardje3d0d2e2004-06-27 10:42:44 +0000187 case Iex_Unop:
sewardj35421a32004-07-05 13:12:34 +0000188 ppIROp(e->Iex.Unop.op);
189 vex_printf( "(" );
190 ppIRExpr(e->Iex.Unop.arg);
191 vex_printf( ")" );
sewardjec6ad592004-06-20 12:26:53 +0000192 break;
sewardje3d0d2e2004-06-27 10:42:44 +0000193 case Iex_LDle:
sewardje05c42c2004-07-08 20:25:10 +0000194 vex_printf( "LDle:" );
sewardj35421a32004-07-05 13:12:34 +0000195 ppIRType(e->Iex.LDle.ty);
sewardje05c42c2004-07-08 20:25:10 +0000196 vex_printf( "(" );
sewardj35421a32004-07-05 13:12:34 +0000197 ppIRExpr(e->Iex.LDle.addr);
198 vex_printf( ")" );
sewardjec6ad592004-06-20 12:26:53 +0000199 break;
sewardje3d0d2e2004-06-27 10:42:44 +0000200 case Iex_Const:
sewardj35421a32004-07-05 13:12:34 +0000201 ppIRConst(e->Iex.Const.con);
sewardjec6ad592004-06-20 12:26:53 +0000202 break;
sewardje87b4842004-07-10 12:23:30 +0000203 case Iex_CCall:
204 vex_printf("%s(", e->Iex.CCall.name);
205 for (i = 0; e->Iex.CCall.args[i] != NULL; i++) {
206 ppIRExpr(e->Iex.CCall.args[i]);
207 if (e->Iex.CCall.args[i+1] != NULL)
208 vex_printf(",");
209 }
210 vex_printf("):");
211 ppIRType(e->Iex.CCall.retty);
212 break;
sewardj4042c7e2004-07-18 01:28:30 +0000213 case Iex_Mux0X:
214 vex_printf("Mux0X(");
215 ppIRExpr(e->Iex.Mux0X.cond);
sewardjeeb9ef82004-07-15 12:39:03 +0000216 vex_printf(",");
sewardj4042c7e2004-07-18 01:28:30 +0000217 ppIRExpr(e->Iex.Mux0X.expr0);
sewardjeeb9ef82004-07-15 12:39:03 +0000218 vex_printf(",");
sewardj4042c7e2004-07-18 01:28:30 +0000219 ppIRExpr(e->Iex.Mux0X.exprX);
sewardjeeb9ef82004-07-15 12:39:03 +0000220 vex_printf(")");
221 break;
sewardjec6ad592004-06-20 12:26:53 +0000222 default:
sewardj35421a32004-07-05 13:12:34 +0000223 vpanic("ppIExpr");
sewardjec6ad592004-06-20 12:26:53 +0000224 }
225}
226
sewardj35421a32004-07-05 13:12:34 +0000227void ppIRStmt ( IRStmt* s )
sewardjec6ad592004-06-20 12:26:53 +0000228{
sewardje3d0d2e2004-06-27 10:42:44 +0000229 switch (s->tag) {
230 case Ist_Put:
sewardjeeb9ef82004-07-15 12:39:03 +0000231 vex_printf( "PUT(%d) = ", s->Ist.Put.offset);
232 ppIRExpr(s->Ist.Put.expr);
sewardjec6ad592004-06-20 12:26:53 +0000233 break;
sewardjd1725d12004-08-12 20:46:53 +0000234 case Ist_PutI:
235 vex_printf( "PUTI[%d,%d](", s->Ist.PutI.minoff, s->Ist.PutI.maxoff);
236 ppIRExpr(s->Ist.PutI.offset);
237 vex_printf( ") = " );
238 ppIRExpr(s->Ist.PutI.expr);
239 break;
sewardje3d0d2e2004-06-27 10:42:44 +0000240 case Ist_Tmp:
sewardj35421a32004-07-05 13:12:34 +0000241 ppIRTemp(s->Ist.Tmp.tmp);
242 vex_printf( " = " );
243 ppIRExpr(s->Ist.Tmp.expr);
sewardjec6ad592004-06-20 12:26:53 +0000244 break;
sewardje3d0d2e2004-06-27 10:42:44 +0000245 case Ist_STle:
sewardj35421a32004-07-05 13:12:34 +0000246 vex_printf( "STle(");
247 ppIRExpr(s->Ist.STle.addr);
248 vex_printf( ") = ");
249 ppIRExpr(s->Ist.STle.data);
sewardjec6ad592004-06-20 12:26:53 +0000250 break;
sewardj64e1d652004-07-12 14:00:46 +0000251 case Ist_Exit:
252 vex_printf( "if (" );
253 ppIRExpr(s->Ist.Exit.cond);
254 vex_printf( ") goto ");
255 ppIRConst(s->Ist.Exit.dst);
256 break;
sewardjec6ad592004-06-20 12:26:53 +0000257 default:
sewardj35421a32004-07-05 13:12:34 +0000258 vpanic("ppIRStmt");
sewardjec6ad592004-06-20 12:26:53 +0000259 }
260}
261
sewardj78c19df2004-07-12 22:49:27 +0000262void ppIRJumpKind ( IRJumpKind kind )
263{
264 switch (kind) {
265 case Ijk_Boring: vex_printf("Boring"); break;
266 case Ijk_Call: vex_printf("Call"); break;
267 case Ijk_Ret: vex_printf("Return"); break;
268 case Ijk_ClientReq: vex_printf("ClientReq"); break;
269 case Ijk_Syscall: vex_printf("Syscall"); break;
270 case Ijk_Yield: vex_printf("Yield"); break;
271 default: vpanic("ppIRJumpKind");
272 }
273}
274
sewardj35421a32004-07-05 13:12:34 +0000275void ppIRTypeEnv ( IRTypeEnv* env ) {
sewardjc97096c2004-06-30 09:28:04 +0000276 UInt i;
sewardje539a402004-07-14 18:24:17 +0000277 for (i = 0; i < env->types_used; i++) {
sewardjc97096c2004-06-30 09:28:04 +0000278 if (i % 8 == 0)
sewardj35421a32004-07-05 13:12:34 +0000279 vex_printf( " ");
sewardje539a402004-07-14 18:24:17 +0000280 ppIRTemp(i);
sewardj35421a32004-07-05 13:12:34 +0000281 vex_printf( ":");
sewardje539a402004-07-14 18:24:17 +0000282 ppIRType(env->types[i]);
sewardjc97096c2004-06-30 09:28:04 +0000283 if (i % 8 == 7)
sewardj35421a32004-07-05 13:12:34 +0000284 vex_printf( "\n");
sewardjc97096c2004-06-30 09:28:04 +0000285 else
sewardj35421a32004-07-05 13:12:34 +0000286 vex_printf( " ");
sewardjc97096c2004-06-30 09:28:04 +0000287 }
sewardje539a402004-07-14 18:24:17 +0000288 if (env->types_used > 0 && env->types_used % 8 != 7)
sewardj35421a32004-07-05 13:12:34 +0000289 vex_printf( "\n");
sewardjc97096c2004-06-30 09:28:04 +0000290}
291
292
sewardjd7cb8532004-08-17 23:59:23 +0000293
294
sewardj35421a32004-07-05 13:12:34 +0000295void ppIRBB ( IRBB* bb )
sewardjec6ad592004-06-20 12:26:53 +0000296{
sewardjd7cb8532004-08-17 23:59:23 +0000297 Int i;
sewardj35439212004-07-14 22:36:10 +0000298 vex_printf("IRBB {\n");
sewardj35421a32004-07-05 13:12:34 +0000299 ppIRTypeEnv(bb->tyenv);
sewardj35439212004-07-14 22:36:10 +0000300 vex_printf("\n");
sewardjd7cb8532004-08-17 23:59:23 +0000301 for (i = 0; i < bb->stmts_used; i++) {
sewardj39e3f242004-08-18 16:54:52 +0000302 if (bb->stmts[i]) {
303 vex_printf( " ");
304 ppIRStmt(bb->stmts[i]);
305 }
sewardj35421a32004-07-05 13:12:34 +0000306 vex_printf( "\n");
sewardjec6ad592004-06-20 12:26:53 +0000307 }
sewardje539a402004-07-14 18:24:17 +0000308 vex_printf( " goto {");
309 ppIRJumpKind(bb->jumpkind);
310 vex_printf( "} ");
311 ppIRExpr( bb->next );
sewardj35439212004-07-14 22:36:10 +0000312 vex_printf( "\n}\n");
sewardjec6ad592004-06-20 12:26:53 +0000313}
314
315
316/*---------------------------------------------------------------*/
317/*--- Constructors ---*/
318/*---------------------------------------------------------------*/
319
sewardjc97096c2004-06-30 09:28:04 +0000320
321/* Constructors -- IRConst */
322
sewardjb8e75862004-08-19 17:58:45 +0000323IRConst* IRConst_Bit ( Bool bit )
324{
325 IRConst* c = LibVEX_Alloc(sizeof(IRConst));
326 c->tag = Ico_Bit;
327 c->Ico.Bit = bit;
328 return c;
329}
sewardjc97096c2004-06-30 09:28:04 +0000330IRConst* IRConst_U8 ( UChar u8 )
331{
sewardj35421a32004-07-05 13:12:34 +0000332 IRConst* c = LibVEX_Alloc(sizeof(IRConst));
sewardjc97096c2004-06-30 09:28:04 +0000333 c->tag = Ico_U8;
334 c->Ico.U8 = u8;
335 return c;
336}
337IRConst* IRConst_U16 ( UShort u16 )
338{
sewardj35421a32004-07-05 13:12:34 +0000339 IRConst* c = LibVEX_Alloc(sizeof(IRConst));
sewardjc97096c2004-06-30 09:28:04 +0000340 c->tag = Ico_U16;
341 c->Ico.U16 = u16;
342 return c;
343}
344IRConst* IRConst_U32 ( UInt u32 )
345{
sewardj35421a32004-07-05 13:12:34 +0000346 IRConst* c = LibVEX_Alloc(sizeof(IRConst));
sewardjc97096c2004-06-30 09:28:04 +0000347 c->tag = Ico_U32;
348 c->Ico.U32 = u32;
349 return c;
350}
351IRConst* IRConst_U64 ( ULong u64 )
352{
sewardj35421a32004-07-05 13:12:34 +0000353 IRConst* c = LibVEX_Alloc(sizeof(IRConst));
sewardjc97096c2004-06-30 09:28:04 +0000354 c->tag = Ico_U64;
355 c->Ico.U64 = u64;
356 return c;
357}
sewardja58ea662004-08-15 03:12:41 +0000358IRConst* IRConst_F64 ( Double f64 )
359{
360 IRConst* c = LibVEX_Alloc(sizeof(IRConst));
361 c->tag = Ico_F64;
362 c->Ico.F64 = f64;
363 return c;
364}
sewardj207557a2004-08-27 12:00:18 +0000365IRConst* IRConst_NaN64 ( void )
366{
367 IRConst* c = LibVEX_Alloc(sizeof(IRConst));
368 c->tag = Ico_NaN64;
369 return c;
370}
371
sewardjc97096c2004-06-30 09:28:04 +0000372
sewardje3d0d2e2004-06-27 10:42:44 +0000373/* Constructors -- IRExpr */
374
sewardj443cd9d2004-07-18 23:06:45 +0000375IRExpr* IRExpr_Binder ( Int binder ) {
376 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
377 e->tag = Iex_Binder;
378 e->Iex.Binder.binder = binder;
379 return e;
380}
sewardjfbcaf332004-07-08 01:46:01 +0000381IRExpr* IRExpr_Get ( Int off, IRType ty ) {
sewardj35421a32004-07-05 13:12:34 +0000382 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
sewardje3d0d2e2004-06-27 10:42:44 +0000383 e->tag = Iex_Get;
384 e->Iex.Get.offset = off;
sewardjfbcaf332004-07-08 01:46:01 +0000385 e->Iex.Get.ty = ty;
sewardje3d0d2e2004-06-27 10:42:44 +0000386 return e;
387}
sewardjd1725d12004-08-12 20:46:53 +0000388IRExpr* IRExpr_GetI ( IRExpr* off, IRType ty,
389 UShort minoff, UShort maxoff ) {
390 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
391 e->tag = Iex_GetI;
392 e->Iex.GetI.offset = off;
393 e->Iex.GetI.ty = ty;
394 e->Iex.GetI.minoff = minoff;
395 e->Iex.GetI.maxoff = maxoff;
396 return e;
397}
sewardjc97096c2004-06-30 09:28:04 +0000398IRExpr* IRExpr_Tmp ( IRTemp tmp ) {
sewardj35421a32004-07-05 13:12:34 +0000399 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
sewardje3d0d2e2004-06-27 10:42:44 +0000400 e->tag = Iex_Tmp;
401 e->Iex.Tmp.tmp = tmp;
402 return e;
403}
sewardjc97096c2004-06-30 09:28:04 +0000404IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 ) {
sewardj35421a32004-07-05 13:12:34 +0000405 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
sewardje3d0d2e2004-06-27 10:42:44 +0000406 e->tag = Iex_Binop;
407 e->Iex.Binop.op = op;
408 e->Iex.Binop.arg1 = arg1;
409 e->Iex.Binop.arg2 = arg2;
410 return e;
411}
sewardjc97096c2004-06-30 09:28:04 +0000412IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg ) {
sewardj35421a32004-07-05 13:12:34 +0000413 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
sewardje3d0d2e2004-06-27 10:42:44 +0000414 e->tag = Iex_Unop;
415 e->Iex.Unop.op = op;
416 e->Iex.Unop.arg = arg;
417 return e;
418}
sewardjc97096c2004-06-30 09:28:04 +0000419IRExpr* IRExpr_LDle ( IRType ty, IRExpr* addr ) {
sewardj35421a32004-07-05 13:12:34 +0000420 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
sewardje3d0d2e2004-06-27 10:42:44 +0000421 e->tag = Iex_LDle;
422 e->Iex.LDle.ty = ty;
423 e->Iex.LDle.addr = addr;
424 return e;
425}
sewardjc97096c2004-06-30 09:28:04 +0000426IRExpr* IRExpr_Const ( IRConst* con ) {
sewardj35421a32004-07-05 13:12:34 +0000427 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
sewardje3d0d2e2004-06-27 10:42:44 +0000428 e->tag = Iex_Const;
429 e->Iex.Const.con = con;
430 return e;
sewardjec6ad592004-06-20 12:26:53 +0000431}
sewardje87b4842004-07-10 12:23:30 +0000432IRExpr* IRExpr_CCall ( Char* name, IRType retty, IRExpr** args ) {
433 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
434 e->tag = Iex_CCall;
435 e->Iex.CCall.name = name;
436 e->Iex.CCall.retty = retty;
437 e->Iex.CCall.args = args;
438 return e;
439}
sewardj4042c7e2004-07-18 01:28:30 +0000440IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX ) {
sewardjeeb9ef82004-07-15 12:39:03 +0000441 IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
sewardj4042c7e2004-07-18 01:28:30 +0000442 e->tag = Iex_Mux0X;
443 e->Iex.Mux0X.cond = cond;
444 e->Iex.Mux0X.expr0 = expr0;
445 e->Iex.Mux0X.exprX = exprX;
sewardjeeb9ef82004-07-15 12:39:03 +0000446 return e;
447}
sewardjec6ad592004-06-20 12:26:53 +0000448
sewardjec6ad592004-06-20 12:26:53 +0000449
450/* Constructors -- IRStmt */
sewardje3d0d2e2004-06-27 10:42:44 +0000451
sewardjeeb9ef82004-07-15 12:39:03 +0000452IRStmt* IRStmt_Put ( Int off, IRExpr* value ) {
sewardj35421a32004-07-05 13:12:34 +0000453 IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
sewardje3d0d2e2004-06-27 10:42:44 +0000454 s->tag = Ist_Put;
455 s->Ist.Put.offset = off;
sewardje3d0d2e2004-06-27 10:42:44 +0000456 s->Ist.Put.expr = value;
457 return s;
sewardjec6ad592004-06-20 12:26:53 +0000458}
sewardjd1725d12004-08-12 20:46:53 +0000459IRStmt* IRStmt_PutI ( IRExpr* off, IRExpr* value,
460 UShort minoff, UShort maxoff ) {
461 IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
462 s->tag = Ist_PutI;
sewardjd1725d12004-08-12 20:46:53 +0000463 s->Ist.PutI.offset = off;
464 s->Ist.PutI.expr = value;
465 s->Ist.PutI.minoff = minoff;
466 s->Ist.PutI.maxoff = maxoff;
467 return s;
468}
sewardjc97096c2004-06-30 09:28:04 +0000469IRStmt* IRStmt_Tmp ( IRTemp tmp, IRExpr* expr ) {
sewardj35421a32004-07-05 13:12:34 +0000470 IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
sewardje3d0d2e2004-06-27 10:42:44 +0000471 s->tag = Ist_Tmp;
472 s->Ist.Tmp.tmp = tmp;
473 s->Ist.Tmp.expr = expr;
474 return s;
sewardjec6ad592004-06-20 12:26:53 +0000475}
sewardjc97096c2004-06-30 09:28:04 +0000476IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* value ) {
sewardj35421a32004-07-05 13:12:34 +0000477 IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
sewardje3d0d2e2004-06-27 10:42:44 +0000478 s->tag = Ist_STle;
479 s->Ist.STle.addr = addr;
480 s->Ist.STle.data = value;
481 return s;
sewardjec6ad592004-06-20 12:26:53 +0000482}
sewardj64e1d652004-07-12 14:00:46 +0000483IRStmt* IRStmt_Exit ( IRExpr* cond, IRConst* dst ) {
484 IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
485 s->tag = Ist_Exit;
sewardj64e1d652004-07-12 14:00:46 +0000486 s->Ist.Exit.cond = cond;
487 s->Ist.Exit.dst = dst;
488 return s;
489}
sewardje3d0d2e2004-06-27 10:42:44 +0000490
sewardjd7cb8532004-08-17 23:59:23 +0000491/* Constructors -- IRBB (sort of) */
sewardje3d0d2e2004-06-27 10:42:44 +0000492
sewardjd7cb8532004-08-17 23:59:23 +0000493IRBB* emptyIRBB ( void )
494{
495 IRBB* bb = LibVEX_Alloc(sizeof(IRBB));
496 bb->tyenv = emptyIRTypeEnv();
497 bb->stmts_used = 0;
498 bb->stmts_size = 8;
499 bb->stmts = LibVEX_Alloc(bb->stmts_size * sizeof(IRStmt*));
500 bb->next = NULL;
501 bb->jumpkind = Ijk_Boring;
sewardje3d0d2e2004-06-27 10:42:44 +0000502 return bb;
sewardjec6ad592004-06-20 12:26:53 +0000503}
504
sewardjd7cb8532004-08-17 23:59:23 +0000505void addStmtToIRBB ( IRBB* bb, IRStmt* st )
506{
507 Int i;
508 if (bb->stmts_used == bb->stmts_size) {
509 IRStmt** stmts2 = LibVEX_Alloc(2 * bb->stmts_size * sizeof(IRStmt*));
510 for (i = 0; i < bb->stmts_size; i++)
511 stmts2[i] = bb->stmts[i];
512 bb->stmts = stmts2;
513 bb->stmts_size *= 2;
514 }
515 vassert(bb->stmts_used < bb->stmts_size);
516 bb->stmts[bb->stmts_used] = st;
517 bb->stmts_used++;
518}
519
sewardjec6ad592004-06-20 12:26:53 +0000520
sewardjc97096c2004-06-30 09:28:04 +0000521/*---------------------------------------------------------------*/
sewardj6efd4a12004-07-15 03:54:23 +0000522/*--- Primop types ---*/
523/*---------------------------------------------------------------*/
524
525static
526void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
527{
528# define UNARY(_td,_ta1) \
529 *t_dst = (_td); *t_arg1 = (_ta1); break
530# define BINARY(_td,_ta1,_ta2) \
531 *t_dst = (_td); *t_arg1 = (_ta1); *t_arg2 = (_ta2); break
532# define COMPARISON(_ta) \
533 *t_dst = Ity_Bit; *t_arg1 = *t_arg2 = (_ta); break;
534
535 *t_dst = Ity_INVALID;
536 *t_arg1 = Ity_INVALID;
537 *t_arg2 = Ity_INVALID;
538 switch (op) {
sewardj66de2272004-07-16 21:19:05 +0000539 case Iop_Add8: case Iop_Sub8: //case Iop_Adc8: case Iop_Sbb8:
sewardj6efd4a12004-07-15 03:54:23 +0000540 case Iop_Mul8: case Iop_Or8: case Iop_And8: case Iop_Xor8:
541 BINARY(Ity_I8,Ity_I8,Ity_I8);
542
sewardj66de2272004-07-16 21:19:05 +0000543 case Iop_Add16: case Iop_Sub16: //case Iop_Adc16: case Iop_Sbb16:
sewardj6efd4a12004-07-15 03:54:23 +0000544 case Iop_Mul16: case Iop_Or16: case Iop_And16: case Iop_Xor16:
545 BINARY(Ity_I16,Ity_I16,Ity_I16);
546
sewardj66de2272004-07-16 21:19:05 +0000547 case Iop_Add32: case Iop_Sub32: //case Iop_Adc32: case Iop_Sbb32:
sewardj6efd4a12004-07-15 03:54:23 +0000548 case Iop_Mul32: case Iop_Or32: case Iop_And32: case Iop_Xor32:
549 BINARY(Ity_I32,Ity_I32,Ity_I32);
550
sewardj66de2272004-07-16 21:19:05 +0000551 case Iop_Add64: case Iop_Sub64: //case Iop_Adc64: case Iop_Sbb64:
sewardj6efd4a12004-07-15 03:54:23 +0000552 case Iop_Mul64: case Iop_Or64: case Iop_And64: case Iop_Xor64:
553 BINARY(Ity_I64,Ity_I64,Ity_I64);
554
555 case Iop_Shl8: case Iop_Shr8: case Iop_Sar8:
556 BINARY(Ity_I8,Ity_I8,Ity_I8);
557 case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
558 BINARY(Ity_I16,Ity_I16,Ity_I8);
559 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
560 BINARY(Ity_I32,Ity_I32,Ity_I8);
561 case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
562 BINARY(Ity_I64,Ity_I64,Ity_I8);
563
564 case Iop_Not8: case Iop_Neg8:
565 UNARY(Ity_I8,Ity_I8);
566 case Iop_Not16: case Iop_Neg16:
567 UNARY(Ity_I16,Ity_I16);
568 case Iop_Not32: case Iop_Neg32:
569 UNARY(Ity_I32,Ity_I32);
570 case Iop_Not64: case Iop_Neg64:
571 UNARY(Ity_I64,Ity_I64);
572
573 case Iop_CmpEQ8: case Iop_CmpNE8:
574 COMPARISON(Ity_I8);
575 case Iop_CmpEQ16: case Iop_CmpNE16:
576 COMPARISON(Ity_I16);
577 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardj84ff0652004-08-23 16:16:08 +0000578 case Iop_CmpLT32S:
579 case Iop_CmpLE32S:
580 case Iop_CmpLT32U:
581 case Iop_CmpLE32U:
sewardj6efd4a12004-07-15 03:54:23 +0000582 COMPARISON(Ity_I32);
583 case Iop_CmpEQ64: case Iop_CmpNE64:
584 COMPARISON(Ity_I64);
585
sewardjb81f8b32004-07-30 10:17:50 +0000586 case Iop_MullU8: case Iop_MullS8:
587 BINARY(Ity_I16,Ity_I8,Ity_I8);
588 case Iop_MullU16: case Iop_MullS16:
589 BINARY(Ity_I32,Ity_I16,Ity_I16);
sewardj6d2638e2004-07-15 09:38:27 +0000590 case Iop_MullU32: case Iop_MullS32:
591 BINARY(Ity_I64,Ity_I32,Ity_I32);
592
sewardjce646f22004-08-31 23:55:54 +0000593 case Iop_Clz32:
594 case Iop_Ctz32:
595 UNARY(Ity_I32,Ity_I32);
596
sewardj6d2638e2004-07-15 09:38:27 +0000597 case Iop_DivModU64to32:
sewardj02552072004-07-28 07:13:38 +0000598 case Iop_DivModS64to32:
sewardj6d2638e2004-07-15 09:38:27 +0000599 BINARY(Ity_I64,Ity_I64,Ity_I32);
600
sewardjb81f8b32004-07-30 10:17:50 +0000601 case Iop_16HIto8: case Iop_16to8:
602 UNARY(Ity_I8,Ity_I16);
603 case Iop_8HLto16:
604 BINARY(Ity_I16,Ity_I8,Ity_I8);
605
sewardj8c7f1ab2004-07-29 20:31:09 +0000606 case Iop_32HIto16: case Iop_32to16:
607 UNARY(Ity_I16,Ity_I32);
608 case Iop_16HLto32:
609 BINARY(Ity_I32,Ity_I16,Ity_I16);
610
611 case Iop_64HIto32: case Iop_64to32:
sewardj6d2638e2004-07-15 09:38:27 +0000612 UNARY(Ity_I32, Ity_I64);
613 case Iop_32HLto64:
614 BINARY(Ity_I64,Ity_I32,Ity_I32);
615
616 case Iop_1Uto8: UNARY(Ity_I8,Ity_Bit);
sewardj84ff0652004-08-23 16:16:08 +0000617 case Iop_1Uto32: UNARY(Ity_I32,Ity_Bit);
sewardj6d2638e2004-07-15 09:38:27 +0000618 case Iop_32to1: UNARY(Ity_Bit,Ity_I32);
619 case Iop_8Uto32: UNARY(Ity_I32,Ity_I8);
sewardjc22a6fd2004-07-29 23:41:47 +0000620 case Iop_8Sto32: UNARY(Ity_I32,Ity_I8);
sewardj6d2638e2004-07-15 09:38:27 +0000621 case Iop_16Uto32: UNARY(Ity_I32,Ity_I16);
sewardjc22a6fd2004-07-29 23:41:47 +0000622 case Iop_16Sto32: UNARY(Ity_I32,Ity_I16);
sewardjbb53f8c2004-08-14 11:50:01 +0000623 case Iop_32Sto64: UNARY(Ity_I64,Ity_I32);
sewardja2384712004-07-29 14:36:40 +0000624 case Iop_32to8: UNARY(Ity_I8,Ity_I32);
sewardj6d2638e2004-07-15 09:38:27 +0000625
sewardjce646f22004-08-31 23:55:54 +0000626 case Iop_AddF64: case Iop_SubF64:
627 case Iop_MulF64: case Iop_DivF64:
sewardja58ea662004-08-15 03:12:41 +0000628 BINARY(Ity_F64,Ity_F64,Ity_F64);
sewardjbdc7d212004-09-09 02:46:40 +0000629 case Iop_CmpF64:
630 BINARY(Ity_I32,Ity_F64,Ity_F64);
sewardj8f3debf2004-09-08 23:42:23 +0000631
sewardj89cd0932004-09-08 18:23:25 +0000632 case Iop_I32toF64: UNARY(Ity_F64,Ity_I32);
sewardjbdc7d212004-09-09 02:46:40 +0000633 case Iop_I64toF64: UNARY(Ity_F64,Ity_I64);
sewardj8f3debf2004-09-08 23:42:23 +0000634
635 case Iop_F64toI32: BINARY(Ity_I32, Ity_I32,Ity_F64);
636 case Iop_F64toI16: BINARY(Ity_I16, Ity_I32,Ity_F64);
637
sewardj89cd0932004-09-08 18:23:25 +0000638 case Iop_F32toF64: UNARY(Ity_F64,Ity_F32);
639 case Iop_F64toF32: UNARY(Ity_F32,Ity_F64);
sewardjbb53f8c2004-08-14 11:50:01 +0000640
sewardj6efd4a12004-07-15 03:54:23 +0000641 default:
642 ppIROp(op);
643 vpanic("typeOfPrimop");
644 }
645# undef UNARY
646# undef BINARY
647# undef COMPARISON
648}
649
650
651/*---------------------------------------------------------------*/
sewardjd7cb8532004-08-17 23:59:23 +0000652/*--- Helper functions for the IR -- IR Type Environments ---*/
sewardjc97096c2004-06-30 09:28:04 +0000653/*---------------------------------------------------------------*/
654
sewardjd7cb8532004-08-17 23:59:23 +0000655/* Make a new, empty IRTypeEnv. */
656
657IRTypeEnv* emptyIRTypeEnv ( void )
sewardjc97096c2004-06-30 09:28:04 +0000658{
sewardje539a402004-07-14 18:24:17 +0000659 IRTypeEnv* env = LibVEX_Alloc(sizeof(IRTypeEnv));
660 env->types = LibVEX_Alloc(8 * sizeof(IRType));
661 env->types_size = 8;
662 env->types_used = 0;
sewardjc97096c2004-06-30 09:28:04 +0000663 return env;
664}
sewardje3d0d2e2004-06-27 10:42:44 +0000665
sewardjd7cb8532004-08-17 23:59:23 +0000666/* Make an exact copy of the given IRTypeEnv, usually so we can
667 add new stuff to the copy without messing up the original. */
668
669IRTypeEnv* copyIRTypeEnv ( IRTypeEnv* src )
670{
671 Int i;
672 IRTypeEnv* dst = LibVEX_Alloc(sizeof(IRTypeEnv));
673 dst->types_size = src->types_size;
674 dst->types_used = src->types_used;
675 dst->types = LibVEX_Alloc(dst->types_size * sizeof(IRType));
676 for (i = 0; i < src->types_used; i++)
677 dst->types[i] = src->types[i];
678 return dst;
679}
680
681/* Allocate a new IRTemp, given its type. */
sewardje3d0d2e2004-06-27 10:42:44 +0000682
sewardje539a402004-07-14 18:24:17 +0000683IRTemp newIRTemp ( IRTypeEnv* env, IRType ty )
sewardjc97096c2004-06-30 09:28:04 +0000684{
sewardj35421a32004-07-05 13:12:34 +0000685 vassert(env);
sewardje539a402004-07-14 18:24:17 +0000686 vassert(env->types_used >= 0);
687 vassert(env->types_size >= 0);
688 vassert(env->types_used <= env->types_size);
689 if (env->types_used < env->types_size) {
690 env->types[env->types_used] = ty;
691 return env->types_used++;
sewardjc97096c2004-06-30 09:28:04 +0000692 } else {
693 Int i;
sewardje539a402004-07-14 18:24:17 +0000694 Int new_size = env->types_size==0 ? 8 : 2*env->types_size;
695 IRType* new_types
696 = LibVEX_Alloc(new_size * sizeof(IRType));
697 for (i = 0; i < env->types_used; i++)
698 new_types[i] = env->types[i];
699 env->types = new_types;
700 env->types_size = new_size;
701 return newIRTemp(env, ty);
sewardjc97096c2004-06-30 09:28:04 +0000702 }
703}
704
sewardjd7cb8532004-08-17 23:59:23 +0000705/* Find the type of a temporary previously allocated in an
706 environment. */
sewardjc97096c2004-06-30 09:28:04 +0000707
708IRType lookupIRTypeEnv ( IRTypeEnv* env, IRTemp tmp )
709{
sewardje539a402004-07-14 18:24:17 +0000710 vassert(tmp >= 0);
711 vassert(tmp < env->types_used);
712 return env->types[tmp];
sewardjc97096c2004-06-30 09:28:04 +0000713}
714
715
sewardjd7cb8532004-08-17 23:59:23 +0000716/*---------------------------------------------------------------*/
717/*--- Helper functions for the IR -- finding types of exprs ---*/
718/*---------------------------------------------------------------*/
719
sewardj6efd4a12004-07-15 03:54:23 +0000720IRType typeOfIRConst ( IRConst* con )
721{
722 switch (con->tag) {
sewardj207557a2004-08-27 12:00:18 +0000723 case Ico_Bit: return Ity_Bit;
724 case Ico_U8: return Ity_I8;
725 case Ico_U16: return Ity_I16;
726 case Ico_U32: return Ity_I32;
727 case Ico_U64: return Ity_I64;
728 case Ico_F64: return Ity_F64;
729 case Ico_NaN64: return Ity_F64;
sewardj6efd4a12004-07-15 03:54:23 +0000730 default: vpanic("typeOfIRConst");
731 }
732}
733
sewardjc97096c2004-06-30 09:28:04 +0000734IRType typeOfIRExpr ( IRTypeEnv* tyenv, IRExpr* e )
735{
sewardj6efd4a12004-07-15 03:54:23 +0000736 IRType t_dst, t_arg1, t_arg2;
sewardjc97096c2004-06-30 09:28:04 +0000737 switch (e->tag) {
sewardje05c42c2004-07-08 20:25:10 +0000738 case Iex_LDle:
739 return e->Iex.LDle.ty;
sewardjfbcaf332004-07-08 01:46:01 +0000740 case Iex_Get:
741 return e->Iex.Get.ty;
sewardjbb53f8c2004-08-14 11:50:01 +0000742 case Iex_GetI:
743 return e->Iex.GetI.ty;
sewardjc97096c2004-06-30 09:28:04 +0000744 case Iex_Tmp:
745 return lookupIRTypeEnv(tyenv, e->Iex.Tmp.tmp);
746 case Iex_Const:
sewardj6efd4a12004-07-15 03:54:23 +0000747 return typeOfIRConst(e->Iex.Const.con);
sewardjc97096c2004-06-30 09:28:04 +0000748 case Iex_Binop:
sewardj6efd4a12004-07-15 03:54:23 +0000749 typeOfPrimop(e->Iex.Binop.op, &t_dst, &t_arg1, &t_arg2);
750 return t_dst;
751 case Iex_Unop:
752 typeOfPrimop(e->Iex.Unop.op, &t_dst, &t_arg1, &t_arg2);
753 return t_dst;
754 case Iex_CCall:
755 return e->Iex.CCall.retty;
sewardj4042c7e2004-07-18 01:28:30 +0000756 case Iex_Mux0X:
757 return typeOfIRExpr(tyenv, e->Iex.Mux0X.expr0);
sewardj443cd9d2004-07-18 23:06:45 +0000758 case Iex_Binder:
759 vpanic("typeOfIRExpr: Binder is not a valid expression");
sewardjc97096c2004-06-30 09:28:04 +0000760 default:
sewardj6efd4a12004-07-15 03:54:23 +0000761 ppIRExpr(e);
762 vpanic("typeOfIRExpr");
sewardjc97096c2004-06-30 09:28:04 +0000763 }
sewardjc97096c2004-06-30 09:28:04 +0000764}
sewardj887a11a2004-07-05 17:26:47 +0000765
sewardj6d2638e2004-07-15 09:38:27 +0000766/* Is this any value actually in the enumeration 'IRType' ? */
767Bool isPlausibleType ( IRType ty )
768{
769 switch (ty) {
770 case Ity_INVALID: case Ity_Bit:
771 case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64:
sewardjbb53f8c2004-08-14 11:50:01 +0000772 case Ity_F32: case Ity_F64:
sewardj6d2638e2004-07-15 09:38:27 +0000773 return True;
774 default:
775 return False;
776 }
777}
778
sewardj6efd4a12004-07-15 03:54:23 +0000779
sewardj887a11a2004-07-05 17:26:47 +0000780/*---------------------------------------------------------------*/
sewardje539a402004-07-14 18:24:17 +0000781/*--- Sanity checking ---*/
782/*---------------------------------------------------------------*/
783
784/* Checks:
785
786 Everything is type-consistent. No ill-typed anything.
sewardj35439212004-07-14 22:36:10 +0000787 The target address at the end of the BB is a 32- or 64-
788 bit expression, depending on the guest's word size.
sewardje539a402004-07-14 18:24:17 +0000789
790 Each temp is assigned only once, before its uses.
sewardje539a402004-07-14 18:24:17 +0000791 */
792
sewardj35439212004-07-14 22:36:10 +0000793static
794__attribute((noreturn))
795void sanityCheckFail ( IRBB* bb, IRStmt* stmt, Char* what )
sewardje539a402004-07-14 18:24:17 +0000796{
sewardj35439212004-07-14 22:36:10 +0000797 vex_printf("\nIR SANITY CHECK FAILURE\n\n");
798 ppIRBB(bb);
799 if (stmt) {
800 vex_printf("\nIN STATEMENT:\n\n");
801 ppIRStmt(stmt);
802 }
803 vex_printf("\n\nERROR = %s\n\n", what );
804 vpanic("sanityCheckFail: exiting due to bad IR");
805}
806
807
808/* Traverse a Stmt/Expr, inspecting IRTemp uses. Report any out of
809 range ones. Report any which are read and for which the current
810 def_count is zero. */
811
812static
813void useBeforeDef_Expr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, Int* def_counts )
814{
815 Int i;
816 switch (expr->tag) {
817 case Iex_Get:
818 break;
sewardjbb53f8c2004-08-14 11:50:01 +0000819 case Iex_GetI:
820 useBeforeDef_Expr(bb,stmt,expr->Iex.GetI.offset,def_counts);
821 break;
sewardj35439212004-07-14 22:36:10 +0000822 case Iex_Tmp:
823 if (expr->Iex.Tmp.tmp < 0 || expr->Iex.Tmp.tmp >= bb->tyenv->types_used)
824 sanityCheckFail(bb,stmt, "out of range Temp in IRExpr");
825 if (def_counts[expr->Iex.Tmp.tmp] < 1)
sewardj39e3f242004-08-18 16:54:52 +0000826 sanityCheckFail(bb,stmt, "IRTemp use before def in IRExpr");
sewardj35439212004-07-14 22:36:10 +0000827 break;
828 case Iex_Binop:
829 useBeforeDef_Expr(bb,stmt,expr->Iex.Binop.arg1,def_counts);
830 useBeforeDef_Expr(bb,stmt,expr->Iex.Binop.arg2,def_counts);
831 break;
832 case Iex_Unop:
833 useBeforeDef_Expr(bb,stmt,expr->Iex.Unop.arg,def_counts);
834 break;
835 case Iex_LDle:
836 useBeforeDef_Expr(bb,stmt,expr->Iex.LDle.addr,def_counts);
837 break;
838 case Iex_Const:
839 break;
840 case Iex_CCall:
841 for (i = 0; expr->Iex.CCall.args[i]; i++)
842 useBeforeDef_Expr(bb,stmt,expr->Iex.CCall.args[i],def_counts);
843 break;
sewardj4042c7e2004-07-18 01:28:30 +0000844 case Iex_Mux0X:
845 useBeforeDef_Expr(bb,stmt,expr->Iex.Mux0X.cond,def_counts);
846 useBeforeDef_Expr(bb,stmt,expr->Iex.Mux0X.expr0,def_counts);
847 useBeforeDef_Expr(bb,stmt,expr->Iex.Mux0X.exprX,def_counts);
sewardjeeb9ef82004-07-15 12:39:03 +0000848 break;
849 default:
850 vpanic("useBeforeDef_Expr");
sewardj35439212004-07-14 22:36:10 +0000851 }
852}
853
854static
855void useBeforeDef_Stmt ( IRBB* bb, IRStmt* stmt, Int* def_counts )
856{
857 switch (stmt->tag) {
858 case Ist_Put:
sewardj35439212004-07-14 22:36:10 +0000859 useBeforeDef_Expr(bb,stmt,stmt->Ist.Put.expr,def_counts);
860 break;
sewardjd1725d12004-08-12 20:46:53 +0000861 case Ist_PutI:
862 useBeforeDef_Expr(bb,stmt,stmt->Ist.PutI.offset,def_counts);
863 useBeforeDef_Expr(bb,stmt,stmt->Ist.PutI.expr,def_counts);
864 break;
sewardj35439212004-07-14 22:36:10 +0000865 case Ist_Tmp:
866 useBeforeDef_Expr(bb,stmt,stmt->Ist.Tmp.expr,def_counts);
867 break;
868 case Ist_STle:
869 useBeforeDef_Expr(bb,stmt,stmt->Ist.STle.addr,def_counts);
870 useBeforeDef_Expr(bb,stmt,stmt->Ist.STle.data,def_counts);
871 break;
872 case Ist_Exit:
873 useBeforeDef_Expr(bb,stmt,stmt->Ist.Exit.cond,def_counts);
874 break;
875 default:
876 vpanic("useBeforeDef_Stmt");
877 }
878}
879
sewardj6efd4a12004-07-15 03:54:23 +0000880static
881void tcExpr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, IRType gWordTy )
882{
883 Int i;
884 IRType t_dst, t_arg1, t_arg2;
885 IRTypeEnv* tyenv = bb->tyenv;
886 switch (expr->tag) {
887 case Iex_Get:
888 case Iex_Tmp:
889 break;
sewardjbb53f8c2004-08-14 11:50:01 +0000890 case Iex_GetI:
891 tcExpr(bb,stmt, expr->Iex.GetI.offset, gWordTy );
892 if (typeOfIRExpr(tyenv,expr->Iex.GetI.offset) != Ity_I32)
893 sanityCheckFail(bb,stmt,"IRExpr.GetI.offset: not :: Ity_I32");
894 break;
sewardj6d2638e2004-07-15 09:38:27 +0000895 case Iex_Binop: {
896 IRType ttarg1, ttarg2;
sewardj6efd4a12004-07-15 03:54:23 +0000897 tcExpr(bb,stmt, expr->Iex.Binop.arg1, gWordTy );
898 tcExpr(bb,stmt, expr->Iex.Binop.arg2, gWordTy );
899 typeOfPrimop(expr->Iex.Binop.op, &t_dst, &t_arg1, &t_arg2);
sewardj8f3debf2004-09-08 23:42:23 +0000900 if (t_arg1 == Ity_INVALID || t_arg2 == Ity_INVALID) {
901 vex_printf(" op name: " );
902 ppIROp(expr->Iex.Binop.op);
903 vex_printf("\n");
904 sanityCheckFail(bb,stmt,
905 "Iex.Binop: wrong arity op\n"
906 "... name of op precedes BB printout\n");
907 }
sewardj6d2638e2004-07-15 09:38:27 +0000908 ttarg1 = typeOfIRExpr(tyenv, expr->Iex.Binop.arg1);
909 ttarg2 = typeOfIRExpr(tyenv, expr->Iex.Binop.arg2);
910 if (t_arg1 != ttarg1 || t_arg2 != ttarg2) {
911 vex_printf(" op name: ");
912 ppIROp(expr->Iex.Binop.op);
913 vex_printf("\n");
914 vex_printf(" op type is (");
915 ppIRType(t_arg1);
916 vex_printf(",");
917 ppIRType(t_arg2);
918 vex_printf(") -> ");
919 ppIRType (t_dst);
920 vex_printf("\narg tys are (");
921 ppIRType(ttarg1);
922 vex_printf(",");
923 ppIRType(ttarg2);
924 vex_printf(")\n");
925 sanityCheckFail(bb,stmt,
926 "Iex.Binop: arg tys don't match op tys\n"
927 "... additional details precede BB printout\n");
928 }
sewardj6efd4a12004-07-15 03:54:23 +0000929 break;
sewardj6d2638e2004-07-15 09:38:27 +0000930 }
sewardj6efd4a12004-07-15 03:54:23 +0000931 case Iex_Unop:
932 tcExpr(bb,stmt, expr->Iex.Unop.arg, gWordTy );
933 typeOfPrimop(expr->Iex.Binop.op, &t_dst, &t_arg1, &t_arg2);
934 if (t_arg1 == Ity_INVALID || t_arg2 != Ity_INVALID)
935 sanityCheckFail(bb,stmt,"Iex.Unop: wrong arity op");
936 if (t_arg1 != typeOfIRExpr(tyenv, expr->Iex.Unop.arg))
937 sanityCheckFail(bb,stmt,"Iex.Unop: arg ty doesn't match op ty");
938 break;
939 case Iex_LDle:
940 tcExpr(bb,stmt, expr->Iex.LDle.addr, gWordTy);
941 if (typeOfIRExpr(tyenv, expr->Iex.LDle.addr) != gWordTy)
942 sanityCheckFail(bb,stmt,"Iex.LDle.addr: not :: guest word type");
943 break;
944 case Iex_CCall:
945 for (i = 0; expr->Iex.CCall.args[i]; i++)
946 tcExpr(bb,stmt, expr->Iex.CCall.args[i], gWordTy);
947 if (expr->Iex.CCall.retty == Ity_Bit)
948 sanityCheckFail(bb,stmt,"Iex.CCall.retty: cannot return :: Ity_Bit");
949 for (i = 0; expr->Iex.CCall.args[i]; i++)
950 if (typeOfIRExpr(tyenv, expr->Iex.CCall.args[i]) == Ity_Bit)
951 sanityCheckFail(bb,stmt,"Iex.CCall.arg: arg :: Ity_Bit");
952 break;
953 case Iex_Const:
954 break;
sewardj4042c7e2004-07-18 01:28:30 +0000955 case Iex_Mux0X:
956 tcExpr(bb,stmt, expr->Iex.Mux0X.cond, gWordTy);
957 tcExpr(bb,stmt, expr->Iex.Mux0X.expr0, gWordTy);
958 tcExpr(bb,stmt, expr->Iex.Mux0X.exprX, gWordTy);
959 if (typeOfIRExpr(tyenv, expr->Iex.Mux0X.cond) != Ity_I8)
960 sanityCheckFail(bb,stmt,"Iex.Mux0X.cond: cond :: Ity_I8");
961 if (typeOfIRExpr(tyenv, expr->Iex.Mux0X.expr0)
962 != typeOfIRExpr(tyenv, expr->Iex.Mux0X.exprX))
963 sanityCheckFail(bb,stmt,"Iex.Mux0X: expr0/exprX mismatch");
sewardjeeb9ef82004-07-15 12:39:03 +0000964 break;
965 default:
sewardj6efd4a12004-07-15 03:54:23 +0000966 vpanic("tcExpr");
967 }
968}
969
970
971static
972void tcStmt ( IRBB* bb, IRStmt* stmt, IRType gWordTy )
973{
974 IRTypeEnv* tyenv = bb->tyenv;
975 switch (stmt->tag) {
976 case Ist_Put:
sewardj6efd4a12004-07-15 03:54:23 +0000977 tcExpr( bb, stmt, stmt->Ist.Put.expr, gWordTy );
978 if (typeOfIRExpr(tyenv,stmt->Ist.Put.expr) == Ity_Bit)
979 sanityCheckFail(bb,stmt,"IRStmt.Put.expr: cannot Put :: Ity_Bit");
980 break;
sewardjd1725d12004-08-12 20:46:53 +0000981 case Ist_PutI:
982 tcExpr( bb, stmt, stmt->Ist.PutI.expr, gWordTy );
983 tcExpr( bb, stmt, stmt->Ist.PutI.offset, gWordTy );
984 if (typeOfIRExpr(tyenv,stmt->Ist.PutI.expr) == Ity_Bit)
985 sanityCheckFail(bb,stmt,"IRStmt.PutI.expr: cannot PutI :: Ity_Bit");
986 if (typeOfIRExpr(tyenv,stmt->Ist.PutI.offset) != Ity_I32)
987 sanityCheckFail(bb,stmt,"IRStmt.PutI.offset: not :: Ity_I32");
988 break;
sewardj6efd4a12004-07-15 03:54:23 +0000989 case Ist_Tmp:
990 tcExpr( bb, stmt, stmt->Ist.Tmp.expr, gWordTy );
991 if (lookupIRTypeEnv(tyenv, stmt->Ist.Tmp.tmp)
992 != typeOfIRExpr(tyenv, stmt->Ist.Tmp.expr))
sewardj6d2638e2004-07-15 09:38:27 +0000993 sanityCheckFail(bb,stmt,"IRStmt.Put.Tmp: tmp and expr do not match");
sewardj6efd4a12004-07-15 03:54:23 +0000994 break;
995 case Ist_STle:
996 tcExpr( bb, stmt, stmt->Ist.STle.addr, gWordTy );
997 tcExpr( bb, stmt, stmt->Ist.STle.data, gWordTy );
998 if (typeOfIRExpr(tyenv, stmt->Ist.STle.addr) != gWordTy)
999 sanityCheckFail(bb,stmt,"IRStmt.STle.addr: not :: guest word type");
1000 if (typeOfIRExpr(tyenv, stmt->Ist.STle.data) == Ity_Bit)
1001 sanityCheckFail(bb,stmt,"IRStmt.STle.data: cannot STle :: Ity_Bit");
1002 break;
1003 case Ist_Exit:
1004 tcExpr( bb, stmt, stmt->Ist.Exit.cond, gWordTy );
1005 if (typeOfIRExpr(tyenv,stmt->Ist.Exit.cond) != Ity_Bit)
1006 sanityCheckFail(bb,stmt,"IRStmt.Exit.cond: not :: Ity_Bit");
1007 if (typeOfIRConst(stmt->Ist.Exit.dst) != gWordTy)
1008 sanityCheckFail(bb,stmt,"IRStmt.Exit.dst: not :: guest word type");
1009 break;
1010 default:
1011 vpanic("tcStmt");
1012 }
1013}
1014
sewardj35439212004-07-14 22:36:10 +00001015void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size )
1016{
1017 Int i;
1018 IRStmt* stmt;
1019 Int n_temps = bb->tyenv->types_used;
1020 Int* def_counts = LibVEX_Alloc(n_temps * sizeof(Int));
1021
1022 vassert(guest_word_size == Ity_I32
1023 || guest_word_size == Ity_I64);
1024
sewardjd7cb8532004-08-17 23:59:23 +00001025 if (bb->stmts_used < 0 || bb->stmts_size < 8
1026 || bb->stmts_used > bb->stmts_size)
1027 /* this BB is so strange we can't even print it */
1028 vpanic("sanityCheckIRBB: stmts array limits wierd");
1029
sewardj6d2638e2004-07-15 09:38:27 +00001030 /* Ensure each temp has a plausible type. */
1031 for (i = 0; i < n_temps; i++) {
1032 IRType ty = lookupIRTypeEnv(bb->tyenv,(IRTemp)i);
1033 if (!isPlausibleType(ty)) {
1034 vex_printf("Temp t%d declared with implausible type 0x%x\n",
1035 i, (UInt)ty);
1036 sanityCheckFail(bb,NULL,"Temp declared with implausible type");
1037 }
1038 }
sewardj35439212004-07-14 22:36:10 +00001039
1040 /* Count the defs of each temp. Only one def is allowed.
1041 Also, check that each used temp has already been defd. */
sewardj6d2638e2004-07-15 09:38:27 +00001042
1043 for (i = 0; i < n_temps; i++)
1044 def_counts[i] = 0;
1045
sewardjd7cb8532004-08-17 23:59:23 +00001046 for (i = 0; i < bb->stmts_used; i++) {
1047 stmt = bb->stmts[i];
sewardj39e3f242004-08-18 16:54:52 +00001048 if (!stmt)
1049 continue;
sewardj35439212004-07-14 22:36:10 +00001050 useBeforeDef_Stmt(bb,stmt,def_counts);
1051 if (stmt->tag == Ist_Tmp) {
1052 if (stmt->Ist.Tmp.tmp < 0 || stmt->Ist.Tmp.tmp >= n_temps)
1053 sanityCheckFail(bb, stmt, "Invalid temp in Tmp assignment");
1054 def_counts[stmt->Ist.Tmp.tmp]++;
1055 if (def_counts[stmt->Ist.Tmp.tmp] > 1)
1056 sanityCheckFail(bb, stmt, "Tmp assigned more than once");
1057 }
1058 }
1059
sewardj6efd4a12004-07-15 03:54:23 +00001060 /* Typecheck everything. */
sewardjd7cb8532004-08-17 23:59:23 +00001061 for (i = 0; i < bb->stmts_used; i++)
sewardj39e3f242004-08-18 16:54:52 +00001062 if (bb->stmts[i])
1063 tcStmt( bb, bb->stmts[i], guest_word_size );
sewardj6efd4a12004-07-15 03:54:23 +00001064 if (typeOfIRExpr(bb->tyenv,bb->next) != guest_word_size)
1065 sanityCheckFail(bb, NULL, "bb->next field has wrong type");
sewardje539a402004-07-14 18:24:17 +00001066}
1067
sewardj6efd4a12004-07-15 03:54:23 +00001068
sewardje539a402004-07-14 18:24:17 +00001069/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +00001070/*--- end ir/irdefs.c ---*/
sewardj887a11a2004-07-05 17:26:47 +00001071/*---------------------------------------------------------------*/