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     }
     55 
     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 
     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:
    103   explicit RSObjectRefCount(clang::ASTContext &C)
    104       : mCtx(C),
    105         RSInitFD(false) {
    106   }
    107 
    108   void Init() {
    109     if (!RSInitFD) {
    110       GetRSRefCountingFunctions(mCtx);
    111       RSInitFD = true;
    112     }
    113   }
    114 
    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 NULL;
    122     }
    123   }
    124 
    125   static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) {
    126     return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
    127   }
    128 
    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 NULL;
    136     }
    137   }
    138 
    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