2 +----------------------------------------------------------------------+
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_
26 #include <forward_list>
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"
55 // forward declaration
60 using HPHP::JIT::RegSet
;
61 using HPHP::JIT::PhysReg
;
62 using HPHP::JIT::ConditionCode
;
67 struct LocalStateHook
;
69 class FailedIRGen
: public std::runtime_error
{
71 const char* const file
;
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())
84 class FailedTraceGen
: public std::runtime_error
{
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
{
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 {}. {}@{}",
104 _vmFunc
->fullName()->data(), _bcOff
)
114 #define SPUNT(instr) do { \
115 throw FailedIRGen(__FILE__, __LINE__, instr); \
117 #define PUNT(instr) SPUNT(#instr)
118 #define TRACE_PUNT(why) do { \
119 throw FailedTraceGen(__FILE__, __LINE__, why); \
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.
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
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
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
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:
195 #define O_STK(name, dst, src, flags) \
196 O(name, dst, src, StkFlags(flags)) \
197 O(name ## Stk, DStk(dst), src, flags)
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) \
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) \
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) \
465 S(FramePtr), E|N|Er) \
466 O(LdArrFPushCuf, ND, S(Arr) \
468 S(FramePtr), E|N|Er) \
469 O(LdStrFPushCuf, ND, S(Str) \
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) \
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) \
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 \
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) \
528 S(Ctx,Cls,InitNull), CRc) \
529 O(CufIterSpillFrame, D(StkPtr), S(StkPtr) \
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) \
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) \
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) \
575 S(Cell), N|CRc|PRc) \
576 O(AddElemIntKey, D(Arr), S(Arr) \
578 S(Cell), N|CRc|PRc) \
579 O(AddNewElem, D(Arr), SUnk, N|CRc|PRc) \
580 O(ColAddElemC, D(Obj), S(Obj) \
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), \
593 O(InterpOneCF, D(StkPtr), S(StkPtr) S(FramePtr), \
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) \
625 C(Int), Er|E|N|CRc) \
626 O(IterInitK, D(Bool), S(Arr,Obj) \
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) \
638 C(Int), Er|E|N|CRc) \
639 O(WIterInitK, D(Bool), S(Arr,Obj) \
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) \
652 O(MIterInitK, D(Bool), S(BoxedCell) \
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) \
665 O(CIterFree, ND, S(FramePtr), E|N) \
666 O(DefMIStateBase, D(PtrToCell), NA, NF) \
667 O(BaseG, D(PtrToGen), C(TCA) \
669 S(PtrToCell), E|N|Er) \
670 O(PropX, D(PtrToGen), C(TCA) \
674 S(PtrToCell), E|N|Er) \
675 O_STK(PropDX, D(PtrToGen), C(TCA) \
679 S(PtrToCell), MProp|E|N|Er) \
680 O(CGetProp, D(Cell), C(TCA) \
684 S(PtrToCell), E|N|PRc|Er) \
685 O_STK(VGetProp, D(BoxedCell), C(TCA) \
691 O_STK(BindProp, ND, C(TCA) \
696 S(PtrToCell), MProp|E|N|Er) \
697 O_STK(SetProp, ND, C(TCA) \
701 S(Cell), MProp|E|N|Er) \
702 O(UnsetProp, ND, C(TCA) \
706 O_STK(SetOpProp, D(Cell), C(TCA) \
711 C(Int), MProp|E|N|PRc|Er) \
712 O_STK(IncDecProp, D(Cell), C(TCA) \
716 C(Int), MProp|E|N|PRc|Er) \
717 O(EmptyProp, D(Bool), C(TCA) \
721 O(IssetProp, D(Bool), C(TCA) \
725 O(ElemX, D(PtrToGen), C(TCA) \
728 S(PtrToCell), E|N|Er) \
729 O(ElemArray, D(PtrToGen), C(TCA) \
731 S(Int,Str), E|N|Er) \
732 O_STK(ElemDX, D(PtrToGen), C(TCA) \
735 S(PtrToCell), MElem|E|N|Er) \
736 O_STK(ElemUX, D(PtrToGen), C(TCA) \
739 S(PtrToCell), MElem|E|N|Er) \
740 O(ArrayGet, D(Cell), C(TCA) \
742 S(Int,Str), N|PRc|Er) \
743 O(StringGet, D(StaticStr), C(TCA) \
746 O(MapGet, D(Cell), C(TCA) \
748 S(Int,Str), E|N|PRc|Er) \
749 O(CGetElem, D(Cell), C(TCA) \
752 S(PtrToCell), E|N|PRc|Er) \
753 O_STK(VGetElem, D(BoxedCell), C(TCA) \
758 O_STK(BindElem, ND, C(TCA) \
762 S(PtrToCell), MElem|E|N|Er) \
763 O(ArraySet, D(Arr), C(TCA) \
766 S(Cell), E|N|PRc|CRc|K|Er) \
767 O(MapSet, ND, C(TCA) \
771 O(ArraySetRef, ND, C(TCA) \
775 S(BoxedArr), E|N|CRc|K) \
776 O_STK(SetElem, DSetElem, C(TCA) \
779 S(Cell), MElem|E|N|PRc|Er) \
780 O_STK(SetWithRefElem, ND, C(TCA) \
784 S(PtrToCell), MElem|E|N|Er) \
785 O_STK(UnsetElem, ND, C(TCA) \
787 S(Cell), MElem|E|N|Er) \
788 O_STK(SetOpElem, D(Cell), C(TCA) \
794 O_STK(IncDecElem, D(Cell), C(TCA) \
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) \
806 S(PtrToCell), MElem|E|N|Er) \
807 O_STK(BindNewElem, ND, S(PtrToGen) \
809 S(PtrToCell), MElem|E|N|Er) \
810 O(ArrayIsset, D(Bool), C(TCA) \
812 S(Int,Str), E|N|Er) \
813 O(StringIsset, D(Bool), S(Str) S(Int), NF) \
814 O(VectorIsset, D(Bool), C(TCA) \
817 O(PairIsset, D(Bool), C(TCA) \
820 O(MapIsset, D(Bool), C(TCA) \
823 O(IssetElem, D(Bool), C(TCA) \
826 S(PtrToCell), E|N|Er) \
827 O(EmptyElem, D(Bool), C(TCA) \
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) \
841 O(GenericIdx, D(Cell), 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) \
851 enum class Opcode
: uint16_t {
852 #define O(name, ...) name,
856 #define O(name, ...) UNUSED auto constexpr name = Opcode::name;
861 * Returns true for instructions that refine the types of values with
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
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
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
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 {
948 Essential
= 1ULL << 2,
950 CallsNative
= 1ULL << 4,
951 ConsumesRC
= 1ULL << 5,
952 ProducesRC
= 1ULL << 6,
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
);
974 * returns the Type type for a C++ type that may be used with
978 // The only interesting case is int/bool disambiguation. Enums are
981 typename
std::enable_if
<
982 std::is_integral
<T
>::value
|| std::is_enum
<T
>::value
,
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
) {
1014 case KindOfStaticString
:
1015 return Type(tv
.m_type
);
1018 return typeForConst(tv
.m_data
.pstr
);
1021 return typeForConst(tv
.m_data
.parr
);
1024 always_assert(false && "Invalid KindOf for constant TypedValue");
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
{
1038 struct needs_promotion
1039 : std::integral_constant
<
1041 std::is_integral
<T
>::value
||
1042 std::is_same
<T
,bool>::value
||
1043 std::is_enum
<T
>::value
1048 typename
std::enable_if
<needs_promotion
<T
>::value
,uint64_t>::type
1049 promoteIfNeeded(T t
) { return static_cast<uint64_t>(t
); }
1052 typename
std::enable_if
<!needs_promotion
<T
>::value
,T
>::type
1053 promoteIfNeeded(T t
) { return t
; }
1057 uintptr_t constToBits(T input
) {
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
);
1068 inline uintptr_t constToBits(const TypedValue
& tv
) {
1069 return tv
.m_data
.num
;
1076 ContLabel
, ContIndex
, ContState
,
1077 StrLen
, FuncNumParams
, ContEntry
, MisCtx
, MaxKind
1080 static RawMemSlot
& Get(Kind 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
; }
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
);
1106 static RawMemSlot
& GetContIndex() {
1107 static RawMemSlot
m(CONTOFF(m_index
), sz::qword
, Type::Int
);
1110 static RawMemSlot
& GetContState() {
1111 static RawMemSlot
m(c_Continuation::stateOffset(),
1112 sz::byte
, Type::Int
);
1115 static RawMemSlot
& GetStrLen() {
1116 static RawMemSlot
m(StringData::sizeOffset(), sz::dword
, Type::Int
);
1119 static RawMemSlot
& GetFuncNumParams() {
1120 static RawMemSlot
m(Func::numParamsOff(), sz::dword
, Type::Int
);
1123 static RawMemSlot
& GetContEntry() {
1124 static RawMemSlot
m(CONTOFF(m_entry
), sz::qword
, Type::TCA
);
1127 static RawMemSlot
& GetMisCtx() {
1128 static RawMemSlot
m(MISOFF(ctx
), sz::qword
, Type::Cls
);
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
);
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
);
1189 bool baseTypeChanged
;
1190 bool baseValChanged
;
1193 void init(const Opcode op
, const Type base
);
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. */
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. */
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. */
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
);
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(); }
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
);
1248 HPHP::JIT::Opcode m_op
;