forked from facebook/hhvm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathirgen.h
375 lines (324 loc) · 11.3 KB
/
irgen.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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-present 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_JIT_IRGEN_H_
#define incl_HPHP_JIT_IRGEN_H_
#include "hphp/runtime/base/repo-auth-type.h"
#include "hphp/runtime/base/types.h"
#include "hphp/runtime/vm/hhbc.h"
#include "hphp/runtime/vm/member-key.h"
#include "hphp/runtime/vm/srckey.h"
#include "hphp/runtime/vm/jit/bc-marker.h"
#include "hphp/runtime/vm/jit/ir-builder.h"
#include "hphp/runtime/vm/jit/ir-opcode.h"
#include "hphp/runtime/vm/jit/ir-unit.h"
#include "hphp/runtime/vm/jit/irgen-state.h"
#include "hphp/runtime/vm/jit/location.h"
#include "hphp/runtime/vm/jit/region-selection.h"
#include "hphp/runtime/vm/jit/stack-offsets.h"
#include "hphp/runtime/vm/jit/types.h"
#include "hphp/util/ringbuffer.h"
#include <cstdint>
#include <utility>
#include <vector>
namespace HPHP {
struct ArrayData;
struct Func;
struct ImmVector;
struct StringData;
namespace jit {
struct Block;
struct IRGS;
struct IRInstruction;
struct NormalizedInstruction;
struct SSATmp;
namespace irgen {
///////////////////////////////////////////////////////////////////////////////
/*
* The public interface to the HHIR frontend is exported here. Don't include
* other headers outside of the implementation of this module.
*
* This module is used for two tasks:
*
* o It is used by the region translator, and does most of the work of
* parsing HHBC into HHIR when we're trying to create an IRUnit out of a
* RegionDesc.
*
* o The tracelet region selector uses this code to generate a RegionDesc.
*
* To use this code, the client creates an IRGS structure, and calls these
* irgen::foo methods on it.
*
* TODO: we should push translateRegion and selectTracelet into this module, so
* we can just export functions that do the above two tasks.
*/
///////////////////////////////////////////////////////////////////////////////
/*
* The main function for generating new IRInstructions. Attempts to append an
* IRInstruction at the end of the current Block.
*
* Uses the same argument list format as IRUnit::gen.
*/
namespace detail { SSATmp* genInstruction(IRGS& env, IRInstruction*); }
template<class... Args>
SSATmp* gen(IRGS& env, Opcode op, Args&&... args) {
return makeInstruction(
[&] (IRInstruction* inst) { return detail::genInstruction(env, inst); },
op,
env.irb->nextBCContext(),
std::forward<Args>(args)...
);
}
/*
* Create constant-valued SSATmps inside the IRUnit we're creating.
*/
template<class... Args>
SSATmp* cns(IRGS& env, Args&&... args) {
return env.unit.cns(std::forward<Args>(args)...);
}
///////////////////////////////////////////////////////////////////////////////
/*
* Type checks and assertions.
*/
void checkType(IRGS&, const Location&, Type,
Offset dest, bool outerOnly);
void assertTypeStack(IRGS&, BCSPRelOffset, Type);
void assertTypeLocal(IRGS&, uint32_t id, Type);
void assertTypeLocation(IRGS&, const Location&, Type);
/*
* Type predictions.
*/
void predictType(IRGS&, const Location&, Type);
/*
* Special type of guards for param-passing reffiness. These checks are needed
* when an FPush* instruction is in a different region from its FCall, and we
* don't know statically whether the callee will want arguments by reference.
*/
void checkRefs(IRGS&, int64_t entryArDelta, const std::vector<bool>& mask,
const std::vector<bool>& vals, Offset);
/*
* After all initial guards instructions have been emitted, the client of this
* module calls the following function to allow some "region header" code to be
* emitted.
*/
void prepareEntry(IRGS&);
///////////////////////////////////////////////////////////////////////////////
/*
* Creates a no-op IR instruction that branches to an exit.
*
* These placeholder instructions are later removed after any passes that want
* to use them for their exits.
*/
void makeExitPlaceholder(IRGS&);
/*
* Support for Profiling counters, including reoptimization (CheckCold).
*/
void incProfCounter(IRGS&, TransID);
void checkCold(IRGS&, TransID);
uint64_t curProfCount(const IRGS& env);
/*
* If ringbuffer tracing is enabled, generate a ringbuffer entry associated
* with a SrcKey or string.
*/
void ringbufferEntry(IRGS&, Trace::RingBufferType, SrcKey, int level = 1);
void ringbufferMsg(IRGS&, Trace::RingBufferType, const StringData*,
int level = 1);
///////////////////////////////////////////////////////////////////////////////
/*
* For handling PUNT-based interpOnes. When we PUNT, an exception is thrown
* and the whole region is retried, with a bit set to interp the instruction
* that failed.
*/
void interpOne(IRGS&, const NormalizedInstruction&);
///////////////////////////////////////////////////////////////////////////////
/*
* Before translating/processing each bytecode instruction, the driver
* of the irgen module calls this function to move to the next
* bytecode instruction (`newSk') to translate.
*
* The flag `lastBcInst' should be set if this is the last bytecode in
* a region that's being translated.
*/
void prepareForNextHHBC(IRGS&, const NormalizedInstruction*,
SrcKey newSk, bool lastBcInst);
/*
* After translating each bytecode instruction, the driver of the
* irgen module calls this function to signal that it has finished
* processing the HHBC instruction.
*/
void finishHHBC(IRGS&);
/*
* When done translating a region, or a block in a region, these calls are
* made.
*/
void endRegion(IRGS&);
void endRegion(IRGS&, SrcKey);
void endBlock(IRGS&, Offset next);
/*
* When we're done creating the IRUnit, this function must be called to ensure
* all the IR invariants hold.
*/
void sealUnit(IRGS&);
///////////////////////////////////////////////////////////////////////////////
/*
* Returns whether `env' is currently inlining or not.
*/
bool isInlining(const IRGS& env);
/*
* Attempt to begin inlining, and return whether or not we succeeded.
*
* When doing gen-time inlining, we set up a series of IR instructions that
* looks like this:
*
* fp0 = DefFP
* sp = DefSP<offset>
*
* // ... normal stuff happens ...
*
* // FPI region:
* SpillFrame sp, ...
* // ... probably some StStks due to argument expressions
* BeginInlining<offset> sp
* fp2 = DefInlineFP<func,retBC,retSP,off> sp
*
* // ... callee body ...
*
* InlineReturn fp2
*
* In DCE we attempt to remove the InlineReturn and DefInlineFP instructions if
* they aren't needed.
*/
bool beginInlining(IRGS& env,
unsigned numParams,
const Func* target,
SrcKey startSk,
Offset returnBcOffset,
ReturnTarget returnTarget);
/*
* End the current inlined frame, after all its blocks have been emitted.
*
* This decrefs locals and $this and pushes the return value onto the caller's
* eval stack, in addition to the actual control transfer and bookkeeping done
* by implInlineReturn().
*/
void endInlining(IRGS& env);
/*
* Begin inlining func into a dummy region used to measure the cost of
* inlining func. This will generate a region that cannot be executed.
*
* Simulating the inlining measures the cost of pushing a dummy frame (or not if
* we are able to elide it) and any effects that may have on alias analysis.
*
* Returns false if the inlined region would be invalid for inlining
*/
bool conjureBeginInlining(IRGS& env,
const Func* func,
SrcKey startSk,
Type thisType,
const std::vector<Type>& args,
ReturnTarget returnTarget);
/*
* Close an inlined function inserted using conjureBeginInlining; returns false
* if the inlined region would have been invalid for inlining. As with
* conjureBeginInlining, this function should not be used in a region that will
* be executed.
*/
void conjureEndInlining(IRGS& env, bool builtin);
/*
* We do two special-case optimizations to partially inline 'singleton'
* accessor functions (functions that just return a static local or static
* property if it's not null).
*
* This is exposed publically because the region translator drives inlining
* decisions.
*/
void inlSingletonSProp(IRGS&, const Func*, PC clsOp, PC propOp);
void inlSingletonSLoc(IRGS&, const Func*, PC op);
///////////////////////////////////////////////////////////////////////////////
/*
* State introspection.
*
* These functions should only be used for inspecting state. None of them
* constrain types, so if the type information is actually used, it must be
* constrained appropriately.
*/
/*
* Access the type of the top of the stack.
*/
Type publicTopType(const IRGS& env, BCSPRelOffset);
/*
* Return the proven or predicted Type for the given location.
*/
Type provenType(const IRGS&, const Location&);
Type predictedType(const IRGS&, const Location&);
///////////////////////////////////////////////////////////////////////////////
/*
* Forward-declare an irgen::emitFoo function for each bytecode Foo.
*
* The arguments to the functions are pre-unpacked bytecode immediates.
*/
#define IMM_BLA const ImmVector&
#define IMM_SLA const ImmVector&
#define IMM_ILA const ImmVector&
#define IMM_VSA const ImmVector&
#define IMM_IVA uint32_t
#define IMM_I64A int64_t
#define IMM_LA int32_t
#define IMM_IA int32_t
#define IMM_CAR uint32_t
#define IMM_CAW uint32_t
#define IMM_DA double
#define IMM_SA const StringData*
#define IMM_RATA RepoAuthType
#define IMM_AA const ArrayData*
#define IMM_BA Offset
#define IMM_OA(subop) subop
#define IMM_KA MemberKey
#define IMM_LAR LocalRange
#define NA /* */
#define ONE(x0) , IMM_##x0
#define TWO(x0, x1) , IMM_##x0, IMM_##x1
#define THREE(x0, x1, x2) , IMM_##x0, IMM_##x1, IMM_##x2
#define FOUR(x0, x1, x2, x3) , IMM_##x0, IMM_##x1, IMM_##x2, IMM_##x3
#define O(name, imms, ...) void emit##name(IRGS& imms);
OPCODES
#undef O
#undef NA
#undef ONE
#undef TWO
#undef THREE
#undef FOUR
#undef IMM_MA
#undef IMM_BLA
#undef IMM_SLA
#undef IMM_ILA
#undef IMM_VSA
#undef IMM_IVA
#undef IMM_I64A
#undef IMM_LA
#undef IMM_IA
#undef IMM_CAR
#undef IMM_CAW
#undef IMM_DA
#undef IMM_SA
#undef IMM_RATA
#undef IMM_AA
#undef IMM_BA
#undef IMM_OA
#undef IMM_KA
#undef IMM_LAR
///////////////////////////////////////////////////////////////////////////////
}}}
#endif