Codemod asserts to assertxs in the runtime
[hiphop-php.git] / hphp / runtime / vm / jit / irlower-internal-inl.h
blob56008cdc2b54610ec9c15dbaf7f7779cd27b1397
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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/base/array-data.h"
18 #include "hphp/runtime/base/attr.h"
19 #include "hphp/runtime/base/datatype.h"
20 #include "hphp/runtime/base/header-kind.h"
21 #include "hphp/runtime/base/object-data.h"
23 #include "hphp/runtime/vm/jit/arg-group.h"
24 #include "hphp/runtime/vm/jit/code-gen-helpers.h"
25 #include "hphp/runtime/vm/jit/ir-instruction.h"
26 #include "hphp/runtime/vm/jit/ir-opcode.h"
27 #include "hphp/runtime/vm/jit/irlower.h"
28 #include "hphp/runtime/vm/jit/type.h"
29 #include "hphp/runtime/vm/jit/type-specialization.h"
30 #include "hphp/runtime/vm/jit/vasm.h"
31 #include "hphp/runtime/vm/jit/vasm-gen.h"
32 #include "hphp/runtime/vm/jit/vasm-instr.h"
33 #include "hphp/runtime/vm/jit/vasm-reg.h"
35 #include "hphp/util/asm-x64.h"
37 namespace HPHP { namespace jit { namespace irlower {
39 ///////////////////////////////////////////////////////////////////////////////
41 inline Vout& vmain(IRLS& env) { assertx(env.vmain); return *env.vmain; }
42 inline Vout& vcold(IRLS& env) { assertx(env.vcold); return *env.vcold; }
44 inline Vlabel label(IRLS& env, Block* b) { return env.labels[b]; }
46 inline Vloc srcLoc(IRLS& env, const IRInstruction* inst, unsigned i) {
47 return env.locs[inst->src(i)];
50 inline Vloc dstLoc(IRLS& env, const IRInstruction* inst, unsigned i) {
51 return env.locs[inst->dst(i)];
54 inline ArgGroup argGroup(IRLS& env, const IRInstruction* inst) {
55 return ArgGroup(inst, env.locs);
58 inline CallDest callDest(Vreg reg0) {
59 return { DestType::SSA, reg0 };
62 inline CallDest callDest(Vreg reg0, Vreg reg1) {
63 return { DestType::TV, reg0, reg1 };
66 inline CallDest callDest(IRLS& env, const IRInstruction* inst) {
67 if (!inst->numDsts()) return kVoidDest;
69 auto const loc = dstLoc(env, inst, 0);
70 if (loc.numAllocated() == 0) return kVoidDest;
71 assertx(loc.numAllocated() == 1);
73 return {
74 inst->dst(0)->isA(TBool) ? DestType::Byte : DestType::SSA,
75 loc.reg(0)
79 inline CallDest callDestTV(IRLS& env, const IRInstruction* inst) {
80 if (!inst->numDsts()) return kVoidDest;
82 auto const loc = dstLoc(env, inst, 0);
83 if (loc.numAllocated() == 0) return kVoidDest;
85 if (loc.isFullSIMD()) {
86 assertx(loc.numAllocated() == 1);
87 return { DestType::SIMD, loc.reg(0) };
89 if (loc.numAllocated() == 2) {
90 return { DestType::TV, loc.reg(0), loc.reg(1) };
92 assertx(loc.numAllocated() == 1);
94 // Sometimes we statically know the type and only need the value.
95 return { DestType::TV, loc.reg(0), InvalidReg };
98 inline CallDest callDestDbl(IRLS& env, const IRInstruction* inst) {
99 if (!inst->numDsts()) return kVoidDest;
100 auto const loc = dstLoc(env, inst, 0);
101 return { DestType::Dbl, loc.reg(0) };
104 ///////////////////////////////////////////////////////////////////////////////
106 inline void fwdJcc(Vout& v, IRLS& env, ConditionCode cc,
107 Vreg sf, Block* target) {
108 auto const next = v.makeBlock();
109 v << jcc{cc, sf, {next, label(env, target)}};
110 v = next;
113 ///////////////////////////////////////////////////////////////////////////////
115 namespace detail {
117 ///////////////////////////////////////////////////////////////////////////////
120 * Materialize `data' into a Vreg and return it.
122 inline Vreg materialize(Vout& v, Vptr data) {
123 auto const t = v.makeReg();
124 v << load{data, t};
125 return t;
127 inline Vreg materialize(Vout&, Vreg data) { return data; }
130 * Test whether the value given by `dataSrc' has the same type specialization
131 * as `type' does.
133 * Assumes that the DataType corresponding to `dataSrc' already matches `type'.
135 template <class Loc, class JmpFn>
136 void emitSpecializedTypeTest(Vout& v, IRLS& /*env*/, Type type, Loc dataSrc,
137 Vreg sf, JmpFn doJcc) {
138 if (type < TRes) {
139 // No cls field in Resource.
140 always_assert(false && "unexpected guard on specialized Resource");
143 if (type < TObj || type < TCls) {
144 // Emit the specific class test.
145 assertx(type.clsSpec());
146 assertx(type.clsSpec().exact() ||
147 type.clsSpec().cls()->attrs() & AttrNoOverride);
149 auto const data = materialize(v, dataSrc);
150 if (type < TObj) {
151 emitCmpLowPtr(v, sf, type.clsSpec().cls(),
152 data[ObjectData::getVMClassOffset()]);
153 } else {
154 v << cmpq{v.cns(type.clsSpec().cls()), data, sf};
156 doJcc(CC_E, sf);
157 } else {
158 assertx(type < TArr && type.arrSpec() && type.arrSpec().kind());
159 assertx(type.arrSpec().type() == nullptr);
161 auto const arrSpec = type.arrSpec();
162 auto const data = materialize(v, dataSrc);
164 static_assert(sizeof(HeaderKind) == 1, "");
165 v << cmpbim{*arrSpec.kind(), data[HeaderKindOffset], sf};
166 doJcc(CC_E, sf);
170 ///////////////////////////////////////////////////////////////////////////////
174 ///////////////////////////////////////////////////////////////////////////////
176 template<class Loc, class JmpFn>
177 void emitTypeTest(Vout& v, IRLS& env, Type type,
178 Loc typeSrc, Loc dataSrc, Vreg sf, JmpFn doJcc) {
179 // Note: If you add new supported type tests, you should update
180 // negativeCheckType() to indicate whether it is precise or not.
181 always_assert(!type.hasConstVal());
182 always_assert_flog(
183 !type.subtypeOfAny(TCls, TCountedStr, TPersistentArrLike),
184 "Unsupported type in emitTypeTest(): {}", type
187 // Nothing to check.
188 if (type == TGen) return;
190 auto const cc = [&] {
192 auto const mask_cmp = [&] (int mask, int bits, ConditionCode cc) {
193 auto const masked = emitMaskTVType(v, mask, typeSrc);
194 emitCmpTVType(v, sf, bits, masked);
195 return cc;
198 auto const cmp = [&] (DataType kind, ConditionCode cc) {
199 emitCmpTVType(v, sf, kind, typeSrc);
200 return cc;
203 auto const test = [&] (int bits, ConditionCode cc) {
204 emitTestTVType(v, sf, bits, typeSrc);
205 return cc;
208 if (type <= TPersistentStr) return cmp(KindOfPersistentString, CC_E);
209 if (type <= TStr) return test(KindOfStringBit, CC_NZ);
210 if (type <= TArr) return test(KindOfArrayBit, CC_NZ);
211 if (type <= TVec) return mask_cmp(kDataTypeEquivalentMask,
212 KindOfHackArrayVecType,
213 CC_E);
214 if (type <= TDict) return mask_cmp(kDataTypeEquivalentMask,
215 KindOfHackArrayDictType,
216 CC_E);
217 if (type <= TKeyset) return mask_cmp(kDataTypeEquivalentMask,
218 KindOfHackArrayKeysetType,
219 CC_E);
220 if (type <= TArrLike) return test(KindOfArrayLikeMask, CC_NZ);
222 // These are intentionally == and not <=.
223 if (type == TNull) return cmp(KindOfNull, CC_LE);
224 if (type == TUncountedInit) return test(KindOfUncountedInitBit, CC_NZ);
225 if (type == TUncounted) return cmp(KindOfRefCountThreshold, CC_LE);
226 if (type == TCell) return cmp(KindOfRef, CC_NE);
228 always_assert(type.isKnownDataType());
229 always_assert(!(type < TBoxedInitCell));
231 auto const dt = type.toDataType();
232 return cmp(dt, CC_E);
233 }();
235 doJcc(cc, sf);
237 if (type.isSpecialized()) {
238 auto const sf2 = v.makeReg();
239 detail::emitSpecializedTypeTest(v, env, type, dataSrc, sf2, doJcc);
243 template<class Loc>
244 void emitTypeCheck(Vout& v, IRLS& env, Type type,
245 Loc typeSrc, Loc dataSrc, Block* taken) {
246 emitTypeTest(v, env, type, typeSrc, dataSrc, v.makeReg(),
247 [&] (ConditionCode cc, Vreg sf) {
248 fwdJcc(v, env, ccNegate(cc), sf, taken);
253 ///////////////////////////////////////////////////////////////////////////////