forked from facebook/hhvm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathir-opcode.h
310 lines (266 loc) · 9.4 KB
/
ir-opcode.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_VM_IR_OPCODE_H_
#define incl_HPHP_VM_IR_OPCODE_H_
#include <type_traits>
#include <vector>
#include <folly/Range.h>
#include "hphp/runtime/vm/jit/types.h"
#include "hphp/runtime/vm/jit/type.h"
#include "hphp/runtime/base/types.h"
namespace HPHP {
//////////////////////////////////////////////////////////////////////
struct StringData;
namespace jit {
//////////////////////////////////////////////////////////////////////
struct IRUnit;
struct IRInstruction;
struct SSATmp;
struct LocalStateHook;
struct FrameStateMgr;
//////////////////////////////////////////////////////////////////////
/*
* The instruction table below uses the following notation. To use
* it, you have to define these symbols to do what you want, and then
* instantiate IR_OPCODES.
*
* dstinfo:
*
* Contains a description of how to compute the type of the
* destination(s) of an instruction from its sources.
*
* ND instruction has no destination
* D(type) single dst has a specific type
* DofS(N) single dst has the type of src N
* DBox(N) single dst has boxed type of src N
* DRefineS(N) single dst's type is intersection of src N and paramType
* DParam single dst has type of the instruction's type parameter
* DParamMayRelax like DParam, except type may relax
* DParamPtr(k) like DParam, but the param must be a PtrTo* of kind k
* DUnboxPtr Unboxed PtrTo*T; adds possibility of pointing into a ref
* DBoxPtr Boxed PtrTo*T
* DAllocObj single dst has a type of a newly allocated object; may be a
* specialized object type if the class is known
* DArrPacked single dst has a packed array type
* DArrElem single dst has type based on reading an array element,
* intersected with an optional type parameter
* DThis single dst has type Obj<ctx>, where ctx is the
* current context class
* DMulti multiple dests. type and number depend on instruction
* DSetElem single dst is a subset of CountedStr|Nullptr depending on
* sources
* DStk(x) up to two dests. x should be another D* macro and indicates
* the type of the first dest, if any. the second (or first,
* depending on the presence of a primary destination), will
* be of type Type::StkPtr. implies ModifiesStack.
* DBuiltin single dst for CallBuiltin. This can return complex data
* types such as (Type::Str | Type::Null)
* DSubtract(N,t) single dest has type of src N with t removed
* DCns single dst's type is the union of legal types for PHP
* constants
*
* srcinfo:
*
* Contains a series of tests on the source parameters in order.
*
* NA instruction takes no sources
* S(t1,...,tn) source must be a subtype of {t1|..|tn}
* AK(<kind>) source must be an array with specified kind
* C(type) source must be a constant, and subtype of type
* CStr same as C(StaticStr)
* SVar(t1,...,tn) variadic source list, all subtypes of {t1|..|tn}
*
* flags:
*
* See doc/ir.specification for the meaning of these flags.
*
* The flags in this opcode table supply default values for the
* querying functions in IRInstruction---those functions involve
* additional logic (based on operand types, etc) on a
* per-instruction basis.
*
* The following abbreviations are used in this table:
*
* NF no flags
* C canCSE
* Er mayRaiseError
* PRc producesRC
* CRc consumesRC
* T isTerminal
* B isBranch
* P passthrough
* K killsSource
* MProp MInstrProp
* MElem MInstrElem
*/
#define O_STK(name, dst, src, flags) \
O(name, dst, src, StkFlags(flags)) \
O(name ## Stk, DStk(dst), src S(StkPtr), flags)
// The IR opcode table is generated from lines that start with | in
// hphp/doc/ir.specification.
#include "hphp/runtime/ir-opcode-generated.h"
enum class Opcode : uint16_t {
#define O(name, ...) name,
IR_OPCODES
#undef O
};
#define O(name, ...) UNUSED auto constexpr name = Opcode::name;
IR_OPCODES
#undef O
#define O(...) +1
size_t constexpr kNumOpcodes = IR_OPCODES;
#undef O
/*
* Returns true for instructions that perform calls.
*/
bool isCallOp(Opcode opc);
/*
* Returns true for instructions that refine the types of values with
* a runtime check.
*/
bool isGuardOp(Opcode opc);
/*
* A "query op" is any instruction returning Type::Bool that is
* negateable.
*/
bool isQueryOp(Opcode opc);
/*
* Return true if opc is an int comparison operator
*/
bool isIntQueryOp(Opcode opc);
/*
* Return the int-query opcode for the given non-int-query opcode
*/
Opcode queryToIntQueryOp(Opcode opc);
/*
* Return true if opc is a dbl comparison operator
*/
bool isDblQueryOp(Opcode opc);
/*
* Return the dbl-query opcode for the given non-dbl-query opcode
*/
Opcode queryToDblQueryOp(Opcode opc);
/*
* A "fusable query op" is any instruction returning Type::Bool that
* has a corresponding "query jump op" for branch fusion.
*/
bool isFusableQueryOp(Opcode opc);
/*
* A "query jump op" is a conditional jump instruction that
* corresponds to one of the fusable query op instructions.
*/
bool isQueryJmpOp(Opcode opc);
/*
* Translate a query op into a conditional jump that does the same
* test (a "query jump op").
*
* Pre: isFusableQueryOp(opc)
*/
Opcode queryToJmpOp(Opcode opc);
/*
* Translate a "query jump op" to a query op.
*
* Pre: isQueryJmpOp(opc);
*/
Opcode queryJmpToQueryOp(Opcode opc);
/*
* Convert a jump operation to its corresponding conditional
* ReqBindJmp.
*
* Pre: opc is a conditional jump.
*/
Opcode jmpToReqBindJmp(Opcode opc);
/*
* Return the opcode that corresponds to negation of opc.
*/
Opcode negateQueryOp(Opcode opc);
/*
* Return the opcode that corresponds to commuting the arguments of
* opc.
*
* Pre: opc is a 2-argument query op.
*/
Opcode commuteQueryOp(Opcode opc);
const char* opcodeName(Opcode opcode);
bool opHasExtraData(Opcode op);
enum OpcodeFlag : uint64_t {
NoFlags = 0,
HasDest = 1ULL << 0,
CanCSE = 1ULL << 1,
Branch = 1ULL << 2,
HasStackVersion = 1ULL << 3,
ConsumesRC = 1ULL << 4,
ProducesRC = 1ULL << 5,
MInstrProp = 1ULL << 6,
MInstrElem = 1ULL << 7,
MayRaiseError = 1ULL << 8,
Terminal = 1ULL << 9, // has no next instruction
NaryDest = 1ULL << 10, // has 0 or more destinations
HasExtra = 1ULL << 11,
Passthrough = 1ULL << 12,
KillsSources = 1ULL << 13,
ModifiesStack = 1ULL << 14,
};
bool hasEdges(Opcode opc);
bool opcodeHasFlags(Opcode opc, uint64_t flags);
Opcode getStackModifyingOpcode(Opcode opc);
using SrcRange = folly::Range<SSATmp**>;
using DstRange = folly::Range<SSATmp*>;
/*
* Given an SSATmp of type Cls, try to find the name of the class.
* Returns nullptr if can't find it.
*/
const StringData* findClassName(SSATmp* cls);
/*
* Return the output type from a given IRInstruction.
*
* The destination type is always predictable from the types of the inputs, any
* type parameters to the instruction, and the id of the dest.
*/
Type outputType(const IRInstruction*, int dstId = 0);
/*
* Check that an instruction has operands of allowed types.
*/
bool checkOperandTypes(const IRInstruction*, const IRUnit* unit = nullptr);
using TcaRange = folly::Range<TCA>;
/*
* Counts the number of cells a SpillStack will logically push. (Not
* including the number it pops.) That is, for each SSATmp in the
* spill sources, this totals up whether it is an ActRec or a cell.
*/
int32_t spillValueCells(const IRInstruction* spillStack);
} // namespace jit
} // namespace HPHP
namespace std {
template<> struct hash<HPHP::jit::Opcode> {
size_t operator()(HPHP::jit::Opcode op) const { return uint16_t(op); }
};
template<> struct hash<HPHP::jit::Type> {
size_t operator()(HPHP::jit::Type t) const { return t.hash(); }
};
}
namespace folly {
template<> struct FormatValue<HPHP::jit::Opcode> {
explicit FormatValue(HPHP::jit::Opcode op) : m_op(op) {}
template<typename Callback> void format(FormatArg& arg, Callback& cb) const {
format_value::formatString(opcodeName(m_op), arg, cb);
}
private:
HPHP::jit::Opcode m_op;
};
}
#include "hphp/runtime/vm/jit/ir-opcode-inl.h"
#endif