14b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines/* 24b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Copyright 2010, The Android Open Source Project 34b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * 44b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Licensed under the Apache License, Version 2.0 (the "License"); 54b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * you may not use this file except in compliance with the License. 64b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * You may obtain a copy of the License at 74b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * 84b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * http://www.apache.org/licenses/LICENSE-2.0 94b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * 104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Unless required by applicable law or agreed to in writing, software 114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * distributed under the License is distributed on an "AS IS" BASIS, 124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * See the License for the specific language governing permissions and 144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * limitations under the License. 154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines */ 164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 17e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ // NOLINT 18e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ 19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines 20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <list> 214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include <stack> 2231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni#include <vector> 234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h" 254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 26f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines#include "slang_assert.h" 274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h" 284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesnamespace clang { 304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines class Expr; 31d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines class Stmt; 324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines} 334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 34e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang { 35e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines 3665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross// Recursive check 3765f23ed862e1a1e16477ba740f295ff4a83ac822David Grossbool HasRSObjectType(const clang::Type *T); 3865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross 39292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// This class provides the overall reference counting mechanism for handling 40292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// local variables of RS object types (rs_font, rs_allocation, ...). This 41292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// class ensures that appropriate functions (rsSetObject, rsClearObject) are 42292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// called at proper points in the object's lifetime. 43b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// 1) Each local object of appropriate type must be zero-initialized to 44b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// prevent corruption during subsequent rsSetObject()/rsClearObject() calls. 45292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// 2) Assignments using these types must also be converted into the 46292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// appropriate (possibly a series of) rsSetObject() calls. 47b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// 3) Finally, rsClearObject() must be called for each local object when it goes 48b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// out of scope. 494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclass RSObjectRefCount : public clang::StmtVisitor<RSObjectRefCount> { 504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines private: 514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines class Scope { 524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines private: 53b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni clang::CompoundStmt *mCS; // Associated compound statement ({ ... }) 54b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni clang::Stmt *mCurrent; // The statement currently being analyzed 55b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni std::list<clang::VarDecl*> mRSO; // Declared RS objects in this scope (but 56b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // not any scopes nested) 571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines public: 59e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines explicit Scope(clang::CompoundStmt *CS) : mCS(CS) { 604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines } 614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 62b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni bool hasRSObject() const { return !mRSO.empty(); } 63b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni 641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines inline void addRSObject(clang::VarDecl* VD) { 651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines mRSO.push_back(VD); 664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines } 671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 68d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines void ReplaceRSObjectAssignment(clang::BinaryOperator *AS); 69c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines 70d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines void AppendRSObjectInit(clang::VarDecl *VD, 71e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines clang::DeclStmt *DS, 72cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet DataType DT, 73e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines clang::Expr *InitExpr); 74e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines 75b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // Inserts rsClearObject() calls at the end and at all exiting points of the 76b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // current scope. At each statement that exits the current scope -- e.g., 77b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // a return, break, or continue statement in the current or a nested scope 78b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // -- rsClearObject() calls are inserted for local variables defined in the 79b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // current scope before that point. 80b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // Note goto statements are not handled. (See the DestructorVisitor class in 81b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // the .cpp file.) 82b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // Also note this function is called for every nested scope. As a result, for a 83b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // return statement, each rsObject declared in all its (nested) enclosing 84b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // scopes would have a rsClearObject() call properly inserted before 85b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // the return statement. 861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines void InsertLocalVarDestructors(); 871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 88b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // Sets the current statement being analyzed 89b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni void setCurrentStmt(clang::Stmt *S) { mCurrent = S; } 90b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni 91b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // Inserts a statement before the current statement 92b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni void InsertStmt(const clang::ASTContext &C, clang::Stmt *NewStmt); 93b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni 94b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // Replaces the current statement with NewStmt; 95b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni void ReplaceStmt(const clang::ASTContext &C, clang::Stmt *NewStmt); 96b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni 97b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // Replaces OldExpr with NewExpr in the current statement 98b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni void ReplaceExpr(const clang::ASTContext& C, clang::Expr* OldExpr, 99b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni clang::Expr* NewExpr); 100b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni 1013f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines static clang::Stmt *ClearRSObject(clang::VarDecl *VD, 1023f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines clang::DeclContext *DC); 1034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines }; 1044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 105d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines clang::ASTContext &mCtx; 106b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni std::deque<Scope*> mScopeStack; // A deque used as a stack to store scopes, but also 107b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // accessed through its iterator in read-only mode. 108b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni clang::DeclContext* mCurrentDC; 10931d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni bool RSInitFD; // TODO: this should be static, since this flag affects all instances. 110b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni unsigned mTempID; // A unique id that can be used to distinguish temporary variables 1114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 112f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject() 113f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // and rsClearObject() in the current ASTContext. 114f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static clang::FunctionDecl *RSSetObjectFD[]; 115f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static clang::FunctionDecl *RSClearObjectFD[]; 116f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 117b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni inline bool emptyScope() const { return mScopeStack.empty(); } 118b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni 1194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines inline Scope *getCurrentScope() { 120b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni return mScopeStack.back(); 1214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines } 1224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 123b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni // Returns the next available unique id for temporary variables 124b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni unsigned getNextID() { return mTempID++; } 125b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni 126f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // Initialize RSSetObjectFD and RSClearObjectFD. 127f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static void GetRSRefCountingFunctions(clang::ASTContext &C); 128f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 129f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // Return false if the type of variable declared in VD does not contain 130f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // an RS object type. 131e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines static bool InitializeRSObject(clang::VarDecl *VD, 132cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet DataType *DT, 133e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines clang::Expr **InitExpr); 1344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 135d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines // Return an empty list initializer expression at the appropriate location. 136d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines // This construct can then be used to cheaply construct a zero-initializer 137d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines // for any RenderScript objects (like rs_allocation) or rs_matrix* types 138d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines // (possibly even embedded within other types). These types are expected to 139d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines // be zero-initialized always, and so we can use this helper to ensure that 140d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines // they at least have an empty initializer. 141d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines static clang::Expr *CreateEmptyInitListExpr( 1424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines clang::ASTContext &C, 1434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines const clang::SourceLocation &Loc); 1444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 1455767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni // Given a return statement RS that returns an rsObject, creates a temporary 1465767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni // variable, and sets it to the original return expression using rsSetObject(). 1475767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni // Creates a new return statement that returns the temporary variable. 1485767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni // Returns a new compound statement that contains the new variable declaration, 1495767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni // the rsSetOjbect() call, and the new return statement. 1505767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni static clang::CompoundStmt* CreateRetStmtWithTempVar( 1515767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni clang::ASTContext& C, 1525767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni clang::DeclContext* DC, 1535767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni clang::ReturnStmt* RS, 1545767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni const unsigned id); 1555767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni 1564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines public: 157d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines explicit RSObjectRefCount(clang::ASTContext &C) 158b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni : mCtx(C), RSInitFD(false), mTempID(0) { 1591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines } 1601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 161d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines void Init() { 1621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines if (!RSInitFD) { 163d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines GetRSRefCountingFunctions(mCtx); 1641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines RSInitFD = true; 1651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines } 1661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines } 1671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 16831d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // For function parameters and local variables that are or contain RS objects, 16931d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // e.g., rs_allocation, this method transforms the function body to correctly 17031d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // adjust reference counts of those objects. 17131d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni void HandleParamsAndLocals(clang::FunctionDecl *FD); 17231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni 173cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet static clang::FunctionDecl *GetRSSetObjectFD(DataType DT) { 174f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)); 175cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet if (DT >= 0 && DT < DataTypeMax) { 176474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet return RSSetObjectFD[DT]; 177474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet } else { 178474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet slangAssert(false && "incorrect type"); 1795abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes return nullptr; 180474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet } 181f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines } 182f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 183f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) { 184f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T)); 185f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines } 186f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 187cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet static clang::FunctionDecl *GetRSClearObjectFD(DataType DT) { 188f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)); 189cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet if (DT >= 0 && DT < DataTypeMax) { 190474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet return RSClearObjectFD[DT]; 191474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet } else { 192474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet slangAssert(false && "incorrect type"); 1935abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes return nullptr; 194474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet } 195f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines } 196f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 197f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) { 198f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T)); 199f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines } 200f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 20131d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // This method creates a "guard" variable for the expression E that is object- 20231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // typed or object-containing, e.g., a struct with object-type fields. 20331d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // It creates one or more rsSetObject() calls to set the value of the guard to E. 20431d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // This effectively increases the sysRef count of the objects referenced by E 20531d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // by 1, therefore "guarding" the objects, which might otherwise lose a 20631d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // reference and get deleted. Statements that declare the new variable and set 20731d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // the value of the new variable are added to the vector NewStmts. 20831d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // 20931d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // Parameters: 21031d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // C: The clang AST Context. 21131d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // DC: The DeclContext for any new Decl to add 21231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // E: The expression with reference to the objects for which we want to 21331d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // increase the sysRef count 21431d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // VarName: The name to use for the new guard variable 21531d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // NewStmts: The vector for all statements added to create and set the guard. 21631d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // 21731d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // Returns: 21831d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // An expression consisting of the guard variable 21931d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // 22031d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni static clang::DeclRefExpr *CreateGuard(clang::ASTContext &C, 22131d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni clang::DeclContext *DC, 22231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni clang::Expr *E, 22331d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni const llvm::Twine &VarName, 22431d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni std::vector<clang::Stmt*> &NewStmts); 22531d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni 22631d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // For any function parameter that is object-typed or object-containing, if it 22731d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // is overwritten inside the function, a system reference (sysRef) count 22831d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // would decrement and may reach 0, leading the object to be deleted. This may 22931d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // create a dangling pointer reference after a call to the function. 23031d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // For example, the object in parameter a in the function below may be deleted 23131d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // before the function returns. 23231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // void foo(rs_allocation a) { // assuming a references obj with sysRef of 1 23331d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // rs_allocation b = {}; 23431d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // a = b; // decrements sysRef of obj and deletes it 23531d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // } 23631d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // 23731d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // To avoid this problem, the sysRef counts of objects contained in parameters 23831d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // --directly for object-typed parameters or indirectly as fields for struct- 23931d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // typed parameters--are incremented at the beginning of the function, and 24031d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // decremented at the end and any exiting point of the function. To achieve 24131d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // these effects, the compiler creates a temporary local variable, and calls 24231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // rsSetObject() to set its value to that of the parameter. At the end of the 24331d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // function and at any exiting point, the compiler adds calls to 24431d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // rsClearObject() on the parameter. Each rsClearObject() call would decrement 24531d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // the sysRef count of an incoming object if the parameter is never overwritten 24631d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // in the function, or it would properly decrement the sysRef count of the new 24731d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // object that the parameter is updated to in the function, since now the 24831d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // parameter is going out of scope. For example, the compiler would transform 24931d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // the previous code example into the following. 25031d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // void foo(rs_allocation a) { // assuming a references obj with sysRef of 1 25131d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // rs_allocation .rs.param.a; 25231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // rsSetObject(&.rs.param.a, a); // sysRef of obj becomes 2 25331d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // rs_allocation b = {}; 25431d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // a = b; // sysRef of obj becomes 1 25531d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // rsClearObject(&a); // sysRef of obj stays 1. obj stays undeleted. 25631d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // } 25731d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // 25831d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // This method creates the guard variable for a object-type parameter, 25931d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // named with the prefix ".rs.param." added to the parameter name. It calls 26031d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // CreateGuard() to do this. The rsClearObject() call for the parameter as 26131d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // described above is not added by this function, but by the caller of this 26231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // function, i.e., HandleParametersAndLocals(). 26331d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // 26431d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // Parameters: 26531d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // C: The clang AST Context. 26631d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // DC: The DeclContext for any new Decl to add. It should be the FunctionnDecl 26731d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // of the function being transformed. 26831d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // PD: The ParmDecl for the parameter. 26931d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // NewStmts: The vector for all statements added to create and set the guard. 27031d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni // 27131d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni static void CreateParameterGuard( 27231d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni clang::ASTContext &C, 27331d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni clang::DeclContext *DC, 27431d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni clang::ParmVarDecl *PD, 27531d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni std::vector<clang::Stmt*> &NewStmts); 27631d2ea3cb95fde60862e7032148c36f6edfbec5cYang Ni 277b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni void SetDeclContext(clang::DeclContext* DC) { mCurrentDC = DC; } 278b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni clang::DeclContext* GetDeclContext() const { return mCurrentDC; } 279b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni 2804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines void VisitStmt(clang::Stmt *S); 281b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni void VisitCallExpr(clang::CallExpr *CE); 2824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines void VisitDeclStmt(clang::DeclStmt *DS); 2834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines void VisitCompoundStmt(clang::CompoundStmt *CS); 2844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines void VisitBinAssign(clang::BinaryOperator *AS); 285b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni void VisitReturnStmt(clang::ReturnStmt *RS); 2864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines // We believe that RS objects are never involved in CompoundAssignOperator. 2874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines // I.e., rs_allocation foo; foo += bar; 288688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines 289688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines // Emit a global destructor to clean up RS objects. 290688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines clang::FunctionDecl *CreateStaticGlobalDtor(); 2914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}; 2924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 293e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines} // namespace slang 294e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines 295e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ NOLINT 296