libvex_ir.h revision 636ad762e49597ef608323f27c7b8eb66962cd90
1
2/*---------------------------------------------------------------*/
3/*---                                                         ---*/
4/*--- This file (libvex_ir.h) is                              ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
6/*---                                                         ---*/
7/*---------------------------------------------------------------*/
8
9/*
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
36#ifndef __LIBVEX_IR_H
37#define __LIBVEX_IR_H
38
39#include "libvex_basictypes.h"
40
41
42/*---------------------------------------------------------------*/
43/*--- Type definitions for the IR                             ---*/
44/*---------------------------------------------------------------*/
45
46/* ------------------ Types ------------------ */
47
48typedef
49   enum {
50      Ity_INVALID=0x10FFF,
51      Ity_I1=0x11000,
52      Ity_I8,
53      Ity_I16,
54      Ity_I32,
55      Ity_I64,
56      Ity_F32,   /* IEEE 754 float */
57      Ity_F64,   /* IEEE 754 double */
58      Ity_V128   /* 128-bit SIMD */
59   }
60   IRType;
61
62extern void ppIRType ( IRType );
63extern Int  sizeofIRType ( IRType );
64
65
66/* ------------------ Constants ------------------ */
67
68typedef
69   enum {
70      Ico_U1=0x12000,
71      Ico_U8,
72      Ico_U16,
73      Ico_U32,
74      Ico_U64,
75      Ico_F64,   /* 64-bit IEEE754 floating */
76      Ico_F64i,  /* 64-bit unsigned int to be interpreted literally
77                    as a IEEE754 double value. */
78      Ico_V128   /* 128-bit restricted vector constant, with 1 bit for
79                    each of 16 byte lanes */
80   }
81   IRConstTag;
82
83typedef
84   struct _IRConst {
85      IRConstTag tag;
86      union {
87         Bool   U1;
88         UChar  U8;
89         UShort U16;
90         UInt   U32;
91         ULong  U64;
92         Double F64;
93         ULong  F64i;
94         UShort V128;
95      } Ico;
96   }
97   IRConst;
98
99extern IRConst* IRConst_U1   ( Bool );
100extern IRConst* IRConst_U8   ( UChar );
101extern IRConst* IRConst_U16  ( UShort );
102extern IRConst* IRConst_U32  ( UInt );
103extern IRConst* IRConst_U64  ( ULong );
104extern IRConst* IRConst_F64  ( Double );
105extern IRConst* IRConst_F64i ( ULong );
106extern IRConst* IRConst_V128 ( UShort );
107
108extern IRConst* dopyIRConst ( IRConst* );
109
110extern void ppIRConst ( IRConst* );
111extern Bool eqIRConst ( IRConst*, IRConst* );
112
113
114/* ------------------ Call targets ------------------ */
115
116/* Describes a helper function to call.  The name part is purely for
117   pretty printing and not actually used.  regparms=n tells the back
118   end that the callee has been declared
119   "__attribute__((regparm(n)))".  On some targets (x86) the back end
120   will need to construct a non-standard sequence to call a function
121   declared like this.
122
123   mcx_mask is a sop to Memcheck.  It indicates which args should be
124   considered 'always defined' when lazily computing definedness of
125   the result.  Bit 0 of mcx_mask corresponds to args[0], bit 1 to
126   args[1], etc.  If a bit is set, the corresponding arg is excluded
127   (hence "x" in "mcx") from definedness checking.
128*/
129
130typedef
131   struct {
132      Int   regparms;
133      Char* name;
134      void* addr;
135      UInt  mcx_mask;
136   }
137   IRCallee;
138
139extern IRCallee* mkIRCallee ( Int regparms, Char* name, void* addr );
140
141extern IRCallee* dopyIRCallee ( IRCallee* );
142
143extern void ppIRCallee ( IRCallee* );
144
145
146/* ------------------ Guest state arrays ------------------ */
147
148typedef
149   struct {
150      Int    base;
151      IRType elemTy;
152      Int    nElems;
153   }
154   IRArray;
155
156extern IRArray* mkIRArray ( Int, IRType, Int );
157
158extern IRArray* dopyIRArray ( IRArray* );
159
160extern void ppIRArray ( IRArray* );
161extern Bool eqIRArray ( IRArray*, IRArray* );
162
163
164/* ------------------ Temporaries ------------------ */
165
166/* The IR optimiser relies on the fact that IRTemps are 32-bit
167   ints.  Do not change them to be ints of any other size. */
168typedef UInt IRTemp;
169
170extern void ppIRTemp ( IRTemp );
171
172#define IRTemp_INVALID ((IRTemp)0xFFFFFFFF)
173
174
175/* ------------------ Binary and unary ops ------------------ */
176
177typedef
178   enum {
179      /* Do not change this ordering.  The IR generators
180         rely on (eg) Iop_Add64 == IopAdd8 + 3. */
181      Iop_INVALID=0x13000,
182      Iop_Add8,  Iop_Add16,  Iop_Add32,  Iop_Add64,
183      Iop_Sub8,  Iop_Sub16,  Iop_Sub32,  Iop_Sub64,
184      /* Signless mul.  MullS/MullU is elsewhere. */
185      Iop_Mul8,  Iop_Mul16,  Iop_Mul32,  Iop_Mul64,
186      Iop_Or8,   Iop_Or16,   Iop_Or32,   Iop_Or64,
187      Iop_And8,  Iop_And16,  Iop_And32,  Iop_And64,
188      Iop_Xor8,  Iop_Xor16,  Iop_Xor32,  Iop_Xor64,
189      Iop_Shl8,  Iop_Shl16,  Iop_Shl32,  Iop_Shl64,
190      Iop_Shr8,  Iop_Shr16,  Iop_Shr32,  Iop_Shr64,
191      Iop_Sar8,  Iop_Sar16,  Iop_Sar32,  Iop_Sar64,
192      /* Integer comparisons. */
193      Iop_CmpEQ8,  Iop_CmpEQ16,  Iop_CmpEQ32,  Iop_CmpEQ64,
194      Iop_CmpNE8,  Iop_CmpNE16,  Iop_CmpNE32,  Iop_CmpNE64,
195      /* Tags for unary ops */
196      Iop_Not8,  Iop_Not16,  Iop_Not32,  Iop_Not64,
197      /* Widening multiplies */
198      Iop_MullS8, Iop_MullS16, Iop_MullS32,
199      Iop_MullU8, Iop_MullU16, Iop_MullU32,
200
201      /* Wierdo integer stuff */
202      Iop_Clz32,   /* count leading zeroes */
203      Iop_Ctz32,   /* count trailing zeros */
204      /* Ctz32/Clz32 are UNDEFINED when given arguments of zero.
205         You must ensure they are never given a zero argument.
206      */
207
208      /* Ordering not important after here. */
209      Iop_CmpLT32S,
210      Iop_CmpLE32S,
211      Iop_CmpLT32U,
212      Iop_CmpLE32U,
213      /* Division */
214      /* TODO: clarify semantics wrt rounding, negative values, whatever */
215      Iop_DivModU64to32, // :: I64,I32 -> I64
216                         // of which lo half is div and hi half is mod
217      Iop_DivModS64to32, // ditto, signed
218
219      /* Widening conversions */
220      Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, Iop_32Uto64,
221      Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, Iop_32Sto64,
222      /* Narrowing conversions */
223      Iop_32to8,
224      /* 8 <-> 16 bit conversions */
225      Iop_16to8,      // :: I16 -> I8, low half
226      Iop_16HIto8,    // :: I16 -> I8, high half
227      Iop_8HLto16,    // :: (I8,I8) -> I16
228      /* 16 <-> 32 bit conversions */
229      Iop_32to16,     // :: I32 -> I16, low half
230      Iop_32HIto16,   // :: I32 -> I16, high half
231      Iop_16HLto32,   // :: (I16,I16) -> I32
232      /* 32 <-> 64 bit conversions */
233      Iop_64to32,     // :: I64 -> I32, low half
234      Iop_64HIto32,   // :: I64 -> I32, high half
235      Iop_32HLto64,   // :: (I32,I32) -> I64
236      /* 1-bit stuff */
237      Iop_Not1,   /* :: Ity_Bit -> Ity_Bit */
238      Iop_32to1,  /* :: Ity_I32 -> Ity_Bit, just select bit[0] */
239      Iop_1Uto8,  /* :: Ity_Bit -> Ity_I8, unsigned widen */
240      Iop_1Uto32, /* :: Ity_Bit -> Ity_I32, unsigned widen */
241      Iop_1Sto8,  /* :: Ity_Bit -> Ity_I8,  signed widen */
242      Iop_1Sto16, /* :: Ity_Bit -> Ity_I16, signed widen */
243      Iop_1Sto32, /* :: Ity_Bit -> Ity_I32, signed widen */
244      Iop_1Sto64, /* :: Ity_Bit -> Ity_I64, signed widen */
245
246      /* ------ Floating point.  We try and be IEEE754 compliant. ------ */
247
248      /* Binary operations mandated by IEEE754. */
249      Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64, /* Iop_RemF64, */
250
251      /* Binary ops supported by IA32 but not mandated by 754. */
252      Iop_AtanF64,       /* FPATAN,  arctan(arg1/arg2)       */
253      Iop_Yl2xF64,       /* FYL2X,   arg1 * log2(arg2)       */
254      Iop_Yl2xp1F64,     /* FYL2XP1, arg1 * log2(arg2+1.0)   */
255      Iop_PRemF64,       /* FPREM,   non-IEEE remainder(arg1/arg2)    */
256      Iop_PRemC3210F64,  /* C3210 flags resulting from FPREM, :: I32 */
257      Iop_PRem1F64,      /* FPREM1,  IEEE remainder(arg1/arg2)    */
258      Iop_PRem1C3210F64, /* C3210 flags resulting from FPREM1, :: I32 */
259      Iop_ScaleF64,      /* FSCALE,  arg1 * (2^RoundTowardsZero(arg2)) */
260      /* Note that on x86 guest, PRem1{C3210} has the same behaviour
261         as the IEEE mandated RemF64, except it is limited in the
262         range of its operand.  Hence the partialness. */
263
264      /* Unary operations mandated by IEEE754. */
265      Iop_NegF64, Iop_SqrtF64,
266
267      /* Unary ops supported by IA32 but not mandated by 754. */
268      Iop_AbsF64,    /* FABS */
269      Iop_SinF64,    /* FSIN */
270      Iop_CosF64,    /* FCOS */
271      Iop_TanF64,    /* FTAN */
272      Iop_2xm1F64,   /* (2^arg - 1.0) */
273
274      /* Comparison, yielding GT/LT/EQ/UN(ordered), as per the following:
275            0x45 Unordered
276            0x01 LT
277            0x00 GT
278            0x40 EQ
279         This just happens to be the Intel encoding.  The values
280         are recorded in the type IRCmpF64Result.
281      */
282      Iop_CmpF64,
283
284      /* --- Int to/from FP conversions. --- */
285      /* For the most part, these take a first argument :: Ity_I32
286	 (as IRRoundingMode) which is an indication of the rounding
287         mode to use, as per the following encoding:
288            00b  to nearest (the default)
289            01b  to -infinity
290            10b  to +infinity
291            11b  to zero
292         This just happens to be the Intel encoding.  For reference only,
293         the PPC encoding is:
294            00b  to nearest (the default)
295            01b  to zero
296            10b  to +infinity
297            11b  to -infinity
298         Any PPC -> IR front end will have to translate these PPC
299         encodings to the standard encodings.
300
301         If one of these conversions gets an out-of-range condition,
302         or a NaN, as an argument, the result is host-defined.  On x86
303         the "integer indefinite" value 0x80..00 is produced.
304         On PPC it is either 0x80..00 or 0x7F..FF depending on the sign
305         of the argument.
306
307         Rounding is required whenever the destination type cannot
308         represent exactly all values of the source type.
309      */
310      Iop_F64toI16,  /* IRRoundingMode(I32) x F64 -> I16 */
311      Iop_F64toI32,  /* IRRoundingMode(I32) x F64 -> I32 */
312      Iop_F64toI64,  /* IRRoundingMode(I32) x F64 -> I64 */
313
314      Iop_I16toF64,  /*                       I16 -> F64 */
315      Iop_I32toF64,  /*                       I32 -> F64 */
316      Iop_I64toF64,  /* IRRoundingMode(I32) x I64 -> F64 */
317
318      Iop_F32toF64,  /*                       F32 -> F64 */
319      Iop_F64toF32,  /* IRRoundingMode(I32) x F64 -> F32 */
320
321      /* F64 -> F64, also takes an I32 first argument encoding the
322         rounding mode. */
323      Iop_RoundF64,
324
325      /* Reinterpretation.  Take an F64 and produce an I64 with
326         the same bit pattern, or vice versa. */
327      Iop_ReinterpF64asI64, Iop_ReinterpI64asF64,
328
329      /* ------------------ 128-bit SIMD. ------------------ */
330
331      /* 128-bit ops */
332      Iop_And128, Iop_Or128, Iop_Xor128,
333
334      /* --- 32x4 vector FP --- */
335
336      /* binary */
337      Iop_Add32Fx4, Iop_Sub32Fx4, Iop_Mul32Fx4, Iop_Div32Fx4,
338      Iop_Max32Fx4, Iop_Min32Fx4,
339      Iop_CmpEQ32Fx4, Iop_CmpLT32Fx4, Iop_CmpLE32Fx4, Iop_CmpUN32Fx4,
340
341      /* unary */
342      Iop_Recip32Fx4, Iop_Sqrt32Fx4, Iop_RSqrt32Fx4,
343
344      /* --- 32x4 lowest-lane-only scalar FP --- */
345
346      /* In binary cases, upper 3/4 is copied from first operand.  In
347	 unary cases, upper 3/4 is copied from the operand. */
348
349      /* binary */
350      Iop_Add32F0x4, Iop_Sub32F0x4, Iop_Mul32F0x4, Iop_Div32F0x4,
351      Iop_Max32F0x4, Iop_Min32F0x4,
352      Iop_CmpEQ32F0x4, Iop_CmpLT32F0x4, Iop_CmpLE32F0x4, Iop_CmpUN32F0x4,
353
354      /* unary */
355      Iop_Recip32F0x4, Iop_Sqrt32F0x4, Iop_RSqrt32F0x4,
356
357      /* --- 64x2 vector FP --- */
358
359      /* binary */
360      Iop_Add64Fx2, Iop_Sub64Fx2, Iop_Mul64Fx2, Iop_Div64Fx2,
361      Iop_Max64Fx2, Iop_Min64Fx2,
362      Iop_CmpEQ64Fx2, Iop_CmpLT64Fx2, Iop_CmpLE64Fx2, Iop_CmpUN64Fx2,
363
364      /* unary */
365      Iop_Recip64Fx2, Iop_Sqrt64Fx2, Iop_RSqrt64Fx2,
366
367      /* --- 64x2 lowest-lane-only scalar FP --- */
368
369      /* In binary cases, upper half is copied from first operand.  In
370	 unary cases, upper half is copied from the operand. */
371
372      /* binary */
373      Iop_Add64F0x2, Iop_Sub64F0x2, Iop_Mul64F0x2, Iop_Div64F0x2,
374      Iop_Max64F0x2, Iop_Min64F0x2,
375      Iop_CmpEQ64F0x2, Iop_CmpLT64F0x2, Iop_CmpLE64F0x2, Iop_CmpUN64F0x2,
376
377      /* unary */
378      Iop_Recip64F0x2, Iop_Sqrt64F0x2, Iop_RSqrt64F0x2,
379
380      /* --- pack / unpack --- */
381
382      /* 64 <-> 128 bit pack/unpack */
383      Iop_128to64,     // :: V128 -> I64, low half
384      Iop_128HIto64,   // :: V128 -> I64, high half
385      Iop_64HLto128,   // :: (I64,I64) -> V128
386
387      Iop_32Uto128,
388      Iop_64Uto128,
389      Iop_Set128lo32,
390      /* 128 -> 32 bit unpack */
391      //Iop_128W3to32,   // :: V128 -> I32, bits 127-96
392      //Iop_128W2to32,   // :: V128 -> I32, bits 95-64
393      //Iop_128W1to32,   // :: V128 -> I32, bits 63-32
394      //Iop_128W0to32    // :: V128 -> I32, bits 31-0
395   }
396   IROp;
397
398extern void ppIROp ( IROp );
399
400
401/* Encoding of IEEE754-specified rounding modes in Float -> Int
402   conversions.  This is the same as the encoding used by Intel IA32
403   to indicate x87 rounding mode. */
404typedef
405   enum { Irrm_NEAREST=0, Irrm_NegINF=1, Irrm_PosINF=2, Irrm_ZERO=3 }
406   IRRoundingMode;
407
408/* Floating point comparison result values, as created by Iop_CmpF64.
409   This is also derived from what IA32 does. */
410typedef
411   enum {
412      Ircr_UN = 0x45,
413      Ircr_LT = 0x01,
414      Ircr_GT = 0x00,
415      Ircr_EQ = 0x40
416   }
417   IRCmpF64Result;
418
419
420/* ------------------ Expressions ------------------ */
421/*
422   Some details of expression semantics:
423
424   IRExpr_GetI (also IRStmt_PutI)
425   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
426   This carries two ints, which give the lowest and highest possible
427   byte offsets that the GetI can possibly reference.  For example, if
428   the type is Ity_I32, and the Expr may have a value of M, M+4 or
429   M+8, where M is a translation-time known constant, then the low and
430   high limits are M and M+11 respectively.
431
432   PutI's limit values are interpreted identically.
433
434   The limit values are used by IR optimisers to establish
435   aliasing/non-aliasing between seperate GetI and PutI events, which
436   could be used to do reordering of them, or suchlike things.
437   Clearly it's critical to give the correct limit values -- this is
438   something that can't be automatically checked (in general), and so
439   the front-end writers must be very careful to tell the truth, since
440   not doing so could lead to obscure IR optimisation bugs.
441
442   IRExpr_CCall
443   ~~~~~~~~~~~~
444   The name is the C helper function; the backends will call back to
445   the front ends to get the address of a host-code helper function to
446   be called.
447
448   The args are a NULL-terminated array of arguments.  The stated
449   return IRType, and the implied argument types, must match that of
450   the function being called well enough so that the back end can
451   actually generate correct code for the call.
452
453   The called function **must** satisfy the following:
454
455   * no side effects -- must be a pure function, the result of which
456     depends only on the passed parameters.
457
458   * it may not look at, nor modify, any of the guest state since that
459     would hide guest state transitions from instrumenters
460
461   * it may not access guest memory, since that would hide guest
462     memory transactions from the instrumenters
463
464   This is restrictive, but makes the semantics clean, and does
465   not interfere with IR optimisation.
466
467   If you want to call a helper which can mess with guest state and/or
468   memory, instead use IRStmt_Dirty.  This is a lot more flexible, but
469   you pay for that flexibility in that you have to give a bunch of
470   details about what the helper does (and you better be telling the
471   truth, otherwise any derived instrumentation will be wrong).  Also
472   IRStmt_Dirty inhibits various IR optimisations and so can cause
473   quite poor code to be generated.  Try to avoid it.
474*/
475
476/* The possible kinds of expressions are as follows: */
477typedef
478   enum {
479      Iex_Binder,  /* Used only in pattern matching.
480                      Not an expression. */
481      Iex_Get,     /* read guest state, fixed offset */
482      Iex_GetI,    /* read guest state, run-time offset */
483      Iex_Tmp,     /* value of temporary */
484      Iex_Binop,   /* binary operation */
485      Iex_Unop,    /* unary operation */
486      Iex_LDle,    /* little-endian read from memory */
487      Iex_Const,   /* constant-valued expression */
488      Iex_Mux0X,   /* ternary if-then-else operator (STRICT) */
489      Iex_CCall    /* call to pure (side-effect-free) helper fn */
490   }
491   IRExprTag;
492
493typedef
494   struct _IRExpr {
495      IRExprTag tag;
496      union {
497	 struct {
498            Int binder;
499         } Binder;
500         struct {
501            Int    offset;
502            IRType ty;
503         } Get;
504         struct {
505            IRArray* descr;
506            struct _IRExpr* ix;
507            Int bias;
508         } GetI;
509         struct {
510            IRTemp tmp;
511         } Tmp;
512         struct {
513            IROp op;
514            struct _IRExpr* arg1;
515            struct _IRExpr* arg2;
516         } Binop;
517         struct {
518            IROp op;
519            struct _IRExpr* arg;
520         } Unop;
521         struct {
522            IRType ty;
523            struct _IRExpr* addr;
524         } LDle;
525         struct {
526            IRConst* con;
527         } Const;
528         struct {
529            IRCallee* cee;
530            IRType    retty;
531            struct _IRExpr** args;
532         }  CCall;
533         struct {
534            struct _IRExpr* cond;
535            struct _IRExpr* expr0;
536            struct _IRExpr* exprX;
537         } Mux0X;
538      } Iex;
539   }
540   IRExpr;
541
542extern IRExpr* IRExpr_Binder ( Int binder );
543extern IRExpr* IRExpr_Get    ( Int off, IRType ty );
544extern IRExpr* IRExpr_GetI   ( IRArray* descr, IRExpr* ix, Int bias );
545extern IRExpr* IRExpr_Tmp    ( IRTemp tmp );
546extern IRExpr* IRExpr_Binop  ( IROp op, IRExpr* arg1, IRExpr* arg2 );
547extern IRExpr* IRExpr_Unop   ( IROp op, IRExpr* arg );
548extern IRExpr* IRExpr_LDle   ( IRType ty, IRExpr* addr );
549extern IRExpr* IRExpr_Const  ( IRConst* con );
550extern IRExpr* IRExpr_CCall  ( IRCallee* cee, IRType retty, IRExpr** args );
551extern IRExpr* IRExpr_Mux0X  ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX );
552
553extern IRExpr* dopyIRExpr ( IRExpr* );
554
555extern void ppIRExpr ( IRExpr* );
556
557/* NULL-terminated IRExpr expression vectors, suitable for use as arg
558   lists in clean/dirty helper calls. */
559
560extern IRExpr** mkIRExprVec_0 ( void );
561extern IRExpr** mkIRExprVec_1 ( IRExpr* );
562extern IRExpr** mkIRExprVec_2 ( IRExpr*, IRExpr* );
563extern IRExpr** mkIRExprVec_3 ( IRExpr*, IRExpr*, IRExpr* );
564extern IRExpr** mkIRExprVec_4 ( IRExpr*, IRExpr*, IRExpr*, IRExpr* );
565extern IRExpr** mkIRExprVec_5 ( IRExpr*, IRExpr*,
566                                IRExpr*, IRExpr*, IRExpr* );
567
568extern IRExpr** sopyIRExprVec ( IRExpr** );
569extern IRExpr** dopyIRExprVec ( IRExpr** );
570
571/* Make a constant expression from the given host word taking into
572   account of course the host word size. */
573extern IRExpr* mkIRExpr_HWord ( HWord );
574
575/* Convenience function for constructing clean helper calls. */
576extern
577IRExpr* mkIRExprCCall ( IRType retty,
578                        Int regparms, Char* name, void* addr,
579                        IRExpr** args );
580
581
582inline static Bool isAtom ( IRExpr* e ) {
583   return e->tag == Iex_Tmp || e->tag == Iex_Const;
584}
585
586
587/* ------------------ Jump kinds ------------------ */
588
589/* This describes hints which can be passed to the dispatcher at guest
590   control-flow transfer points.
591*/
592typedef
593   enum {
594      Ijk_Boring=0x14000, /* not interesting; just goto next */
595      Ijk_Call,           /* guest is doing a call */
596      Ijk_Ret,            /* guest is doing a return */
597      Ijk_ClientReq,      /* do guest client req before continuing */
598      Ijk_Syscall,        /* do guest syscall before continuing */
599      Ijk_Yield,          /* client is yielding to thread scheduler */
600      Ijk_EmWarn          /* report emulation warning before continuing */
601   }
602   IRJumpKind;
603
604extern void ppIRJumpKind ( IRJumpKind );
605
606
607/* ------------------ Dirty helper calls ------------------ */
608
609/* A dirty call is a flexible mechanism for calling a helper function
610   or procedure.  The helper function may read, write or modify client
611   memory, and may read, write or modify client state.  It can take
612   arguments and optionally return a value.  It may return different
613   results and/or do different things when called repeated with the
614   same arguments, by means of storing private state.
615
616   If a value is returned, it is assigned to the nominated return
617   temporary.
618
619   Dirty calls are statements rather than expressions for obvious
620   reasons.  If a dirty call is stated as writing guest state, any
621   values derived from the written parts of the guest state are
622   invalid.  Similarly, if the dirty call is stated as writing
623   memory, any loaded values are invalidated by it.
624
625   In order that instrumentation is possible, the call must state, and
626   state correctly
627
628   * whether it reads, writes or modifies memory, and if so where
629     (only one chunk can be stated)
630
631   * whether it reads, writes or modifies guest state, and if so which
632     pieces (several pieces may be stated, and currently their extents
633     must be known at translation-time).
634
635   Normally, code is generated to pass just the args to the helper.
636   However, if .needsBBP is set, then an extra first argument is
637   passed, which is the baseblock pointer, so that the callee can
638   access the guest state.  It is invalid for .nFxState to be zero
639   but .needsBBP to be True, since .nFxState==0 is a claim that the
640   call does not access guest state.
641
642   IMPORTANT NOTE re GUARDS: Dirty calls are strict, very strict.  The
643   arguments are evaluated REGARDLESS of the guard value.  It is
644   unspecified the relative order of arg evaluation and guard
645   evaluation.
646*/
647
648#define VEX_N_FXSTATE  5   /* enough for FSAVE/FRSTOR on x86 */
649
650typedef
651   enum {
652      Ifx_None = 0x15000,   /* no effect */
653      Ifx_Read,             /* reads the resource */
654      Ifx_Write,            /* writes the resource */
655      Ifx_Modify,           /* modifies the resource */
656   }
657   IREffect;
658
659extern void ppIREffect ( IREffect );
660
661
662typedef
663   struct {
664      /* What to call, and details of args/results */
665      IRCallee* cee;    /* where to call */
666      IRExpr*   guard;  /* :: Ity_Bit.  Controls whether call happens */
667      IRExpr**  args;   /* arg list, ends in NULL */
668      IRTemp    tmp;    /* to assign result to, or IRTemp_INVALID if none */
669
670      /* Mem effects; we allow only one R/W/M region to be stated */
671      IREffect  mFx;    /* indicates memory effects, if any */
672      IRExpr*   mAddr;  /* of access, or NULL if mFx==Ifx_None */
673      Int       mSize;  /* of access, or zero if mFx==Ifx_None */
674
675      /* Guest state effects; up to N allowed */
676      Bool needsBBP; /* True => also pass guest state ptr to callee */
677      Int  nFxState; /* must be 0 .. VEX_N_FXSTATE */
678      struct {
679         IREffect fx;   /* read, write or modify?  Ifx_None is invalid. */
680         Int      offset;
681         Int      size;
682      } fxState[VEX_N_FXSTATE];
683   }
684   IRDirty;
685
686extern void     ppIRDirty ( IRDirty* );
687extern IRDirty* emptyIRDirty ( void );
688
689extern IRDirty* dopyIRDirty ( IRDirty* );
690
691/* A handy function which takes some of the tedium out of constructing
692   dirty helper calls.  The called function impliedly does not return
693   any value and has a constant-True guard.  The call is marked as
694   accessing neither guest state nor memory (hence the "unsafe"
695   designation) -- you can mess with this later if need be.  A
696   suitable IRCallee is constructed from the supplied bits. */
697extern
698IRDirty* unsafeIRDirty_0_N ( Int regparms, Char* name, void* addr,
699                             IRExpr** args );
700
701/* Similarly, make a zero-annotation dirty call which returns a value,
702   and assign that to the given temp. */
703extern
704IRDirty* unsafeIRDirty_1_N ( IRTemp dst,
705                             Int regparms, Char* name, void* addr,
706                             IRExpr** args );
707
708
709/* ------------------ Statements ------------------ */
710
711/* The possible kinds of statements are as follows: */
712typedef
713   enum {
714      Ist_Put,    /* write guest state, fixed offset */
715      Ist_PutI,   /* write guest state, run-time offset */
716      Ist_Tmp,    /* assign value to temporary */
717      Ist_STle,   /* little-endian write to memory */
718      Ist_Dirty,  /* call complex ("dirty") helper function */
719      Ist_Exit    /* conditional exit from BB */
720   }
721   IRStmtTag;
722
723typedef
724   struct _IRStmt {
725      IRStmtTag tag;
726      union {
727         struct {
728            Int     offset;
729            IRExpr* data;
730         } Put;
731         struct {
732            IRArray* descr;
733            IRExpr*  ix;
734            Int      bias;
735            IRExpr*  data;
736         } PutI;
737         struct {
738            IRTemp  tmp;
739            IRExpr* data;
740         } Tmp;
741         struct {
742            IRExpr* addr;
743            IRExpr* data;
744         } STle;
745         struct {
746            IRDirty* details;
747         } Dirty;
748         struct {
749            IRExpr*    guard;
750            IRJumpKind jk;
751            IRConst*   dst;
752         } Exit;
753      } Ist;
754   }
755   IRStmt;
756
757extern IRStmt* IRStmt_Put   ( Int off, IRExpr* data );
758extern IRStmt* IRStmt_PutI  ( IRArray* descr, IRExpr* ix, Int bias,
759                              IRExpr* data );
760extern IRStmt* IRStmt_Tmp   ( IRTemp tmp, IRExpr* data );
761extern IRStmt* IRStmt_STle  ( IRExpr* addr, IRExpr* data );
762extern IRStmt* IRStmt_Dirty ( IRDirty* details );
763extern IRStmt* IRStmt_Exit  ( IRExpr* guard, IRJumpKind jk, IRConst* dst );
764
765extern IRStmt* dopyIRStmt ( IRStmt* );
766
767extern void ppIRStmt ( IRStmt* );
768
769
770/* ------------------ Basic Blocks ------------------ */
771
772/* A bunch of statements, expressions, etc, are incomplete without an
773   environment indicating the type of each IRTemp.  So this provides
774   one.  IR temporaries are really just unsigned ints and so this
775   provides an array, 0 .. n_types_used-1 of them.
776*/
777typedef
778   struct {
779      IRType* types;
780      Int     types_size;
781      Int     types_used;
782   }
783   IRTypeEnv;
784
785extern IRTemp     newIRTemp     ( IRTypeEnv*, IRType );
786extern IRTypeEnv* dopyIRTypeEnv ( IRTypeEnv* );
787
788extern void ppIRTypeEnv ( IRTypeEnv* );
789
790
791/* Basic blocks contain:
792   - A table giving a type for each temp
793   - An expandable array of statements
794   - An expression of type 32 or 64 bits, depending on the
795     guest's word size, indicating the next destination.
796   - An indication of any special actions (JumpKind) needed
797     for this final jump.
798*/
799typedef
800   struct _IRBB {
801      IRTypeEnv* tyenv;
802      IRStmt**   stmts;
803      Int        stmts_size;
804      Int        stmts_used;
805      IRExpr*    next;
806      IRJumpKind jumpkind;
807   }
808   IRBB;
809
810extern IRBB* emptyIRBB ( void );
811
812extern IRBB* dopyIRBB ( IRBB* );
813
814extern void ppIRBB ( IRBB* );
815
816extern void addStmtToIRBB ( IRBB*, IRStmt* );
817
818
819/*---------------------------------------------------------------*/
820/*--- Helper functions for the IR                             ---*/
821/*---------------------------------------------------------------*/
822
823/* For messing with IR type environments */
824extern IRTypeEnv* emptyIRTypeEnv  ( void );
825
826/* What is the type of this expression? */
827extern IRType typeOfIRConst ( IRConst* );
828extern IRType typeOfIRTemp  ( IRTypeEnv*, IRTemp );
829extern IRType typeOfIRExpr  ( IRTypeEnv*, IRExpr* );
830
831/* Sanity check a BB of IR */
832extern void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size );
833extern Bool isFlatIRStmt ( IRStmt* );
834
835/* Is this any value actually in the enumeration 'IRType' ? */
836extern Bool isPlausibleType ( IRType ty );
837
838#endif /* ndef __LIBVEX_IR_H */
839
840
841/*---------------------------------------------------------------*/
842/*---                                             libvex_ir.h ---*/
843/*---------------------------------------------------------------*/
844