libvex_ir.h revision 84ff0657940e62f38e618ea18bac6f27ce0e741f
1
2/*---------------------------------------------------------------*/
3/*---                                                         ---*/
4/*--- This file (libvex_ir.h) is                              ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved. ---*/
6/*---                                                         ---*/
7/*---------------------------------------------------------------*/
8
9#ifndef __LIBVEX_IR_H
10#define __LIBVEX_IR_H
11
12#include "libvex_basictypes.h"
13
14
15/*---------------------------------------------------------------*/
16/*--- Type definitions for the IR                             ---*/
17/*---------------------------------------------------------------*/
18
19/* ------------------ Types ------------------ */
20
21typedef
22   enum { Ity_INVALID=0x10FFF,
23          Ity_Bit=0x11000,
24          Ity_I8, Ity_I16, Ity_I32, Ity_I64,
25          Ity_F32, Ity_F64
26   }
27   IRType;
28
29extern void ppIRType ( IRType );
30
31
32/* ------------------ Constants ------------------ */
33
34typedef
35   enum { Ico_Bit=0x12000,
36          Ico_U8, Ico_U16, Ico_U32, Ico_U64, Ico_F64 }
37   IRConstTag;
38
39typedef
40   struct _IRConst {
41      IRConstTag tag;
42      union {
43         Bool   Bit;
44         UChar  U8;
45         UShort U16;
46         UInt   U32;
47         ULong  U64;
48         Double F64;
49      } Ico;
50   }
51   IRConst;
52
53extern IRConst* IRConst_Bit ( Bool );
54extern IRConst* IRConst_U8  ( UChar );
55extern IRConst* IRConst_U16 ( UShort );
56extern IRConst* IRConst_U32 ( UInt );
57extern IRConst* IRConst_U64 ( ULong );
58extern IRConst* IRConst_F64 ( Double );
59
60extern void ppIRConst ( IRConst* );
61
62
63/* ------------------ Temporaries ------------------ */
64
65typedef UInt IRTemp;
66
67extern void ppIRTemp ( IRTemp );
68
69#define INVALID_IRTEMP ((IRTemp)0xFFFFFFFF)
70
71
72/* ------------------ Binary and unary ops ------------------ */
73
74typedef
75   enum {
76      /* Do not change this ordering.  The IR generators
77         rely on (eg) Iop_Add64 == IopAdd8 + 3. */
78      Iop_INVALID=0x13000,
79      Iop_Add8,  Iop_Add16,  Iop_Add32,  Iop_Add64,
80      Iop_Sub8,  Iop_Sub16,  Iop_Sub32,  Iop_Sub64,
81      /* Signless mul.  MullS/MullU is elsewhere. */
82      Iop_Mul8,  Iop_Mul16,  Iop_Mul32,  Iop_Mul64,
83      Iop_Or8,   Iop_Or16,   Iop_Or32,   Iop_Or64,
84      Iop_And8,  Iop_And16,  Iop_And32,  Iop_And64,
85      Iop_Xor8,  Iop_Xor16,  Iop_Xor32,  Iop_Xor64,
86      Iop_Shl8,  Iop_Shl16,  Iop_Shl32,  Iop_Shl64,
87      Iop_Shr8,  Iop_Shr16,  Iop_Shr32,  Iop_Shr64,
88      Iop_Sar8,  Iop_Sar16,  Iop_Sar32,  Iop_Sar64,
89      /* Integer comparisons. */
90      Iop_CmpEQ8,  Iop_CmpEQ16,  Iop_CmpEQ32,  Iop_CmpEQ64,
91      Iop_CmpNE8,  Iop_CmpNE16,  Iop_CmpNE32,  Iop_CmpNE64,
92      /* Tags for unary ops */
93      Iop_Not8,  Iop_Not16,  Iop_Not32,  Iop_Not64,
94      Iop_Neg8,  Iop_Neg16,  Iop_Neg32,  Iop_Neg64,
95      /* Widening multiplies */
96      Iop_MullS8, Iop_MullS16, Iop_MullS32,
97      Iop_MullU8, Iop_MullU16, Iop_MullU32,
98      /* Ordering not important after here. */
99      Iop_CmpLT32S,
100      Iop_CmpLE32S,
101      Iop_CmpLT32U,
102      Iop_CmpLE32U,
103      /* Division */
104      Iop_DivModU64to32, // :: I64,I32 -> I64
105                         // of which lo half is div and hi half is mod
106      Iop_DivModS64to32, // ditto, signed
107      /* Widening conversions */
108      Iop_8Uto16, Iop_8Uto32, Iop_16Uto32,
109      Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, Iop_32Sto64,
110      /* Narrowing conversions */
111      Iop_32to8,
112      /* 8 <-> 16 bit conversions */
113      Iop_16to8,      // :: I16 -> I8, low half
114      Iop_16HIto8,    // :: I16 -> I8, high half
115      Iop_8HLto16,    // :: (I8,I8) -> I16
116      /* 16 <-> 32 bit conversions */
117      Iop_32to16,     // :: I32 -> I16, low half
118      Iop_32HIto16,   // :: I32 -> I16, high half
119      Iop_16HLto32,   // :: (I16,I16) -> I32
120      /* 32 <-> 64 bit conversions */
121      Iop_64to32,     // :: I64 -> I32, low half
122      Iop_64HIto32,   // :: I64 -> I32, high half
123      Iop_32HLto64,   // :: (I32,I32) -> I64
124      /* 1-bit stuff */
125      Iop_32to1,  /* :: Ity_I32 -> Ity_Bit, just select bit[0] */
126      Iop_1Uto8,  /* :: Ity_Bit -> Ity_I8, unsigned widen */
127      Iop_1Uto32, /* :: Ity_Bit -> Ity_I32, unsigned widen */
128      /* FP stuff */
129      Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64,
130      Iop_SqrtF64,
131      Iop_I64toF64, Iop_F64toI64
132   }
133   IROp;
134
135extern void ppIROp ( IROp );
136
137
138/* ------------------ Expressions ------------------ */
139/*
140data Expr
141   = GET   Int Type        -- offset, size
142   | GETI  Expr Type Int Int -- offset, size, minoff, maxoff
143   | TMP   Temp            -- value of temporary
144   | BINOP Op Expr Expr    -- binary op
145   | UNOP  Op Expr         -- unary op
146   | LDle  Type Expr       -- load of the given type, Expr:: 32 or 64
147   | CONST Const           -- 8/16/32/64-bit int constant
148
149Re GETI.  It carries two ints, which give the lowest and highest
150possible byte offsets that the GetI can possibly reference.
151For example, if the type is Ity_I32, and the Expr may have
152a value of M, M+4 or M+8, where M is a translation-time known
153constant, then the low and high limits are M and M+11 respectively.
154
155PUTI carries similar limit values.
156
157These can be used by IR optimisers to establish aliasing/non-aliasing
158between seperate GETI and PUTI terms, which could be used to do
159reordering of them, or suchlike things.  Clearly it's critical to give
160the correct limit values -- this is something that can't be
161automatically checked (in general), and so the front-end writers must
162be very careful to tell the truth, since not doing so could lead to
163obscure IR optimisation bugs.
164*/
165
166typedef
167     enum { Iex_Binder, /* Used only in pattern matching.
168                           Not an expression. */
169          Iex_Get, Iex_GetI, Iex_Tmp, Iex_Binop, Iex_Unop, Iex_LDle,
170          Iex_Const, Iex_CCall, Iex_Mux0X }
171   IRExprTag;
172
173typedef
174   struct _IRExpr {
175      IRExprTag tag;
176      union {
177	 struct {
178            Int binder;
179         } Binder;
180         struct {
181            Int    offset;
182            IRType ty;
183         } Get;
184         struct {
185            struct _IRExpr* offset;
186            IRType  ty;
187            UShort  minoff;
188            UShort  maxoff;
189         } GetI;
190         struct {
191            IRTemp tmp;
192         } Tmp;
193         struct {
194            IROp op;
195            struct _IRExpr* arg1;
196            struct _IRExpr* arg2;
197         } Binop;
198         struct {
199            IROp op;
200            struct _IRExpr* arg;
201         } Unop;
202         struct {
203            IRType ty;
204            struct _IRExpr* addr;
205         } LDle;
206         struct {
207            IRConst* con;
208         } Const;
209         struct {
210            Char*  name;
211            IRType retty;
212            struct _IRExpr** args;
213         }  CCall;
214         struct {
215            struct _IRExpr* cond;
216            struct _IRExpr* expr0;
217            struct _IRExpr* exprX;
218         } Mux0X;
219      } Iex;
220   }
221   IRExpr;
222
223extern IRExpr* IRExpr_Binder ( Int binder );
224extern IRExpr* IRExpr_Get    ( Int off, IRType ty );
225extern IRExpr* IRExpr_GetI   ( IRExpr* off, IRType ty,
226                               UShort minoff, UShort maxoff );
227extern IRExpr* IRExpr_Tmp    ( IRTemp tmp );
228extern IRExpr* IRExpr_Binop  ( IROp op, IRExpr* arg1, IRExpr* arg2 );
229extern IRExpr* IRExpr_Unop   ( IROp op, IRExpr* arg );
230extern IRExpr* IRExpr_LDle   ( IRType ty, IRExpr* addr );
231extern IRExpr* IRExpr_Const  ( IRConst* con );
232extern IRExpr* IRExpr_CCall  ( Char* name, IRType retty, IRExpr** args );
233extern IRExpr* IRExpr_Mux0X  ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX );
234
235extern void ppIRExpr ( IRExpr* );
236
237/* CCall info.  The name is the C helper function; the backends
238   will hand the name to the front ends to get the address of a
239   host-code helper function to be called.
240
241   The args are a NULL-terminated array of arguments.  The stated
242   return IRType, and the implied argument types, must match that
243   of the function being called well enough so that the back end
244   can actually generate correct code for the call.  (too vague)
245
246   The called function must satisfy the following:
247
248   * no side effects -- must be a pure function
249   * it may not look at any of the guest state -- must depend
250     purely on passed parameters
251   * it may not access guest memory -- since that would
252     hide guest memory transactions from the instrumenters
253*/
254
255/* ------------------ Statements ------------------ */
256/*
257data Stmt
258   = PUT    Int Int Expr      -- offset, size, value
259   | TMP    Temp Expr         -- store value in Temp
260   | STle   Expr Expr         -- address (32 or 64 bit), value
261   | Exit   Expr Const        -- conditional exit from middle of BB
262                              -- Const is destination guest addr
263*/
264typedef
265   enum { Ist_Put, Ist_PutI, Ist_Tmp, Ist_STle, Ist_Exit }
266   IRStmtTag;
267
268typedef
269   struct _IRStmt {
270      IRStmtTag tag;
271      union {
272         struct {
273            Int     offset;
274            IRExpr* expr;
275         } Put;
276         struct {
277            IRExpr* offset;
278            IRExpr* expr;
279            UShort  minoff;
280            UShort  maxoff;
281         } PutI;
282         struct {
283            IRTemp  tmp;
284            IRExpr* expr;
285         } Tmp;
286         struct {
287            IRExpr* addr;
288            IRExpr* data;
289         } STle;
290         struct {
291            IRExpr*  cond;
292            IRConst* dst;
293         } Exit;
294      } Ist;
295   }
296   IRStmt;
297
298extern IRStmt* IRStmt_Put  ( Int off, IRExpr* value );
299extern IRStmt* IRStmt_PutI ( IRExpr* off, IRExpr* value,
300                             UShort minoff, UShort maxoff );
301extern IRStmt* IRStmt_Tmp  ( IRTemp tmp, IRExpr* expr );
302extern IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* value );
303extern IRStmt* IRStmt_Exit ( IRExpr* cond, IRConst* dst );
304
305extern void ppIRStmt ( IRStmt* );
306
307/* Guards in Put: if NULL, the Put is always done.
308   If non-NULL, the expr must denote a value of Ity_Bit, and
309   the Put is only done if this evaluates to 1.  The expression
310   to be stored (expr) will be evaluated regardless of what
311   the guard is.
312*/
313
314/* ------------------ Basic Blocks ------------------ */
315
316/* This describes the unconditional jumps which implicitly happen at
317   the end of each basic block.  Conditional jumps -- which can only
318   be done with the IRStmt_Exit statement -- are implicitly of the
319   Ijk_Boring kind. */
320
321typedef
322   enum {
323      Ijk_Boring=0x14000, /* not interesting; just goto next */
324      Ijk_Call,           /* guest is doing a call */
325      Ijk_Ret,            /* guest is doing a return */
326      Ijk_ClientReq,      /* do guest client req before continuing */
327      Ijk_Syscall,        /* do guest syscall before continuing */
328      Ijk_Yield           /* client is yielding to thread scheduler */
329   }
330   IRJumpKind;
331
332extern void ppIRJumpKind ( IRJumpKind );
333
334
335/* A bunch of statements, expressions, etc, are incomplete without an
336   environment indicating the type of each IRTemp.  So this provides
337   one.  IR temporaries are really just unsigned ints and so this
338   provides an array, 0 .. n_types_used-1 of them.
339*/
340typedef
341   struct {
342      IRType* types;
343      Int     types_size;
344      Int     types_used;
345   }
346   IRTypeEnv;
347
348extern void ppIRTypeEnv ( IRTypeEnv* );
349
350
351/* Basic blocks contain:
352   - A table giving a type for each temp
353   - An expandable array of statements
354   - An expression of type 32 or 64 bits, depending on the
355     guest's word size, indicating the next destination.
356   - An indication of any special actions (JumpKind) needed
357     for this final jump.
358*/
359typedef
360   struct _IRBB {
361      IRTypeEnv* tyenv;
362      IRStmt**   stmts;
363      Int        stmts_size;
364      Int        stmts_used;
365      IRExpr*    next;
366      IRJumpKind jumpkind;
367   }
368   IRBB;
369
370extern IRBB* emptyIRBB ( void );
371extern void  addStmtToIRBB ( IRBB*, IRStmt* );
372
373extern void ppIRBB ( IRBB* );
374
375
376/*---------------------------------------------------------------*/
377/*--- Helper functions for the IR                             ---*/
378/*---------------------------------------------------------------*/
379
380/* For messing with IR type environments */
381extern IRTypeEnv* emptyIRTypeEnv  ( void );
382extern IRTemp     newIRTemp       ( IRTypeEnv*, IRType );
383extern IRType     lookupIRTypeEnv ( IRTypeEnv*, IRTemp );
384extern IRTypeEnv* copyIRTypeEnv   ( IRTypeEnv* );
385
386/* What is the type of this expression? */
387extern IRType typeOfIRConst ( IRConst* );
388extern IRType typeOfIRExpr  ( IRTypeEnv*, IRExpr* );
389
390/* Sanity check a BB of IR */
391extern void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size );
392
393/* Is this any value actually in the enumeration 'IRType' ? */
394extern Bool isPlausibleType ( IRType ty );
395
396#endif /* ndef __LIBVEX_IR_H */
397
398
399/*---------------------------------------------------------------*/
400/*---                                             libvex_ir.h ---*/
401/*---------------------------------------------------------------*/
402