aboutsummaryrefslogtreecommitdiffstats
path: root/slang_rs_object_ref_count.h
blob: eb200b8993cc931b3b2a92ae9ad2648f69e5d965 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 * Copyright 2010, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_  // NOLINT
#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_

#include <list>
#include <stack>

#include "clang/AST/StmtVisitor.h"

#include "slang_assert.h"
#include "slang_rs_export_type.h"

namespace clang {
  class Expr;
  class Stmt;
}

namespace slang {

// This class provides the overall reference counting mechanism for handling
// local variables of RS object types (rs_font, rs_allocation, ...). This
// class ensures that appropriate functions (rsSetObject, rsClearObject) are
// called at proper points in the object's lifetime.
// 1) Each local object of appropriate type must be zero-initialized (to
// prevent corruption) during subsequent rsSetObject()/rsClearObject() calls.
// 2) Assignments using these types must also be converted into the
// appropriate (possibly a series of) rsSetObject() calls.
// 3) Finally, each local object must call rsClearObject() when it goes out
// of scope.
class RSObjectRefCount : public clang::StmtVisitor<RSObjectRefCount> {
 private:
  class Scope {
   private:
    clang::CompoundStmt *mCS;      // Associated compound statement ({ ... })
    std::list<clang::VarDecl*> mRSO;  // Declared RS objects in this scope

   public:
    explicit Scope(clang::CompoundStmt *CS) : mCS(CS) {
    }

    inline void addRSObject(clang::VarDecl* VD) {
      mRSO.push_back(VD);
    }

    void ReplaceRSObjectAssignment(clang::BinaryOperator *AS);

    void AppendRSObjectInit(clang::VarDecl *VD,
                            clang::DeclStmt *DS,
                            DataType DT,
                            clang::Expr *InitExpr);

    void InsertLocalVarDestructors();

    static clang::Stmt *ClearRSObject(clang::VarDecl *VD,
                                      clang::DeclContext *DC);
  };

  clang::ASTContext &mCtx;
  std::stack<Scope*> mScopeStack;
  bool RSInitFD;

  // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject()
  // and rsClearObject() in the current ASTContext.
  static clang::FunctionDecl *RSSetObjectFD[];
  static clang::FunctionDecl *RSClearObjectFD[];

  inline Scope *getCurrentScope() {
    return mScopeStack.top();
  }

  // Initialize RSSetObjectFD and RSClearObjectFD.
  static void GetRSRefCountingFunctions(clang::ASTContext &C);

  // Return false if the type of variable declared in VD does not contain
  // an RS object type.
  static bool InitializeRSObject(clang::VarDecl *VD,
                                 DataType *DT,
                                 clang::Expr **InitExpr);

  // Return a zero-initializer expr of the type DT. This processes both
  // RS matrix type and RS object type.
  static clang::Expr *CreateZeroInitializerForRSSpecificType(
      DataType DT,
      clang::ASTContext &C,
      const clang::SourceLocation &Loc);

 public:
  explicit RSObjectRefCount(clang::ASTContext &C)
      : mCtx(C),
        RSInitFD(false) {
  }

  void Init() {
    if (!RSInitFD) {
      GetRSRefCountingFunctions(mCtx);
      RSInitFD = true;
    }
  }

  static clang::FunctionDecl *GetRSSetObjectFD(DataType DT) {
    slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
    if (DT >= 0 && DT < DataTypeMax) {
      return RSSetObjectFD[DT];
    } else {
      slangAssert(false && "incorrect type");
      return nullptr;
    }
  }

  static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) {
    return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
  }

  static clang::FunctionDecl *GetRSClearObjectFD(DataType DT) {
    slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
    if (DT >= 0 && DT < DataTypeMax) {
      return RSClearObjectFD[DT];
    } else {
      slangAssert(false && "incorrect type");
      return nullptr;
    }
  }

  static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) {
    return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
  }

  void VisitStmt(clang::Stmt *S);
  void VisitDeclStmt(clang::DeclStmt *DS);
  void VisitCompoundStmt(clang::CompoundStmt *CS);
  void VisitBinAssign(clang::BinaryOperator *AS);
  // We believe that RS objects are never involved in CompoundAssignOperator.
  // I.e., rs_allocation foo; foo += bar;

  // Emit a global destructor to clean up RS objects.
  clang::FunctionDecl *CreateStaticGlobalDtor();
};

}  // namespace slang

#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_  NOLINT