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 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_ANALYSIS_RESULT_H_
18 #define incl_HPHP_ANALYSIS_RESULT_H_
20 #include "hphp/compiler/code_generator.h"
21 #include "hphp/compiler/analysis/code_error.h"
22 #include "hphp/compiler/option.h"
23 #include "hphp/compiler/analysis/block_scope.h"
24 #include "hphp/compiler/analysis/symbol_table.h"
25 #include "hphp/compiler/analysis/function_container.h"
26 #include "hphp/compiler/package.h"
27 #include "hphp/compiler/hphp.h"
29 #include "hphp/util/string-bag.h"
30 #include "hphp/util/thread-local.h"
32 #include <tbb/concurrent_hash_map.h>
41 ///////////////////////////////////////////////////////////////////////////////
44 DECLARE_EXTENDED_BOOST_TYPES(ClassScope
);
45 DECLARE_EXTENDED_BOOST_TYPES(FileScope
);
46 DECLARE_BOOST_TYPES(FunctionScope
);
47 DECLARE_BOOST_TYPES(AnalysisResult
);
48 DECLARE_BOOST_TYPES(ScalarExpression
);
52 struct AnalysisResult
: BlockScope
, FunctionContainer
{
54 * There are multiple passes over our syntax trees. This lists all of them.
70 enum GlobalSymbolType
{
71 KindOfStaticGlobalVariable
,
72 KindOfDynamicGlobalVariable
,
73 KindOfMethodStaticVariable
,
74 KindOfClassStaticVariable
,
75 KindOfDynamicConstant
,
77 KindOfRedeclaredFunction
,
78 KindOfRedeclaredClass
,
79 KindOfRedeclaredClassId
,
81 KindOfLazyStaticInitializer
,
87 explicit Locker(const AnalysisResult
*ar
) :
88 m_ar(const_cast<AnalysisResult
*>(ar
)),
89 m_mutex(m_ar
->getMutex()) {
92 explicit Locker(AnalysisResultConstPtr ar
) :
93 m_ar(const_cast<AnalysisResult
*>(ar
.get())),
94 m_mutex(m_ar
->getMutex()) {
97 Locker(const Locker
&l
) : m_ar(l
.m_ar
), m_mutex(l
.m_mutex
) {
98 const_cast<Locker
&>(l
).m_ar
= 0;
101 if (m_ar
) m_mutex
.unlock();
103 AnalysisResultPtr
get() const {
104 return m_ar
->shared_from_this();
106 AnalysisResult
*operator->() const {
110 AnalysisResult
*m_ar
;
116 ~AnalysisResult() override
;
117 Locker
lock() const { return Locker(this); }
118 void setPackage(Package
*package
) { m_package
= package
;}
119 void setParseOnDemand(bool v
) { m_parseOnDemand
= v
;}
120 bool isParseOnDemand() const { return m_package
&& m_parseOnDemand
;}
121 void setParseOnDemandDirs(const std::vector
<std::string
> &dirs
) {
122 assert(m_package
&& !m_parseOnDemand
);
123 m_parseOnDemandDirs
= dirs
;
125 void setFinish(std::function
<void(AnalysisResultPtr
)>&& fn
) {
126 m_finish
= std::move(fn
);
131 * create_function() generates extra PHP code that defines the lambda.
132 * Stores the code in a temporary string, so we can parse this as an
133 * extra file appended to parsed code.
135 void appendExtraCode(const std::string
&key
, const std::string
&code
);
136 void appendExtraCode(const std::string
&key
, const std::string
&code
) const;
137 void parseExtraCode(const std::string
&key
);
139 Phase
getPhase() const { return m_phase
;}
140 void setPhase(Phase phase
) { m_phase
= phase
;}
142 int getFunctionCount() const;
143 int getClassCount() const;
145 void addEntryPoint(const std::string
&name
);
146 void addEntryPoints(const std::vector
<std::string
> &names
);
148 void addNSFallbackFunc(ConstructPtr c
, FileScopePtr fs
);
150 void addSystemFunction(FunctionScopeRawPtr fs
);
151 void addSystemClass(ClassScopeRawPtr cs
);
152 void analyzeProgram(bool system
= false);
153 void analyzeProgramFinal();
156 void visitFiles(void (*cb
)(AnalysisResultPtr
, StatementPtr
, void*),
159 void getScopesSet(BlockScopeRawPtrQueue
&v
);
164 * Code generation functions.
166 bool outputAllPHP(CodeGenerator::Output output
);
169 * Parser creates a FileScope upon parsing a new file.
171 void parseOnDemand(const std::string
&name
) const;
172 void parseOnDemandByClass(const std::string
&name
) const {
173 parseOnDemandBy(name
, Option::AutoloadClassMap
);
175 void parseOnDemandByFunction(const std::string
&name
) const {
176 parseOnDemandBy(name
, Option::AutoloadFuncMap
);
178 void parseOnDemandByConstant(const std::string
&name
) const {
179 parseOnDemandBy(name
, Option::AutoloadConstMap
);
182 void parseOnDemandBy(const std::string
&name
,
183 const Map
& amap
) const;
184 FileScopePtr
findFileScope(const std::string
&name
) const;
185 const StringToFileScopePtrMap
&getAllFiles() { return m_files
;}
186 const std::vector
<FileScopePtr
> &getAllFilesVector() {
190 void addFileScope(FileScopePtr fileScope
);
195 bool declareFunction(FunctionScopePtr funcScope
) const;
196 bool declareClass(ClassScopePtr classScope
) const;
197 void declareUnknownClass(const std::string
&name
);
198 bool declareConst(FileScopePtr fs
, const std::string
&name
);
200 ClassScopePtr
findClass(const std::string
&className
) const;
203 * Find all the redeclared classes by the name, excluding system classes.
204 * Note that system classes cannot be redeclared.
206 const std::vector
<ClassScopePtr
>& findRedeclaredClasses(
207 const std::string
&className
) const;
210 * Find all the classes by the name, including system classes.
212 std::vector
<ClassScopePtr
> findClasses(const std::string
&className
) const;
213 ClassScopePtr
findExactClass(ConstructPtr cs
, const std::string
&name
) const;
214 FunctionScopePtr
findFunction(const std::string
&funcName
) const ;
215 BlockScopeConstPtr
findConstantDeclarer(const std::string
&constName
) const {
216 return const_cast<AnalysisResult
*>(this)->findConstantDeclarer(constName
);
218 BlockScopePtr
findConstantDeclarer(const std::string
&constName
);
220 bool isConstantDeclared(const std::string
&constName
) const;
221 bool isConstantRedeclared(const std::string
&constName
) const;
222 bool isSystemConstant(const std::string
&constName
) const;
225 * For function declaration parsing.
227 static std::string
prepareFile(const char *root
, const std::string
&fileName
,
228 bool chop
, bool stripPath
= true);
230 void setOutputPath(const std::string
&path
) {
233 const std::string
&getOutputPath() {
237 void addHhasFile(std::unique_ptr
<UnitEmitter
>&& ue
);
238 std::vector
<std::unique_ptr
<UnitEmitter
>> getHhasFiles();
240 std::function
<void(AnalysisResultPtr
)> m_finish
;
242 bool m_parseOnDemand
;
243 std::vector
<std::string
> m_parseOnDemandDirs
;
244 std::set
<std::pair
<ConstructPtr
, FileScopePtr
> > m_nsFallbackFuncs
;
246 StringToFileScopePtrMap m_files
;
247 std::vector
<FileScopePtr
> m_fileScopes
;
248 std::vector
<std::unique_ptr
<UnitEmitter
>> m_hhasFiles
;
250 StringBag m_extraCodeFileNames
;
251 std::map
<std::string
, std::string
> m_extraCodes
;
253 StringToClassScopePtrMap m_systemClasses
;
254 StringToFunctionScopePtrMap m_functionDecs
;
255 StringToFunctionScopePtrVecMap m_functionReDecs
;
256 StringToClassScopePtrVecMap m_classDecs
;
257 StringToFileScopePtrMap m_constDecs
;
258 std::set
<std::string
> m_constRedeclared
;
260 // Names of type aliases.
261 std::set
<std::string
> m_typeAliasNames
;
263 std::vector
<StatementPtr
> m_stmts
;
266 std::string m_outputPath
;
268 AnalysisResultPtr
shared_from_this() {
269 return static_pointer_cast
<AnalysisResult
>
270 (BlockScope::shared_from_this());
273 AnalysisResultConstPtr
shared_from_this() const {
274 return static_pointer_cast
<const AnalysisResult
>
275 (BlockScope::shared_from_this());
279 std::vector
<BlockScopePtr
> m_ignoredScopes
;
282 * Checks whether the file is in one of the on-demand parsing directories.
284 bool inParseOnDemandDirs(const std::string
&filename
) const;
287 * Find the names of all functions and classes in the program; mark
288 * functions with duplicate names as redeclaring, but duplicate
289 * classes aren't yet marked. See markRedeclaringClasses.
291 void collectFunctionsAndClasses(FileScopePtr fs
);
294 * Making sure symbol orders are not different even with multithreading, so
295 * to make sure generated code are consistent every time.
297 void canonicalizeSymbolOrder();
300 * After all the class names have been collected and symbol order is
301 * canonicalized, this passes through and marks duplicate class
302 * names as redeclaring.
304 void markRedeclaringClasses();
307 * Checks circular class derivations that can cause stack overflows for
308 * subsequent analysis. Also checks to make sure no two redundant parents.
310 void checkClassDerivations();
312 void resolveNSFallbackFuncs();
314 int getFileSize(FileScopePtr fs
);
317 static DECLARE_THREAD_LOCAL(BlockScopeRawPtr
, s_currentScopeThreadLocal
);
318 static DECLARE_THREAD_LOCAL(BlockScopeRawPtrFlagsHashMap
,
319 s_changedScopesMapThreadLocal
);
322 void processScopesParallel(const char* id
, void* context
= nullptr);
325 ///////////////////////////////////////////////////////////////////////////////
327 #endif // incl_HPHP_ANALYSIS_RESULT_H_