Added IterBreakV, MIter{Init,InitK,Next,NextK,Free} and fixed memory tracking bug.
[hiphop-php.git] / hphp / compiler / analysis / emitter.h
blobf4fbe5ac8d4538bb9db03bc3a8ab9a2d0ed0c5a1
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_COMPILER_EMITTER_H_
18 #define incl_HPHP_COMPILER_EMITTER_H_
20 #include "hphp/compiler/expression/expression.h"
21 #include "hphp/compiler/statement/statement.h"
22 #include "hphp/compiler/statement/use_trait_statement.h"
23 #include "hphp/compiler/statement/trait_prec_statement.h"
24 #include "hphp/compiler/statement/trait_alias_statement.h"
25 #include "hphp/compiler/statement/typedef_statement.h"
27 #include "hphp/runtime/vm/func.h"
28 #include "hphp/runtime/vm/unit.h"
29 #include "hphp/util/hash.h"
31 namespace HPHP {
33 DECLARE_BOOST_TYPES(ClosureExpression);
34 DECLARE_BOOST_TYPES(MethodStatement);
35 DECLARE_BOOST_TYPES(InterfaceStatement);
36 DECLARE_BOOST_TYPES(ListAssignment);
37 DECLARE_BOOST_TYPES(FunctionScope);
38 DECLARE_BOOST_TYPES(FileScope);
39 DECLARE_BOOST_TYPES(FunctionCall);
40 DECLARE_BOOST_TYPES(SimpleFunctionCall);
41 DECLARE_BOOST_TYPES(SwitchStatement);
42 DECLARE_BOOST_TYPES(ForEachStatement);
43 class StaticClassName;
44 class HhbcExtFuncInfo;
45 class HhbcExtClassInfo;
47 namespace Compiler {
48 ///////////////////////////////////////////////////////////////////////////////
50 // Forward declarations.
51 class Label;
52 class EmitterVisitor;
54 // Helper for creating unit MetaInfo.
55 struct MetaInfoBuilder {
56 void add(int pos, Unit::MetaInfo::Kind kind,
57 bool mVector, int arg, Id data);
58 void addKnownDataType(DataType dt,
59 bool dtPredicted,
60 int pos,
61 bool mVector,
62 int arg);
63 void deleteInfo(Offset bcOffset);
64 void setForUnit(UnitEmitter&) const;
66 private:
67 typedef std::vector<Unit::MetaInfo> Vec;
68 typedef std::map<Offset,Vec> Map;
69 Map m_metaMap;
72 class Emitter {
73 public:
74 Emitter(ConstructPtr node, UnitEmitter& ue, EmitterVisitor& ev)
75 : m_node(node), m_ue(ue), m_ev(ev) {}
76 UnitEmitter& getUnitEmitter() { return m_ue; }
77 ConstructPtr getNode() { return m_node; }
78 EmitterVisitor& getEmitterVisitor() { return m_ev; }
79 void setTempLocation(LocationPtr loc) { m_tempLoc = loc; }
80 LocationPtr getTempLocation() { return m_tempLoc; }
81 void incStat(int counter, int value) {
82 if (RuntimeOption::EnableEmitterStats) {
83 IncStat(counter, value);
87 struct StrOff {
88 StrOff(Id s, Label* d) : str(s), dest(d) {}
89 Id str;
90 Label* dest;
93 struct IterPair {
94 IterPair(IterKind k, Id i) : kind(k), id(i) {}
95 IterKind kind;
96 Id id;
98 #define O(name, imm, pop, push, flags) \
99 void name(imm);
100 #define NA
101 #define ONE(typ) \
102 typ a1
103 #define TWO(typ1, typ2) \
104 typ1 a1, typ2 a2
105 #define THREE(typ1, typ2, typ3) \
106 typ1 a1, typ2 a2, typ3 a3
107 #define FOUR(typ1, typ2, typ3, typ4) \
108 typ1 a1, typ2 a2, typ3 a3, typ4 a4
109 #define MA std::vector<uchar>
110 #define BLA std::vector<Label*>&
111 #define SLA std::vector<StrOff>&
112 #define ILA std::vector<IterPair>&
113 #define IVA int32_t
114 #define HA int32_t
115 #define IA int32_t
116 #define I64A int64_t
117 #define DA double
118 #define SA const StringData*
119 #define AA ArrayData*
120 #define BA Label&
121 #define OA unsigned char
122 OPCODES
123 #undef O
124 #undef NA
125 #undef ONE
126 #undef TWO
127 #undef THREE
128 #undef FOUR
129 #undef MA
130 #undef BLA
131 #undef SLA
132 #undef ILA
133 #undef IVA
134 #undef HA
135 #undef IA
136 #undef I64A
137 #undef DA
138 #undef SA
139 #undef AA
140 #undef BA
141 #undef OA
142 private:
143 ConstructPtr m_node;
144 UnitEmitter& m_ue;
145 EmitterVisitor& m_ev;
146 LocationPtr m_tempLoc;
149 struct SymbolicStack {
150 enum ClassBaseType {
151 CLS_INVALID,
152 CLS_LATE_BOUND,
153 CLS_UNNAMED_LOCAL, // loc is an unnamed local
154 CLS_NAMED_LOCAL, // loc is a normal program local
155 CLS_STRING_NAME, // name is the string to use
156 CLS_SELF,
157 CLS_PARENT
160 enum MetaType {
161 META_NONE,
162 META_LITSTR,
163 META_DATA_TYPE
166 private:
168 * Symbolic stack (m_symStack)
170 * The symbolic stack is used to keep track of the flavor descriptors
171 * of values along with other contextual information. Each position in
172 * the symbolic stack can encode a "symbolic flavor" and a "marker".
173 * Most symbolic flavors correspond with flavor descriptors in the HHBC
174 * spec, but some symbolic flavors used in the symbolic stack (ex. "L")
175 * do not correspond with a flavor descriptor from the spec. Markers
176 * provide contextual information and are used by the emitter in various
177 * situations to determine the appropriate bytecode instruction to use.
179 * Note that not all positions on the symbolic stack correspond to a
180 * value on the actual evaluation stack as described in the HHBC spec.
182 struct SymEntry {
183 explicit SymEntry(char s = 0)
184 : sym(s)
185 , metaType(META_NONE)
186 , notRef(false)
187 , notNull(false)
188 , dtPredicted(false)
189 , className(nullptr)
190 , intval(-1)
191 , unnamedLocalStart(InvalidAbsoluteOffset)
192 , clsBaseType(CLS_INVALID)
194 char sym;
195 MetaType metaType;
196 bool notRef:1;
197 bool notNull:1;
198 bool dtPredicted:1;
199 union {
200 const StringData* name; // META_LITSTR
201 DataType dt; // META_DATA_TYPE
202 } metaData;
203 const StringData* className;
204 int64_t intval; // used for L and I symbolic flavors
206 // If intval is an unnamed local temporary, this offset is the start
207 // of the region we are using it (which we will need to have a
208 // fault funclet for).
209 Offset unnamedLocalStart;
211 // When class bases are emitted, we need to delay class lookup for
212 // evaluation order reasons, but may have to do some evaluation
213 // early. How this works depends on the type of class base---see
214 // emitResolveClsBase for details.
215 ClassBaseType clsBaseType;
217 std::vector<SymEntry> m_symStack;
220 * Actual stack (m_actualStack)
222 * The actual stack represents the evaluation stack as described in the
223 * HHBC spec. Each position in m_actualStack contains the index of the
224 * corresponding symbolic value in m_symStack.
226 std::vector<int> m_actualStack;
228 // The number of Func descriptors (in HHVM terms, ActRecs) currently on the
229 // stack.
230 int m_fdescCount;
232 public:
233 int* m_actualStackHighWaterPtr;
234 int* m_fdescHighWaterPtr;
236 SymbolicStack() : m_fdescCount(0) {}
238 std::string pretty() const;
240 void push(char sym);
241 void setInt(int64_t v);
242 void setString(const StringData* s);
243 void setKnownCls(const StringData* s, bool nonNull);
244 void setNotRef();
245 bool getNotRef() const;
246 void setKnownType(DataType dt, bool predicted = false);
247 void cleanTopMeta();
248 DataType getKnownType(int index = -1, bool noRef = true) const;
249 void setClsBaseType(ClassBaseType);
250 void setUnnamedLocal(int index, int localId, Offset startOffset);
251 void pop();
252 char top() const;
253 char get(int index) const;
254 const StringData* getName(int index) const;
255 const StringData* getClsName(int index) const;
256 bool isCls(int index) const;
257 bool isTypePredicted(int index = -1 /* stack top */) const;
258 void set(int index, char sym);
259 unsigned size() const;
260 bool empty() const;
261 void clear();
264 * Erase a stack element depth below the top. This is used for some
265 * instructions that pull elements out of the middle, and for our
266 * ClassBaseType virtual elements.
268 void consumeBelowTop(int depth);
270 int getActualPos(int vpos) const;
271 char getActual(int index) const;
272 void setActual(int index, char sym);
273 void insertAt(int depth, char sym);
274 int sizeActual() const;
276 ClassBaseType getClsBaseType(int index) const;
277 int getLoc(int index) const;
278 int64_t getInt(int index) const;
279 Offset getUnnamedLocStart(int index) const;
281 void pushFDesc();
282 void popFDesc();
285 class Label {
286 public:
287 Label() : m_off(InvalidAbsoluteOffset) {}
288 explicit Label(Emitter& e) : m_off(InvalidAbsoluteOffset) {
289 set(e);
291 Offset getAbsoluteOffset() const { return m_off; }
292 // Sets the Label to the bytecode offset of given by e,
293 // fixes up any instructions that have already been
294 // emitted that reference this Label, and fixes up the
295 // EmitterVisitor's jump target info
296 void set(Emitter& e);
297 // If a Label is has not been set, it is the Emitter's
298 // resposibility to call bind on the Label each time it
299 // prepares to emit an instruction that uses the Label
300 void bind(EmitterVisitor& ev, Offset instrAddr, Offset offAddr);
301 bool isSet() { return m_off != InvalidAbsoluteOffset; }
302 bool isUsed();
303 private:
304 Offset m_off;
305 std::vector<std::pair<Offset, Offset> > m_emittedOffs;
306 // m_evalStack is used to store the eval stack of the
307 // first forward jump we see that references this label
308 SymbolicStack m_evalStack;
311 class Thunklet {
312 public:
313 virtual ~Thunklet();
314 virtual void emit(Emitter& e) = 0;
317 class Funclet {
318 public:
319 Funclet(Thunklet* body, Label* entry) : m_body(body), m_entry(entry) {}
320 Thunklet* m_body;
321 Label* m_entry;
324 class EmitterVisitor {
325 friend class UnsetUnnamedLocalThunklet;
326 public:
327 explicit EmitterVisitor(UnitEmitter& ue);
328 ~EmitterVisitor();
330 bool visit(ConstructPtr c);
331 bool visitImpl(ConstructPtr c);
332 void visitKids(ConstructPtr c);
333 void visit(FileScopePtr file);
334 void assignLocalVariableIds(FunctionScopePtr fs);
335 void fixReturnType(Emitter& e, FunctionCallPtr fn,
336 Func* builtinFunc = nullptr);
337 typedef std::vector<int> IndexChain;
338 void visitListAssignmentLHS(Emitter& e, ExpressionPtr exp,
339 IndexChain& indexChain,
340 std::vector<IndexChain*>& chainList);
341 void visitIfCondition(ExpressionPtr cond, Emitter& e, Label& tru, Label& fals,
342 bool truFallthrough);
343 const SymbolicStack& getEvalStack() const { return m_evalStack; }
344 SymbolicStack& getEvalStack() { return m_evalStack; }
345 void setEvalStack(const SymbolicStack& es) {
346 m_evalStack = es;
347 m_evalStackIsUnknown = false;
349 bool evalStackIsUnknown() { return m_evalStackIsUnknown; }
350 void popEvalStack(char symFlavor, int arg = -1, int pos = -1);
351 void popSymbolicLocal(Op opcode, int arg = -1, int pos = -1);
352 void popEvalStackLMany();
353 void popEvalStackMany(int len, char symFlavor);
354 void popEvalStackCVMany(int len);
355 void pushEvalStack(char symFlavor);
356 void peekEvalStack(char symFlavor, int depthActual);
357 void pokeEvalStack(char symFlavor, int depthActual);
358 void prepareEvalStack();
359 void recordJumpTarget(Offset target, const SymbolicStack& evalStack);
360 void recordJumpTarget(Offset target) {
361 recordJumpTarget(target, m_evalStack);
363 void restoreJumpTargetEvalStack();
364 void recordCall();
365 bool isJumpTarget(Offset target);
366 void setPrevOpcode(Op op) { m_prevOpcode = op; }
367 Op getPrevOpcode() const { return m_prevOpcode; }
368 bool currentPositionIsReachable() {
369 return (m_ue.bcPos() == m_curFunc->base()
370 || isJumpTarget(m_ue.bcPos())
371 || (instrFlags(getPrevOpcode()) & TF) == 0);
374 class IncludeTimeFatalException : public Exception {
375 public:
376 ConstructPtr m_node;
377 IncludeTimeFatalException(ConstructPtr node, const char* fmt, ...)
378 : Exception(), m_node(node) {
379 va_list ap; va_start(ap, fmt); format(fmt, ap); va_end(ap);
381 virtual ~IncludeTimeFatalException() throw() {}
382 EXCEPTION_COMMON_IMPL(IncludeTimeFatalException);
385 void pushIterScope(Id id, IterKind kind) {
386 m_pendingIters.emplace_back(id, kind);
388 void popIterScope() { m_pendingIters.pop_back(); }
390 private:
391 typedef std::pair<StringData*, bool> ClosureUseVar; // (name, byRef)
392 typedef std::vector<ClosureUseVar> ClosureUseVarVec;
393 typedef std::vector<std::pair<Id,IterKind> > PendingIterVec;
394 typedef std::pair<StringData*, ExpressionPtr> NonScalarPair;
395 typedef std::vector<NonScalarPair> NonScalarVec;
396 typedef std::pair<Id, int> StrCase;
398 class PostponedMeth {
399 public:
400 PostponedMeth(MethodStatementPtr m, FuncEmitter* fe, bool top,
401 ClosureUseVarVec* useVars)
402 : m_meth(m), m_fe(fe), m_top(top), m_closureUseVars(useVars) {}
403 MethodStatementPtr m_meth;
404 FuncEmitter* m_fe;
405 bool m_top;
406 ClosureUseVarVec* m_closureUseVars;
409 class PostponedCtor {
410 public:
411 PostponedCtor(InterfaceStatementPtr is, FuncEmitter* fe)
412 : m_is(is), m_fe(fe) {}
413 InterfaceStatementPtr m_is;
414 FuncEmitter* m_fe;
417 class PostponedNonScalars {
418 public:
419 PostponedNonScalars(InterfaceStatementPtr is, FuncEmitter* fe,
420 NonScalarVec* v)
421 : m_is(is), m_fe(fe), m_vec(v) {}
422 void release() {
423 delete m_vec;
425 InterfaceStatementPtr m_is;
426 FuncEmitter* m_fe;
427 NonScalarVec* m_vec;
430 class PostponedClosureCtor {
431 public:
432 PostponedClosureCtor(ClosureUseVarVec& v, ClosureExpressionPtr e,
433 FuncEmitter* fe)
434 : m_useVars(v), m_expr(e), m_fe(fe) {}
435 ClosureUseVarVec m_useVars;
436 ClosureExpressionPtr m_expr;
437 FuncEmitter* m_fe;
440 class ControlTargets {
441 public:
442 ControlTargets(Id itId, bool itRef, Label& brkTarg, Label& cntTarg)
443 : m_itId(itId), m_itRef(itRef), m_brkTarg(brkTarg), m_cntTarg(cntTarg)
445 Id m_itId;
446 bool m_itRef;
447 Label& m_brkTarg; // Jump here for "break;" (after doing IterFree)
448 Label& m_cntTarg; // Jump here for "continue;"
451 class ControlTargetPusher {
452 public:
453 ControlTargetPusher(EmitterVisitor* e, Id itId, bool itRef, Label& brkTarg,
454 Label& cntTarg) : m_e(e) {
455 e->m_controlTargets.push_front(ControlTargets(itId, itRef, brkTarg,
456 cntTarg));
458 ~ControlTargetPusher() {
459 m_e->m_controlTargets.pop_front();
461 private:
462 EmitterVisitor* m_e;
465 class ExnHandlerRegion {
466 public:
467 ExnHandlerRegion(Offset start, Offset end) : m_start(start),
468 m_end(end) {}
469 ~ExnHandlerRegion() {
470 for (std::vector<std::pair<StringData*, Label*> >::const_iterator it =
471 m_catchLabels.begin(); it != m_catchLabels.end(); it++) {
472 delete it->second;
475 Offset m_start;
476 Offset m_end;
477 std::set<StringData*, string_data_lt> m_names;
478 std::vector<std::pair<StringData*, Label*> > m_catchLabels;
481 class FaultRegion {
482 public:
483 FaultRegion(Offset start, Offset end, Id iterId, IterKind kind)
484 : m_start(start)
485 , m_end(end)
486 , m_iterId(iterId)
487 , m_iterKind(kind)
490 Offset m_start;
491 Offset m_end;
492 Id m_iterId;
493 IterKind m_iterKind;
494 Label m_func; // note: a pointer to this is handed out to the Funclet
497 class FPIRegion {
498 public:
499 FPIRegion(Offset start, Offset end, Offset fpOff)
500 : m_start(start), m_end(end), m_fpOff(fpOff) {}
501 Offset m_start;
502 Offset m_end;
503 Offset m_fpOff;
506 struct SwitchState : private boost::noncopyable {
507 SwitchState() : nonZeroI(-1), defI(-1) {}
508 std::map<int64_t, int> cases; // a map from int (or litstr id) to case index
509 std::vector<StrCase> caseOrder; // for string switches, a list of the
510 // <litstr id, case index> in the order
511 // they appear in the source
512 int nonZeroI;
513 int defI;
516 private:
517 void emitFatal(Emitter& e, const char* message);
519 private:
520 static const size_t kMinStringSwitchCases = 8;
521 UnitEmitter& m_ue;
522 FuncEmitter* m_curFunc;
523 FileScopePtr m_file;
525 Op m_prevOpcode;
527 std::deque<PostponedMeth> m_postponedMeths;
528 std::deque<PostponedCtor> m_postponedCtors;
529 std::deque<PostponedNonScalars> m_postponedPinits;
530 std::deque<PostponedNonScalars> m_postponedSinits;
531 std::deque<PostponedNonScalars> m_postponedCinits;
532 std::deque<PostponedClosureCtor> m_postponedClosureCtors;
533 PendingIterVec m_pendingIters;
534 hphp_hash_set<std::string> m_generatorEmitted;
535 hphp_hash_set<std::string> m_topMethodEmitted;
536 SymbolicStack m_evalStack;
537 bool m_evalStackIsUnknown;
538 hphp_hash_map<Offset, SymbolicStack> m_jumpTargetEvalStacks;
539 int m_actualStackHighWater;
540 int m_fdescHighWater;
541 typedef tbb::concurrent_hash_map<const StringData*, int,
542 StringDataHashCompare> EmittedClosures;
543 static EmittedClosures s_emittedClosures;
544 std::deque<ControlTargets> m_controlTargets;
545 std::deque<Funclet> m_funclets;
546 std::deque<ExnHandlerRegion*> m_exnHandlers;
547 std::deque<FaultRegion*> m_faultRegions;
548 std::deque<FPIRegion*> m_fpiRegions;
549 std::vector<HphpArray*> m_staticArrays;
550 std::set<std::string,stdltistr> m_hoistables;
551 LocationPtr m_tempLoc;
552 std::map<StringData*, Label, string_data_lt> m_gotoLabels;
553 std::vector<Label> m_yieldLabels;
554 MetaInfoBuilder m_metaInfo;
555 public:
556 bool checkIfStackEmpty(const char* forInstruction) const;
557 void unexpectedStackSym(char sym, const char* where) const;
559 int scanStackForLocation(int iLast);
560 void buildVectorImm(std::vector<uchar>& vectorImm,
561 int iFirst, int iLast, bool allowW,
562 Emitter& e);
563 enum class PassByRefKind {
564 AllowCell,
565 WarnOnCell,
566 ErrorOnCell,
568 PassByRefKind getPassByRefKind(ExpressionPtr exp);
569 void emitAGet(Emitter& e);
570 void emitCGetL2(Emitter& e);
571 void emitCGetL3(Emitter& e);
572 void emitCGet(Emitter& e);
573 void emitVGet(Emitter& e);
574 void emitIsset(Emitter& e);
575 void emitIsNull(Emitter& e);
576 void emitIsArray(Emitter& e);
577 void emitIsObject(Emitter& e);
578 void emitIsString(Emitter& e);
579 void emitIsInt(Emitter& e);
580 void emitIsDouble(Emitter& e);
581 void emitIsBool(Emitter& e);
582 void emitEmpty(Emitter& e);
583 void emitUnset(Emitter& e, ExpressionPtr exp = ExpressionPtr());
584 void emitVisitAndUnset(Emitter& e, ExpressionPtr exp);
585 void emitSet(Emitter& e);
586 void emitSetOp(Emitter& e, int op);
587 void emitBind(Emitter& e);
588 void emitIncDec(Emitter& e, unsigned char cop);
589 void emitPop(Emitter& e);
590 void emitConvertToCell(Emitter& e);
591 void emitFreePendingIters(Emitter& e);
592 void emitConvertToCellIfVar(Emitter& e);
593 void emitConvertToCellOrLoc(Emitter& e);
594 void emitConvertSecondToCell(Emitter& e);
595 void emitConvertToVar(Emitter& e);
596 void emitFPass(Emitter& e, int paramID, PassByRefKind passByRefKind);
597 void emitVirtualLocal(int localId, DataType dt = KindOfUnknown);
598 template<class Expr> void emitVirtualClassBase(Emitter&, Expr* node);
599 void emitResolveClsBase(Emitter& e, int pos);
600 void emitClsIfSPropBase(Emitter& e);
601 Id emitVisitAndSetUnnamedL(Emitter& e, ExpressionPtr exp);
602 void emitPushAndFreeUnnamedL(Emitter& e, Id tempLocal, Offset start);
603 void emitContinuationSwitch(Emitter& e, int ncase);
604 DataType analyzeSwitch(SwitchStatementPtr s, SwitchState& state);
605 void emitIntegerSwitch(Emitter& e, SwitchStatementPtr s,
606 std::vector<Label>& caseLabels, Label& done,
607 const SwitchState& state);
608 void emitStringSwitch(Emitter& e, SwitchStatementPtr s,
609 std::vector<Label>& caseLabels, Label& done,
610 const SwitchState& state);
611 void emitIterBreak(Emitter& e, uint64_t n, Label& targ);
613 void markElem(Emitter& e);
614 void markNewElem(Emitter& e);
615 void markProp(Emitter& e);
616 void markSProp(Emitter& e);
617 void markName(Emitter& e);
618 void markNameSecond(Emitter& e);
619 void markGlobalName(Emitter& e);
621 void emitNameString(Emitter& e, ExpressionPtr n, bool allowLiteral = false);
622 void emitAssignment(Emitter& e, ExpressionPtr c, int op, bool bind);
623 void emitListAssignment(Emitter& e, ListAssignmentPtr lst);
624 void postponeMeth(MethodStatementPtr m, FuncEmitter* fe, bool top,
625 ClosureUseVarVec* useVars = nullptr);
626 void postponeCtor(InterfaceStatementPtr m, FuncEmitter* fe);
627 void postponePinit(InterfaceStatementPtr m, FuncEmitter* fe, NonScalarVec* v);
628 void postponeSinit(InterfaceStatementPtr m, FuncEmitter* fe, NonScalarVec* v);
629 void postponeCinit(InterfaceStatementPtr m, FuncEmitter* fe, NonScalarVec* v);
630 void emitPostponedMeths();
631 void emitPostponedCtors();
632 void emitPostponedPSinit(PostponedNonScalars& p, bool pinit);
633 void emitPostponedPinits();
634 void emitPostponedSinits();
635 void emitPostponedCinits();
636 void emitPostponedClosureCtors();
637 enum CallUserFuncFlags {
638 CallUserFuncNone = -1,
639 CallUserFuncPlain = 0,
640 CallUserFuncArray = 1,
641 CallUserFuncSafe = 2,
642 CallUserFuncReturn = 4,
643 CallUserFuncForward = 8,
644 CallUserFuncSafeArray = CallUserFuncSafe | CallUserFuncArray,
645 CallUserFuncSafeReturn = CallUserFuncSafe | CallUserFuncReturn,
646 CallUserFuncForwardArray = CallUserFuncForward | CallUserFuncArray
649 bool emitCallUserFunc(Emitter& e, SimpleFunctionCallPtr node);
650 Func* canEmitBuiltinCall(const std::string& name, int numParams);
651 void emitFuncCall(Emitter& e, FunctionCallPtr node);
652 void emitFuncCallArg(Emitter& e, ExpressionPtr exp, int paramId);
653 void emitBuiltinCallArg(Emitter& e, ExpressionPtr exp, int paramId,
654 bool byRef);
655 void emitBuiltinDefaultArg(Emitter& e, Variant& v, DataType t, int paramId);
656 PreClass::Hoistable emitClass(Emitter& e, ClassScopePtr cNode,
657 bool topLevel);
658 void emitTypedef(Emitter& e, TypedefStatementPtr);
659 void emitForeach(Emitter& e, ForEachStatementPtr fe);
660 void emitRestoreErrorReporting(Emitter& e, Id oldLevelLoc);
661 void emitMakeUnitFatal(Emitter& e, const std::string& message);
663 void addFunclet(Thunklet* body, Label* entry);
664 void emitFunclets(Emitter& e);
666 struct FaultIterInfo {
667 Id iterId;
668 IterKind kind;
670 void newFaultRegion(Offset start, Offset end, Thunklet* t,
671 FaultIterInfo = FaultIterInfo { -1, KindOfIter });
673 void newFPIRegion(Offset start, Offset end, Offset fpOff);
674 void copyOverExnHandlers(FuncEmitter* fe);
675 void copyOverFPIRegions(FuncEmitter* fe);
676 void saveMaxStackCells(FuncEmitter* fe);
677 void finishFunc(Emitter& e, FuncEmitter* fe);
679 void initScalar(TypedValue& tvVal, ExpressionPtr val);
680 bool requiresDeepInit(ExpressionPtr initExpr) const;
682 void emitClassTraitPrecRule(PreClassEmitter* pce, TraitPrecStatementPtr rule);
683 void emitClassTraitAliasRule(PreClassEmitter* pce,
684 TraitAliasStatementPtr rule);
685 void emitClassUseTrait(PreClassEmitter* pce, UseTraitStatementPtr useStmt);
688 void emitAllHHBC(AnalysisResultPtr ar);
690 extern "C" {
691 Unit* hphp_compiler_parse(const char* code, int codeLen, const MD5& md5,
692 const char* filename);
693 Unit* hphp_build_native_func_unit(const HhbcExtFuncInfo* builtinFuncs,
694 ssize_t numBuiltinFuncs);
695 Unit* hphp_build_native_class_unit(const HhbcExtClassInfo* builtinClasses,
696 ssize_t numBuiltinClasses);
699 ///////////////////////////////////////////////////////////////////////////////
703 #endif // incl_HPHP_COMPILER_EMITTER_H_