slang_rs_object_ref_count.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. * Copyright 2010, The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ // NOLINT
  17. #define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_
  18. #include <list>
  19. #include <stack>
  20. #include <vector>
  21. #include "clang/AST/StmtVisitor.h"
  22. #include "slang_assert.h"
  23. #include "slang_rs_export_type.h"
  24. namespace clang {
  25. class Expr;
  26. class Stmt;
  27. }
  28. namespace slang {
  29. // Recursive check
  30. bool HasRSObjectType(const clang::Type *T);
  31. // This class provides the overall reference counting mechanism for handling
  32. // local variables of RS object types (rs_font, rs_allocation, ...). This
  33. // class ensures that appropriate functions (rsSetObject, rsClearObject) are
  34. // called at proper points in the object's lifetime.
  35. // 1) Each local object of appropriate type must be zero-initialized to
  36. // prevent corruption during subsequent rsSetObject()/rsClearObject() calls.
  37. // 2) Assignments using these types must also be converted into the
  38. // appropriate (possibly a series of) rsSetObject() calls.
  39. // 3) Finally, rsClearObject() must be called for each local object when it goes
  40. // out of scope.
  41. class RSObjectRefCount : public clang::StmtVisitor<RSObjectRefCount> {
  42. private:
  43. class Scope {
  44. private:
  45. clang::CompoundStmt *mCS; // Associated compound statement ({ ... })
  46. clang::Stmt *mCurrent; // The statement currently being analyzed
  47. std::list<clang::VarDecl*> mRSO; // Declared RS objects in this scope (but
  48. // not any scopes nested)
  49. public:
  50. explicit Scope(clang::CompoundStmt *CS) : mCS(CS) {
  51. }
  52. bool hasRSObject() const { return !mRSO.empty(); }
  53. inline void addRSObject(clang::VarDecl* VD) {
  54. mRSO.push_back(VD);
  55. }
  56. void ReplaceRSObjectAssignment(clang::BinaryOperator *AS);
  57. void AppendRSObjectInit(clang::VarDecl *VD,
  58. clang::DeclStmt *DS,
  59. DataType DT,
  60. clang::Expr *InitExpr);
  61. // Inserts rsClearObject() calls at the end and at all exiting points of the
  62. // current scope. At each statement that exits the current scope -- e.g.,
  63. // a return, break, or continue statement in the current or a nested scope
  64. // -- rsClearObject() calls are inserted for local variables defined in the
  65. // current scope before that point.
  66. // Note goto statements are not handled. (See the DestructorVisitor class in
  67. // the .cpp file.)
  68. // Also note this function is called for every nested scope. As a result, for a
  69. // return statement, each rsObject declared in all its (nested) enclosing
  70. // scopes would have a rsClearObject() call properly inserted before
  71. // the return statement.
  72. void InsertLocalVarDestructors();
  73. // Sets the current statement being analyzed
  74. void setCurrentStmt(clang::Stmt *S) { mCurrent = S; }
  75. // Inserts a statement before the current statement
  76. void InsertStmt(const clang::ASTContext &C, clang::Stmt *NewStmt);
  77. // Replaces the current statement with NewStmt;
  78. void ReplaceStmt(const clang::ASTContext &C, clang::Stmt *NewStmt);
  79. // Replaces OldExpr with NewExpr in the current statement
  80. void ReplaceExpr(const clang::ASTContext& C, clang::Expr* OldExpr,
  81. clang::Expr* NewExpr);
  82. static clang::Stmt *ClearRSObject(clang::VarDecl *VD,
  83. clang::DeclContext *DC);
  84. };
  85. clang::ASTContext &mCtx;
  86. std::deque<Scope*> mScopeStack; // A deque used as a stack to store scopes, but also
  87. // accessed through its iterator in read-only mode.
  88. clang::DeclContext* mCurrentDC;
  89. bool RSInitFD; // TODO: this should be static, since this flag affects all instances.
  90. unsigned mTempID; // A unique id that can be used to distinguish temporary variables
  91. // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject()
  92. // and rsClearObject() in the current ASTContext.
  93. static clang::FunctionDecl *RSSetObjectFD[];
  94. static clang::FunctionDecl *RSClearObjectFD[];
  95. inline bool emptyScope() const { return mScopeStack.empty(); }
  96. inline Scope *getCurrentScope() {
  97. return mScopeStack.back();
  98. }
  99. // Returns the next available unique id for temporary variables
  100. unsigned getNextID() { return mTempID++; }
  101. // Initialize RSSetObjectFD and RSClearObjectFD.
  102. static void GetRSRefCountingFunctions(clang::ASTContext &C);
  103. // Return false if the type of variable declared in VD does not contain
  104. // an RS object type.
  105. static bool InitializeRSObject(clang::VarDecl *VD,
  106. DataType *DT,
  107. clang::Expr **InitExpr);
  108. // Return an empty list initializer expression at the appropriate location.
  109. // This construct can then be used to cheaply construct a zero-initializer
  110. // for any RenderScript objects (like rs_allocation) or rs_matrix* types
  111. // (possibly even embedded within other types). These types are expected to
  112. // be zero-initialized always, and so we can use this helper to ensure that
  113. // they at least have an empty initializer.
  114. static clang::Expr *CreateEmptyInitListExpr(
  115. clang::ASTContext &C,
  116. const clang::SourceLocation &Loc);
  117. // Given a return statement RS that returns an rsObject, creates a temporary
  118. // variable, and sets it to the original return expression using rsSetObject().
  119. // Creates a new return statement that returns the temporary variable.
  120. // Returns a new compound statement that contains the new variable declaration,
  121. // the rsSetOjbect() call, and the new return statement.
  122. static clang::CompoundStmt* CreateRetStmtWithTempVar(
  123. clang::ASTContext& C,
  124. clang::DeclContext* DC,
  125. clang::ReturnStmt* RS,
  126. const unsigned id);
  127. public:
  128. explicit RSObjectRefCount(clang::ASTContext &C)
  129. : mCtx(C), RSInitFD(false), mTempID(0) {
  130. }
  131. void Init() {
  132. if (!RSInitFD) {
  133. GetRSRefCountingFunctions(mCtx);
  134. RSInitFD = true;
  135. }
  136. }
  137. // For function parameters and local variables that are or contain RS objects,
  138. // e.g., rs_allocation, this method transforms the function body to correctly
  139. // adjust reference counts of those objects.
  140. void HandleParamsAndLocals(clang::FunctionDecl *FD);
  141. static clang::FunctionDecl *GetRSSetObjectFD(DataType DT) {
  142. slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
  143. if (DT >= 0 && DT < DataTypeMax) {
  144. return RSSetObjectFD[DT];
  145. } else {
  146. slangAssert(false && "incorrect type");
  147. return nullptr;
  148. }
  149. }
  150. static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) {
  151. return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
  152. }
  153. static clang::FunctionDecl *GetRSClearObjectFD(DataType DT) {
  154. slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
  155. if (DT >= 0 && DT < DataTypeMax) {
  156. return RSClearObjectFD[DT];
  157. } else {
  158. slangAssert(false && "incorrect type");
  159. return nullptr;
  160. }
  161. }
  162. static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) {
  163. return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
  164. }
  165. // This method creates a "guard" variable for the expression E that is object-
  166. // typed or object-containing, e.g., a struct with object-type fields.
  167. // It creates one or more rsSetObject() calls to set the value of the guard to E.
  168. // This effectively increases the sysRef count of the objects referenced by E
  169. // by 1, therefore "guarding" the objects, which might otherwise lose a
  170. // reference and get deleted. Statements that declare the new variable and set
  171. // the value of the new variable are added to the vector NewStmts.
  172. //
  173. // Parameters:
  174. // C: The clang AST Context.
  175. // DC: The DeclContext for any new Decl to add
  176. // E: The expression with reference to the objects for which we want to
  177. // increase the sysRef count
  178. // VarName: The name to use for the new guard variable
  179. // NewStmts: The vector for all statements added to create and set the guard.
  180. //
  181. // Returns:
  182. // An expression consisting of the guard variable
  183. //
  184. static clang::DeclRefExpr *CreateGuard(clang::ASTContext &C,
  185. clang::DeclContext *DC,
  186. clang::Expr *E,
  187. const llvm::Twine &VarName,
  188. std::vector<clang::Stmt*> &NewStmts);
  189. // For any function parameter that is object-typed or object-containing, if it
  190. // is overwritten inside the function, a system reference (sysRef) count
  191. // would decrement and may reach 0, leading the object to be deleted. This may
  192. // create a dangling pointer reference after a call to the function.
  193. // For example, the object in parameter a in the function below may be deleted
  194. // before the function returns.
  195. // void foo(rs_allocation a) { // assuming a references obj with sysRef of 1
  196. // rs_allocation b = {};
  197. // a = b; // decrements sysRef of obj and deletes it
  198. // }
  199. //
  200. // To avoid this problem, the sysRef counts of objects contained in parameters
  201. // --directly for object-typed parameters or indirectly as fields for struct-
  202. // typed parameters--are incremented at the beginning of the function, and
  203. // decremented at the end and any exiting point of the function. To achieve
  204. // these effects, the compiler creates a temporary local variable, and calls
  205. // rsSetObject() to set its value to that of the parameter. At the end of the
  206. // function and at any exiting point, the compiler adds calls to
  207. // rsClearObject() on the parameter. Each rsClearObject() call would decrement
  208. // the sysRef count of an incoming object if the parameter is never overwritten
  209. // in the function, or it would properly decrement the sysRef count of the new
  210. // object that the parameter is updated to in the function, since now the
  211. // parameter is going out of scope. For example, the compiler would transform
  212. // the previous code example into the following.
  213. // void foo(rs_allocation a) { // assuming a references obj with sysRef of 1
  214. // rs_allocation .rs.param.a;
  215. // rsSetObject(&.rs.param.a, a); // sysRef of obj becomes 2
  216. // rs_allocation b = {};
  217. // a = b; // sysRef of obj becomes 1
  218. // rsClearObject(&a); // sysRef of obj stays 1. obj stays undeleted.
  219. // }
  220. //
  221. // This method creates the guard variable for a object-type parameter,
  222. // named with the prefix ".rs.param." added to the parameter name. It calls
  223. // CreateGuard() to do this. The rsClearObject() call for the parameter as
  224. // described above is not added by this function, but by the caller of this
  225. // function, i.e., HandleParametersAndLocals().
  226. //
  227. // Parameters:
  228. // C: The clang AST Context.
  229. // DC: The DeclContext for any new Decl to add. It should be the FunctionnDecl
  230. // of the function being transformed.
  231. // PD: The ParmDecl for the parameter.
  232. // NewStmts: The vector for all statements added to create and set the guard.
  233. //
  234. static void CreateParameterGuard(
  235. clang::ASTContext &C,
  236. clang::DeclContext *DC,
  237. clang::ParmVarDecl *PD,
  238. std::vector<clang::Stmt*> &NewStmts);
  239. void SetDeclContext(clang::DeclContext* DC) { mCurrentDC = DC; }
  240. clang::DeclContext* GetDeclContext() const { return mCurrentDC; }
  241. void VisitStmt(clang::Stmt *S);
  242. void VisitCallExpr(clang::CallExpr *CE);
  243. void VisitDeclStmt(clang::DeclStmt *DS);
  244. void VisitCompoundStmt(clang::CompoundStmt *CS);
  245. void VisitBinAssign(clang::BinaryOperator *AS);
  246. void VisitReturnStmt(clang::ReturnStmt *RS);
  247. // We believe that RS objects are never involved in CompoundAssignOperator.
  248. // I.e., rs_allocation foo; foo += bar;
  249. // Emit a global destructor to clean up RS objects.
  250. clang::FunctionDecl *CreateStaticGlobalDtor();
  251. };
  252. } // namespace slang
  253. #endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ NOLINT