Add catch blocks to more Concat instructions, fix refcount opts bug
[hiphop-php.git] / hphp / runtime / vm / jit / ir.h
blob5d4977308148388e534e84b91146923cb2493528
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_VM_IR_H_
18 #define incl_HPHP_VM_IR_H_
20 #include <algorithm>
21 #include <cstdarg>
22 #include <iostream>
23 #include <vector>
24 #include <stack>
25 #include <list>
26 #include <forward_list>
27 #include <cassert>
28 #include <type_traits>
30 #include <boost/noncopyable.hpp>
31 #include <boost/checked_delete.hpp>
32 #include <boost/type_traits/has_trivial_destructor.hpp>
33 #include <boost/algorithm/string.hpp>
34 #include <boost/intrusive/list.hpp>
36 #include "folly/Conv.h"
37 #include "folly/Format.h"
38 #include "folly/Range.h"
40 #include "hphp/util/asm-x64.h"
41 #include "hphp/util/trace.h"
42 #include "hphp/runtime/base/smart-containers.h"
43 #include "hphp/runtime/ext/ext_continuation.h"
44 #include "hphp/runtime/vm/jit/phys-reg.h"
45 #include "hphp/runtime/vm/jit/abi-x64.h"
46 #include "hphp/runtime/vm/jit/types.h"
47 #include "hphp/runtime/vm/jit/runtime-type.h"
48 #include "hphp/runtime/vm/jit/translator-runtime.h"
49 #include "hphp/runtime/vm/jit/type.h"
50 #include "hphp/runtime/base/types.h"
51 #include "hphp/runtime/vm/func.h"
52 #include "hphp/runtime/vm/class.h"
54 namespace HPHP {
55 // forward declaration
56 class StringData;
57 namespace JIT {
59 using HPHP::JIT::TCA;
60 using HPHP::JIT::RegSet;
61 using HPHP::JIT::PhysReg;
62 using HPHP::JIT::ConditionCode;
64 class IRUnit;
65 struct IRInstruction;
66 class SSATmp;
67 struct LocalStateHook;
69 class FailedIRGen : public std::runtime_error {
70 public:
71 const char* const file;
72 const int line;
73 const char* const func;
75 FailedIRGen(const char* _file, int _line, const char* _func)
76 : std::runtime_error(folly::format("FailedIRGen @ {}:{} in {}",
77 _file, _line, _func).str())
78 , file(_file)
79 , line(_line)
80 , func(_func)
84 class FailedTraceGen : public std::runtime_error {
85 public:
86 FailedTraceGen(const char* file, int line, const char* why)
87 : std::runtime_error(folly::format("FailedTraceGen @ {}:{} - {}",
88 file, line, why).str())
92 class FailedCodeGen : public std::runtime_error {
93 public:
94 const char* file;
95 const int line;
96 const char* func;
97 const Offset bcOff;
98 const Func* vmFunc;
100 FailedCodeGen(const char* _file, int _line, const char* _func,
101 uint32_t _bcOff, const Func* _vmFunc)
102 : std::runtime_error(folly::format("FailedCodeGen @ {}:{} in {}. {}@{}",
103 _file, _line, _func,
104 _vmFunc->fullName()->data(), _bcOff)
105 .str())
106 , file(_file)
107 , line(_line)
108 , func(_func)
109 , bcOff(_bcOff)
110 , vmFunc(_vmFunc)
114 #define SPUNT(instr) do { \
115 throw FailedIRGen(__FILE__, __LINE__, instr); \
116 } while(0)
117 #define PUNT(instr) SPUNT(#instr)
118 #define TRACE_PUNT(why) do { \
119 throw FailedTraceGen(__FILE__, __LINE__, why); \
120 } while(0)
123 //////////////////////////////////////////////////////////////////////
126 * The instruction table below uses the following notation. To use
127 * it, you have to define these symbols to do what you want, and then
128 * instantiate IR_OPCODES.
130 * dstinfo:
132 * Contains a description of how to compute the type of the
133 * destination(s) of an instruction from its sources.
135 * ND instruction has no destination
136 * D(type) single dst has a specific type
137 * DofS(N) single dst has the type of src N
138 * DUnbox(N) single dst has unboxed type of src N
139 * DBox(N) single dst has boxed type of src N
140 * DParam single dst has type of the instruction's type parameter
141 * DLdRef single dst has type of the instruction's type parameter, with
142 * any specialization removed
143 * DAllocObj single dst has a type of a newly allocated object; may be a
144 * specialized object type if the class is known
145 * DThis single dst has type Obj<ctx>, where ctx is the
146 * current context class
147 * DMulti multiple dests. type and number depend on instruction
148 * DSetElem single dst is a subset of CountedStr|Nullptr depending on
149 * sources
150 * DStk(x) up to two dests. x should be another D* macro and indicates
151 * the type of the first dest, if any. the second (or first,
152 * depending on the presence of a primary destination), will be
153 * of type Type::StkPtr. implies ModifiesStack.
154 * DBuiltin single dst for CallBuiltin. This can return complex data
155 * types such as (Type::Str | Type::Null)
156 * DSubtract(N,t) single dest has type of src N with t removed
158 * srcinfo:
160 * Contains a series of tests on the source parameters in order.
162 * NA instruction takes no sources
163 * SUnk intructions sources are not yet documented/checked
164 * S(t1,...,tn) source must be a subtype of {t1|..|tn}
165 * C(type) source must be a constant, and subtype of type
166 * CStr same as C(StaticStr)
167 * SSpills SpillStack's variadic source list
169 * flags:
171 * See doc/ir.specification for the meaning of these flags.
173 * The flags in this opcode table supply default values for the
174 * querying functions in IRInstruction---those functions involve
175 * additional logic (based on operand types, etc) on a
176 * per-instruction basis.
178 * The following abbreviations are used in this table:
180 * NF no flags
181 * C canCSE
182 * E isEssential
183 * N callsNative
184 * PRc producesRC
185 * CRc consumesRC
186 * Er mayRaiseError
187 * T isTerminal
188 * B isBranch
189 * P passthrough
190 * K killsSource
191 * MProp MInstrProp
192 * MElem MInstrElem
195 #define O_STK(name, dst, src, flags) \
196 O(name, dst, src, StkFlags(flags)) \
197 O(name ## Stk, DStk(dst), src, flags)
199 #define IR_OPCODES \
200 /* name dstinfo srcinfo flags */ \
201 O(CheckType, DParam, S(Gen), B|E|P) \
202 O(AssertType, DParam, S(Gen,Cls), C|E|P) \
203 O(CheckTypeMem, ND, S(PtrToGen), B|E) \
204 O(GuardLoc, D(FramePtr), S(FramePtr), E) \
205 O(GuardStk, D(StkPtr), S(StkPtr), E) \
206 O(CheckLoc, D(FramePtr), S(FramePtr), B|E) \
207 O(CheckStk, D(StkPtr), S(StkPtr), B|E) \
208 O(CastStk, D(StkPtr), S(StkPtr), N|Er) \
209 O(CoerceStk, D(StkPtr), S(StkPtr), B|N|Er) \
210 O(AssertStk, D(StkPtr), S(StkPtr), E) \
211 O(CheckDefinedClsEq, ND, NA, B|E) \
212 O(GuardRefs, ND, S(Func) \
213 S(Int) \
214 S(Int) \
215 S(Int) \
216 S(Int), E) \
217 O(AssertLoc, D(FramePtr), S(FramePtr), E) \
218 O(BeginCatch, ND, NA, E) \
219 O(EndCatch, ND, S(FramePtr) S(StkPtr), E|T) \
220 O(TryEndCatch, ND, S(FramePtr) S(StkPtr), E) \
221 O(LdUnwinderValue, DParam, NA, PRc) \
222 O(DeleteUnwinderException, ND, NA, N|E) \
223 O(AddInt, D(Int), S(Int) S(Int), C) \
224 O(SubInt, D(Int), S(Int) S(Int), C) \
225 O(MulInt, D(Int), S(Int) S(Int), C) \
226 O(AddDbl, D(Dbl), S(Dbl) S(Dbl), C) \
227 O(SubDbl, D(Dbl), S(Dbl) S(Dbl), C) \
228 O(MulDbl, D(Dbl), S(Dbl) S(Dbl), C) \
229 O(DivDbl, D(Dbl), S(Dbl) S(Dbl), B|C) \
230 O(Mod, D(Int), S(Int) S(Int), C) \
231 O(Sqrt, D(Dbl), S(Dbl), C) \
232 O(AbsDbl, D(Dbl), S(Dbl), C) \
233 O(BitAnd, D(Int), S(Int) S(Int), C) \
234 O(BitOr, D(Int), S(Int) S(Int), C) \
235 O(BitXor, D(Int), S(Int) S(Int), C) \
236 O(BitNot, D(Int), S(Int), C) \
237 O(LogicXor, D(Bool), S(Bool) S(Bool), C) \
238 O(Not, D(Bool), S(Bool), C) \
239 O(Shl, D(Int), S(Int) S(Int), C) \
240 O(Shr, D(Int), S(Int) S(Int), C) \
242 O(ConvBoolToArr, D(Arr), S(Bool), C|N|PRc) \
243 O(ConvDblToArr, D(Arr), S(Dbl), C|N|PRc) \
244 O(ConvIntToArr, D(Arr), S(Int), C|N|PRc) \
245 O(ConvObjToArr, D(Arr), S(Obj), Er|N|PRc|CRc|K) \
246 O(ConvStrToArr, D(Arr), S(Str), N|PRc|CRc) \
247 O(ConvCellToArr, D(Arr), S(Cell), Er|N|PRc|CRc|K) \
249 O(ConvArrToBool, D(Bool), S(Arr), N) \
250 O(ConvDblToBool, D(Bool), S(Dbl), C) \
251 O(ConvIntToBool, D(Bool), S(Int), C) \
252 O(ConvStrToBool, D(Bool), S(Str), N) \
253 O(ConvObjToBool, D(Bool), S(Obj), N) \
254 O(ConvCellToBool, D(Bool), S(Cell), N) \
256 O(ConvArrToDbl, D(Dbl), S(Arr), N) \
257 O(ConvBoolToDbl, D(Dbl), S(Bool), C) \
258 O(ConvIntToDbl, D(Dbl), S(Int), C) \
259 O(ConvObjToDbl, D(Dbl), S(Obj), N|Er) \
260 O(ConvStrToDbl, D(Dbl), S(Str), N) \
261 O(ConvCellToDbl, D(Dbl), S(Cell), N|Er) \
263 O(ConvArrToInt, D(Int), S(Arr), N) \
264 O(ConvBoolToInt, D(Int), S(Bool), C) \
265 O(ConvDblToInt, D(Int), S(Dbl), C) \
266 O(ConvObjToInt, D(Int), S(Obj), N|Er|K) \
267 O(ConvStrToInt, D(Int), S(Str), N) \
268 O(ConvCellToInt, D(Int), S(Cell), N|Er|K) \
270 O(ConvCellToObj, D(Obj), S(Cell), N|CRc|PRc|K) \
272 O(ConvBoolToStr, D(StaticStr), S(Bool), C) \
273 O(ConvDblToStr, D(Str), S(Dbl), N|PRc) \
274 O(ConvIntToStr, D(Str), S(Int), N|PRc) \
275 O(ConvObjToStr, D(Str), S(Obj), N|PRc|Er) \
276 O(ConvResToStr, D(Str), S(Res), N|PRc|Er) \
277 O(ConvCellToStr, D(Str), S(Cell), N|PRc|Er) \
279 O(ExtendsClass, D(Bool), S(Cls) C(Cls), C) \
280 O(IsWaitHandle, D(Bool), S(Obj), C) \
281 O(ThingExists, D(Bool), S(Str), N|E|Er) \
282 O(InstanceOf, D(Bool), S(Cls) S(Cls), C|N) \
283 O(InstanceOfIface, D(Bool), S(Cls) CStr, C|N) \
284 O(InterfaceSupportsArr, D(Bool), S(Str), C|N) \
285 O(InterfaceSupportsStr, D(Bool), S(Str), C|N) \
286 O(InterfaceSupportsInt, D(Bool), S(Str), C|N) \
287 O(InterfaceSupportsDbl, D(Bool), S(Str), C|N) \
288 O(IsTypeMem, D(Bool), S(PtrToGen), NA) \
289 O(IsNTypeMem, D(Bool), S(PtrToGen), NA) \
290 /* name dstinfo srcinfo flags */ \
291 O(Gt, D(Bool), S(Gen) S(Gen), C|N) \
292 O(GtX, D(Bool), S(Gen) S(Gen), Er|C|N) \
293 O(Gte, D(Bool), S(Gen) S(Gen), C|N) \
294 O(GteX, D(Bool), S(Gen) S(Gen), Er|C|N) \
295 O(Lt, D(Bool), S(Gen) S(Gen), C|N) \
296 O(LtX, D(Bool), S(Gen) S(Gen), Er|C|N) \
297 O(Lte, D(Bool), S(Gen) S(Gen), C|N) \
298 O(LteX, D(Bool), S(Gen) S(Gen), Er|C|N) \
299 O(Eq, D(Bool), S(Gen) S(Gen), C|N) \
300 O(EqX, D(Bool), S(Gen) S(Gen), Er|C|N) \
301 O(Neq, D(Bool), S(Gen) S(Gen), C|N) \
302 O(NeqX, D(Bool), S(Gen) S(Gen), Er|C|N) \
303 O(Same, D(Bool), S(Gen) S(Gen), C|N) \
304 O(NSame, D(Bool), S(Gen) S(Gen), C|N) \
305 O(GtInt, D(Bool), S(Int) S(Int), C) \
306 O(GteInt, D(Bool), S(Int) S(Int), C) \
307 O(LtInt, D(Bool), S(Int) S(Int), C) \
308 O(LteInt, D(Bool), S(Int) S(Int), C) \
309 O(EqInt, D(Bool), S(Int) S(Int), C) \
310 O(NeqInt, D(Bool), S(Int) S(Int), C) \
311 O(Floor, D(Dbl), S(Dbl), C) \
312 O(Ceil, D(Dbl), S(Dbl), C) \
313 O(InstanceOfBitmask, D(Bool), S(Cls) CStr, C) \
314 O(NInstanceOfBitmask, D(Bool), S(Cls) CStr, C) \
315 /* there is a conditional branch for each of the above fusable query ops */ \
316 O(IsType, D(Bool), S(Cell), C) \
317 O(IsNType, D(Bool), S(Cell), C) \
318 O(IsScalarType, D(Bool), S(Cell), C) \
319 O(JmpGt, D(None), S(Gen) S(Gen), B|E) \
320 O(JmpGte, D(None), S(Gen) S(Gen), B|E) \
321 O(JmpLt, D(None), S(Gen) S(Gen), B|E) \
322 O(JmpLte, D(None), S(Gen) S(Gen), B|E) \
323 O(JmpEq, D(None), S(Gen) S(Gen), B|E) \
324 O(JmpNeq, D(None), S(Gen) S(Gen), B|E) \
325 O(JmpSame, D(None), S(Gen) S(Gen), B|E) \
326 O(JmpNSame, D(None), S(Gen) S(Gen), B|E) \
327 O(JmpGtInt, D(None), S(Int) S(Int), B|E) \
328 O(JmpGteInt, D(None), S(Int) S(Int), B|E) \
329 O(JmpLtInt, D(None), S(Int) S(Int), B|E) \
330 O(JmpLteInt, D(None), S(Int) S(Int), B|E) \
331 O(JmpEqInt, D(None), S(Int) S(Int), B|E) \
332 O(JmpNeqInt, D(None), S(Int) S(Int), B|E) \
333 O(JmpInstanceOfBitmask, D(None), S(Cls) CStr, B|E) \
334 O(JmpNInstanceOfBitmask, D(None), S(Cls) CStr, B|E) \
335 /* name dstinfo srcinfo flags */ \
336 O(JmpZero, D(None), S(Int,Bool), B|E) \
337 O(JmpNZero, D(None), S(Int,Bool), B|E) \
338 O(Jmp, D(None), SUnk, B|T|E) \
339 O(ReqBindJmpGt, ND, S(Gen) S(Gen), T|E) \
340 O(ReqBindJmpGte, ND, S(Gen) S(Gen), T|E) \
341 O(ReqBindJmpLt, ND, S(Gen) S(Gen), T|E) \
342 O(ReqBindJmpLte, ND, S(Gen) S(Gen), T|E) \
343 O(ReqBindJmpEq, ND, S(Gen) S(Gen), T|E) \
344 O(ReqBindJmpNeq, ND, S(Gen) S(Gen), T|E) \
345 O(ReqBindJmpGtInt, ND, S(Int) S(Int), T|E) \
346 O(ReqBindJmpGteInt, ND, S(Int) S(Int), T|E) \
347 O(ReqBindJmpLtInt, ND, S(Int) S(Int), T|E) \
348 O(ReqBindJmpLteInt, ND, S(Int) S(Int), T|E) \
349 O(ReqBindJmpEqInt, ND, S(Int) S(Int), T|E) \
350 O(ReqBindJmpNeqInt, ND, S(Int) S(Int), T|E) \
351 O(ReqBindJmpSame, ND, S(Gen) S(Gen), T|E) \
352 O(ReqBindJmpNSame, ND, S(Gen) S(Gen), T|E) \
353 O(ReqBindJmpInstanceOfBitmask, ND, S(Cls) CStr, T|E) \
354 O(ReqBindJmpNInstanceOfBitmask, ND, S(Cls) CStr, T|E) \
355 O(ReqBindJmpZero, ND, S(Int,Bool), T|E) \
356 O(ReqBindJmpNZero, ND, S(Int,Bool), T|E) \
357 O(SideExitJmpGt, D(None), S(Gen) S(Gen), E) \
358 O(SideExitJmpGte, D(None), S(Gen) S(Gen), E) \
359 O(SideExitJmpLt, D(None), S(Gen) S(Gen), E) \
360 O(SideExitJmpLte, D(None), S(Gen) S(Gen), E) \
361 O(SideExitJmpEq, D(None), S(Gen) S(Gen), E) \
362 O(SideExitJmpNeq, D(None), S(Gen) S(Gen), E) \
363 O(SideExitJmpGtInt, D(None), S(Int) S(Int), E) \
364 O(SideExitJmpGteInt, D(None), S(Int) S(Int), E) \
365 O(SideExitJmpLtInt, D(None), S(Int) S(Int), E) \
366 O(SideExitJmpLteInt, D(None), S(Int) S(Int), E) \
367 O(SideExitJmpEqInt, D(None), S(Int) S(Int), E) \
368 O(SideExitJmpNeqInt, D(None), S(Int) S(Int), E) \
369 O(SideExitJmpSame, D(None), S(Int) S(Int), E) \
370 O(SideExitJmpNSame, D(None), S(Int) S(Int), E) \
371 O(SideExitJmpInstanceOfBitmask, \
372 D(None), S(Cls) CStr, E) \
373 O(SideExitJmpNInstanceOfBitmask, \
374 D(None), S(Cls) CStr, E) \
375 O(SideExitJmpZero, D(None), S(Int,Bool), E) \
376 O(SideExitJmpNZero, D(None), S(Int,Bool), E) \
377 O(SideExitGuardLoc, D(FramePtr), S(FramePtr), E) \
378 O(SideExitGuardStk, D(StkPtr), S(StkPtr), E) \
379 /* name dstinfo srcinfo flags */ \
380 O(JmpIndirect, ND, S(TCA), T|E) \
381 O(CheckSurpriseFlags, ND, NA, B|E) \
382 O(SurpriseHook, ND, NA, Er|N|E) \
383 O(FunctionExitSurpriseHook, ND, S(FramePtr) S(StkPtr) S(Gen), Er|N|E) \
384 O(ExitOnVarEnv, ND, S(FramePtr), B|E) \
385 O(ReleaseVVOrExit, ND, S(FramePtr), B|N|E) \
386 O(RaiseError, ND, S(Str), E|N|T|Er) \
387 O(RaiseWarning, ND, S(Str), E|N|Er) \
388 O(RaiseNotice, ND, S(Str), E|N|Er) \
389 O(RaiseArrayIndexNotice, ND, S(Int), E|N|Er) \
390 O(CheckInit, ND, S(Gen), B) \
391 O(CheckInitMem, ND, S(PtrToGen) C(Int), B) \
392 O(CheckCold, ND, NA, B|E) \
393 O(CheckNullptr, ND, S(CountedStr,Nullptr), B|E|CRc) \
394 O(CheckNonNull, DSubtract(0, Nullptr), S(Nullptr,Func), B) \
395 O(CheckBounds, ND, S(Int) S(Int), E|N|Er) \
396 O(LdVectorSize, D(Int), S(Obj), E) \
397 O(CheckPackedArrayBounds, ND, S(Arr) S(Int), B|E) \
398 O(CheckPackedArrayElemNull, D(Bool), S(Arr) S(Int), E) \
399 O(VectorHasFrozenCopy, ND, S(Obj), B) \
400 O(VectorDoCow, ND, S(Obj), N|E) \
401 O(AssertNonNull, DSubtract(0, Nullptr), S(Nullptr,CountedStr,Func), P) \
402 O(Unbox, DUnbox(0), S(Gen), B) \
403 O(Box, DBox(0), S(Init), E|N|CRc|PRc) \
404 O(UnboxPtr, D(PtrToCell), S(PtrToGen), NF) \
405 O(BoxPtr, D(PtrToBoxedCell), S(PtrToGen), N) \
406 O(LdVectorBase, D(PtrToCell), S(Obj), E) \
407 O(LdPairBase, D(PtrToCell), S(Obj), E) \
408 O(LdStack, DParam, S(StkPtr), NF) \
409 O(LdLoc, DParam, S(FramePtr), NF) \
410 O(LdStackAddr, DParam, S(StkPtr), C) \
411 O(LdLocAddr, DParam, S(FramePtr), C) \
412 O(LdMem, DParam, S(PtrToGen) C(Int), B) \
413 O(LdProp, DParam, S(Obj) C(Int), B) \
414 O(LdElem, D(Cell), S(PtrToCell) S(Int), E) \
415 O(LdPackedArrayElem, D(Gen), S(Arr) S(Int), E) \
416 O(LdRef, DLdRef, S(BoxedCell), B) \
417 O(LdThis, DThis, S(FramePtr), B|C) \
418 O(LdRetAddr, D(RetAddr), S(FramePtr), NF) \
419 O(LdConst, DParam, NA, C) \
420 O(DefConst, DParam, NA, C) \
421 O(ConvClsToCctx, D(Cctx), S(Cls), C) \
422 O(LdCtx, D(Ctx), S(FramePtr), C) \
423 O(LdCctx, D(Cctx), S(FramePtr), C) \
424 O(LdCls, D(Cls), S(Str) C(Cls), C|E|N|Er) \
425 O(LdClsCached, D(Cls), CStr, C|E|N|Er) \
426 O(LdClsCachedSafe, D(Cls), CStr, B) \
427 O(LdClsCtx, D(Cls), S(Ctx), C) \
428 O(LdClsCctx, D(Cls), S(Cctx), C) \
429 O(LdClsCns, DParam, NA, B) \
430 O(LookupClsRDSHandle, D(RDSHandle), S(Str), C|N) \
431 O(DerefClsRDSHandle, D(Cls), S(RDSHandle), NF) \
432 O(LookupClsCns, D(Uncounted), NA, E|Er|N) \
433 O(LdCns, D(Uncounted), CStr, NF) \
434 O(LookupCns, D(Uncounted), CStr, E|Er|N) \
435 O(LookupCnsE, D(Uncounted), CStr, E|Er|N) \
436 O(LookupCnsU, D(Uncounted), CStr CStr, E|Er|N) \
437 O(LookupClsMethod, ND, S(Cls) \
438 S(Str) \
439 S(StkPtr) \
440 S(FramePtr), N|E|Er) \
441 O(LdClsMethodCacheFunc,D(Func|Nullptr), NA, NF) \
442 O(LdClsMethodCacheCls, D(Cctx), NA, NF) \
443 O(LookupClsMethodCache,D(Func|Nullptr), C(NamedEntity) \
444 S(FramePtr), N|E|Er) \
445 O(LdClsMethodFCacheFunc, \
446 D(Func|Nullptr), NA, NF) \
447 O(LookupClsMethodFCache, \
448 D(Func|Nullptr), C(Cls) \
449 S(FramePtr), N|E|Er) \
450 O(GetCtxFwdCallDyn, D(Ctx), S(Ctx), PRc) \
451 O(GetCtxFwdCall, D(Ctx), S(Ctx) C(Func), C|PRc) \
452 O(LdClsMethod, D(Func), S(Cls) C(Int), C) \
453 O(LdPropAddr, D(PtrToGen), S(Obj) C(Int), C) \
454 O(LdClsPropAddr, D(PtrToGen), S(Cls) S(Str) C(Cls), B|C|E|N|Er) \
455 O(LdClsPropAddrCached, DParam, S(Cls) CStr CStr C(Cls), B|C|E|N|Er) \
456 O(LdClsInitData, D(PtrToCell), S(Cls), N|C) \
457 O(LdClsStaticInitData, D(PtrToCell), S(Cls), N|C) \
458 O(LdObjMethod, ND, S(Cls) CStr S(StkPtr), E|N|Er) \
459 O(LdObjInvoke, D(Func), S(Cls), B) \
460 O(LdGblAddrDef, D(PtrToGen), S(Str), E|N) \
461 O(LdGblAddr, D(PtrToGen), S(Str), B|N) \
462 O(LdObjClass, D(Cls), S(Obj), C) \
463 O(LdArrFuncCtx, ND, S(Arr) \
464 S(StkPtr) \
465 S(FramePtr), E|N|Er) \
466 O(LdArrFPushCuf, ND, S(Arr) \
467 S(StkPtr) \
468 S(FramePtr), E|N|Er) \
469 O(LdStrFPushCuf, ND, S(Str) \
470 S(StkPtr) \
471 S(FramePtr), E|N|Er) \
472 O(LdFunc, D(Func), S(Str), E|N|CRc|Er) \
473 O(LdFuncCached, D(Func), NA, N|E|Er) \
474 O(LdFuncCachedU, D(Func), NA, N|E|Er) \
475 O(LdFuncCachedSafe, D(Func), NA, B) \
476 O(LdARFuncPtr, D(Func), S(StkPtr,FramePtr) C(Int), C) \
477 O(LdSSwitchDestFast, D(TCA), S(Gen), N) \
478 O(LdSSwitchDestSlow, D(TCA), S(Gen), E|N|Er) \
479 O(LdSwitchDblIndex, D(Int), S(Dbl) S(Int) S(Int), N) \
480 O(LdSwitchStrIndex, D(Int), S(Str) S(Int) S(Int), CRc|N) \
481 O(LdSwitchObjIndex, D(Int), S(Obj) S(Int) S(Int), CRc|N|Er) \
482 O(JmpSwitchDest, ND, S(Int), T|E) \
483 O(AllocObj, DAllocObj, S(Cls), Er|N) \
484 O(AllocObjFast, DAllocObj, NA, N) \
485 O(LdClsCtor, D(Func), S(Cls), C|Er|N) \
486 O(StClosureFunc, ND, S(Obj), E) \
487 O(StClosureArg, ND, S(Obj) S(Gen), CRc|E) \
488 O(StClosureCtx, ND, S(Obj) S(Ctx,Nullptr), CRc|E) \
489 O(NewArray, D(Arr), C(Int), N|PRc) \
490 O(NewPackedArray, D(Arr), C(Int) S(StkPtr), E|N|PRc|CRc) \
491 O(NewStructArray, D(Arr), S(StkPtr), E|N|PRc|CRc) \
492 O(NewCol, D(Obj), C(Int) C(Int), N|PRc) \
493 O(Clone, D(Obj), S(Obj), N|E|PRc|Er) \
494 O(LdRaw, DParam, SUnk, NF) \
495 O(FreeActRec, D(FramePtr), S(FramePtr), NF) \
496 /* name dstinfo srcinfo flags */ \
497 O(Call, D(StkPtr), SUnk, E|CRc) \
498 O(CallArray, D(StkPtr), S(StkPtr), E|N|CRc) \
499 O(CallBuiltin, DBuiltin, SUnk, E|Er|N|PRc) \
500 O(NativeImpl, ND, C(Func) S(FramePtr), E|N) \
501 O(RetCtrl, ND, S(StkPtr) \
502 S(FramePtr) \
503 S(RetAddr), T|E) \
504 O(StRetVal, ND, S(FramePtr) S(Gen), E|CRc) \
505 O(RetAdjustStack, D(StkPtr), S(FramePtr), E) \
506 O(StMem, ND, S(PtrToGen) \
507 C(Int) S(Gen), E|CRc) \
508 O(StProp, ND, S(Obj) S(Int) S(Gen), E|CRc) \
509 O(StLoc, ND, S(FramePtr) S(Gen), E|CRc) \
510 O(StLocNT, ND, S(FramePtr) S(Gen), E|CRc) \
511 O(StRef, DBox(1), S(BoxedCell) S(Cell), E|CRc|P) \
512 O(StRaw, ND, SUnk, E) \
513 O(StElem, ND, S(PtrToCell) \
514 S(Int) \
515 S(Cell), E|CRc) \
516 O(IterCopy, ND, S(FramePtr) S(Int) \
517 S(PtrToGen) S(Int), E) \
518 O(LdStaticLocCached, D(BoxedCell), NA, NF) \
519 O(CheckStaticLocInit, ND, S(BoxedCell), B) \
520 O(ClosureStaticLocInit, D(BoxedCell), CStr \
521 S(FramePtr) \
522 S(Cell), E|N) \
523 O(StaticLocInitCached, ND, S(BoxedCell) S(Cell), E) \
524 O(SpillStack, D(StkPtr), S(StkPtr) C(Int) SSpills, CRc) \
525 O(SpillFrame, D(StkPtr), S(StkPtr) \
526 S(FramePtr) \
527 S(Func,Null) \
528 S(Ctx,Cls,InitNull), CRc) \
529 O(CufIterSpillFrame, D(StkPtr), S(StkPtr) \
530 S(FramePtr), NF) \
531 O(ExceptionBarrier, D(StkPtr), S(StkPtr), E) \
532 O(ReqBindJmp, ND, NA, T|E) \
533 O(ReqRetranslateOpt, ND, NA, T|E) \
534 O(ReqRetranslate, ND, NA, T|E) \
535 O(SyncABIRegs, ND, S(FramePtr) S(StkPtr), E) \
536 O(Mov, DofS(0), SUnk, C|P) \
537 O(LdAddr, DofS(0), SUnk, C) \
538 O(IncRef, ND, S(Gen), E) \
539 O(TakeStack, ND, S(StackElem), E) \
540 O(IncRefCtx, ND, S(Ctx), E) \
541 O(DecRefLoc, ND, S(FramePtr), N|E) \
542 O(DecRefStack, ND, S(StkPtr), N|E) \
543 O(DecRefThis, ND, S(FramePtr), N|E) \
544 O(GenericRetDecRefs, D(StkPtr), S(FramePtr), E|N) \
545 O(DecRef, ND, S(Gen), N|E|K|CRc) \
546 O(DecRefNZ, ND, S(Gen), N|E|CRc) \
547 O(DecRefMem, ND, S(PtrToGen) \
548 C(Int), N|E|CRc) \
549 O(DefLabel, DMulti, NA, E) \
550 O(DefInlineFP, D(FramePtr), S(StkPtr) S(StkPtr) S(FramePtr), NF) \
551 O(InlineReturn, ND, S(FramePtr), E) \
552 O(DefFP, D(FramePtr), NA, E) \
553 O(DefSP, D(StkPtr), S(FramePtr), E) \
554 O(DefInlineSP, D(StkPtr), S(StkPtr) S(FramePtr), E) \
555 O(ReDefSP, D(StkPtr), S(StkPtr) S(FramePtr), NF) \
556 O(PassSP, D(StkPtr), S(StkPtr), P) \
557 O(PassFP, D(FramePtr), S(FramePtr), P) \
558 O(StashGeneratorSP, ND, S(FramePtr) S(StkPtr), E) \
559 O(ReDefGeneratorSP, D(StkPtr), S(StkPtr) S(FramePtr), E) \
560 O(VerifyParamCls, ND, S(Cls) \
561 S(Cls) \
562 C(Int) \
563 C(Int), E|N|Er) \
564 O(VerifyParamCallable, ND, S(Cell) C(Int), E|N|Er) \
565 O(VerifyParamFail, ND, C(Int), E|N|Er) \
566 O(RaiseUninitLoc, ND, S(Str), E|N|Er) \
567 O(WarnNonObjProp, ND, NA, E|N|Er) \
568 O(ThrowNonObjProp, ND, NA, T|E|N|Er) \
569 O(RaiseUndefProp, ND, S(Obj) CStr, E|N|Er) \
570 O(PrintStr, ND, S(Str), E|N|CRc) \
571 O(PrintInt, ND, S(Int), E|N|CRc) \
572 O(PrintBool, ND, S(Bool), E|N|CRc) \
573 O(AddElemStrKey, D(Arr), S(Arr) \
574 S(Str) \
575 S(Cell), N|CRc|PRc) \
576 O(AddElemIntKey, D(Arr), S(Arr) \
577 S(Int) \
578 S(Cell), N|CRc|PRc) \
579 O(AddNewElem, D(Arr), SUnk, N|CRc|PRc) \
580 O(ColAddElemC, D(Obj), S(Obj) \
581 S(Cell) \
582 S(Cell), N|Er|CRc|P) \
583 O(ColAddNewElemC, D(Obj), S(Obj) S(Cell), N|Er|CRc|P) \
584 /* name dstinfo srcinfo flags */ \
585 O(ConcatStrStr, D(Str), S(Str) S(Str), Er|N|CRc|PRc) \
586 O(ConcatIntStr, D(Str), S(Int) S(Str), Er|N|PRc) \
587 O(ConcatStrInt, D(Str), S(Str) S(Int), Er|N|CRc|PRc) \
588 O(ConcatCellCell, D(Str), S(Cell) S(Cell), Er|N|CRc|PRc) \
589 O(ArrayAdd, D(Arr), S(Arr) S(Arr), Er|N|CRc|PRc) \
590 O(AKExists, D(Bool), S(Cell) S(Cell), N) \
591 O(InterpOne, D(StkPtr), S(StkPtr) S(FramePtr), \
592 E|N|Er) \
593 O(InterpOneCF, D(StkPtr), S(StkPtr) S(FramePtr), \
594 T|E|N|Er) \
595 O(Spill, DofS(0), SUnk, NF) \
596 O(Reload, DofS(0), SUnk, NF) \
597 O(Shuffle, ND, SUnk, NF) \
598 O(CreateContFunc, D(Obj), NA, E|N|PRc) \
599 O(CreateContMeth, D(Obj), S(Ctx), E|N|PRc) \
600 O(ContEnter, ND, S(FramePtr) \
601 S(TCA) C(Int) S(FramePtr), E) \
602 O(ContPreNext, ND, S(Obj), B|E) \
603 O(ContStartedCheck, ND, S(Obj), B|E) \
604 O(ContSetRunning, ND, S(Obj) C(Bool), E) \
605 O(ContValid, D(Bool), S(Obj), E) \
606 O(ContArIncKey, ND, S(FramePtr), E) \
607 O(ContArUpdateIdx, ND, S(FramePtr) S(Int), E) \
608 O(LdContActRec, DParam, S(Obj), C) \
609 O(LdContArRaw, DParam, S(FramePtr) C(Int), NF) \
610 O(StContArRaw, ND, S(FramePtr) C(Int) S(Gen), E) \
611 O(LdContArValue, DParam, S(FramePtr), PRc) \
612 O(StContArValue, ND, S(FramePtr) S(Cell), E|CRc) \
613 O(LdContArKey, DParam, S(FramePtr), PRc) \
614 O(StContArKey, ND, S(FramePtr) S(Gen), E|CRc) \
615 O(LdWHState, D(Int), S(Obj), NF) \
616 O(LdWHResult, D(Cell), S(Obj), NF) \
617 O(LdAFWHActRec, DParam, S(Obj), C) \
618 O(CreateAFWHFunc, D(Obj), C(Int) S(Obj), E|Er|N|CRc|PRc) \
619 O(CreateAFWHMeth, D(Obj), S(Ctx) C(Int) S(Obj), E|Er|N|CRc|PRc) \
620 O(CreateSRWH, D(Obj), S(Cell), N|CRc|PRc) \
621 O(CreateSEWH, D(Obj), S(Obj), N|CRc|PRc) \
622 O(IterInit, D(Bool), S(Arr,Obj) \
623 S(FramePtr) \
624 C(Int) \
625 C(Int), Er|E|N|CRc) \
626 O(IterInitK, D(Bool), S(Arr,Obj) \
627 S(FramePtr) \
628 C(Int) \
629 C(Int) \
630 C(Int), Er|E|N|CRc) \
631 O(IterNext, D(Bool), S(FramePtr) \
632 C(Int) C(Int), Er|E|N) \
633 O(IterNextK, D(Bool), S(FramePtr) \
634 C(Int) C(Int) C(Int), Er|E|N) \
635 O(WIterInit, D(Bool), S(Arr,Obj) \
636 S(FramePtr) \
637 C(Int) \
638 C(Int), Er|E|N|CRc) \
639 O(WIterInitK, D(Bool), S(Arr,Obj) \
640 S(FramePtr) \
641 C(Int) \
642 C(Int) \
643 C(Int), Er|E|N|CRc) \
644 O(WIterNext, D(Bool), S(FramePtr) \
645 C(Int) C(Int), Er|E|N) \
646 O(WIterNextK, D(Bool), S(FramePtr) \
647 C(Int) C(Int) C(Int), Er|E|N) \
648 O(MIterInit, D(Bool), S(BoxedCell) \
649 S(FramePtr) \
650 C(Int) \
651 C(Int), Er|E|N) \
652 O(MIterInitK, D(Bool), S(BoxedCell) \
653 S(FramePtr) \
654 C(Int) \
655 C(Int) \
656 C(Int), Er|E|N) \
657 O(MIterNext, D(Bool), S(FramePtr) \
658 C(Int) C(Int), E|N) \
659 O(MIterNextK, D(Bool), S(FramePtr) \
660 C(Int) C(Int) C(Int), E|N) \
661 O(IterFree, ND, S(FramePtr), E|N) \
662 O(MIterFree, ND, S(FramePtr), E|N) \
663 O(DecodeCufIter, D(Bool), S(Arr,Obj,Str) \
664 S(FramePtr), E|N) \
665 O(CIterFree, ND, S(FramePtr), E|N) \
666 O(DefMIStateBase, D(PtrToCell), NA, NF) \
667 O(BaseG, D(PtrToGen), C(TCA) \
668 S(Str) \
669 S(PtrToCell), E|N|Er) \
670 O(PropX, D(PtrToGen), C(TCA) \
671 C(Cls) \
672 S(Obj,PtrToGen) \
673 S(Cell) \
674 S(PtrToCell), E|N|Er) \
675 O_STK(PropDX, D(PtrToGen), C(TCA) \
676 C(Cls) \
677 S(Obj,PtrToGen) \
678 S(Cell) \
679 S(PtrToCell), MProp|E|N|Er) \
680 O(CGetProp, D(Cell), C(TCA) \
681 C(Cls) \
682 S(Obj,PtrToGen) \
683 S(Cell) \
684 S(PtrToCell), E|N|PRc|Er) \
685 O_STK(VGetProp, D(BoxedCell), C(TCA) \
686 C(Cls) \
687 S(Obj,PtrToGen) \
688 S(Cell) \
689 S(PtrToCell), \
690 MProp|E|N|PRc|Er) \
691 O_STK(BindProp, ND, C(TCA) \
692 C(Cls) \
693 S(Obj,PtrToGen) \
694 S(Cell) \
695 S(BoxedCell) \
696 S(PtrToCell), MProp|E|N|Er) \
697 O_STK(SetProp, ND, C(TCA) \
698 C(Cls) \
699 S(Obj,PtrToGen) \
700 S(Cell) \
701 S(Cell), MProp|E|N|Er) \
702 O(UnsetProp, ND, C(TCA) \
703 C(Cls) \
704 S(Obj,PtrToGen) \
705 S(Cell), E|N|Er) \
706 O_STK(SetOpProp, D(Cell), C(TCA) \
707 S(Obj,PtrToGen) \
708 S(Cell) \
709 S(Cell) \
710 S(PtrToCell) \
711 C(Int), MProp|E|N|PRc|Er) \
712 O_STK(IncDecProp, D(Cell), C(TCA) \
713 S(Obj,PtrToGen) \
714 S(Cell) \
715 S(PtrToCell) \
716 C(Int), MProp|E|N|PRc|Er) \
717 O(EmptyProp, D(Bool), C(TCA) \
718 C(Cls) \
719 S(Obj,PtrToGen) \
720 S(Cell), E|N|Er) \
721 O(IssetProp, D(Bool), C(TCA) \
722 C(Cls) \
723 S(Obj,PtrToGen) \
724 S(Cell), E|N|Er) \
725 O(ElemX, D(PtrToGen), C(TCA) \
726 S(PtrToGen) \
727 S(Cell) \
728 S(PtrToCell), E|N|Er) \
729 O(ElemArray, D(PtrToGen), C(TCA) \
730 S(PtrToArr) \
731 S(Int,Str), E|N|Er) \
732 O_STK(ElemDX, D(PtrToGen), C(TCA) \
733 S(PtrToGen) \
734 S(Cell) \
735 S(PtrToCell), MElem|E|N|Er) \
736 O_STK(ElemUX, D(PtrToGen), C(TCA) \
737 S(PtrToGen) \
738 S(Cell) \
739 S(PtrToCell), MElem|E|N|Er) \
740 O(ArrayGet, D(Cell), C(TCA) \
741 S(Arr) \
742 S(Int,Str), N|PRc|Er) \
743 O(StringGet, D(StaticStr), C(TCA) \
744 S(Str) \
745 S(Int), N|PRc|Er) \
746 O(MapGet, D(Cell), C(TCA) \
747 S(Obj) \
748 S(Int,Str), E|N|PRc|Er) \
749 O(CGetElem, D(Cell), C(TCA) \
750 S(PtrToGen) \
751 S(Cell) \
752 S(PtrToCell), E|N|PRc|Er) \
753 O_STK(VGetElem, D(BoxedCell), C(TCA) \
754 S(PtrToGen) \
755 S(Cell) \
756 S(PtrToCell), \
757 MElem|E|N|PRc|Er) \
758 O_STK(BindElem, ND, C(TCA) \
759 S(PtrToGen) \
760 S(Cell) \
761 S(BoxedCell) \
762 S(PtrToCell), MElem|E|N|Er) \
763 O(ArraySet, D(Arr), C(TCA) \
764 S(Arr) \
765 S(Int,Str) \
766 S(Cell), E|N|PRc|CRc|K|Er) \
767 O(MapSet, ND, C(TCA) \
768 S(Obj) \
769 S(Int,Str) \
770 S(Cell), E|N|Er) \
771 O(ArraySetRef, ND, C(TCA) \
772 S(Arr) \
773 S(Int,Str) \
774 S(Cell) \
775 S(BoxedArr), E|N|CRc|K) \
776 O_STK(SetElem, DSetElem, C(TCA) \
777 S(PtrToGen) \
778 S(Cell) \
779 S(Cell), MElem|E|N|PRc|Er) \
780 O_STK(SetWithRefElem, ND, C(TCA) \
781 S(PtrToGen) \
782 S(Cell) \
783 S(PtrToGen) \
784 S(PtrToCell), MElem|E|N|Er) \
785 O_STK(UnsetElem, ND, C(TCA) \
786 S(PtrToGen) \
787 S(Cell), MElem|E|N|Er) \
788 O_STK(SetOpElem, D(Cell), C(TCA) \
789 S(PtrToGen) \
790 S(Cell) \
791 S(Cell) \
792 S(PtrToCell), \
793 MElem|E|N|PRc|Er) \
794 O_STK(IncDecElem, D(Cell), C(TCA) \
795 S(PtrToGen) \
796 S(Cell) \
797 S(PtrToCell), \
798 MElem|E|N|PRc|Er) \
799 O_STK(SetNewElem, ND, S(PtrToGen) \
800 S(Cell), MElem|E|N|Er) \
801 O_STK(SetNewElemArray, ND, S(PtrToArr) \
802 S(Cell), MElem|E|N|Er) \
803 O_STK(SetWithRefNewElem, ND, C(TCA) \
804 S(PtrToGen) \
805 S(PtrToGen) \
806 S(PtrToCell), MElem|E|N|Er) \
807 O_STK(BindNewElem, ND, S(PtrToGen) \
808 S(BoxedCell) \
809 S(PtrToCell), MElem|E|N|Er) \
810 O(ArrayIsset, D(Bool), C(TCA) \
811 S(Arr) \
812 S(Int,Str), E|N|Er) \
813 O(StringIsset, D(Bool), S(Str) S(Int), NF) \
814 O(VectorIsset, D(Bool), C(TCA) \
815 S(Obj) \
816 S(Int), E|N) \
817 O(PairIsset, D(Bool), C(TCA) \
818 S(Obj) \
819 S(Int), E|N) \
820 O(MapIsset, D(Bool), C(TCA) \
821 S(Obj) \
822 S(Int,Str), E|N) \
823 O(IssetElem, D(Bool), C(TCA) \
824 S(PtrToGen) \
825 S(Cell) \
826 S(PtrToCell), E|N|Er) \
827 O(EmptyElem, D(Bool), C(TCA) \
828 S(PtrToGen) \
829 S(Cell) \
830 S(PtrToCell), E|N|Er) \
831 O(IncStat, ND, C(Int) C(Int) C(Bool), E) \
832 O(TypeProfileFunc, ND, S(Gen) S(Func), E|N) \
833 O(IncStatGrouped, ND, CStr CStr C(Int), E|N) \
834 O(RBTrace, ND, NA, E|N) \
835 O(IncTransCounter, ND, NA, E) \
836 O(IncProfCounter, ND, NA, E) \
837 O(ArrayIdx, D(Cell), C(TCA) \
838 S(Arr) \
839 S(Int,Str) \
840 S(Cell), E|N|PRc) \
841 O(GenericIdx, D(Cell), S(Cell) \
842 S(Cell) \
843 S(Cell), E|N|PRc|Er) \
844 O(DbgAssertRefCount, ND, S(Counted,StaticStr,StaticArr), N|E) \
845 O(DbgAssertPtr, ND, S(PtrToGen), N|E) \
846 O(DbgAssertType, ND, S(Cell), E) \
847 O(DbgAssertRetAddr, ND, NA, E) \
848 O(Nop, ND, NA, NF) \
849 /* */
851 enum class Opcode : uint16_t {
852 #define O(name, ...) name,
853 IR_OPCODES
854 #undef O
856 #define O(name, ...) UNUSED auto constexpr name = Opcode::name;
857 IR_OPCODES
858 #undef O
861 * Returns true for instructions that refine the types of values with
862 * a runtime check.
864 bool isGuardOp(Opcode opc);
867 * Returns the corresponding Assert* opcode for a guard instruction.
869 Opcode guardToAssert(Opcode opc);
872 * A "query op" is any instruction returning Type::Bool that is
873 * negateable.
875 bool isQueryOp(Opcode opc);
878 * Return true if opc is an int comparison operator
880 bool isIntQueryOp(Opcode opc);
883 * Return the int-query opcode for the given non-int-query opcode
885 Opcode queryToIntQueryOp(Opcode opc);
888 * A "fusable query op" is any instruction returning Type::Bool that
889 * has a corresponding "query jump op" for branch fusion.
891 bool isFusableQueryOp(Opcode opc);
894 * A "query jump op" is a conditional jump instruction that
895 * corresponds to one of the fusable query op instructions.
897 bool isQueryJmpOp(Opcode opc);
900 * Translate a query op into a conditional jump that does the same
901 * test (a "query jump op").
903 * Pre: isFusableQueryOp(opc)
905 Opcode queryToJmpOp(Opcode opc);
908 * Translate a "query jump op" to a query op.
910 * Pre: isQueryJmpOp(opc);
912 Opcode queryJmpToQueryOp(Opcode opc);
915 * Convert a jump to its corresponding side exit.
917 Opcode jmpToSideExitJmp(Opcode opc);
920 * Convert a jump operation to its corresponding conditional
921 * ReqBindJmp.
923 * Pre: opc is a conditional jump.
925 Opcode jmpToReqBindJmp(Opcode opc);
928 * Return the opcode that corresponds to negation of opc.
930 Opcode negateQueryOp(Opcode opc);
933 * Return the opcode that corresponds to commuting the arguments of
934 * opc.
936 * Pre: opc is a 2-argument query op.
938 Opcode commuteQueryOp(Opcode opc);
940 const char* opcodeName(Opcode opcode);
942 bool opHasExtraData(Opcode op);
944 enum OpcodeFlag : uint64_t {
945 NoFlags = 0,
946 HasDest = 1ULL << 0,
947 CanCSE = 1ULL << 1,
948 Essential = 1ULL << 2,
949 Branch = 1ULL << 3,
950 CallsNative = 1ULL << 4,
951 ConsumesRC = 1ULL << 5,
952 ProducesRC = 1ULL << 6,
953 // Unused
954 // Unused
955 MayRaiseError = 1ULL << 9,
956 Terminal = 1ULL << 10, // has no next instruction
957 NaryDest = 1ULL << 11, // has 0 or more destinations
958 HasExtra = 1ULL << 12,
959 Passthrough = 1ULL << 13,
960 KillsSources = 1ULL << 14,
961 ModifiesStack = 1ULL << 15,
962 HasStackVersion = 1ULL << 16,
963 MInstrProp = 1ULL << 17,
964 MInstrElem = 1ULL << 18,
967 bool hasEdges(Opcode opc);
968 bool opcodeHasFlags(Opcode opc, uint64_t flags);
969 Opcode getStackModifyingOpcode(Opcode opc);
972 * typeForConst(T)
974 * returns the Type type for a C++ type that may be used with
975 * ConstData.
978 // The only interesting case is int/bool disambiguation. Enums are
979 // treated as ints.
980 template<class T>
981 typename std::enable_if<
982 std::is_integral<T>::value || std::is_enum<T>::value,
983 Type
984 >::type typeForConst(T) {
985 return std::is_same<T,bool>::value ? Type::Bool : Type::Int;
988 inline Type typeForConst(const NamedEntity*) { return Type::NamedEntity; }
989 inline Type typeForConst(const Func*) { return Type::Func; }
990 inline Type typeForConst(const Class*) { return Type::Cls; }
991 inline Type typeForConst(const TypedValue*) { return Type::PtrToGen; }
992 inline Type typeForConst(TCA) { return Type::TCA; }
993 inline Type typeForConst(double) { return Type::Dbl; }
994 inline Type typeForConst(SetOpOp) { return Type::Int; }
995 inline Type typeForConst(IncDecOp) { return Type::Int; }
996 inline Type typeForConst(std::nullptr_t) { return Type::Nullptr; }
998 inline Type typeForConst(const StringData* sd) {
999 assert(sd->isStatic());
1000 return Type::StaticStr;
1002 inline Type typeForConst(const ArrayData* ad) {
1003 assert(ad->isStatic());
1004 return Type::StaticArr.specialize(ad->kind());
1006 inline Type typeForConst(const TypedValue& tv) {
1007 switch (tv.m_type) {
1008 case KindOfClass:
1009 case KindOfUninit:
1010 case KindOfNull:
1011 case KindOfBoolean:
1012 case KindOfInt64:
1013 case KindOfDouble:
1014 case KindOfStaticString:
1015 return Type(tv.m_type);
1017 case KindOfString:
1018 return typeForConst(tv.m_data.pstr);
1020 case KindOfArray:
1021 return typeForConst(tv.m_data.parr);
1023 default:
1024 always_assert(false && "Invalid KindOf for constant TypedValue");
1029 * constToBits(T)
1031 * Returns a constant value as a 8-byte word (in the shape it would
1032 * need to be to go into a register). Takes care to ensure that
1033 * various types are safely copied.
1036 namespace constToBits_detail {
1037 template<class T>
1038 struct needs_promotion
1039 : std::integral_constant<
1040 bool,
1041 std::is_integral<T>::value ||
1042 std::is_same<T,bool>::value ||
1043 std::is_enum<T>::value
1047 template<class T>
1048 typename std::enable_if<needs_promotion<T>::value,uint64_t>::type
1049 promoteIfNeeded(T t) { return static_cast<uint64_t>(t); }
1051 template<class T>
1052 typename std::enable_if<!needs_promotion<T>::value,T>::type
1053 promoteIfNeeded(T t) { return t; }
1056 template<class T>
1057 uintptr_t constToBits(T input) {
1058 uintptr_t ret;
1059 static_assert(sizeof(T) <= sizeof ret,
1060 "Constant data was larger than supported");
1061 static_assert(std::is_pod<T>::value,
1062 "Constant data wasn't a pod?");
1063 const auto toCopy = constToBits_detail::promoteIfNeeded(input);
1064 std::memcpy(&ret, &toCopy, sizeof toCopy);
1065 return ret;
1068 inline uintptr_t constToBits(const TypedValue& tv) {
1069 return tv.m_data.num;
1072 class RawMemSlot {
1073 public:
1075 enum Kind {
1076 ContLabel, ContIndex, ContState,
1077 StrLen, FuncNumParams, ContEntry, MisCtx, MaxKind
1080 static RawMemSlot& Get(Kind k) {
1081 switch (k) {
1082 case ContLabel: return GetContLabel();
1083 case ContIndex: return GetContIndex();
1084 case ContState: return GetContState();
1085 case StrLen: return GetStrLen();
1086 case FuncNumParams: return GetFuncNumParams();
1087 case ContEntry: return GetContEntry();
1088 case MisCtx: return GetMisCtx();
1089 default: not_reached();
1093 int64_t offset() const { return m_offset; }
1094 int32_t size() const { return m_size; }
1095 Type type() const { return m_type; }
1096 bool allowExtra() const { return m_allowExtra; }
1098 private:
1099 RawMemSlot(int64_t offset, int32_t size, Type type, bool allowExtra = false)
1100 : m_offset(offset), m_size(size), m_type(type), m_allowExtra(allowExtra) { }
1102 static RawMemSlot& GetContLabel() {
1103 static RawMemSlot m(CONTOFF(m_label), sz::dword, Type::Int);
1104 return m;
1106 static RawMemSlot& GetContIndex() {
1107 static RawMemSlot m(CONTOFF(m_index), sz::qword, Type::Int);
1108 return m;
1110 static RawMemSlot& GetContState() {
1111 static RawMemSlot m(c_Continuation::stateOffset(),
1112 sz::byte, Type::Int);
1113 return m;
1115 static RawMemSlot& GetStrLen() {
1116 static RawMemSlot m(StringData::sizeOffset(), sz::dword, Type::Int);
1117 return m;
1119 static RawMemSlot& GetFuncNumParams() {
1120 static RawMemSlot m(Func::numParamsOff(), sz::dword, Type::Int);
1121 return m;
1123 static RawMemSlot& GetContEntry() {
1124 static RawMemSlot m(CONTOFF(m_entry), sz::qword, Type::TCA);
1125 return m;
1127 static RawMemSlot& GetMisCtx() {
1128 static RawMemSlot m(MISOFF(ctx), sz::qword, Type::Cls);
1129 return m;
1132 int64_t m_offset;
1133 int32_t m_size;
1134 Type m_type;
1135 bool m_allowExtra; // Used as a flag to ensure that extra offets are
1136 // only used with RawMemSlots that support it
1139 bool isRefCounted(SSATmp* opnd);
1141 using folly::Range;
1142 typedef Range<SSATmp**> SrcRange;
1143 typedef Range<SSATmp*> DstRange;
1146 * Given an SSATmp of type Cls, try to find the name of the class.
1147 * Returns nullptr if can't find it.
1149 const StringData* findClassName(SSATmp* cls);
1152 * Return the output type from a given IRInstruction.
1154 * The destination type is always predictable from the types of the inputs, any
1155 * type parameters to the instruction, and the id of the dest.
1157 Type outputType(const IRInstruction*, int dstId = 0);
1160 * Assert that an instruction has operands of allowed types.
1162 void assertOperandTypes(const IRInstruction*);
1165 int minstrBaseIdx(Opcode opc);
1166 int minstrKeyIdx(Opcode opc);
1167 int minstrValueIdx(Opcode opc);
1168 int minstrBaseIdx(const IRInstruction* inst);
1169 int minstrKeyIdx(const IRInstruction* inst);
1170 int minstrValueIdx(const IRInstruction* inst);
1172 struct MInstrEffects {
1173 static bool supported(Opcode op);
1174 static bool supported(const IRInstruction* inst);
1177 * MInstrEffects::get is used to allow multiple different consumers to deal
1178 * with the side effects of vector instructions. It takes an instruction and
1179 * a LocalStateHook, which is defined in frame-state.h.
1181 static void get(const IRInstruction*, LocalStateHook&);
1183 explicit MInstrEffects(const IRInstruction* inst);
1184 MInstrEffects(Opcode op, Type base);
1185 MInstrEffects(Opcode op, SSATmp* base);
1186 MInstrEffects(Opcode opc, const std::vector<SSATmp*>& srcs);
1188 Type baseType;
1189 bool baseTypeChanged;
1190 bool baseValChanged;
1192 private:
1193 void init(const Opcode op, const Type base);
1196 struct CatchInfo {
1197 /* afterCall is the address after the call instruction that this catch trace
1198 * belongs to. It's the key used to look up catch traces by the
1199 * unwinder, since it's the value of %rip during unwinding. */
1200 TCA afterCall;
1202 /* savedRegs contains the caller-saved registers that were pushed onto the
1203 * C++ stack at the time of the call. The catch trace will pop these
1204 * registers (in the same order as PhysRegSaver's destructor) before doing
1205 * any real work to restore the register state from before the call. */
1206 RegSet savedRegs;
1208 /* rspOffset is the number of bytes pushed on the C++ stack after the
1209 * registers in savedRegs were saved, typically from function calls with >6
1210 * arguments. The catch trace will adjust rsp by this amount before popping
1211 * anything in savedRegs. */
1212 Offset rspOffset;
1215 typedef folly::Range<TCA> TcaRange;
1217 // Used instead of StateVector because it's expected to be very sparse.
1218 typedef smart::flat_map<const IRInstruction*, TypeConstraint> GuardConstraints;
1221 * Counts the number of cells a SpillStack will logically push. (Not
1222 * including the number it pops.) That is, for each SSATmp in the
1223 * spill sources, this totals up whether it is an ActRec or a cell.
1225 int32_t spillValueCells(const IRInstruction* spillStack);
1227 } // namespace JIT
1228 } // namespace HPHP
1230 namespace std {
1231 template<> struct hash<HPHP::JIT::Opcode> {
1232 size_t operator()(HPHP::JIT::Opcode op) const { return uint16_t(op); }
1234 template<> struct hash<HPHP::JIT::Type> {
1235 size_t operator()(HPHP::JIT::Type t) const { return t.hash(); }
1239 namespace folly {
1240 template<> struct FormatValue<HPHP::JIT::Opcode> {
1241 explicit FormatValue(HPHP::JIT::Opcode op) : m_op(op) {}
1243 template<typename Callback> void format(FormatArg& arg, Callback& cb) const {
1244 format_value::formatString(opcodeName(m_op), arg, cb);
1247 private:
1248 HPHP::JIT::Opcode m_op;
1252 #endif