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 // This class provides the overall reference counting mechanism for handling 36 // local variables of RS object types (rs_font, rs_allocation, ...). This 37 // class ensures that appropriate functions (rsSetObject, rsClearObject) are 38 // called at proper points in the object's lifetime. 39 // 1) Each local object of appropriate type must be zero-initialized (to 40 // prevent corruption) during subsequent rsSetObject()/rsClearObject() calls. 41 // 2) Assignments using these types must also be converted into the 42 // appropriate (possibly a series of) rsSetObject() calls. 43 // 3) Finally, each local object must call rsClearObject() when it goes out 44 // of scope. 45 class RSObjectRefCount : public clang::StmtVisitor<RSObjectRefCount> { 46 private: 47 class Scope { 48 private: 49 clang::CompoundStmt *mCS; // Associated compound statement ({ ... }) 50 std::list<clang::VarDecl*> mRSO; // Declared RS objects in this scope 51 52 public: Scope(clang::CompoundStmt * CS)53 explicit Scope(clang::CompoundStmt *CS) : mCS(CS) { 54 } 55 addRSObject(clang::VarDecl * VD)56 inline void addRSObject(clang::VarDecl* VD) { 57 mRSO.push_back(VD); 58 } 59 60 void ReplaceRSObjectAssignment(clang::BinaryOperator *AS); 61 62 void AppendRSObjectInit(clang::VarDecl *VD, 63 clang::DeclStmt *DS, 64 DataType DT, 65 clang::Expr *InitExpr); 66 67 void InsertLocalVarDestructors(); 68 69 static clang::Stmt *ClearRSObject(clang::VarDecl *VD, 70 clang::DeclContext *DC); 71 }; 72 73 clang::ASTContext &mCtx; 74 std::stack<Scope*> mScopeStack; 75 bool RSInitFD; 76 77 // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject() 78 // and rsClearObject() in the current ASTContext. 79 static clang::FunctionDecl *RSSetObjectFD[]; 80 static clang::FunctionDecl *RSClearObjectFD[]; 81 getCurrentScope()82 inline Scope *getCurrentScope() { 83 return mScopeStack.top(); 84 } 85 86 // Initialize RSSetObjectFD and RSClearObjectFD. 87 static void GetRSRefCountingFunctions(clang::ASTContext &C); 88 89 // Return false if the type of variable declared in VD does not contain 90 // an RS object type. 91 static bool InitializeRSObject(clang::VarDecl *VD, 92 DataType *DT, 93 clang::Expr **InitExpr); 94 95 // Return a zero-initializer expr of the type DT. This processes both 96 // RS matrix type and RS object type. 97 static clang::Expr *CreateZeroInitializerForRSSpecificType( 98 DataType DT, 99 clang::ASTContext &C, 100 const clang::SourceLocation &Loc); 101 102 public: RSObjectRefCount(clang::ASTContext & C)103 explicit RSObjectRefCount(clang::ASTContext &C) 104 : mCtx(C), 105 RSInitFD(false) { 106 } 107 Init()108 void Init() { 109 if (!RSInitFD) { 110 GetRSRefCountingFunctions(mCtx); 111 RSInitFD = true; 112 } 113 } 114 GetRSSetObjectFD(DataType DT)115 static clang::FunctionDecl *GetRSSetObjectFD(DataType DT) { 116 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)); 117 if (DT >= 0 && DT < DataTypeMax) { 118 return RSSetObjectFD[DT]; 119 } else { 120 slangAssert(false && "incorrect type"); 121 return nullptr; 122 } 123 } 124 GetRSSetObjectFD(const clang::Type * T)125 static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) { 126 return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T)); 127 } 128 GetRSClearObjectFD(DataType DT)129 static clang::FunctionDecl *GetRSClearObjectFD(DataType DT) { 130 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)); 131 if (DT >= 0 && DT < DataTypeMax) { 132 return RSClearObjectFD[DT]; 133 } else { 134 slangAssert(false && "incorrect type"); 135 return nullptr; 136 } 137 } 138 GetRSClearObjectFD(const clang::Type * T)139 static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) { 140 return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T)); 141 } 142 143 void VisitStmt(clang::Stmt *S); 144 void VisitDeclStmt(clang::DeclStmt *DS); 145 void VisitCompoundStmt(clang::CompoundStmt *CS); 146 void VisitBinAssign(clang::BinaryOperator *AS); 147 // We believe that RS objects are never involved in CompoundAssignOperator. 148 // I.e., rs_allocation foo; foo += bar; 149 150 // Emit a global destructor to clean up RS objects. 151 clang::FunctionDecl *CreateStaticGlobalDtor(); 152 }; 153 154 } // namespace slang 155 156 #endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ NOLINT 157