blob: fe3154646851c4f1dad33c51b41032d937c38a7d [file] [log] [blame]
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001/*
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
Stephen Hinese639eb52010-11-08 19:27:20 -080017#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ // NOLINT
18#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_
19
20#include <list>
Stephen Hines4b32ffd2010-11-05 18:47:11 -070021#include <stack>
Yang Ni31d2ea32017-04-14 15:44:23 -070022#include <vector>
Stephen Hines4b32ffd2010-11-05 18:47:11 -070023
24#include "clang/AST/StmtVisitor.h"
25
Stephen Hinesf2174cf2011-02-09 23:21:37 -080026#include "slang_assert.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070027#include "slang_rs_export_type.h"
28
Stephen Hines4b32ffd2010-11-05 18:47:11 -070029namespace clang {
30 class Expr;
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -080031 class Stmt;
Stephen Hines4b32ffd2010-11-05 18:47:11 -070032}
33
Stephen Hinese639eb52010-11-08 19:27:20 -080034namespace slang {
35
David Gross65f23ed2016-01-08 12:04:59 -080036// Recursive check
37bool HasRSObjectType(const clang::Type *T);
38
Stephen Hines292e00a2011-03-18 19:11:30 -070039// This class provides the overall reference counting mechanism for handling
40// local variables of RS object types (rs_font, rs_allocation, ...). This
41// class ensures that appropriate functions (rsSetObject, rsClearObject) are
42// called at proper points in the object's lifetime.
Yang Nib478c3d2016-01-15 16:37:04 -080043// 1) Each local object of appropriate type must be zero-initialized to
44// prevent corruption during subsequent rsSetObject()/rsClearObject() calls.
Stephen Hines292e00a2011-03-18 19:11:30 -070045// 2) Assignments using these types must also be converted into the
46// appropriate (possibly a series of) rsSetObject() calls.
Yang Nib478c3d2016-01-15 16:37:04 -080047// 3) Finally, rsClearObject() must be called for each local object when it goes
48// out of scope.
Stephen Hines4b32ffd2010-11-05 18:47:11 -070049class RSObjectRefCount : public clang::StmtVisitor<RSObjectRefCount> {
50 private:
51 class Scope {
52 private:
Yang Nib478c3d2016-01-15 16:37:04 -080053 clang::CompoundStmt *mCS; // Associated compound statement ({ ... })
54 clang::Stmt *mCurrent; // The statement currently being analyzed
55 std::list<clang::VarDecl*> mRSO; // Declared RS objects in this scope (but
56 // not any scopes nested)
Stephen Hines1bdd4972010-11-08 17:35:08 -080057
Stephen Hines4b32ffd2010-11-05 18:47:11 -070058 public:
Stephen Hinese639eb52010-11-08 19:27:20 -080059 explicit Scope(clang::CompoundStmt *CS) : mCS(CS) {
Stephen Hines4b32ffd2010-11-05 18:47:11 -070060 }
61
Yang Nib478c3d2016-01-15 16:37:04 -080062 bool hasRSObject() const { return !mRSO.empty(); }
63
Stephen Hines1bdd4972010-11-08 17:35:08 -080064 inline void addRSObject(clang::VarDecl* VD) {
65 mRSO.push_back(VD);
Stephen Hines4b32ffd2010-11-05 18:47:11 -070066 }
Stephen Hines1bdd4972010-11-08 17:35:08 -080067
Stephen Hinesd0b5edd2011-04-18 16:38:03 -070068 void ReplaceRSObjectAssignment(clang::BinaryOperator *AS);
Stephen Hinesc202d2d2011-01-26 11:57:57 -080069
Stephen Hinesd0b5edd2011-04-18 16:38:03 -070070 void AppendRSObjectInit(clang::VarDecl *VD,
Stephen Hinese79fb5e2011-02-01 19:12:43 -080071 clang::DeclStmt *DS,
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070072 DataType DT,
Stephen Hinese79fb5e2011-02-01 19:12:43 -080073 clang::Expr *InitExpr);
74
Yang Nib478c3d2016-01-15 16:37:04 -080075 // Inserts rsClearObject() calls at the end and at all exiting points of the
76 // current scope. At each statement that exits the current scope -- e.g.,
77 // a return, break, or continue statement in the current or a nested scope
78 // -- rsClearObject() calls are inserted for local variables defined in the
79 // current scope before that point.
80 // Note goto statements are not handled. (See the DestructorVisitor class in
81 // the .cpp file.)
82 // Also note this function is called for every nested scope. As a result, for a
83 // return statement, each rsObject declared in all its (nested) enclosing
84 // scopes would have a rsClearObject() call properly inserted before
85 // the return statement.
Stephen Hines1bdd4972010-11-08 17:35:08 -080086 void InsertLocalVarDestructors();
Stephen Hines1bdd4972010-11-08 17:35:08 -080087
Yang Nib478c3d2016-01-15 16:37:04 -080088 // Sets the current statement being analyzed
89 void setCurrentStmt(clang::Stmt *S) { mCurrent = S; }
90
91 // Inserts a statement before the current statement
92 void InsertStmt(const clang::ASTContext &C, clang::Stmt *NewStmt);
93
94 // Replaces the current statement with NewStmt;
95 void ReplaceStmt(const clang::ASTContext &C, clang::Stmt *NewStmt);
96
97 // Replaces OldExpr with NewExpr in the current statement
98 void ReplaceExpr(const clang::ASTContext& C, clang::Expr* OldExpr,
99 clang::Expr* NewExpr);
100
Stephen Hines3f175af2011-09-16 16:26:29 -0700101 static clang::Stmt *ClearRSObject(clang::VarDecl *VD,
102 clang::DeclContext *DC);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700103 };
104
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700105 clang::ASTContext &mCtx;
Yang Nib478c3d2016-01-15 16:37:04 -0800106 std::deque<Scope*> mScopeStack; // A deque used as a stack to store scopes, but also
107 // accessed through its iterator in read-only mode.
108 clang::DeclContext* mCurrentDC;
Yang Ni31d2ea32017-04-14 15:44:23 -0700109 bool RSInitFD; // TODO: this should be static, since this flag affects all instances.
Yang Nib478c3d2016-01-15 16:37:04 -0800110 unsigned mTempID; // A unique id that can be used to distinguish temporary variables
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700111
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800112 // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject()
113 // and rsClearObject() in the current ASTContext.
114 static clang::FunctionDecl *RSSetObjectFD[];
115 static clang::FunctionDecl *RSClearObjectFD[];
116
Yang Nib478c3d2016-01-15 16:37:04 -0800117 inline bool emptyScope() const { return mScopeStack.empty(); }
118
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700119 inline Scope *getCurrentScope() {
Yang Nib478c3d2016-01-15 16:37:04 -0800120 return mScopeStack.back();
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700121 }
122
Yang Nib478c3d2016-01-15 16:37:04 -0800123 // Returns the next available unique id for temporary variables
124 unsigned getNextID() { return mTempID++; }
125
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800126 // Initialize RSSetObjectFD and RSClearObjectFD.
127 static void GetRSRefCountingFunctions(clang::ASTContext &C);
128
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800129 // Return false if the type of variable declared in VD does not contain
130 // an RS object type.
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800131 static bool InitializeRSObject(clang::VarDecl *VD,
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700132 DataType *DT,
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800133 clang::Expr **InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700134
Stephen Hinesd9ed6b52016-03-30 22:09:53 -0700135 // Return an empty list initializer expression at the appropriate location.
136 // This construct can then be used to cheaply construct a zero-initializer
137 // for any RenderScript objects (like rs_allocation) or rs_matrix* types
138 // (possibly even embedded within other types). These types are expected to
139 // be zero-initialized always, and so we can use this helper to ensure that
140 // they at least have an empty initializer.
141 static clang::Expr *CreateEmptyInitListExpr(
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700142 clang::ASTContext &C,
143 const clang::SourceLocation &Loc);
144
Yang Ni5767c352016-03-22 16:30:27 -0700145 // Given a return statement RS that returns an rsObject, creates a temporary
146 // variable, and sets it to the original return expression using rsSetObject().
147 // Creates a new return statement that returns the temporary variable.
148 // Returns a new compound statement that contains the new variable declaration,
149 // the rsSetOjbect() call, and the new return statement.
150 static clang::CompoundStmt* CreateRetStmtWithTempVar(
151 clang::ASTContext& C,
152 clang::DeclContext* DC,
153 clang::ReturnStmt* RS,
154 const unsigned id);
155
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700156 public:
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700157 explicit RSObjectRefCount(clang::ASTContext &C)
Yang Nib478c3d2016-01-15 16:37:04 -0800158 : mCtx(C), RSInitFD(false), mTempID(0) {
Stephen Hines1bdd4972010-11-08 17:35:08 -0800159 }
160
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700161 void Init() {
Stephen Hines1bdd4972010-11-08 17:35:08 -0800162 if (!RSInitFD) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700163 GetRSRefCountingFunctions(mCtx);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800164 RSInitFD = true;
165 }
Stephen Hines1bdd4972010-11-08 17:35:08 -0800166 }
167
Yang Ni31d2ea32017-04-14 15:44:23 -0700168 // For function parameters and local variables that are or contain RS objects,
169 // e.g., rs_allocation, this method transforms the function body to correctly
170 // adjust reference counts of those objects.
171 void HandleParamsAndLocals(clang::FunctionDecl *FD);
172
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700173 static clang::FunctionDecl *GetRSSetObjectFD(DataType DT) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800174 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700175 if (DT >= 0 && DT < DataTypeMax) {
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -0700176 return RSSetObjectFD[DT];
177 } else {
178 slangAssert(false && "incorrect type");
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700179 return nullptr;
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -0700180 }
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800181 }
182
183 static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) {
184 return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
185 }
186
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700187 static clang::FunctionDecl *GetRSClearObjectFD(DataType DT) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800188 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700189 if (DT >= 0 && DT < DataTypeMax) {
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -0700190 return RSClearObjectFD[DT];
191 } else {
192 slangAssert(false && "incorrect type");
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700193 return nullptr;
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -0700194 }
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800195 }
196
197 static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) {
198 return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
199 }
200
Yang Ni31d2ea32017-04-14 15:44:23 -0700201 // This method creates a "guard" variable for the expression E that is object-
202 // typed or object-containing, e.g., a struct with object-type fields.
203 // It creates one or more rsSetObject() calls to set the value of the guard to E.
204 // This effectively increases the sysRef count of the objects referenced by E
205 // by 1, therefore "guarding" the objects, which might otherwise lose a
206 // reference and get deleted. Statements that declare the new variable and set
207 // the value of the new variable are added to the vector NewStmts.
208 //
209 // Parameters:
210 // C: The clang AST Context.
211 // DC: The DeclContext for any new Decl to add
212 // E: The expression with reference to the objects for which we want to
213 // increase the sysRef count
214 // VarName: The name to use for the new guard variable
215 // NewStmts: The vector for all statements added to create and set the guard.
216 //
217 // Returns:
218 // An expression consisting of the guard variable
219 //
220 static clang::DeclRefExpr *CreateGuard(clang::ASTContext &C,
221 clang::DeclContext *DC,
222 clang::Expr *E,
223 const llvm::Twine &VarName,
224 std::vector<clang::Stmt*> &NewStmts);
225
226 // For any function parameter that is object-typed or object-containing, if it
227 // is overwritten inside the function, a system reference (sysRef) count
228 // would decrement and may reach 0, leading the object to be deleted. This may
229 // create a dangling pointer reference after a call to the function.
230 // For example, the object in parameter a in the function below may be deleted
231 // before the function returns.
232 // void foo(rs_allocation a) { // assuming a references obj with sysRef of 1
233 // rs_allocation b = {};
234 // a = b; // decrements sysRef of obj and deletes it
235 // }
236 //
237 // To avoid this problem, the sysRef counts of objects contained in parameters
238 // --directly for object-typed parameters or indirectly as fields for struct-
239 // typed parameters--are incremented at the beginning of the function, and
240 // decremented at the end and any exiting point of the function. To achieve
241 // these effects, the compiler creates a temporary local variable, and calls
242 // rsSetObject() to set its value to that of the parameter. At the end of the
243 // function and at any exiting point, the compiler adds calls to
244 // rsClearObject() on the parameter. Each rsClearObject() call would decrement
245 // the sysRef count of an incoming object if the parameter is never overwritten
246 // in the function, or it would properly decrement the sysRef count of the new
247 // object that the parameter is updated to in the function, since now the
248 // parameter is going out of scope. For example, the compiler would transform
249 // the previous code example into the following.
250 // void foo(rs_allocation a) { // assuming a references obj with sysRef of 1
251 // rs_allocation .rs.param.a;
252 // rsSetObject(&.rs.param.a, a); // sysRef of obj becomes 2
253 // rs_allocation b = {};
254 // a = b; // sysRef of obj becomes 1
255 // rsClearObject(&a); // sysRef of obj stays 1. obj stays undeleted.
256 // }
257 //
258 // This method creates the guard variable for a object-type parameter,
259 // named with the prefix ".rs.param." added to the parameter name. It calls
260 // CreateGuard() to do this. The rsClearObject() call for the parameter as
261 // described above is not added by this function, but by the caller of this
262 // function, i.e., HandleParametersAndLocals().
263 //
264 // Parameters:
265 // C: The clang AST Context.
266 // DC: The DeclContext for any new Decl to add. It should be the FunctionnDecl
267 // of the function being transformed.
268 // PD: The ParmDecl for the parameter.
269 // NewStmts: The vector for all statements added to create and set the guard.
270 //
271 static void CreateParameterGuard(
272 clang::ASTContext &C,
273 clang::DeclContext *DC,
274 clang::ParmVarDecl *PD,
275 std::vector<clang::Stmt*> &NewStmts);
276
Yang Nib478c3d2016-01-15 16:37:04 -0800277 void SetDeclContext(clang::DeclContext* DC) { mCurrentDC = DC; }
278 clang::DeclContext* GetDeclContext() const { return mCurrentDC; }
279
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700280 void VisitStmt(clang::Stmt *S);
Yang Nib478c3d2016-01-15 16:37:04 -0800281 void VisitCallExpr(clang::CallExpr *CE);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700282 void VisitDeclStmt(clang::DeclStmt *DS);
283 void VisitCompoundStmt(clang::CompoundStmt *CS);
284 void VisitBinAssign(clang::BinaryOperator *AS);
Yang Nib478c3d2016-01-15 16:37:04 -0800285 void VisitReturnStmt(clang::ReturnStmt *RS);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700286 // We believe that RS objects are never involved in CompoundAssignOperator.
287 // I.e., rs_allocation foo; foo += bar;
Stephen Hines688e64b2011-08-23 16:01:25 -0700288
289 // Emit a global destructor to clean up RS objects.
290 clang::FunctionDecl *CreateStaticGlobalDtor();
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700291};
292
Stephen Hinese639eb52010-11-08 19:27:20 -0800293} // namespace slang
294
295#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ NOLINT