2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 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/ext/ext_continuation.h"
43 #include "hphp/runtime/vm/jit/physreg.h"
44 #include "hphp/runtime/vm/jit/abi-x64.h"
45 #include "hphp/runtime/vm/jit/types.h"
46 #include "hphp/runtime/vm/jit/runtime-type.h"
47 #include "hphp/runtime/vm/jit/translator-runtime.h"
48 #include "hphp/runtime/vm/jit/type.h"
49 #include "hphp/runtime/base/types.h"
50 #include "hphp/runtime/vm/func.h"
51 #include "hphp/runtime/vm/class.h"
54 // forward declaration
58 using HPHP::Transl::TCA
;
59 using HPHP::Transl::RegSet
;
60 using HPHP::Transl::PhysReg
;
61 using HPHP::Transl::ConditionCode
;
68 class FailedIRGen
: public std::runtime_error
{
70 const char* const file
;
72 const char* const func
;
74 FailedIRGen(const char* _file
, int _line
, const char* _func
)
75 : std::runtime_error(folly::format("FailedIRGen @ {}:{} in {}",
76 _file
, _line
, _func
).str())
83 class FailedCodeGen
: public std::runtime_error
{
91 FailedCodeGen(const char* _file
, int _line
, const char* _func
,
92 uint32_t _bcOff
, const Func
* _vmFunc
)
93 : std::runtime_error(folly::format("FailedCodeGen @ {}:{} in {}. {}@{}",
95 _vmFunc
->fullName()->data(), _bcOff
)
105 #define SPUNT(instr) do { \
106 throw FailedIRGen(__FILE__, __LINE__, instr); \
108 #define PUNT(instr) SPUNT(#instr)
110 //////////////////////////////////////////////////////////////////////
113 * The instruction table below uses the following notation. To use
114 * it, you have to define these symbols to do what you want, and then
115 * instantiate IR_OPCODES.
119 * Contains a description of how to compute the type of the
120 * destination(s) of an instruction from its sources.
122 * ND instruction has no destination
123 * D(type) single dst has a specific type
124 * DofS(N) single dst has the type of src N
125 * DUnbox(N) single dst has unboxed type of src N
126 * DBox(N) single dst has boxed type of src N
127 * DParam single dst has type of the instruction's type parameter
128 * DArith single dst has a type based on arithmetic type rules
129 * DMulti multiple dests. type and number depend on instruction
130 * DSetElem single dst is a subset of CountedStr|Nullptr depending on
132 * DStk(x) up to two dests. x should be another D* macro and indicates
133 * the type of the first dest, if any. the second (or first,
134 * depending on the presence of a primary destination), will be
135 * of type Type::StkPtr. implies ModifiesStack.
136 * DBuiltin single dst for CallBuiltin. This can return complex data
137 * types such as (Type::Str | Type::Null)
138 * DSubtract(N,t) single dest has type of src N with t removed
142 * Contains a series of tests on the source parameters in order.
144 * NA instruction takes no sources
145 * SUnk intructions sources are not yet documented/checked
146 * S(t1,...,tn) source must be a subtype of {t1|..|tn}
147 * C(type) source must be a constant, and subtype of type
148 * CStr same as C(StaticStr)
149 * SNumInt same as S(Int,Bool)
150 * SNum same as S(Int,Bool,Dbl)
151 * SSpills SpillStack's variadic source list
155 * See doc/ir.specification for the meaning of these flag various.
157 * The flags in this opcode table supply default values for the
158 * querying functions in IRInstruction---those functions involve
159 * additional logic (based on operand types, etc) on a
160 * per-instruction basis.
162 * The following abbreviations are used in this table:
180 #define O_STK(name, dst, src, flags) \
181 O(name, dst, src, StkFlags(flags)) \
182 O(name ## Stk, DStk(dst), src, flags)
185 /* name dstinfo srcinfo flags */ \
186 O(CheckType, DParam, S(Gen,Nullptr), E|CRc|PRc|P) \
187 O(AssertType, DParam, S(Gen,Nullptr,Cls), C|E|CRc|PRc|P) \
188 O(CheckTypeMem, ND, S(PtrToGen), E) \
189 O(GuardLoc, ND, S(FramePtr), E) \
190 O(GuardStk, D(StkPtr), S(StkPtr), E) \
191 O(CheckLoc, ND, S(FramePtr), E) \
192 O(CheckStk, D(StkPtr), S(StkPtr), E) \
193 O(CastStk, D(StkPtr), S(StkPtr), Mem|N|Er) \
194 O(CoerceStk, D(StkPtr), S(StkPtr), Mem|N|Er) \
195 O(AssertStk, D(StkPtr), S(StkPtr), E) \
196 O(AssertStkVal, D(StkPtr), S(StkPtr) S(Gen), E) \
197 O(CheckDefinedClsEq, ND, NA, E) \
198 O(GuardRefs, ND, S(Func) \
203 O(AssertLoc, ND, S(FramePtr), E) \
204 O(OverrideLoc, ND, S(FramePtr), E) \
205 O(SmashLocals, ND, S(FramePtr), E) \
206 O(BeginCatch, ND, NA, E|Mem) \
207 O(EndCatch, ND, S(StkPtr), E|Mem) \
208 O(LdUnwinderValue, DParam, NA, PRc) \
209 O(DeleteUnwinderException, ND, NA, N|E|Mem) \
210 O(OpAdd, DArith, S(Int,Dbl) S(Int,Dbl), C) \
211 O(OpSub, DArith, S(Int,Dbl) S(Int,Dbl), C) \
212 O(OpMul, DArith, S(Int,Dbl) S(Int,Dbl), C) \
213 O(OpDiv, DArith, S(Int,Dbl) S(Int,Dbl), C) \
214 O(OpMod, D(Int), S(Int) S(Int), C) \
215 O(OpBitAnd, D(Int), S(Int) S(Int), C) \
216 O(OpBitOr, D(Int), S(Int) S(Int), C) \
217 O(OpBitXor, D(Int), S(Int) S(Int), C) \
218 O(OpBitNot, D(Int), S(Int), C) \
219 O(OpLogicXor, D(Bool), S(Bool) S(Bool), C) \
220 O(OpNot, D(Bool), S(Bool), C) \
222 O(ConvBoolToArr, D(Arr), S(Bool), C|N) \
223 O(ConvDblToArr, D(Arr), S(Dbl), C|N) \
224 O(ConvIntToArr, D(Arr), S(Int), C|N) \
225 O(ConvObjToArr, D(Arr), S(Obj), N|CRc|K) \
226 O(ConvStrToArr, D(Arr), S(Str), N|CRc) \
227 O(ConvCellToArr, D(Arr), S(Cell), N|CRc|K) \
229 O(ConvArrToBool, D(Bool), S(Arr), C|N) \
230 O(ConvDblToBool, D(Bool), S(Dbl), C) \
231 O(ConvIntToBool, D(Bool), S(Int), C) \
232 O(ConvStrToBool, D(Bool), S(Str), N) \
233 O(ConvCellToBool, D(Bool), S(Cell), N) \
235 O(ConvArrToDbl, D(Dbl), S(Arr), C|N) \
236 O(ConvBoolToDbl, D(Dbl), S(Bool), C) \
237 O(ConvIntToDbl, D(Dbl), S(Int), C) \
238 O(ConvObjToDbl, D(Dbl), S(Obj), N|Er|K) \
239 O(ConvStrToDbl, D(Dbl), S(Str), N|K) \
240 O(ConvCellToDbl, D(Dbl), S(Cell), N|Er|K) \
242 O(ConvArrToInt, D(Int), S(Arr), C|N) \
243 O(ConvBoolToInt, D(Int), S(Bool), C) \
244 O(ConvDblToInt, D(Int), S(Dbl), C|N) \
245 O(ConvObjToInt, D(Int), S(Obj), N|Er|K) \
246 O(ConvStrToInt, D(Int), S(Str), N) \
247 O(ConvCellToInt, D(Int), S(Cell), N|Er|K) \
249 O(ConvCellToObj, D(Obj), S(Cell), N|CRc|K) \
251 O(ConvBoolToStr, D(StaticStr), S(Bool), C) \
252 O(ConvDblToStr, D(Str), S(Dbl), N) \
253 O(ConvIntToStr, D(Str), S(Int), N) \
254 O(ConvObjToStr, D(Str), S(Obj), N|Er|CRc|K) \
255 O(ConvCellToStr, D(Str), S(Cell), N|Er|CRc|K) \
257 O(ExtendsClass, D(Bool), S(Cls) C(Cls), C) \
258 O(InstanceOf, D(Bool), S(Cls) S(Cls), C|N) \
259 O(InstanceOfIface, D(Bool), S(Cls) CStr, C|N) \
260 O(IsTypeMem, D(Bool), S(PtrToGen), NA) \
261 O(IsNTypeMem, D(Bool), S(PtrToGen), NA) \
262 /* name dstinfo srcinfo flags */ \
263 O(OpGt, D(Bool), S(Gen) S(Gen), C|N) \
264 O(OpGte, D(Bool), S(Gen) S(Gen), C|N) \
265 O(OpLt, D(Bool), S(Gen) S(Gen), C|N) \
266 O(OpLte, D(Bool), S(Gen) S(Gen), C|N) \
267 O(OpEq, D(Bool), S(Gen) S(Gen), C|N) \
268 O(OpNeq, D(Bool), S(Gen) S(Gen), C|N) \
269 O(OpSame, D(Bool), S(Gen) S(Gen), C|N) \
270 O(OpNSame, D(Bool), S(Gen) S(Gen), C|N) \
271 O(InstanceOfBitmask, D(Bool), S(Cls) CStr, C) \
272 O(NInstanceOfBitmask, D(Bool), S(Cls) CStr, C) \
273 O(IsType, D(Bool), S(Cell), C) \
274 O(IsNType, D(Bool), S(Cell), C) \
275 /* there is a conditional branch for each of the above query ops */ \
276 O(JmpGt, D(None), S(Gen) S(Gen), E) \
277 O(JmpGte, D(None), S(Gen) S(Gen), E) \
278 O(JmpLt, D(None), S(Gen) S(Gen), E) \
279 O(JmpLte, D(None), S(Gen) S(Gen), E) \
280 O(JmpEq, D(None), S(Gen) S(Gen), E) \
281 O(JmpNeq, D(None), S(Gen) S(Gen), E) \
282 O(JmpSame, D(None), S(Gen) S(Gen), E) \
283 O(JmpNSame, D(None), S(Gen) S(Gen), E) \
284 O(JmpInstanceOfBitmask, D(None), S(Cls) CStr, E) \
285 O(JmpNInstanceOfBitmask, D(None), S(Cls) CStr, E) \
286 O(JmpIsType, D(None), SUnk, E) \
287 O(JmpIsNType, D(None), SUnk, E) \
288 /* name dstinfo srcinfo flags */ \
289 O(JmpZero, D(None), SNum, E) \
290 O(JmpNZero, D(None), SNum, E) \
291 O(Jmp_, D(None), SUnk, T|E) \
292 O(ReqBindJmpGt, ND, S(Gen) S(Gen), T|E) \
293 O(ReqBindJmpGte, ND, S(Gen) S(Gen), T|E) \
294 O(ReqBindJmpLt, ND, S(Gen) S(Gen), T|E) \
295 O(ReqBindJmpLte, ND, S(Gen) S(Gen), T|E) \
296 O(ReqBindJmpEq, ND, S(Gen) S(Gen), T|E) \
297 O(ReqBindJmpNeq, ND, S(Gen) S(Gen), T|E) \
298 O(ReqBindJmpSame, ND, S(Gen) S(Gen), T|E) \
299 O(ReqBindJmpNSame, ND, S(Gen) S(Gen), T|E) \
300 O(ReqBindJmpInstanceOfBitmask, ND, S(Cls) CStr, T|E) \
301 O(ReqBindJmpNInstanceOfBitmask, ND, S(Cls) CStr, T|E) \
302 O(ReqBindJmpZero, ND, SNum, T|E) \
303 O(ReqBindJmpNZero, ND, SNum, T|E) \
304 O(SideExitGuardLoc, ND, S(FramePtr), E) \
305 O(SideExitGuardStk, D(StkPtr), S(StkPtr), E) \
306 /* name dstinfo srcinfo flags */ \
307 O(JmpIndirect, ND, S(TCA), T|E) \
308 O(ExitWhenSurprised, ND, NA, E) \
309 O(ExitOnVarEnv, ND, S(FramePtr), E) \
310 O(ReleaseVVOrExit, ND, S(FramePtr), N|E) \
311 O(RaiseError, ND, S(Str), E|N|Mem|Refs|T|Er) \
312 O(RaiseWarning, ND, S(Str), E|N|Mem|Refs|Er) \
313 O(CheckInit, ND, S(Gen), NF) \
314 O(CheckInitMem, ND, S(PtrToGen) C(Int), NF) \
315 O(AssertNonNull, DSubtract(0, Nullptr), S(Nullptr,CountedStr), NF) \
316 O(Unbox, DUnbox(0), S(Gen), NF) \
317 O(Box, DBox(0), S(Init), E|N|Mem|CRc|PRc) \
318 O(UnboxPtr, D(PtrToCell), S(PtrToGen), NF) \
319 O(BoxPtr, D(PtrToBoxedCell), S(PtrToGen), N|Mem) \
320 O(LdStack, DParam, S(StkPtr), NF) \
321 O(LdLoc, DParam, S(FramePtr), NF) \
322 O(LdStackAddr, DParam, S(StkPtr), C) \
323 O(LdLocAddr, DParam, S(FramePtr), C) \
324 O(LdMem, DParam, S(PtrToGen) C(Int), NF) \
325 O(LdProp, DParam, S(Obj) C(Int), NF) \
326 O(LdRef, DParam, S(BoxedCell), NF) \
327 O(LdThis, D(Obj), S(FramePtr), C) \
328 O(LdRetAddr, D(RetAddr), S(FramePtr), NF) \
329 O(LdConst, DParam, NA, C) \
330 O(DefConst, DParam, NA, C) \
331 O(LdCtx, D(Ctx), S(FramePtr) S(Func), C) \
332 O(LdCctx, D(Cctx), S(FramePtr), C) \
333 O(LdCls, D(Cls), S(Str) C(Cls), C|E|N|Refs|Er|Mem) \
334 O(LdClsCached, D(Cls), CStr, C|E|N|Refs|Er|Mem) \
335 O(LdClsCachedSafe, D(Cls), CStr, C) \
336 O(LdClsCtx, D(Cls), S(Ctx), C) \
337 O(LdClsCctx, D(Cls), S(Cctx), C) \
338 O(LdClsCns, DParam, NA, NF) \
339 O(LookupClsCns, DParam, NA, E|Refs|Er|N|Mem) \
340 O(LdCns, DParam, CStr, NF) \
341 O(LookupCns, DParam, CStr, E|Refs|Er|N|Mem) \
342 O(LdClsMethodCache, D(FuncCls), C(Str) \
346 S(StkPtr), N|C|E|Refs|Er|Mem) \
347 O(LdClsMethodFCache, D(FuncCtx), C(Cls) \
350 S(FramePtr), N|C|E|Er) \
351 O(GetCtxFwdCall, D(Ctx), S(Ctx) S(Func), C) \
352 O(LdClsMethod, D(Func), S(Cls) C(Int), C) \
353 O(LdPropAddr, D(PtrToGen), S(Obj) C(Int), C) \
354 O(LdClsPropAddr, D(PtrToGen), S(Cls) S(Str) C(Cls), C|E|N|Er) \
355 O(LdClsPropAddrCached, D(PtrToGen), S(Cls) CStr CStr C(Cls), C|E|N|Er) \
356 O(LdObjMethod, ND, S(Cls) CStr S(StkPtr), E|N|Refs|Er) \
357 O(LdGblAddrDef, D(PtrToGen), S(Str), E|N|CRc) \
358 O(LdGblAddr, D(PtrToGen), S(Str), N) \
359 O(LdObjClass, D(Cls), S(Obj), C) \
360 O(LdFunc, D(Func), S(Str), E|N|CRc|Er) \
361 O(LdFuncCached, D(Func), CStr, N|C|E|Er) \
362 O(LdFuncCachedSafe, D(Func), CStr, C) \
363 O(LdARFuncPtr, D(Func), S(StkPtr,FramePtr) C(Int), C) \
364 O(LdSSwitchDestFast, D(TCA), S(Gen), N) \
365 O(LdSSwitchDestSlow, D(TCA), S(Gen), E|N|Refs|Er) \
366 O(LdSwitchDblIndex, D(Int), S(Dbl) S(Int) S(Int), N) \
367 O(LdSwitchStrIndex, D(Int), S(Str) S(Int) S(Int), CRc|N) \
368 O(LdSwitchObjIndex, D(Int), S(Obj) S(Int) S(Int), CRc|N|Er) \
369 O(JmpSwitchDest, ND, S(Int), T|E) \
370 O(AllocObj, D(Obj), S(Cls), N) \
371 O(AllocObjFast, D(Obj), C(Cls), N) \
372 O(LdClsCtor, D(Func), S(Cls), C|Er|N) \
373 O(CreateCl, D(Obj), C(Cls) \
377 O(NewArray, D(Arr), C(Int), N|PRc) \
378 O(NewTuple, D(Arr), C(Int) S(StkPtr), E|Mem|N|PRc|CRc) \
379 O(LdRaw, DParam, SUnk, NF) \
380 O(FreeActRec, D(FramePtr), S(FramePtr), Mem) \
381 /* name dstinfo srcinfo flags */ \
382 O(Call, D(StkPtr), SUnk, E|Mem|CRc|Refs) \
383 O(CallArray, D(StkPtr), S(StkPtr), E|Mem|N|CRc|Refs) \
384 O(CallBuiltin, DBuiltin, SUnk, E|Mem|Refs|Er|N|PRc) \
385 O(NativeImpl, ND, C(Func) S(FramePtr), E|Mem|N|Refs) \
386 O(RetCtrl, ND, S(StkPtr) \
388 S(RetAddr), T|E|Mem) \
389 O(StRetVal, ND, S(FramePtr) S(Gen), E|Mem|CRc) \
390 O(RetAdjustStack, D(StkPtr), S(FramePtr), E) \
391 O(StMem, ND, S(PtrToGen) \
392 C(Int) S(Gen), E|Mem|CRc|Refs) \
393 O(StMemNT, ND, S(PtrToGen) \
394 C(Int) S(Gen), E|Mem|CRc) \
395 O(StProp, ND, S(Obj) S(Int) S(Gen), E|Mem|CRc|Refs) \
396 O(StPropNT, ND, S(Obj) S(Int) S(Gen), E|Mem|CRc) \
397 O(StLoc, ND, S(FramePtr) S(Gen), E|Mem|CRc) \
398 O(StLocNT, ND, S(FramePtr) S(Gen), E|Mem|CRc) \
399 O(StRef, DBox(1), S(BoxedCell) S(Cell), E|Mem|CRc|Refs) \
400 O(StRefNT, DBox(1), S(BoxedCell) S(Cell), E|Mem|CRc) \
401 O(StRaw, ND, SUnk, E|Mem) \
402 O(LdStaticLocCached, D(BoxedCell), C(CacheHandle), NF) \
403 O(StaticLocInit, D(BoxedCell), CStr \
405 S(Cell), PRc|E|N|Mem) \
406 O(StaticLocInitCached, D(BoxedCell), CStr \
409 C(CacheHandle), PRc|E|N|Mem) \
410 O(SpillStack, D(StkPtr), S(StkPtr) C(Int) SSpills, CRc) \
411 O(SpillFrame, D(StkPtr), S(StkPtr) \
413 S(Func,FuncCls,FuncCtx,Null) \
414 S(Ctx,Cls,InitNull), CRc) \
415 O(CufIterSpillFrame, D(StkPtr), S(StkPtr) \
417 O(ExceptionBarrier, D(StkPtr), S(StkPtr), E) \
418 O(ReqBindJmp, ND, NA, T|E) \
419 O(ReqBindJmpNoIR, ND, NA, T|E) \
420 O(ReqRetranslateNoIR, ND, NA, T|E) \
421 O(ReqRetranslate, ND, NA, T|E) \
422 O(SyncABIRegs, ND, S(FramePtr) S(StkPtr), E) \
423 O(Mov, DofS(0), SUnk, C|P) \
424 O(LdAddr, DofS(0), SUnk, C) \
425 O(IncRef, DofS(0), S(Gen), Mem|PRc|P) \
426 O(DecRefLoc, ND, S(FramePtr), N|E|Mem|Refs) \
427 O(DecRefStack, ND, S(StkPtr), N|E|Mem|Refs) \
428 O(DecRefThis, ND, S(FramePtr), N|E|Mem|Refs) \
429 O(GenericRetDecRefs, D(StkPtr), S(FramePtr) C(Int), E|N|Mem|Refs) \
430 O(DecRef, ND, S(Gen), N|E|Mem|CRc|Refs|K) \
431 O(DecRefMem, ND, S(PtrToGen) \
432 C(Int), N|E|Mem|CRc|Refs) \
433 O(DecRefNZ, ND, S(Gen), Mem|CRc) \
434 O(DecRefNZOrBranch, ND, S(Gen), Mem|CRc) \
435 O(DefLabel, DMulti, NA, E) \
436 O(DefInlineFP, D(FramePtr), S(StkPtr) S(StkPtr), NF) \
437 O(InlineReturn, ND, S(FramePtr), E) \
438 O(DefFP, D(FramePtr), NA, E) \
439 O(DefSP, D(StkPtr), S(FramePtr), E) \
440 O(ReDefSP, D(StkPtr), S(FramePtr) S(StkPtr), NF) \
441 O(StashGeneratorSP, D(StkPtr), S(StkPtr), NF) \
442 O(ReDefGeneratorSP, D(StkPtr), S(StkPtr), NF) \
443 O(VerifyParamCls, ND, S(Cls) \
446 C(Int), E|N|Mem|Refs|Er) \
447 O(VerifyParamCallable, ND, S(Cell) C(Int), E|N|Mem|Refs|Er) \
448 O(VerifyParamFail, ND, C(Int), E|N|Mem|Refs|Er) \
449 O(RaiseUninitLoc, ND, S(Str), E|N|Mem|Refs|Er) \
450 O(WarnNonObjProp, ND, NA, E|N|Refs|Er|Mem) \
451 O(ThrowNonObjProp, ND, NA, T|E|N|Refs|Er|Mem) \
452 O(RaiseUndefProp, ND, S(Obj) CStr, E|N|Refs|Er|Mem) \
453 O(PrintStr, ND, S(Str), E|N|Mem|CRc) \
454 O(PrintInt, ND, S(Int), E|N|Mem|CRc) \
455 O(PrintBool, ND, S(Bool), E|N|Mem|CRc) \
456 O(AddElemStrKey, D(Arr), S(Arr) \
458 S(Cell), N|Mem|CRc|PRc|Refs) \
459 O(AddElemIntKey, D(Arr), S(Arr) \
461 S(Cell), N|Mem|CRc|PRc|Refs) \
462 O(AddNewElem, D(Arr), SUnk, N|Mem|CRc|PRc) \
463 /* name dstinfo srcinfo flags */ \
464 O(Concat, D(Str), S(Gen) S(Gen), N|Mem|CRc|PRc|Refs) \
465 O(ArrayAdd, D(Arr), S(Arr) S(Arr), N|Mem|CRc|PRc) \
466 O(AKExists, D(Bool), S(Cell) S(Cell), C|N) \
467 O(InterpOne, D(StkPtr), S(FramePtr) S(StkPtr), \
469 O(InterpOneCF, ND, S(FramePtr) S(StkPtr) \
470 C(Int), T|E|N|Mem|Refs|Er) \
471 O(Spill, DofS(0), SUnk, Mem) \
472 O(Reload, DofS(0), SUnk, Mem) \
473 O(CreateContFunc, D(Obj), C(Func) C(Func), E|N|PRc) \
474 O(CreateContMeth, D(Obj), C(Func) C(Func) S(Ctx), E|N|PRc) \
475 O(ContEnter, ND, S(FramePtr) \
476 S(TCA) C(Int) S(FramePtr), E|Mem) \
477 O(ContPreNext, ND, S(Obj), E|Mem) \
478 O(ContStartedCheck, ND, S(Obj), E) \
479 O(ContSetRunning, ND, S(Obj) \
481 O(ContDone, ND, S(Obj), E|Mem) \
482 O(ContValid, D(Bool), S(Obj), E) \
483 O(ContIncKey, ND, S(Obj), E|Mem) \
484 O(ContUpdateIdx, ND, S(Obj) \
486 O(IterInit, D(Bool), S(Arr,Obj) \
489 C(Int), E|N|Mem|Refs|CRc) \
490 O(IterInitK, D(Bool), S(Arr,Obj) \
494 C(Int), E|N|Mem|Refs|CRc) \
495 O(IterNext, D(Bool), S(FramePtr) \
496 C(Int) C(Int), E|N|Mem|Refs) \
497 O(IterNextK, D(Bool), S(FramePtr) \
498 C(Int) C(Int) C(Int), E|N|Mem|Refs) \
499 O(WIterInit, D(Bool), S(Arr,Obj) \
502 C(Int), E|N|Mem|Refs|CRc) \
503 O(WIterInitK, D(Bool), S(Arr,Obj) \
507 C(Int), E|N|Mem|Refs|CRc) \
508 O(WIterNext, D(Bool), S(FramePtr) \
509 C(Int) C(Int), E|N|Mem|Refs) \
510 O(WIterNextK, D(Bool), S(FramePtr) \
511 C(Int) C(Int) C(Int), E|N|Mem|Refs) \
512 O(MIterInit, D(Bool), S(BoxedCell) \
515 C(Int), E|N|Mem|Refs|CRc) \
516 O(MIterInitK, D(Bool), S(BoxedCell) \
520 C(Int), E|N|Mem|Refs|CRc) \
521 O(MIterNext, D(Bool), S(FramePtr) \
522 C(Int) C(Int), E|N|Mem|Refs) \
523 O(MIterNextK, D(Bool), S(FramePtr) \
524 C(Int) C(Int) C(Int), E|N|Mem|Refs) \
525 O(IterFree, ND, S(FramePtr), E|N|Mem|Refs) \
526 O(MIterFree, ND, S(FramePtr), E|N|Mem|Refs) \
527 O(DecodeCufIter, D(Bool), S(Arr,Obj,Str) \
528 S(FramePtr), E|N|Mem|Refs) \
529 O(CIterFree, ND, S(FramePtr), E|N|Mem|Refs) \
530 O(DefMIStateBase, D(PtrToCell), NA, NF) \
531 O(BaseG, D(PtrToGen), C(TCA) \
533 S(PtrToCell), E|N|Mem|Refs|Er) \
534 O(PropX, D(PtrToGen), C(TCA) \
538 S(PtrToCell), E|N|Mem|Refs|Er) \
539 O_STK(PropDX, D(PtrToGen), C(TCA) \
543 S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
544 O(CGetProp, D(Cell), C(TCA) \
548 S(PtrToCell), E|N|Mem|Refs|Er) \
549 O_STK(VGetProp, D(BoxedCell), C(TCA) \
553 S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
554 O_STK(BindProp, ND, C(TCA) \
559 S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
560 O_STK(SetProp, ND, C(TCA) \
564 S(Cell), VProp|E|N|Mem|Refs|Er) \
565 O(UnsetProp, ND, C(TCA) \
568 S(Cell), E|N|Mem|Refs|Er) \
569 O_STK(SetOpProp, D(Cell), C(TCA) \
574 C(Int), VProp|E|N|Mem|Refs|Er) \
575 O_STK(IncDecProp, D(Cell), C(TCA) \
579 C(Int), VProp|E|N|Mem|Refs|Er) \
580 O(EmptyProp, D(Bool), C(TCA) \
583 S(Cell), E|N|Mem|Refs|Er) \
584 O(IssetProp, D(Bool), C(TCA) \
587 S(Cell), E|N|Mem|Refs|Er) \
588 O(ElemX, D(PtrToGen), C(TCA) \
591 S(PtrToCell), E|N|Mem|Refs|Er) \
592 O_STK(ElemDX, D(PtrToGen), C(TCA) \
595 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
596 O_STK(ElemUX, D(PtrToGen), C(TCA) \
599 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
600 O(ArrayGet, D(Cell), C(TCA) \
602 S(Int,Str), C|N|PRc|Refs|Mem|Er)\
603 O(VectorGet, D(Cell), C(TCA) \
605 S(Int), E|N|Mem|Refs|Er) \
606 O(PairGet, D(Cell), C(TCA) \
608 S(Int), E|N|Mem|Refs|Er) \
609 O(MapGet, D(Cell), C(TCA) \
611 S(Int,Str), E|N|Mem|Refs|Er) \
612 O(StableMapGet, D(Cell), C(TCA) \
614 S(Int,Str), E|N|Mem|Refs|Er) \
615 O(CGetElem, D(Cell), C(TCA) \
618 S(PtrToCell), E|N|Mem|Refs|Er) \
619 O_STK(VGetElem, D(BoxedCell), C(TCA) \
622 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
623 O_STK(BindElem, ND, C(TCA) \
627 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
628 O(ArraySet, D(Arr), C(TCA) \
631 S(Cell), E|N|PRc|CRc|Refs|Mem|K) \
632 O(VectorSet, ND, C(TCA) \
635 S(Cell), E|N|Mem|Refs|Er) \
636 O(MapSet, ND, C(TCA) \
639 S(Cell), E|N|Mem|Refs|Er) \
640 O(StableMapSet, ND, C(TCA) \
643 S(Cell), E|N|Mem|Refs|Er) \
644 O(ArraySetRef, ND, C(TCA) \
648 S(BoxedArr),E|N|PRc|CRc|Refs|Mem|K) \
649 O_STK(SetElem, DSetElem, C(TCA) \
652 S(Cell), VElem|E|N|Mem|Refs|Er) \
653 O_STK(SetWithRefElem, ND, C(TCA) \
657 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
658 O_STK(UnsetElem, ND, C(TCA) \
660 S(Cell), VElem|E|N|Mem|Refs|Er) \
661 O_STK(SetOpElem, D(Cell), C(TCA) \
665 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
666 O_STK(IncDecElem, D(Cell), C(TCA) \
669 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
670 O_STK(SetNewElem, ND, S(PtrToGen) \
671 S(Cell), VElem|E|N|Mem|Refs|Er) \
672 O_STK(SetWithRefNewElem, ND, C(TCA) \
675 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
676 O_STK(BindNewElem, ND, S(PtrToGen) \
678 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
679 O(ArrayIsset, D(Bool), C(TCA) \
681 S(Int,Str), E|N|Mem|Refs|Er) \
682 O(VectorIsset, D(Bool), C(TCA) \
684 S(Int), E|N|Mem|Refs) \
685 O(PairIsset, D(Bool), C(TCA) \
687 S(Int), E|N|Mem|Refs) \
688 O(MapIsset, D(Bool), C(TCA) \
690 S(Int,Str), E|N|Mem|Refs) \
691 O(StableMapIsset, D(Bool), C(TCA) \
693 S(Int,Str), E|N|Mem|Refs) \
694 O(IssetElem, D(Bool), C(TCA) \
697 S(PtrToCell), E|N|Mem|Refs|Er) \
698 O(EmptyElem, D(Bool), C(TCA) \
701 S(PtrToCell), E|N|Mem|Refs|Er) \
702 O(IncStat, ND, C(Int) C(Int) C(Bool), E|Mem) \
703 O(IncStatGrouped, ND, CStr CStr C(Int), E|N|Mem) \
704 O(IncTransCounter, ND, NA, E) \
705 O(ArrayIdx, D(Cell), C(TCA) \
708 S(Cell), E|N|CRc|PRc|Refs|Mem) \
709 O(DbgAssertRefCount, ND, S(Counted,StaticStr,StaticArr), N|E) \
710 O(DbgAssertPtr, ND, S(PtrToGen), N|E) \
711 O(DbgAssertType, ND, S(Cell), E) \
715 enum Opcode
: uint16_t {
716 #define O(name, dsts, srcs, flags) name,
724 * A "query op" is any instruction returning Type::Bool that is both
725 * branch-fusable and negateable.
727 bool isQueryOp(Opcode opc
);
730 * A "cmp ops" is query op that takes exactly two arguments of type
733 bool isCmpOp(Opcode opc
);
736 * A "query jump op" is a conditional jump instruction that
737 * corresponds to one of the query op instructions.
739 bool isQueryJmpOp(Opcode opc
);
742 * Translate a query op into a conditional jump that does the same
743 * test (a "query jump op").
745 * Pre: isQueryOp(opc)
747 Opcode
queryToJmpOp(Opcode opc
);
750 * Translate a "query jump op" to a query op.
752 * Pre: isQueryJmpOp(opc);
754 Opcode
queryJmpToQueryOp(Opcode opc
);
757 * Convert a jump operation to its corresponding conditional
760 * Pre: opc is a conditional jump.
762 Opcode
jmpToReqBindJmp(Opcode opc
);
765 * Return the opcode that corresponds to negation of opc.
767 Opcode
negateQueryOp(Opcode opc
);
770 * Return the opcode that corresponds to commuting the arguments of
773 Opcode
commuteQueryOp(Opcode opc
);
775 const char* opcodeName(Opcode opcode
);
777 enum OpcodeFlag
: uint64_t {
781 Essential
= 1ULL << 2,
782 MemEffects
= 1ULL << 3,
783 CallsNative
= 1ULL << 4,
784 ConsumesRC
= 1ULL << 5,
785 ProducesRC
= 1ULL << 6,
786 MayModifyRefs
= 1ULL << 7,
788 MayRaiseError
= 1ULL << 9,
789 Terminal
= 1ULL << 10, // has no next instruction
790 NaryDest
= 1ULL << 11, // has 0 or more destinations
791 HasExtra
= 1ULL << 12,
792 Passthrough
= 1ULL << 13,
793 KillsSources
= 1ULL << 14,
794 ModifiesStack
= 1ULL << 15,
795 HasStackVersion
= 1ULL << 16,
796 VectorProp
= 1ULL << 17,
797 VectorElem
= 1ULL << 18,
800 bool opcodeHasFlags(Opcode opc
, uint64_t flags
);
801 Opcode
getStackModifyingOpcode(Opcode opc
);
806 * returns the Type type for a C++ type that may be used with
810 // The only interesting case is int/bool disambiguation. Enums are
813 typename
std::enable_if
<
814 std::is_integral
<T
>::value
|| std::is_enum
<T
>::value
,
816 >::type
typeForConst(T
) {
817 return std::is_same
<T
,bool>::value
? Type::Bool
: Type::Int
;
820 inline Type
typeForConst(const StringData
*) { return Type::StaticStr
; }
821 inline Type
typeForConst(const NamedEntity
*) { return Type::NamedEntity
; }
822 inline Type
typeForConst(const Func
*) { return Type::Func
; }
823 inline Type
typeForConst(const Class
*) { return Type::Cls
; }
824 inline Type
typeForConst(const TypedValue
*) { return Type::PtrToGen
; }
825 inline Type
typeForConst(TCA
) { return Type::TCA
; }
826 inline Type
typeForConst(double) { return Type::Dbl
; }
827 inline Type
typeForConst(SetOpOp
) { return Type::Int
; }
828 inline Type
typeForConst(IncDecOp
) { return Type::Int
; }
829 inline Type
typeForConst(const ArrayData
* ad
) {
830 assert(ad
->isStatic());
831 // TODO: Task #2124292, Reintroduce StaticArr
835 bool cmpOpTypesMayReenter(Opcode
, Type t0
, Type t1
);
841 ContLabel
, ContIndex
, ContARPtr
,
842 StrLen
, FuncNumParams
, ContEntry
, MisCtx
, MaxKind
845 static RawMemSlot
& Get(Kind k
) {
847 case ContLabel
: return GetContLabel();
848 case ContIndex
: return GetContIndex();
849 case ContARPtr
: return GetContARPtr();
850 case StrLen
: return GetStrLen();
851 case FuncNumParams
: return GetFuncNumParams();
852 case ContEntry
: return GetContEntry();
853 case MisCtx
: return GetMisCtx();
854 default: not_reached();
858 int64_t offset() const { return m_offset
; }
859 int32_t size() const { return m_size
; }
860 Type
type() const { return m_type
; }
861 bool allowExtra() const { return m_allowExtra
; }
864 RawMemSlot(int64_t offset
, int32_t size
, Type type
, bool allowExtra
= false)
865 : m_offset(offset
), m_size(size
), m_type(type
), m_allowExtra(allowExtra
) { }
867 static RawMemSlot
& GetContLabel() {
868 static RawMemSlot
m(CONTOFF(m_label
), Transl::sz::dword
, Type::Int
);
871 static RawMemSlot
& GetContIndex() {
872 static RawMemSlot
m(CONTOFF(m_index
), Transl::sz::qword
, Type::Int
);
875 static RawMemSlot
& GetContARPtr() {
876 static RawMemSlot
m(CONTOFF(m_arPtr
), Transl::sz::qword
, Type::StkPtr
);
879 static RawMemSlot
& GetStrLen() {
880 static RawMemSlot
m(StringData::sizeOffset(), Transl::sz::dword
, Type::Int
);
883 static RawMemSlot
& GetFuncNumParams() {
884 static RawMemSlot
m(Func::numParamsOff(), Transl::sz::dword
, Type::Int
);
887 static RawMemSlot
& GetContEntry() {
889 Func::prologueTableOff() + sizeof(HPHP::Transl::TCA
),
890 Transl::sz::qword
, Type::TCA
);
893 static RawMemSlot
& GetMisCtx() {
894 using namespace HPHP::Transl
;
895 static RawMemSlot
m(HHIR_MISOFF(ctx
), Transl::sz::qword
, Type::Cls
);
902 bool m_allowExtra
; // Used as a flag to ensure that extra offets are
903 // only used with RawMemSlots that support it
915 bool isRefCounted(SSATmp
* opnd
);
918 typedef Range
<SSATmp
**> SrcRange
;
919 typedef Range
<SSATmp
*> DstRange
;
922 * Given an SSATmp of type Cls, try to find the name of the class.
923 * Returns nullptr if can't find it.
925 const StringData
* findClassName(SSATmp
* cls
);
928 * Return the output type from a given IRInstruction.
930 * The destination type is always predictable from the types of the inputs, any
931 * type parameters to the instruction, and the id of the dest.
933 Type
outputType(const IRInstruction
*, int dstId
= 0);
936 * Assert that an instruction has operands of allowed types.
938 void assertOperandTypes(const IRInstruction
*);
941 int vectorBaseIdx(Opcode opc
);
942 int vectorKeyIdx(Opcode opc
);
943 int vectorValIdx(Opcode opc
);
944 int vectorBaseIdx(const IRInstruction
* inst
);
945 int vectorKeyIdx(const IRInstruction
* inst
);
946 int vectorValIdx(const IRInstruction
* inst
);
948 struct VectorEffects
{
949 static bool supported(Opcode op
);
950 static bool supported(const IRInstruction
* inst
);
953 * VectorEffects::get is used to allow multiple different consumers to deal
954 * with the side effects of vector instructions. It takes an instruction and
955 * a series of callbacks, each of which will be called when the instruction
956 * has a certain effect:
958 * storeLocValue: This will be called when a local's value is changed.
959 * setLocType: This will be called when a local's type changes and the
960 * new value is not known.
962 typedef std::function
<void(uint32_t, SSATmp
*)> StoreLocFunc
;
963 typedef std::function
<void(uint32_t, Type
)> SetLocTypeFunc
;
964 static void get(const IRInstruction
*,
965 StoreLocFunc storeLocValue
,
966 SetLocTypeFunc setLocType
);
968 explicit VectorEffects(const IRInstruction
* inst
);
969 VectorEffects(Opcode op
, Type base
, Type key
, Type val
);
970 VectorEffects(Opcode op
, SSATmp
* base
, SSATmp
* key
, SSATmp
* val
);
971 VectorEffects(Opcode opc
, const std::vector
<SSATmp
*>& srcs
);
974 bool baseTypeChanged
;
978 void init(const Opcode op
, const Type base
, const Type key
, const Type val
);
982 /* afterCall is the address after the call instruction that this catch trace
983 * belongs to. It's the key used to look up catch traces by the
984 * unwinder, since it's the value of %rip during unwinding. */
987 /* savedRegs contains the caller-saved registers that were pushed onto the
988 * C++ stack at the time of the call. The catch trace will pop these
989 * registers (in the same order as PhysRegSaver's destructor) before doing
990 * any real work to restore the register state from before the call. */
993 /* rspOffset is the number of bytes pushed on the C++ stack after the
994 * registers in savedRegs were saved, typically from function calls with >6
995 * arguments. The catch trace will adjust rsp by this amount before popping
996 * anything in savedRegs. */
1000 typedef folly::Range
<TCA
> TcaRange
;
1003 * Run all optimization passes on this trace
1005 void optimizeTrace(IRTrace
*, IRFactory
* irFactory
);
1008 * Counts the number of cells a SpillStack will logically push. (Not
1009 * including the number it pops.) That is, for each SSATmp in the
1010 * spill sources, this totals up whether it is an ActRec or a cell.
1012 int32_t spillValueCells(IRInstruction
* spillStack
);
1014 bool isConvIntOrPtrToBool(IRInstruction
* instr
);
1019 template<> struct hash
<HPHP::JIT::Opcode
> {
1020 size_t operator()(HPHP::JIT::Opcode op
) const { return op
; }
1022 template<> struct hash
<HPHP::JIT::Type
> {
1023 size_t operator()(HPHP::JIT::Type t
) const { return t
.hash(); }