Clean up VectorEffects::init
[hiphop-php.git] / hphp / runtime / vm / jit / ir.h
bloba80d49ee1ae2bc0019a7061fd2812160467935cc
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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_
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/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"
53 namespace HPHP {
54 // forward declaration
55 class StringData;
56 namespace JIT {
58 using HPHP::Transl::TCA;
59 using HPHP::Transl::RegSet;
60 using HPHP::Transl::PhysReg;
61 using HPHP::Transl::ConditionCode;
63 struct IRInstruction;
64 struct SSATmp;
65 struct Block;
66 struct IRTrace;
68 class FailedIRGen : public std::runtime_error {
69 public:
70 const char* const file;
71 const int line;
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())
77 , file(_file)
78 , line(_line)
79 , func(_func)
83 class FailedCodeGen : public std::runtime_error {
84 public:
85 const char* file;
86 const int line;
87 const char* func;
88 const Offset bcOff;
89 const Func* vmFunc;
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 {}. {}@{}",
94 _file, _line, _func,
95 _vmFunc->fullName()->data(), _bcOff)
96 .str())
97 , file(_file)
98 , line(_line)
99 , func(_func)
100 , bcOff(_bcOff)
101 , vmFunc(_vmFunc)
105 #define SPUNT(instr) do { \
106 throw FailedIRGen(__FILE__, __LINE__, instr); \
107 } while(0)
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.
117 * dstinfo:
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
131 * sources
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
140 * srcinfo:
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
153 * flags:
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:
164 * NF no flags
165 * C canCSE
166 * E isEssential
167 * N callsNative
168 * PRc producesRC
169 * CRc consumesRC
170 * Refs mayModifyRefs
171 * Er mayRaiseError
172 * Mem hasMemEffects
173 * T isTerminal
174 * P passthrough
175 * K killsSource
176 * VProp VectorProp
177 * VElem VectorElem
180 #define O_STK(name, dst, src, flags) \
181 O(name, dst, src, StkFlags(flags)) \
182 O(name ## Stk, DStk(dst), src, flags)
184 #define IR_OPCODES \
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) \
199 S(Int) \
200 S(Int) \
201 S(Int) \
202 S(Int), E) \
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) \
343 C(Str) \
344 C(NamedEntity) \
345 S(FramePtr) \
346 S(StkPtr), N|C|E|Refs|Er|Mem) \
347 O(LdClsMethodFCache, D(FuncCtx), C(Cls) \
348 CStr \
349 S(Obj,Cls,Ctx) \
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) \
374 C(Int) \
375 S(FramePtr) \
376 S(StkPtr), Mem|N) \
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) \
387 S(FramePtr) \
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 \
404 S(FramePtr) \
405 S(Cell), PRc|E|N|Mem) \
406 O(StaticLocInitCached, D(BoxedCell), CStr \
407 S(FramePtr) \
408 S(Cell) \
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) \
412 S(FramePtr) \
413 S(Func,FuncCls,FuncCtx,Null) \
414 S(Ctx,Cls,InitNull), CRc) \
415 O(CufIterSpillFrame, D(StkPtr), S(StkPtr) \
416 S(FramePtr), NF) \
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) \
444 S(Cls) \
445 C(Int) \
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) \
457 S(Str) \
458 S(Cell), N|Mem|CRc|PRc|Refs) \
459 O(AddElemIntKey, D(Arr), S(Arr) \
460 S(Int) \
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), \
468 E|N|Mem|Refs|Er) \
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) \
480 C(Bool), E|Mem) \
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) \
485 S(Int), E|Mem) \
486 O(IterInit, D(Bool), S(Arr,Obj) \
487 S(FramePtr) \
488 C(Int) \
489 C(Int), E|N|Mem|Refs|CRc) \
490 O(IterInitK, D(Bool), S(Arr,Obj) \
491 S(FramePtr) \
492 C(Int) \
493 C(Int) \
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) \
500 S(FramePtr) \
501 C(Int) \
502 C(Int), E|N|Mem|Refs|CRc) \
503 O(WIterInitK, D(Bool), S(Arr,Obj) \
504 S(FramePtr) \
505 C(Int) \
506 C(Int) \
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) \
513 S(FramePtr) \
514 C(Int) \
515 C(Int), E|N|Mem|Refs|CRc) \
516 O(MIterInitK, D(Bool), S(BoxedCell) \
517 S(FramePtr) \
518 C(Int) \
519 C(Int) \
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) \
532 S(Str) \
533 S(PtrToCell), E|N|Mem|Refs|Er) \
534 O(PropX, D(PtrToGen), C(TCA) \
535 C(Cls) \
536 S(Obj,PtrToGen) \
537 S(Cell) \
538 S(PtrToCell), E|N|Mem|Refs|Er) \
539 O_STK(PropDX, D(PtrToGen), C(TCA) \
540 C(Cls) \
541 S(Obj,PtrToGen) \
542 S(Cell) \
543 S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
544 O(CGetProp, D(Cell), C(TCA) \
545 C(Cls) \
546 S(Obj,PtrToGen) \
547 S(Cell) \
548 S(PtrToCell), E|N|Mem|Refs|Er) \
549 O_STK(VGetProp, D(BoxedCell), C(TCA) \
550 C(Cls) \
551 S(Obj,PtrToGen) \
552 S(Cell) \
553 S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
554 O_STK(BindProp, ND, C(TCA) \
555 C(Cls) \
556 S(Obj,PtrToGen) \
557 S(Cell) \
558 S(BoxedCell) \
559 S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
560 O_STK(SetProp, ND, C(TCA) \
561 C(Cls) \
562 S(Obj,PtrToGen) \
563 S(Cell) \
564 S(Cell), VProp|E|N|Mem|Refs|Er) \
565 O(UnsetProp, ND, C(TCA) \
566 C(Cls) \
567 S(Obj,PtrToGen) \
568 S(Cell), E|N|Mem|Refs|Er) \
569 O_STK(SetOpProp, D(Cell), C(TCA) \
570 S(Obj,PtrToGen) \
571 S(Cell) \
572 S(Cell) \
573 S(PtrToCell) \
574 C(Int), VProp|E|N|Mem|Refs|Er) \
575 O_STK(IncDecProp, D(Cell), C(TCA) \
576 S(Obj,PtrToGen) \
577 S(Cell) \
578 S(PtrToCell) \
579 C(Int), VProp|E|N|Mem|Refs|Er) \
580 O(EmptyProp, D(Bool), C(TCA) \
581 C(Cls) \
582 S(Obj,PtrToGen) \
583 S(Cell), E|N|Mem|Refs|Er) \
584 O(IssetProp, D(Bool), C(TCA) \
585 C(Cls) \
586 S(Obj,PtrToGen) \
587 S(Cell), E|N|Mem|Refs|Er) \
588 O(ElemX, D(PtrToGen), C(TCA) \
589 S(PtrToGen) \
590 S(Cell) \
591 S(PtrToCell), E|N|Mem|Refs|Er) \
592 O_STK(ElemDX, D(PtrToGen), C(TCA) \
593 S(PtrToGen) \
594 S(Cell) \
595 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
596 O_STK(ElemUX, D(PtrToGen), C(TCA) \
597 S(PtrToGen) \
598 S(Cell) \
599 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
600 O(ArrayGet, D(Cell), C(TCA) \
601 S(Arr) \
602 S(Int,Str), C|N|PRc|Refs|Mem|Er)\
603 O(VectorGet, D(Cell), C(TCA) \
604 S(Obj) \
605 S(Int), E|N|Mem|Refs|Er) \
606 O(PairGet, D(Cell), C(TCA) \
607 S(Obj) \
608 S(Int), E|N|Mem|Refs|Er) \
609 O(MapGet, D(Cell), C(TCA) \
610 S(Obj) \
611 S(Int,Str), E|N|Mem|Refs|Er) \
612 O(StableMapGet, D(Cell), C(TCA) \
613 S(Obj) \
614 S(Int,Str), E|N|Mem|Refs|Er) \
615 O(CGetElem, D(Cell), C(TCA) \
616 S(PtrToGen) \
617 S(Cell) \
618 S(PtrToCell), E|N|Mem|Refs|Er) \
619 O_STK(VGetElem, D(BoxedCell), C(TCA) \
620 S(PtrToGen) \
621 S(Cell) \
622 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
623 O_STK(BindElem, ND, C(TCA) \
624 S(PtrToGen) \
625 S(Cell) \
626 S(BoxedCell) \
627 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
628 O(ArraySet, D(Arr), C(TCA) \
629 S(Arr) \
630 S(Int,Str) \
631 S(Cell), E|N|PRc|CRc|Refs|Mem|K) \
632 O(VectorSet, ND, C(TCA) \
633 S(Obj) \
634 S(Int) \
635 S(Cell), E|N|Mem|Refs|Er) \
636 O(MapSet, ND, C(TCA) \
637 S(Obj) \
638 S(Int,Str) \
639 S(Cell), E|N|Mem|Refs|Er) \
640 O(StableMapSet, ND, C(TCA) \
641 S(Obj) \
642 S(Int,Str) \
643 S(Cell), E|N|Mem|Refs|Er) \
644 O(ArraySetRef, ND, C(TCA) \
645 S(Arr) \
646 S(Int,Str) \
647 S(Cell) \
648 S(BoxedArr),E|N|PRc|CRc|Refs|Mem|K) \
649 O_STK(SetElem, DSetElem, C(TCA) \
650 S(PtrToGen) \
651 S(Cell) \
652 S(Cell), VElem|E|N|Mem|Refs|Er) \
653 O_STK(SetWithRefElem, ND, C(TCA) \
654 S(PtrToGen) \
655 S(Cell) \
656 S(PtrToGen) \
657 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
658 O_STK(UnsetElem, ND, C(TCA) \
659 S(PtrToGen) \
660 S(Cell), VElem|E|N|Mem|Refs|Er) \
661 O_STK(SetOpElem, D(Cell), C(TCA) \
662 S(PtrToGen) \
663 S(Cell) \
664 S(Cell) \
665 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
666 O_STK(IncDecElem, D(Cell), C(TCA) \
667 S(PtrToGen) \
668 S(Cell) \
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) \
673 S(PtrToGen) \
674 S(PtrToGen) \
675 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
676 O_STK(BindNewElem, ND, S(PtrToGen) \
677 S(BoxedCell) \
678 S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
679 O(ArrayIsset, D(Bool), C(TCA) \
680 S(Arr) \
681 S(Int,Str), E|N|Mem|Refs|Er) \
682 O(VectorIsset, D(Bool), C(TCA) \
683 S(Obj) \
684 S(Int), E|N|Mem|Refs) \
685 O(PairIsset, D(Bool), C(TCA) \
686 S(Obj) \
687 S(Int), E|N|Mem|Refs) \
688 O(MapIsset, D(Bool), C(TCA) \
689 S(Obj) \
690 S(Int,Str), E|N|Mem|Refs) \
691 O(StableMapIsset, D(Bool), C(TCA) \
692 S(Obj) \
693 S(Int,Str), E|N|Mem|Refs) \
694 O(IssetElem, D(Bool), C(TCA) \
695 S(PtrToGen) \
696 S(Cell) \
697 S(PtrToCell), E|N|Mem|Refs|Er) \
698 O(EmptyElem, D(Bool), C(TCA) \
699 S(PtrToGen) \
700 S(Cell) \
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) \
706 S(Arr) \
707 S(Int,Str) \
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) \
712 O(Nop, ND, NA, NF) \
713 /* */
715 enum Opcode : uint16_t {
716 #define O(name, dsts, srcs, flags) name,
717 IR_OPCODES
718 #undef O
720 IR_NUM_OPCODES
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
731 * Gen.
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
758 * ReqBindJmp.
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
771 * opc.
773 Opcode commuteQueryOp(Opcode opc);
775 const char* opcodeName(Opcode opcode);
777 enum OpcodeFlag : uint64_t {
778 NoFlags = 0,
779 HasDest = 1ULL << 0,
780 CanCSE = 1ULL << 1,
781 Essential = 1ULL << 2,
782 MemEffects = 1ULL << 3,
783 CallsNative = 1ULL << 4,
784 ConsumesRC = 1ULL << 5,
785 ProducesRC = 1ULL << 6,
786 MayModifyRefs = 1ULL << 7,
787 // Unused
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);
804 * typeForConst(T)
806 * returns the Type type for a C++ type that may be used with
807 * ConstData.
810 // The only interesting case is int/bool disambiguation. Enums are
811 // treated as ints.
812 template<class T>
813 typename std::enable_if<
814 std::is_integral<T>::value || std::is_enum<T>::value,
815 Type
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
832 return Type::Arr;
835 bool cmpOpTypesMayReenter(Opcode, Type t0, Type t1);
837 class RawMemSlot {
838 public:
840 enum Kind {
841 ContLabel, ContIndex, ContARPtr,
842 StrLen, FuncNumParams, ContEntry, MisCtx, MaxKind
845 static RawMemSlot& Get(Kind k) {
846 switch (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; }
863 private:
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);
869 return m;
871 static RawMemSlot& GetContIndex() {
872 static RawMemSlot m(CONTOFF(m_index), Transl::sz::qword, Type::Int);
873 return m;
875 static RawMemSlot& GetContARPtr() {
876 static RawMemSlot m(CONTOFF(m_arPtr), Transl::sz::qword, Type::StkPtr);
877 return m;
879 static RawMemSlot& GetStrLen() {
880 static RawMemSlot m(StringData::sizeOffset(), Transl::sz::dword, Type::Int);
881 return m;
883 static RawMemSlot& GetFuncNumParams() {
884 static RawMemSlot m(Func::numParamsOff(), Transl::sz::dword, Type::Int);
885 return m;
887 static RawMemSlot& GetContEntry() {
888 static RawMemSlot m(
889 Func::prologueTableOff() + sizeof(HPHP::Transl::TCA),
890 Transl::sz::qword, Type::TCA);
891 return m;
893 static RawMemSlot& GetMisCtx() {
894 using namespace HPHP::Transl;
895 static RawMemSlot m(HHIR_MISOFF(ctx), Transl::sz::qword, Type::Cls);
896 return m;
899 int64_t m_offset;
900 int32_t m_size;
901 Type m_type;
902 bool m_allowExtra; // Used as a flag to ensure that extra offets are
903 // only used with RawMemSlots that support it
906 class SSATmp;
907 class IRTrace;
908 class CodeGenerator;
909 struct AsmInfo;
910 class IRFactory;
911 class Simplifier;
912 struct LifetimeInfo;
913 struct RegAllocInfo;
915 bool isRefCounted(SSATmp* opnd);
917 using folly::Range;
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);
973 Type baseType;
974 bool baseTypeChanged;
975 bool baseValChanged;
977 private:
978 void init(const Opcode op, const Type base, const Type key, const Type val);
981 struct CatchInfo {
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. */
985 TCA afterCall;
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. */
991 RegSet savedRegs;
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. */
997 Offset rspOffset;
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);
1018 namespace std {
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(); }
1027 #endif