2 +----------------------------------------------------------------------+
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 +----------------------------------------------------------------------+
16 #ifndef incl_HHBBC_REPRESENTATION_H_
17 #define incl_HHBBC_REPRESENTATION_H_
23 #include <unordered_map>
27 #include <boost/variant.hpp>
29 #include "hphp/util/atomic-vector.h"
30 #include "hphp/util/compact-vector.h"
31 #include "hphp/util/copy-ptr.h"
32 #include "hphp/util/sha1.h"
34 #include "hphp/runtime/base/user-attributes.h"
35 #include "hphp/runtime/vm/func.h"
36 #include "hphp/runtime/vm/preclass.h"
37 #include "hphp/runtime/vm/type-alias.h"
38 #include "hphp/runtime/vm/type-constraint.h"
40 #include "hphp/hhbbc/bc.h"
41 #include "hphp/hhbbc/misc.h"
42 #include "hphp/hhbbc/src-loc.h"
44 namespace HPHP
{ namespace HHBBC
{
47 //////////////////////////////////////////////////////////////////////
53 //////////////////////////////////////////////////////////////////////
60 //////////////////////////////////////////////////////////////////////
63 * A basic block in our factored control flow graph.
65 * Blocks terminate on control flow, except exceptional control flow.
66 * We keep a set of "throw exits" representing all possible early
67 * exits due to exceptional control flow.
71 * The id of this block's ExnNode, or NoExnNodeId if there is none.
73 ExnNodeId exnNodeId
{NoExnNodeId
};
76 * Instructions in the block. Never empty guarantee.
81 * Edges coming out of blocks are repesented in three ways:
83 * - fallthrough edges (the end of the block unconditionally jumps
84 * to the named block). If fallthroughNS is true, this edge
85 * represents a no-surprise jump.
87 * - throwExit (the edges traversed for exceptions from this block)
89 * - Taken edges (these are encoded in the last instruction in hhbcs).
91 * For the idea behind the factored exit edge thing, see "Efficient
92 * and Precise Modeling of Exceptions for the Analysis of Java
93 * Programs" (http://dl.acm.org/citation.cfm?id=316171).
95 BlockId fallthrough
{NoBlockId
};
96 BlockId throwExit
{NoBlockId
};
97 bool catchEntry
{false};
98 bool fallthroughNS
{false};
99 bool multiPred
{false};
100 bool multiSucc
{false};
104 //////////////////////////////////////////////////////////////////////
109 * Each block in the program body can have a pointer to a node in the
110 * exception handler tree. This means they are in all the "exception
111 * regions" for each node in the tree down to that node. This
112 * information is used to construct exception handling regions at emit
115 * The catch region is described in bytecode.specification. Note though
116 * that although it's not specified there, in addition to an entry offset,
117 * these regions optionally list some information about iterators if the
118 * reason the region is there is to free iterator variables.
120 * Exceptional control flow is also represented more explicitly with
121 * factored exit edges (see php::Block). This tree structure just
122 * exists to get the EHEnts right.
125 struct CatchRegion
{ BlockId catchEntry
;
131 CompactVector
<ExnNodeId
> children
;
136 //////////////////////////////////////////////////////////////////////
139 * Metadata about a parameter to a php function.
143 * Default value for this parameter, or KindOfUninit if it has no
149 * Pointer to the block we'll enter for default-value initialization
150 * of this parameter, or nullptr if this parameter had no default
153 BlockId dvEntryPoint
;
156 * Information about the parameter's typehint, if any.
158 * NOTE: this is represented in the repo as a string type name and
159 * some TypeConstraint::Flags.
161 TypeConstraint typeConstraint
;
164 * User-visible version of the type constraint as a string.
165 * Propagated for reflection.
167 LSString userTypeConstraint
;
170 * Evalable php code that will give the default argument. This is
171 * redundant with the dv initializer, but gets propagated through
177 * Each parameter of a func can have arbitrary user attributes.
179 UserAttributeMap userAttributes
;
182 * The type of the arguments for builtin functions, or for HNI
183 * functions with a native implementation. folly::none for
186 folly::Optional
<DataType
> builtinType
;
189 * Whether this parameter is passed as inout.
194 * Whether this parameter is passed by reference.
199 * Whether this parameter is a variadic capture.
204 template <typename T
>
205 struct IntLikeIterator
{
206 explicit IntLikeIterator(T v
) : val
{v
} {}
207 T
operator *() const { return val
; }
208 T
operator ++() { return ++val
; }
209 bool operator !=(IntLikeIterator other
) { return val
!= other
.val
; }
214 template <typename T
>
215 struct IntLikeRange
{
216 explicit IntLikeRange(T v
) : sz
{v
} {}
218 explicit IntLikeRange(const C
& v
) : sz(v
.size()) {}
219 IntLikeIterator
<T
> begin() const { return IntLikeIterator
<T
>{0}; }
220 IntLikeIterator
<T
> end() const { return IntLikeIterator
<T
>{sz
}; }
226 * Metadata about a local variable in a function. Name may be
227 * nullptr, for unnamed locals.
236 * Extra information for function with a HNI native implementation.
240 * Return type from the C++ implementation function, as an optional DataType;
241 * folly::none stands for a Variant return.
243 folly::Optional
<DataType
> returnType
;
247 * Separate out the fields that need special attention when copying,
248 * so that Func can just have default copy/move semantics.
251 FuncBase() = default;
252 FuncBase(const FuncBase
&);
253 FuncBase(FuncBase
&&) = delete;
254 FuncBase
& operator=(const FuncBase
&) = delete;
257 * All owning pointers to blocks are in this vector, which has the
258 * blocks in an unspecified order. Blocks use BlockIds
259 * to represent control flow arcs. The id of a block is its
260 * index in this vector.
262 CompactVector
<copy_ptr
<Block
>> blocks
;
264 auto blockRange() const { return IntLikeRange
<BlockId
> {blocks
}; }
267 * Catch regions form a tree structure. The tree is hanging
268 * off the func here, with children ids. Each block that is
269 * within a catch region has the index into this array of the
270 * inner-most ExnNode protecting it.
272 * Note that this is updated during the concurrent analyze pass.
274 CompactVector
<ExnNode
> exnNodes
;
277 * For HNI-based extensions, additional information for functions
278 * with a native-implementation is here. If this isn't a function
279 * with an HNI-based native implementation, this will be nullptr.
281 std::unique_ptr
<NativeInfo
> nativeInfo
;
285 * Representation of a function, class method, or pseudomain function.
287 struct Func
: FuncBase
{
289 * An index, so we can lookup auxiliary structures efficiently
294 * Basic information about the function.
301 * Parameters, locals, class-refs, and iterators.
303 * There are at least as many locals as parameters (parameters are
304 * also locals---the names of parameters are stored in the locals
308 ClsRefSlotId numClsRefSlots
;
309 CompactVector
<Param
> params
;
310 CompactVector
<Local
> locals
;
313 * Which unit defined this function. If it is a method, the cls
314 * field will be set to the class that contains it.
320 * Entry point blocks for default value initializers.
322 * Note that in PHP you can declare functions where some of the
323 * earlier parameters have default values, and later ones don't. In
324 * this case we'll have NoBlockIds after the first valid entry here.
326 CompactVector
<BlockId
> dvEntries
;
329 * Entry point to the function when the number of passed args is
330 * equal to the number of parameters.
335 * User-visible return type specification as a string. This is only
336 * passed through to expose it to reflection.
338 LSString returnUserType
;
341 * If traits are being flattened by hphpc, we keep the original
342 * filename of a function (the file that defined the trait) so
343 * backtraces and things work correctly. Otherwise this is nullptr.
344 * Similarly, if hhbbc did the flattening itself, we need the original
345 * unit, to get to the srcLocs. Once we stop flattening in hphpc, we can
346 * drop the originalFilename.
348 LSString originalFilename
;
349 Unit
* originalUnit
{};
352 * Whether or not this function is a top-level function. (Defined
353 * outside of any other function body.)
358 * This is the generated function for a closure body. I.e. this
359 * function contains the code that should run when the closure is
362 bool isClosureBody
: 1;
365 * This is an async function.
370 * This is a generator.
372 bool isGenerator
: 1;
375 * This generator yields key value pairs.
377 bool isPairGenerator
: 1;
379 bool isMemoizeWrapper
: 1;
380 bool isMemoizeWrapperLSB
: 1;
382 bool isMemoizeImpl
: 1;
385 * This is a reified function.
389 bool isRxDisabled
: 1;
391 bool noContextSensitiveAnalysis
: 1;
394 * Return type specified in the source code (ex. "function foo(): Bar").
395 * HHVM checks if the a function's return value matches it's return type
396 * constraint via the VerifyRetType* instructions.
398 TypeConstraint retTypeConstraint
;
401 * User attribute list.
403 UserAttributeMap userAttributes
;
406 //////////////////////////////////////////////////////////////////////
411 * Both static and instance properties use this structure.
416 UserAttributeMap userAttributes
;
420 TypeConstraint typeConstraint
;
423 * The default value of the property, for properties with scalar
424 * initializers. May be KindOfUninit in some cases where the
425 * property should not have an initial value (i.e. not even null).
436 // The class that defined this constant.
440 * The value will be KindOfUninit if the class constant is defined
441 * using an 86cinit method.
443 * The lack of a value represents an abstract class constant.
445 folly::Optional
<Cell
> val
;
448 * We pass through eval'able php code and a string type constraint,
449 * only for exposure to reflection.
452 LSString typeConstraint
;
454 bool isTypeconst
: 1;
455 bool isNoOverride
: 1;
459 * Similar to FuncBase - separate the fields that need special
460 * attention when copying.
463 ClassBase() = default;
464 ClassBase(const ClassBase
&);
465 ClassBase(ClassBase
&&) = delete;
466 ClassBase
& operator=(const ClassBase
&) = delete;
469 * Methods on the class. If there's an 86cinit, it must be last.
471 CompactVector
<std::unique_ptr
<php::Func
>> methods
;
475 * Representation of a php class declaration.
477 struct Class
: ClassBase
{
479 * Basic information about the class.
486 * The id used to reference the class within its unit
491 * Which unit defined this class.
496 * Hoistability of this class. See the description in class.h
497 * formation on hoistability.
499 PreClass::Hoistable hoistability
;
502 * Name of the parent class.
507 * If this class represents a closure, this points to the class that
508 * lexically contains the closure, if there was one. If this class
509 * doesn't represent a closure, this will be nullptr.
511 * The significance of this is that closures created lexically
512 * inside of a class run as if they were part of that class context
513 * (with regard to access checks, etc).
515 php::Class
* closureContextCls
;
518 * Names of inherited interfaces.
520 CompactVector
<LowStringPtr
> interfaceNames
;
523 * Names of used traits, number of declared (i.e., non-trait, non-inherited)
524 * methods, trait alias/precedence rules (if any).
526 * This is using the exact structures from the runtime PreClass. In
527 * WholeProgram mode, we won't see these because traits will already be
530 CompactVector
<LowStringPtr
> usedTraitNames
;
531 CompactVector
<PreClass::ClassRequirement
> requirements
;
532 CompactVector
<PreClass::TraitPrecRule
> traitPrecRules
;
533 CompactVector
<PreClass::TraitAliasRule
> traitAliasRules
;
536 * Properties defined on this class.
538 CompactVector
<Prop
> properties
;
541 * Constants defined on this class.
543 CompactVector
<Const
> constants
;
546 * User attributes for this class declaration.
548 UserAttributeMap userAttributes
;
551 * The underlying base type, if this is an enum
553 TypeConstraint enumBaseTy
;
556 * This is a reified class.
558 bool hasReifiedGenerics
: 1;
561 //////////////////////////////////////////////////////////////////////
563 using TypeAlias
= ::HPHP::TypeAlias
;
565 //////////////////////////////////////////////////////////////////////
575 TypeConstraint typeConstraint
;
576 UserAttributeMap userAttributes
;
579 * Representation of a Hack record
588 UserAttributeMap userAttributes
;
589 CompactVector
<RecordField
> fields
;
592 //////////////////////////////////////////////////////////////////////
594 * Representation of a php file (normal compilation unit).
599 bool isHHFile
{false};
600 std::atomic
<bool> persistent
{true};
601 std::atomic
<bool> persistent_pseudomain
{false};
602 std::unique_ptr
<Func
> pseudomain
;
603 CompactVector
<std::unique_ptr
<Func
>> funcs
;
604 CompactVector
<std::unique_ptr
<Class
>> classes
;
605 CompactVector
<std::unique_ptr
<Record
>> records
;
606 CompactVector
<std::unique_ptr
<TypeAlias
>> typeAliases
;
607 CompactVector
<std::pair
<SString
,SString
>> classAliases
;
608 CompactVector
<SrcLoc
> srcLocs
;
609 UserAttributeMap metaData
;
610 UserAttributeMap fileAttributes
;
614 * A php Program is a set of compilation units.
617 explicit Program(size_t numUnitsGuess
) :
620 constInits(100 + (numUnitsGuess
/ 4), 0) {
623 std::vector
<std::unique_ptr
<Unit
>> units
;
624 std::atomic
<uint32_t> nextFuncId
;
625 std::atomic
<size_t> nextConstInit
;
626 AtomicVector
<php::Func
*> constInits
;
629 //////////////////////////////////////////////////////////////////////
631 std::string
show(const Func
&);
632 std::string
show(const Func
&, const Block
&);
633 std::string
show(const Func
&, const Bytecode
& bc
);
634 std::string
show(const Class
&, bool normalizeClosures
= false);
635 std::string
show(const Unit
&, bool normalizeClosures
= false);
636 std::string
show(const Program
&);
637 std::string
local_string(const Func
&, LocalId
);
639 inline std::string
show(const Func
* f
, const Bytecode
& bc
) {
643 //////////////////////////////////////////////////////////////////////
645 bool check(const Func
&);
646 bool check(const Class
&);
647 bool check(const Unit
&);
648 bool check(const Program
&);
650 //////////////////////////////////////////////////////////////////////