blob: bc58c380afed7eb0482ef9ed19eefc7f029ff8a9 [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
sewardjf8ed9d82004-11-12 17:40:23 +00009/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
13 Copyright (C) 2004 OpenWorks, LLP.
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; Version 2 dated June 1991 of the
18 license.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
23 for damages. See the GNU General Public License for more details.
24
25 Neither the names of the U.S. Department of Energy nor the
26 University of California nor the names of its contributors may be
27 used to endorse or promote products derived from this software
28 without prior written permission.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 USA.
34*/
35
sewardj887a11a2004-07-05 17:26:47 +000036#ifndef __LIBVEX_IR_H
37#define __LIBVEX_IR_H
sewardjac9af022004-07-05 01:15:34 +000038
sewardj887a11a2004-07-05 17:26:47 +000039#include "libvex_basictypes.h"
sewardjec6ad592004-06-20 12:26:53 +000040
sewardjec6ad592004-06-20 12:26:53 +000041
42/*---------------------------------------------------------------*/
sewardjac6b7122004-06-27 01:03:57 +000043/*--- Type definitions for the IR ---*/
sewardjec6ad592004-06-20 12:26:53 +000044/*---------------------------------------------------------------*/
45
sewardjc97096c2004-06-30 09:28:04 +000046/* ------------------ Types ------------------ */
sewardje3d0d2e2004-06-27 10:42:44 +000047
48typedef
sewardj6efd4a12004-07-15 03:54:23 +000049 enum { Ity_INVALID=0x10FFF,
50 Ity_Bit=0x11000,
sewardjd1725d12004-08-12 20:46:53 +000051 Ity_I8, Ity_I16, Ity_I32, Ity_I64,
52 Ity_F32, Ity_F64
53 }
sewardje3d0d2e2004-06-27 10:42:44 +000054 IRType;
55
sewardj35421a32004-07-05 13:12:34 +000056extern void ppIRType ( IRType );
sewardj2d3f77c2004-09-22 23:49:09 +000057extern Int sizeofIRType ( IRType );
sewardje3d0d2e2004-06-27 10:42:44 +000058
sewardjc97096c2004-06-30 09:28:04 +000059
60/* ------------------ Constants ------------------ */
sewardjec6ad592004-06-20 12:26:53 +000061
sewardjac6b7122004-06-27 01:03:57 +000062typedef
sewardj51cba892004-08-20 00:09:03 +000063 enum { Ico_Bit=0x12000,
sewardj17442fe2004-09-20 14:54:28 +000064 Ico_U8, Ico_U16, Ico_U32, Ico_U64,
65 Ico_F64, /* 64-bit IEEE754 floating */
66 Ico_F64i /* 64-bit unsigned int to be interpreted literally
67 as a IEEE754 double value. */
sewardj207557a2004-08-27 12:00:18 +000068 }
sewardjac6b7122004-06-27 01:03:57 +000069 IRConstTag;
70
71typedef
sewardje3d0d2e2004-06-27 10:42:44 +000072 struct _IRConst {
sewardjac6b7122004-06-27 01:03:57 +000073 IRConstTag tag;
74 union {
sewardj51cba892004-08-20 00:09:03 +000075 Bool Bit;
sewardjc97096c2004-06-30 09:28:04 +000076 UChar U8;
77 UShort U16;
78 UInt U32;
79 ULong U64;
sewardja58ea662004-08-15 03:12:41 +000080 Double F64;
sewardj17442fe2004-09-20 14:54:28 +000081 ULong F64i;
sewardjac6b7122004-06-27 01:03:57 +000082 } Ico;
83 }
84 IRConst;
sewardjec6ad592004-06-20 12:26:53 +000085
sewardj17442fe2004-09-20 14:54:28 +000086extern IRConst* IRConst_Bit ( Bool );
87extern IRConst* IRConst_U8 ( UChar );
88extern IRConst* IRConst_U16 ( UShort );
89extern IRConst* IRConst_U32 ( UInt );
90extern IRConst* IRConst_U64 ( ULong );
91extern IRConst* IRConst_F64 ( Double );
92extern IRConst* IRConst_F64i ( ULong );
sewardjec6ad592004-06-20 12:26:53 +000093
sewardj695cff92004-10-13 14:50:14 +000094extern IRConst* dopyIRConst ( IRConst* );
95
sewardj35421a32004-07-05 13:12:34 +000096extern void ppIRConst ( IRConst* );
sewardj4345f7a2004-09-22 19:49:27 +000097extern Bool eqIRConst ( IRConst*, IRConst* );
sewardjc97096c2004-06-30 09:28:04 +000098
99
sewardj8ea867b2004-10-30 19:03:02 +0000100/* ------------------ Call targets ------------------ */
101
102/* Describes a helper function to call. The name part is purely for
sewardj77352542004-10-30 20:39:01 +0000103 pretty printing and not actually used. regparms=n tells the back
sewardj8ea867b2004-10-30 19:03:02 +0000104 end that the callee has been declared
105 "__attribute__((regparm(n)))". On some targets (x86) the back end
106 will need to construct a non-standard sequence to call a function
sewardj43c56462004-11-06 12:17:57 +0000107 declared like this.
108
109 mcx_mask is a sop to Memcheck. It indicates which args should be
110 considered 'always defined' when lazily computing definedness of
111 the result. Bit 0 of mcx_mask corresponds to args[0], bit 1 to
112 args[1], etc. If a bit is set, the corresponding arg is excluded
113 (hence "x" in "mcx") from definedness checking.
114*/
sewardj8ea867b2004-10-30 19:03:02 +0000115
116typedef
117 struct {
sewardj77352542004-10-30 20:39:01 +0000118 Int regparms;
sewardj8ea867b2004-10-30 19:03:02 +0000119 Char* name;
sewardjf9655262004-10-31 20:02:16 +0000120 void* addr;
sewardj43c56462004-11-06 12:17:57 +0000121 UInt mcx_mask;
sewardj8ea867b2004-10-30 19:03:02 +0000122 }
123 IRCallee;
124
sewardjf9655262004-10-31 20:02:16 +0000125extern IRCallee* mkIRCallee ( Int regparms, Char* name, void* addr );
sewardj8ea867b2004-10-30 19:03:02 +0000126
127extern IRCallee* dopyIRCallee ( IRCallee* );
128
129extern void ppIRCallee ( IRCallee* );
130
131
sewardj2d3f77c2004-09-22 23:49:09 +0000132/* ------------------ Guest state arrays ------------------ */
133
134typedef
135 struct {
136 Int base;
137 IRType elemTy;
138 Int nElems;
139 }
140 IRArray;
141
142extern IRArray* mkIRArray ( Int, IRType, Int );
143
sewardj695cff92004-10-13 14:50:14 +0000144extern IRArray* dopyIRArray ( IRArray* );
145
sewardj2d3f77c2004-09-22 23:49:09 +0000146extern void ppIRArray ( IRArray* );
sewardje98dcf22004-10-04 09:15:11 +0000147extern Bool eqIRArray ( IRArray*, IRArray* );
sewardj2d3f77c2004-09-22 23:49:09 +0000148
149
sewardjc97096c2004-06-30 09:28:04 +0000150/* ------------------ Temporaries ------------------ */
sewardjec6ad592004-06-20 12:26:53 +0000151
sewardj1c192762004-10-14 00:28:15 +0000152/* The IR optimiser relies on the fact that IRTemps are 32-bit
153 ints. Do not change them to be ints of any other size. */
sewardjfbcaf332004-07-08 01:46:01 +0000154typedef UInt IRTemp;
sewardjec6ad592004-06-20 12:26:53 +0000155
sewardj35421a32004-07-05 13:12:34 +0000156extern void ppIRTemp ( IRTemp );
sewardjec6ad592004-06-20 12:26:53 +0000157
sewardj92d168d2004-11-15 14:22:12 +0000158#define IRTemp_INVALID ((IRTemp)0xFFFFFFFF)
sewardjfbcaf332004-07-08 01:46:01 +0000159
sewardjc97096c2004-06-30 09:28:04 +0000160
161/* ------------------ Binary and unary ops ------------------ */
sewardjec6ad592004-06-20 12:26:53 +0000162
sewardjac6b7122004-06-27 01:03:57 +0000163typedef
sewardj41f43bc2004-07-08 14:23:22 +0000164 enum {
165 /* Do not change this ordering. The IR generators
166 rely on (eg) Iop_Add64 == IopAdd8 + 3. */
sewardj66de2272004-07-16 21:19:05 +0000167 Iop_INVALID=0x13000,
168 Iop_Add8, Iop_Add16, Iop_Add32, Iop_Add64,
sewardj41f43bc2004-07-08 14:23:22 +0000169 Iop_Sub8, Iop_Sub16, Iop_Sub32, Iop_Sub64,
sewardj41f43bc2004-07-08 14:23:22 +0000170 /* Signless mul. MullS/MullU is elsewhere. */
171 Iop_Mul8, Iop_Mul16, Iop_Mul32, Iop_Mul64,
172 Iop_Or8, Iop_Or16, Iop_Or32, Iop_Or64,
173 Iop_And8, Iop_And16, Iop_And32, Iop_And64,
174 Iop_Xor8, Iop_Xor16, Iop_Xor32, Iop_Xor64,
175 Iop_Shl8, Iop_Shl16, Iop_Shl32, Iop_Shl64,
176 Iop_Shr8, Iop_Shr16, Iop_Shr32, Iop_Shr64,
177 Iop_Sar8, Iop_Sar16, Iop_Sar32, Iop_Sar64,
sewardje90ad6a2004-07-10 19:02:10 +0000178 /* Integer comparisons. */
179 Iop_CmpEQ8, Iop_CmpEQ16, Iop_CmpEQ32, Iop_CmpEQ64,
180 Iop_CmpNE8, Iop_CmpNE16, Iop_CmpNE32, Iop_CmpNE64,
sewardj41f43bc2004-07-08 14:23:22 +0000181 /* Tags for unary ops */
182 Iop_Not8, Iop_Not16, Iop_Not32, Iop_Not64,
sewardj9690d922004-07-14 01:39:17 +0000183 /* Widening multiplies */
184 Iop_MullS8, Iop_MullS16, Iop_MullS32,
185 Iop_MullU8, Iop_MullU16, Iop_MullU32,
sewardj8f3debf2004-09-08 23:42:23 +0000186
sewardjce646f22004-08-31 23:55:54 +0000187 /* Wierdo integer stuff */
188 Iop_Clz32, /* count leading zeroes */
189 Iop_Ctz32, /* count trailing zeros */
sewardj8f3debf2004-09-08 23:42:23 +0000190 /* Ctz32/Clz32 are UNDEFINED when given arguments of zero.
191 You must ensure they are never given a zero argument.
192 */
193
sewardj9690d922004-07-14 01:39:17 +0000194 /* Ordering not important after here. */
sewardj84ff0652004-08-23 16:16:08 +0000195 Iop_CmpLT32S,
196 Iop_CmpLE32S,
197 Iop_CmpLT32U,
198 Iop_CmpLE32U,
sewardj9690d922004-07-14 01:39:17 +0000199 /* Division */
sewardj8f3debf2004-09-08 23:42:23 +0000200 /* TODO: clarify semantics wrt rounding, negative values, whatever */
sewardj9690d922004-07-14 01:39:17 +0000201 Iop_DivModU64to32, // :: I64,I32 -> I64
202 // of which lo half is div and hi half is mod
203 Iop_DivModS64to32, // ditto, signed
sewardj89d4e982004-09-12 19:14:46 +0000204
sewardj9690d922004-07-14 01:39:17 +0000205 /* Widening conversions */
sewardje5427e82004-09-11 19:43:51 +0000206 Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, Iop_32Uto64,
sewardjbb53f8c2004-08-14 11:50:01 +0000207 Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, Iop_32Sto64,
sewardja2384712004-07-29 14:36:40 +0000208 /* Narrowing conversions */
sewardj8c7f1ab2004-07-29 20:31:09 +0000209 Iop_32to8,
sewardjb81f8b32004-07-30 10:17:50 +0000210 /* 8 <-> 16 bit conversions */
211 Iop_16to8, // :: I16 -> I8, low half
212 Iop_16HIto8, // :: I16 -> I8, high half
213 Iop_8HLto16, // :: (I8,I8) -> I16
sewardj8c7f1ab2004-07-29 20:31:09 +0000214 /* 16 <-> 32 bit conversions */
215 Iop_32to16, // :: I32 -> I16, low half
216 Iop_32HIto16, // :: I32 -> I16, high half
217 Iop_16HLto32, // :: (I16,I16) -> I32
sewardj9690d922004-07-14 01:39:17 +0000218 /* 32 <-> 64 bit conversions */
sewardj8c7f1ab2004-07-29 20:31:09 +0000219 Iop_64to32, // :: I64 -> I32, low half
sewardj9690d922004-07-14 01:39:17 +0000220 Iop_64HIto32, // :: I64 -> I32, high half
221 Iop_32HLto64, // :: (I32,I32) -> I64
sewardjcf780b42004-07-13 18:42:17 +0000222 /* 1-bit stuff */
sewardj6e797c52004-10-13 15:20:17 +0000223 Iop_Not1, /* :: Ity_Bit -> Ity_Bit */
sewardj84ff0652004-08-23 16:16:08 +0000224 Iop_32to1, /* :: Ity_I32 -> Ity_Bit, just select bit[0] */
225 Iop_1Uto8, /* :: Ity_Bit -> Ity_I8, unsigned widen */
226 Iop_1Uto32, /* :: Ity_Bit -> Ity_I32, unsigned widen */
sewardjfd332772004-11-09 16:01:40 +0000227 Iop_1Sto8, /* :: Ity_Bit -> Ity_I8, signed widen */
sewardj8eda6302004-11-05 01:55:46 +0000228 Iop_1Sto16, /* :: Ity_Bit -> Ity_I16, signed widen */
sewardjcf787902004-11-03 09:08:33 +0000229 Iop_1Sto32, /* :: Ity_Bit -> Ity_I32, signed widen */
sewardjb5874aa2004-11-04 16:57:50 +0000230 Iop_1Sto64, /* :: Ity_Bit -> Ity_I64, signed widen */
sewardj8f3debf2004-09-08 23:42:23 +0000231
232 /* ------ Floating point. We try and be IEEE754 compliant. ------ */
233
sewardj52ace3e2004-09-11 17:10:08 +0000234 /* Binary operations mandated by IEEE754. */
sewardj46de4072004-09-11 19:23:24 +0000235 Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64, /* Iop_RemF64, */
sewardjcfded9a2004-09-09 11:44:16 +0000236
sewardj52ace3e2004-09-11 17:10:08 +0000237 /* Binary ops supported by IA32 but not mandated by 754. */
sewardj442d0be2004-10-15 22:57:13 +0000238 Iop_AtanF64, /* FPATAN, arctan(arg1/arg2) */
239 Iop_Yl2xF64, /* FYL2X, arg1 * log2(arg2) */
240 Iop_Yl2xp1F64, /* FYL2XP1, arg1 * log2(arg2+1.0) */
241 Iop_PRemF64, /* FPREM, non-IEEE remainder(arg1/arg2) */
242 Iop_PRemC3210F64, /* C3210 flags resulting from FPREM, :: I32 */
243 Iop_PRem1F64, /* FPREM1, IEEE remainder(arg1/arg2) */
244 Iop_PRem1C3210F64, /* C3210 flags resulting from FPREM1, :: I32 */
245 Iop_ScaleF64, /* FSCALE, arg1 * (2^RoundTowardsZero(arg2)) */
246 /* Note that on x86 guest, PRem1{C3210} has the same behaviour
247 as the IEEE mandated RemF64, except it is limited in the
248 range of its operand. Hence the partialness. */
sewardj52ace3e2004-09-11 17:10:08 +0000249
250 /* Unary operations mandated by IEEE754. */
251 Iop_NegF64, Iop_SqrtF64,
252
253 /* Unary ops supported by IA32 but not mandated by 754. */
254 Iop_AbsF64, /* FABS */
255 Iop_SinF64, /* FSIN */
256 Iop_CosF64, /* FCOS */
sewardj99016a72004-10-15 22:09:17 +0000257 Iop_TanF64, /* FTAN */
sewardj06c32a02004-09-12 12:07:34 +0000258 Iop_2xm1F64, /* (2^arg - 1.0) */
sewardj8f3debf2004-09-08 23:42:23 +0000259
260 /* Comparison, yielding GT/LT/EQ/UN(ordered), as per the following:
sewardj883b00b2004-09-11 09:30:24 +0000261 0x45 Unordered
sewardj8f3debf2004-09-08 23:42:23 +0000262 0x01 LT
263 0x00 GT
sewardj883b00b2004-09-11 09:30:24 +0000264 0x40 EQ
sewardj8f3debf2004-09-08 23:42:23 +0000265 This just happens to be the Intel encoding. The values
266 are recorded in the type IRCmpF64Result.
267 */
268 Iop_CmpF64,
269
270 /* int -> double */
271 Iop_I32toF64, Iop_I64toF64,
272
273 /* double -> int. These take a first argument :: Ity_I32
274 (an IRRoundingMode) which is an indication of the rounding mode,
275 as per the following encoding:
276 00b to nearest (the default)
277 01b to -infinity
278 10b to +infinity
279 11b to zero
280 This just happens to be the Intel encoding. For reference only,
281 the PPC encoding is:
282 00b to nearest (the default)
283 01b to zero
284 10b to +infinity
285 11b to -infinity
286 Any PPC -> IR front end will have to translate these PPC
287 encodings to the standard encodings.
288
289 If one of these conversions gets an out-of-range condition,
290 or a NaN, as an argument, the result is host-defined. On x86
291 the "integer indefinite" value 0x80..00 is produced.
292 On PPC it is either 0x80..00 or 0x7F..FF depending on the sign
293 of the argument.
294 */
295 Iop_F64toI64, Iop_F64toI32, Iop_F64toI16,
sewardj52ace3e2004-09-11 17:10:08 +0000296
sewardje6709112004-09-10 18:37:18 +0000297 /* F64 -> F64, also takes an I32 first argument encoding the
298 rounding mode. */
299 Iop_RoundF64,
sewardj8f3debf2004-09-08 23:42:23 +0000300
301 /* double <-> float. What does this mean -- does it round? */
sewardj17442fe2004-09-20 14:54:28 +0000302 Iop_F32toF64, Iop_F64toF32,
303
304 /* Reinterpretation. Take an F64 and produce an I64 with
305 the same bit pattern, or vice versa. */
306 Iop_ReinterpF64asI64, Iop_ReinterpI64asF64
sewardjac6b7122004-06-27 01:03:57 +0000307 }
308 IROp;
sewardjec6ad592004-06-20 12:26:53 +0000309
sewardj35421a32004-07-05 13:12:34 +0000310extern void ppIROp ( IROp );
sewardjec6ad592004-06-20 12:26:53 +0000311
sewardje3d0d2e2004-06-27 10:42:44 +0000312
sewardjc9868d72004-09-12 19:19:17 +0000313/* Encoding of IEEE754-specified rounding modes in Float -> Int
314 conversions. This is the same as the encoding used by Intel IA32
315 to indicate x87 rounding mode. */
316typedef
317 enum { Irrm_NEAREST=0, Irrm_NegINF=1, Irrm_PosINF=2, Irrm_ZERO=3 }
318 IRRoundingMode;
319
320/* Floating point comparison result values, as created by Iop_CmpF64.
321 This is also derived from what IA32 does. */
322typedef
323 enum {
324 Ircr_UN = 0x45,
325 Ircr_LT = 0x01,
326 Ircr_GT = 0x00,
327 Ircr_EQ = 0x40
328 }
329 IRCmpF64Result;
330
331
sewardjc97096c2004-06-30 09:28:04 +0000332/* ------------------ Expressions ------------------ */
sewardjb3bce0e2004-09-14 23:20:10 +0000333/*
334 Some details of expression semantics:
sewardjd1725d12004-08-12 20:46:53 +0000335
sewardjb3bce0e2004-09-14 23:20:10 +0000336 IRExpr_GetI (also IRStmt_PutI)
337 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
338 This carries two ints, which give the lowest and highest possible
339 byte offsets that the GetI can possibly reference. For example, if
340 the type is Ity_I32, and the Expr may have a value of M, M+4 or
341 M+8, where M is a translation-time known constant, then the low and
342 high limits are M and M+11 respectively.
sewardjd1725d12004-08-12 20:46:53 +0000343
sewardjb3bce0e2004-09-14 23:20:10 +0000344 PutI's limit values are interpreted identically.
sewardjd1725d12004-08-12 20:46:53 +0000345
sewardjb3bce0e2004-09-14 23:20:10 +0000346 The limit values are used by IR optimisers to establish
347 aliasing/non-aliasing between seperate GetI and PutI events, which
348 could be used to do reordering of them, or suchlike things.
349 Clearly it's critical to give the correct limit values -- this is
350 something that can't be automatically checked (in general), and so
351 the front-end writers must be very careful to tell the truth, since
352 not doing so could lead to obscure IR optimisation bugs.
353
354 IRExpr_CCall
355 ~~~~~~~~~~~~
356 The name is the C helper function; the backends will call back to
357 the front ends to get the address of a host-code helper function to
358 be called.
359
360 The args are a NULL-terminated array of arguments. The stated
361 return IRType, and the implied argument types, must match that of
362 the function being called well enough so that the back end can
363 actually generate correct code for the call.
364
365 The called function **must** satisfy the following:
366
367 * no side effects -- must be a pure function, the result of which
368 depends only on the passed parameters.
369
370 * it may not look at, nor modify, any of the guest state since that
371 would hide guest state transitions from instrumenters
372
373 * it may not access guest memory, since that would hide guest
374 memory transactions from the instrumenters
375
376 This is restrictive, but makes the semantics clean, and does
377 not interfere with IR optimisation.
378
379 If you want to call a helper which can mess with guest state and/or
380 memory, instead use IRStmt_Dirty. This is a lot more flexible, but
381 you pay for that flexibility in that you have to give a bunch of
382 details about what the helper does (and you better be telling the
383 truth, otherwise any derived instrumentation will be wrong). Also
384 IRStmt_Dirty inhibits various IR optimisations and so can cause
sewardjc5fc7aa2004-10-27 23:00:55 +0000385 quite poor code to be generated. Try to avoid it.
sewardje3d0d2e2004-06-27 10:42:44 +0000386*/
sewardjd1725d12004-08-12 20:46:53 +0000387
sewardjb3bce0e2004-09-14 23:20:10 +0000388/* The possible kinds of expressions are as follows: */
sewardje3d0d2e2004-06-27 10:42:44 +0000389typedef
sewardjb3bce0e2004-09-14 23:20:10 +0000390 enum {
391 Iex_Binder, /* Used only in pattern matching.
392 Not an expression. */
393 Iex_Get, /* read guest state, fixed offset */
394 Iex_GetI, /* read guest state, run-time offset */
395 Iex_Tmp, /* value of temporary */
396 Iex_Binop, /* binary operation */
397 Iex_Unop, /* unary operation */
398 Iex_LDle, /* little-endian read from memory */
399 Iex_Const, /* constant-valued expression */
400 Iex_Mux0X, /* ternary if-then-else operator (STRICT) */
401 Iex_CCall /* call to pure (side-effect-free) helper fn */
402 }
sewardje3d0d2e2004-06-27 10:42:44 +0000403 IRExprTag;
404
405typedef
406 struct _IRExpr {
407 IRExprTag tag;
408 union {
sewardj443cd9d2004-07-18 23:06:45 +0000409 struct {
410 Int binder;
411 } Binder;
sewardje3d0d2e2004-06-27 10:42:44 +0000412 struct {
sewardjfbcaf332004-07-08 01:46:01 +0000413 Int offset;
414 IRType ty;
sewardje3d0d2e2004-06-27 10:42:44 +0000415 } Get;
416 struct {
sewardj2d3f77c2004-09-22 23:49:09 +0000417 IRArray* descr;
sewardjeeac8412004-11-02 00:26:55 +0000418 struct _IRExpr* ix;
sewardj2d3f77c2004-09-22 23:49:09 +0000419 Int bias;
sewardjd1725d12004-08-12 20:46:53 +0000420 } GetI;
421 struct {
sewardje3d0d2e2004-06-27 10:42:44 +0000422 IRTemp tmp;
423 } Tmp;
424 struct {
425 IROp op;
426 struct _IRExpr* arg1;
427 struct _IRExpr* arg2;
428 } Binop;
429 struct {
430 IROp op;
431 struct _IRExpr* arg;
432 } Unop;
433 struct {
434 IRType ty;
435 struct _IRExpr* addr;
436 } LDle;
437 struct {
sewardj66f2f792004-06-30 16:37:16 +0000438 IRConst* con;
sewardje3d0d2e2004-06-27 10:42:44 +0000439 } Const;
sewardje87b4842004-07-10 12:23:30 +0000440 struct {
sewardj8ea867b2004-10-30 19:03:02 +0000441 IRCallee* cee;
442 IRType retty;
sewardje87b4842004-07-10 12:23:30 +0000443 struct _IRExpr** args;
444 } CCall;
sewardjeeb9ef82004-07-15 12:39:03 +0000445 struct {
446 struct _IRExpr* cond;
sewardjeeb9ef82004-07-15 12:39:03 +0000447 struct _IRExpr* expr0;
sewardj4042c7e2004-07-18 01:28:30 +0000448 struct _IRExpr* exprX;
449 } Mux0X;
sewardje3d0d2e2004-06-27 10:42:44 +0000450 } Iex;
451 }
452 IRExpr;
453
sewardj443cd9d2004-07-18 23:06:45 +0000454extern IRExpr* IRExpr_Binder ( Int binder );
455extern IRExpr* IRExpr_Get ( Int off, IRType ty );
sewardjeeac8412004-11-02 00:26:55 +0000456extern IRExpr* IRExpr_GetI ( IRArray* descr, IRExpr* ix, Int bias );
sewardj443cd9d2004-07-18 23:06:45 +0000457extern IRExpr* IRExpr_Tmp ( IRTemp tmp );
458extern IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 );
459extern IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg );
460extern IRExpr* IRExpr_LDle ( IRType ty, IRExpr* addr );
461extern IRExpr* IRExpr_Const ( IRConst* con );
sewardj8ea867b2004-10-30 19:03:02 +0000462extern IRExpr* IRExpr_CCall ( IRCallee* cee, IRType retty, IRExpr** args );
sewardj443cd9d2004-07-18 23:06:45 +0000463extern IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX );
sewardje3d0d2e2004-06-27 10:42:44 +0000464
sewardjf9655262004-10-31 20:02:16 +0000465extern IRExpr* dopyIRExpr ( IRExpr* );
sewardj695cff92004-10-13 14:50:14 +0000466
sewardj35421a32004-07-05 13:12:34 +0000467extern void ppIRExpr ( IRExpr* );
sewardjec6ad592004-06-20 12:26:53 +0000468
sewardjc5fc7aa2004-10-27 23:00:55 +0000469/* NULL-terminated IRExpr expression vectors, suitable for use as arg
470 lists in clean/dirty helper calls. */
471
472extern IRExpr** mkIRExprVec_0 ( void );
sewardjf9655262004-10-31 20:02:16 +0000473extern IRExpr** mkIRExprVec_1 ( IRExpr* );
474extern IRExpr** mkIRExprVec_2 ( IRExpr*, IRExpr* );
475extern IRExpr** mkIRExprVec_3 ( IRExpr*, IRExpr*, IRExpr* );
476extern IRExpr** mkIRExprVec_4 ( IRExpr*, IRExpr*, IRExpr*, IRExpr* );
sewardjf32c67d2004-11-08 13:10:44 +0000477extern IRExpr** mkIRExprVec_5 ( IRExpr*, IRExpr*,
478 IRExpr*, IRExpr*, IRExpr* );
sewardjc5fc7aa2004-10-27 23:00:55 +0000479
480extern IRExpr** sopyIRExprVec ( IRExpr** );
481extern IRExpr** dopyIRExprVec ( IRExpr** );
482
sewardjf9655262004-10-31 20:02:16 +0000483/* Make a constant expression from the given host word taking into
484 account of course the host word size. */
sewardj49651f42004-10-28 22:11:04 +0000485extern IRExpr* mkIRExpr_HWord ( HWord );
486
sewardjf9655262004-10-31 20:02:16 +0000487/* Convenience function for constructing clean helper calls. */
488extern
489IRExpr* mkIRExprCCall ( IRType retty,
490 Int regparms, Char* name, void* addr,
491 IRExpr** args );
492
sewardj49651f42004-10-28 22:11:04 +0000493
494inline static Bool isAtom ( IRExpr* e ) {
495 return e->tag == Iex_Tmp || e->tag == Iex_Const;
496}
497
sewardje87b4842004-07-10 12:23:30 +0000498
sewardjb3bce0e2004-09-14 23:20:10 +0000499/* ------------------ Dirty helper calls ------------------ */
sewardje87b4842004-07-10 12:23:30 +0000500
sewardjb3bce0e2004-09-14 23:20:10 +0000501/* A dirty call is a flexible mechanism for calling a helper function
502 or procedure. The helper function may read, write or modify client
503 memory, and may read, write or modify client state. It can take
504 arguments and optionally return a value. It may return different
505 results and/or do different things when called repeated with the
506 same arguments, by means of storing private state.
sewardje87b4842004-07-10 12:23:30 +0000507
sewardjc5fc7aa2004-10-27 23:00:55 +0000508 If a value is returned, it is assigned to the nominated return
509 temporary.
sewardjb3bce0e2004-09-14 23:20:10 +0000510
511 Dirty calls are statements rather than expressions for obvious
sewardjc5fc7aa2004-10-27 23:00:55 +0000512 reasons. If a dirty call is stated as writing guest state, any
513 values derived from the written parts of the guest state are
514 invalid. Similarly, if the dirty call is stated as writing
515 memory, any loaded values are invalidated by it.
sewardjb3bce0e2004-09-14 23:20:10 +0000516
517 In order that instrumentation is possible, the call must state, and
518 state correctly
519
520 * whether it reads, writes or modifies memory, and if so where
521 (only one chunk can be stated)
522
523 * whether it reads, writes or modifies guest state, and if so which
524 pieces (several pieces may be stated, and currently their extents
525 must be known at translation-time).
sewardjc5fc7aa2004-10-27 23:00:55 +0000526
527 Normally, code is generated to pass just the args to the helper.
528 However, if .needsBBP is set, then an extra first argument is
529 passed, which is the baseblock pointer, so that the callee can
530 access the guest state. It is invalid for .nFxState to be zero
531 but .needsBBP to be True, since .nFxState==0 is a claim that the
532 call does not access guest state.
sewardjb8385d82004-11-02 01:34:15 +0000533
534 IMPORTANT NOTE re GUARDS: Dirty calls are strict, very strict. The
535 arguments are evaluated REGARDLESS of the guard value. It is
536 unspecified the relative order of arg evaluation and guard
537 evaluation.
sewardje87b4842004-07-10 12:23:30 +0000538*/
sewardjc97096c2004-06-30 09:28:04 +0000539
sewardjb3bce0e2004-09-14 23:20:10 +0000540#define VEX_N_FXSTATE 4 /* enough for CPUID on x86 */
541
542typedef
543 enum {
sewardj17442fe2004-09-20 14:54:28 +0000544 Ifx_None = 0x15000, /* no effect */
545 Ifx_Read, /* reads the resource */
546 Ifx_Write, /* writes the resource */
547 Ifx_Modify, /* modifies the resource */
sewardjb3bce0e2004-09-14 23:20:10 +0000548 }
549 IREffect;
550
551extern void ppIREffect ( IREffect );
552
553
554typedef
555 struct {
556 /* What to call, and details of args/results */
sewardj8ea867b2004-10-30 19:03:02 +0000557 IRCallee* cee; /* where to call */
sewardjb8385d82004-11-02 01:34:15 +0000558 IRExpr* guard; /* :: Ity_Bit. Controls whether call happens */
sewardj8ea867b2004-10-30 19:03:02 +0000559 IRExpr** args; /* arg list, ends in NULL */
sewardj92d168d2004-11-15 14:22:12 +0000560 IRTemp tmp; /* to assign result to, or IRTemp_INVALID if none */
sewardjb3bce0e2004-09-14 23:20:10 +0000561
562 /* Mem effects; we allow only one R/W/M region to be stated */
sewardj8ea867b2004-10-30 19:03:02 +0000563 IREffect mFx; /* indicates memory effects, if any */
564 IRExpr* mAddr; /* of access, or NULL if mFx==Ifx_None */
565 Int mSize; /* of access, or zero if mFx==Ifx_None */
sewardjb3bce0e2004-09-14 23:20:10 +0000566
567 /* Guest state effects; up to N allowed */
sewardjc5fc7aa2004-10-27 23:00:55 +0000568 Bool needsBBP; /* True => also pass guest state ptr to callee */
569 Int nFxState; /* must be 0 .. VEX_N_FXSTATE */
sewardjb3bce0e2004-09-14 23:20:10 +0000570 struct {
sewardj94fecf72004-11-10 12:09:42 +0000571 IREffect fx; /* read, write or modify? Ifx_None is invalid. */
sewardjb3bce0e2004-09-14 23:20:10 +0000572 Int offset;
573 Int size;
574 } fxState[VEX_N_FXSTATE];
575 }
576 IRDirty;
577
578extern void ppIRDirty ( IRDirty* );
579extern IRDirty* emptyIRDirty ( void );
580
sewardj695cff92004-10-13 14:50:14 +0000581extern IRDirty* dopyIRDirty ( IRDirty* );
582
sewardjc5fc7aa2004-10-27 23:00:55 +0000583/* A handy function which takes some of the tedium out of constructing
584 dirty helper calls. The called function impliedly does not return
sewardjb8385d82004-11-02 01:34:15 +0000585 any value and has a constant-True guard. The call is marked as
586 accessing neither guest state nor memory (hence the "unsafe"
587 designation) -- you can mess with this later if need be. A
588 suitable IRCallee is constructed from the supplied bits. */
sewardjf9655262004-10-31 20:02:16 +0000589extern
590IRDirty* unsafeIRDirty_0_N ( Int regparms, Char* name, void* addr,
591 IRExpr** args );
sewardjc5fc7aa2004-10-27 23:00:55 +0000592
593/* Similarly, make a zero-annotation dirty call which returns a value,
594 and assign that to the given temp. */
sewardjf9655262004-10-31 20:02:16 +0000595extern
596IRDirty* unsafeIRDirty_1_N ( IRTemp dst,
597 Int regparms, Char* name, void* addr,
598 IRExpr** args );
sewardjc5fc7aa2004-10-27 23:00:55 +0000599
sewardjb3bce0e2004-09-14 23:20:10 +0000600
sewardjc97096c2004-06-30 09:28:04 +0000601/* ------------------ Statements ------------------ */
sewardjb3bce0e2004-09-14 23:20:10 +0000602
603/* The possible kinds of statements are as follows: */
sewardjac6b7122004-06-27 01:03:57 +0000604typedef
sewardjb3bce0e2004-09-14 23:20:10 +0000605 enum {
606 Ist_Put, /* write guest state, fixed offset */
607 Ist_PutI, /* write guest state, run-time offset */
608 Ist_Tmp, /* assign value to temporary */
609 Ist_STle, /* little-endian write to memory */
610 Ist_Dirty, /* call complex ("dirty") helper function */
611 Ist_Exit /* conditional exit from BB */
612 }
sewardjac6b7122004-06-27 01:03:57 +0000613 IRStmtTag;
614
615typedef
616 struct _IRStmt {
617 IRStmtTag tag;
618 union {
619 struct {
620 Int offset;
sewardj6d076362004-09-23 11:06:17 +0000621 IRExpr* data;
sewardjac6b7122004-06-27 01:03:57 +0000622 } Put;
623 struct {
sewardj2d3f77c2004-09-22 23:49:09 +0000624 IRArray* descr;
sewardjeeac8412004-11-02 00:26:55 +0000625 IRExpr* ix;
sewardj2d3f77c2004-09-22 23:49:09 +0000626 Int bias;
627 IRExpr* data;
sewardjd1725d12004-08-12 20:46:53 +0000628 } PutI;
629 struct {
sewardjac6b7122004-06-27 01:03:57 +0000630 IRTemp tmp;
sewardj6d076362004-09-23 11:06:17 +0000631 IRExpr* data;
sewardjac6b7122004-06-27 01:03:57 +0000632 } Tmp;
633 struct {
sewardjc97096c2004-06-30 09:28:04 +0000634 IRExpr* addr;
635 IRExpr* data;
sewardjac6b7122004-06-27 01:03:57 +0000636 } STle;
sewardj64e1d652004-07-12 14:00:46 +0000637 struct {
sewardjb3bce0e2004-09-14 23:20:10 +0000638 IRDirty* details;
639 } Dirty;
640 struct {
sewardj443cd9d2004-07-18 23:06:45 +0000641 IRExpr* cond;
sewardj64e1d652004-07-12 14:00:46 +0000642 IRConst* dst;
643 } Exit;
sewardjac6b7122004-06-27 01:03:57 +0000644 } Ist;
sewardjac6b7122004-06-27 01:03:57 +0000645 }
646 IRStmt;
sewardjec6ad592004-06-20 12:26:53 +0000647
sewardj6d076362004-09-23 11:06:17 +0000648extern IRStmt* IRStmt_Put ( Int off, IRExpr* data );
sewardjeeac8412004-11-02 00:26:55 +0000649extern IRStmt* IRStmt_PutI ( IRArray* descr, IRExpr* ix, Int bias,
sewardj2d3f77c2004-09-22 23:49:09 +0000650 IRExpr* data );
sewardj6d076362004-09-23 11:06:17 +0000651extern IRStmt* IRStmt_Tmp ( IRTemp tmp, IRExpr* data );
652extern IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* data );
sewardjb3bce0e2004-09-14 23:20:10 +0000653extern IRStmt* IRStmt_Dirty ( IRDirty* details );
654extern IRStmt* IRStmt_Exit ( IRExpr* cond, IRConst* dst );
sewardjec6ad592004-06-20 12:26:53 +0000655
sewardj695cff92004-10-13 14:50:14 +0000656extern IRStmt* dopyIRStmt ( IRStmt* );
657
sewardj35421a32004-07-05 13:12:34 +0000658extern void ppIRStmt ( IRStmt* );
sewardjc97096c2004-06-30 09:28:04 +0000659
660
sewardje539a402004-07-14 18:24:17 +0000661/* ------------------ Basic Blocks ------------------ */
sewardj78c19df2004-07-12 22:49:27 +0000662
sewardje539a402004-07-14 18:24:17 +0000663/* This describes the unconditional jumps which implicitly happen at
664 the end of each basic block. Conditional jumps -- which can only
665 be done with the IRStmt_Exit statement -- are implicitly of the
666 Ijk_Boring kind. */
667
sewardj78c19df2004-07-12 22:49:27 +0000668typedef
669 enum {
sewardje8e9d732004-07-16 21:03:45 +0000670 Ijk_Boring=0x14000, /* not interesting; just goto next */
sewardj78c19df2004-07-12 22:49:27 +0000671 Ijk_Call, /* guest is doing a call */
672 Ijk_Ret, /* guest is doing a return */
673 Ijk_ClientReq, /* do guest client req before continuing */
674 Ijk_Syscall, /* do guest syscall before continuing */
675 Ijk_Yield /* client is yielding to thread scheduler */
676 }
677 IRJumpKind;
678
679extern void ppIRJumpKind ( IRJumpKind );
680
681
sewardjc97096c2004-06-30 09:28:04 +0000682/* A bunch of statements, expressions, etc, are incomplete without an
683 environment indicating the type of each IRTemp. So this provides
sewardje539a402004-07-14 18:24:17 +0000684 one. IR temporaries are really just unsigned ints and so this
685 provides an array, 0 .. n_types_used-1 of them.
sewardjc97096c2004-06-30 09:28:04 +0000686*/
687typedef
sewardjc97096c2004-06-30 09:28:04 +0000688 struct {
sewardje539a402004-07-14 18:24:17 +0000689 IRType* types;
690 Int types_size;
691 Int types_used;
sewardjc97096c2004-06-30 09:28:04 +0000692 }
693 IRTypeEnv;
694
sewardj695cff92004-10-13 14:50:14 +0000695extern IRTemp newIRTemp ( IRTypeEnv*, IRType );
696extern IRTypeEnv* dopyIRTypeEnv ( IRTypeEnv* );
697
sewardj35421a32004-07-05 13:12:34 +0000698extern void ppIRTypeEnv ( IRTypeEnv* );
sewardjc97096c2004-06-30 09:28:04 +0000699
sewardjec6ad592004-06-20 12:26:53 +0000700
sewardjd7cb8532004-08-17 23:59:23 +0000701/* Basic blocks contain:
sewardjc97096c2004-06-30 09:28:04 +0000702 - A table giving a type for each temp
sewardjd7cb8532004-08-17 23:59:23 +0000703 - An expandable array of statements
sewardje539a402004-07-14 18:24:17 +0000704 - An expression of type 32 or 64 bits, depending on the
705 guest's word size, indicating the next destination.
sewardjd7cb8532004-08-17 23:59:23 +0000706 - An indication of any special actions (JumpKind) needed
707 for this final jump.
sewardjec6ad592004-06-20 12:26:53 +0000708*/
sewardjac6b7122004-06-27 01:03:57 +0000709typedef
710 struct _IRBB {
sewardjc97096c2004-06-30 09:28:04 +0000711 IRTypeEnv* tyenv;
sewardjd7cb8532004-08-17 23:59:23 +0000712 IRStmt** stmts;
713 Int stmts_size;
714 Int stmts_used;
sewardje539a402004-07-14 18:24:17 +0000715 IRExpr* next;
716 IRJumpKind jumpkind;
sewardjac6b7122004-06-27 01:03:57 +0000717 }
718 IRBB;
sewardjec6ad592004-06-20 12:26:53 +0000719
sewardjd7cb8532004-08-17 23:59:23 +0000720extern IRBB* emptyIRBB ( void );
sewardj695cff92004-10-13 14:50:14 +0000721
722extern IRBB* dopyIRBB ( IRBB* );
sewardjc97096c2004-06-30 09:28:04 +0000723
sewardj35421a32004-07-05 13:12:34 +0000724extern void ppIRBB ( IRBB* );
sewardjc97096c2004-06-30 09:28:04 +0000725
sewardj695cff92004-10-13 14:50:14 +0000726extern void addStmtToIRBB ( IRBB*, IRStmt* );
727
728
sewardjec6ad592004-06-20 12:26:53 +0000729/*---------------------------------------------------------------*/
sewardjc97096c2004-06-30 09:28:04 +0000730/*--- Helper functions for the IR ---*/
sewardjec6ad592004-06-20 12:26:53 +0000731/*---------------------------------------------------------------*/
732
sewardjc97096c2004-06-30 09:28:04 +0000733/* For messing with IR type environments */
sewardjd7cb8532004-08-17 23:59:23 +0000734extern IRTypeEnv* emptyIRTypeEnv ( void );
sewardjec6ad592004-06-20 12:26:53 +0000735
sewardjc97096c2004-06-30 09:28:04 +0000736/* What is the type of this expression? */
sewardj6efd4a12004-07-15 03:54:23 +0000737extern IRType typeOfIRConst ( IRConst* );
sewardj17442fe2004-09-20 14:54:28 +0000738extern IRType typeOfIRTemp ( IRTypeEnv*, IRTemp );
sewardj6efd4a12004-07-15 03:54:23 +0000739extern IRType typeOfIRExpr ( IRTypeEnv*, IRExpr* );
sewardjec6ad592004-06-20 12:26:53 +0000740
sewardj35439212004-07-14 22:36:10 +0000741/* Sanity check a BB of IR */
742extern void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size );
sewardjcf787902004-11-03 09:08:33 +0000743extern Bool isFlatIRStmt ( IRStmt* );
sewardjec6ad592004-06-20 12:26:53 +0000744
sewardj6d2638e2004-07-15 09:38:27 +0000745/* Is this any value actually in the enumeration 'IRType' ? */
746extern Bool isPlausibleType ( IRType ty );
747
sewardj887a11a2004-07-05 17:26:47 +0000748#endif /* ndef __LIBVEX_IR_H */
sewardjac9af022004-07-05 01:15:34 +0000749
750
751/*---------------------------------------------------------------*/
sewardj887a11a2004-07-05 17:26:47 +0000752/*--- libvex_ir.h ---*/
sewardjac9af022004-07-05 01:15:34 +0000753/*---------------------------------------------------------------*/