slang_rs_object_ref_count.cpp revision 1bdd4978caabcdc9489bdcb7f1cd6087340699e8
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#include "slang_rs_object_ref_count.h"
18
19#include "clang/AST/DeclGroup.h"
20#include "clang/AST/Expr.h"
21#include "clang/AST/OperationKinds.h"
22#include "clang/AST/Stmt.h"
23#include "clang/AST/StmtVisitor.h"
24
25#include "slang_rs.h"
26#include "slang_rs_export_type.h"
27
28using namespace slang;
29
30clang::FunctionDecl *RSObjectRefCount::Scope::
31    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
32                  RSExportPrimitiveType::FirstRSObjectType + 1];
33clang::FunctionDecl *RSObjectRefCount::Scope::
34    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
35                    RSExportPrimitiveType::FirstRSObjectType + 1];
36
37void RSObjectRefCount::Scope::GetRSRefCountingFunctions(
38    clang::ASTContext &C) {
39  for (unsigned i = 0;
40       i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
41       i++) {
42    RSSetObjectFD[i] = NULL;
43    RSClearObjectFD[i] = NULL;
44  }
45
46  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
47
48  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
49          E = TUDecl->decls_end(); I != E; I++) {
50    if ((I->getKind() >= clang::Decl::firstFunction) &&
51        (I->getKind() <= clang::Decl::lastFunction)) {
52      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
53
54      // points to RSSetObjectFD or RSClearObjectFD
55      clang::FunctionDecl **RSObjectFD;
56
57      if (FD->getName() == "rsSetObject") {
58        assert((FD->getNumParams() == 2) &&
59               "Invalid rsSetObject function prototype (# params)");
60        RSObjectFD = RSSetObjectFD;
61      } else if (FD->getName() == "rsClearObject") {
62        assert((FD->getNumParams() == 1) &&
63               "Invalid rsClearObject function prototype (# params)");
64        RSObjectFD = RSClearObjectFD;
65      }
66      else {
67        continue;
68      }
69
70      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
71      clang::QualType PVT = PVD->getOriginalType();
72      // The first parameter must be a pointer like rs_allocation*
73      assert(PVT->isPointerType() &&
74             "Invalid rs{Set,Clear}Object function prototype (pointer param)");
75
76      // The rs object type passed to the FD
77      clang::QualType RST = PVT->getPointeeType();
78      RSExportPrimitiveType::DataType DT =
79          RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
80      assert(RSExportPrimitiveType::IsRSObjectType(DT)
81             && "must be RS object type");
82
83      RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
84    }
85  }
86}
87
88void RSObjectRefCount::Scope::AppendToCompoundStatement(
89    clang::ASTContext& C, std::list<clang::Expr*> &ExprList) {
90  // Destructor code will be inserted before any return statement.
91  // Any subsequent statements in the compound statement are then placed
92  // after our new code.
93  // TODO: This should also handle the case of goto/break/continue.
94  clang::CompoundStmt::body_iterator bI = mCS->body_begin();
95  clang::CompoundStmt::body_iterator bE = mCS->body_end();
96
97  unsigned OldStmtCount = 0;
98  for ( ; bI != bE; bI++) {
99    OldStmtCount++;
100  }
101
102  unsigned NewExprCount = ExprList.size();
103
104  clang::Stmt **StmtList;
105  StmtList = new clang::Stmt*[OldStmtCount+NewExprCount];
106
107  unsigned UpdatedStmtCount = 0;
108  for (bI = mCS->body_begin(); bI != bE; bI++) {
109    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
110      break;
111    }
112    StmtList[UpdatedStmtCount++] = *bI;
113  }
114
115  std::list<clang::Expr*>::const_iterator E = ExprList.end();
116  for (std::list<clang::Expr*>::const_iterator I = ExprList.begin(),
117          E = ExprList.end();
118       I != E;
119       I++) {
120    StmtList[UpdatedStmtCount++] = *I;
121  }
122
123  // Pick up anything left over after a return statement
124  for ( ; bI != bE; bI++) {
125    StmtList[UpdatedStmtCount++] = *bI;
126  }
127
128  mCS->setStmts(C, StmtList, UpdatedStmtCount);
129  assert(UpdatedStmtCount == (OldStmtCount + NewExprCount));
130
131  delete [] StmtList;
132
133  return;
134}
135
136void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
137  std::list<clang::Expr*> RSClearObjectCalls;
138  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
139          E = mRSO.end();
140        I != E;
141        I++) {
142    clang::Expr *E = ClearRSObject(*I);
143    if (E) {
144      RSClearObjectCalls.push_back(E);
145    }
146  }
147  if (RSClearObjectCalls.size() > 0) {
148    clang::ASTContext &C = (*mRSO.begin())->getASTContext();
149    AppendToCompoundStatement(C, RSClearObjectCalls);
150    // TODO: This should also be extended to append destructors to any
151    // further nested scope (we need another visitor here from within the
152    // current compound statement in case they call return/goto).
153  }
154  return;
155}
156
157clang::Expr *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
158  clang::ASTContext &C = VD->getASTContext();
159  clang::SourceLocation Loc = VD->getLocation();
160  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
161  RSExportPrimitiveType::DataType DT =
162      RSExportPrimitiveType::GetRSSpecificType(T);
163
164  assert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
165      "Should be RS object");
166
167  // Find the rsClearObject() for VD of RS object type DT
168  clang::FunctionDecl *ClearObjectFD =
169      RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
170  assert((ClearObjectFD != NULL) &&
171      "rsClearObject doesn't cover all RS object types");
172
173  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
174  clang::QualType ClearObjectFDArgType =
175      ClearObjectFD->getParamDecl(0)->getOriginalType();
176
177  // We generate a call to rsClearObject passing &VD as the parameter
178  // (CallExpr 'void'
179  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
180  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
181  //   (UnaryOperator 'rs_font *' prefix '&'
182  //     (DeclRefExpr 'rs_font':'rs_font' Var='[var name]')))
183
184  // Reference expr to target RS object variable
185  clang::DeclRefExpr *RefRSVar =
186      clang::DeclRefExpr::Create(C,
187                                 NULL,
188                                 VD->getQualifierRange(),
189                                 VD,
190                                 Loc,
191                                 T->getCanonicalTypeInternal(),
192                                 NULL);
193
194  // Get address of RSObject in VD
195  clang::Expr *AddrRefRSVar =
196      new (C) clang::UnaryOperator(RefRSVar,
197                                   clang::UO_AddrOf,
198                                   ClearObjectFDArgType,
199                                   Loc);
200
201  clang::Expr *RefRSClearObjectFD =
202      clang::DeclRefExpr::Create(C,
203                                 NULL,
204                                 ClearObjectFD->getQualifierRange(),
205                                 ClearObjectFD,
206                                 ClearObjectFD->getLocation(),
207                                 ClearObjectFDType,
208                                 NULL);
209
210  clang::Expr *RSClearObjectFP =
211      clang::ImplicitCastExpr::Create(C,
212                                      C.getPointerType(ClearObjectFDType),
213                                      clang::CK_FunctionToPointerDecay,
214                                      RefRSClearObjectFD,
215                                      NULL,
216                                      clang::VK_RValue);
217
218  clang::CallExpr *RSClearObjectCall =
219      new (C) clang::CallExpr(C,
220                              RSClearObjectFP,
221                              &AddrRefRSVar,
222                              1,
223                              ClearObjectFD->getCallResultType(),
224                              clang::SourceLocation());
225
226  return RSClearObjectCall;
227}
228
229bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) {
230  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
231  RSExportPrimitiveType::DataType DT =
232      RSExportPrimitiveType::GetRSSpecificType(T);
233
234  if (DT == RSExportPrimitiveType::DataTypeUnknown)
235    return false;
236
237  if (VD->hasInit()) {
238    // TODO: Update the reference count of RS object in initializer.
239    // This can potentially be done as part of the assignment pass.
240  } else {
241    clang::Expr *ZeroInitializer =
242        CreateZeroInitializerForRSSpecificType(DT,
243                                               VD->getASTContext(),
244                                               VD->getLocation());
245
246    if (ZeroInitializer) {
247      ZeroInitializer->setType(T->getCanonicalTypeInternal());
248      VD->setInit(ZeroInitializer);
249    }
250  }
251
252  return RSExportPrimitiveType::IsRSObjectType(DT);
253}
254
255clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
256    RSExportPrimitiveType::DataType DT,
257    clang::ASTContext &C,
258    const clang::SourceLocation &Loc) {
259  clang::Expr *Res = NULL;
260  switch (DT) {
261    case RSExportPrimitiveType::DataTypeRSElement:
262    case RSExportPrimitiveType::DataTypeRSType:
263    case RSExportPrimitiveType::DataTypeRSAllocation:
264    case RSExportPrimitiveType::DataTypeRSSampler:
265    case RSExportPrimitiveType::DataTypeRSScript:
266    case RSExportPrimitiveType::DataTypeRSMesh:
267    case RSExportPrimitiveType::DataTypeRSProgramFragment:
268    case RSExportPrimitiveType::DataTypeRSProgramVertex:
269    case RSExportPrimitiveType::DataTypeRSProgramRaster:
270    case RSExportPrimitiveType::DataTypeRSProgramStore:
271    case RSExportPrimitiveType::DataTypeRSFont: {
272      //    (ImplicitCastExpr 'nullptr_t'
273      //      (IntegerLiteral 0)))
274      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
275      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
276      clang::Expr *CastToNull =
277          clang::ImplicitCastExpr::Create(C,
278                                          C.NullPtrTy,
279                                          clang::CK_IntegralToPointer,
280                                          Int0,
281                                          NULL,
282                                          clang::VK_RValue);
283
284      Res = new (C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
285      break;
286    }
287    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
288    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
289    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
290      // RS matrix is not completely an RS object. They hold data by themselves.
291      // (InitListExpr rs_matrix2x2
292      //   (InitListExpr float[4]
293      //     (FloatingLiteral 0)
294      //     (FloatingLiteral 0)
295      //     (FloatingLiteral 0)
296      //     (FloatingLiteral 0)))
297      clang::QualType FloatTy = C.FloatTy;
298      // Constructor sets value to 0.0f by default
299      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
300      clang::FloatingLiteral *Float0Val =
301          clang::FloatingLiteral::Create(C,
302                                         Val,
303                                         /* isExact = */true,
304                                         FloatTy,
305                                         Loc);
306
307      unsigned N = 0;
308      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
309        N = 2;
310      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
311        N = 3;
312      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
313        N = 4;
314
315      // Directly allocate 16 elements instead of dynamically allocate N*N
316      clang::Expr *InitVals[16];
317      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
318        InitVals[i] = Float0Val;
319      clang::Expr *InitExpr =
320          new (C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
321      InitExpr->setType(C.getConstantArrayType(FloatTy,
322                                               llvm::APInt(32, 4),
323                                               clang::ArrayType::Normal,
324                                               /* EltTypeQuals = */0));
325
326      Res = new (C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
327      break;
328    }
329    case RSExportPrimitiveType::DataTypeUnknown:
330    case RSExportPrimitiveType::DataTypeFloat16:
331    case RSExportPrimitiveType::DataTypeFloat32:
332    case RSExportPrimitiveType::DataTypeFloat64:
333    case RSExportPrimitiveType::DataTypeSigned8:
334    case RSExportPrimitiveType::DataTypeSigned16:
335    case RSExportPrimitiveType::DataTypeSigned32:
336    case RSExportPrimitiveType::DataTypeSigned64:
337    case RSExportPrimitiveType::DataTypeUnsigned8:
338    case RSExportPrimitiveType::DataTypeUnsigned16:
339    case RSExportPrimitiveType::DataTypeUnsigned32:
340    case RSExportPrimitiveType::DataTypeUnsigned64:
341    case RSExportPrimitiveType::DataTypeBoolean:
342    case RSExportPrimitiveType::DataTypeUnsigned565:
343    case RSExportPrimitiveType::DataTypeUnsigned5551:
344    case RSExportPrimitiveType::DataTypeUnsigned4444:
345    case RSExportPrimitiveType::DataTypeMax: {
346      assert(false && "Not RS object type!");
347    }
348    // No default case will enable compiler detecting the missing cases
349  }
350
351  return Res;
352}
353
354void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
355  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
356       I != E;
357       I++) {
358    clang::Decl *D = *I;
359    if (D->getKind() == clang::Decl::Var) {
360      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
361      if (InitializeRSObject(VD))
362        getCurrentScope()->addRSObject(VD);
363    }
364  }
365  return;
366}
367
368void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
369  if (!CS->body_empty()) {
370    // Push a new scope
371    Scope *S = new Scope(CS);
372    mScopeStack.push(S);
373
374    VisitStmt(CS);
375
376    // Destroy the scope
377    // TODO: Update reference count of the RS object refenced by
378    //       getCurrentScope().
379    assert((getCurrentScope() == S) && "Corrupted scope stack!");
380    S->InsertLocalVarDestructors();
381    mScopeStack.pop();
382    delete S;
383  }
384  return;
385}
386
387void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
388  // TODO: Update reference count
389  return;
390}
391
392void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
393  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
394       I != E;
395       I++) {
396    if (clang::Stmt *Child = *I) {
397      Visit(Child);
398    }
399  }
400  return;
401}
402
403
404