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