sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 1 | |
| 2 | /*---------------------------------------------------------------*/ |
| 3 | /*--- ---*/ |
sewardj | c0ee2ed | 2004-07-27 10:29:41 +0000 | [diff] [blame] | 4 | /*--- This file (ir/irdefs.c) is ---*/ |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 5 | /*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/ |
| 6 | /*--- ---*/ |
| 7 | /*---------------------------------------------------------------*/ |
| 8 | |
sewardj | 887a11a | 2004-07-05 17:26:47 +0000 | [diff] [blame] | 9 | #include "libvex_basictypes.h" |
| 10 | #include "libvex_ir.h" |
| 11 | #include "libvex.h" |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 12 | |
sewardj | c0ee2ed | 2004-07-27 10:29:41 +0000 | [diff] [blame] | 13 | #include "main/vex_util.h" |
| 14 | |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 15 | |
| 16 | /*---------------------------------------------------------------*/ |
| 17 | /*--- Printing the IR ---*/ |
| 18 | /*---------------------------------------------------------------*/ |
| 19 | |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 20 | void ppIRType ( IRType ty ) |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 21 | { |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 22 | switch (ty) { |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 23 | 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; |
sewardj | d1725d1 | 2004-08-12 20:46:53 +0000 | [diff] [blame] | 29 | case Ity_F32: vex_printf( "F32"); break; |
| 30 | case Ity_F64: vex_printf( "F64"); break; |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 31 | default: vex_printf("ty = 0x%x\n", (Int)ty); |
| 32 | vpanic("ppIRType"); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 33 | } |
| 34 | } |
| 35 | |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 36 | void ppIRConst ( IRConst* con ) |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 37 | { |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 38 | switch (con->tag) { |
sewardj | 207557a | 2004-08-27 12:00:18 +0000 | [diff] [blame] | 39 | 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; |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 46 | default: vpanic("ppIRConst"); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 47 | } |
| 48 | } |
| 49 | |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 50 | void ppIRTemp ( IRTemp tmp ) |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 51 | { |
sewardj | fbcaf33 | 2004-07-08 01:46:01 +0000 | [diff] [blame] | 52 | if (tmp == INVALID_IRTEMP) |
| 53 | vex_printf("INVALID_IRTEMP"); |
| 54 | else |
sewardj | 41f43bc | 2004-07-08 14:23:22 +0000 | [diff] [blame] | 55 | vex_printf( "t%d", (Int)tmp); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 56 | } |
| 57 | |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 58 | void ppIROp ( IROp op ) |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 59 | { |
sewardj | 41f43bc | 2004-07-08 14:23:22 +0000 | [diff] [blame] | 60 | 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; |
sewardj | e90ad6a | 2004-07-10 19:02:10 +0000 | [diff] [blame] | 81 | 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; |
sewardj | 41f43bc | 2004-07-08 14:23:22 +0000 | [diff] [blame] | 85 | 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;" */ |
sewardj | 9690d92 | 2004-07-14 01:39:17 +0000 | [diff] [blame] | 90 | 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; |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 96 | case Iop_32Sto64: vex_printf("32Sto64"); return; |
sewardj | a238471 | 2004-07-29 14:36:40 +0000 | [diff] [blame] | 97 | case Iop_32to8: vex_printf("32to8"); return; |
sewardj | 9690d92 | 2004-07-14 01:39:17 +0000 | [diff] [blame] | 98 | case Iop_32to1: vex_printf("32to1"); return; |
| 99 | case Iop_1Uto8: vex_printf("1Uto8"); return; |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 100 | case Iop_1Uto32: vex_printf("1Uto32"); return; |
sewardj | 9690d92 | 2004-07-14 01:39:17 +0000 | [diff] [blame] | 101 | |
| 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 | |
sewardj | ce646f2 | 2004-08-31 23:55:54 +0000 | [diff] [blame] | 109 | case Iop_Clz32: vex_printf("Clz32"); return; |
| 110 | case Iop_Ctz32: vex_printf("Ctz32"); return; |
| 111 | |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 112 | 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 | |
sewardj | 9690d92 | 2004-07-14 01:39:17 +0000 | [diff] [blame] | 117 | case Iop_DivModU64to32: vex_printf("DivModU64to32"); return; |
| 118 | case Iop_DivModS64to32: vex_printf("DivModS64to32"); return; |
| 119 | |
sewardj | b81f8b3 | 2004-07-30 10:17:50 +0000 | [diff] [blame] | 120 | case Iop_16HIto8: vex_printf("16HIto8"); return; |
| 121 | case Iop_16to8: vex_printf("16to8"); return; |
| 122 | case Iop_8HLto16: vex_printf("8HLto16"); return; |
| 123 | |
sewardj | 8c7f1ab | 2004-07-29 20:31:09 +0000 | [diff] [blame] | 124 | case Iop_32HIto16: vex_printf("32HIto16"); return; |
| 125 | case Iop_32to16: vex_printf("32to16"); return; |
| 126 | case Iop_16HLto32: vex_printf("16HLto32"); return; |
| 127 | |
sewardj | 9690d92 | 2004-07-14 01:39:17 +0000 | [diff] [blame] | 128 | case Iop_64HIto32: vex_printf("64HIto32"); return; |
sewardj | 8c7f1ab | 2004-07-29 20:31:09 +0000 | [diff] [blame] | 129 | case Iop_64to32: vex_printf("64to32"); return; |
sewardj | 9690d92 | 2004-07-14 01:39:17 +0000 | [diff] [blame] | 130 | case Iop_32HLto64: vex_printf("32HLto64"); return; |
| 131 | |
sewardj | a58ea66 | 2004-08-15 03:12:41 +0000 | [diff] [blame] | 132 | case Iop_AddF64: vex_printf("AddF64"); return; |
sewardj | ce646f2 | 2004-08-31 23:55:54 +0000 | [diff] [blame] | 133 | case Iop_SubF64: vex_printf("SubF64"); return; |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 134 | case Iop_MulF64: vex_printf("MulF64"); return; |
sewardj | ce646f2 | 2004-08-31 23:55:54 +0000 | [diff] [blame] | 135 | case Iop_DivF64: vex_printf("DivF64"); return; |
sewardj | bdc7d21 | 2004-09-09 02:46:40 +0000 | [diff] [blame^] | 136 | case Iop_CmpF64: vex_printf("CmpF64"); return; |
| 137 | |
sewardj | 89cd093 | 2004-09-08 18:23:25 +0000 | [diff] [blame] | 138 | case Iop_I32toF64: vex_printf("I32toF64"); return; |
sewardj | bdc7d21 | 2004-09-09 02:46:40 +0000 | [diff] [blame^] | 139 | case Iop_I64toF64: vex_printf("I64toF64"); return; |
| 140 | |
sewardj | 89cd093 | 2004-09-08 18:23:25 +0000 | [diff] [blame] | 141 | 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; |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 145 | |
sewardj | 9690d92 | 2004-07-14 01:39:17 +0000 | [diff] [blame] | 146 | default: vpanic("ppIROp(1)"); |
sewardj | 41f43bc | 2004-07-08 14:23:22 +0000 | [diff] [blame] | 147 | } |
| 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 | } |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 156 | } |
| 157 | |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 158 | void ppIRExpr ( IRExpr* e ) |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 159 | { |
sewardj | e87b484 | 2004-07-10 12:23:30 +0000 | [diff] [blame] | 160 | Int i; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 161 | switch (e->tag) { |
sewardj | 443cd9d | 2004-07-18 23:06:45 +0000 | [diff] [blame] | 162 | case Iex_Binder: |
| 163 | vex_printf("BIND-%d", e->Iex.Binder.binder); |
| 164 | break; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 165 | case Iex_Get: |
sewardj | fbcaf33 | 2004-07-08 01:46:01 +0000 | [diff] [blame] | 166 | vex_printf( "GET(%d,", e->Iex.Get.offset); |
| 167 | ppIRType(e->Iex.Get.ty); |
| 168 | vex_printf(")"); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 169 | break; |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 170 | 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; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 176 | case Iex_Tmp: |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 177 | ppIRTemp(e->Iex.Tmp.tmp); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 178 | break; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 179 | case Iex_Binop: |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 180 | 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( ")" ); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 186 | break; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 187 | case Iex_Unop: |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 188 | ppIROp(e->Iex.Unop.op); |
| 189 | vex_printf( "(" ); |
| 190 | ppIRExpr(e->Iex.Unop.arg); |
| 191 | vex_printf( ")" ); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 192 | break; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 193 | case Iex_LDle: |
sewardj | e05c42c | 2004-07-08 20:25:10 +0000 | [diff] [blame] | 194 | vex_printf( "LDle:" ); |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 195 | ppIRType(e->Iex.LDle.ty); |
sewardj | e05c42c | 2004-07-08 20:25:10 +0000 | [diff] [blame] | 196 | vex_printf( "(" ); |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 197 | ppIRExpr(e->Iex.LDle.addr); |
| 198 | vex_printf( ")" ); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 199 | break; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 200 | case Iex_Const: |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 201 | ppIRConst(e->Iex.Const.con); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 202 | break; |
sewardj | e87b484 | 2004-07-10 12:23:30 +0000 | [diff] [blame] | 203 | 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; |
sewardj | 4042c7e | 2004-07-18 01:28:30 +0000 | [diff] [blame] | 213 | case Iex_Mux0X: |
| 214 | vex_printf("Mux0X("); |
| 215 | ppIRExpr(e->Iex.Mux0X.cond); |
sewardj | eeb9ef8 | 2004-07-15 12:39:03 +0000 | [diff] [blame] | 216 | vex_printf(","); |
sewardj | 4042c7e | 2004-07-18 01:28:30 +0000 | [diff] [blame] | 217 | ppIRExpr(e->Iex.Mux0X.expr0); |
sewardj | eeb9ef8 | 2004-07-15 12:39:03 +0000 | [diff] [blame] | 218 | vex_printf(","); |
sewardj | 4042c7e | 2004-07-18 01:28:30 +0000 | [diff] [blame] | 219 | ppIRExpr(e->Iex.Mux0X.exprX); |
sewardj | eeb9ef8 | 2004-07-15 12:39:03 +0000 | [diff] [blame] | 220 | vex_printf(")"); |
| 221 | break; |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 222 | default: |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 223 | vpanic("ppIExpr"); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 224 | } |
| 225 | } |
| 226 | |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 227 | void ppIRStmt ( IRStmt* s ) |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 228 | { |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 229 | switch (s->tag) { |
| 230 | case Ist_Put: |
sewardj | eeb9ef8 | 2004-07-15 12:39:03 +0000 | [diff] [blame] | 231 | vex_printf( "PUT(%d) = ", s->Ist.Put.offset); |
| 232 | ppIRExpr(s->Ist.Put.expr); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 233 | break; |
sewardj | d1725d1 | 2004-08-12 20:46:53 +0000 | [diff] [blame] | 234 | 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; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 240 | case Ist_Tmp: |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 241 | ppIRTemp(s->Ist.Tmp.tmp); |
| 242 | vex_printf( " = " ); |
| 243 | ppIRExpr(s->Ist.Tmp.expr); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 244 | break; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 245 | case Ist_STle: |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 246 | vex_printf( "STle("); |
| 247 | ppIRExpr(s->Ist.STle.addr); |
| 248 | vex_printf( ") = "); |
| 249 | ppIRExpr(s->Ist.STle.data); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 250 | break; |
sewardj | 64e1d65 | 2004-07-12 14:00:46 +0000 | [diff] [blame] | 251 | 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; |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 257 | default: |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 258 | vpanic("ppIRStmt"); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 259 | } |
| 260 | } |
| 261 | |
sewardj | 78c19df | 2004-07-12 22:49:27 +0000 | [diff] [blame] | 262 | void 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 | |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 275 | void ppIRTypeEnv ( IRTypeEnv* env ) { |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 276 | UInt i; |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 277 | for (i = 0; i < env->types_used; i++) { |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 278 | if (i % 8 == 0) |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 279 | vex_printf( " "); |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 280 | ppIRTemp(i); |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 281 | vex_printf( ":"); |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 282 | ppIRType(env->types[i]); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 283 | if (i % 8 == 7) |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 284 | vex_printf( "\n"); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 285 | else |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 286 | vex_printf( " "); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 287 | } |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 288 | if (env->types_used > 0 && env->types_used % 8 != 7) |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 289 | vex_printf( "\n"); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 290 | } |
| 291 | |
| 292 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 293 | |
| 294 | |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 295 | void ppIRBB ( IRBB* bb ) |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 296 | { |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 297 | Int i; |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 298 | vex_printf("IRBB {\n"); |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 299 | ppIRTypeEnv(bb->tyenv); |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 300 | vex_printf("\n"); |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 301 | for (i = 0; i < bb->stmts_used; i++) { |
sewardj | 39e3f24 | 2004-08-18 16:54:52 +0000 | [diff] [blame] | 302 | if (bb->stmts[i]) { |
| 303 | vex_printf( " "); |
| 304 | ppIRStmt(bb->stmts[i]); |
| 305 | } |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 306 | vex_printf( "\n"); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 307 | } |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 308 | vex_printf( " goto {"); |
| 309 | ppIRJumpKind(bb->jumpkind); |
| 310 | vex_printf( "} "); |
| 311 | ppIRExpr( bb->next ); |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 312 | vex_printf( "\n}\n"); |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 313 | } |
| 314 | |
| 315 | |
| 316 | /*---------------------------------------------------------------*/ |
| 317 | /*--- Constructors ---*/ |
| 318 | /*---------------------------------------------------------------*/ |
| 319 | |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 320 | |
| 321 | /* Constructors -- IRConst */ |
| 322 | |
sewardj | b8e7586 | 2004-08-19 17:58:45 +0000 | [diff] [blame] | 323 | IRConst* 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 | } |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 330 | IRConst* IRConst_U8 ( UChar u8 ) |
| 331 | { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 332 | IRConst* c = LibVEX_Alloc(sizeof(IRConst)); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 333 | c->tag = Ico_U8; |
| 334 | c->Ico.U8 = u8; |
| 335 | return c; |
| 336 | } |
| 337 | IRConst* IRConst_U16 ( UShort u16 ) |
| 338 | { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 339 | IRConst* c = LibVEX_Alloc(sizeof(IRConst)); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 340 | c->tag = Ico_U16; |
| 341 | c->Ico.U16 = u16; |
| 342 | return c; |
| 343 | } |
| 344 | IRConst* IRConst_U32 ( UInt u32 ) |
| 345 | { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 346 | IRConst* c = LibVEX_Alloc(sizeof(IRConst)); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 347 | c->tag = Ico_U32; |
| 348 | c->Ico.U32 = u32; |
| 349 | return c; |
| 350 | } |
| 351 | IRConst* IRConst_U64 ( ULong u64 ) |
| 352 | { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 353 | IRConst* c = LibVEX_Alloc(sizeof(IRConst)); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 354 | c->tag = Ico_U64; |
| 355 | c->Ico.U64 = u64; |
| 356 | return c; |
| 357 | } |
sewardj | a58ea66 | 2004-08-15 03:12:41 +0000 | [diff] [blame] | 358 | IRConst* 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 | } |
sewardj | 207557a | 2004-08-27 12:00:18 +0000 | [diff] [blame] | 365 | IRConst* IRConst_NaN64 ( void ) |
| 366 | { |
| 367 | IRConst* c = LibVEX_Alloc(sizeof(IRConst)); |
| 368 | c->tag = Ico_NaN64; |
| 369 | return c; |
| 370 | } |
| 371 | |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 372 | |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 373 | /* Constructors -- IRExpr */ |
| 374 | |
sewardj | 443cd9d | 2004-07-18 23:06:45 +0000 | [diff] [blame] | 375 | IRExpr* 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 | } |
sewardj | fbcaf33 | 2004-07-08 01:46:01 +0000 | [diff] [blame] | 381 | IRExpr* IRExpr_Get ( Int off, IRType ty ) { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 382 | IRExpr* e = LibVEX_Alloc(sizeof(IRExpr)); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 383 | e->tag = Iex_Get; |
| 384 | e->Iex.Get.offset = off; |
sewardj | fbcaf33 | 2004-07-08 01:46:01 +0000 | [diff] [blame] | 385 | e->Iex.Get.ty = ty; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 386 | return e; |
| 387 | } |
sewardj | d1725d1 | 2004-08-12 20:46:53 +0000 | [diff] [blame] | 388 | IRExpr* 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 | } |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 398 | IRExpr* IRExpr_Tmp ( IRTemp tmp ) { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 399 | IRExpr* e = LibVEX_Alloc(sizeof(IRExpr)); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 400 | e->tag = Iex_Tmp; |
| 401 | e->Iex.Tmp.tmp = tmp; |
| 402 | return e; |
| 403 | } |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 404 | IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 ) { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 405 | IRExpr* e = LibVEX_Alloc(sizeof(IRExpr)); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 406 | 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 | } |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 412 | IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg ) { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 413 | IRExpr* e = LibVEX_Alloc(sizeof(IRExpr)); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 414 | e->tag = Iex_Unop; |
| 415 | e->Iex.Unop.op = op; |
| 416 | e->Iex.Unop.arg = arg; |
| 417 | return e; |
| 418 | } |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 419 | IRExpr* IRExpr_LDle ( IRType ty, IRExpr* addr ) { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 420 | IRExpr* e = LibVEX_Alloc(sizeof(IRExpr)); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 421 | e->tag = Iex_LDle; |
| 422 | e->Iex.LDle.ty = ty; |
| 423 | e->Iex.LDle.addr = addr; |
| 424 | return e; |
| 425 | } |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 426 | IRExpr* IRExpr_Const ( IRConst* con ) { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 427 | IRExpr* e = LibVEX_Alloc(sizeof(IRExpr)); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 428 | e->tag = Iex_Const; |
| 429 | e->Iex.Const.con = con; |
| 430 | return e; |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 431 | } |
sewardj | e87b484 | 2004-07-10 12:23:30 +0000 | [diff] [blame] | 432 | IRExpr* 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 | } |
sewardj | 4042c7e | 2004-07-18 01:28:30 +0000 | [diff] [blame] | 440 | IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX ) { |
sewardj | eeb9ef8 | 2004-07-15 12:39:03 +0000 | [diff] [blame] | 441 | IRExpr* e = LibVEX_Alloc(sizeof(IRExpr)); |
sewardj | 4042c7e | 2004-07-18 01:28:30 +0000 | [diff] [blame] | 442 | e->tag = Iex_Mux0X; |
| 443 | e->Iex.Mux0X.cond = cond; |
| 444 | e->Iex.Mux0X.expr0 = expr0; |
| 445 | e->Iex.Mux0X.exprX = exprX; |
sewardj | eeb9ef8 | 2004-07-15 12:39:03 +0000 | [diff] [blame] | 446 | return e; |
| 447 | } |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 448 | |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 449 | |
| 450 | /* Constructors -- IRStmt */ |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 451 | |
sewardj | eeb9ef8 | 2004-07-15 12:39:03 +0000 | [diff] [blame] | 452 | IRStmt* IRStmt_Put ( Int off, IRExpr* value ) { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 453 | IRStmt* s = LibVEX_Alloc(sizeof(IRStmt)); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 454 | s->tag = Ist_Put; |
| 455 | s->Ist.Put.offset = off; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 456 | s->Ist.Put.expr = value; |
| 457 | return s; |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 458 | } |
sewardj | d1725d1 | 2004-08-12 20:46:53 +0000 | [diff] [blame] | 459 | IRStmt* IRStmt_PutI ( IRExpr* off, IRExpr* value, |
| 460 | UShort minoff, UShort maxoff ) { |
| 461 | IRStmt* s = LibVEX_Alloc(sizeof(IRStmt)); |
| 462 | s->tag = Ist_PutI; |
sewardj | d1725d1 | 2004-08-12 20:46:53 +0000 | [diff] [blame] | 463 | 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 | } |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 469 | IRStmt* IRStmt_Tmp ( IRTemp tmp, IRExpr* expr ) { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 470 | IRStmt* s = LibVEX_Alloc(sizeof(IRStmt)); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 471 | s->tag = Ist_Tmp; |
| 472 | s->Ist.Tmp.tmp = tmp; |
| 473 | s->Ist.Tmp.expr = expr; |
| 474 | return s; |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 475 | } |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 476 | IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* value ) { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 477 | IRStmt* s = LibVEX_Alloc(sizeof(IRStmt)); |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 478 | s->tag = Ist_STle; |
| 479 | s->Ist.STle.addr = addr; |
| 480 | s->Ist.STle.data = value; |
| 481 | return s; |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 482 | } |
sewardj | 64e1d65 | 2004-07-12 14:00:46 +0000 | [diff] [blame] | 483 | IRStmt* IRStmt_Exit ( IRExpr* cond, IRConst* dst ) { |
| 484 | IRStmt* s = LibVEX_Alloc(sizeof(IRStmt)); |
| 485 | s->tag = Ist_Exit; |
sewardj | 64e1d65 | 2004-07-12 14:00:46 +0000 | [diff] [blame] | 486 | s->Ist.Exit.cond = cond; |
| 487 | s->Ist.Exit.dst = dst; |
| 488 | return s; |
| 489 | } |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 490 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 491 | /* Constructors -- IRBB (sort of) */ |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 492 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 493 | IRBB* 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; |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 502 | return bb; |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 503 | } |
| 504 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 505 | void 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 | |
sewardj | ec6ad59 | 2004-06-20 12:26:53 +0000 | [diff] [blame] | 520 | |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 521 | /*---------------------------------------------------------------*/ |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 522 | /*--- Primop types ---*/ |
| 523 | /*---------------------------------------------------------------*/ |
| 524 | |
| 525 | static |
| 526 | void 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) { |
sewardj | 66de227 | 2004-07-16 21:19:05 +0000 | [diff] [blame] | 539 | case Iop_Add8: case Iop_Sub8: //case Iop_Adc8: case Iop_Sbb8: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 540 | case Iop_Mul8: case Iop_Or8: case Iop_And8: case Iop_Xor8: |
| 541 | BINARY(Ity_I8,Ity_I8,Ity_I8); |
| 542 | |
sewardj | 66de227 | 2004-07-16 21:19:05 +0000 | [diff] [blame] | 543 | case Iop_Add16: case Iop_Sub16: //case Iop_Adc16: case Iop_Sbb16: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 544 | case Iop_Mul16: case Iop_Or16: case Iop_And16: case Iop_Xor16: |
| 545 | BINARY(Ity_I16,Ity_I16,Ity_I16); |
| 546 | |
sewardj | 66de227 | 2004-07-16 21:19:05 +0000 | [diff] [blame] | 547 | case Iop_Add32: case Iop_Sub32: //case Iop_Adc32: case Iop_Sbb32: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 548 | case Iop_Mul32: case Iop_Or32: case Iop_And32: case Iop_Xor32: |
| 549 | BINARY(Ity_I32,Ity_I32,Ity_I32); |
| 550 | |
sewardj | 66de227 | 2004-07-16 21:19:05 +0000 | [diff] [blame] | 551 | case Iop_Add64: case Iop_Sub64: //case Iop_Adc64: case Iop_Sbb64: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 552 | 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: |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 578 | case Iop_CmpLT32S: |
| 579 | case Iop_CmpLE32S: |
| 580 | case Iop_CmpLT32U: |
| 581 | case Iop_CmpLE32U: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 582 | COMPARISON(Ity_I32); |
| 583 | case Iop_CmpEQ64: case Iop_CmpNE64: |
| 584 | COMPARISON(Ity_I64); |
| 585 | |
sewardj | b81f8b3 | 2004-07-30 10:17:50 +0000 | [diff] [blame] | 586 | 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); |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 590 | case Iop_MullU32: case Iop_MullS32: |
| 591 | BINARY(Ity_I64,Ity_I32,Ity_I32); |
| 592 | |
sewardj | ce646f2 | 2004-08-31 23:55:54 +0000 | [diff] [blame] | 593 | case Iop_Clz32: |
| 594 | case Iop_Ctz32: |
| 595 | UNARY(Ity_I32,Ity_I32); |
| 596 | |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 597 | case Iop_DivModU64to32: |
sewardj | 0255207 | 2004-07-28 07:13:38 +0000 | [diff] [blame] | 598 | case Iop_DivModS64to32: |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 599 | BINARY(Ity_I64,Ity_I64,Ity_I32); |
| 600 | |
sewardj | b81f8b3 | 2004-07-30 10:17:50 +0000 | [diff] [blame] | 601 | 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 | |
sewardj | 8c7f1ab | 2004-07-29 20:31:09 +0000 | [diff] [blame] | 606 | 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: |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 612 | 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); |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 617 | case Iop_1Uto32: UNARY(Ity_I32,Ity_Bit); |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 618 | case Iop_32to1: UNARY(Ity_Bit,Ity_I32); |
| 619 | case Iop_8Uto32: UNARY(Ity_I32,Ity_I8); |
sewardj | c22a6fd | 2004-07-29 23:41:47 +0000 | [diff] [blame] | 620 | case Iop_8Sto32: UNARY(Ity_I32,Ity_I8); |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 621 | case Iop_16Uto32: UNARY(Ity_I32,Ity_I16); |
sewardj | c22a6fd | 2004-07-29 23:41:47 +0000 | [diff] [blame] | 622 | case Iop_16Sto32: UNARY(Ity_I32,Ity_I16); |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 623 | case Iop_32Sto64: UNARY(Ity_I64,Ity_I32); |
sewardj | a238471 | 2004-07-29 14:36:40 +0000 | [diff] [blame] | 624 | case Iop_32to8: UNARY(Ity_I8,Ity_I32); |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 625 | |
sewardj | ce646f2 | 2004-08-31 23:55:54 +0000 | [diff] [blame] | 626 | case Iop_AddF64: case Iop_SubF64: |
| 627 | case Iop_MulF64: case Iop_DivF64: |
sewardj | a58ea66 | 2004-08-15 03:12:41 +0000 | [diff] [blame] | 628 | BINARY(Ity_F64,Ity_F64,Ity_F64); |
sewardj | bdc7d21 | 2004-09-09 02:46:40 +0000 | [diff] [blame^] | 629 | case Iop_CmpF64: |
| 630 | BINARY(Ity_I32,Ity_F64,Ity_F64); |
sewardj | 8f3debf | 2004-09-08 23:42:23 +0000 | [diff] [blame] | 631 | |
sewardj | 89cd093 | 2004-09-08 18:23:25 +0000 | [diff] [blame] | 632 | case Iop_I32toF64: UNARY(Ity_F64,Ity_I32); |
sewardj | bdc7d21 | 2004-09-09 02:46:40 +0000 | [diff] [blame^] | 633 | case Iop_I64toF64: UNARY(Ity_F64,Ity_I64); |
sewardj | 8f3debf | 2004-09-08 23:42:23 +0000 | [diff] [blame] | 634 | |
| 635 | case Iop_F64toI32: BINARY(Ity_I32, Ity_I32,Ity_F64); |
| 636 | case Iop_F64toI16: BINARY(Ity_I16, Ity_I32,Ity_F64); |
| 637 | |
sewardj | 89cd093 | 2004-09-08 18:23:25 +0000 | [diff] [blame] | 638 | case Iop_F32toF64: UNARY(Ity_F64,Ity_F32); |
| 639 | case Iop_F64toF32: UNARY(Ity_F32,Ity_F64); |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 640 | |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 641 | default: |
| 642 | ppIROp(op); |
| 643 | vpanic("typeOfPrimop"); |
| 644 | } |
| 645 | # undef UNARY |
| 646 | # undef BINARY |
| 647 | # undef COMPARISON |
| 648 | } |
| 649 | |
| 650 | |
| 651 | /*---------------------------------------------------------------*/ |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 652 | /*--- Helper functions for the IR -- IR Type Environments ---*/ |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 653 | /*---------------------------------------------------------------*/ |
| 654 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 655 | /* Make a new, empty IRTypeEnv. */ |
| 656 | |
| 657 | IRTypeEnv* emptyIRTypeEnv ( void ) |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 658 | { |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 659 | IRTypeEnv* env = LibVEX_Alloc(sizeof(IRTypeEnv)); |
| 660 | env->types = LibVEX_Alloc(8 * sizeof(IRType)); |
| 661 | env->types_size = 8; |
| 662 | env->types_used = 0; |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 663 | return env; |
| 664 | } |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 665 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 666 | /* 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 | |
| 669 | IRTypeEnv* 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. */ |
sewardj | e3d0d2e | 2004-06-27 10:42:44 +0000 | [diff] [blame] | 682 | |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 683 | IRTemp newIRTemp ( IRTypeEnv* env, IRType ty ) |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 684 | { |
sewardj | 35421a3 | 2004-07-05 13:12:34 +0000 | [diff] [blame] | 685 | vassert(env); |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 686 | 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++; |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 692 | } else { |
| 693 | Int i; |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 694 | 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); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 702 | } |
| 703 | } |
| 704 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 705 | /* Find the type of a temporary previously allocated in an |
| 706 | environment. */ |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 707 | |
| 708 | IRType lookupIRTypeEnv ( IRTypeEnv* env, IRTemp tmp ) |
| 709 | { |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 710 | vassert(tmp >= 0); |
| 711 | vassert(tmp < env->types_used); |
| 712 | return env->types[tmp]; |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 713 | } |
| 714 | |
| 715 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 716 | /*---------------------------------------------------------------*/ |
| 717 | /*--- Helper functions for the IR -- finding types of exprs ---*/ |
| 718 | /*---------------------------------------------------------------*/ |
| 719 | |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 720 | IRType typeOfIRConst ( IRConst* con ) |
| 721 | { |
| 722 | switch (con->tag) { |
sewardj | 207557a | 2004-08-27 12:00:18 +0000 | [diff] [blame] | 723 | 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; |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 730 | default: vpanic("typeOfIRConst"); |
| 731 | } |
| 732 | } |
| 733 | |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 734 | IRType typeOfIRExpr ( IRTypeEnv* tyenv, IRExpr* e ) |
| 735 | { |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 736 | IRType t_dst, t_arg1, t_arg2; |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 737 | switch (e->tag) { |
sewardj | e05c42c | 2004-07-08 20:25:10 +0000 | [diff] [blame] | 738 | case Iex_LDle: |
| 739 | return e->Iex.LDle.ty; |
sewardj | fbcaf33 | 2004-07-08 01:46:01 +0000 | [diff] [blame] | 740 | case Iex_Get: |
| 741 | return e->Iex.Get.ty; |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 742 | case Iex_GetI: |
| 743 | return e->Iex.GetI.ty; |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 744 | case Iex_Tmp: |
| 745 | return lookupIRTypeEnv(tyenv, e->Iex.Tmp.tmp); |
| 746 | case Iex_Const: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 747 | return typeOfIRConst(e->Iex.Const.con); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 748 | case Iex_Binop: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 749 | 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; |
sewardj | 4042c7e | 2004-07-18 01:28:30 +0000 | [diff] [blame] | 756 | case Iex_Mux0X: |
| 757 | return typeOfIRExpr(tyenv, e->Iex.Mux0X.expr0); |
sewardj | 443cd9d | 2004-07-18 23:06:45 +0000 | [diff] [blame] | 758 | case Iex_Binder: |
| 759 | vpanic("typeOfIRExpr: Binder is not a valid expression"); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 760 | default: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 761 | ppIRExpr(e); |
| 762 | vpanic("typeOfIRExpr"); |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 763 | } |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 764 | } |
sewardj | 887a11a | 2004-07-05 17:26:47 +0000 | [diff] [blame] | 765 | |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 766 | /* Is this any value actually in the enumeration 'IRType' ? */ |
| 767 | Bool 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: |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 772 | case Ity_F32: case Ity_F64: |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 773 | return True; |
| 774 | default: |
| 775 | return False; |
| 776 | } |
| 777 | } |
| 778 | |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 779 | |
sewardj | 887a11a | 2004-07-05 17:26:47 +0000 | [diff] [blame] | 780 | /*---------------------------------------------------------------*/ |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 781 | /*--- Sanity checking ---*/ |
| 782 | /*---------------------------------------------------------------*/ |
| 783 | |
| 784 | /* Checks: |
| 785 | |
| 786 | Everything is type-consistent. No ill-typed anything. |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 787 | The target address at the end of the BB is a 32- or 64- |
| 788 | bit expression, depending on the guest's word size. |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 789 | |
| 790 | Each temp is assigned only once, before its uses. |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 791 | */ |
| 792 | |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 793 | static |
| 794 | __attribute((noreturn)) |
| 795 | void sanityCheckFail ( IRBB* bb, IRStmt* stmt, Char* what ) |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 796 | { |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 797 | 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 | |
| 812 | static |
| 813 | void 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; |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 819 | case Iex_GetI: |
| 820 | useBeforeDef_Expr(bb,stmt,expr->Iex.GetI.offset,def_counts); |
| 821 | break; |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 822 | 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) |
sewardj | 39e3f24 | 2004-08-18 16:54:52 +0000 | [diff] [blame] | 826 | sanityCheckFail(bb,stmt, "IRTemp use before def in IRExpr"); |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 827 | 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; |
sewardj | 4042c7e | 2004-07-18 01:28:30 +0000 | [diff] [blame] | 844 | 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); |
sewardj | eeb9ef8 | 2004-07-15 12:39:03 +0000 | [diff] [blame] | 848 | break; |
| 849 | default: |
| 850 | vpanic("useBeforeDef_Expr"); |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 851 | } |
| 852 | } |
| 853 | |
| 854 | static |
| 855 | void useBeforeDef_Stmt ( IRBB* bb, IRStmt* stmt, Int* def_counts ) |
| 856 | { |
| 857 | switch (stmt->tag) { |
| 858 | case Ist_Put: |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 859 | useBeforeDef_Expr(bb,stmt,stmt->Ist.Put.expr,def_counts); |
| 860 | break; |
sewardj | d1725d1 | 2004-08-12 20:46:53 +0000 | [diff] [blame] | 861 | 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; |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 865 | 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 | |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 880 | static |
| 881 | void 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; |
sewardj | bb53f8c | 2004-08-14 11:50:01 +0000 | [diff] [blame] | 890 | 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; |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 895 | case Iex_Binop: { |
| 896 | IRType ttarg1, ttarg2; |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 897 | 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); |
sewardj | 8f3debf | 2004-09-08 23:42:23 +0000 | [diff] [blame] | 900 | 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 | } |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 908 | 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 | } |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 929 | break; |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 930 | } |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 931 | 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; |
sewardj | 4042c7e | 2004-07-18 01:28:30 +0000 | [diff] [blame] | 955 | 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"); |
sewardj | eeb9ef8 | 2004-07-15 12:39:03 +0000 | [diff] [blame] | 964 | break; |
| 965 | default: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 966 | vpanic("tcExpr"); |
| 967 | } |
| 968 | } |
| 969 | |
| 970 | |
| 971 | static |
| 972 | void tcStmt ( IRBB* bb, IRStmt* stmt, IRType gWordTy ) |
| 973 | { |
| 974 | IRTypeEnv* tyenv = bb->tyenv; |
| 975 | switch (stmt->tag) { |
| 976 | case Ist_Put: |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 977 | 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; |
sewardj | d1725d1 | 2004-08-12 20:46:53 +0000 | [diff] [blame] | 981 | 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; |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 989 | 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)) |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 993 | sanityCheckFail(bb,stmt,"IRStmt.Put.Tmp: tmp and expr do not match"); |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 994 | 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 | |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 1015 | void 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 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 1025 | 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 | |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 1030 | /* 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 | } |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 1039 | |
| 1040 | /* Count the defs of each temp. Only one def is allowed. |
| 1041 | Also, check that each used temp has already been defd. */ |
sewardj | 6d2638e | 2004-07-15 09:38:27 +0000 | [diff] [blame] | 1042 | |
| 1043 | for (i = 0; i < n_temps; i++) |
| 1044 | def_counts[i] = 0; |
| 1045 | |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 1046 | for (i = 0; i < bb->stmts_used; i++) { |
| 1047 | stmt = bb->stmts[i]; |
sewardj | 39e3f24 | 2004-08-18 16:54:52 +0000 | [diff] [blame] | 1048 | if (!stmt) |
| 1049 | continue; |
sewardj | 3543921 | 2004-07-14 22:36:10 +0000 | [diff] [blame] | 1050 | 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 | |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 1060 | /* Typecheck everything. */ |
sewardj | d7cb853 | 2004-08-17 23:59:23 +0000 | [diff] [blame] | 1061 | for (i = 0; i < bb->stmts_used; i++) |
sewardj | 39e3f24 | 2004-08-18 16:54:52 +0000 | [diff] [blame] | 1062 | if (bb->stmts[i]) |
| 1063 | tcStmt( bb, bb->stmts[i], guest_word_size ); |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 1064 | if (typeOfIRExpr(bb->tyenv,bb->next) != guest_word_size) |
| 1065 | sanityCheckFail(bb, NULL, "bb->next field has wrong type"); |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 1066 | } |
| 1067 | |
sewardj | 6efd4a1 | 2004-07-15 03:54:23 +0000 | [diff] [blame] | 1068 | |
sewardj | e539a40 | 2004-07-14 18:24:17 +0000 | [diff] [blame] | 1069 | /*---------------------------------------------------------------*/ |
sewardj | c0ee2ed | 2004-07-27 10:29:41 +0000 | [diff] [blame] | 1070 | /*--- end ir/irdefs.c ---*/ |
sewardj | 887a11a | 2004-07-05 17:26:47 +0000 | [diff] [blame] | 1071 | /*---------------------------------------------------------------*/ |