blob: 0b7e0871bc4180123e00cc93df4c1541ad5cf5ce [file] [log] [blame]
sewardjec6ad592004-06-20 12:26:53 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
sewardj887a11a2004-07-05 17:26:47 +00004/*--- This file (libvex_ir.h) 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#ifndef __LIBVEX_IR_H
10#define __LIBVEX_IR_H
sewardjac9af022004-07-05 01:15:34 +000011
sewardj887a11a2004-07-05 17:26:47 +000012#include "libvex_basictypes.h"
sewardjec6ad592004-06-20 12:26:53 +000013
sewardjec6ad592004-06-20 12:26:53 +000014
15/*---------------------------------------------------------------*/
sewardjac6b7122004-06-27 01:03:57 +000016/*--- Type definitions for the IR ---*/
sewardjec6ad592004-06-20 12:26:53 +000017/*---------------------------------------------------------------*/
18
sewardjc97096c2004-06-30 09:28:04 +000019/* ------------------ Types ------------------ */
sewardje3d0d2e2004-06-27 10:42:44 +000020
21typedef
sewardj6efd4a12004-07-15 03:54:23 +000022 enum { Ity_INVALID=0x10FFF,
23 Ity_Bit=0x11000,
sewardjd1725d12004-08-12 20:46:53 +000024 Ity_I8, Ity_I16, Ity_I32, Ity_I64,
25 Ity_F32, Ity_F64
26 }
sewardje3d0d2e2004-06-27 10:42:44 +000027 IRType;
28
sewardj35421a32004-07-05 13:12:34 +000029extern void ppIRType ( IRType );
sewardj2d3f77c2004-09-22 23:49:09 +000030extern Int sizeofIRType ( IRType );
sewardje3d0d2e2004-06-27 10:42:44 +000031
sewardjc97096c2004-06-30 09:28:04 +000032
33/* ------------------ Constants ------------------ */
sewardjec6ad592004-06-20 12:26:53 +000034
sewardjac6b7122004-06-27 01:03:57 +000035typedef
sewardj51cba892004-08-20 00:09:03 +000036 enum { Ico_Bit=0x12000,
sewardj17442fe2004-09-20 14:54:28 +000037 Ico_U8, Ico_U16, Ico_U32, Ico_U64,
38 Ico_F64, /* 64-bit IEEE754 floating */
39 Ico_F64i /* 64-bit unsigned int to be interpreted literally
40 as a IEEE754 double value. */
sewardj207557a2004-08-27 12:00:18 +000041 }
sewardjac6b7122004-06-27 01:03:57 +000042 IRConstTag;
43
44typedef
sewardje3d0d2e2004-06-27 10:42:44 +000045 struct _IRConst {
sewardjac6b7122004-06-27 01:03:57 +000046 IRConstTag tag;
47 union {
sewardj51cba892004-08-20 00:09:03 +000048 Bool Bit;
sewardjc97096c2004-06-30 09:28:04 +000049 UChar U8;
50 UShort U16;
51 UInt U32;
52 ULong U64;
sewardja58ea662004-08-15 03:12:41 +000053 Double F64;
sewardj17442fe2004-09-20 14:54:28 +000054 ULong F64i;
sewardjac6b7122004-06-27 01:03:57 +000055 } Ico;
56 }
57 IRConst;
sewardjec6ad592004-06-20 12:26:53 +000058
sewardj17442fe2004-09-20 14:54:28 +000059extern IRConst* IRConst_Bit ( Bool );
60extern IRConst* IRConst_U8 ( UChar );
61extern IRConst* IRConst_U16 ( UShort );
62extern IRConst* IRConst_U32 ( UInt );
63extern IRConst* IRConst_U64 ( ULong );
64extern IRConst* IRConst_F64 ( Double );
65extern IRConst* IRConst_F64i ( ULong );
sewardjec6ad592004-06-20 12:26:53 +000066
sewardj695cff92004-10-13 14:50:14 +000067extern IRConst* dopyIRConst ( IRConst* );
68
sewardj35421a32004-07-05 13:12:34 +000069extern void ppIRConst ( IRConst* );
sewardj4345f7a2004-09-22 19:49:27 +000070extern Bool eqIRConst ( IRConst*, IRConst* );
sewardjc97096c2004-06-30 09:28:04 +000071
72
sewardj8ea867b2004-10-30 19:03:02 +000073/* ------------------ Call targets ------------------ */
74
75/* Describes a helper function to call. The name part is purely for
sewardj77352542004-10-30 20:39:01 +000076 pretty printing and not actually used. regparms=n tells the back
sewardj8ea867b2004-10-30 19:03:02 +000077 end that the callee has been declared
78 "__attribute__((regparm(n)))". On some targets (x86) the back end
79 will need to construct a non-standard sequence to call a function
80 declared like this. */
81
82typedef
83 struct {
sewardj77352542004-10-30 20:39:01 +000084 Int regparms;
sewardj8ea867b2004-10-30 19:03:02 +000085 Char* name;
86 HWord addr;
87 }
88 IRCallee;
89
sewardj77352542004-10-30 20:39:01 +000090extern IRCallee* mkIRCallee ( Int regparms, Char* name, HWord addr );
sewardj8ea867b2004-10-30 19:03:02 +000091
92extern IRCallee* dopyIRCallee ( IRCallee* );
93
94extern void ppIRCallee ( IRCallee* );
95
96
sewardj2d3f77c2004-09-22 23:49:09 +000097/* ------------------ Guest state arrays ------------------ */
98
99typedef
100 struct {
101 Int base;
102 IRType elemTy;
103 Int nElems;
104 }
105 IRArray;
106
107extern IRArray* mkIRArray ( Int, IRType, Int );
108
sewardj695cff92004-10-13 14:50:14 +0000109extern IRArray* dopyIRArray ( IRArray* );
110
sewardj2d3f77c2004-09-22 23:49:09 +0000111extern void ppIRArray ( IRArray* );
sewardje98dcf22004-10-04 09:15:11 +0000112extern Bool eqIRArray ( IRArray*, IRArray* );
sewardj2d3f77c2004-09-22 23:49:09 +0000113
114
sewardjc97096c2004-06-30 09:28:04 +0000115/* ------------------ Temporaries ------------------ */
sewardjec6ad592004-06-20 12:26:53 +0000116
sewardj1c192762004-10-14 00:28:15 +0000117/* The IR optimiser relies on the fact that IRTemps are 32-bit
118 ints. Do not change them to be ints of any other size. */
sewardjfbcaf332004-07-08 01:46:01 +0000119typedef UInt IRTemp;
sewardjec6ad592004-06-20 12:26:53 +0000120
sewardj35421a32004-07-05 13:12:34 +0000121extern void ppIRTemp ( IRTemp );
sewardjec6ad592004-06-20 12:26:53 +0000122
sewardjfbcaf332004-07-08 01:46:01 +0000123#define INVALID_IRTEMP ((IRTemp)0xFFFFFFFF)
124
sewardjc97096c2004-06-30 09:28:04 +0000125
126/* ------------------ Binary and unary ops ------------------ */
sewardjec6ad592004-06-20 12:26:53 +0000127
sewardjac6b7122004-06-27 01:03:57 +0000128typedef
sewardj41f43bc2004-07-08 14:23:22 +0000129 enum {
130 /* Do not change this ordering. The IR generators
131 rely on (eg) Iop_Add64 == IopAdd8 + 3. */
sewardj66de2272004-07-16 21:19:05 +0000132 Iop_INVALID=0x13000,
133 Iop_Add8, Iop_Add16, Iop_Add32, Iop_Add64,
sewardj41f43bc2004-07-08 14:23:22 +0000134 Iop_Sub8, Iop_Sub16, Iop_Sub32, Iop_Sub64,
sewardj41f43bc2004-07-08 14:23:22 +0000135 /* Signless mul. MullS/MullU is elsewhere. */
136 Iop_Mul8, Iop_Mul16, Iop_Mul32, Iop_Mul64,
137 Iop_Or8, Iop_Or16, Iop_Or32, Iop_Or64,
138 Iop_And8, Iop_And16, Iop_And32, Iop_And64,
139 Iop_Xor8, Iop_Xor16, Iop_Xor32, Iop_Xor64,
140 Iop_Shl8, Iop_Shl16, Iop_Shl32, Iop_Shl64,
141 Iop_Shr8, Iop_Shr16, Iop_Shr32, Iop_Shr64,
142 Iop_Sar8, Iop_Sar16, Iop_Sar32, Iop_Sar64,
sewardje90ad6a2004-07-10 19:02:10 +0000143 /* Integer comparisons. */
144 Iop_CmpEQ8, Iop_CmpEQ16, Iop_CmpEQ32, Iop_CmpEQ64,
145 Iop_CmpNE8, Iop_CmpNE16, Iop_CmpNE32, Iop_CmpNE64,
sewardj41f43bc2004-07-08 14:23:22 +0000146 /* Tags for unary ops */
147 Iop_Not8, Iop_Not16, Iop_Not32, Iop_Not64,
sewardje87b4842004-07-10 12:23:30 +0000148 Iop_Neg8, Iop_Neg16, Iop_Neg32, Iop_Neg64,
sewardj9690d922004-07-14 01:39:17 +0000149 /* Widening multiplies */
150 Iop_MullS8, Iop_MullS16, Iop_MullS32,
151 Iop_MullU8, Iop_MullU16, Iop_MullU32,
sewardj8f3debf2004-09-08 23:42:23 +0000152
sewardjce646f22004-08-31 23:55:54 +0000153 /* Wierdo integer stuff */
154 Iop_Clz32, /* count leading zeroes */
155 Iop_Ctz32, /* count trailing zeros */
sewardj8f3debf2004-09-08 23:42:23 +0000156 /* Ctz32/Clz32 are UNDEFINED when given arguments of zero.
157 You must ensure they are never given a zero argument.
158 */
159
sewardj9690d922004-07-14 01:39:17 +0000160 /* Ordering not important after here. */
sewardj84ff0652004-08-23 16:16:08 +0000161 Iop_CmpLT32S,
162 Iop_CmpLE32S,
163 Iop_CmpLT32U,
164 Iop_CmpLE32U,
sewardj9690d922004-07-14 01:39:17 +0000165 /* Division */
sewardj8f3debf2004-09-08 23:42:23 +0000166 /* TODO: clarify semantics wrt rounding, negative values, whatever */
sewardj9690d922004-07-14 01:39:17 +0000167 Iop_DivModU64to32, // :: I64,I32 -> I64
168 // of which lo half is div and hi half is mod
169 Iop_DivModS64to32, // ditto, signed
sewardj89d4e982004-09-12 19:14:46 +0000170
sewardj9690d922004-07-14 01:39:17 +0000171 /* Widening conversions */
sewardje5427e82004-09-11 19:43:51 +0000172 Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, Iop_32Uto64,
sewardjbb53f8c2004-08-14 11:50:01 +0000173 Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, Iop_32Sto64,
sewardja2384712004-07-29 14:36:40 +0000174 /* Narrowing conversions */
sewardj8c7f1ab2004-07-29 20:31:09 +0000175 Iop_32to8,
sewardjb81f8b32004-07-30 10:17:50 +0000176 /* 8 <-> 16 bit conversions */
177 Iop_16to8, // :: I16 -> I8, low half
178 Iop_16HIto8, // :: I16 -> I8, high half
179 Iop_8HLto16, // :: (I8,I8) -> I16
sewardj8c7f1ab2004-07-29 20:31:09 +0000180 /* 16 <-> 32 bit conversions */
181 Iop_32to16, // :: I32 -> I16, low half
182 Iop_32HIto16, // :: I32 -> I16, high half
183 Iop_16HLto32, // :: (I16,I16) -> I32
sewardj9690d922004-07-14 01:39:17 +0000184 /* 32 <-> 64 bit conversions */
sewardj8c7f1ab2004-07-29 20:31:09 +0000185 Iop_64to32, // :: I64 -> I32, low half
sewardj9690d922004-07-14 01:39:17 +0000186 Iop_64HIto32, // :: I64 -> I32, high half
187 Iop_32HLto64, // :: (I32,I32) -> I64
sewardjcf780b42004-07-13 18:42:17 +0000188 /* 1-bit stuff */
sewardj6e797c52004-10-13 15:20:17 +0000189 Iop_Not1, /* :: Ity_Bit -> Ity_Bit */
sewardj84ff0652004-08-23 16:16:08 +0000190 Iop_32to1, /* :: Ity_I32 -> Ity_Bit, just select bit[0] */
191 Iop_1Uto8, /* :: Ity_Bit -> Ity_I8, unsigned widen */
192 Iop_1Uto32, /* :: Ity_Bit -> Ity_I32, unsigned widen */
sewardj8f3debf2004-09-08 23:42:23 +0000193
194 /* ------ Floating point. We try and be IEEE754 compliant. ------ */
195
sewardj52ace3e2004-09-11 17:10:08 +0000196 /* Binary operations mandated by IEEE754. */
sewardj46de4072004-09-11 19:23:24 +0000197 Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64, /* Iop_RemF64, */
sewardjcfded9a2004-09-09 11:44:16 +0000198
sewardj52ace3e2004-09-11 17:10:08 +0000199 /* Binary ops supported by IA32 but not mandated by 754. */
sewardj442d0be2004-10-15 22:57:13 +0000200 Iop_AtanF64, /* FPATAN, arctan(arg1/arg2) */
201 Iop_Yl2xF64, /* FYL2X, arg1 * log2(arg2) */
202 Iop_Yl2xp1F64, /* FYL2XP1, arg1 * log2(arg2+1.0) */
203 Iop_PRemF64, /* FPREM, non-IEEE remainder(arg1/arg2) */
204 Iop_PRemC3210F64, /* C3210 flags resulting from FPREM, :: I32 */
205 Iop_PRem1F64, /* FPREM1, IEEE remainder(arg1/arg2) */
206 Iop_PRem1C3210F64, /* C3210 flags resulting from FPREM1, :: I32 */
207 Iop_ScaleF64, /* FSCALE, arg1 * (2^RoundTowardsZero(arg2)) */
208 /* Note that on x86 guest, PRem1{C3210} has the same behaviour
209 as the IEEE mandated RemF64, except it is limited in the
210 range of its operand. Hence the partialness. */
sewardj52ace3e2004-09-11 17:10:08 +0000211
212 /* Unary operations mandated by IEEE754. */
213 Iop_NegF64, Iop_SqrtF64,
214
215 /* Unary ops supported by IA32 but not mandated by 754. */
216 Iop_AbsF64, /* FABS */
217 Iop_SinF64, /* FSIN */
218 Iop_CosF64, /* FCOS */
sewardj99016a72004-10-15 22:09:17 +0000219 Iop_TanF64, /* FTAN */
sewardj06c32a02004-09-12 12:07:34 +0000220 Iop_2xm1F64, /* (2^arg - 1.0) */
sewardj8f3debf2004-09-08 23:42:23 +0000221
222 /* Comparison, yielding GT/LT/EQ/UN(ordered), as per the following:
sewardj883b00b2004-09-11 09:30:24 +0000223 0x45 Unordered
sewardj8f3debf2004-09-08 23:42:23 +0000224 0x01 LT
225 0x00 GT
sewardj883b00b2004-09-11 09:30:24 +0000226 0x40 EQ
sewardj8f3debf2004-09-08 23:42:23 +0000227 This just happens to be the Intel encoding. The values
228 are recorded in the type IRCmpF64Result.
229 */
230 Iop_CmpF64,
231
232 /* int -> double */
233 Iop_I32toF64, Iop_I64toF64,
234
235 /* double -> int. These take a first argument :: Ity_I32
236 (an IRRoundingMode) which is an indication of the rounding mode,
237 as per the following encoding:
238 00b to nearest (the default)
239 01b to -infinity
240 10b to +infinity
241 11b to zero
242 This just happens to be the Intel encoding. For reference only,
243 the PPC encoding is:
244 00b to nearest (the default)
245 01b to zero
246 10b to +infinity
247 11b to -infinity
248 Any PPC -> IR front end will have to translate these PPC
249 encodings to the standard encodings.
250
251 If one of these conversions gets an out-of-range condition,
252 or a NaN, as an argument, the result is host-defined. On x86
253 the "integer indefinite" value 0x80..00 is produced.
254 On PPC it is either 0x80..00 or 0x7F..FF depending on the sign
255 of the argument.
256 */
257 Iop_F64toI64, Iop_F64toI32, Iop_F64toI16,
sewardj52ace3e2004-09-11 17:10:08 +0000258
sewardje6709112004-09-10 18:37:18 +0000259 /* F64 -> F64, also takes an I32 first argument encoding the
260 rounding mode. */
261 Iop_RoundF64,
sewardj8f3debf2004-09-08 23:42:23 +0000262
263 /* double <-> float. What does this mean -- does it round? */
sewardj17442fe2004-09-20 14:54:28 +0000264 Iop_F32toF64, Iop_F64toF32,
265
266 /* Reinterpretation. Take an F64 and produce an I64 with
267 the same bit pattern, or vice versa. */
268 Iop_ReinterpF64asI64, Iop_ReinterpI64asF64
sewardjac6b7122004-06-27 01:03:57 +0000269 }
270 IROp;
sewardjec6ad592004-06-20 12:26:53 +0000271
sewardjce646f22004-08-31 23:55:54 +0000272
sewardj35421a32004-07-05 13:12:34 +0000273extern void ppIROp ( IROp );
sewardjec6ad592004-06-20 12:26:53 +0000274
sewardje3d0d2e2004-06-27 10:42:44 +0000275
sewardjc9868d72004-09-12 19:19:17 +0000276
277/* Encoding of IEEE754-specified rounding modes in Float -> Int
278 conversions. This is the same as the encoding used by Intel IA32
279 to indicate x87 rounding mode. */
280typedef
281 enum { Irrm_NEAREST=0, Irrm_NegINF=1, Irrm_PosINF=2, Irrm_ZERO=3 }
282 IRRoundingMode;
283
284/* Floating point comparison result values, as created by Iop_CmpF64.
285 This is also derived from what IA32 does. */
286typedef
287 enum {
288 Ircr_UN = 0x45,
289 Ircr_LT = 0x01,
290 Ircr_GT = 0x00,
291 Ircr_EQ = 0x40
292 }
293 IRCmpF64Result;
294
295
sewardjc97096c2004-06-30 09:28:04 +0000296/* ------------------ Expressions ------------------ */
sewardjb3bce0e2004-09-14 23:20:10 +0000297/*
298 Some details of expression semantics:
sewardjd1725d12004-08-12 20:46:53 +0000299
sewardjb3bce0e2004-09-14 23:20:10 +0000300 IRExpr_GetI (also IRStmt_PutI)
301 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
302 This carries two ints, which give the lowest and highest possible
303 byte offsets that the GetI can possibly reference. For example, if
304 the type is Ity_I32, and the Expr may have a value of M, M+4 or
305 M+8, where M is a translation-time known constant, then the low and
306 high limits are M and M+11 respectively.
sewardjd1725d12004-08-12 20:46:53 +0000307
sewardjb3bce0e2004-09-14 23:20:10 +0000308 PutI's limit values are interpreted identically.
sewardjd1725d12004-08-12 20:46:53 +0000309
sewardjb3bce0e2004-09-14 23:20:10 +0000310 The limit values are used by IR optimisers to establish
311 aliasing/non-aliasing between seperate GetI and PutI events, which
312 could be used to do reordering of them, or suchlike things.
313 Clearly it's critical to give the correct limit values -- this is
314 something that can't be automatically checked (in general), and so
315 the front-end writers must be very careful to tell the truth, since
316 not doing so could lead to obscure IR optimisation bugs.
317
318 IRExpr_CCall
319 ~~~~~~~~~~~~
320 The name is the C helper function; the backends will call back to
321 the front ends to get the address of a host-code helper function to
322 be called.
323
324 The args are a NULL-terminated array of arguments. The stated
325 return IRType, and the implied argument types, must match that of
326 the function being called well enough so that the back end can
327 actually generate correct code for the call.
328
329 The called function **must** satisfy the following:
330
331 * no side effects -- must be a pure function, the result of which
332 depends only on the passed parameters.
333
334 * it may not look at, nor modify, any of the guest state since that
335 would hide guest state transitions from instrumenters
336
337 * it may not access guest memory, since that would hide guest
338 memory transactions from the instrumenters
339
340 This is restrictive, but makes the semantics clean, and does
341 not interfere with IR optimisation.
342
343 If you want to call a helper which can mess with guest state and/or
344 memory, instead use IRStmt_Dirty. This is a lot more flexible, but
345 you pay for that flexibility in that you have to give a bunch of
346 details about what the helper does (and you better be telling the
347 truth, otherwise any derived instrumentation will be wrong). Also
348 IRStmt_Dirty inhibits various IR optimisations and so can cause
sewardjc5fc7aa2004-10-27 23:00:55 +0000349 quite poor code to be generated. Try to avoid it.
sewardje3d0d2e2004-06-27 10:42:44 +0000350*/
sewardjd1725d12004-08-12 20:46:53 +0000351
sewardjb3bce0e2004-09-14 23:20:10 +0000352/* The possible kinds of expressions are as follows: */
sewardje3d0d2e2004-06-27 10:42:44 +0000353typedef
sewardjb3bce0e2004-09-14 23:20:10 +0000354 enum {
355 Iex_Binder, /* Used only in pattern matching.
356 Not an expression. */
357 Iex_Get, /* read guest state, fixed offset */
358 Iex_GetI, /* read guest state, run-time offset */
359 Iex_Tmp, /* value of temporary */
360 Iex_Binop, /* binary operation */
361 Iex_Unop, /* unary operation */
362 Iex_LDle, /* little-endian read from memory */
363 Iex_Const, /* constant-valued expression */
364 Iex_Mux0X, /* ternary if-then-else operator (STRICT) */
365 Iex_CCall /* call to pure (side-effect-free) helper fn */
366 }
sewardje3d0d2e2004-06-27 10:42:44 +0000367 IRExprTag;
368
369typedef
370 struct _IRExpr {
371 IRExprTag tag;
372 union {
sewardj443cd9d2004-07-18 23:06:45 +0000373 struct {
374 Int binder;
375 } Binder;
sewardje3d0d2e2004-06-27 10:42:44 +0000376 struct {
sewardjfbcaf332004-07-08 01:46:01 +0000377 Int offset;
378 IRType ty;
sewardje3d0d2e2004-06-27 10:42:44 +0000379 } Get;
380 struct {
sewardj2d3f77c2004-09-22 23:49:09 +0000381 IRArray* descr;
382 struct _IRExpr* off;
383 Int bias;
sewardjd1725d12004-08-12 20:46:53 +0000384 } GetI;
385 struct {
sewardje3d0d2e2004-06-27 10:42:44 +0000386 IRTemp tmp;
387 } Tmp;
388 struct {
389 IROp op;
390 struct _IRExpr* arg1;
391 struct _IRExpr* arg2;
392 } Binop;
393 struct {
394 IROp op;
395 struct _IRExpr* arg;
396 } Unop;
397 struct {
398 IRType ty;
399 struct _IRExpr* addr;
400 } LDle;
401 struct {
sewardj66f2f792004-06-30 16:37:16 +0000402 IRConst* con;
sewardje3d0d2e2004-06-27 10:42:44 +0000403 } Const;
sewardje87b4842004-07-10 12:23:30 +0000404 struct {
sewardj8ea867b2004-10-30 19:03:02 +0000405 IRCallee* cee;
406 IRType retty;
sewardje87b4842004-07-10 12:23:30 +0000407 struct _IRExpr** args;
408 } CCall;
sewardjeeb9ef82004-07-15 12:39:03 +0000409 struct {
410 struct _IRExpr* cond;
sewardjeeb9ef82004-07-15 12:39:03 +0000411 struct _IRExpr* expr0;
sewardj4042c7e2004-07-18 01:28:30 +0000412 struct _IRExpr* exprX;
413 } Mux0X;
sewardje3d0d2e2004-06-27 10:42:44 +0000414 } Iex;
415 }
416 IRExpr;
417
sewardj443cd9d2004-07-18 23:06:45 +0000418extern IRExpr* IRExpr_Binder ( Int binder );
419extern IRExpr* IRExpr_Get ( Int off, IRType ty );
sewardj2d3f77c2004-09-22 23:49:09 +0000420extern IRExpr* IRExpr_GetI ( IRArray* descr, IRExpr* off, Int bias );
sewardj443cd9d2004-07-18 23:06:45 +0000421extern IRExpr* IRExpr_Tmp ( IRTemp tmp );
422extern IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 );
423extern IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg );
424extern IRExpr* IRExpr_LDle ( IRType ty, IRExpr* addr );
425extern IRExpr* IRExpr_Const ( IRConst* con );
sewardj8ea867b2004-10-30 19:03:02 +0000426extern IRExpr* IRExpr_CCall ( IRCallee* cee, IRType retty, IRExpr** args );
sewardj443cd9d2004-07-18 23:06:45 +0000427extern IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX );
sewardje3d0d2e2004-06-27 10:42:44 +0000428
sewardj695cff92004-10-13 14:50:14 +0000429extern IRExpr* dopyIRExpr ( IRExpr* );
sewardj695cff92004-10-13 14:50:14 +0000430
sewardj35421a32004-07-05 13:12:34 +0000431extern void ppIRExpr ( IRExpr* );
sewardjec6ad592004-06-20 12:26:53 +0000432
sewardjc5fc7aa2004-10-27 23:00:55 +0000433/* NULL-terminated IRExpr expression vectors, suitable for use as arg
434 lists in clean/dirty helper calls. */
435
436extern IRExpr** mkIRExprVec_0 ( void );
437extern IRExpr** mkIRExprVec_1 ( IRExpr* arg1 );
438extern IRExpr** mkIRExprVec_2 ( IRExpr* arg1, IRExpr* arg2 );
439
440extern IRExpr** sopyIRExprVec ( IRExpr** );
441extern IRExpr** dopyIRExprVec ( IRExpr** );
442
sewardj49651f42004-10-28 22:11:04 +0000443/* Make a constant expression from the given host word,
444 taking into account of course the host word size. */
445extern IRExpr* mkIRExpr_HWord ( HWord );
446
447
448inline static Bool isAtom ( IRExpr* e ) {
449 return e->tag == Iex_Tmp || e->tag == Iex_Const;
450}
451
sewardje87b4842004-07-10 12:23:30 +0000452
sewardjb3bce0e2004-09-14 23:20:10 +0000453/* ------------------ Dirty helper calls ------------------ */
sewardje87b4842004-07-10 12:23:30 +0000454
sewardjb3bce0e2004-09-14 23:20:10 +0000455/* A dirty call is a flexible mechanism for calling a helper function
456 or procedure. The helper function may read, write or modify client
457 memory, and may read, write or modify client state. It can take
458 arguments and optionally return a value. It may return different
459 results and/or do different things when called repeated with the
460 same arguments, by means of storing private state.
sewardje87b4842004-07-10 12:23:30 +0000461
sewardjc5fc7aa2004-10-27 23:00:55 +0000462 If a value is returned, it is assigned to the nominated return
463 temporary.
sewardjb3bce0e2004-09-14 23:20:10 +0000464
465 Dirty calls are statements rather than expressions for obvious
sewardjc5fc7aa2004-10-27 23:00:55 +0000466 reasons. If a dirty call is stated as writing guest state, any
467 values derived from the written parts of the guest state are
468 invalid. Similarly, if the dirty call is stated as writing
469 memory, any loaded values are invalidated by it.
sewardjb3bce0e2004-09-14 23:20:10 +0000470
471 In order that instrumentation is possible, the call must state, and
472 state correctly
473
474 * whether it reads, writes or modifies memory, and if so where
475 (only one chunk can be stated)
476
477 * whether it reads, writes or modifies guest state, and if so which
478 pieces (several pieces may be stated, and currently their extents
479 must be known at translation-time).
sewardjc5fc7aa2004-10-27 23:00:55 +0000480
481 Normally, code is generated to pass just the args to the helper.
482 However, if .needsBBP is set, then an extra first argument is
483 passed, which is the baseblock pointer, so that the callee can
484 access the guest state. It is invalid for .nFxState to be zero
485 but .needsBBP to be True, since .nFxState==0 is a claim that the
486 call does not access guest state.
sewardje87b4842004-07-10 12:23:30 +0000487*/
sewardjc97096c2004-06-30 09:28:04 +0000488
sewardjb3bce0e2004-09-14 23:20:10 +0000489#define VEX_N_FXSTATE 4 /* enough for CPUID on x86 */
490
491typedef
492 enum {
sewardj17442fe2004-09-20 14:54:28 +0000493 Ifx_None = 0x15000, /* no effect */
494 Ifx_Read, /* reads the resource */
495 Ifx_Write, /* writes the resource */
496 Ifx_Modify, /* modifies the resource */
sewardjb3bce0e2004-09-14 23:20:10 +0000497 }
498 IREffect;
499
500extern void ppIREffect ( IREffect );
501
502
503typedef
504 struct {
505 /* What to call, and details of args/results */
sewardj8ea867b2004-10-30 19:03:02 +0000506 IRCallee* cee; /* where to call */
507 IRExpr** args; /* arg list, ends in NULL */
508 IRTemp tmp; /* to assign result to, or INVALID_IRTEMP if none */
sewardjb3bce0e2004-09-14 23:20:10 +0000509
510 /* Mem effects; we allow only one R/W/M region to be stated */
sewardj8ea867b2004-10-30 19:03:02 +0000511 IREffect mFx; /* indicates memory effects, if any */
512 IRExpr* mAddr; /* of access, or NULL if mFx==Ifx_None */
513 Int mSize; /* of access, or zero if mFx==Ifx_None */
sewardjb3bce0e2004-09-14 23:20:10 +0000514
515 /* Guest state effects; up to N allowed */
sewardjc5fc7aa2004-10-27 23:00:55 +0000516 Bool needsBBP; /* True => also pass guest state ptr to callee */
517 Int nFxState; /* must be 0 .. VEX_N_FXSTATE */
sewardjb3bce0e2004-09-14 23:20:10 +0000518 struct {
519 IREffect fx; /* read, write or modify? */
520 Int offset;
521 Int size;
522 } fxState[VEX_N_FXSTATE];
523 }
524 IRDirty;
525
526extern void ppIRDirty ( IRDirty* );
527extern IRDirty* emptyIRDirty ( void );
528
sewardj695cff92004-10-13 14:50:14 +0000529extern IRDirty* dopyIRDirty ( IRDirty* );
530
sewardjc5fc7aa2004-10-27 23:00:55 +0000531/* A handy function which takes some of the tedium out of constructing
532 dirty helper calls. The called function impliedly does not return
533 any value. The call is marked as accessing neither guest state nor
534 memory (hence the "unsafe" designation) -- you can mess with this
535 later if need be.*/
sewardj8ea867b2004-10-30 19:03:02 +0000536extern IRDirty* unsafeIRDirty_0_N ( IRCallee* cee, IRExpr** args );
sewardjc5fc7aa2004-10-27 23:00:55 +0000537
538/* Similarly, make a zero-annotation dirty call which returns a value,
539 and assign that to the given temp. */
sewardj8ea867b2004-10-30 19:03:02 +0000540extern IRDirty* unsafeIRDirty_1_N ( IRTemp dst, IRCallee* cee, IRExpr** args );
sewardjc5fc7aa2004-10-27 23:00:55 +0000541
sewardjb3bce0e2004-09-14 23:20:10 +0000542
sewardjc97096c2004-06-30 09:28:04 +0000543/* ------------------ Statements ------------------ */
sewardjb3bce0e2004-09-14 23:20:10 +0000544
545/* The possible kinds of statements are as follows: */
sewardjac6b7122004-06-27 01:03:57 +0000546typedef
sewardjb3bce0e2004-09-14 23:20:10 +0000547 enum {
548 Ist_Put, /* write guest state, fixed offset */
549 Ist_PutI, /* write guest state, run-time offset */
550 Ist_Tmp, /* assign value to temporary */
551 Ist_STle, /* little-endian write to memory */
552 Ist_Dirty, /* call complex ("dirty") helper function */
553 Ist_Exit /* conditional exit from BB */
554 }
sewardjac6b7122004-06-27 01:03:57 +0000555 IRStmtTag;
556
557typedef
558 struct _IRStmt {
559 IRStmtTag tag;
560 union {
561 struct {
562 Int offset;
sewardj6d076362004-09-23 11:06:17 +0000563 IRExpr* data;
sewardjac6b7122004-06-27 01:03:57 +0000564 } Put;
565 struct {
sewardj2d3f77c2004-09-22 23:49:09 +0000566 IRArray* descr;
567 IRExpr* off;
568 Int bias;
569 IRExpr* data;
sewardjd1725d12004-08-12 20:46:53 +0000570 } PutI;
571 struct {
sewardjac6b7122004-06-27 01:03:57 +0000572 IRTemp tmp;
sewardj6d076362004-09-23 11:06:17 +0000573 IRExpr* data;
sewardjac6b7122004-06-27 01:03:57 +0000574 } Tmp;
575 struct {
sewardjc97096c2004-06-30 09:28:04 +0000576 IRExpr* addr;
577 IRExpr* data;
sewardjac6b7122004-06-27 01:03:57 +0000578 } STle;
sewardj64e1d652004-07-12 14:00:46 +0000579 struct {
sewardjb3bce0e2004-09-14 23:20:10 +0000580 IRDirty* details;
581 } Dirty;
582 struct {
sewardj443cd9d2004-07-18 23:06:45 +0000583 IRExpr* cond;
sewardj64e1d652004-07-12 14:00:46 +0000584 IRConst* dst;
585 } Exit;
sewardjac6b7122004-06-27 01:03:57 +0000586 } Ist;
sewardjac6b7122004-06-27 01:03:57 +0000587 }
588 IRStmt;
sewardjec6ad592004-06-20 12:26:53 +0000589
sewardj6d076362004-09-23 11:06:17 +0000590extern IRStmt* IRStmt_Put ( Int off, IRExpr* data );
sewardj2d3f77c2004-09-22 23:49:09 +0000591extern IRStmt* IRStmt_PutI ( IRArray* descr, IRExpr* off, Int bias,
592 IRExpr* data );
sewardj6d076362004-09-23 11:06:17 +0000593extern IRStmt* IRStmt_Tmp ( IRTemp tmp, IRExpr* data );
594extern IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* data );
sewardjb3bce0e2004-09-14 23:20:10 +0000595extern IRStmt* IRStmt_Dirty ( IRDirty* details );
596extern IRStmt* IRStmt_Exit ( IRExpr* cond, IRConst* dst );
sewardjec6ad592004-06-20 12:26:53 +0000597
sewardj695cff92004-10-13 14:50:14 +0000598extern IRStmt* dopyIRStmt ( IRStmt* );
599
sewardj35421a32004-07-05 13:12:34 +0000600extern void ppIRStmt ( IRStmt* );
sewardjc97096c2004-06-30 09:28:04 +0000601
602
sewardje539a402004-07-14 18:24:17 +0000603/* ------------------ Basic Blocks ------------------ */
sewardj78c19df2004-07-12 22:49:27 +0000604
sewardje539a402004-07-14 18:24:17 +0000605/* This describes the unconditional jumps which implicitly happen at
606 the end of each basic block. Conditional jumps -- which can only
607 be done with the IRStmt_Exit statement -- are implicitly of the
608 Ijk_Boring kind. */
609
sewardj78c19df2004-07-12 22:49:27 +0000610typedef
611 enum {
sewardje8e9d732004-07-16 21:03:45 +0000612 Ijk_Boring=0x14000, /* not interesting; just goto next */
sewardj78c19df2004-07-12 22:49:27 +0000613 Ijk_Call, /* guest is doing a call */
614 Ijk_Ret, /* guest is doing a return */
615 Ijk_ClientReq, /* do guest client req before continuing */
616 Ijk_Syscall, /* do guest syscall before continuing */
617 Ijk_Yield /* client is yielding to thread scheduler */
618 }
619 IRJumpKind;
620
621extern void ppIRJumpKind ( IRJumpKind );
622
623
sewardjc97096c2004-06-30 09:28:04 +0000624/* A bunch of statements, expressions, etc, are incomplete without an
625 environment indicating the type of each IRTemp. So this provides
sewardje539a402004-07-14 18:24:17 +0000626 one. IR temporaries are really just unsigned ints and so this
627 provides an array, 0 .. n_types_used-1 of them.
sewardjc97096c2004-06-30 09:28:04 +0000628*/
629typedef
sewardjc97096c2004-06-30 09:28:04 +0000630 struct {
sewardje539a402004-07-14 18:24:17 +0000631 IRType* types;
632 Int types_size;
633 Int types_used;
sewardjc97096c2004-06-30 09:28:04 +0000634 }
635 IRTypeEnv;
636
sewardj695cff92004-10-13 14:50:14 +0000637extern IRTemp newIRTemp ( IRTypeEnv*, IRType );
638extern IRTypeEnv* dopyIRTypeEnv ( IRTypeEnv* );
639
sewardj35421a32004-07-05 13:12:34 +0000640extern void ppIRTypeEnv ( IRTypeEnv* );
sewardjc97096c2004-06-30 09:28:04 +0000641
sewardjec6ad592004-06-20 12:26:53 +0000642
sewardjd7cb8532004-08-17 23:59:23 +0000643/* Basic blocks contain:
sewardjc97096c2004-06-30 09:28:04 +0000644 - A table giving a type for each temp
sewardjd7cb8532004-08-17 23:59:23 +0000645 - An expandable array of statements
sewardje539a402004-07-14 18:24:17 +0000646 - An expression of type 32 or 64 bits, depending on the
647 guest's word size, indicating the next destination.
sewardjd7cb8532004-08-17 23:59:23 +0000648 - An indication of any special actions (JumpKind) needed
649 for this final jump.
sewardjec6ad592004-06-20 12:26:53 +0000650*/
sewardjac6b7122004-06-27 01:03:57 +0000651typedef
652 struct _IRBB {
sewardjc97096c2004-06-30 09:28:04 +0000653 IRTypeEnv* tyenv;
sewardjd7cb8532004-08-17 23:59:23 +0000654 IRStmt** stmts;
655 Int stmts_size;
656 Int stmts_used;
sewardje539a402004-07-14 18:24:17 +0000657 IRExpr* next;
658 IRJumpKind jumpkind;
sewardjac6b7122004-06-27 01:03:57 +0000659 }
660 IRBB;
sewardjec6ad592004-06-20 12:26:53 +0000661
sewardjd7cb8532004-08-17 23:59:23 +0000662extern IRBB* emptyIRBB ( void );
sewardj695cff92004-10-13 14:50:14 +0000663
664extern IRBB* dopyIRBB ( IRBB* );
sewardjc97096c2004-06-30 09:28:04 +0000665
sewardj35421a32004-07-05 13:12:34 +0000666extern void ppIRBB ( IRBB* );
sewardjc97096c2004-06-30 09:28:04 +0000667
sewardj695cff92004-10-13 14:50:14 +0000668extern void addStmtToIRBB ( IRBB*, IRStmt* );
669
670
sewardjec6ad592004-06-20 12:26:53 +0000671
672/*---------------------------------------------------------------*/
sewardjc97096c2004-06-30 09:28:04 +0000673/*--- Helper functions for the IR ---*/
sewardjec6ad592004-06-20 12:26:53 +0000674/*---------------------------------------------------------------*/
675
sewardjc97096c2004-06-30 09:28:04 +0000676/* For messing with IR type environments */
sewardjd7cb8532004-08-17 23:59:23 +0000677extern IRTypeEnv* emptyIRTypeEnv ( void );
sewardjec6ad592004-06-20 12:26:53 +0000678
sewardjc97096c2004-06-30 09:28:04 +0000679/* What is the type of this expression? */
sewardj6efd4a12004-07-15 03:54:23 +0000680extern IRType typeOfIRConst ( IRConst* );
sewardj17442fe2004-09-20 14:54:28 +0000681extern IRType typeOfIRTemp ( IRTypeEnv*, IRTemp );
sewardj6efd4a12004-07-15 03:54:23 +0000682extern IRType typeOfIRExpr ( IRTypeEnv*, IRExpr* );
sewardjec6ad592004-06-20 12:26:53 +0000683
sewardj35439212004-07-14 22:36:10 +0000684/* Sanity check a BB of IR */
685extern void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size );
sewardjec6ad592004-06-20 12:26:53 +0000686
sewardj6d2638e2004-07-15 09:38:27 +0000687/* Is this any value actually in the enumeration 'IRType' ? */
688extern Bool isPlausibleType ( IRType ty );
689
sewardj887a11a2004-07-05 17:26:47 +0000690#endif /* ndef __LIBVEX_IR_H */
sewardjac9af022004-07-05 01:15:34 +0000691
692
693/*---------------------------------------------------------------*/
sewardj887a11a2004-07-05 17:26:47 +0000694/*--- libvex_ir.h ---*/
sewardjac9af022004-07-05 01:15:34 +0000695/*---------------------------------------------------------------*/