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 17 #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> 21 #include <stack> 22 23 #include "clang/AST/StmtVisitor.h" 24 25 #include "slang_assert.h" 26 #include "slang_rs_export_type.h" 27 28 namespace clang { 29 class Expr; 30 class Stmt; 31 } 32 33 namespace slang { 34 35 // Recursive check 36 bool HasRSObjectType(const clang::Type *T); 37 38 // This class provides the overall reference counting mechanism for handling 39 // local variables of RS object types (rs_font, rs_allocation, ...). This 40 // class ensures that appropriate functions (rsSetObject, rsClearObject) are 41 // called at proper points in the object's lifetime. 42 // 1) Each local object of appropriate type must be zero-initialized to 43 // prevent corruption during subsequent rsSetObject()/rsClearObject() calls. 44 // 2) Assignments using these types must also be converted into the 45 // appropriate (possibly a series of) rsSetObject() calls. 46 // 3) Finally, rsClearObject() must be called for each local object when it goes 47 // out of scope. 48 class RSObjectRefCount : public clang::StmtVisitor<RSObjectRefCount> { 49 private: 50 class Scope { 51 private: 52 clang::CompoundStmt *mCS; // Associated compound statement ({ ... }) 53 clang::Stmt *mCurrent; // The statement currently being analyzed 54 std::list<clang::VarDecl*> mRSO; // Declared RS objects in this scope (but 55 // not any scopes nested) 56 57 public: Scope(clang::CompoundStmt * CS)58 explicit Scope(clang::CompoundStmt *CS) : mCS(CS) { 59 } 60 hasRSObject()61 bool hasRSObject() const { return !mRSO.empty(); } 62 addRSObject(clang::VarDecl * VD)63 inline void addRSObject(clang::VarDecl* VD) { 64 mRSO.push_back(VD); 65 } 66 67 void ReplaceRSObjectAssignment(clang::BinaryOperator *AS); 68 69 void AppendRSObjectInit(clang::VarDecl *VD, 70 clang::DeclStmt *DS, 71 DataType DT, 72 clang::Expr *InitExpr); 73 74 // Inserts rsClearObject() calls at the end and at all exiting points of the 75 // current scope. At each statement that exits the current scope -- e.g., 76 // a return, break, or continue statement in the current or a nested scope 77 // -- rsClearObject() calls are inserted for local variables defined in the 78 // current scope before that point. 79 // Note goto statements are not handled. (See the DestructorVisitor class in 80 // the .cpp file.) 81 // Also note this function is called for every nested scope. As a result, for a 82 // return statement, each rsObject declared in all its (nested) enclosing 83 // scopes would have a rsClearObject() call properly inserted before 84 // the return statement. 85 void InsertLocalVarDestructors(); 86 87 // Sets the current statement being analyzed setCurrentStmt(clang::Stmt * S)88 void setCurrentStmt(clang::Stmt *S) { mCurrent = S; } 89 90 // Inserts a statement before the current statement 91 void InsertStmt(const clang::ASTContext &C, clang::Stmt *NewStmt); 92 93 // Replaces the current statement with NewStmt; 94 void ReplaceStmt(const clang::ASTContext &C, clang::Stmt *NewStmt); 95 96 // Replaces OldExpr with NewExpr in the current statement 97 void ReplaceExpr(const clang::ASTContext& C, clang::Expr* OldExpr, 98 clang::Expr* NewExpr); 99 100 static clang::Stmt *ClearRSObject(clang::VarDecl *VD, 101 clang::DeclContext *DC); 102 }; 103 104 clang::ASTContext &mCtx; 105 std::deque<Scope*> mScopeStack; // A deque used as a stack to store scopes, but also 106 // accessed through its iterator in read-only mode. 107 clang::DeclContext* mCurrentDC; 108 bool RSInitFD; 109 unsigned mTempID; // A unique id that can be used to distinguish temporary variables 110 111 // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject() 112 // and rsClearObject() in the current ASTContext. 113 static clang::FunctionDecl *RSSetObjectFD[]; 114 static clang::FunctionDecl *RSClearObjectFD[]; 115 emptyScope()116 inline bool emptyScope() const { return mScopeStack.empty(); } 117 getCurrentScope()118 inline Scope *getCurrentScope() { 119 return mScopeStack.back(); 120 } 121 122 // Returns the next available unique id for temporary variables getNextID()123 unsigned getNextID() { return mTempID++; } 124 125 // Initialize RSSetObjectFD and RSClearObjectFD. 126 static void GetRSRefCountingFunctions(clang::ASTContext &C); 127 128 // Return false if the type of variable declared in VD does not contain 129 // an RS object type. 130 static bool InitializeRSObject(clang::VarDecl *VD, 131 DataType *DT, 132 clang::Expr **InitExpr); 133 134 // Return an empty list initializer expression at the appropriate location. 135 // This construct can then be used to cheaply construct a zero-initializer 136 // for any RenderScript objects (like rs_allocation) or rs_matrix* types 137 // (possibly even embedded within other types). These types are expected to 138 // be zero-initialized always, and so we can use this helper to ensure that 139 // they at least have an empty initializer. 140 static clang::Expr *CreateEmptyInitListExpr( 141 clang::ASTContext &C, 142 const clang::SourceLocation &Loc); 143 144 // Given a return statement RS that returns an rsObject, creates a temporary 145 // variable, and sets it to the original return expression using rsSetObject(). 146 // Creates a new return statement that returns the temporary variable. 147 // Returns a new compound statement that contains the new variable declaration, 148 // the rsSetOjbect() call, and the new return statement. 149 static clang::CompoundStmt* CreateRetStmtWithTempVar( 150 clang::ASTContext& C, 151 clang::DeclContext* DC, 152 clang::ReturnStmt* RS, 153 const unsigned id); 154 155 public: RSObjectRefCount(clang::ASTContext & C)156 explicit RSObjectRefCount(clang::ASTContext &C) 157 : mCtx(C), RSInitFD(false), mTempID(0) { 158 } 159 Init()160 void Init() { 161 if (!RSInitFD) { 162 GetRSRefCountingFunctions(mCtx); 163 RSInitFD = true; 164 } 165 } 166 GetRSSetObjectFD(DataType DT)167 static clang::FunctionDecl *GetRSSetObjectFD(DataType DT) { 168 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)); 169 if (DT >= 0 && DT < DataTypeMax) { 170 return RSSetObjectFD[DT]; 171 } else { 172 slangAssert(false && "incorrect type"); 173 return nullptr; 174 } 175 } 176 GetRSSetObjectFD(const clang::Type * T)177 static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) { 178 return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T)); 179 } 180 GetRSClearObjectFD(DataType DT)181 static clang::FunctionDecl *GetRSClearObjectFD(DataType DT) { 182 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)); 183 if (DT >= 0 && DT < DataTypeMax) { 184 return RSClearObjectFD[DT]; 185 } else { 186 slangAssert(false && "incorrect type"); 187 return nullptr; 188 } 189 } 190 GetRSClearObjectFD(const clang::Type * T)191 static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) { 192 return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T)); 193 } 194 SetDeclContext(clang::DeclContext * DC)195 void SetDeclContext(clang::DeclContext* DC) { mCurrentDC = DC; } GetDeclContext()196 clang::DeclContext* GetDeclContext() const { return mCurrentDC; } 197 198 void VisitStmt(clang::Stmt *S); 199 void VisitCallExpr(clang::CallExpr *CE); 200 void VisitDeclStmt(clang::DeclStmt *DS); 201 void VisitCompoundStmt(clang::CompoundStmt *CS); 202 void VisitBinAssign(clang::BinaryOperator *AS); 203 void VisitReturnStmt(clang::ReturnStmt *RS); 204 // We believe that RS objects are never involved in CompoundAssignOperator. 205 // I.e., rs_allocation foo; foo += bar; 206 207 // Emit a global destructor to clean up RS objects. 208 clang::FunctionDecl *CreateStaticGlobalDtor(); 209 }; 210 211 } // namespace slang 212 213 #endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ NOLINT 214