slang_rs_object_ref_count.cpp revision 4cc67fce91f43215d61b2695746eab102a3db516
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 <list>
20
21#include "clang/AST/DeclGroup.h"
22#include "clang/AST/Expr.h"
23#include "clang/AST/OperationKinds.h"
24#include "clang/AST/Stmt.h"
25#include "clang/AST/StmtVisitor.h"
26
27#include "slang_rs.h"
28#include "slang_rs_export_type.h"
29
30namespace slang {
31
32clang::FunctionDecl *RSObjectRefCount::Scope::
33    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
34                  RSExportPrimitiveType::FirstRSObjectType + 1];
35clang::FunctionDecl *RSObjectRefCount::Scope::
36    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
37                    RSExportPrimitiveType::FirstRSObjectType + 1];
38
39void RSObjectRefCount::Scope::GetRSRefCountingFunctions(
40    clang::ASTContext &C) {
41  for (unsigned i = 0;
42       i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
43       i++) {
44    RSSetObjectFD[i] = NULL;
45    RSClearObjectFD[i] = NULL;
46  }
47
48  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
49
50  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
51          E = TUDecl->decls_end(); I != E; I++) {
52    if ((I->getKind() >= clang::Decl::firstFunction) &&
53        (I->getKind() <= clang::Decl::lastFunction)) {
54      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
55
56      // points to RSSetObjectFD or RSClearObjectFD
57      clang::FunctionDecl **RSObjectFD;
58
59      if (FD->getName() == "rsSetObject") {
60        assert((FD->getNumParams() == 2) &&
61               "Invalid rsSetObject function prototype (# params)");
62        RSObjectFD = RSSetObjectFD;
63      } else if (FD->getName() == "rsClearObject") {
64        assert((FD->getNumParams() == 1) &&
65               "Invalid rsClearObject function prototype (# params)");
66        RSObjectFD = RSClearObjectFD;
67      } else {
68        continue;
69      }
70
71      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
72      clang::QualType PVT = PVD->getOriginalType();
73      // The first parameter must be a pointer like rs_allocation*
74      assert(PVT->isPointerType() &&
75             "Invalid rs{Set,Clear}Object function prototype (pointer param)");
76
77      // The rs object type passed to the FD
78      clang::QualType RST = PVT->getPointeeType();
79      RSExportPrimitiveType::DataType DT =
80          RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
81      assert(RSExportPrimitiveType::IsRSObjectType(DT)
82             && "must be RS object type");
83
84      RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
85    }
86  }
87}
88
89namespace {
90
91static void AppendToCompoundStatement(clang::ASTContext& C,
92                                      clang::CompoundStmt *CS,
93                                      std::list<clang::Stmt*> &StmtList,
94                                      bool InsertAtEndOfBlock) {
95  // Destructor code will be inserted before any return statement.
96  // Any subsequent statements in the compound statement are then placed
97  // after our new code.
98  // TODO(srhines): This should also handle the case of goto/break/continue.
99
100  clang::CompoundStmt::body_iterator bI = CS->body_begin();
101
102  unsigned OldStmtCount = 0;
103  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
104    OldStmtCount++;
105  }
106
107  unsigned NewStmtCount = StmtList.size();
108
109  clang::Stmt **UpdatedStmtList;
110  UpdatedStmtList = new clang::Stmt*[OldStmtCount+NewStmtCount];
111
112  unsigned UpdatedStmtCount = 0;
113  bool FoundReturn = false;
114  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
115    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
116      FoundReturn = true;
117      break;
118    }
119    UpdatedStmtList[UpdatedStmtCount++] = *bI;
120  }
121
122  // Always insert before a return that we found, or if we are told
123  // to insert at the end of the block
124  if (FoundReturn || InsertAtEndOfBlock) {
125    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
126    for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
127         I != StmtList.end();
128         I++) {
129      UpdatedStmtList[UpdatedStmtCount++] = *I;
130    }
131  }
132
133  // Pick up anything left over after a return statement
134  for ( ; bI != CS->body_end(); bI++) {
135    UpdatedStmtList[UpdatedStmtCount++] = *bI;
136  }
137
138  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
139
140  delete [] UpdatedStmtList;
141
142  return;
143}
144
145static void ReplaceinCompoundStmt(clang::ASTContext& C,
146                                  clang::CompoundStmt *CS,
147                                  clang::Stmt* OldStmt,
148                                  clang::Stmt* NewStmt) {
149  clang::CompoundStmt::body_iterator bI = CS->body_begin();
150
151  unsigned StmtCount = 0;
152  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
153    StmtCount++;
154  }
155
156  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
157
158  unsigned UpdatedStmtCount = 0;
159  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
160    if (*bI == OldStmt) {
161      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
162    } else {
163      UpdatedStmtList[UpdatedStmtCount++] = *bI;
164    }
165  }
166
167  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
168
169  delete [] UpdatedStmtList;
170
171  return;
172}
173
174
175// This class visits a compound statement and inserts the StmtList containing
176// destructors in proper locations. This includes inserting them before any
177// return statement in any sub-block, at the end of the logical enclosing
178// scope (compound statement), and/or before any break/continue statement that
179// would resume outside the declared scope. We will not handle the case for
180// goto statements that leave a local scope.
181// TODO(srhines): Make this work properly for break/continue.
182class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
183 private:
184  clang::ASTContext &mC;
185  std::list<clang::Stmt*> &mStmtList;
186  bool mTopLevel;
187 public:
188  DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList);
189  void VisitStmt(clang::Stmt *S);
190  void VisitCompoundStmt(clang::CompoundStmt *CS);
191};
192
193DestructorVisitor::DestructorVisitor(clang::ASTContext &C,
194                                     std::list<clang::Stmt*> &StmtList)
195  : mC(C),
196    mStmtList(StmtList),
197    mTopLevel(true) {
198  return;
199}
200
201void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
202  if (!CS->body_empty()) {
203    AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel);
204    mTopLevel = false;
205    VisitStmt(CS);
206  }
207  return;
208}
209
210void DestructorVisitor::VisitStmt(clang::Stmt *S) {
211  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
212       I != E;
213       I++) {
214    if (clang::Stmt *Child = *I) {
215      Visit(Child);
216    }
217  }
218  return;
219}
220
221static int ArrayDim(clang::VarDecl *VD) {
222  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
223
224  if (!T || !T->isArrayType()) {
225    return 0;
226  }
227
228  const clang::ConstantArrayType *CAT =
229    static_cast<const clang::ConstantArrayType *>(T);
230  return static_cast<int>(CAT->getSize().getSExtValue());
231}
232
233static clang::Stmt *ClearArrayRSObject(clang::VarDecl *VD,
234    const clang::Type *T,
235    clang::FunctionDecl *ClearObjectFD) {
236  clang::ASTContext &C = VD->getASTContext();
237  clang::SourceRange Range = VD->getQualifierRange();
238  clang::SourceLocation Loc = Range.getEnd();
239
240  clang::Stmt *StmtArray[2] = {NULL};
241  int StmtCtr = 0;
242
243  int NumArrayElements = ArrayDim(VD);
244  if (NumArrayElements <= 0) {
245    return NULL;
246  }
247
248  // Example destructor loop for "rs_font fontArr[10];"
249  //
250  // (CompoundStmt
251  //   (DeclStmt "int rsIntIter")
252  //   (ForStmt
253  //     (BinaryOperator 'int' '='
254  //       (DeclRefExpr 'int' Var='rsIntIter')
255  //       (IntegerLiteral 'int' 0))
256  //     (BinaryOperator 'int' '<'
257  //       (DeclRefExpr 'int' Var='rsIntIter')
258  //       (IntegerLiteral 'int' 10)
259  //     NULL << CondVar >>
260  //     (UnaryOperator 'int' postfix '++'
261  //       (DeclRefExpr 'int' Var='rsIntIter'))
262  //     (CallExpr 'void'
263  //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
264  //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
265  //       (UnaryOperator 'rs_font *' prefix '&'
266  //         (ArraySubscriptExpr 'rs_font':'rs_font'
267  //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
268  //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
269  //           (DeclRefExpr 'int' Var='rsIntIter')))))))
270
271  // Create helper variable for iterating through elements
272  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
273  clang::VarDecl *IIVD =
274      clang::VarDecl::Create(C,
275                             VD->getDeclContext(),
276                             Loc,
277                             &II,
278                             C.IntTy,
279                             C.getTrivialTypeSourceInfo(C.IntTy),
280                             clang::SC_None,
281                             clang::SC_None);
282  clang::Decl *IID = (clang::Decl *)IIVD;
283
284  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
285  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
286
287  // Form the actual destructor loop
288  // for (Init; Cond; Inc)
289  //   RSClearObjectCall;
290
291  // Init -> "rsIntIter = 0"
292  clang::DeclRefExpr *RefrsIntIter =
293      clang::DeclRefExpr::Create(C,
294                                 NULL,
295                                 Range,
296                                 IIVD,
297                                 Loc,
298                                 C.IntTy);
299
300  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
301      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
302
303  clang::BinaryOperator *Init =
304      new(C) clang::BinaryOperator(RefrsIntIter,
305                                   Int0,
306                                   clang::BO_Assign,
307                                   C.IntTy,
308                                   Loc);
309
310  // Cond -> "rsIntIter < NumArrayElements"
311  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
312      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
313
314  clang::BinaryOperator *Cond =
315      new(C) clang::BinaryOperator(RefrsIntIter,
316                                   NumArrayElementsExpr,
317                                   clang::BO_LT,
318                                   C.IntTy,
319                                   Loc);
320
321  // Inc -> "rsIntIter++"
322  clang::UnaryOperator *Inc =
323      new(C) clang::UnaryOperator(RefrsIntIter,
324                                  clang::UO_PostInc,
325                                  C.IntTy,
326                                  Loc);
327
328  // Body -> "rsClearObject(&VD[rsIntIter]);"
329  // Destructor loop operates on individual array elements
330  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
331  clang::QualType ClearObjectFDArgType =
332      ClearObjectFD->getParamDecl(0)->getOriginalType();
333
334  const clang::Type *VT = RSExportType::GetTypeOfDecl(VD);
335  clang::DeclRefExpr *RefRSVar =
336      clang::DeclRefExpr::Create(C,
337                                 NULL,
338                                 Range,
339                                 VD,
340                                 Loc,
341                                 VT->getCanonicalTypeInternal());
342
343  clang::Expr *RefRSVarPtr =
344      clang::ImplicitCastExpr::Create(C,
345          C.getPointerType(T->getCanonicalTypeInternal()),
346          clang::CK_ArrayToPointerDecay,
347          RefRSVar,
348          NULL,
349          clang::VK_RValue);
350
351  clang::Expr *RefRSVarPtrSubscript =
352      new(C) clang::ArraySubscriptExpr(RefRSVarPtr,
353                                       RefrsIntIter,
354                                       T->getCanonicalTypeInternal(),
355                                       VD->getLocation());
356
357  clang::Expr *AddrRefRSVarPtrSubscript =
358      new(C) clang::UnaryOperator(RefRSVarPtrSubscript,
359                                  clang::UO_AddrOf,
360                                  ClearObjectFDArgType,
361                                  VD->getLocation());
362
363  clang::Expr *RefRSClearObjectFD =
364      clang::DeclRefExpr::Create(C,
365                                 NULL,
366                                 Range,
367                                 ClearObjectFD,
368                                 Loc,
369                                 ClearObjectFDType);
370
371  clang::Expr *RSClearObjectFP =
372      clang::ImplicitCastExpr::Create(C,
373                                      C.getPointerType(ClearObjectFDType),
374                                      clang::CK_FunctionToPointerDecay,
375                                      RefRSClearObjectFD,
376                                      NULL,
377                                      clang::VK_RValue);
378
379  clang::CallExpr *RSClearObjectCall =
380      new(C) clang::CallExpr(C,
381                             RSClearObjectFP,
382                             &AddrRefRSVarPtrSubscript,
383                             1,
384                             ClearObjectFD->getCallResultType(),
385                             Loc);
386
387  clang::ForStmt *DestructorLoop =
388      new(C) clang::ForStmt(C,
389                            Init,
390                            Cond,
391                            NULL,  // no condVar
392                            Inc,
393                            RSClearObjectCall,
394                            Loc,
395                            Loc,
396                            Loc);
397
398  StmtArray[StmtCtr++] = DestructorLoop;
399  assert(StmtCtr == 2);
400
401  clang::CompoundStmt *CS =
402      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
403
404  return CS;
405}
406
407}  // namespace
408
409void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
410    clang::BinaryOperator *AS) {
411
412  clang::QualType QT = AS->getType();
413  RSExportPrimitiveType::DataType DT =
414      RSExportPrimitiveType::GetRSSpecificType(QT.getTypePtr());
415
416  clang::FunctionDecl *SetObjectFD =
417      RSSetObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
418  assert((SetObjectFD != NULL) &&
419      "rsSetObject doesn't cover all RS object types");
420  clang::ASTContext &C = SetObjectFD->getASTContext();
421
422  clang::QualType SetObjectFDType = SetObjectFD->getType();
423  clang::QualType SetObjectFDArgType[2];
424  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
425  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
426
427  clang::SourceLocation Loc = SetObjectFD->getLocation();
428  clang::Expr *RefRSSetObjectFD =
429      clang::DeclRefExpr::Create(C,
430                                 NULL,
431                                 SetObjectFD->getQualifierRange(),
432                                 SetObjectFD,
433                                 Loc,
434                                 SetObjectFDType);
435
436  clang::Expr *RSSetObjectFP =
437      clang::ImplicitCastExpr::Create(C,
438                                      C.getPointerType(SetObjectFDType),
439                                      clang::CK_FunctionToPointerDecay,
440                                      RefRSSetObjectFD,
441                                      NULL,
442                                      clang::VK_RValue);
443
444  clang::Expr *ArgList[2];
445  ArgList[0] = new(C) clang::UnaryOperator(AS->getLHS(),
446                                           clang::UO_AddrOf,
447                                           SetObjectFDArgType[0],
448                                           Loc);
449  ArgList[1] = AS->getRHS();
450
451  clang::CallExpr *RSSetObjectCall =
452      new(C) clang::CallExpr(C,
453                             RSSetObjectFP,
454                             ArgList,
455                             2,
456                             SetObjectFD->getCallResultType(),
457                             Loc);
458
459  ReplaceinCompoundStmt(C, mCS, AS, RSSetObjectCall);
460
461  return;
462}
463
464void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
465  std::list<clang::Stmt*> RSClearObjectCalls;
466  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
467          E = mRSO.end();
468        I != E;
469        I++) {
470    clang::Stmt *S = ClearRSObject(*I);
471    if (S) {
472      RSClearObjectCalls.push_back(S);
473    }
474  }
475  if (RSClearObjectCalls.size() > 0) {
476    DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
477    DV.Visit(mCS);
478  }
479  return;
480}
481
482clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
483  bool IsArrayType = false;
484  clang::ASTContext &C = VD->getASTContext();
485  clang::SourceLocation Loc = VD->getLocation();
486  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
487
488  // Loop through array types to get to base type
489  while (T && T->isArrayType()) {
490    T = T->getArrayElementTypeNoTypeQual();
491    IsArrayType = true;
492  }
493
494  RSExportPrimitiveType::DataType DT =
495      RSExportPrimitiveType::GetRSSpecificType(T);
496
497  assert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
498      "Should be RS object");
499
500  // Find the rsClearObject() for VD of RS object type DT
501  clang::FunctionDecl *ClearObjectFD =
502      RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
503  assert((ClearObjectFD != NULL) &&
504      "rsClearObject doesn't cover all RS object types");
505
506  if (IsArrayType) {
507    return ClearArrayRSObject(VD, T, ClearObjectFD);
508  }
509
510  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
511  clang::QualType ClearObjectFDArgType =
512      ClearObjectFD->getParamDecl(0)->getOriginalType();
513
514  // Example destructor for "rs_font localFont;"
515  //
516  // (CallExpr 'void'
517  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
518  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
519  //   (UnaryOperator 'rs_font *' prefix '&'
520  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
521
522  // Reference expr to target RS object variable
523  clang::DeclRefExpr *RefRSVar =
524      clang::DeclRefExpr::Create(C,
525                                 NULL,
526                                 VD->getQualifierRange(),
527                                 VD,
528                                 Loc,
529                                 T->getCanonicalTypeInternal());
530
531  // Get address of RSObject in VD
532  clang::Expr *AddrRefRSVar =
533      new(C) clang::UnaryOperator(RefRSVar,
534                                  clang::UO_AddrOf,
535                                  ClearObjectFDArgType,
536                                  Loc);
537
538  clang::Expr *RefRSClearObjectFD =
539      clang::DeclRefExpr::Create(C,
540                                 NULL,
541                                 ClearObjectFD->getQualifierRange(),
542                                 ClearObjectFD,
543                                 ClearObjectFD->getLocation(),
544                                 ClearObjectFDType);
545
546  clang::Expr *RSClearObjectFP =
547      clang::ImplicitCastExpr::Create(C,
548                                      C.getPointerType(ClearObjectFDType),
549                                      clang::CK_FunctionToPointerDecay,
550                                      RefRSClearObjectFD,
551                                      NULL,
552                                      clang::VK_RValue);
553
554  clang::CallExpr *RSClearObjectCall =
555      new(C) clang::CallExpr(C,
556                             RSClearObjectFP,
557                             &AddrRefRSVar,
558                             1,
559                             ClearObjectFD->getCallResultType(),
560                             clang::SourceLocation());
561
562  return RSClearObjectCall;
563}
564
565bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) {
566  bool IsArrayType = false;
567  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
568
569  // Loop through array types to get to base type
570  while (T && T->isArrayType()) {
571    T = T->getArrayElementTypeNoTypeQual();
572    IsArrayType = true;
573  }
574
575  RSExportPrimitiveType::DataType DT =
576      RSExportPrimitiveType::GetRSSpecificType(T);
577
578  if (DT == RSExportPrimitiveType::DataTypeUnknown) {
579    return false;
580  }
581
582  if (VD->hasInit()) {
583    // TODO(srhines): Update the reference count of RS object in initializer.
584    // This can potentially be done as part of the assignment pass.
585  } else {
586    clang::Expr *ZeroInitializer =
587        CreateZeroInitializerForRSSpecificType(DT,
588                                               VD->getASTContext(),
589                                               VD->getLocation());
590
591    if (ZeroInitializer) {
592      ZeroInitializer->setType(T->getCanonicalTypeInternal());
593      VD->setInit(ZeroInitializer);
594    }
595  }
596
597  return RSExportPrimitiveType::IsRSObjectType(DT);
598}
599
600clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
601    RSExportPrimitiveType::DataType DT,
602    clang::ASTContext &C,
603    const clang::SourceLocation &Loc) {
604  clang::Expr *Res = NULL;
605  switch (DT) {
606    case RSExportPrimitiveType::DataTypeRSElement:
607    case RSExportPrimitiveType::DataTypeRSType:
608    case RSExportPrimitiveType::DataTypeRSAllocation:
609    case RSExportPrimitiveType::DataTypeRSSampler:
610    case RSExportPrimitiveType::DataTypeRSScript:
611    case RSExportPrimitiveType::DataTypeRSMesh:
612    case RSExportPrimitiveType::DataTypeRSProgramFragment:
613    case RSExportPrimitiveType::DataTypeRSProgramVertex:
614    case RSExportPrimitiveType::DataTypeRSProgramRaster:
615    case RSExportPrimitiveType::DataTypeRSProgramStore:
616    case RSExportPrimitiveType::DataTypeRSFont: {
617      //    (ImplicitCastExpr 'nullptr_t'
618      //      (IntegerLiteral 0)))
619      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
620      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
621      clang::Expr *CastToNull =
622          clang::ImplicitCastExpr::Create(C,
623                                          C.NullPtrTy,
624                                          clang::CK_IntegralToPointer,
625                                          Int0,
626                                          NULL,
627                                          clang::VK_RValue);
628
629      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
630      break;
631    }
632    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
633    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
634    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
635      // RS matrix is not completely an RS object. They hold data by themselves.
636      // (InitListExpr rs_matrix2x2
637      //   (InitListExpr float[4]
638      //     (FloatingLiteral 0)
639      //     (FloatingLiteral 0)
640      //     (FloatingLiteral 0)
641      //     (FloatingLiteral 0)))
642      clang::QualType FloatTy = C.FloatTy;
643      // Constructor sets value to 0.0f by default
644      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
645      clang::FloatingLiteral *Float0Val =
646          clang::FloatingLiteral::Create(C,
647                                         Val,
648                                         /* isExact = */true,
649                                         FloatTy,
650                                         Loc);
651
652      unsigned N = 0;
653      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
654        N = 2;
655      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
656        N = 3;
657      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
658        N = 4;
659
660      // Directly allocate 16 elements instead of dynamically allocate N*N
661      clang::Expr *InitVals[16];
662      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
663        InitVals[i] = Float0Val;
664      clang::Expr *InitExpr =
665          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
666      InitExpr->setType(C.getConstantArrayType(FloatTy,
667                                               llvm::APInt(32, 4),
668                                               clang::ArrayType::Normal,
669                                               /* EltTypeQuals = */0));
670
671      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
672      break;
673    }
674    case RSExportPrimitiveType::DataTypeUnknown:
675    case RSExportPrimitiveType::DataTypeFloat16:
676    case RSExportPrimitiveType::DataTypeFloat32:
677    case RSExportPrimitiveType::DataTypeFloat64:
678    case RSExportPrimitiveType::DataTypeSigned8:
679    case RSExportPrimitiveType::DataTypeSigned16:
680    case RSExportPrimitiveType::DataTypeSigned32:
681    case RSExportPrimitiveType::DataTypeSigned64:
682    case RSExportPrimitiveType::DataTypeUnsigned8:
683    case RSExportPrimitiveType::DataTypeUnsigned16:
684    case RSExportPrimitiveType::DataTypeUnsigned32:
685    case RSExportPrimitiveType::DataTypeUnsigned64:
686    case RSExportPrimitiveType::DataTypeBoolean:
687    case RSExportPrimitiveType::DataTypeUnsigned565:
688    case RSExportPrimitiveType::DataTypeUnsigned5551:
689    case RSExportPrimitiveType::DataTypeUnsigned4444:
690    case RSExportPrimitiveType::DataTypeMax: {
691      assert(false && "Not RS object type!");
692    }
693    // No default case will enable compiler detecting the missing cases
694  }
695
696  return Res;
697}
698
699void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
700  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
701       I != E;
702       I++) {
703    clang::Decl *D = *I;
704    if (D->getKind() == clang::Decl::Var) {
705      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
706      if (InitializeRSObject(VD))
707        getCurrentScope()->addRSObject(VD);
708    }
709  }
710  return;
711}
712
713void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
714  if (!CS->body_empty()) {
715    // Push a new scope
716    Scope *S = new Scope(CS);
717    mScopeStack.push(S);
718
719    VisitStmt(CS);
720
721    // Destroy the scope
722    assert((getCurrentScope() == S) && "Corrupted scope stack!");
723    S->InsertLocalVarDestructors();
724    mScopeStack.pop();
725    delete S;
726  }
727  return;
728}
729
730void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
731  clang::QualType QT = AS->getType();
732  RSExportPrimitiveType::DataType DT =
733      RSExportPrimitiveType::GetRSSpecificType(QT.getTypePtr());
734
735  if (RSExportPrimitiveType::IsRSObjectType(DT)) {
736    getCurrentScope()->ReplaceRSObjectAssignment(AS);
737  }
738
739  return;
740}
741
742void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
743  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
744       I != E;
745       I++) {
746    if (clang::Stmt *Child = *I) {
747      Visit(Child);
748    }
749  }
750  return;
751}
752
753}  // namespace slang
754