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