1
2 /*---------------------------------------------------------------*/
3 /*--- begin libvex_ir.h ---*/
4 /*---------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2004-2010 OpenWorks LLP
11 info@open-works.net
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
34 */
35
36 #ifndef __LIBVEX_IR_H
37 #define __LIBVEX_IR_H
38
39 #include "libvex_basictypes.h"
40
41
42 /*---------------------------------------------------------------*/
43 /*--- High-level IR description ---*/
44 /*---------------------------------------------------------------*/
45
46 /* Vex IR is an architecture-neutral intermediate representation.
47 Unlike some IRs in systems similar to Vex, it is not like assembly
48 language (ie. a list of instructions). Rather, it is more like the
49 IR that might be used in a compiler.
50
51 Code blocks
52 ~~~~~~~~~~~
53 The code is broken into small code blocks ("superblocks", type:
54 'IRSB'). Each code block typically represents from 1 to perhaps 50
55 instructions. IRSBs are single-entry, multiple-exit code blocks.
56 Each IRSB contains three things:
57 - a type environment, which indicates the type of each temporary
58 value present in the IRSB
59 - a list of statements, which represent code
60 - a jump that exits from the end the IRSB
61 Because the blocks are multiple-exit, there can be additional
62 conditional exit statements that cause control to leave the IRSB
63 before the final exit. Also because of this, IRSBs can cover
64 multiple non-consecutive sequences of code (up to 3). These are
65 recorded in the type VexGuestExtents (see libvex.h).
66
67 Statements and expressions
68 ~~~~~~~~~~~~~~~~~~~~~~~~~~
69 Statements (type 'IRStmt') represent operations with side-effects,
70 eg. guest register writes, stores, and assignments to temporaries.
71 Expressions (type 'IRExpr') represent operations without
72 side-effects, eg. arithmetic operations, loads, constants.
73 Expressions can contain sub-expressions, forming expression trees,
74 eg. (3 + (4 * load(addr1)).
75
76 Storage of guest state
77 ~~~~~~~~~~~~~~~~~~~~~~
78 The "guest state" contains the guest registers of the guest machine
79 (ie. the machine that we are simulating). It is stored by default
80 in a block of memory supplied by the user of the VEX library,
81 generally referred to as the guest state (area). To operate on
82 these registers, one must first read ("Get") them from the guest
83 state into a temporary value. Afterwards, one can write ("Put")
84 them back into the guest state.
85
86 Get and Put are characterised by a byte offset into the guest
87 state, a small integer which effectively gives the identity of the
88 referenced guest register, and a type, which indicates the size of
89 the value to be transferred.
90
91 The basic "Get" and "Put" operations are sufficient to model normal
92 fixed registers on the guest. Selected areas of the guest state
93 can be treated as a circular array of registers (type:
94 'IRRegArray'), which can be indexed at run-time. This is done with
95 the "GetI" and "PutI" primitives. This is necessary to describe
96 rotating register files, for example the x87 FPU stack, SPARC
97 register windows, and the Itanium register files.
98
99 Examples, and flattened vs. unflattened code
100 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101 For example, consider this x86 instruction:
102
103 addl %eax, %ebx
104
105 One Vex IR translation for this code would be this:
106
107 ------ IMark(0x24F275, 7) ------
108 t3 = GET:I32(0) # get %eax, a 32-bit integer
109 t2 = GET:I32(12) # get %ebx, a 32-bit integer
110 t1 = Add32(t3,t2) # addl
111 PUT(0) = t1 # put %eax
112
113 (For simplicity, this ignores the effects on the condition codes, and
114 the update of the instruction pointer.)
115
116 The "IMark" is an IR statement that doesn't represent actual code.
117 Instead it indicates the address and length of the original
118 instruction. The numbers 0 and 12 are offsets into the guest state
119 for %eax and %ebx. The full list of offsets for an architecture
120 <ARCH> can be found in the type VexGuest<ARCH>State in the file
121 VEX/pub/libvex_guest_<ARCH>.h.
122
123 The five statements in this example are:
124 - the IMark
125 - three assignments to temporaries
126 - one register write (put)
127
128 The six expressions in this example are:
129 - two register reads (gets)
130 - one arithmetic (add) operation
131 - three temporaries (two nested within the Add32, one in the PUT)
132
133 The above IR is "flattened", ie. all sub-expressions are "atoms",
134 either constants or temporaries. An equivalent, unflattened version
135 would be:
136
137 PUT(0) = Add32(GET:I32(0), GET:I32(12))
138
139 IR is guaranteed to be flattened at instrumentation-time. This makes
140 instrumentation easier. Equivalent flattened and unflattened IR
141 typically results in the same generated code.
142
143 Another example, this one showing loads and stores:
144
145 addl %edx,4(%eax)
146
147 This becomes (again ignoring condition code and instruction pointer
148 updates):
149
150 ------ IMark(0x4000ABA, 3) ------
151 t3 = Add32(GET:I32(0),0x4:I32)
152 t2 = LDle:I32(t3)
153 t1 = GET:I32(8)
154 t0 = Add32(t2,t1)
155 STle(t3) = t0
156
157 The "le" in "LDle" and "STle" is short for "little-endian".
158
159 No need for deallocations
160 ~~~~~~~~~~~~~~~~~~~~~~~~~
161 Although there are allocation functions for various data structures
162 in this file, there are no deallocation functions. This is because
163 Vex uses a memory allocation scheme that automatically reclaims the
164 memory used by allocated structures once translation is completed.
165 This makes things easier for tools that instruments/transforms code
166 blocks.
167
168 SSAness and typing
169 ~~~~~~~~~~~~~~~~~~
170 The IR is fully typed. For every IRSB (IR block) it is possible to
171 say unambiguously whether or not it is correctly typed.
172 Incorrectly typed IR has no meaning and the VEX will refuse to
173 process it. At various points during processing VEX typechecks the
174 IR and aborts if any violations are found. This seems overkill but
175 makes it a great deal easier to build a reliable JIT.
176
177 IR also has the SSA property. SSA stands for Static Single
178 Assignment, and what it means is that each IR temporary may be
179 assigned to only once. This idea became widely used in compiler
180 construction in the mid to late 90s. It makes many IR-level
181 transformations/code improvements easier, simpler and faster.
182 Whenever it typechecks an IR block, VEX also checks the SSA
183 property holds, and will abort if not so. So SSAness is
184 mechanically and rigidly enforced.
185 */
186
187 /*---------------------------------------------------------------*/
188 /*--- Type definitions for the IR ---*/
189 /*---------------------------------------------------------------*/
190
191 /* General comments about naming schemes:
192
193 All publically visible functions contain the name of the primary
194 type on which they operate (IRFoo, IRBar, etc). Hence you should
195 be able to identify these functions by grepping for "IR[A-Z]".
196
197 For some type 'IRFoo':
198
199 - ppIRFoo is the printing method for IRFoo, printing it to the
200 output channel specified in the LibVEX_Initialise call.
201
202 - eqIRFoo is a structural equality predicate for IRFoos.
203
204 - deepCopyIRFoo is a deep copy constructor for IRFoos.
205 It recursively traverses the entire argument tree and
206 produces a complete new tree. All types have a deep copy
207 constructor.
208
209 - shallowCopyIRFoo is the shallow copy constructor for IRFoos.
210 It creates a new top-level copy of the supplied object,
211 but does not copy any sub-objects. Only some types have a
212 shallow copy constructor.
213 */
214
215 /* ------------------ Types ------------------ */
216
217 /* A type indicates the size of a value, and whether it's an integer, a
218 float, or a vector (SIMD) value. */
219 typedef
220 enum {
221 Ity_INVALID=0x11000,
222 Ity_I1,
223 Ity_I8,
224 Ity_I16,
225 Ity_I32,
226 Ity_I64,
227 Ity_I128, /* 128-bit scalar */
228 Ity_F32, /* IEEE 754 float */
229 Ity_F64, /* IEEE 754 double */
230 Ity_V128 /* 128-bit SIMD */
231 }
232 IRType;
233
234 /* Pretty-print an IRType */
235 extern void ppIRType ( IRType );
236
237 /* Get the size (in bytes) of an IRType */
238 extern Int sizeofIRType ( IRType );
239
240
241 /* ------------------ Endianness ------------------ */
242
243 /* IREndness is used in load IRExprs and store IRStmts. */
244 typedef
245 enum {
246 Iend_LE=0x12000, /* little endian */
247 Iend_BE /* big endian */
248 }
249 IREndness;
250
251
252 /* ------------------ Constants ------------------ */
253
254 /* IRConsts are used within 'Const' and 'Exit' IRExprs. */
255
256 /* The various kinds of constant. */
257 typedef
258 enum {
259 Ico_U1=0x13000,
260 Ico_U8,
261 Ico_U16,
262 Ico_U32,
263 Ico_U64,
264 Ico_F64, /* 64-bit IEEE754 floating */
265 Ico_F64i, /* 64-bit unsigned int to be interpreted literally
266 as a IEEE754 double value. */
267 Ico_V128 /* 128-bit restricted vector constant, with 1 bit
268 (repeated 8 times) for each of the 16 x 1-byte lanes */
269 }
270 IRConstTag;
271
272 /* A constant. Stored as a tagged union. 'tag' indicates what kind of
273 constant this is. 'Ico' is the union that holds the fields. If an
274 IRConst 'c' has c.tag equal to Ico_U32, then it's a 32-bit constant,
275 and its value can be accessed with 'c.Ico.U32'. */
276 typedef
277 struct _IRConst {
278 IRConstTag tag;
279 union {
280 Bool U1;
281 UChar U8;
282 UShort U16;
283 UInt U32;
284 ULong U64;
285 Double F64;
286 ULong F64i;
287 UShort V128; /* 16-bit value; see Ico_V128 comment above */
288 } Ico;
289 }
290 IRConst;
291
292 /* IRConst constructors */
293 extern IRConst* IRConst_U1 ( Bool );
294 extern IRConst* IRConst_U8 ( UChar );
295 extern IRConst* IRConst_U16 ( UShort );
296 extern IRConst* IRConst_U32 ( UInt );
297 extern IRConst* IRConst_U64 ( ULong );
298 extern IRConst* IRConst_F64 ( Double );
299 extern IRConst* IRConst_F64i ( ULong );
300 extern IRConst* IRConst_V128 ( UShort );
301
302 /* Deep-copy an IRConst */
303 extern IRConst* deepCopyIRConst ( IRConst* );
304
305 /* Pretty-print an IRConst */
306 extern void ppIRConst ( IRConst* );
307
308 /* Compare two IRConsts for equality */
309 extern Bool eqIRConst ( IRConst*, IRConst* );
310
311
312 /* ------------------ Call targets ------------------ */
313
314 /* Describes a helper function to call. The name part is purely for
315 pretty printing and not actually used. regparms=n tells the back
316 end that the callee has been declared
317 "__attribute__((regparm(n)))". On some targets (x86) the back end
318 will need to construct a non-standard sequence to call a function
319 declared like this.
320
321 mcx_mask is a sop to Memcheck. It indicates which args should be
322 considered 'always defined' when lazily computing definedness of
323 the result. Bit 0 of mcx_mask corresponds to args[0], bit 1 to
324 args[1], etc. If a bit is set, the corresponding arg is excluded
325 (hence "x" in "mcx") from definedness checking.
326 */
327
328 typedef
329 struct {
330 Int regparms;
331 HChar* name;
332 void* addr;
333 UInt mcx_mask;
334 }
335 IRCallee;
336
337 /* Create an IRCallee. */
338 extern IRCallee* mkIRCallee ( Int regparms, HChar* name, void* addr );
339
340 /* Deep-copy an IRCallee. */
341 extern IRCallee* deepCopyIRCallee ( IRCallee* );
342
343 /* Pretty-print an IRCallee. */
344 extern void ppIRCallee ( IRCallee* );
345
346
347 /* ------------------ Guest state arrays ------------------ */
348
349 /* This describes a section of the guest state that we want to
350 be able to index at run time, so as to be able to describe
351 indexed or rotating register files on the guest. */
352 typedef
353 struct {
354 Int base; /* guest state offset of start of indexed area */
355 IRType elemTy; /* type of each element in the indexed area */
356 Int nElems; /* number of elements in the indexed area */
357 }
358 IRRegArray;
359
360 extern IRRegArray* mkIRRegArray ( Int, IRType, Int );
361
362 extern IRRegArray* deepCopyIRRegArray ( IRRegArray* );
363
364 extern void ppIRRegArray ( IRRegArray* );
365 extern Bool eqIRRegArray ( IRRegArray*, IRRegArray* );
366
367
368 /* ------------------ Temporaries ------------------ */
369
370 /* This represents a temporary, eg. t1. The IR optimiser relies on the
371 fact that IRTemps are 32-bit ints. Do not change them to be ints of
372 any other size. */
373 typedef UInt IRTemp;
374
375 /* Pretty-print an IRTemp. */
376 extern void ppIRTemp ( IRTemp );
377
378 #define IRTemp_INVALID ((IRTemp)0xFFFFFFFF)
379
380
381 /* --------------- Primops (arity 1,2,3 and 4) --------------- */
382
383 /* Primitive operations that are used in Unop, Binop, Triop and Qop
384 IRExprs. Once we take into account integer, floating point and SIMD
385 operations of all the different sizes, there are quite a lot of them.
386 Most instructions supported by the architectures that Vex supports
387 (x86, PPC, etc) are represented. Some more obscure ones (eg. cpuid)
388 are not; they are instead handled with dirty helpers that emulate
389 their functionality. Such obscure ones are thus not directly visible
390 in the IR, but their effects on guest state (memory and registers)
391 are made visible via the annotations in IRDirty structures.
392 */
393 typedef
394 enum {
395 /* -- Do not change this ordering. The IR generators rely on
396 (eg) Iop_Add64 == IopAdd8 + 3. -- */
397
398 Iop_INVALID=0x14000,
399 Iop_Add8, Iop_Add16, Iop_Add32, Iop_Add64,
400 Iop_Sub8, Iop_Sub16, Iop_Sub32, Iop_Sub64,
401 /* Signless mul. MullS/MullU is elsewhere. */
402 Iop_Mul8, Iop_Mul16, Iop_Mul32, Iop_Mul64,
403 Iop_Or8, Iop_Or16, Iop_Or32, Iop_Or64,
404 Iop_And8, Iop_And16, Iop_And32, Iop_And64,
405 Iop_Xor8, Iop_Xor16, Iop_Xor32, Iop_Xor64,
406 Iop_Shl8, Iop_Shl16, Iop_Shl32, Iop_Shl64,
407 Iop_Shr8, Iop_Shr16, Iop_Shr32, Iop_Shr64,
408 Iop_Sar8, Iop_Sar16, Iop_Sar32, Iop_Sar64,
409 /* Integer comparisons. */
410 Iop_CmpEQ8, Iop_CmpEQ16, Iop_CmpEQ32, Iop_CmpEQ64,
411 Iop_CmpNE8, Iop_CmpNE16, Iop_CmpNE32, Iop_CmpNE64,
412 /* Tags for unary ops */
413 Iop_Not8, Iop_Not16, Iop_Not32, Iop_Not64,
414
415 /* Exactly like CmpEQ8/16/32/64, but carrying the additional
416 hint that these compute the success/failure of a CAS
417 operation, and hence are almost certainly applied to two
418 copies of the same value, which in turn has implications for
419 Memcheck's instrumentation. */
420 Iop_CasCmpEQ8, Iop_CasCmpEQ16, Iop_CasCmpEQ32, Iop_CasCmpEQ64,
421 Iop_CasCmpNE8, Iop_CasCmpNE16, Iop_CasCmpNE32, Iop_CasCmpNE64,
422
423 /* -- Ordering not important after here. -- */
424
425 /* Widening multiplies */
426 Iop_MullS8, Iop_MullS16, Iop_MullS32, Iop_MullS64,
427 Iop_MullU8, Iop_MullU16, Iop_MullU32, Iop_MullU64,
428
429 /* Wierdo integer stuff */
430 Iop_Clz64, Iop_Clz32, /* count leading zeroes */
431 Iop_Ctz64, Iop_Ctz32, /* count trailing zeros */
432 /* Ctz64/Ctz32/Clz64/Clz32 are UNDEFINED when given arguments of
433 zero. You must ensure they are never given a zero argument.
434 */
435
436 /* Standard integer comparisons */
437 Iop_CmpLT32S, Iop_CmpLT64S,
438 Iop_CmpLE32S, Iop_CmpLE64S,
439 Iop_CmpLT32U, Iop_CmpLT64U,
440 Iop_CmpLE32U, Iop_CmpLE64U,
441
442 /* As a sop to Valgrind-Memcheck, the following are useful. */
443 Iop_CmpNEZ8, Iop_CmpNEZ16, Iop_CmpNEZ32, Iop_CmpNEZ64,
444 Iop_CmpwNEZ32, Iop_CmpwNEZ64, /* all-0s -> all-Os; other -> all-1s */
445 Iop_Left8, Iop_Left16, Iop_Left32, Iop_Left64, /* \x -> x | -x */
446 Iop_Max32U, /* unsigned max */
447
448 /* PowerPC-style 3-way integer comparisons. Without them it is
449 difficult to simulate PPC efficiently.
450 op(x,y) | x < y = 0x8 else
451 | x > y = 0x4 else
452 | x == y = 0x2
453 */
454 Iop_CmpORD32U, Iop_CmpORD64U,
455 Iop_CmpORD32S, Iop_CmpORD64S,
456
457 /* Division */
458 /* TODO: clarify semantics wrt rounding, negative values, whatever */
459 Iop_DivU32, // :: I32,I32 -> I32 (simple div, no mod)
460 Iop_DivS32, // ditto, signed
461 Iop_DivU64, // :: I64,I64 -> I64 (simple div, no mod)
462 Iop_DivS64, // ditto, signed
463
464 Iop_DivModU64to32, // :: I64,I32 -> I64
465 // of which lo half is div and hi half is mod
466 Iop_DivModS64to32, // ditto, signed
467
468 Iop_DivModU128to64, // :: V128,I64 -> V128
469 // of which lo half is div and hi half is mod
470 Iop_DivModS128to64, // ditto, signed
471
472 /* Integer conversions. Some of these are redundant (eg
473 Iop_64to8 is the same as Iop_64to32 and then Iop_32to8), but
474 having a complete set reduces the typical dynamic size of IR
475 and makes the instruction selectors easier to write. */
476
477 /* Widening conversions */
478 Iop_8Uto16, Iop_8Uto32, Iop_8Uto64,
479 Iop_16Uto32, Iop_16Uto64,
480 Iop_32Uto64,
481 Iop_8Sto16, Iop_8Sto32, Iop_8Sto64,
482 Iop_16Sto32, Iop_16Sto64,
483 Iop_32Sto64,
484
485 /* Narrowing conversions */
486 Iop_64to8, Iop_32to8, Iop_64to16,
487 /* 8 <-> 16 bit conversions */
488 Iop_16to8, // :: I16 -> I8, low half
489 Iop_16HIto8, // :: I16 -> I8, high half
490 Iop_8HLto16, // :: (I8,I8) -> I16
491 /* 16 <-> 32 bit conversions */
492 Iop_32to16, // :: I32 -> I16, low half
493 Iop_32HIto16, // :: I32 -> I16, high half
494 Iop_16HLto32, // :: (I16,I16) -> I32
495 /* 32 <-> 64 bit conversions */
496 Iop_64to32, // :: I64 -> I32, low half
497 Iop_64HIto32, // :: I64 -> I32, high half
498 Iop_32HLto64, // :: (I32,I32) -> I64
499 /* 64 <-> 128 bit conversions */
500 Iop_128to64, // :: I128 -> I64, low half
501 Iop_128HIto64, // :: I128 -> I64, high half
502 Iop_64HLto128, // :: (I64,I64) -> I128
503 /* 1-bit stuff */
504 Iop_Not1, /* :: Ity_Bit -> Ity_Bit */
505 Iop_32to1, /* :: Ity_I32 -> Ity_Bit, just select bit[0] */
506 Iop_64to1, /* :: Ity_I64 -> Ity_Bit, just select bit[0] */
507 Iop_1Uto8, /* :: Ity_Bit -> Ity_I8, unsigned widen */
508 Iop_1Uto32, /* :: Ity_Bit -> Ity_I32, unsigned widen */
509 Iop_1Uto64, /* :: Ity_Bit -> Ity_I64, unsigned widen */
510 Iop_1Sto8, /* :: Ity_Bit -> Ity_I8, signed widen */
511 Iop_1Sto16, /* :: Ity_Bit -> Ity_I16, signed widen */
512 Iop_1Sto32, /* :: Ity_Bit -> Ity_I32, signed widen */
513 Iop_1Sto64, /* :: Ity_Bit -> Ity_I64, signed widen */
514
515 /* ------ Floating point. We try to be IEEE754 compliant. ------ */
516
517 /* --- Simple stuff as mandated by 754. --- */
518
519 /* Binary operations, with rounding. */
520 /* :: IRRoundingMode(I32) x F64 x F64 -> F64 */
521 Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64,
522
523 /* :: IRRoundingMode(I32) x F32 x F32 -> F32 */
524 Iop_AddF32, Iop_SubF32, Iop_MulF32, Iop_DivF32,
525
526 /* Variants of the above which produce a 64-bit result but which
527 round their result to a IEEE float range first. */
528 /* :: IRRoundingMode(I32) x F64 x F64 -> F64 */
529 Iop_AddF64r32, Iop_SubF64r32, Iop_MulF64r32, Iop_DivF64r32,
530
531 /* Unary operations, without rounding. */
532 /* :: F64 -> F64 */
533 Iop_NegF64, Iop_AbsF64,
534
535 /* :: F32 -> F32 */
536 Iop_NegF32, Iop_AbsF32,
537
538 /* Unary operations, with rounding. */
539 /* :: IRRoundingMode(I32) x F64 -> F64 */
540 Iop_SqrtF64, Iop_SqrtF64r32,
541
542 /* :: IRRoundingMode(I32) x F32 -> F32 */
543 Iop_SqrtF32,
544
545 /* Comparison, yielding GT/LT/EQ/UN(ordered), as per the following:
546 0x45 Unordered
547 0x01 LT
548 0x00 GT
549 0x40 EQ
550 This just happens to be the Intel encoding. The values
551 are recorded in the type IRCmpF64Result.
552 */
553 /* :: F64 x F64 -> IRCmpF64Result(I32) */
554 Iop_CmpF64,
555
556 /* --- Int to/from FP conversions. --- */
557
558 /* For the most part, these take a first argument :: Ity_I32 (as
559 IRRoundingMode) which is an indication of the rounding mode
560 to use, as per the following encoding ("the standard
561 encoding"):
562 00b to nearest (the default)
563 01b to -infinity
564 10b to +infinity
565 11b to zero
566 This just happens to be the Intel encoding. For reference only,
567 the PPC encoding is:
568 00b to nearest (the default)
569 01b to zero
570 10b to +infinity
571 11b to -infinity
572 Any PPC -> IR front end will have to translate these PPC
573 encodings, as encoded in the guest state, to the standard
574 encodings, to pass to the primops.
575 For reference only, the ARM VFP encoding is:
576 00b to nearest
577 01b to +infinity
578 10b to -infinity
579 11b to zero
580 Again, this will have to be converted to the standard encoding
581 to pass to primops.
582
583 If one of these conversions gets an out-of-range condition,
584 or a NaN, as an argument, the result is host-defined. On x86
585 the "integer indefinite" value 0x80..00 is produced. On PPC
586 it is either 0x80..00 or 0x7F..FF depending on the sign of
587 the argument.
588
589 On ARMvfp, when converting to a signed integer result, the
590 overflow result is 0x80..00 for negative args and 0x7F..FF
591 for positive args. For unsigned integer results it is
592 0x00..00 and 0xFF..FF respectively.
593
594 Rounding is required whenever the destination type cannot
595 represent exactly all values of the source type.
596 */
597 Iop_F64toI16S, /* IRRoundingMode(I32) x F64 -> signed I16 */
598 Iop_F64toI32S, /* IRRoundingMode(I32) x F64 -> signed I32 */
599 Iop_F64toI64S, /* IRRoundingMode(I32) x F64 -> signed I64 */
600
601 Iop_F64toI32U, /* IRRoundingMode(I32) x F64 -> unsigned I32 */
602
603 Iop_I16StoF64, /* signed I16 -> F64 */
604 Iop_I32StoF64, /* signed I32 -> F64 */
605 Iop_I64StoF64, /* IRRoundingMode(I32) x signed I64 -> F64 */
606
607 Iop_I32UtoF64, /* unsigned I32 -> F64 */
608
609 /* Conversion between floating point formats */
610 Iop_F32toF64, /* F32 -> F64 */
611 Iop_F64toF32, /* IRRoundingMode(I32) x F64 -> F32 */
612
613 /* Reinterpretation. Take an F64 and produce an I64 with
614 the same bit pattern, or vice versa. */
615 Iop_ReinterpF64asI64, Iop_ReinterpI64asF64,
616 Iop_ReinterpF32asI32, Iop_ReinterpI32asF32,
617
618 /* --- guest x86/amd64 specifics, not mandated by 754. --- */
619
620 /* Binary ops, with rounding. */
621 /* :: IRRoundingMode(I32) x F64 x F64 -> F64 */
622 Iop_AtanF64, /* FPATAN, arctan(arg1/arg2) */
623 Iop_Yl2xF64, /* FYL2X, arg1 * log2(arg2) */
624 Iop_Yl2xp1F64, /* FYL2XP1, arg1 * log2(arg2+1.0) */
625 Iop_PRemF64, /* FPREM, non-IEEE remainder(arg1/arg2) */
626 Iop_PRemC3210F64, /* C3210 flags resulting from FPREM, :: I32 */
627 Iop_PRem1F64, /* FPREM1, IEEE remainder(arg1/arg2) */
628 Iop_PRem1C3210F64, /* C3210 flags resulting from FPREM1, :: I32 */
629 Iop_ScaleF64, /* FSCALE, arg1 * (2^RoundTowardsZero(arg2)) */
630 /* Note that on x86 guest, PRem1{C3210} has the same behaviour
631 as the IEEE mandated RemF64, except it is limited in the
632 range of its operand. Hence the partialness. */
633
634 /* Unary ops, with rounding. */
635 /* :: IRRoundingMode(I32) x F64 -> F64 */
636 Iop_SinF64, /* FSIN */
637 Iop_CosF64, /* FCOS */
638 Iop_TanF64, /* FTAN */
639 Iop_2xm1F64, /* (2^arg - 1.0) */
640 Iop_RoundF64toInt, /* F64 value to nearest integral value (still
641 as F64) */
642 Iop_RoundF32toInt, /* F32 value to nearest integral value (still
643 as F32) */
644
645 /* --- guest ppc32/64 specifics, not mandated by 754. --- */
646
647 /* Ternary operations, with rounding. */
648 /* Fused multiply-add/sub, with 112-bit intermediate
649 precision */
650 /* :: IRRoundingMode(I32) x F64 x F64 x F64 -> F64
651 (computes arg2 * arg3 +/- arg4) */
652 Iop_MAddF64, Iop_MSubF64,
653
654 /* Variants of the above which produce a 64-bit result but which
655 round their result to a IEEE float range first. */
656 /* :: IRRoundingMode(I32) x F64 x F64 x F64 -> F64 */
657 Iop_MAddF64r32, Iop_MSubF64r32,
658
659 /* :: F64 -> F64 */
660 Iop_Est5FRSqrt, /* reciprocal square root estimate, 5 good bits */
661 Iop_RoundF64toF64_NEAREST, /* frin */
662 Iop_RoundF64toF64_NegINF, /* frim */
663 Iop_RoundF64toF64_PosINF, /* frip */
664 Iop_RoundF64toF64_ZERO, /* friz */
665
666 /* :: F64 -> F32 */
667 Iop_TruncF64asF32, /* do F64->F32 truncation as per 'fsts' */
668
669 /* :: IRRoundingMode(I32) x F64 -> F64 */
670 Iop_RoundF64toF32, /* round F64 to nearest F32 value (still as F64) */
671 /* NB: pretty much the same as Iop_F64toF32, except no change
672 of type. */
673
674 /* :: F64 -> I32 */
675 Iop_CalcFPRF, /* Calc 5 fpscr[FPRF] bits (Class, <, =, >, Unord)
676 from FP result */
677
678 /* ------------------ 32-bit SIMD Integer ------------------ */
679
680 /* 16x2 add/sub, also signed/unsigned saturating variants */
681 Iop_Add16x2, Iop_Sub16x2,
682 Iop_QAdd16Sx2, Iop_QAdd16Ux2,
683 Iop_QSub16Sx2, Iop_QSub16Ux2,
684
685 /* 16x2 signed/unsigned halving add/sub. For each lane, these
686 compute bits 16:1 of (eg) sx(argL) + sx(argR),
687 or zx(argL) - zx(argR) etc. */
688 Iop_HAdd16Ux2, Iop_HAdd16Sx2,
689 Iop_HSub16Ux2, Iop_HSub16Sx2,
690
691 /* 8x4 add/sub, also signed/unsigned saturating variants */
692 Iop_Add8x4, Iop_Sub8x4,
693 Iop_QAdd8Sx4, Iop_QAdd8Ux4,
694 Iop_QSub8Sx4, Iop_QSub8Ux4,
695
696 /* 8x4 signed/unsigned halving add/sub. For each lane, these
697 compute bits 8:1 of (eg) sx(argL) + sx(argR),
698 or zx(argL) - zx(argR) etc. */
699 Iop_HAdd8Ux4, Iop_HAdd8Sx4,
700 Iop_HSub8Ux4, Iop_HSub8Sx4,
701
702 /* 8x4 sum of absolute unsigned differences. */
703 Iop_Sad8Ux4,
704
705 /* MISC (vector integer cmp != 0) */
706 Iop_CmpNEZ16x2, Iop_CmpNEZ8x4,
707
708 /* ------------------ 64-bit SIMD FP ------------------------ */
709
710 /* Convertion to/from int */
711 Iop_I32UtoFx2, Iop_I32StoFx2, /* I32x4 -> F32x4 */
712 Iop_FtoI32Ux2_RZ, Iop_FtoI32Sx2_RZ, /* F32x4 -> I32x4 */
713 /* Fixed32 format is floating-point number with fixed number of fraction
714 bits. The number of fraction bits is passed as a second argument of
715 type I8. */
716 Iop_F32ToFixed32Ux2_RZ, Iop_F32ToFixed32Sx2_RZ, /* fp -> fixed-point */
717 Iop_Fixed32UToF32x2_RN, Iop_Fixed32SToF32x2_RN, /* fixed-point -> fp */
718
719 /* Binary operations */
720 Iop_Max32Fx2, Iop_Min32Fx2,
721 /* Pairwise Min and Max. See integer pairwise operations for more
722 details. */
723 Iop_PwMax32Fx2, Iop_PwMin32Fx2,
724 /* Note: For the following compares, the arm front-end assumes a
725 nan in a lane of either argument returns zero for that lane. */
726 Iop_CmpEQ32Fx2, Iop_CmpGT32Fx2, Iop_CmpGE32Fx2,
727
728 /* Vector Reciprocal Estimate finds an approximate reciprocal of each
729 element in the operand vector, and places the results in the destination
730 vector. */
731 Iop_Recip32Fx2,
732
733 /* Vector Reciprocal Step computes (2.0 - arg1 * arg2).
734 Note, that if one of the arguments is zero and another one is infinity
735 of arbitrary sign the result of the operation is 2.0. */
736 Iop_Recps32Fx2,
737
738 /* Vector Reciprocal Square Root Estimate finds an approximate reciprocal
739 square root of each element in the operand vector. */
740 Iop_Rsqrte32Fx2,
741
742 /* Vector Reciprocal Square Root Step computes (3.0 - arg1 * arg2) / 2.0.
743 Note, that of one of the arguments is zero and another one is infiinty
744 of arbitrary sign the result of the operation is 1.5. */
745 Iop_Rsqrts32Fx2,
746
747 /* Unary */
748 Iop_Neg32Fx2, Iop_Abs32Fx2,
749
750 /* ------------------ 64-bit SIMD Integer. ------------------ */
751
752 /* MISC (vector integer cmp != 0) */
753 Iop_CmpNEZ8x8, Iop_CmpNEZ16x4, Iop_CmpNEZ32x2,
754
755 /* ADDITION (normal / unsigned sat / signed sat) */
756 Iop_Add8x8, Iop_Add16x4, Iop_Add32x2,
757 Iop_QAdd8Ux8, Iop_QAdd16Ux4, Iop_QAdd32Ux2, Iop_QAdd64Ux1,
758 Iop_QAdd8Sx8, Iop_QAdd16Sx4, Iop_QAdd32Sx2, Iop_QAdd64Sx1,
759
760 /* PAIRWISE operations */
761 /* Iop_PwFoo16x4( [a,b,c,d], [e,f,g,h] ) =
762 [Foo16(a,b), Foo16(c,d), Foo16(e,f), Foo16(g,h)] */
763 Iop_PwAdd8x8, Iop_PwAdd16x4, Iop_PwAdd32x2,
764 Iop_PwMax8Sx8, Iop_PwMax16Sx4, Iop_PwMax32Sx2,
765 Iop_PwMax8Ux8, Iop_PwMax16Ux4, Iop_PwMax32Ux2,
766 Iop_PwMin8Sx8, Iop_PwMin16Sx4, Iop_PwMin32Sx2,
767 Iop_PwMin8Ux8, Iop_PwMin16Ux4, Iop_PwMin32Ux2,
768 /* Longening variant is unary. The resulting vector contains two times
769 less elements than operand, but they are two times wider.
770 Example:
771 Iop_PAddL16Ux4( [a,b,c,d] ) = [a+b,c+d]
772 where a+b and c+d are unsigned 32-bit values. */
773 Iop_PwAddL8Ux8, Iop_PwAddL16Ux4, Iop_PwAddL32Ux2,
774 Iop_PwAddL8Sx8, Iop_PwAddL16Sx4, Iop_PwAddL32Sx2,
775
776 /* SUBTRACTION (normal / unsigned sat / signed sat) */
777 Iop_Sub8x8, Iop_Sub16x4, Iop_Sub32x2,
778 Iop_QSub8Ux8, Iop_QSub16Ux4, Iop_QSub32Ux2, Iop_QSub64Ux1,
779 Iop_QSub8Sx8, Iop_QSub16Sx4, Iop_QSub32Sx2, Iop_QSub64Sx1,
780
781 /* ABSOLUTE VALUE */
782 Iop_Abs8x8, Iop_Abs16x4, Iop_Abs32x2,
783
784 /* MULTIPLICATION (normal / high half of signed/unsigned / plynomial ) */
785 Iop_Mul8x8, Iop_Mul16x4, Iop_Mul32x2,
786 Iop_Mul32Fx2,
787 Iop_MulHi16Ux4,
788 Iop_MulHi16Sx4,
789 /* Plynomial multiplication treats it's arguments as coefficients of
790 polynoms over {0, 1}. */
791 Iop_PolynomialMul8x8,
792
793 /* Vector Saturating Doubling Multiply Returning High Half and
794 Vector Saturating Rounding Doubling Multiply Returning High Half */
795 /* These IROp's multiply corresponding elements in two vectors, double
796 the results, and place the most significant half of the final results
797 in the destination vector. The results are truncated or rounded. If
798 any of the results overflow, they are saturated. */
799 Iop_QDMulHi16Sx4, Iop_QDMulHi32Sx2,
800 Iop_QRDMulHi16Sx4, Iop_QRDMulHi32Sx2,
801
802 /* AVERAGING: note: (arg1 + arg2 + 1) >>u 1 */
803 Iop_Avg8Ux8,
804 Iop_Avg16Ux4,
805
806 /* MIN/MAX */
807 Iop_Max8Sx8, Iop_Max16Sx4, Iop_Max32Sx2,
808 Iop_Max8Ux8, Iop_Max16Ux4, Iop_Max32Ux2,
809 Iop_Min8Sx8, Iop_Min16Sx4, Iop_Min32Sx2,
810 Iop_Min8Ux8, Iop_Min16Ux4, Iop_Min32Ux2,
811
812 /* COMPARISON */
813 Iop_CmpEQ8x8, Iop_CmpEQ16x4, Iop_CmpEQ32x2,
814 Iop_CmpGT8Ux8, Iop_CmpGT16Ux4, Iop_CmpGT32Ux2,
815 Iop_CmpGT8Sx8, Iop_CmpGT16Sx4, Iop_CmpGT32Sx2,
816
817 /* COUNT ones / leading zeroes / leading sign bits (not including topmost
818 bit) */
819 Iop_Cnt8x8,
820 Iop_Clz8Sx8, Iop_Clz16Sx4, Iop_Clz32Sx2,
821 Iop_Cls8Sx8, Iop_Cls16Sx4, Iop_Cls32Sx2,
822
823 /* VECTOR x VECTOR SHIFT / ROTATE */
824 Iop_Shl8x8, Iop_Shl16x4, Iop_Shl32x2,
825 Iop_Shr8x8, Iop_Shr16x4, Iop_Shr32x2,
826 Iop_Sar8x8, Iop_Sar16x4, Iop_Sar32x2,
827 Iop_Sal8x8, Iop_Sal16x4, Iop_Sal32x2, Iop_Sal64x1,
828
829 /* VECTOR x SCALAR SHIFT (shift amt :: Ity_I8) */
830 Iop_ShlN8x8, Iop_ShlN16x4, Iop_ShlN32x2,
831 Iop_ShrN8x8, Iop_ShrN16x4, Iop_ShrN32x2,
832 Iop_SarN8x8, Iop_SarN16x4, Iop_SarN32x2,
833
834 /* VECTOR x VECTOR SATURATING SHIFT */
835 Iop_QShl8x8, Iop_QShl16x4, Iop_QShl32x2, Iop_QShl64x1,
836 Iop_QSal8x8, Iop_QSal16x4, Iop_QSal32x2, Iop_QSal64x1,
837 /* VECTOR x INTEGER SATURATING SHIFT */
838 Iop_QShlN8Sx8, Iop_QShlN16Sx4, Iop_QShlN32Sx2, Iop_QShlN64Sx1,
839 Iop_QShlN8x8, Iop_QShlN16x4, Iop_QShlN32x2, Iop_QShlN64x1,
840 Iop_QSalN8x8, Iop_QSalN16x4, Iop_QSalN32x2, Iop_QSalN64x1,
841
842 /* NARROWING -- narrow 2xI64 into 1xI64, hi half from left arg */
843 Iop_QNarrow16Ux4,
844 Iop_QNarrow16Sx4,
845 Iop_QNarrow32Sx2,
846
847 /* INTERLEAVING */
848 /* Interleave lanes from low or high halves of
849 operands. Most-significant result lane is from the left
850 arg. */
851 Iop_InterleaveHI8x8, Iop_InterleaveHI16x4, Iop_InterleaveHI32x2,
852 Iop_InterleaveLO8x8, Iop_InterleaveLO16x4, Iop_InterleaveLO32x2,
853 /* Interleave odd/even lanes of operands. Most-significant result lane
854 is from the left arg. Note that Interleave{Odd,Even}Lanes32x2 are
855 identical to Interleave{HI,LO}32x2 and so are omitted.*/
856 Iop_InterleaveOddLanes8x8, Iop_InterleaveEvenLanes8x8,
857 Iop_InterleaveOddLanes16x4, Iop_InterleaveEvenLanes16x4,
858
859
860 /* CONCATENATION -- build a new value by concatenating either
861 the even or odd lanes of both operands. Note that
862 Cat{Odd,Even}Lanes32x2 are identical to Interleave{HI,LO}32x2
863 and so are omitted. */
864 Iop_CatOddLanes8x8, Iop_CatOddLanes16x4,
865 Iop_CatEvenLanes8x8, Iop_CatEvenLanes16x4,
866
867 /* GET / SET elements of VECTOR
868 GET is binop (I64, I8) -> I<elem_size>
869 SET is triop (I64, I8, I<elem_size>) -> I64 */
870 /* Note: the arm back-end handles only constant second argument */
871 Iop_GetElem8x8, Iop_GetElem16x4, Iop_GetElem32x2,
872 Iop_SetElem8x8, Iop_SetElem16x4, Iop_SetElem32x2,
873
874 /* DUPLICATING -- copy value to all lanes */
875 Iop_Dup8x8, Iop_Dup16x4, Iop_Dup32x2,
876
877 /* EXTRACT -- copy 8-arg3 highest bytes from arg1 to 8-arg3 lowest bytes
878 of result and arg3 lowest bytes of arg2 to arg3 highest bytes of
879 result.
880 It is a triop: (I64, I64, I8) -> I64 */
881 /* Note: the arm back-end handles only constant third argumnet. */
882 Iop_Extract64,
883
884 /* REVERSE the order of elements in each Half-words, Words,
885 Double-words */
886 /* Examples:
887 Reverse16_8x8([a,b,c,d,e,f,g,h]) = [b,a,d,c,f,e,h,g]
888 Reverse32_8x8([a,b,c,d,e,f,g,h]) = [d,c,b,a,h,g,f,e]
889 Reverse64_8x8([a,b,c,d,e,f,g,h]) = [h,g,f,e,d,c,b,a] */
890 Iop_Reverse16_8x8,
891 Iop_Reverse32_8x8, Iop_Reverse32_16x4,
892 Iop_Reverse64_8x8, Iop_Reverse64_16x4, Iop_Reverse64_32x2,
893
894 /* PERMUTING -- copy src bytes to dst,
895 as indexed by control vector bytes:
896 for i in 0 .. 7 . result[i] = argL[ argR[i] ]
897 argR[i] values may only be in the range 0 .. 7, else behaviour
898 is undefined. */
899 Iop_Perm8x8,
900
901 /* Vector Reciprocal Estimate and Vector Reciprocal Square Root Estimate
902 See floating-point equiwalents for details. */
903 Iop_Recip32x2, Iop_Rsqrte32x2,
904
905 /* ------------------ 128-bit SIMD FP. ------------------ */
906
907 /* --- 32x4 vector FP --- */
908
909 /* binary */
910 Iop_Add32Fx4, Iop_Sub32Fx4, Iop_Mul32Fx4, Iop_Div32Fx4,
911 Iop_Max32Fx4, Iop_Min32Fx4,
912 Iop_Add32Fx2, Iop_Sub32Fx2,
913 /* Note: For the following compares, the ppc and arm front-ends assume a
914 nan in a lane of either argument returns zero for that lane. */
915 Iop_CmpEQ32Fx4, Iop_CmpLT32Fx4, Iop_CmpLE32Fx4, Iop_CmpUN32Fx4,
916 Iop_CmpGT32Fx4, Iop_CmpGE32Fx4,
917
918 /* Vector Absolute */
919 Iop_Abs32Fx4,
920
921 /* Pairwise Max and Min. See integer pairwise operations for details. */
922 Iop_PwMax32Fx4, Iop_PwMin32Fx4,
923
924 /* unary */
925 Iop_Sqrt32Fx4, Iop_RSqrt32Fx4,
926 Iop_Neg32Fx4,
927
928 /* Vector Reciprocal Estimate finds an approximate reciprocal of each
929 element in the operand vector, and places the results in the destination
930 vector. */
931 Iop_Recip32Fx4,
932
933 /* Vector Reciprocal Step computes (2.0 - arg1 * arg2).
934 Note, that if one of the arguments is zero and another one is infinity
935 of arbitrary sign the result of the operation is 2.0. */
936 Iop_Recps32Fx4,
937
938 /* Vector Reciprocal Square Root Estimate finds an approximate reciprocal
939 square root of each element in the operand vector. */
940 Iop_Rsqrte32Fx4,
941
942 /* Vector Reciprocal Square Root Step computes (3.0 - arg1 * arg2) / 2.0.
943 Note, that of one of the arguments is zero and another one is infiinty
944 of arbitrary sign the result of the operation is 1.5. */
945 Iop_Rsqrts32Fx4,
946
947
948 /* --- Int to/from FP conversion --- */
949 /* Unlike the standard fp conversions, these irops take no
950 rounding mode argument. Instead the irop trailers _R{M,P,N,Z}
951 indicate the mode: {-inf, +inf, nearest, zero} respectively. */
952 Iop_I32UtoFx4, Iop_I32StoFx4, /* I32x4 -> F32x4 */
953 Iop_FtoI32Ux4_RZ, Iop_FtoI32Sx4_RZ, /* F32x4 -> I32x4 */
954 Iop_QFtoI32Ux4_RZ, Iop_QFtoI32Sx4_RZ, /* F32x4 -> I32x4 (with saturation) */
955 Iop_RoundF32x4_RM, Iop_RoundF32x4_RP, /* round to fp integer */
956 Iop_RoundF32x4_RN, Iop_RoundF32x4_RZ, /* round to fp integer */
957 /* Fixed32 format is floating-point number with fixed number of fraction
958 bits. The number of fraction bits is passed as a second argument of
959 type I8. */
960 Iop_F32ToFixed32Ux4_RZ, Iop_F32ToFixed32Sx4_RZ, /* fp -> fixed-point */
961 Iop_Fixed32UToF32x4_RN, Iop_Fixed32SToF32x4_RN, /* fixed-point -> fp */
962
963 /* --- Single to/from half conversion --- */
964 Iop_F32toF16x4, Iop_F16toF32x4, /* F32x4 <-> F16x4 */
965
966 /* --- 32x4 lowest-lane-only scalar FP --- */
967
968 /* In binary cases, upper 3/4 is copied from first operand. In
969 unary cases, upper 3/4 is copied from the operand. */
970
971 /* binary */
972 Iop_Add32F0x4, Iop_Sub32F0x4, Iop_Mul32F0x4, Iop_Div32F0x4,
973 Iop_Max32F0x4, Iop_Min32F0x4,
974 Iop_CmpEQ32F0x4, Iop_CmpLT32F0x4, Iop_CmpLE32F0x4, Iop_CmpUN32F0x4,
975
976 /* unary */
977 Iop_Recip32F0x4, Iop_Sqrt32F0x4, Iop_RSqrt32F0x4,
978
979 /* --- 64x2 vector FP --- */
980
981 /* binary */
982 Iop_Add64Fx2, Iop_Sub64Fx2, Iop_Mul64Fx2, Iop_Div64Fx2,
983 Iop_Max64Fx2, Iop_Min64Fx2,
984 Iop_CmpEQ64Fx2, Iop_CmpLT64Fx2, Iop_CmpLE64Fx2, Iop_CmpUN64Fx2,
985
986 /* unary */
987 Iop_Recip64Fx2, Iop_Sqrt64Fx2, Iop_RSqrt64Fx2,
988
989 /* --- 64x2 lowest-lane-only scalar FP --- */
990
991 /* In binary cases, upper half is copied from first operand. In
992 unary cases, upper half is copied from the operand. */
993
994 /* binary */
995 Iop_Add64F0x2, Iop_Sub64F0x2, Iop_Mul64F0x2, Iop_Div64F0x2,
996 Iop_Max64F0x2, Iop_Min64F0x2,
997 Iop_CmpEQ64F0x2, Iop_CmpLT64F0x2, Iop_CmpLE64F0x2, Iop_CmpUN64F0x2,
998
999 /* unary */
1000 Iop_Recip64F0x2, Iop_Sqrt64F0x2, Iop_RSqrt64F0x2,
1001
1002 /* --- pack / unpack --- */
1003
1004 /* 64 <-> 128 bit vector */
1005 Iop_V128to64, // :: V128 -> I64, low half
1006 Iop_V128HIto64, // :: V128 -> I64, high half
1007 Iop_64HLtoV128, // :: (I64,I64) -> V128
1008
1009 Iop_64UtoV128,
1010 Iop_SetV128lo64,
1011
1012 /* 32 <-> 128 bit vector */
1013 Iop_32UtoV128,
1014 Iop_V128to32, // :: V128 -> I32, lowest lane
1015 Iop_SetV128lo32, // :: (V128,I32) -> V128
1016
1017 /* ------------------ 128-bit SIMD Integer. ------------------ */
1018
1019 /* BITWISE OPS */
1020 Iop_NotV128,
1021 Iop_AndV128, Iop_OrV128, Iop_XorV128,
1022
1023 /* VECTOR SHIFT (shift amt :: Ity_I8) */
1024 Iop_ShlV128, Iop_ShrV128,
1025
1026 /* MISC (vector integer cmp != 0) */
1027 Iop_CmpNEZ8x16, Iop_CmpNEZ16x8, Iop_CmpNEZ32x4, Iop_CmpNEZ64x2,
1028
1029 /* ADDITION (normal / unsigned sat / signed sat) */
1030 Iop_Add8x16, Iop_Add16x8, Iop_Add32x4, Iop_Add64x2,
1031 Iop_QAdd8Ux16, Iop_QAdd16Ux8, Iop_QAdd32Ux4, Iop_QAdd64Ux2,
1032 Iop_QAdd8Sx16, Iop_QAdd16Sx8, Iop_QAdd32Sx4, Iop_QAdd64Sx2,
1033
1034 /* SUBTRACTION (normal / unsigned sat / signed sat) */
1035 Iop_Sub8x16, Iop_Sub16x8, Iop_Sub32x4, Iop_Sub64x2,
1036 Iop_QSub8Ux16, Iop_QSub16Ux8, Iop_QSub32Ux4, Iop_QSub64Ux2,
1037 Iop_QSub8Sx16, Iop_QSub16Sx8, Iop_QSub32Sx4, Iop_QSub64Sx2,
1038
1039 /* MULTIPLICATION (normal / high half of signed/unsigned) */
1040 Iop_Mul8x16, Iop_Mul16x8, Iop_Mul32x4,
1041 Iop_MulHi16Ux8, Iop_MulHi32Ux4,
1042 Iop_MulHi16Sx8, Iop_MulHi32Sx4,
1043 /* (widening signed/unsigned of even lanes, with lowest lane=zero) */
1044 Iop_MullEven8Ux16, Iop_MullEven16Ux8,
1045 Iop_MullEven8Sx16, Iop_MullEven16Sx8,
1046 /* FIXME: document these */
1047 Iop_Mull8Ux8, Iop_Mull8Sx8,
1048 Iop_Mull16Ux4, Iop_Mull16Sx4,
1049 Iop_Mull32Ux2, Iop_Mull32Sx2,
1050 /* Vector Saturating Doubling Multiply Returning High Half and
1051 Vector Saturating Rounding Doubling Multiply Returning High Half */
1052 /* These IROp's multiply corresponding elements in two vectors, double
1053 the results, and place the most significant half of the final results
1054 in the destination vector. The results are truncated or rounded. If
1055 any of the results overflow, they are saturated. */
1056 Iop_QDMulHi16Sx8, Iop_QDMulHi32Sx4,
1057 Iop_QRDMulHi16Sx8, Iop_QRDMulHi32Sx4,
1058 /* Doubling saturating multiplication (long) (I64, I64) -> V128 */
1059 Iop_QDMulLong16Sx4, Iop_QDMulLong32Sx2,
1060 /* Plynomial multiplication treats it's arguments as coefficients of
1061 polynoms over {0, 1}. */
1062 Iop_PolynomialMul8x16, /* (V128, V128) -> V128 */
1063 Iop_PolynomialMull8x8, /* (I64, I64) -> V128 */
1064
1065 /* PAIRWISE operations */
1066 /* Iop_PwFoo16x4( [a,b,c,d], [e,f,g,h] ) =
1067 [Foo16(a,b), Foo16(c,d), Foo16(e,f), Foo16(g,h)] */
1068 Iop_PwAdd8x16, Iop_PwAdd16x8, Iop_PwAdd32x4,
1069 Iop_PwAdd32Fx2,
1070 /* Longening variant is unary. The resulting vector contains two times
1071 less elements than operand, but they are two times wider.
1072 Example:
1073 Iop_PwAddL16Ux4( [a,b,c,d] ) = [a+b,c+d]
1074 where a+b and c+d are unsigned 32-bit values. */
1075 Iop_PwAddL8Ux16, Iop_PwAddL16Ux8, Iop_PwAddL32Ux4,
1076 Iop_PwAddL8Sx16, Iop_PwAddL16Sx8, Iop_PwAddL32Sx4,
1077
1078 /* ABSOLUTE VALUE */
1079 Iop_Abs8x16, Iop_Abs16x8, Iop_Abs32x4,
1080
1081 /* AVERAGING: note: (arg1 + arg2 + 1) >>u 1 */
1082 Iop_Avg8Ux16, Iop_Avg16Ux8, Iop_Avg32Ux4,
1083 Iop_Avg8Sx16, Iop_Avg16Sx8, Iop_Avg32Sx4,
1084
1085 /* MIN/MAX */
1086 Iop_Max8Sx16, Iop_Max16Sx8, Iop_Max32Sx4,
1087 Iop_Max8Ux16, Iop_Max16Ux8, Iop_Max32Ux4,
1088 Iop_Min8Sx16, Iop_Min16Sx8, Iop_Min32Sx4,
1089 Iop_Min8Ux16, Iop_Min16Ux8, Iop_Min32Ux4,
1090
1091 /* COMPARISON */
1092 Iop_CmpEQ8x16, Iop_CmpEQ16x8, Iop_CmpEQ32x4,
1093 Iop_CmpGT8Sx16, Iop_CmpGT16Sx8, Iop_CmpGT32Sx4, Iop_CmpGT64Sx2,
1094 Iop_CmpGT8Ux16, Iop_CmpGT16Ux8, Iop_CmpGT32Ux4,
1095
1096 /* COUNT ones / leading zeroes / leading sign bits (not including topmost
1097 bit) */
1098 Iop_Cnt8x16,
1099 Iop_Clz8Sx16, Iop_Clz16Sx8, Iop_Clz32Sx4,
1100 Iop_Cls8Sx16, Iop_Cls16Sx8, Iop_Cls32Sx4,
1101
1102 /* VECTOR x SCALAR SHIFT (shift amt :: Ity_I8) */
1103 Iop_ShlN8x16, Iop_ShlN16x8, Iop_ShlN32x4, Iop_ShlN64x2,
1104 Iop_ShrN8x16, Iop_ShrN16x8, Iop_ShrN32x4, Iop_ShrN64x2,
1105 Iop_SarN8x16, Iop_SarN16x8, Iop_SarN32x4, Iop_SarN64x2,
1106
1107 /* VECTOR x VECTOR SHIFT / ROTATE */
1108 Iop_Shl8x16, Iop_Shl16x8, Iop_Shl32x4, Iop_Shl64x2,
1109 Iop_Shr8x16, Iop_Shr16x8, Iop_Shr32x4, Iop_Shr64x2,
1110 Iop_Sar8x16, Iop_Sar16x8, Iop_Sar32x4, Iop_Sar64x2,
1111 Iop_Sal8x16, Iop_Sal16x8, Iop_Sal32x4, Iop_Sal64x2,
1112 Iop_Rol8x16, Iop_Rol16x8, Iop_Rol32x4,
1113
1114 /* VECTOR x VECTOR SATURATING SHIFT */
1115 Iop_QShl8x16, Iop_QShl16x8, Iop_QShl32x4, Iop_QShl64x2,
1116 Iop_QSal8x16, Iop_QSal16x8, Iop_QSal32x4, Iop_QSal64x2,
1117 /* VECTOR x INTEGER SATURATING SHIFT */
1118 Iop_QShlN8Sx16, Iop_QShlN16Sx8, Iop_QShlN32Sx4, Iop_QShlN64Sx2,
1119 Iop_QShlN8x16, Iop_QShlN16x8, Iop_QShlN32x4, Iop_QShlN64x2,
1120 Iop_QSalN8x16, Iop_QSalN16x8, Iop_QSalN32x4, Iop_QSalN64x2,
1121
1122 /* NARROWING -- narrow 2xV128 into 1xV128, hi half from left arg */
1123 /* Note: the 16{U,S} and 32{U,S} are the pre-narrow lane widths. */
1124 Iop_QNarrow16Ux8, Iop_QNarrow32Ux4,
1125 Iop_QNarrow16Sx8, Iop_QNarrow32Sx4,
1126 Iop_Narrow16x8, Iop_Narrow32x4,
1127 /* Shortening V128->I64, lo half from each element */
1128 Iop_Shorten16x8, Iop_Shorten32x4, Iop_Shorten64x2,
1129 /* Saturating shortening from signed source to signed/unsigned destination */
1130 Iop_QShortenS16Sx8, Iop_QShortenS32Sx4, Iop_QShortenS64Sx2,
1131 Iop_QShortenU16Sx8, Iop_QShortenU32Sx4, Iop_QShortenU64Sx2,
1132 /* Saturating shortening from unsigned source to unsigned destination */
1133 Iop_QShortenU16Ux8, Iop_QShortenU32Ux4, Iop_QShortenU64Ux2,
1134
1135 /* WIDENING */
1136 /* Longening --- sign or zero extends each element of the argument
1137 vector to the twice original size. The resulting vector consists of
1138 the same number of elements but each element and the vector itself
1139 are two times wider.
1140 All operations are I64->V128.
1141 Example
1142 Iop_Longen32Sx2( [a, b] ) = [c, d]
1143 where c = Iop_32Sto64(a) and d = Iop_32Sto64(b) */
1144 Iop_Longen8Ux8, Iop_Longen16Ux4, Iop_Longen32Ux2,
1145 Iop_Longen8Sx8, Iop_Longen16Sx4, Iop_Longen32Sx2,
1146
1147 /* INTERLEAVING */
1148 /* Interleave lanes from low or high halves of
1149 operands. Most-significant result lane is from the left
1150 arg. */
1151 Iop_InterleaveHI8x16, Iop_InterleaveHI16x8,
1152 Iop_InterleaveHI32x4, Iop_InterleaveHI64x2,
1153 Iop_InterleaveLO8x16, Iop_InterleaveLO16x8,
1154 Iop_InterleaveLO32x4, Iop_InterleaveLO64x2,
1155 /* Interleave odd/even lanes of operands. Most-significant result lane
1156 is from the left arg. */
1157 Iop_InterleaveOddLanes8x16, Iop_InterleaveEvenLanes8x16,
1158 Iop_InterleaveOddLanes16x8, Iop_InterleaveEvenLanes16x8,
1159 Iop_InterleaveOddLanes32x4, Iop_InterleaveEvenLanes32x4,
1160
1161 /* CONCATENATION -- build a new value by concatenating either
1162 the even or odd lanes of both operands. */
1163 Iop_CatOddLanes8x16, Iop_CatOddLanes16x8, Iop_CatOddLanes32x4,
1164 Iop_CatEvenLanes8x16, Iop_CatEvenLanes16x8, Iop_CatEvenLanes32x4,
1165
1166 /* GET elements of VECTOR
1167 GET is binop (V128, I8) -> I<elem_size> */
1168 /* Note: the arm back-end handles only constant second argument. */
1169 Iop_GetElem8x16, Iop_GetElem16x8, Iop_GetElem32x4, Iop_GetElem64x2,
1170
1171 /* DUPLICATING -- copy value to all lanes */
1172 Iop_Dup8x16, Iop_Dup16x8, Iop_Dup32x4,
1173
1174 /* EXTRACT -- copy 16-arg3 highest bytes from arg1 to 16-arg3 lowest bytes
1175 of result and arg3 lowest bytes of arg2 to arg3 highest bytes of
1176 result.
1177 It is a triop: (V128, V128, I8) -> V128 */
1178 /* Note: the ARM back end handles only constant arg3 in this operation. */
1179 Iop_ExtractV128,
1180
1181 /* REVERSE the order of elements in each Half-words, Words,
1182 Double-words */
1183 /* Examples:
1184 Reverse32_16x8([a,b,c,d,e,f,g,h]) = [b,a,d,c,f,e,h,g]
1185 Reverse64_16x8([a,b,c,d,e,f,g,h]) = [d,c,b,a,h,g,f,e] */
1186 Iop_Reverse16_8x16,
1187 Iop_Reverse32_8x16, Iop_Reverse32_16x8,
1188 Iop_Reverse64_8x16, Iop_Reverse64_16x8, Iop_Reverse64_32x4,
1189
1190 /* PERMUTING -- copy src bytes to dst,
1191 as indexed by control vector bytes:
1192 for i in 0 .. 15 . result[i] = argL[ argR[i] ]
1193 argR[i] values may only be in the range 0 .. 15, else behaviour
1194 is undefined. */
1195 Iop_Perm8x16,
1196
1197 /* Vector Reciprocal Estimate and Vector Reciprocal Square Root Estimate
1198 See floating-point equiwalents for details. */
1199 Iop_Recip32x4, Iop_Rsqrte32x4
1200 }
1201 IROp;
1202
1203 /* Pretty-print an op. */
1204 extern void ppIROp ( IROp );
1205
1206
1207 /* Encoding of IEEE754-specified rounding modes. This is the same as
1208 the encoding used by Intel IA32 to indicate x87 rounding mode.
1209 Note, various front and back ends rely on the actual numerical
1210 values of these, so do not change them. */
1211 typedef
1212 enum {
1213 Irrm_NEAREST = 0,
1214 Irrm_NegINF = 1,
1215 Irrm_PosINF = 2,
1216 Irrm_ZERO = 3
1217 }
1218 IRRoundingMode;
1219
1220 /* Floating point comparison result values, as created by Iop_CmpF64.
1221 This is also derived from what IA32 does. */
1222 typedef
1223 enum {
1224 Ircr_UN = 0x45,
1225 Ircr_LT = 0x01,
1226 Ircr_GT = 0x00,
1227 Ircr_EQ = 0x40
1228 }
1229 IRCmpF64Result;
1230
1231
1232 /* ------------------ Expressions ------------------ */
1233
1234 /* The different kinds of expressions. Their meaning is explained below
1235 in the comments for IRExpr. */
1236 typedef
1237 enum {
1238 Iex_Binder=0x15000,
1239 Iex_Get,
1240 Iex_GetI,
1241 Iex_RdTmp,
1242 Iex_Qop,
1243 Iex_Triop,
1244 Iex_Binop,
1245 Iex_Unop,
1246 Iex_Load,
1247 Iex_Const,
1248 Iex_Mux0X,
1249 Iex_CCall
1250 }
1251 IRExprTag;
1252
1253 /* An expression. Stored as a tagged union. 'tag' indicates what kind
1254 of expression this is. 'Iex' is the union that holds the fields. If
1255 an IRExpr 'e' has e.tag equal to Iex_Load, then it's a load
1256 expression, and the fields can be accessed with
1257 'e.Iex.Load.<fieldname>'.
1258
1259 For each kind of expression, we show what it looks like when
1260 pretty-printed with ppIRExpr().
1261 */
1262 typedef
1263 struct _IRExpr
1264 IRExpr;
1265
1266 struct _IRExpr {
1267 IRExprTag tag;
1268 union {
1269 /* Used only in pattern matching within Vex. Should not be seen
1270 outside of Vex. */
1271 struct {
1272 Int binder;
1273 } Binder;
1274
1275 /* Read a guest register, at a fixed offset in the guest state.
1276 ppIRExpr output: GET:<ty>(<offset>), eg. GET:I32(0)
1277 */
1278 struct {
1279 Int offset; /* Offset into the guest state */
1280 IRType ty; /* Type of the value being read */
1281 } Get;
1282
1283 /* Read a guest register at a non-fixed offset in the guest
1284 state. This allows circular indexing into parts of the guest
1285 state, which is essential for modelling situations where the
1286 identity of guest registers is not known until run time. One
1287 example is the x87 FP register stack.
1288
1289 The part of the guest state to be treated as a circular array
1290 is described in the IRRegArray 'descr' field. It holds the
1291 offset of the first element in the array, the type of each
1292 element, and the number of elements.
1293
1294 The array index is indicated rather indirectly, in a way
1295 which makes optimisation easy: as the sum of variable part
1296 (the 'ix' field) and a constant offset (the 'bias' field).
1297
1298 Since the indexing is circular, the actual array index to use
1299 is computed as (ix + bias) % num-of-elems-in-the-array.
1300
1301 Here's an example. The description
1302
1303 (96:8xF64)[t39,-7]
1304
1305 describes an array of 8 F64-typed values, the
1306 guest-state-offset of the first being 96. This array is
1307 being indexed at (t39 - 7) % 8.
1308
1309 It is important to get the array size/type exactly correct
1310 since IR optimisation looks closely at such info in order to
1311 establish aliasing/non-aliasing between seperate GetI and
1312 PutI events, which is used to establish when they can be
1313 reordered, etc. Putting incorrect info in will lead to
1314 obscure IR optimisation bugs.
1315
1316 ppIRExpr output: GETI<descr>[<ix>,<bias]
1317 eg. GETI(128:8xI8)[t1,0]
1318 */
1319 struct {
1320 IRRegArray* descr; /* Part of guest state treated as circular */
1321 IRExpr* ix; /* Variable part of index into array */
1322 Int bias; /* Constant offset part of index into array */
1323 } GetI;
1324
1325 /* The value held by a temporary.
1326 ppIRExpr output: t<tmp>, eg. t1
1327 */
1328 struct {
1329 IRTemp tmp; /* The temporary number */
1330 } RdTmp;
1331
1332 /* A quaternary operation.
1333 ppIRExpr output: <op>(<arg1>, <arg2>, <arg3>, <arg4>),
1334 eg. MAddF64r32(t1, t2, t3, t4)
1335 */
1336 struct {
1337 IROp op; /* op-code */
1338 IRExpr* arg1; /* operand 1 */
1339 IRExpr* arg2; /* operand 2 */
1340 IRExpr* arg3; /* operand 3 */
1341 IRExpr* arg4; /* operand 4 */
1342 } Qop;
1343
1344 /* A ternary operation.
1345 ppIRExpr output: <op>(<arg1>, <arg2>, <arg3>),
1346 eg. MulF64(1, 2.0, 3.0)
1347 */
1348 struct {
1349 IROp op; /* op-code */
1350 IRExpr* arg1; /* operand 1 */
1351 IRExpr* arg2; /* operand 2 */
1352 IRExpr* arg3; /* operand 3 */
1353 } Triop;
1354
1355 /* A binary operation.
1356 ppIRExpr output: <op>(<arg1>, <arg2>), eg. Add32(t1,t2)
1357 */
1358 struct {
1359 IROp op; /* op-code */
1360 IRExpr* arg1; /* operand 1 */
1361 IRExpr* arg2; /* operand 2 */
1362 } Binop;
1363
1364 /* A unary operation.
1365 ppIRExpr output: <op>(<arg>), eg. Neg8(t1)
1366 */
1367 struct {
1368 IROp op; /* op-code */
1369 IRExpr* arg; /* operand */
1370 } Unop;
1371
1372 /* A load from memory -- a normal load, not a load-linked.
1373 Load-Linkeds (and Store-Conditionals) are instead represented
1374 by IRStmt.LLSC since Load-Linkeds have side effects and so
1375 are not semantically valid IRExpr's.
1376 ppIRExpr output: LD<end>:<ty>(<addr>), eg. LDle:I32(t1)
1377 */
1378 struct {
1379 IREndness end; /* Endian-ness of the load */
1380 IRType ty; /* Type of the loaded value */
1381 IRExpr* addr; /* Address being loaded from */
1382 } Load;
1383
1384 /* A constant-valued expression.
1385 ppIRExpr output: <con>, eg. 0x4:I32
1386 */
1387 struct {
1388 IRConst* con; /* The constant itself */
1389 } Const;
1390
1391 /* A call to a pure (no side-effects) helper C function.
1392
1393 With the 'cee' field, 'name' is the function's name. It is
1394 only used for pretty-printing purposes. The address to call
1395 (host address, of course) is stored in the 'addr' field
1396 inside 'cee'.
1397
1398 The 'args' field is a NULL-terminated array of arguments.
1399 The stated return IRType, and the implied argument types,
1400 must match that of the function being called well enough so
1401 that the back end can actually generate correct code for the
1402 call.
1403
1404 The called function **must** satisfy the following:
1405
1406 * no side effects -- must be a pure function, the result of
1407 which depends only on the passed parameters.
1408
1409 * it may not look at, nor modify, any of the guest state
1410 since that would hide guest state transitions from
1411 instrumenters
1412
1413 * it may not access guest memory, since that would hide
1414 guest memory transactions from the instrumenters
1415
1416 This is restrictive, but makes the semantics clean, and does
1417 not interfere with IR optimisation.
1418
1419 If you want to call a helper which can mess with guest state
1420 and/or memory, instead use Ist_Dirty. This is a lot more
1421 flexible, but you have to give a bunch of details about what
1422 the helper does (and you better be telling the truth,
1423 otherwise any derived instrumentation will be wrong). Also
1424 Ist_Dirty inhibits various IR optimisations and so can cause
1425 quite poor code to be generated. Try to avoid it.
1426
1427 ppIRExpr output: <cee>(<args>):<retty>
1428 eg. foo{0x80489304}(t1, t2):I32
1429 */
1430 struct {
1431 IRCallee* cee; /* Function to call. */
1432 IRType retty; /* Type of return value. */
1433 IRExpr** args; /* Vector of argument expressions. */
1434 } CCall;
1435
1436 /* A ternary if-then-else operator. It returns expr0 if cond is
1437 zero, exprX otherwise. Note that it is STRICT, ie. both
1438 expr0 and exprX are evaluated in all cases.
1439
1440 ppIRExpr output: Mux0X(<cond>,<expr0>,<exprX>),
1441 eg. Mux0X(t6,t7,t8)
1442 */
1443 struct {
1444 IRExpr* cond; /* Condition */
1445 IRExpr* expr0; /* True expression */
1446 IRExpr* exprX; /* False expression */
1447 } Mux0X;
1448 } Iex;
1449 };
1450
1451 /* Expression constructors. */
1452 extern IRExpr* IRExpr_Binder ( Int binder );
1453 extern IRExpr* IRExpr_Get ( Int off, IRType ty );
1454 extern IRExpr* IRExpr_GetI ( IRRegArray* descr, IRExpr* ix, Int bias );
1455 extern IRExpr* IRExpr_RdTmp ( IRTemp tmp );
1456 extern IRExpr* IRExpr_Qop ( IROp op, IRExpr* arg1, IRExpr* arg2,
1457 IRExpr* arg3, IRExpr* arg4 );
1458 extern IRExpr* IRExpr_Triop ( IROp op, IRExpr* arg1,
1459 IRExpr* arg2, IRExpr* arg3 );
1460 extern IRExpr* IRExpr_Binop ( IROp op, IRExpr* arg1, IRExpr* arg2 );
1461 extern IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg );
1462 extern IRExpr* IRExpr_Load ( IREndness end, IRType ty, IRExpr* addr );
1463 extern IRExpr* IRExpr_Const ( IRConst* con );
1464 extern IRExpr* IRExpr_CCall ( IRCallee* cee, IRType retty, IRExpr** args );
1465 extern IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX );
1466
1467 /* Deep-copy an IRExpr. */
1468 extern IRExpr* deepCopyIRExpr ( IRExpr* );
1469
1470 /* Pretty-print an IRExpr. */
1471 extern void ppIRExpr ( IRExpr* );
1472
1473 /* NULL-terminated IRExpr vector constructors, suitable for
1474 use as arg lists in clean/dirty helper calls. */
1475 extern IRExpr** mkIRExprVec_0 ( void );
1476 extern IRExpr** mkIRExprVec_1 ( IRExpr* );
1477 extern IRExpr** mkIRExprVec_2 ( IRExpr*, IRExpr* );
1478 extern IRExpr** mkIRExprVec_3 ( IRExpr*, IRExpr*, IRExpr* );
1479 extern IRExpr** mkIRExprVec_4 ( IRExpr*, IRExpr*, IRExpr*, IRExpr* );
1480 extern IRExpr** mkIRExprVec_5 ( IRExpr*, IRExpr*, IRExpr*, IRExpr*,
1481 IRExpr* );
1482 extern IRExpr** mkIRExprVec_6 ( IRExpr*, IRExpr*, IRExpr*, IRExpr*,
1483 IRExpr*, IRExpr* );
1484 extern IRExpr** mkIRExprVec_7 ( IRExpr*, IRExpr*, IRExpr*, IRExpr*,
1485 IRExpr*, IRExpr*, IRExpr* );
1486 extern IRExpr** mkIRExprVec_8 ( IRExpr*, IRExpr*, IRExpr*, IRExpr*,
1487 IRExpr*, IRExpr*, IRExpr*, IRExpr*);
1488
1489 /* IRExpr copiers:
1490 - shallowCopy: shallow-copy (ie. create a new vector that shares the
1491 elements with the original).
1492 - deepCopy: deep-copy (ie. create a completely new vector). */
1493 extern IRExpr** shallowCopyIRExprVec ( IRExpr** );
1494 extern IRExpr** deepCopyIRExprVec ( IRExpr** );
1495
1496 /* Make a constant expression from the given host word taking into
1497 account (of course) the host word size. */
1498 extern IRExpr* mkIRExpr_HWord ( HWord );
1499
1500 /* Convenience function for constructing clean helper calls. */
1501 extern
1502 IRExpr* mkIRExprCCall ( IRType retty,
1503 Int regparms, HChar* name, void* addr,
1504 IRExpr** args );
1505
1506
1507 /* Convenience functions for atoms (IRExprs which are either Iex_Tmp or
1508 * Iex_Const). */
isIRAtom(IRExpr * e)1509 static inline Bool isIRAtom ( IRExpr* e ) {
1510 return toBool(e->tag == Iex_RdTmp || e->tag == Iex_Const);
1511 }
1512
1513 /* Are these two IR atoms identical? Causes an assertion
1514 failure if they are passed non-atoms. */
1515 extern Bool eqIRAtom ( IRExpr*, IRExpr* );
1516
1517
1518 /* ------------------ Jump kinds ------------------ */
1519
1520 /* This describes hints which can be passed to the dispatcher at guest
1521 control-flow transfer points.
1522
1523 Re Ijk_TInval: the guest state _must_ have two pseudo-registers,
1524 guest_TISTART and guest_TILEN, which specify the start and length
1525 of the region to be invalidated. These are both the size of a
1526 guest word. It is the responsibility of the relevant toIR.c to
1527 ensure that these are filled in with suitable values before issuing
1528 a jump of kind Ijk_TInval.
1529
1530 Re Ijk_EmWarn and Ijk_EmFail: the guest state must have a
1531 pseudo-register guest_EMWARN, which is 32-bits regardless of the
1532 host or guest word size. That register should be made to hold an
1533 EmWarn_* value to indicate the reason for the exit.
1534
1535 In the case of Ijk_EmFail, the exit is fatal (Vex-generated code
1536 cannot continue) and so the jump destination can be anything.
1537
1538 Re Ijk_Sys_ (syscall jumps): the guest state must have a
1539 pseudo-register guest_IP_AT_SYSCALL, which is the size of a guest
1540 word. Front ends should set this to be the IP at the most recently
1541 executed kernel-entering (system call) instruction. This makes it
1542 very much easier (viz, actually possible at all) to back up the
1543 guest to restart a syscall that has been interrupted by a signal.
1544 */
1545 typedef
1546 enum {
1547 Ijk_Boring=0x16000, /* not interesting; just goto next */
1548 Ijk_Call, /* guest is doing a call */
1549 Ijk_Ret, /* guest is doing a return */
1550 Ijk_ClientReq, /* do guest client req before continuing */
1551 Ijk_Yield, /* client is yielding to thread scheduler */
1552 Ijk_YieldNoRedir, /* client is yielding to thread scheduler AND jump to
1553 un-redirected guest addr */
1554 Ijk_EmWarn, /* report emulation warning before continuing */
1555 Ijk_EmFail, /* emulation critical (FATAL) error; give up */
1556 Ijk_NoDecode, /* next instruction cannot be decoded */
1557 Ijk_MapFail, /* Vex-provided address translation failed */
1558 Ijk_TInval, /* Invalidate translations before continuing. */
1559 Ijk_NoRedir, /* Jump to un-redirected guest addr */
1560 Ijk_SigTRAP, /* current instruction synths SIGTRAP */
1561 Ijk_SigSEGV, /* current instruction synths SIGSEGV */
1562 Ijk_SigBUS, /* current instruction synths SIGBUS */
1563 /* Unfortunately, various guest-dependent syscall kinds. They
1564 all mean: do a syscall before continuing. */
1565 Ijk_Sys_syscall, /* amd64 'syscall', ppc 'sc', arm 'svc #0' */
1566 Ijk_Sys_int32, /* amd64/x86 'int $0x20' */
1567 Ijk_Sys_int128, /* amd64/x86 'int $0x80' */
1568 Ijk_Sys_int129, /* amd64/x86 'int $0x81' */
1569 Ijk_Sys_int130, /* amd64/x86 'int $0x82' */
1570 Ijk_Sys_sysenter /* x86 'sysenter'. guest_EIP becomes
1571 invalid at the point this happens. */
1572 }
1573 IRJumpKind;
1574
1575 extern void ppIRJumpKind ( IRJumpKind );
1576
1577
1578 /* ------------------ Dirty helper calls ------------------ */
1579
1580 /* A dirty call is a flexible mechanism for calling (possibly
1581 conditionally) a helper function or procedure. The helper function
1582 may read, write or modify client memory, and may read, write or
1583 modify client state. It can take arguments and optionally return a
1584 value. It may return different results and/or do different things
1585 when called repeatedly with the same arguments, by means of storing
1586 private state.
1587
1588 If a value is returned, it is assigned to the nominated return
1589 temporary.
1590
1591 Dirty calls are statements rather than expressions for obvious
1592 reasons. If a dirty call is marked as writing guest state, any
1593 values derived from the written parts of the guest state are
1594 invalid. Similarly, if the dirty call is stated as writing
1595 memory, any loaded values are invalidated by it.
1596
1597 In order that instrumentation is possible, the call must state, and
1598 state correctly:
1599
1600 * whether it reads, writes or modifies memory, and if so where
1601 (only one chunk can be stated)
1602
1603 * whether it reads, writes or modifies guest state, and if so which
1604 pieces (several pieces may be stated, and currently their extents
1605 must be known at translation-time).
1606
1607 Normally, code is generated to pass just the args to the helper.
1608 However, if .needsBBP is set, then an extra first argument is
1609 passed, which is the baseblock pointer, so that the callee can
1610 access the guest state. It is invalid for .nFxState to be zero
1611 but .needsBBP to be True, since .nFxState==0 is a claim that the
1612 call does not access guest state.
1613
1614 IMPORTANT NOTE re GUARDS: Dirty calls are strict, very strict. The
1615 arguments are evaluated REGARDLESS of the guard value. It is
1616 unspecified the relative order of arg evaluation and guard
1617 evaluation.
1618 */
1619
1620 #define VEX_N_FXSTATE 7 /* enough for FXSAVE/FXRSTOR on x86 */
1621
1622 /* Effects on resources (eg. registers, memory locations) */
1623 typedef
1624 enum {
1625 Ifx_None = 0x17000, /* no effect */
1626 Ifx_Read, /* reads the resource */
1627 Ifx_Write, /* writes the resource */
1628 Ifx_Modify, /* modifies the resource */
1629 }
1630 IREffect;
1631
1632 /* Pretty-print an IREffect */
1633 extern void ppIREffect ( IREffect );
1634
1635
1636 typedef
1637 struct {
1638 /* What to call, and details of args/results */
1639 IRCallee* cee; /* where to call */
1640 IRExpr* guard; /* :: Ity_Bit. Controls whether call happens */
1641 IRExpr** args; /* arg list, ends in NULL */
1642 IRTemp tmp; /* to assign result to, or IRTemp_INVALID if none */
1643
1644 /* Mem effects; we allow only one R/W/M region to be stated */
1645 IREffect mFx; /* indicates memory effects, if any */
1646 IRExpr* mAddr; /* of access, or NULL if mFx==Ifx_None */
1647 Int mSize; /* of access, or zero if mFx==Ifx_None */
1648
1649 /* Guest state effects; up to N allowed */
1650 Bool needsBBP; /* True => also pass guest state ptr to callee */
1651 Int nFxState; /* must be 0 .. VEX_N_FXSTATE */
1652 struct {
1653 IREffect fx; /* read, write or modify? Ifx_None is invalid. */
1654 Int offset;
1655 Int size;
1656 } fxState[VEX_N_FXSTATE];
1657 }
1658 IRDirty;
1659
1660 /* Pretty-print a dirty call */
1661 extern void ppIRDirty ( IRDirty* );
1662
1663 /* Allocate an uninitialised dirty call */
1664 extern IRDirty* emptyIRDirty ( void );
1665
1666 /* Deep-copy a dirty call */
1667 extern IRDirty* deepCopyIRDirty ( IRDirty* );
1668
1669 /* A handy function which takes some of the tedium out of constructing
1670 dirty helper calls. The called function impliedly does not return
1671 any value and has a constant-True guard. The call is marked as
1672 accessing neither guest state nor memory (hence the "unsafe"
1673 designation) -- you can change this marking later if need be. A
1674 suitable IRCallee is constructed from the supplied bits. */
1675 extern
1676 IRDirty* unsafeIRDirty_0_N ( Int regparms, HChar* name, void* addr,
1677 IRExpr** args );
1678
1679 /* Similarly, make a zero-annotation dirty call which returns a value,
1680 and assign that to the given temp. */
1681 extern
1682 IRDirty* unsafeIRDirty_1_N ( IRTemp dst,
1683 Int regparms, HChar* name, void* addr,
1684 IRExpr** args );
1685
1686
1687 /* --------------- Memory Bus Events --------------- */
1688
1689 typedef
1690 enum {
1691 Imbe_Fence=0x18000,
1692 }
1693 IRMBusEvent;
1694
1695 extern void ppIRMBusEvent ( IRMBusEvent );
1696
1697
1698 /* --------------- Compare and Swap --------------- */
1699
1700 /* This denotes an atomic compare and swap operation, either
1701 a single-element one or a double-element one.
1702
1703 In the single-element case:
1704
1705 .addr is the memory address.
1706 .end is the endianness with which memory is accessed
1707
1708 If .addr contains the same value as .expdLo, then .dataLo is
1709 written there, else there is no write. In both cases, the
1710 original value at .addr is copied into .oldLo.
1711
1712 Types: .expdLo, .dataLo and .oldLo must all have the same type.
1713 It may be any integral type, viz: I8, I16, I32 or, for 64-bit
1714 guests, I64.
1715
1716 .oldHi must be IRTemp_INVALID, and .expdHi and .dataHi must
1717 be NULL.
1718
1719 In the double-element case:
1720
1721 .addr is the memory address.
1722 .end is the endianness with which memory is accessed
1723
1724 The operation is the same:
1725
1726 If .addr contains the same value as .expdHi:.expdLo, then
1727 .dataHi:.dataLo is written there, else there is no write. In
1728 both cases the original value at .addr is copied into
1729 .oldHi:.oldLo.
1730
1731 Types: .expdHi, .expdLo, .dataHi, .dataLo, .oldHi, .oldLo must
1732 all have the same type, which may be any integral type, viz: I8,
1733 I16, I32 or, for 64-bit guests, I64.
1734
1735 The double-element case is complicated by the issue of
1736 endianness. In all cases, the two elements are understood to be
1737 located adjacently in memory, starting at the address .addr.
1738
1739 If .end is Iend_LE, then the .xxxLo component is at the lower
1740 address and the .xxxHi component is at the higher address, and
1741 each component is itself stored little-endianly.
1742
1743 If .end is Iend_BE, then the .xxxHi component is at the lower
1744 address and the .xxxLo component is at the higher address, and
1745 each component is itself stored big-endianly.
1746
1747 This allows representing more cases than most architectures can
1748 handle. For example, x86 cannot do DCAS on 8- or 16-bit elements.
1749
1750 How to know if the CAS succeeded?
1751
1752 * if .oldLo == .expdLo (resp. .oldHi:.oldLo == .expdHi:.expdLo),
1753 then the CAS succeeded, .dataLo (resp. .dataHi:.dataLo) is now
1754 stored at .addr, and the original value there was .oldLo (resp
1755 .oldHi:.oldLo).
1756
1757 * if .oldLo != .expdLo (resp. .oldHi:.oldLo != .expdHi:.expdLo),
1758 then the CAS failed, and the original value at .addr was .oldLo
1759 (resp. .oldHi:.oldLo).
1760
1761 Hence it is easy to know whether or not the CAS succeeded.
1762 */
1763 typedef
1764 struct {
1765 IRTemp oldHi; /* old value of *addr is written here */
1766 IRTemp oldLo;
1767 IREndness end; /* endianness of the data in memory */
1768 IRExpr* addr; /* store address */
1769 IRExpr* expdHi; /* expected old value at *addr */
1770 IRExpr* expdLo;
1771 IRExpr* dataHi; /* new value for *addr */
1772 IRExpr* dataLo;
1773 }
1774 IRCAS;
1775
1776 extern void ppIRCAS ( IRCAS* cas );
1777
1778 extern IRCAS* mkIRCAS ( IRTemp oldHi, IRTemp oldLo,
1779 IREndness end, IRExpr* addr,
1780 IRExpr* expdHi, IRExpr* expdLo,
1781 IRExpr* dataHi, IRExpr* dataLo );
1782
1783 extern IRCAS* deepCopyIRCAS ( IRCAS* );
1784
1785 /* ------------------ Statements ------------------ */
1786
1787 /* The different kinds of statements. Their meaning is explained
1788 below in the comments for IRStmt.
1789
1790 Those marked META do not represent code, but rather extra
1791 information about the code. These statements can be removed
1792 without affecting the functional behaviour of the code, however
1793 they are required by some IR consumers such as tools that
1794 instrument the code.
1795 */
1796
1797 typedef
1798 enum {
1799 Ist_NoOp=0x19000,
1800 Ist_IMark, /* META */
1801 Ist_AbiHint, /* META */
1802 Ist_Put,
1803 Ist_PutI,
1804 Ist_WrTmp,
1805 Ist_Store,
1806 Ist_CAS,
1807 Ist_LLSC,
1808 Ist_Dirty,
1809 Ist_MBE, /* META (maybe) */
1810 Ist_Exit
1811 }
1812 IRStmtTag;
1813
1814 /* A statement. Stored as a tagged union. 'tag' indicates what kind
1815 of expression this is. 'Ist' is the union that holds the fields.
1816 If an IRStmt 'st' has st.tag equal to Iex_Store, then it's a store
1817 statement, and the fields can be accessed with
1818 'st.Ist.Store.<fieldname>'.
1819
1820 For each kind of statement, we show what it looks like when
1821 pretty-printed with ppIRStmt().
1822 */
1823 typedef
1824 struct _IRStmt {
1825 IRStmtTag tag;
1826 union {
1827 /* A no-op (usually resulting from IR optimisation). Can be
1828 omitted without any effect.
1829
1830 ppIRStmt output: IR-NoOp
1831 */
1832 struct {
1833 } NoOp;
1834
1835 /* META: instruction mark. Marks the start of the statements
1836 that represent a single machine instruction (the end of
1837 those statements is marked by the next IMark or the end of
1838 the IRSB). Contains the address and length of the
1839 instruction.
1840
1841 ppIRStmt output: ------ IMark(<addr>, <len>) ------,
1842 eg. ------ IMark(0x4000792, 5) ------,
1843 */
1844 struct {
1845 Addr64 addr; /* instruction address */
1846 Int len; /* instruction length */
1847 } IMark;
1848
1849 /* META: An ABI hint, which says something about this
1850 platform's ABI.
1851
1852 At the moment, the only AbiHint is one which indicates
1853 that a given chunk of address space, [base .. base+len-1],
1854 has become undefined. This is used on amd64-linux and
1855 some ppc variants to pass stack-redzoning hints to whoever
1856 wants to see them. It also indicates the address of the
1857 next (dynamic) instruction that will be executed. This is
1858 to help Memcheck to origin tracking.
1859
1860 ppIRStmt output: ====== AbiHint(<base>, <len>, <nia>) ======
1861 eg. ====== AbiHint(t1, 16, t2) ======
1862 */
1863 struct {
1864 IRExpr* base; /* Start of undefined chunk */
1865 Int len; /* Length of undefined chunk */
1866 IRExpr* nia; /* Address of next (guest) insn */
1867 } AbiHint;
1868
1869 /* Write a guest register, at a fixed offset in the guest state.
1870 ppIRStmt output: PUT(<offset>) = <data>, eg. PUT(60) = t1
1871 */
1872 struct {
1873 Int offset; /* Offset into the guest state */
1874 IRExpr* data; /* The value to write */
1875 } Put;
1876
1877 /* Write a guest register, at a non-fixed offset in the guest
1878 state. See the comment for GetI expressions for more
1879 information.
1880
1881 ppIRStmt output: PUTI<descr>[<ix>,<bias>] = <data>,
1882 eg. PUTI(64:8xF64)[t5,0] = t1
1883 */
1884 struct {
1885 IRRegArray* descr; /* Part of guest state treated as circular */
1886 IRExpr* ix; /* Variable part of index into array */
1887 Int bias; /* Constant offset part of index into array */
1888 IRExpr* data; /* The value to write */
1889 } PutI;
1890
1891 /* Assign a value to a temporary. Note that SSA rules require
1892 each tmp is only assigned to once. IR sanity checking will
1893 reject any block containing a temporary which is not assigned
1894 to exactly once.
1895
1896 ppIRStmt output: t<tmp> = <data>, eg. t1 = 3
1897 */
1898 struct {
1899 IRTemp tmp; /* Temporary (LHS of assignment) */
1900 IRExpr* data; /* Expression (RHS of assignment) */
1901 } WrTmp;
1902
1903 /* Write a value to memory. This is a normal store, not a
1904 Store-Conditional. To represent a Store-Conditional,
1905 instead use IRStmt.LLSC.
1906 ppIRStmt output: ST<end>(<addr>) = <data>, eg. STle(t1) = t2
1907 */
1908 struct {
1909 IREndness end; /* Endianness of the store */
1910 IRExpr* addr; /* store address */
1911 IRExpr* data; /* value to write */
1912 } Store;
1913
1914 /* Do an atomic compare-and-swap operation. Semantics are
1915 described above on a comment at the definition of IRCAS.
1916
1917 ppIRStmt output:
1918 t<tmp> = CAS<end>(<addr> :: <expected> -> <new>)
1919 eg
1920 t1 = CASle(t2 :: t3->Add32(t3,1))
1921 which denotes a 32-bit atomic increment
1922 of a value at address t2
1923
1924 A double-element CAS may also be denoted, in which case <tmp>,
1925 <expected> and <new> are all pairs of items, separated by
1926 commas.
1927 */
1928 struct {
1929 IRCAS* details;
1930 } CAS;
1931
1932 /* Either Load-Linked or Store-Conditional, depending on
1933 STOREDATA.
1934
1935 If STOREDATA is NULL then this is a Load-Linked, meaning
1936 that data is loaded from memory as normal, but a
1937 'reservation' for the address is also lodged in the
1938 hardware.
1939
1940 result = Load-Linked(addr, end)
1941
1942 The data transfer type is the type of RESULT (I32, I64,
1943 etc). ppIRStmt output:
1944
1945 result = LD<end>-Linked(<addr>), eg. LDbe-Linked(t1)
1946
1947 If STOREDATA is not NULL then this is a Store-Conditional,
1948 hence:
1949
1950 result = Store-Conditional(addr, storedata, end)
1951
1952 The data transfer type is the type of STOREDATA and RESULT
1953 has type Ity_I1. The store may fail or succeed depending
1954 on the state of a previously lodged reservation on this
1955 address. RESULT is written 1 if the store succeeds and 0
1956 if it fails. eg ppIRStmt output:
1957
1958 result = ( ST<end>-Cond(<addr>) = <storedata> )
1959 eg t3 = ( STbe-Cond(t1, t2) )
1960
1961 In all cases, the address must be naturally aligned for
1962 the transfer type -- any misaligned addresses should be
1963 caught by a dominating IR check and side exit. This
1964 alignment restriction exists because on at least some
1965 LL/SC platforms (ppc), stwcx. etc will trap w/ SIGBUS on
1966 misaligned addresses, and we have to actually generate
1967 stwcx. on the host, and we don't want it trapping on the
1968 host.
1969
1970 Summary of rules for transfer type:
1971 STOREDATA == NULL (LL):
1972 transfer type = type of RESULT
1973 STOREDATA != NULL (SC):
1974 transfer type = type of STOREDATA, and RESULT :: Ity_I1
1975 */
1976 struct {
1977 IREndness end;
1978 IRTemp result;
1979 IRExpr* addr;
1980 IRExpr* storedata; /* NULL => LL, non-NULL => SC */
1981 } LLSC;
1982
1983 /* Call (possibly conditionally) a C function that has side
1984 effects (ie. is "dirty"). See the comments above the
1985 IRDirty type declaration for more information.
1986
1987 ppIRStmt output:
1988 t<tmp> = DIRTY <guard> <effects>
1989 ::: <callee>(<args>)
1990 eg.
1991 t1 = DIRTY t27 RdFX-gst(16,4) RdFX-gst(60,4)
1992 ::: foo{0x380035f4}(t2)
1993 */
1994 struct {
1995 IRDirty* details;
1996 } Dirty;
1997
1998 /* A memory bus event - a fence, or acquisition/release of the
1999 hardware bus lock. IR optimisation treats all these as fences
2000 across which no memory references may be moved.
2001 ppIRStmt output: MBusEvent-Fence,
2002 MBusEvent-BusLock, MBusEvent-BusUnlock.
2003 */
2004 struct {
2005 IRMBusEvent event;
2006 } MBE;
2007
2008 /* Conditional exit from the middle of an IRSB.
2009 ppIRStmt output: if (<guard>) goto {<jk>} <dst>
2010 eg. if (t69) goto {Boring} 0x4000AAA:I32
2011 */
2012 struct {
2013 IRExpr* guard; /* Conditional expression */
2014 IRJumpKind jk; /* Jump kind */
2015 IRConst* dst; /* Jump target (constant only) */
2016 } Exit;
2017 } Ist;
2018 }
2019 IRStmt;
2020
2021 /* Statement constructors. */
2022 extern IRStmt* IRStmt_NoOp ( void );
2023 extern IRStmt* IRStmt_IMark ( Addr64 addr, Int len );
2024 extern IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len, IRExpr* nia );
2025 extern IRStmt* IRStmt_Put ( Int off, IRExpr* data );
2026 extern IRStmt* IRStmt_PutI ( IRRegArray* descr, IRExpr* ix, Int bias,
2027 IRExpr* data );
2028 extern IRStmt* IRStmt_WrTmp ( IRTemp tmp, IRExpr* data );
2029 extern IRStmt* IRStmt_Store ( IREndness end, IRExpr* addr, IRExpr* data );
2030 extern IRStmt* IRStmt_CAS ( IRCAS* details );
2031 extern IRStmt* IRStmt_LLSC ( IREndness end, IRTemp result,
2032 IRExpr* addr, IRExpr* storedata );
2033 extern IRStmt* IRStmt_Dirty ( IRDirty* details );
2034 extern IRStmt* IRStmt_MBE ( IRMBusEvent event );
2035 extern IRStmt* IRStmt_Exit ( IRExpr* guard, IRJumpKind jk, IRConst* dst );
2036
2037 /* Deep-copy an IRStmt. */
2038 extern IRStmt* deepCopyIRStmt ( IRStmt* );
2039
2040 /* Pretty-print an IRStmt. */
2041 extern void ppIRStmt ( IRStmt* );
2042
2043
2044 /* ------------------ Basic Blocks ------------------ */
2045
2046 /* Type environments: a bunch of statements, expressions, etc, are
2047 incomplete without an environment indicating the type of each
2048 IRTemp. So this provides one. IR temporaries are really just
2049 unsigned ints and so this provides an array, 0 .. n_types_used-1 of
2050 them.
2051 */
2052 typedef
2053 struct {
2054 IRType* types;
2055 Int types_size;
2056 Int types_used;
2057 }
2058 IRTypeEnv;
2059
2060 /* Obtain a new IRTemp */
2061 extern IRTemp newIRTemp ( IRTypeEnv*, IRType );
2062
2063 /* Deep-copy a type environment */
2064 extern IRTypeEnv* deepCopyIRTypeEnv ( IRTypeEnv* );
2065
2066 /* Pretty-print a type environment */
2067 extern void ppIRTypeEnv ( IRTypeEnv* );
2068
2069
2070 /* Code blocks, which in proper compiler terminology are superblocks
2071 (single entry, multiple exit code sequences) contain:
2072
2073 - A table giving a type for each temp (the "type environment")
2074 - An expandable array of statements
2075 - An expression of type 32 or 64 bits, depending on the
2076 guest's word size, indicating the next destination if the block
2077 executes all the way to the end, without a side exit
2078 - An indication of any special actions (JumpKind) needed
2079 for this final jump.
2080
2081 "IRSB" stands for "IR Super Block".
2082 */
2083 typedef
2084 struct {
2085 IRTypeEnv* tyenv;
2086 IRStmt** stmts;
2087 Int stmts_size;
2088 Int stmts_used;
2089 IRExpr* next;
2090 IRJumpKind jumpkind;
2091 }
2092 IRSB;
2093
2094 /* Allocate a new, uninitialised IRSB */
2095 extern IRSB* emptyIRSB ( void );
2096
2097 /* Deep-copy an IRSB */
2098 extern IRSB* deepCopyIRSB ( IRSB* );
2099
2100 /* Deep-copy an IRSB, except for the statements list, which set to be
2101 a new, empty, list of statements. */
2102 extern IRSB* deepCopyIRSBExceptStmts ( IRSB* );
2103
2104 /* Pretty-print an IRSB */
2105 extern void ppIRSB ( IRSB* );
2106
2107 /* Append an IRStmt to an IRSB */
2108 extern void addStmtToIRSB ( IRSB*, IRStmt* );
2109
2110
2111 /*---------------------------------------------------------------*/
2112 /*--- Helper functions for the IR ---*/
2113 /*---------------------------------------------------------------*/
2114
2115 /* For messing with IR type environments */
2116 extern IRTypeEnv* emptyIRTypeEnv ( void );
2117
2118 /* What is the type of this expression? */
2119 extern IRType typeOfIRConst ( IRConst* );
2120 extern IRType typeOfIRTemp ( IRTypeEnv*, IRTemp );
2121 extern IRType typeOfIRExpr ( IRTypeEnv*, IRExpr* );
2122
2123 /* Sanity check a BB of IR */
2124 extern void sanityCheckIRSB ( IRSB* bb,
2125 HChar* caller,
2126 Bool require_flatness,
2127 IRType guest_word_size );
2128 extern Bool isFlatIRStmt ( IRStmt* );
2129
2130 /* Is this any value actually in the enumeration 'IRType' ? */
2131 extern Bool isPlausibleIRType ( IRType ty );
2132
2133 #endif /* ndef __LIBVEX_IR_H */
2134
2135
2136 /*---------------------------------------------------------------*/
2137 /*--- libvex_ir.h ---*/
2138 /*---------------------------------------------------------------*/
2139