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> 224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h" 244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 25f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines#include "slang_assert.h" 264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h" 274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesnamespace clang { 294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines class Expr; 30d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines class Stmt; 314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines} 324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 33e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang { 34e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines 3565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross// Recursive check 3665f23ed862e1a1e16477ba740f295ff4a83ac822David Grossbool HasRSObjectType(const clang::Type *T); 3765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross 38292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// This class provides the overall reference counting mechanism for handling 39292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// local variables of RS object types (rs_font, rs_allocation, ...). This 40292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// class ensures that appropriate functions (rsSetObject, rsClearObject) are 41292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// called at proper points in the object's lifetime. 42283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// 1) Each local object of appropriate type must be zero-initialized to 43283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// prevent corruption during subsequent rsSetObject()/rsClearObject() calls. 44292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// 2) Assignments using these types must also be converted into the 45292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// appropriate (possibly a series of) rsSetObject() calls. 46283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// 3) Finally, rsClearObject() must be called for each local object when it goes 47283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// out of scope. 484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclass RSObjectRefCount : public clang::StmtVisitor<RSObjectRefCount> { 494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines private: 504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines class Scope { 514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines private: 52283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni clang::CompoundStmt *mCS; // Associated compound statement ({ ... }) 53283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni clang::Stmt *mCurrent; // The statement currently being analyzed 54283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni std::list<clang::VarDecl*> mRSO; // Declared RS objects in this scope (but 55283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // not any scopes nested) 561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines public: 58e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines explicit Scope(clang::CompoundStmt *CS) : mCS(CS) { 594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines } 604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 61283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni bool hasRSObject() const { return !mRSO.empty(); } 62283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni 631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines inline void addRSObject(clang::VarDecl* VD) { 641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines mRSO.push_back(VD); 654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines } 661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 67d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines void ReplaceRSObjectAssignment(clang::BinaryOperator *AS); 68c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines 69d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines void AppendRSObjectInit(clang::VarDecl *VD, 70e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines clang::DeclStmt *DS, 71cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet DataType DT, 72e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines clang::Expr *InitExpr); 73e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines 74283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // Inserts rsClearObject() calls at the end and at all exiting points of the 75283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // current scope. At each statement that exits the current scope -- e.g., 76283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // a return, break, or continue statement in the current or a nested scope 77283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // -- rsClearObject() calls are inserted for local variables defined in the 78283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // current scope before that point. 79283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // Note goto statements are not handled. (See the DestructorVisitor class in 80283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // the .cpp file.) 81283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // Also note this function is called for every nested scope. As a result, for a 82283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // return statement, each rsObject declared in all its (nested) enclosing 83283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // scopes would have a rsClearObject() call properly inserted before 84283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // the return statement. 851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines void InsertLocalVarDestructors(); 861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 87283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // Sets the current statement being analyzed 88283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni void setCurrentStmt(clang::Stmt *S) { mCurrent = S; } 89283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni 90283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // Inserts a statement before the current statement 91283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni void InsertStmt(const clang::ASTContext &C, clang::Stmt *NewStmt); 92283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni 93283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // Replaces the current statement with NewStmt; 94283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni void ReplaceStmt(const clang::ASTContext &C, clang::Stmt *NewStmt); 95283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni 96283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // Replaces OldExpr with NewExpr in the current statement 97283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni void ReplaceExpr(const clang::ASTContext& C, clang::Expr* OldExpr, 98283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni clang::Expr* NewExpr); 99283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni 1003f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines static clang::Stmt *ClearRSObject(clang::VarDecl *VD, 1013f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines clang::DeclContext *DC); 1024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines }; 1034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 104d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines clang::ASTContext &mCtx; 105283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni std::deque<Scope*> mScopeStack; // A deque used as a stack to store scopes, but also 106283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // accessed through its iterator in read-only mode. 107283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni clang::DeclContext* mCurrentDC; 1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines bool RSInitFD; 109283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni unsigned mTempID; // A unique id that can be used to distinguish temporary variables 1104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 111f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject() 112f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // and rsClearObject() in the current ASTContext. 113f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static clang::FunctionDecl *RSSetObjectFD[]; 114f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static clang::FunctionDecl *RSClearObjectFD[]; 115f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 116283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni inline bool emptyScope() const { return mScopeStack.empty(); } 117283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni 1184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines inline Scope *getCurrentScope() { 119283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni return mScopeStack.back(); 1204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines } 1214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 122283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni // Returns the next available unique id for temporary variables 123283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni unsigned getNextID() { return mTempID++; } 124283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni 125f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // Initialize RSSetObjectFD and RSClearObjectFD. 126f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static void GetRSRefCountingFunctions(clang::ASTContext &C); 127f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 128f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // Return false if the type of variable declared in VD does not contain 129f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines // an RS object type. 130e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines static bool InitializeRSObject(clang::VarDecl *VD, 131cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet DataType *DT, 132e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines clang::Expr **InitExpr); 1334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 134670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines // Return an empty list initializer expression at the appropriate location. 135670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines // This construct can then be used to cheaply construct a zero-initializer 136670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines // for any RenderScript objects (like rs_allocation) or rs_matrix* types 137670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines // (possibly even embedded within other types). These types are expected to 138670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines // be zero-initialized always, and so we can use this helper to ensure that 139670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines // they at least have an empty initializer. 140670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines static clang::Expr *CreateEmptyInitListExpr( 1414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines clang::ASTContext &C, 1424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines const clang::SourceLocation &Loc); 1434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 144f44e96036289beae53f6b3f345a723d990563f81Yang Ni // Given a return statement RS that returns an rsObject, creates a temporary 145f44e96036289beae53f6b3f345a723d990563f81Yang Ni // variable, and sets it to the original return expression using rsSetObject(). 146f44e96036289beae53f6b3f345a723d990563f81Yang Ni // Creates a new return statement that returns the temporary variable. 147f44e96036289beae53f6b3f345a723d990563f81Yang Ni // Returns a new compound statement that contains the new variable declaration, 148f44e96036289beae53f6b3f345a723d990563f81Yang Ni // the rsSetOjbect() call, and the new return statement. 149f44e96036289beae53f6b3f345a723d990563f81Yang Ni static clang::CompoundStmt* CreateRetStmtWithTempVar( 150f44e96036289beae53f6b3f345a723d990563f81Yang Ni clang::ASTContext& C, 151f44e96036289beae53f6b3f345a723d990563f81Yang Ni clang::DeclContext* DC, 152f44e96036289beae53f6b3f345a723d990563f81Yang Ni clang::ReturnStmt* RS, 153f44e96036289beae53f6b3f345a723d990563f81Yang Ni const unsigned id); 154f44e96036289beae53f6b3f345a723d990563f81Yang Ni 1554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines public: 156d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines explicit RSObjectRefCount(clang::ASTContext &C) 157283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni : mCtx(C), RSInitFD(false), mTempID(0) { 1581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines } 1591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 160d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines void Init() { 1611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines if (!RSInitFD) { 162d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines GetRSRefCountingFunctions(mCtx); 1631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines RSInitFD = true; 1641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines } 1651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines } 1661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines 167cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet static clang::FunctionDecl *GetRSSetObjectFD(DataType DT) { 168f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)); 169cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet if (DT >= 0 && DT < DataTypeMax) { 170474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet return RSSetObjectFD[DT]; 171474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet } else { 172474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet slangAssert(false && "incorrect type"); 1735abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes return nullptr; 174474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet } 175f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines } 176f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 177f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) { 178f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T)); 179f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines } 180f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 181cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet static clang::FunctionDecl *GetRSClearObjectFD(DataType DT) { 182f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)); 183cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet if (DT >= 0 && DT < DataTypeMax) { 184474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet return RSClearObjectFD[DT]; 185474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet } else { 186474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet slangAssert(false && "incorrect type"); 1875abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes return nullptr; 188474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet } 189f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines } 190f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 191f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) { 192f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T)); 193f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines } 194f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines 195283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni void SetDeclContext(clang::DeclContext* DC) { mCurrentDC = DC; } 196283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni clang::DeclContext* GetDeclContext() const { return mCurrentDC; } 197283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni 1984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines void VisitStmt(clang::Stmt *S); 199283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni void VisitCallExpr(clang::CallExpr *CE); 2004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines void VisitDeclStmt(clang::DeclStmt *DS); 2014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines void VisitCompoundStmt(clang::CompoundStmt *CS); 2024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines void VisitBinAssign(clang::BinaryOperator *AS); 203283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni void VisitReturnStmt(clang::ReturnStmt *RS); 2044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines // We believe that RS objects are never involved in CompoundAssignOperator. 2054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines // I.e., rs_allocation foo; foo += bar; 206688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines 207688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines // Emit a global destructor to clean up RS objects. 208688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines clang::FunctionDecl *CreateStaticGlobalDtor(); 2094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}; 2104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines 211e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines} // namespace slang 212e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines 213e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_ NOLINT 214