PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/compiler/analysis/function_scope.h

https://gitlab.com/Blueprint-Marketing/hhvm
C Header | 444 lines | 270 code | 73 blank | 101 comment | 6 complexity | 6ed95c19f571210a887ea0e04b4b076b MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2014 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. +----------------------------------------------------------------------+
  15. */
  16. #ifndef incl_HPHP_FUNCTION_SCOPE_H_
  17. #define incl_HPHP_FUNCTION_SCOPE_H_
  18. #include "hphp/compiler/expression/user_attribute.h"
  19. #include <list>
  20. #include <set>
  21. #include <utility>
  22. #include <vector>
  23. #include "hphp/compiler/analysis/block_scope.h"
  24. #include "hphp/compiler/option.h"
  25. #include "hphp/compiler/json.h"
  26. #include "hphp/util/hash-map-typedefs.h"
  27. #include "hphp/parser/parser.h"
  28. namespace HPHP {
  29. ///////////////////////////////////////////////////////////////////////////////
  30. DECLARE_BOOST_TYPES(Type);
  31. DECLARE_BOOST_TYPES(Construct);
  32. DECLARE_BOOST_TYPES(ExpressionList);
  33. DECLARE_BOOST_TYPES(FileScope);
  34. DECLARE_BOOST_TYPES(AnalysisResult);
  35. DECLARE_BOOST_TYPES(FunctionScope);
  36. DECLARE_BOOST_TYPES(Expression);
  37. DECLARE_BOOST_TYPES(SimpleFunctionCall);
  38. DECLARE_BOOST_TYPES(ClassScope);
  39. DECLARE_BOOST_TYPES(ParameterExpression);
  40. DECLARE_BOOST_TYPES(MethodStatement);
  41. class CodeGenerator;
  42. typedef ExpressionPtr (*FunctionOptPtr)(CodeGenerator *cg,
  43. AnalysisResultConstPtr ar,
  44. SimpleFunctionCallPtr, int);
  45. typedef std::pair< ParameterExpressionPtr, int >
  46. ParameterExpressionPtrIdxPair;
  47. typedef std::vector< ParameterExpressionPtrIdxPair >
  48. ParameterExpressionPtrIdxPairVec;
  49. /**
  50. * A FunctionScope corresponds to a function declaration. We store all
  51. * inferred types and analyzed results here, so not to pollute syntax trees.
  52. */
  53. class FunctionScope : public BlockScope,
  54. public JSON::CodeError::ISerializable,
  55. public JSON::DocTarget::ISerializable {
  56. public:
  57. /**
  58. * User defined functions.
  59. */
  60. FunctionScope(AnalysisResultConstPtr ar, bool method,
  61. const std::string &name, StatementPtr stmt,
  62. bool reference, int minParam, int maxParam,
  63. ModifierExpressionPtr modifiers, int attribute,
  64. const std::string &docComment,
  65. FileScopePtr file,
  66. const std::vector<UserAttributePtr> &attrs,
  67. bool inPseudoMain = false);
  68. FunctionScope(FunctionScopePtr orig, AnalysisResultConstPtr ar,
  69. const std::string &name, const std::string &originalName,
  70. StatementPtr stmt, ModifierExpressionPtr modifiers, bool user);
  71. /**
  72. * System functions.
  73. */
  74. FunctionScope(bool method, const std::string &name, bool reference);
  75. void setParamCounts(AnalysisResultConstPtr ar,
  76. int minParam, int numDeclParam);
  77. void setParamName(int index, const std::string &name);
  78. void setRefParam(int index);
  79. bool hasRefParam(int max) const;
  80. void addModifier(int mod);
  81. bool hasUserAttr(const char *attr) const;
  82. /**
  83. * What kind of function this is.
  84. */
  85. bool isUserFunction() const { return !m_system && !isNative(); }
  86. bool isSystem() const { return m_system; }
  87. bool isDynamic() const { return m_dynamic; }
  88. bool isPublic() const;
  89. bool isProtected() const;
  90. bool isPrivate() const;
  91. bool isStatic() const;
  92. bool isAbstract() const;
  93. bool isNative() const;
  94. bool isFinal() const;
  95. bool isMagic() const;
  96. bool isBuiltin() const override { return !getStmt() || isNative(); }
  97. bool isRefParam(int index) const;
  98. bool isRefReturn() const { return m_refReturn;}
  99. bool isDynamicInvoke() const { return m_dynamicInvoke; }
  100. void setDynamicInvoke();
  101. bool hasImpl() const;
  102. bool isParamCoerceMode() const;
  103. bool mayContainThis();
  104. bool isClosure() const;
  105. bool isGenerator() const { return m_generator; }
  106. void setGenerator(bool f) { m_generator = f; }
  107. bool isAsync() const { return m_async; }
  108. void setAsync(bool f) { m_async = f; }
  109. int nextInlineIndex() { return ++m_inlineIndex; }
  110. bool usesLSB() const { return !m_noLSB; }
  111. void clearUsesLSB() { m_noLSB = true; }
  112. bool nextLSB() const { return m_nextLSB; }
  113. void setNextLSB(bool f) { m_nextLSB = f; }
  114. void setHasGoto() { m_hasGoto = true; }
  115. void setHasTry() { m_hasTry = true; }
  116. bool hasGoto() const { return m_hasGoto; }
  117. bool hasTry() const { return m_hasTry; }
  118. unsigned getNewID() { return m_nextID++; }
  119. bool needsLocalThis() const;
  120. /**
  121. * Either __construct or a class-name constructor.
  122. */
  123. bool isConstructor(ClassScopePtr cls) const;
  124. const std::string &getParamName(int index) const;
  125. const std::string &name() const {
  126. return getName();
  127. }
  128. int getRedeclaringId() const {
  129. return m_redeclaring;
  130. }
  131. void setDynamic() {
  132. m_dynamic = true;
  133. }
  134. void setSystem() {
  135. m_system = true;
  136. m_volatile = false;
  137. }
  138. /**
  139. * Tell this function about another outer scope that contains it.
  140. */
  141. void addClonedTraitOuterScope(FunctionScopePtr scope) {
  142. m_clonedTraitOuterScope.push_back(scope);
  143. }
  144. /**
  145. * Get/set original name of the function, without case being lowered.
  146. */
  147. const std::string &getOriginalName() const;
  148. void setOriginalName(const std::string &name) { m_originalName = name; }
  149. std::string getDocName() const;
  150. std::string getDocFullName() const;
  151. /**
  152. * If class method, returns class::name, otherwise just name.
  153. */
  154. std::string getFullName() const;
  155. std::string getOriginalFullName() const;
  156. /**
  157. * Whether this function can take variable number of arguments.
  158. */
  159. bool allowsVariableArguments() const;
  160. bool hasVariadicParam() const;
  161. bool usesVariableArgumentFunc() const;
  162. bool isReferenceVariableArgument() const;
  163. void setVariableArgument(int reference);
  164. /**
  165. * Whether this function has no side effects
  166. */
  167. bool hasEffect() const;
  168. void setNoEffect();
  169. /**
  170. * Whether this function can be constant folded
  171. */
  172. bool isFoldable() const;
  173. void setIsFoldable();
  174. /*
  175. * If this is a builtin function and does not need an ActRec
  176. */
  177. bool noFCallBuiltin() const;
  178. void setNoFCallBuiltin();
  179. /*
  180. * If this is a builtin (C++ or PHP) and can be redefined
  181. */
  182. bool allowOverride() const;
  183. void setAllowOverride();
  184. bool needsFinallyLocals() const;
  185. /**
  186. * Whether this function is a runtime helper function
  187. */
  188. void setHelperFunction();
  189. /**
  190. * Whether this function returns reference or has reference parameters.
  191. */
  192. bool containsReference() const;
  193. /**
  194. * Whether this function contains a usage of $this
  195. */
  196. bool containsThis() const { return m_containsThis;}
  197. void setContainsThis(bool f = true);
  198. bool containsBareThis() const { return m_containsBareThis; }
  199. bool containsRefThis() const { return m_containsBareThis & 2; }
  200. void setContainsBareThis(bool f, bool ref = false);
  201. /**
  202. * How many parameters a caller should provide.
  203. */
  204. int getMinParamCount() const { return m_minParam; }
  205. int getDeclParamCount() const { return m_numDeclParams; }
  206. int getMaxParamCount() const {
  207. return hasVariadicParam() ? (m_numDeclParams-1) : m_numDeclParams;
  208. }
  209. int getOptionalParamCount() const { return getMaxParamCount() - m_minParam;}
  210. /**
  211. * What is the inferred type of this function's return.
  212. * Note that for generators and async functions, this is different
  213. * from what caller actually gets when calling the function.
  214. */
  215. void setReturnType(AnalysisResultConstPtr ar, TypePtr type);
  216. TypePtr getReturnType() const {
  217. return m_returnType;
  218. }
  219. void setOptFunction(FunctionOptPtr fn) { m_optFunction = fn; }
  220. FunctionOptPtr getOptFunction() const { return m_optFunction; }
  221. /**
  222. * Whether this is a virtual function that needs to go through invoke().
  223. * "Overriding" is only being used by magic methods, enforcing parameter
  224. * and return types.
  225. */
  226. void setVirtual() { m_virtual = true;}
  227. bool isVirtual() const { return m_virtual;}
  228. void setHasOverride() { m_hasOverride = true; }
  229. bool hasOverride() const { return m_hasOverride; }
  230. void setOverriding(TypePtr returnType, TypePtr param1 = TypePtr(),
  231. TypePtr param2 = TypePtr());
  232. bool isOverriding() const { return m_overriding;}
  233. /**
  234. * Whether same function name was declared twice or more.
  235. */
  236. void setRedeclaring(int redecId) {
  237. m_redeclaring = redecId;
  238. setVolatile(); // redeclared function is also volatile
  239. }
  240. bool isRedeclaring() const { return m_redeclaring >= 0;}
  241. void setLocalRedeclaring() { m_localRedeclaring = true; }
  242. bool isLocalRedeclaring() const { return m_localRedeclaring; }
  243. /* For function_exists */
  244. void setVolatile() { m_volatile = true; }
  245. bool isVolatile() const { return m_volatile; }
  246. bool isPersistent() const { return m_persistent; }
  247. void setPersistent(bool p) { m_persistent = p; }
  248. /* Indicates if a function may need to use a VarEnv or varargs (aka
  249. * extraArgs) at run time */
  250. bool mayUseVV() const;
  251. TypePtr setParamType(AnalysisResultConstPtr ar, int index, TypePtr type);
  252. TypePtr getParamType(int index);
  253. typedef hphp_hash_map<std::string, ExpressionPtr, string_hashi,
  254. string_eqstri> UserAttributeMap;
  255. UserAttributeMap& userAttributes() { return m_userAttributes;}
  256. std::vector<std::string> getUserAttributeStringParams(const std::string& key);
  257. /**
  258. * Override BlockScope::outputPHP() to generate return type.
  259. */
  260. void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) override;
  261. /**
  262. * Serialize the iface, not everything.
  263. */
  264. void serialize(JSON::CodeError::OutputStream &out) const override;
  265. void serialize(JSON::DocTarget::OutputStream &out) const override;
  266. bool inPseudoMain() const override {
  267. return m_pseudoMain;
  268. }
  269. void setMagicMethod() {
  270. m_magicMethod = true;
  271. }
  272. bool isMagicMethod() const {
  273. return m_magicMethod;
  274. }
  275. void setClosureVars(ExpressionListPtr closureVars) {
  276. m_closureVars = closureVars;
  277. }
  278. ExpressionListPtr getClosureVars() const {
  279. return m_closureVars;
  280. }
  281. void getClosureUseVars(ParameterExpressionPtrIdxPairVec &useVars,
  282. bool filterUsed = true);
  283. void addCaller(BlockScopePtr caller, bool careAboutReturn = true);
  284. void addNewObjCaller(BlockScopePtr caller);
  285. ReadWriteMutex &getInlineMutex() { return m_inlineMutex; }
  286. DECLARE_EXTENDED_BOOST_TYPES(FunctionInfo);
  287. static void RecordFunctionInfo(std::string fname, FunctionScopePtr func);
  288. static FunctionInfoPtr GetFunctionInfo(std::string fname);
  289. class FunctionInfo {
  290. public:
  291. explicit FunctionInfo(int rva = -1)
  292. : m_maybeStatic(false)
  293. /*
  294. * Note: m_maybeRefReturn used to implement an optimization to
  295. * avoid unbox checks when we call functions where we know no
  296. * function with that name returns by reference. This isn't
  297. * correct, however, because __call can return by reference, so
  298. * it's disabled here. (The default to enable it should be
  299. * 'false'.)
  300. */
  301. , m_maybeRefReturn(true)
  302. , m_refVarArg(rva)
  303. {}
  304. bool isRefParam(int p) const {
  305. if (m_refVarArg >= 0 && p >= m_refVarArg) return true;
  306. return (m_refParams.find(p) != m_refParams.end());
  307. }
  308. void setRefVarArg(int rva) {
  309. if (rva > m_refVarArg) m_refVarArg = rva;
  310. }
  311. void setRefParam(int p) {
  312. m_refParams.insert(p);
  313. }
  314. void setMaybeStatic() { m_maybeStatic = true; }
  315. bool getMaybeStatic() { return m_maybeStatic; }
  316. void setMaybeRefReturn() { m_maybeRefReturn = true; }
  317. bool getMaybeRefReturn() { return m_maybeRefReturn; }
  318. private:
  319. bool m_maybeStatic; // this could be a static method
  320. bool m_maybeRefReturn;
  321. int m_refVarArg; // -1: no ref varargs;
  322. // otherwise, any arg >= m_refVarArg is a reference
  323. std::set<int> m_refParams; // set of ref arg positions
  324. };
  325. private:
  326. void init(AnalysisResultConstPtr ar);
  327. static StringToFunctionInfoPtrMap s_refParamInfo;
  328. int m_minParam;
  329. int m_numDeclParams;
  330. int m_attribute;
  331. std::vector<std::string> m_paramNames;
  332. TypePtrVec m_paramTypes;
  333. std::vector<bool> m_refs;
  334. TypePtr m_returnType;
  335. ModifierExpressionPtr m_modifiers;
  336. UserAttributeMap m_userAttributes;
  337. unsigned m_hasVoid : 1;
  338. unsigned m_method : 1;
  339. unsigned m_refReturn : 1; // whether it's "function &get_reference()"
  340. unsigned m_virtual : 1;
  341. unsigned m_hasOverride : 1;
  342. unsigned m_dynamic : 1;
  343. unsigned m_dynamicInvoke : 1;
  344. unsigned m_overriding : 1; // overriding a virtual function
  345. unsigned m_volatile : 1; // for function_exists
  346. unsigned m_persistent : 1;
  347. unsigned m_pseudoMain : 1;
  348. unsigned m_magicMethod : 1;
  349. unsigned m_system : 1;
  350. unsigned m_containsThis : 1; // contains a usage of $this?
  351. unsigned m_containsBareThis : 2; // $this outside object-context,
  352. // 2 if in reference context
  353. unsigned m_generator : 1;
  354. unsigned m_async : 1;
  355. unsigned m_noLSB : 1;
  356. unsigned m_nextLSB : 1;
  357. unsigned m_hasTry : 1;
  358. unsigned m_hasGoto : 1;
  359. unsigned m_localRedeclaring : 1;
  360. int m_redeclaring; // multiple definition of the same function
  361. int m_inlineIndex;
  362. FunctionOptPtr m_optFunction;
  363. ExpressionListPtr m_closureVars;
  364. ExpressionListPtr m_closureValues;
  365. ReadWriteMutex m_inlineMutex;
  366. unsigned m_nextID; // used when cloning generators for traits
  367. std::list<FunctionScopeRawPtr> m_clonedTraitOuterScope;
  368. };
  369. ///////////////////////////////////////////////////////////////////////////////
  370. }
  371. #endif // incl_HPHP_FUNCTION_SCOPE_H_