Home | History | Annotate | Download | only in slang
      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:
     53     explicit Scope(clang::CompoundStmt *CS) : mCS(CS) {
     54       return;
     55     }
     56 
     57     inline void addRSObject(clang::VarDecl* VD) {
     58       mRSO.push_back(VD);
     59       return;
     60     }
     61 
     62     void ReplaceRSObjectAssignment(clang::BinaryOperator *AS);
     63 
     64     void AppendRSObjectInit(clang::VarDecl *VD,
     65                             clang::DeclStmt *DS,
     66                             RSExportPrimitiveType::DataType DT,
     67                             clang::Expr *InitExpr);
     68 
     69     void InsertLocalVarDestructors();
     70 
     71     static clang::Stmt *ClearRSObject(clang::VarDecl *VD,
     72                                       clang::DeclContext *DC);
     73   };
     74 
     75   clang::ASTContext &mCtx;
     76   std::stack<Scope*> mScopeStack;
     77   bool RSInitFD;
     78 
     79   // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject()
     80   // and rsClearObject() in the current ASTContext.
     81   static clang::FunctionDecl *RSSetObjectFD[];
     82   static clang::FunctionDecl *RSClearObjectFD[];
     83 
     84   inline Scope *getCurrentScope() {
     85     return mScopeStack.top();
     86   }
     87 
     88   // Initialize RSSetObjectFD and RSClearObjectFD.
     89   static void GetRSRefCountingFunctions(clang::ASTContext &C);
     90 
     91   // Return false if the type of variable declared in VD does not contain
     92   // an RS object type.
     93   static bool InitializeRSObject(clang::VarDecl *VD,
     94                                  RSExportPrimitiveType::DataType *DT,
     95                                  clang::Expr **InitExpr);
     96 
     97   // Return a zero-initializer expr of the type DT. This processes both
     98   // RS matrix type and RS object type.
     99   static clang::Expr *CreateZeroInitializerForRSSpecificType(
    100       RSExportPrimitiveType::DataType DT,
    101       clang::ASTContext &C,
    102       const clang::SourceLocation &Loc);
    103 
    104  public:
    105   explicit RSObjectRefCount(clang::ASTContext &C)
    106       : mCtx(C),
    107         RSInitFD(false) {
    108     return;
    109   }
    110 
    111   void Init() {
    112     if (!RSInitFD) {
    113       GetRSRefCountingFunctions(mCtx);
    114       RSInitFD = true;
    115     }
    116     return;
    117   }
    118 
    119   static clang::FunctionDecl *GetRSSetObjectFD(
    120       RSExportPrimitiveType::DataType DT) {
    121     slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
    122     return RSSetObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
    123   }
    124 
    125   static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) {
    126     return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
    127   }
    128 
    129   static clang::FunctionDecl *GetRSClearObjectFD(
    130       RSExportPrimitiveType::DataType DT) {
    131     slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
    132     return RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
    133   }
    134 
    135   static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) {
    136     return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
    137   }
    138 
    139   void VisitStmt(clang::Stmt *S);
    140   void VisitDeclStmt(clang::DeclStmt *DS);
    141   void VisitCompoundStmt(clang::CompoundStmt *CS);
    142   void VisitBinAssign(clang::BinaryOperator *AS);
    143   // We believe that RS objects are never involved in CompoundAssignOperator.
    144   // I.e., rs_allocation foo; foo += bar;
    145 
    146   // Emit a global destructor to clean up RS objects.
    147   clang::FunctionDecl *CreateStaticGlobalDtor();
    148 };
    149 
    150 }  // namespace slang
    151 
    152 #endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_  NOLINT
    153