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 #include "hphp/runtime/vm/jit/ir-opcode.h"
19 #include "hphp/runtime/base/string-data.h"
20 #include "hphp/runtime/vm/jit/cfg.h"
21 #include "hphp/runtime/vm/jit/extra-data.h"
22 #include "hphp/runtime/vm/jit/ir-instruction.h"
23 #include "hphp/runtime/vm/jit/ir-unit.h"
24 #include "hphp/runtime/vm/jit/ssa-tmp.h"
25 #include "hphp/runtime/vm/jit/print.h"
26 #include "hphp/runtime/vm/jit/type.h"
27 #include "hphp/runtime/vm/runtime.h"
29 #include "hphp/util/trace.h"
31 // Include last to localize effects to this file
32 #include "hphp/util/assert-throw.h"
34 namespace HPHP
{ namespace jit
{
35 ///////////////////////////////////////////////////////////////////////////////
40 #define Er MayRaiseError
41 #define PRc ProducesRC
42 #define CRc ConsumesRC
46 #define MProp MInstrProp
47 #define MElem MInstrElem
51 #define DofS(n) HasDest
52 #define DRefineS(n) HasDest
53 #define DParamMayRelax HasDest
54 #define DParam HasDest
55 #define DParamPtr(k) HasDest
56 #define DUnboxPtr HasDest
57 #define DBoxPtr HasDest
58 #define DAllocObj HasDest
59 #define DArrElem HasDest
60 #define DArrPacked HasDest
64 #define DMulti NaryDest
65 #define DSetElem HasDest
66 #define DPtrToParam HasDest
67 #define DBuiltin HasDest
68 #define DSubtract(n,t) HasDest
72 template<Opcode op
, uint64_t flags
>
74 static constexpr uint64_t value
=
75 (OpHasExtraData
<op
>::value
? HasExtra
: 0) | flags
;
77 static_assert(!(value
& ProducesRC
) ||
78 (value
& (HasDest
| NaryDest
)) == HasDest
,
79 "ProducesRC instructions must have exactly one dest");
84 #define O(name, dsts, srcs, flags) \
86 op_flags<name, dsts | flags>::value \
110 #undef DParamMayRelax
128 ///////////////////////////////////////////////////////////////////////////////
130 const StringData
* findClassName(SSATmp
* cls
) {
131 assertx(cls
->isA(TCls
));
133 if (cls
->hasConstVal()) {
134 return cls
->clsVal()->preClass()->name();
136 // Try to get the class name from a LdCls
137 IRInstruction
* clsInst
= cls
->inst();
138 if (clsInst
->op() == LdCls
|| clsInst
->op() == LdClsCached
) {
139 SSATmp
* clsName
= clsInst
->src(0);
140 assertx(clsName
->isA(TStr
));
141 if (clsName
->hasConstVal()) {
142 return clsName
->strVal();
148 bool isCallOp(Opcode opc
) {
149 // CallBuiltin doesn't count because it is not a php-level call. (It will
150 // call a C++ helper and we can push/pop around it normally.)
161 bool isGuardOp(Opcode opc
) {
173 bool isQueryOp(Opcode opc
) {
203 case InstanceOfBitmask
:
204 case NInstanceOfBitmask
:
213 bool isIntQueryOp(Opcode opc
) {
227 bool isDblQueryOp(Opcode opc
) {
241 bool isStrQueryOp(Opcode opc
) {
257 Opcode
negateQueryOp(Opcode opc
) {
258 assertx(isQueryOp(opc
));
266 case GtInt
: return LteInt
;
267 case GteInt
: return LtInt
;
268 case LtInt
: return GteInt
;
269 case LteInt
: return GtInt
;
270 case EqInt
: return NeqInt
;
271 case NeqInt
: return EqInt
;
272 case EqDbl
: return NeqDbl
;
273 case NeqDbl
: return EqDbl
;
274 case GtStr
: return LteStr
;
275 case GteStr
: return LtStr
;
276 case LtStr
: return GteStr
;
277 case LteStr
: return GtStr
;
278 case EqStr
: return NeqStr
;
279 case NeqStr
: return EqStr
;
280 case SameStr
: return NSameStr
;
281 case NSameStr
: return SameStr
;
282 case Same
: return NSame
;
283 case NSame
: return Same
;
284 case InstanceOfBitmask
: return NInstanceOfBitmask
;
285 case NInstanceOfBitmask
: return InstanceOfBitmask
;
286 case IsType
: return IsNType
;
287 case IsNType
: return IsType
;
292 // Negating dbl relational ops probably isn't what you want:
293 // (X < Y) != !(X >= Y) -- when NaN gets involved
294 always_assert(false);
295 default: always_assert(0);
299 Opcode
commuteQueryOp(Opcode opc
) {
300 assertx(isQueryOp(opc
));
303 case Gte
: return Lte
;
305 case Lte
: return Gte
;
307 case Neq
: return Neq
;
308 case GtInt
: return LtInt
;
309 case GteInt
:return LteInt
;
310 case LtInt
: return GtInt
;
311 case LteInt
:return GteInt
;
312 case EqInt
: return EqInt
;
313 case NeqInt
:return NeqInt
;
314 case GtDbl
: return LtDbl
;
315 case GteDbl
:return LteDbl
;
316 case LtDbl
: return GtDbl
;
317 case LteDbl
:return GteDbl
;
318 case EqDbl
: return EqDbl
;
319 case NeqDbl
:return NeqDbl
;
320 case GtStr
: return LtStr
;
321 case GteStr
:return LteStr
;
322 case LtStr
: return GtStr
;
323 case LteStr
:return GteStr
;
329 case Same
: return Same
;
330 case NSame
: return NSame
;
331 default: always_assert(0);
335 Opcode
queryToIntQueryOp(Opcode opc
) {
336 assertx(isQueryOp(opc
));
338 case Gt
: return GtInt
;
339 case Gte
: return GteInt
;
340 case Lt
: return LtInt
;
341 case Lte
: return LteInt
;
342 case Eq
: return EqInt
;
343 case Neq
: return NeqInt
;
344 case GtDbl
: return GtInt
;
345 case GteDbl
:return GteInt
;
346 case LtDbl
: return LtInt
;
347 case LteDbl
:return LteInt
;
348 case EqDbl
: return EqInt
;
349 case NeqDbl
:return NeqInt
;
350 default: always_assert(0);
354 Opcode
queryToDblQueryOp(Opcode opc
) {
355 assertx(isQueryOp(opc
));
357 case Gt
: return GtDbl
;
358 case Gte
: return GteDbl
;
359 case Lt
: return LtDbl
;
360 case Lte
: return LteDbl
;
361 case Eq
: return EqDbl
;
362 case Neq
: return NeqDbl
;
363 case GtInt
: return GtDbl
;
364 case GteInt
:return GteDbl
;
365 case LtInt
: return LtDbl
;
366 case LteInt
:return LteDbl
;
367 case EqInt
: return EqDbl
;
368 case NeqInt
:return NeqDbl
;
369 default: always_assert(0);
373 Opcode
queryToStrQueryOp(Opcode opc
) {
374 assertx(isQueryOp(opc
));
376 case Gt
: return GtStr
;
377 case Gte
: return GteStr
;
378 case Lt
: return LtStr
;
379 case Lte
: return LteStr
;
380 case Eq
: return EqStr
;
381 case Neq
: return NeqStr
;
382 case Same
: return SameStr
;
383 case NSame
: return NSameStr
;
384 default: always_assert(0);
388 ///////////////////////////////////////////////////////////////////////////////