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 +----------------------------------------------------------------------+
22 #include <unordered_map>
26 #include <boost/variant.hpp>
28 #include "hphp/util/atomic-vector.h"
29 #include "hphp/util/compact-vector.h"
30 #include "hphp/util/copy-ptr.h"
31 #include "hphp/util/sha1.h"
33 #include "hphp/runtime/base/user-attributes.h"
34 #include "hphp/runtime/vm/coeffects.h"
35 #include "hphp/runtime/vm/constant.h"
36 #include "hphp/runtime/vm/func.h"
37 #include "hphp/runtime/vm/preclass.h"
38 #include "hphp/runtime/vm/type-alias.h"
39 #include "hphp/runtime/vm/type-constraint.h"
41 #include "hphp/hhbbc/bc.h"
42 #include "hphp/hhbbc/misc.h"
43 #include "hphp/hhbbc/src-loc.h"
45 namespace HPHP::HHBBC::php
{
47 //////////////////////////////////////////////////////////////////////
54 //////////////////////////////////////////////////////////////////////
61 //////////////////////////////////////////////////////////////////////
64 * A basic block in our factored control flow graph.
66 * Blocks terminate on control flow, except exceptional control flow.
67 * We keep a set of "throw exits" representing all possible early
68 * exits due to exceptional control flow.
72 * Instructions in the block. Never empty guarantee.
77 * The id of this block's ExnNode, or NoExnNodeId if there is none.
79 ExnNodeId exnNodeId
{NoExnNodeId
};
82 * Edges coming out of blocks are repesented in three ways:
84 * - fallthrough edges (the end of the block unconditionally jumps
85 * to the named block). If fallthroughNS is true, this edge
86 * represents a no-surprise jump.
88 * - throwExit (the edges traversed for exceptions from this block)
90 * - Taken edges (these are encoded in the last instruction in hhbcs).
92 * For the idea behind the factored exit edge thing, see "Efficient
93 * and Precise Modeling of Exceptions for the Analysis of Java
94 * Programs" (http://dl.acm.org/citation.cfm?id=316171).
96 BlockId fallthrough
{NoBlockId
};
97 BlockId throwExit
{NoBlockId
};
100 uint8_t initializer
{0};
103 bool fallthroughNS
: 1;
111 //////////////////////////////////////////////////////////////////////
116 * Each block in the program body can have a pointer to a node in the
117 * exception handler tree. This means they are in all the "exception
118 * regions" for each node in the tree down to that node. This
119 * information is used to construct exception handling regions at emit
122 * The catch region is described in bytecode.specification. Note though
123 * that although it's not specified there, in addition to an entry offset,
124 * these regions optionally list some information about iterators if the
125 * reason the region is there is to free iterator variables.
127 * Exceptional control flow is also represented more explicitly with
128 * factored exit edges (see php::Block). This tree structure just
129 * exists to get the EHEnts right.
132 struct CatchRegion
{ BlockId catchEntry
;
138 CompactVector
<ExnNodeId
> children
;
143 //////////////////////////////////////////////////////////////////////
146 * Metadata about a parameter to a php function.
150 * Default value for this parameter, or KindOfUninit if it has no
153 TypedValue defaultValue
;
156 * Pointer to the block we'll enter for default-value initialization
157 * of this parameter, or nullptr if this parameter had no default
160 BlockId dvEntryPoint
;
163 * Information about the parameter's typehint, if any.
165 * NOTE: this is represented in the repo as a string type name and
166 * some TypeConstraint::Flags.
168 TypeConstraint typeConstraint
;
171 * User-visible version of the type constraint as a string.
172 * Propagated for reflection.
174 LSString userTypeConstraint
;
176 CompactVector
<TypeConstraint
> upperBounds
;
179 * Each parameter of a func can have arbitrary user attributes.
181 UserAttributeMap userAttributes
;
184 * Evalable php code that will give the default argument. This is
185 * redundant with the dv initializer, but gets propagated through
191 * The type of the arguments for builtin functions, or for HNI
192 * functions with a native implementation. std::nullopt for
195 Optional
<DataType
> builtinType
;
198 * Whether this parameter is passed as inout.
203 * Whether this parameter is passed as readonly.
208 * Whether this parameter is a variadic capture.
214 * Metadata about a local variable in a function. Name may be
215 * nullptr, for unnamed locals.
221 uint32_t nameId
: 31;
222 uint32_t unusedName
: 1;
226 * Extra information for function with a HNI native implementation.
230 * Return type from the C++ implementation function, as an optional DataType;
231 * std::nullopt stands for a Variant return.
233 Optional
<DataType
> returnType
;
236 using BlockVec
= CompactVector
<copy_ptr
<Block
>>;
239 * Separate out the fields that need special attention when copying,
240 * so that Func can just have default copy/move semantics.
243 FuncBase() = default;
244 FuncBase(const FuncBase
&);
245 FuncBase(FuncBase
&&) = delete;
246 FuncBase
& operator=(const FuncBase
&) = delete;
249 * Catch regions form a tree structure. The tree is hanging
250 * off the func here, with children ids. Each block that is
251 * within a catch region has the index into this array of the
252 * inner-most ExnNode protecting it.
254 * Note that this is updated during the concurrent analyze pass.
256 CompactVector
<ExnNode
> exnNodes
;
259 * For HNI-based extensions, additional information for functions
260 * with a native-implementation is here. If this isn't a function
261 * with an HNI-based native implementation, this will be nullptr.
263 std::unique_ptr
<NativeInfo
> nativeInfo
;
267 * All owning pointers to blocks are in this vector, which has the
268 * blocks in an unspecified order. Blocks use BlockIds to represent
269 * control flow arcs. The id of a block is its index in this vector.
271 * Use WideFunc to access this data.
273 copy_ptr
<CompactVector
<char>> rawBlocks
;
275 friend struct WideFunc
;
279 * Representation of a function, class method, or pseudomain function.
281 struct Func
: FuncBase
{
283 * An index, so we can lookup auxiliary structures efficiently
288 * Basic information about the function.
295 * Parameters and locals.
297 * There are at least as many locals as parameters (parameters are also
298 * locals - the names of parameters are stored in the locals vector.)
300 CompactVector
<Param
> params
;
301 CompactVector
<Local
> locals
;
305 * Which unit defined this function. If it is a method, the cls
306 * field will be set to the class that contains it.
312 * Entry point blocks for default value initializers.
314 * Note that in PHP you can declare functions where some of the
315 * earlier parameters have default values, and later ones don't. In
316 * this case we'll have NoBlockIds after the first valid entry here.
318 CompactVector
<BlockId
> dvEntries
;
321 * The number of (nested) iterators used within this function.
326 * The number of closures used within this function.
328 ClosureId numClosures
;
331 * Entry point to the function when the number of passed args is
332 * equal to the number of parameters.
337 * User-visible return type specification as a string. This is only
338 * passed through to expose it to reflection.
340 LSString returnUserType
;
343 * If traits are being flattened by hphpc, we keep the original
344 * filename of a function (the file that defined the trait) so
345 * backtraces and things work correctly. Otherwise this is nullptr.
346 * Similarly, if hhbbc did the flattening itself, we need the original
347 * unit, to get to the srcLocs. Once we stop flattening in hphpc, we can
348 * drop the originalFilename.
350 LSString originalFilename
;
351 Unit
* originalUnit
{};
354 * The refernece of the trait where the method was originally defined.
355 * This is used to detected if a method is imported multiple
356 * times via different use-chains as the pair (name, originalClass)
357 * uniquely identifies a method.
359 Class
* originalClass
;
362 * This is the generated function for a closure body. I.e. this
363 * function contains the code that should run when the closure is
366 bool isClosureBody
: 1;
369 * This is an async function.
374 * This is a generator.
376 bool isGenerator
: 1;
379 * This generator yields key value pairs.
381 bool isPairGenerator
: 1;
383 bool isMemoizeWrapper
: 1;
384 bool isMemoizeWrapperLSB
: 1;
386 bool isMemoizeImpl
: 1;
389 * This is a reified function.
393 bool noContextSensitiveAnalysis
: 1;
395 bool hasInOutArgs
: 1;
397 bool sampleDynamicCalls
: 1;
399 bool hasCreateCl
: 1; // Function has CreateCl opcode
401 bool isReadonlyReturn
: 1;
403 bool isReadonlyThis
: 1;
406 * Type parameter upper bounds. May be enforced and used for optimizations.
408 bool hasParamsWithMultiUBs
: 1;
409 bool hasReturnWithMultiUBs
: 1;
410 CompactVector
<TypeConstraint
> returnUBs
;
413 * Return type specified in the source code (ex. "function foo(): Bar").
414 * HHVM checks if the a function's return value matches it's return type
415 * constraint via the VerifyRetType* instructions.
417 TypeConstraint retTypeConstraint
;
420 * Static coeffects in bit encoding
422 RuntimeCoeffects requiredCoeffects
{RuntimeCoeffects::none()};
423 RuntimeCoeffects coeffectEscapes
{RuntimeCoeffects::none()};
426 * Lists of all static coeffect names and coeffect rules
428 CompactVector
<LowStringPtr
> staticCoeffects
;
429 CompactVector
<CoeffectRule
> coeffectRules
;
432 * User attribute list.
434 UserAttributeMap userAttributes
;
438 //////////////////////////////////////////////////////////////////////
443 * Both static and instance properties use this structure.
448 UserAttributeMap userAttributes
;
452 TypeConstraint typeConstraint
;
453 CompactVector
<TypeConstraint
> ubs
;
456 * The default value of the property, for properties with scalar
457 * initializers. May be KindOfUninit in some cases where the
458 * property should not have an initial value (i.e. not even null).
469 // The class that defined this constant.
473 * The value will be KindOfUninit if the class constant is defined
474 * using an 86cinit method.
477 Optional
<TypedValue
> val
;
479 std::vector
<LowStringPtr
> coeffects
;
481 SArray resolvedTypeStructure
;
483 ConstModifiers::Kind kind
;
485 using Invariance
= PreClass::Const::Invariance
;
486 Invariance invariance
: 2;
488 bool isFromTrait
: 1;
492 * Similar to FuncBase - separate the fields that need special
493 * attention when copying.
496 ClassBase() = default;
497 ClassBase(const ClassBase
&);
498 ClassBase(ClassBase
&&) = delete;
499 ClassBase
& operator=(const ClassBase
&) = delete;
502 * Methods on the class. If there's an 86cinit, it must be last.
504 CompactVector
<std::unique_ptr
<php::Func
>> methods
;
508 * Representation of a php class declaration.
510 struct Class
: ClassBase
{
512 * Basic information about the class.
519 * The id used to reference the class within its unit
524 * Which unit defined this class.
529 * Name of the parent class.
534 * If this class represents a closure, this points to the class that
535 * lexically contains the closure, if there was one. If this class
536 * doesn't represent a closure, this will be nullptr.
538 * The significance of this is that closures created lexically
539 * inside of a class run as if they were part of that class context
540 * (with regard to access checks, etc).
542 php::Class
* closureContextCls
;
545 * Names of inherited interfaces.
547 CompactVector
<LowStringPtr
> interfaceNames
;
550 * Names of included enums.
552 CompactVector
<LowStringPtr
> includedEnumNames
;
555 * Names of used traits, number of declared (i.e., non-trait, non-inherited)
556 * methods, trait alias/precedence rules (if any).
558 * This is using the exact structures from the runtime PreClass. In
559 * WholeProgram mode, we won't see these because traits will already be
562 CompactVector
<LowStringPtr
> usedTraitNames
;
563 CompactVector
<PreClass::ClassRequirement
> requirements
;
564 CompactVector
<PreClass::TraitPrecRule
> traitPrecRules
;
565 CompactVector
<PreClass::TraitAliasRule
> traitAliasRules
;
568 * Properties defined on this class.
570 CompactVector
<Prop
> properties
;
573 * Constants defined on this class.
575 CompactVector
<Const
> constants
;
578 * User attributes for this class declaration.
580 UserAttributeMap userAttributes
;
583 * The underlying base type, if this is an enum
585 TypeConstraint enumBaseTy
;
588 * This is a reified class.
590 bool hasReifiedGenerics
: 1;
592 * This class has at least one const instance property.
594 bool hasConstProp
: 1;
596 * Dynamic construction of this class can yield at most a warning and is
597 * sampled at a user defined rate.
599 bool sampleDynamicConstruct
: 1;
616 bool nullable
; // null is allowed; for ?Foo aliases
617 UserAttributeMap userAttrs
;
618 Array typeStructure
{ArrayData::CreateDict()};
619 Array resolvedTypeStructure
;
622 //////////////////////////////////////////////////////////////////////
625 * Information regarding a runtime/parse error in a unit
628 Location::Range fatalLoc
;
630 std::string fatalMsg
;
634 * Representation of a php file (normal compilation unit).
640 std::unique_ptr
<FatalInfo
> fatalInfo
{nullptr};
641 CompactVector
<std::unique_ptr
<Func
>> funcs
;
642 CompactVector
<std::unique_ptr
<Class
>> classes
;
643 CompactVector
<std::unique_ptr
<TypeAlias
>> typeAliases
;
644 CompactVector
<std::unique_ptr
<Constant
>> constants
;
645 CompactVector
<SrcLoc
> srcLocs
;
646 UserAttributeMap metaData
;
647 UserAttributeMap fileAttributes
;
651 * A php Program is a set of compilation units.
655 std::atomic
<uint32_t> nextFuncId
{};
656 std::vector
<std::unique_ptr
<Unit
>> units
;
657 std::vector
<php::Func
*> constInits
;
660 //////////////////////////////////////////////////////////////////////
662 std::string
show(const Func
&);
663 std::string
show(const Func
&, const Block
&);
664 std::string
show(const Func
&, const Bytecode
& bc
);
665 std::string
show(const Class
&);
666 std::string
show(const Unit
&);
667 std::string
show(const Program
&);
668 std::string
local_string(const Func
&, LocalId
);
670 inline std::string
show(const Func
* f
, const Bytecode
& bc
) {
674 //////////////////////////////////////////////////////////////////////
676 bool check(const Func
&);
677 bool check(const Class
&);
678 bool check(const Unit
&);
679 bool check(const Program
&);
681 //////////////////////////////////////////////////////////////////////