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