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 #include "slang_rs_object_ref_count.h"
     18 
     19 #include "clang/AST/DeclGroup.h"
     20 #include "clang/AST/Expr.h"
     21 #include "clang/AST/NestedNameSpecifier.h"
     22 #include "clang/AST/OperationKinds.h"
     23 #include "clang/AST/RecursiveASTVisitor.h"
     24 #include "clang/AST/Stmt.h"
     25 #include "clang/AST/StmtVisitor.h"
     26 
     27 #include "slang_assert.h"
     28 #include "slang.h"
     29 #include "slang_rs_ast_replace.h"
     30 #include "slang_rs_export_type.h"
     31 
     32 namespace slang {
     33 
     34 /* Even though those two arrays are of size DataTypeMax, only entries that
     35  * correspond to object types will be set.
     36  */
     37 clang::FunctionDecl *
     38 RSObjectRefCount::RSSetObjectFD[DataTypeMax];
     39 clang::FunctionDecl *
     40 RSObjectRefCount::RSClearObjectFD[DataTypeMax];
     41 
     42 void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
     43   for (unsigned i = 0; i < DataTypeMax; i++) {
     44     RSSetObjectFD[i] = nullptr;
     45     RSClearObjectFD[i] = nullptr;
     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         slangAssert((FD->getNumParams() == 2) &&
     61                     "Invalid rsSetObject function prototype (# params)");
     62         RSObjectFD = RSSetObjectFD;
     63       } else if (FD->getName() == "rsClearObject") {
     64         slangAssert((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       slangAssert(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       DataType DT = RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
     80       slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
     81              && "must be RS object type");
     82 
     83       if (DT >= 0 && DT < DataTypeMax) {
     84           RSObjectFD[DT] = FD;
     85       } else {
     86           slangAssert(false && "incorrect type");
     87       }
     88     }
     89   }
     90 }
     91 
     92 namespace {
     93 
     94 unsigned CountRSObjectTypes(const clang::Type *T);
     95 
     96 clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
     97                                      clang::Expr *DstExpr,
     98                                      clang::Expr *SrcExpr,
     99                                      clang::SourceLocation StartLoc,
    100                                      clang::SourceLocation Loc);
    101 
    102 // This function constructs a new CompoundStmt from the input StmtList.
    103 clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
    104       std::vector<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
    105   unsigned NewStmtCount = StmtList.size();
    106   unsigned CompoundStmtCount = 0;
    107 
    108   clang::Stmt **CompoundStmtList;
    109   CompoundStmtList = new clang::Stmt*[NewStmtCount];
    110 
    111   std::vector<clang::Stmt*>::const_iterator I = StmtList.begin();
    112   std::vector<clang::Stmt*>::const_iterator E = StmtList.end();
    113   for ( ; I != E; I++) {
    114     CompoundStmtList[CompoundStmtCount++] = *I;
    115   }
    116   slangAssert(CompoundStmtCount == NewStmtCount);
    117 
    118   clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
    119       C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);
    120 
    121   delete [] CompoundStmtList;
    122 
    123   return CS;
    124 }
    125 
    126 void AppendAfterStmt(clang::ASTContext &C,
    127                      clang::CompoundStmt *CS,
    128                      clang::Stmt *S,
    129                      std::list<clang::Stmt*> &StmtList) {
    130   slangAssert(CS);
    131   clang::CompoundStmt::body_iterator bI = CS->body_begin();
    132   clang::CompoundStmt::body_iterator bE = CS->body_end();
    133   clang::Stmt **UpdatedStmtList =
    134       new clang::Stmt*[CS->size() + StmtList.size()];
    135 
    136   unsigned UpdatedStmtCount = 0;
    137   unsigned Once = 0;
    138   for ( ; bI != bE; bI++) {
    139     if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
    140       // If we come across a return here, we don't have anything we can
    141       // reasonably replace. We should have already inserted our destructor
    142       // code in the proper spot, so we just clean up and return.
    143       delete [] UpdatedStmtList;
    144 
    145       return;
    146     }
    147 
    148     UpdatedStmtList[UpdatedStmtCount++] = *bI;
    149 
    150     if ((*bI == S) && !Once) {
    151       Once++;
    152       std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
    153       std::list<clang::Stmt*>::const_iterator E = StmtList.end();
    154       for ( ; I != E; I++) {
    155         UpdatedStmtList[UpdatedStmtCount++] = *I;
    156       }
    157     }
    158   }
    159   slangAssert(Once <= 1);
    160 
    161   // When S is nullptr, we are appending to the end of the CompoundStmt.
    162   if (!S) {
    163     slangAssert(Once == 0);
    164     std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
    165     std::list<clang::Stmt*>::const_iterator E = StmtList.end();
    166     for ( ; I != E; I++) {
    167       UpdatedStmtList[UpdatedStmtCount++] = *I;
    168     }
    169   }
    170 
    171   CS->setStmts(C, llvm::makeArrayRef(UpdatedStmtList, UpdatedStmtCount));
    172 
    173   delete [] UpdatedStmtList;
    174 }
    175 
    176 // This class visits a compound statement and collects a list of all the exiting
    177 // statements, such as any return statement in any sub-block, and any
    178 // break/continue statement that would resume outside the current scope.
    179 // We do not handle the case for goto statements that leave a local scope.
    180 class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
    181  private:
    182   // The loop depth of the currently visited node.
    183   int mLoopDepth;
    184 
    185   // The switch statement depth of the currently visited node.
    186   // Note that this is tracked separately from the loop depth because
    187   // SwitchStmt-contained ContinueStmt's should have destructors for the
    188   // corresponding loop scope.
    189   int mSwitchDepth;
    190 
    191   // Output of the visitor: the statements that should be replaced by compound
    192   // statements, each of which contains rsClearObject() calls followed by the
    193   // original statement.
    194   std::vector<clang::Stmt*> mExitingStmts;
    195 
    196  public:
    197   DestructorVisitor() : mLoopDepth(0), mSwitchDepth(0) {}
    198 
    199   const std::vector<clang::Stmt*>& getExitingStmts() const {
    200     return mExitingStmts;
    201   }
    202 
    203   void VisitStmt(clang::Stmt *S);
    204   void VisitBreakStmt(clang::BreakStmt *BS);
    205   void VisitContinueStmt(clang::ContinueStmt *CS);
    206   void VisitDoStmt(clang::DoStmt *DS);
    207   void VisitForStmt(clang::ForStmt *FS);
    208   void VisitReturnStmt(clang::ReturnStmt *RS);
    209   void VisitSwitchStmt(clang::SwitchStmt *SS);
    210   void VisitWhileStmt(clang::WhileStmt *WS);
    211 };
    212 
    213 void DestructorVisitor::VisitStmt(clang::Stmt *S) {
    214   for (clang::Stmt* Child : S->children()) {
    215     if (Child) {
    216       Visit(Child);
    217     }
    218   }
    219 }
    220 
    221 void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
    222   VisitStmt(BS);
    223   if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
    224     mExitingStmts.push_back(BS);
    225   }
    226 }
    227 
    228 void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
    229   VisitStmt(CS);
    230   if (mLoopDepth == 0) {
    231     // Switch statements can have nested continues.
    232     mExitingStmts.push_back(CS);
    233   }
    234 }
    235 
    236 void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
    237   mLoopDepth++;
    238   VisitStmt(DS);
    239   mLoopDepth--;
    240 }
    241 
    242 void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
    243   mLoopDepth++;
    244   VisitStmt(FS);
    245   mLoopDepth--;
    246 }
    247 
    248 void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
    249   mExitingStmts.push_back(RS);
    250 }
    251 
    252 void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
    253   mSwitchDepth++;
    254   VisitStmt(SS);
    255   mSwitchDepth--;
    256 }
    257 
    258 void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
    259   mLoopDepth++;
    260   VisitStmt(WS);
    261   mLoopDepth--;
    262 }
    263 
    264 clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
    265                                  clang::Expr *RefRSVar,
    266                                  clang::SourceLocation Loc) {
    267   slangAssert(RefRSVar);
    268   const clang::Type *T = RefRSVar->getType().getTypePtr();
    269   slangAssert(!T->isArrayType() &&
    270               "Should not be destroying arrays with this function");
    271 
    272   clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
    273   slangAssert((ClearObjectFD != nullptr) &&
    274               "rsClearObject doesn't cover all RS object types");
    275 
    276   clang::QualType ClearObjectFDType = ClearObjectFD->getType();
    277   clang::QualType ClearObjectFDArgType =
    278       ClearObjectFD->getParamDecl(0)->getOriginalType();
    279 
    280   // Example destructor for "rs_font localFont;"
    281   //
    282   // (CallExpr 'void'
    283   //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
    284   //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
    285   //   (UnaryOperator 'rs_font *' prefix '&'
    286   //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
    287 
    288   // Get address of targeted RS object
    289   clang::Expr *AddrRefRSVar =
    290       new(C) clang::UnaryOperator(RefRSVar,
    291                                   clang::UO_AddrOf,
    292                                   ClearObjectFDArgType,
    293                                   clang::VK_RValue,
    294                                   clang::OK_Ordinary,
    295                                   Loc);
    296 
    297   clang::Expr *RefRSClearObjectFD =
    298       clang::DeclRefExpr::Create(C,
    299                                  clang::NestedNameSpecifierLoc(),
    300                                  clang::SourceLocation(),
    301                                  ClearObjectFD,
    302                                  false,
    303                                  ClearObjectFD->getLocation(),
    304                                  ClearObjectFDType,
    305                                  clang::VK_RValue,
    306                                  nullptr);
    307 
    308   clang::Expr *RSClearObjectFP =
    309       clang::ImplicitCastExpr::Create(C,
    310                                       C.getPointerType(ClearObjectFDType),
    311                                       clang::CK_FunctionToPointerDecay,
    312                                       RefRSClearObjectFD,
    313                                       nullptr,
    314                                       clang::VK_RValue);
    315 
    316   llvm::SmallVector<clang::Expr*, 1> ArgList;
    317   ArgList.push_back(AddrRefRSVar);
    318 
    319   clang::CallExpr *RSClearObjectCall =
    320       new(C) clang::CallExpr(C,
    321                              RSClearObjectFP,
    322                              ArgList,
    323                              ClearObjectFD->getCallResultType(),
    324                              clang::VK_RValue,
    325                              Loc);
    326 
    327   return RSClearObjectCall;
    328 }
    329 
    330 static int ArrayDim(const clang::Type *T) {
    331   if (!T || !T->isArrayType()) {
    332     return 0;
    333   }
    334 
    335   const clang::ConstantArrayType *CAT =
    336     static_cast<const clang::ConstantArrayType *>(T);
    337   return static_cast<int>(CAT->getSize().getSExtValue());
    338 }
    339 
    340 clang::Stmt *ClearStructRSObject(
    341     clang::ASTContext &C,
    342     clang::DeclContext *DC,
    343     clang::Expr *RefRSStruct,
    344     clang::SourceLocation StartLoc,
    345     clang::SourceLocation Loc);
    346 
    347 clang::Stmt *ClearArrayRSObject(
    348     clang::ASTContext &C,
    349     clang::DeclContext *DC,
    350     clang::Expr *RefRSArr,
    351     clang::SourceLocation StartLoc,
    352     clang::SourceLocation Loc) {
    353   const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
    354   slangAssert(BaseType->isArrayType());
    355 
    356   int NumArrayElements = ArrayDim(BaseType);
    357   // Actually extract out the base RS object type for use later
    358   BaseType = BaseType->getArrayElementTypeNoTypeQual();
    359 
    360   if (NumArrayElements <= 0) {
    361     return nullptr;
    362   }
    363 
    364   // Example destructor loop for "rs_font fontArr[10];"
    365   //
    366   // (ForStmt
    367   //   (DeclStmt
    368   //     (VarDecl used rsIntIter 'int' cinit
    369   //       (IntegerLiteral 'int' 0)))
    370   //   (BinaryOperator 'int' '<'
    371   //     (ImplicitCastExpr int LValueToRValue
    372   //       (DeclRefExpr 'int' Var='rsIntIter'))
    373   //     (IntegerLiteral 'int' 10)
    374   //   nullptr << CondVar >>
    375   //   (UnaryOperator 'int' postfix '++'
    376   //     (DeclRefExpr 'int' Var='rsIntIter'))
    377   //   (CallExpr 'void'
    378   //     (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
    379   //       (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
    380   //     (UnaryOperator 'rs_font *' prefix '&'
    381   //       (ArraySubscriptExpr 'rs_font':'rs_font'
    382   //         (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
    383   //           (DeclRefExpr 'rs_font [10]' Var='fontArr'))
    384   //         (DeclRefExpr 'int' Var='rsIntIter'))))))
    385 
    386   // Create helper variable for iterating through elements
    387   static unsigned sIterCounter = 0;
    388   std::stringstream UniqueIterName;
    389   UniqueIterName << "rsIntIter" << sIterCounter++;
    390   clang::IdentifierInfo *II = &C.Idents.get(UniqueIterName.str());
    391   clang::VarDecl *IIVD =
    392       clang::VarDecl::Create(C,
    393                              DC,
    394                              StartLoc,
    395                              Loc,
    396                              II,
    397                              C.IntTy,
    398                              C.getTrivialTypeSourceInfo(C.IntTy),
    399                              clang::SC_None);
    400   // Mark "rsIntIter" as used
    401   IIVD->markUsed(C);
    402 
    403   // Form the actual destructor loop
    404   // for (Init; Cond; Inc)
    405   //   RSClearObjectCall;
    406 
    407   // Init -> "int rsIntIter = 0"
    408   clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
    409       llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
    410   IIVD->setInit(Int0);
    411 
    412   clang::Decl *IID = (clang::Decl *)IIVD;
    413   clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
    414   clang::Stmt *Init = new(C) clang::DeclStmt(DGR, Loc, Loc);
    415 
    416   // Cond -> "rsIntIter < NumArrayElements"
    417   clang::DeclRefExpr *RefrsIntIterLValue =
    418       clang::DeclRefExpr::Create(C,
    419                                  clang::NestedNameSpecifierLoc(),
    420                                  clang::SourceLocation(),
    421                                  IIVD,
    422                                  false,
    423                                  Loc,
    424                                  C.IntTy,
    425                                  clang::VK_LValue,
    426                                  nullptr);
    427 
    428   clang::Expr *RefrsIntIterRValue =
    429       clang::ImplicitCastExpr::Create(C,
    430                                       RefrsIntIterLValue->getType(),
    431                                       clang::CK_LValueToRValue,
    432                                       RefrsIntIterLValue,
    433                                       nullptr,
    434                                       clang::VK_RValue);
    435 
    436   clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
    437       llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
    438 
    439   clang::BinaryOperator *Cond =
    440       new(C) clang::BinaryOperator(RefrsIntIterRValue,
    441                                    NumArrayElementsExpr,
    442                                    clang::BO_LT,
    443                                    C.IntTy,
    444                                    clang::VK_RValue,
    445                                    clang::OK_Ordinary,
    446                                    Loc,
    447                                    false);
    448 
    449   // Inc -> "rsIntIter++"
    450   clang::UnaryOperator *Inc =
    451       new(C) clang::UnaryOperator(RefrsIntIterLValue,
    452                                   clang::UO_PostInc,
    453                                   C.IntTy,
    454                                   clang::VK_RValue,
    455                                   clang::OK_Ordinary,
    456                                   Loc);
    457 
    458   // Body -> "rsClearObject(&VD[rsIntIter]);"
    459   // Destructor loop operates on individual array elements
    460 
    461   clang::Expr *RefRSArrPtr =
    462       clang::ImplicitCastExpr::Create(C,
    463           C.getPointerType(BaseType->getCanonicalTypeInternal()),
    464           clang::CK_ArrayToPointerDecay,
    465           RefRSArr,
    466           nullptr,
    467           clang::VK_RValue);
    468 
    469   clang::Expr *RefRSArrPtrSubscript =
    470       new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
    471                                        RefrsIntIterRValue,
    472                                        BaseType->getCanonicalTypeInternal(),
    473                                        clang::VK_RValue,
    474                                        clang::OK_Ordinary,
    475                                        Loc);
    476 
    477   DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
    478 
    479   clang::Stmt *RSClearObjectCall = nullptr;
    480   if (BaseType->isArrayType()) {
    481     RSClearObjectCall =
    482         ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
    483   } else if (DT == DataTypeUnknown) {
    484     RSClearObjectCall =
    485         ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
    486   } else {
    487     RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
    488   }
    489 
    490   clang::ForStmt *DestructorLoop =
    491       new(C) clang::ForStmt(C,
    492                             Init,
    493                             Cond,
    494                             nullptr,  // no condVar
    495                             Inc,
    496                             RSClearObjectCall,
    497                             Loc,
    498                             Loc,
    499                             Loc);
    500 
    501   return DestructorLoop;
    502 }
    503 
    504 unsigned CountRSObjectTypes(const clang::Type *T) {
    505   slangAssert(T);
    506   unsigned RSObjectCount = 0;
    507 
    508   if (T->isArrayType()) {
    509     return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
    510   }
    511 
    512   DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
    513   if (DT != DataTypeUnknown) {
    514     return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
    515   }
    516 
    517   if (T->isUnionType()) {
    518     clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
    519     RD = RD->getDefinition();
    520     for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    521            FE = RD->field_end();
    522          FI != FE;
    523          FI++) {
    524       const clang::FieldDecl *FD = *FI;
    525       const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    526       if (CountRSObjectTypes(FT)) {
    527         slangAssert(false && "can't have unions with RS object types!");
    528         return 0;
    529       }
    530     }
    531   }
    532 
    533   if (!T->isStructureType()) {
    534     return 0;
    535   }
    536 
    537   clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
    538   RD = RD->getDefinition();
    539   for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    540          FE = RD->field_end();
    541        FI != FE;
    542        FI++) {
    543     const clang::FieldDecl *FD = *FI;
    544     const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    545     if (CountRSObjectTypes(FT)) {
    546       // Sub-structs should only count once (as should arrays, etc.)
    547       RSObjectCount++;
    548     }
    549   }
    550 
    551   return RSObjectCount;
    552 }
    553 
    554 clang::Stmt *ClearStructRSObject(
    555     clang::ASTContext &C,
    556     clang::DeclContext *DC,
    557     clang::Expr *RefRSStruct,
    558     clang::SourceLocation StartLoc,
    559     clang::SourceLocation Loc) {
    560   const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
    561 
    562   slangAssert(!BaseType->isArrayType());
    563 
    564   // Structs should show up as unknown primitive types
    565   slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
    566               DataTypeUnknown);
    567 
    568   unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
    569   slangAssert(FieldsToDestroy != 0);
    570 
    571   unsigned StmtCount = 0;
    572   clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
    573   for (unsigned i = 0; i < FieldsToDestroy; i++) {
    574     StmtArray[i] = nullptr;
    575   }
    576 
    577   // Populate StmtArray by creating a destructor for each RS object field
    578   clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
    579   RD = RD->getDefinition();
    580   for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    581          FE = RD->field_end();
    582        FI != FE;
    583        FI++) {
    584     // We just look through all field declarations to see if we find a
    585     // declaration for an RS object type (or an array of one).
    586     bool IsArrayType = false;
    587     clang::FieldDecl *FD = *FI;
    588     const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    589     const clang::Type *OrigType = FT;
    590     while (FT && FT->isArrayType()) {
    591       FT = FT->getArrayElementTypeNoTypeQual();
    592       IsArrayType = true;
    593     }
    594 
    595     // Pass a DeclarationNameInfo with a valid DeclName, since name equality
    596     // gets asserted during CodeGen.
    597     clang::DeclarationNameInfo FDDeclNameInfo(FD->getDeclName(),
    598                                               FD->getLocation());
    599 
    600     if (RSExportPrimitiveType::IsRSObjectType(FT)) {
    601       clang::DeclAccessPair FoundDecl =
    602           clang::DeclAccessPair::make(FD, clang::AS_none);
    603       clang::MemberExpr *RSObjectMember =
    604           clang::MemberExpr::Create(C,
    605                                     RefRSStruct,
    606                                     false,
    607                                     clang::SourceLocation(),
    608                                     clang::NestedNameSpecifierLoc(),
    609                                     clang::SourceLocation(),
    610                                     FD,
    611                                     FoundDecl,
    612                                     FDDeclNameInfo,
    613                                     nullptr,
    614                                     OrigType->getCanonicalTypeInternal(),
    615                                     clang::VK_RValue,
    616                                     clang::OK_Ordinary);
    617 
    618       slangAssert(StmtCount < FieldsToDestroy);
    619 
    620       if (IsArrayType) {
    621         StmtArray[StmtCount++] = ClearArrayRSObject(C,
    622                                                     DC,
    623                                                     RSObjectMember,
    624                                                     StartLoc,
    625                                                     Loc);
    626       } else {
    627         StmtArray[StmtCount++] = ClearSingleRSObject(C,
    628                                                      RSObjectMember,
    629                                                      Loc);
    630       }
    631     } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
    632       // In this case, we have a nested struct. We may not end up filling all
    633       // of the spaces in StmtArray (sub-structs should handle themselves
    634       // with separate compound statements).
    635       clang::DeclAccessPair FoundDecl =
    636           clang::DeclAccessPair::make(FD, clang::AS_none);
    637       clang::MemberExpr *RSObjectMember =
    638           clang::MemberExpr::Create(C,
    639                                     RefRSStruct,
    640                                     false,
    641                                     clang::SourceLocation(),
    642                                     clang::NestedNameSpecifierLoc(),
    643                                     clang::SourceLocation(),
    644                                     FD,
    645                                     FoundDecl,
    646                                     clang::DeclarationNameInfo(),
    647                                     nullptr,
    648                                     OrigType->getCanonicalTypeInternal(),
    649                                     clang::VK_RValue,
    650                                     clang::OK_Ordinary);
    651 
    652       if (IsArrayType) {
    653         StmtArray[StmtCount++] = ClearArrayRSObject(C,
    654                                                     DC,
    655                                                     RSObjectMember,
    656                                                     StartLoc,
    657                                                     Loc);
    658       } else {
    659         StmtArray[StmtCount++] = ClearStructRSObject(C,
    660                                                      DC,
    661                                                      RSObjectMember,
    662                                                      StartLoc,
    663                                                      Loc);
    664       }
    665     }
    666   }
    667 
    668   slangAssert(StmtCount > 0);
    669   clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
    670       C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
    671 
    672   delete [] StmtArray;
    673 
    674   return CS;
    675 }
    676 
    677 clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
    678                                      clang::Expr *DstExpr,
    679                                      clang::Expr *SrcExpr,
    680                                      clang::SourceLocation StartLoc,
    681                                      clang::SourceLocation Loc) {
    682   const clang::Type *T = DstExpr->getType().getTypePtr();
    683   clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
    684   slangAssert((SetObjectFD != nullptr) &&
    685               "rsSetObject doesn't cover all RS object types");
    686 
    687   clang::QualType SetObjectFDType = SetObjectFD->getType();
    688   clang::QualType SetObjectFDArgType[2];
    689   SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
    690   SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
    691 
    692   clang::Expr *RefRSSetObjectFD =
    693       clang::DeclRefExpr::Create(C,
    694                                  clang::NestedNameSpecifierLoc(),
    695                                  clang::SourceLocation(),
    696                                  SetObjectFD,
    697                                  false,
    698                                  Loc,
    699                                  SetObjectFDType,
    700                                  clang::VK_RValue,
    701                                  nullptr);
    702 
    703   clang::Expr *RSSetObjectFP =
    704       clang::ImplicitCastExpr::Create(C,
    705                                       C.getPointerType(SetObjectFDType),
    706                                       clang::CK_FunctionToPointerDecay,
    707                                       RefRSSetObjectFD,
    708                                       nullptr,
    709                                       clang::VK_RValue);
    710 
    711   llvm::SmallVector<clang::Expr*, 2> ArgList;
    712   ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
    713                                                 clang::UO_AddrOf,
    714                                                 SetObjectFDArgType[0],
    715                                                 clang::VK_RValue,
    716                                                 clang::OK_Ordinary,
    717                                                 Loc));
    718   ArgList.push_back(SrcExpr);
    719 
    720   clang::CallExpr *RSSetObjectCall =
    721       new(C) clang::CallExpr(C,
    722                              RSSetObjectFP,
    723                              ArgList,
    724                              SetObjectFD->getCallResultType(),
    725                              clang::VK_RValue,
    726                              Loc);
    727 
    728   return RSSetObjectCall;
    729 }
    730 
    731 clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
    732                                      clang::Expr *LHS,
    733                                      clang::Expr *RHS,
    734                                      clang::SourceLocation StartLoc,
    735                                      clang::SourceLocation Loc);
    736 
    737 /*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
    738                                            clang::Expr *DstArr,
    739                                            clang::Expr *SrcArr,
    740                                            clang::SourceLocation StartLoc,
    741                                            clang::SourceLocation Loc) {
    742   clang::DeclContext *DC = nullptr;
    743   const clang::Type *BaseType = DstArr->getType().getTypePtr();
    744   slangAssert(BaseType->isArrayType());
    745 
    746   int NumArrayElements = ArrayDim(BaseType);
    747   // Actually extract out the base RS object type for use later
    748   BaseType = BaseType->getArrayElementTypeNoTypeQual();
    749 
    750   clang::Stmt *StmtArray[2] = {nullptr};
    751   int StmtCtr = 0;
    752 
    753   if (NumArrayElements <= 0) {
    754     return nullptr;
    755   }
    756 
    757   // Create helper variable for iterating through elements
    758   clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
    759   clang::VarDecl *IIVD =
    760       clang::VarDecl::Create(C,
    761                              DC,
    762                              StartLoc,
    763                              Loc,
    764                              &II,
    765                              C.IntTy,
    766                              C.getTrivialTypeSourceInfo(C.IntTy),
    767                              clang::SC_None,
    768                              clang::SC_None);
    769   clang::Decl *IID = (clang::Decl *)IIVD;
    770 
    771   clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
    772   StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
    773 
    774   // Form the actual loop
    775   // for (Init; Cond; Inc)
    776   //   RSSetObjectCall;
    777 
    778   // Init -> "rsIntIter = 0"
    779   clang::DeclRefExpr *RefrsIntIter =
    780       clang::DeclRefExpr::Create(C,
    781                                  clang::NestedNameSpecifierLoc(),
    782                                  IIVD,
    783                                  Loc,
    784                                  C.IntTy,
    785                                  clang::VK_RValue,
    786                                  nullptr);
    787 
    788   clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
    789       llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
    790 
    791   clang::BinaryOperator *Init =
    792       new(C) clang::BinaryOperator(RefrsIntIter,
    793                                    Int0,
    794                                    clang::BO_Assign,
    795                                    C.IntTy,
    796                                    clang::VK_RValue,
    797                                    clang::OK_Ordinary,
    798                                    Loc);
    799 
    800   // Cond -> "rsIntIter < NumArrayElements"
    801   clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
    802       llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
    803 
    804   clang::BinaryOperator *Cond =
    805       new(C) clang::BinaryOperator(RefrsIntIter,
    806                                    NumArrayElementsExpr,
    807                                    clang::BO_LT,
    808                                    C.IntTy,
    809                                    clang::VK_RValue,
    810                                    clang::OK_Ordinary,
    811                                    Loc);
    812 
    813   // Inc -> "rsIntIter++"
    814   clang::UnaryOperator *Inc =
    815       new(C) clang::UnaryOperator(RefrsIntIter,
    816                                   clang::UO_PostInc,
    817                                   C.IntTy,
    818                                   clang::VK_RValue,
    819                                   clang::OK_Ordinary,
    820                                   Loc);
    821 
    822   // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
    823   // Loop operates on individual array elements
    824 
    825   clang::Expr *DstArrPtr =
    826       clang::ImplicitCastExpr::Create(C,
    827           C.getPointerType(BaseType->getCanonicalTypeInternal()),
    828           clang::CK_ArrayToPointerDecay,
    829           DstArr,
    830           nullptr,
    831           clang::VK_RValue);
    832 
    833   clang::Expr *DstArrPtrSubscript =
    834       new(C) clang::ArraySubscriptExpr(DstArrPtr,
    835                                        RefrsIntIter,
    836                                        BaseType->getCanonicalTypeInternal(),
    837                                        clang::VK_RValue,
    838                                        clang::OK_Ordinary,
    839                                        Loc);
    840 
    841   clang::Expr *SrcArrPtr =
    842       clang::ImplicitCastExpr::Create(C,
    843           C.getPointerType(BaseType->getCanonicalTypeInternal()),
    844           clang::CK_ArrayToPointerDecay,
    845           SrcArr,
    846           nullptr,
    847           clang::VK_RValue);
    848 
    849   clang::Expr *SrcArrPtrSubscript =
    850       new(C) clang::ArraySubscriptExpr(SrcArrPtr,
    851                                        RefrsIntIter,
    852                                        BaseType->getCanonicalTypeInternal(),
    853                                        clang::VK_RValue,
    854                                        clang::OK_Ordinary,
    855                                        Loc);
    856 
    857   DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
    858 
    859   clang::Stmt *RSSetObjectCall = nullptr;
    860   if (BaseType->isArrayType()) {
    861     RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
    862                                              SrcArrPtrSubscript,
    863                                              StartLoc, Loc);
    864   } else if (DT == DataTypeUnknown) {
    865     RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
    866                                               SrcArrPtrSubscript,
    867                                               StartLoc, Loc);
    868   } else {
    869     RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
    870                                               SrcArrPtrSubscript,
    871                                               StartLoc, Loc);
    872   }
    873 
    874   clang::ForStmt *DestructorLoop =
    875       new(C) clang::ForStmt(C,
    876                             Init,
    877                             Cond,
    878                             nullptr,  // no condVar
    879                             Inc,
    880                             RSSetObjectCall,
    881                             Loc,
    882                             Loc,
    883                             Loc);
    884 
    885   StmtArray[StmtCtr++] = DestructorLoop;
    886   slangAssert(StmtCtr == 2);
    887 
    888   clang::CompoundStmt *CS =
    889       new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
    890 
    891   return CS;
    892 } */
    893 
    894 clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
    895                                      clang::Expr *LHS,
    896                                      clang::Expr *RHS,
    897                                      clang::SourceLocation StartLoc,
    898                                      clang::SourceLocation Loc) {
    899   clang::QualType QT = LHS->getType();
    900   const clang::Type *T = QT.getTypePtr();
    901   slangAssert(T->isStructureType());
    902   slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
    903 
    904   // Keep an extra slot for the original copy (memcpy)
    905   unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
    906 
    907   unsigned StmtCount = 0;
    908   clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
    909   for (unsigned i = 0; i < FieldsToSet; i++) {
    910     StmtArray[i] = nullptr;
    911   }
    912 
    913   clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
    914   RD = RD->getDefinition();
    915   for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    916          FE = RD->field_end();
    917        FI != FE;
    918        FI++) {
    919     bool IsArrayType = false;
    920     clang::FieldDecl *FD = *FI;
    921     const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    922     const clang::Type *OrigType = FT;
    923 
    924     if (!CountRSObjectTypes(FT)) {
    925       // Skip to next if we don't have any viable RS object types
    926       continue;
    927     }
    928 
    929     clang::DeclAccessPair FoundDecl =
    930         clang::DeclAccessPair::make(FD, clang::AS_none);
    931     clang::MemberExpr *DstMember =
    932         clang::MemberExpr::Create(C,
    933                                   LHS,
    934                                   false,
    935                                   clang::SourceLocation(),
    936                                   clang::NestedNameSpecifierLoc(),
    937                                   clang::SourceLocation(),
    938                                   FD,
    939                                   FoundDecl,
    940                                   clang::DeclarationNameInfo(
    941                                       FD->getDeclName(),
    942                                       clang::SourceLocation()),
    943                                   nullptr,
    944                                   OrigType->getCanonicalTypeInternal(),
    945                                   clang::VK_RValue,
    946                                   clang::OK_Ordinary);
    947 
    948     clang::MemberExpr *SrcMember =
    949         clang::MemberExpr::Create(C,
    950                                   RHS,
    951                                   false,
    952                                   clang::SourceLocation(),
    953                                   clang::NestedNameSpecifierLoc(),
    954                                   clang::SourceLocation(),
    955                                   FD,
    956                                   FoundDecl,
    957                                   clang::DeclarationNameInfo(
    958                                       FD->getDeclName(),
    959                                       clang::SourceLocation()),
    960                                   nullptr,
    961                                   OrigType->getCanonicalTypeInternal(),
    962                                   clang::VK_RValue,
    963                                   clang::OK_Ordinary);
    964 
    965     if (FT->isArrayType()) {
    966       FT = FT->getArrayElementTypeNoTypeQual();
    967       IsArrayType = true;
    968     }
    969 
    970     DataType DT = RSExportPrimitiveType::GetRSSpecificType(FT);
    971 
    972     if (IsArrayType) {
    973       clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
    974       DiagEngine.Report(
    975         clang::FullSourceLoc(Loc, C.getSourceManager()),
    976         DiagEngine.getCustomDiagID(
    977           clang::DiagnosticsEngine::Error,
    978           "Arrays of RS object types within structures cannot be copied"));
    979       // TODO(srhines): Support setting arrays of RS objects
    980       // StmtArray[StmtCount++] =
    981       //    CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
    982     } else if (DT == DataTypeUnknown) {
    983       StmtArray[StmtCount++] =
    984           CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
    985     } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
    986       StmtArray[StmtCount++] =
    987           CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
    988     } else {
    989       slangAssert(false);
    990     }
    991   }
    992 
    993   slangAssert(StmtCount < FieldsToSet);
    994 
    995   // We still need to actually do the overall struct copy. For simplicity,
    996   // we just do a straight-up assignment (which will still preserve all
    997   // the proper RS object reference counts).
    998   clang::BinaryOperator *CopyStruct =
    999       new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
   1000                                    clang::VK_RValue, clang::OK_Ordinary, Loc,
   1001                                    false);
   1002   StmtArray[StmtCount++] = CopyStruct;
   1003 
   1004   clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
   1005       C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
   1006 
   1007   delete [] StmtArray;
   1008 
   1009   return CS;
   1010 }
   1011 
   1012 }  // namespace
   1013 
   1014 void RSObjectRefCount::Scope::InsertStmt(const clang::ASTContext &C,
   1015                                          clang::Stmt *NewStmt) {
   1016   std::vector<clang::Stmt*> newBody;
   1017   for (clang::Stmt* S1 : mCS->body()) {
   1018     if (S1 == mCurrent) {
   1019       newBody.push_back(NewStmt);
   1020     }
   1021     newBody.push_back(S1);
   1022   }
   1023   mCS->setStmts(C, newBody);
   1024 }
   1025 
   1026 void RSObjectRefCount::Scope::ReplaceStmt(const clang::ASTContext &C,
   1027                                           clang::Stmt *NewStmt) {
   1028   std::vector<clang::Stmt*> newBody;
   1029   for (clang::Stmt* S1 : mCS->body()) {
   1030     if (S1 == mCurrent) {
   1031       newBody.push_back(NewStmt);
   1032     } else {
   1033       newBody.push_back(S1);
   1034     }
   1035   }
   1036   mCS->setStmts(C, newBody);
   1037 }
   1038 
   1039 void RSObjectRefCount::Scope::ReplaceExpr(const clang::ASTContext& C,
   1040                                           clang::Expr* OldExpr,
   1041                                           clang::Expr* NewExpr) {
   1042   RSASTReplace R(C);
   1043   R.ReplaceStmt(mCurrent, OldExpr, NewExpr);
   1044 }
   1045 
   1046 void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
   1047     clang::BinaryOperator *AS) {
   1048 
   1049   clang::QualType QT = AS->getType();
   1050 
   1051   clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
   1052       DataTypeRSAllocation)->getASTContext();
   1053 
   1054   clang::SourceLocation Loc = AS->getExprLoc();
   1055   clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
   1056   clang::Stmt *UpdatedStmt = nullptr;
   1057 
   1058   if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
   1059     // By definition, this is a struct assignment if we get here
   1060     UpdatedStmt =
   1061         CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
   1062   } else {
   1063     UpdatedStmt =
   1064         CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
   1065   }
   1066 
   1067   RSASTReplace R(C);
   1068   R.ReplaceStmt(mCS, AS, UpdatedStmt);
   1069 }
   1070 
   1071 void RSObjectRefCount::Scope::AppendRSObjectInit(
   1072     clang::VarDecl *VD,
   1073     clang::DeclStmt *DS,
   1074     DataType DT,
   1075     clang::Expr *InitExpr) {
   1076   slangAssert(VD);
   1077 
   1078   if (!InitExpr) {
   1079     return;
   1080   }
   1081 
   1082   clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
   1083       DataTypeRSAllocation)->getASTContext();
   1084   clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
   1085       DataTypeRSAllocation)->getLocation();
   1086   clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
   1087       DataTypeRSAllocation)->getInnerLocStart();
   1088 
   1089   if (DT == DataTypeIsStruct) {
   1090     const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1091     clang::DeclRefExpr *RefRSVar =
   1092         clang::DeclRefExpr::Create(C,
   1093                                    clang::NestedNameSpecifierLoc(),
   1094                                    clang::SourceLocation(),
   1095                                    VD,
   1096                                    false,
   1097                                    Loc,
   1098                                    T->getCanonicalTypeInternal(),
   1099                                    clang::VK_RValue,
   1100                                    nullptr);
   1101 
   1102     clang::Stmt *RSSetObjectOps =
   1103         CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
   1104     // Fix for b/37363420; consider:
   1105     //
   1106     // struct foo { rs_matrix m; };
   1107     // void bar() {
   1108     //   struct foo M = {...};
   1109     // }
   1110     //
   1111     // slang modifies that declaration with initialization to a
   1112     // declaration plus an assignment of the initialization values.
   1113     //
   1114     // void bar() {
   1115     //   struct foo M = {};
   1116     //   M = {...}; // by CreateStructRSSetObject() above
   1117     // }
   1118     //
   1119     // the slang-generated statement (M = {...}) is a use of M, and we
   1120     // need to mark M (clang::VarDecl *VD) as used.
   1121     VD->markUsed(C);
   1122 
   1123     std::list<clang::Stmt*> StmtList;
   1124     StmtList.push_back(RSSetObjectOps);
   1125     AppendAfterStmt(C, mCS, DS, StmtList);
   1126     return;
   1127   }
   1128 
   1129   clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
   1130   slangAssert((SetObjectFD != nullptr) &&
   1131               "rsSetObject doesn't cover all RS object types");
   1132 
   1133   clang::QualType SetObjectFDType = SetObjectFD->getType();
   1134   clang::QualType SetObjectFDArgType[2];
   1135   SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
   1136   SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
   1137 
   1138   clang::Expr *RefRSSetObjectFD =
   1139       clang::DeclRefExpr::Create(C,
   1140                                  clang::NestedNameSpecifierLoc(),
   1141                                  clang::SourceLocation(),
   1142                                  SetObjectFD,
   1143                                  false,
   1144                                  Loc,
   1145                                  SetObjectFDType,
   1146                                  clang::VK_RValue,
   1147                                  nullptr);
   1148 
   1149   clang::Expr *RSSetObjectFP =
   1150       clang::ImplicitCastExpr::Create(C,
   1151                                       C.getPointerType(SetObjectFDType),
   1152                                       clang::CK_FunctionToPointerDecay,
   1153                                       RefRSSetObjectFD,
   1154                                       nullptr,
   1155                                       clang::VK_RValue);
   1156 
   1157   const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1158   clang::DeclRefExpr *RefRSVar =
   1159       clang::DeclRefExpr::Create(C,
   1160                                  clang::NestedNameSpecifierLoc(),
   1161                                  clang::SourceLocation(),
   1162                                  VD,
   1163                                  false,
   1164                                  Loc,
   1165                                  T->getCanonicalTypeInternal(),
   1166                                  clang::VK_RValue,
   1167                                  nullptr);
   1168 
   1169   llvm::SmallVector<clang::Expr*, 2> ArgList;
   1170   ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
   1171                                                 clang::UO_AddrOf,
   1172                                                 SetObjectFDArgType[0],
   1173                                                 clang::VK_RValue,
   1174                                                 clang::OK_Ordinary,
   1175                                                 Loc));
   1176   ArgList.push_back(InitExpr);
   1177 
   1178   clang::CallExpr *RSSetObjectCall =
   1179       new(C) clang::CallExpr(C,
   1180                              RSSetObjectFP,
   1181                              ArgList,
   1182                              SetObjectFD->getCallResultType(),
   1183                              clang::VK_RValue,
   1184                              Loc);
   1185 
   1186   std::list<clang::Stmt*> StmtList;
   1187   StmtList.push_back(RSSetObjectCall);
   1188   AppendAfterStmt(C, mCS, DS, StmtList);
   1189 }
   1190 
   1191 void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
   1192   if (mRSO.empty()) {
   1193     return;
   1194   }
   1195 
   1196   clang::DeclContext* DC = mRSO.front()->getDeclContext();
   1197   clang::ASTContext& C = DC->getParentASTContext();
   1198   clang::SourceManager& SM = C.getSourceManager();
   1199 
   1200   const auto& OccursBefore = [&SM] (clang::SourceLocation L1, clang::SourceLocation L2)->bool {
   1201     return SM.isBeforeInTranslationUnit(L1, L2);
   1202   };
   1203   typedef std::map<clang::SourceLocation, clang::Stmt*, decltype(OccursBefore)> DMap;
   1204 
   1205   DMap dtors(OccursBefore);
   1206 
   1207   // Create rsClearObject calls. Note the DMap entries are sorted by the SourceLocation.
   1208   for (clang::VarDecl* VD : mRSO) {
   1209     clang::SourceLocation Loc = VD->getSourceRange().getBegin();
   1210     clang::Stmt* RSClearObjectCall = ClearRSObject(VD, DC);
   1211     dtors.insert(std::make_pair(Loc, RSClearObjectCall));
   1212   }
   1213 
   1214   DestructorVisitor Visitor;
   1215   Visitor.Visit(mCS);
   1216 
   1217   // Replace each exiting statement with a block that contains the original statement
   1218   // and added rsClearObject() calls before it.
   1219   for (clang::Stmt* S : Visitor.getExitingStmts()) {
   1220 
   1221     const clang::SourceLocation currentLoc = S->getLocStart();
   1222 
   1223     DMap::iterator firstDtorIter = dtors.begin();
   1224     DMap::iterator currentDtorIter = firstDtorIter;
   1225     DMap::iterator lastDtorIter = dtors.end();
   1226 
   1227     while (currentDtorIter != lastDtorIter &&
   1228            OccursBefore(currentDtorIter->first, currentLoc)) {
   1229       currentDtorIter++;
   1230     }
   1231 
   1232     if (currentDtorIter == firstDtorIter) {
   1233       continue;
   1234     }
   1235 
   1236     std::vector<clang::Stmt*> Stmts;
   1237 
   1238     // Insert rsClearObject() calls for all rsObjects declared before the current statement
   1239     for(DMap::iterator it = firstDtorIter; it != currentDtorIter; it++) {
   1240       Stmts.push_back(it->second);
   1241     }
   1242     Stmts.push_back(S);
   1243 
   1244     RSASTReplace R(C);
   1245     clang::CompoundStmt* CS = BuildCompoundStmt(C, Stmts, S->getLocEnd());
   1246     R.ReplaceStmt(mCS, S, CS);
   1247   }
   1248 
   1249   std::list<clang::Stmt*> Stmts;
   1250   for(auto LocCallPair : dtors) {
   1251     Stmts.push_back(LocCallPair.second);
   1252   }
   1253   AppendAfterStmt(C, mCS, nullptr, Stmts);
   1254 }
   1255 
   1256 clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
   1257     clang::VarDecl *VD,
   1258     clang::DeclContext *DC) {
   1259   slangAssert(VD);
   1260   clang::ASTContext &C = VD->getASTContext();
   1261   clang::SourceLocation Loc = VD->getLocation();
   1262   clang::SourceLocation StartLoc = VD->getInnerLocStart();
   1263   const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1264 
   1265   // Reference expr to target RS object variable
   1266   clang::DeclRefExpr *RefRSVar =
   1267       clang::DeclRefExpr::Create(C,
   1268                                  clang::NestedNameSpecifierLoc(),
   1269                                  clang::SourceLocation(),
   1270                                  VD,
   1271                                  false,
   1272                                  Loc,
   1273                                  T->getCanonicalTypeInternal(),
   1274                                  clang::VK_RValue,
   1275                                  nullptr);
   1276 
   1277   if (T->isArrayType()) {
   1278     return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
   1279   }
   1280 
   1281   DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
   1282 
   1283   if (DT == DataTypeUnknown ||
   1284       DT == DataTypeIsStruct) {
   1285     return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
   1286   }
   1287 
   1288   slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
   1289               "Should be RS object");
   1290 
   1291   return ClearSingleRSObject(C, RefRSVar, Loc);
   1292 }
   1293 
   1294 bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
   1295                                           DataType *DT,
   1296                                           clang::Expr **InitExpr) {
   1297   slangAssert(VD && DT && InitExpr);
   1298   const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1299 
   1300   // Loop through array types to get to base type
   1301   while (T && T->isArrayType()) {
   1302     T = T->getArrayElementTypeNoTypeQual();
   1303   }
   1304 
   1305   bool DataTypeIsStructWithRSObject = false;
   1306   *DT = RSExportPrimitiveType::GetRSSpecificType(T);
   1307 
   1308   if (*DT == DataTypeUnknown) {
   1309     if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
   1310       *DT = DataTypeIsStruct;
   1311       DataTypeIsStructWithRSObject = true;
   1312     } else {
   1313       return false;
   1314     }
   1315   }
   1316 
   1317   bool DataTypeIsRSObject = false;
   1318   if (DataTypeIsStructWithRSObject) {
   1319     DataTypeIsRSObject = true;
   1320   } else {
   1321     DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
   1322   }
   1323   *InitExpr = VD->getInit();
   1324 
   1325   if (!DataTypeIsRSObject && *InitExpr) {
   1326     // If we already have an initializer for a matrix type, we are done.
   1327     return DataTypeIsRSObject;
   1328   }
   1329 
   1330   clang::Expr *ZeroInitializer =
   1331       CreateEmptyInitListExpr(VD->getASTContext(), VD->getLocation());
   1332 
   1333   if (ZeroInitializer) {
   1334     ZeroInitializer->setType(T->getCanonicalTypeInternal());
   1335     VD->setInit(ZeroInitializer);
   1336   }
   1337 
   1338   return DataTypeIsRSObject;
   1339 }
   1340 
   1341 clang::Expr *RSObjectRefCount::CreateEmptyInitListExpr(
   1342     clang::ASTContext &C,
   1343     const clang::SourceLocation &Loc) {
   1344 
   1345   // We can cheaply construct a zero initializer by just creating an empty
   1346   // initializer list. Clang supports this extension to C(99), and will create
   1347   // any necessary constructs to zero out the entire variable.
   1348   llvm::SmallVector<clang::Expr*, 1> EmptyInitList;
   1349   return new(C) clang::InitListExpr(C, Loc, EmptyInitList, Loc);
   1350 }
   1351 
   1352 clang::DeclRefExpr *RSObjectRefCount::CreateGuard(clang::ASTContext &C,
   1353                                                   clang::DeclContext *DC,
   1354                                                   clang::Expr *E,
   1355                                                   const llvm::Twine &VarName,
   1356                                                   std::vector<clang::Stmt*> &NewStmts) {
   1357   clang::SourceLocation Loc = E->getLocStart();
   1358   const clang::QualType Ty = E->getType();
   1359   clang::VarDecl* TmpDecl = clang::VarDecl::Create(
   1360       C,                                     // AST context
   1361       DC,                                    // Decl context
   1362       Loc,                                   // Start location
   1363       Loc,                                   // Id location
   1364       &C.Idents.get(VarName.str()),          // Id
   1365       Ty,                                    // Type
   1366       C.getTrivialTypeSourceInfo(Ty),        // Type info
   1367       clang::SC_None                         // Storage class
   1368   );
   1369   const clang::Type *T = Ty.getTypePtr();
   1370   clang::Expr *ZeroInitializer =
   1371       RSObjectRefCount::CreateEmptyInitListExpr(C, Loc);
   1372   ZeroInitializer->setType(T->getCanonicalTypeInternal());
   1373   TmpDecl->setInit(ZeroInitializer);
   1374   TmpDecl->markUsed(C);
   1375   clang::Decl* Decls[] = { TmpDecl };
   1376   const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
   1377       C, Decls, sizeof(Decls) / sizeof(*Decls));
   1378   clang::DeclStmt* DS = new (C) clang::DeclStmt(DGR, Loc, Loc);
   1379   NewStmts.push_back(DS);
   1380 
   1381   clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
   1382       C,
   1383       clang::NestedNameSpecifierLoc(),       // QualifierLoc
   1384       Loc,                                   // TemplateKWLoc
   1385       TmpDecl,
   1386       false,                                 // RefersToEnclosingVariableOrCapture
   1387       Loc,                                   // NameLoc
   1388       Ty,
   1389       clang::VK_LValue
   1390   );
   1391 
   1392   clang::Stmt *UpdatedStmt = nullptr;
   1393   if (CountRSObjectTypes(Ty.getTypePtr()) == 0) {
   1394     // The expression E is not an RS object itself. Instead of calling
   1395     // rsSetObject(), create an assignment statement to set the value of the
   1396     // temporary "guard" variable to the expression.
   1397     // This can happen if called from RSObjectRefCount::VisitReturnStmt(),
   1398     // when the return expression is not an RS object but references one.
   1399     UpdatedStmt =
   1400       new(C) clang::BinaryOperator(DRE, E, clang::BO_Assign, Ty,
   1401                                    clang::VK_RValue, clang::OK_Ordinary, Loc,
   1402                                    false);
   1403 
   1404   } else if (!RSExportPrimitiveType::IsRSObjectType(Ty.getTypePtr())) {
   1405     // By definition, this is a struct assignment if we get here
   1406     UpdatedStmt =
   1407         CreateStructRSSetObject(C, DRE, E, Loc, Loc);
   1408   } else {
   1409     UpdatedStmt =
   1410         CreateSingleRSSetObject(C, DRE, E, Loc, Loc);
   1411   }
   1412   NewStmts.push_back(UpdatedStmt);
   1413 
   1414   return DRE;
   1415 }
   1416 
   1417 void RSObjectRefCount::CreateParameterGuard(clang::ASTContext &C,
   1418                                             clang::DeclContext *DC,
   1419                                             clang::ParmVarDecl *PD,
   1420                                             std::vector<clang::Stmt*> &NewStmts) {
   1421   clang::SourceLocation Loc = PD->getLocStart();
   1422   clang::DeclRefExpr* ParamDRE = clang::DeclRefExpr::Create(
   1423       C,
   1424       clang::NestedNameSpecifierLoc(),       // QualifierLoc
   1425       Loc,                                   // TemplateKWLoc
   1426       PD,
   1427       false,                                 // RefersToEnclosingVariableOrCapture
   1428       Loc,                                   // NameLoc
   1429       PD->getType(),
   1430       clang::VK_RValue
   1431   );
   1432 
   1433   CreateGuard(C, DC, ParamDRE,
   1434               llvm::Twine(".rs.param.") + llvm::Twine(PD->getName()), NewStmts);
   1435 }
   1436 
   1437 void RSObjectRefCount::HandleParamsAndLocals(clang::FunctionDecl *FD) {
   1438   std::vector<clang::Stmt*> NewStmts;
   1439   std::list<clang::ParmVarDecl*> ObjParams;
   1440   for (clang::ParmVarDecl *Param : FD->parameters()) {
   1441     clang::QualType QT = Param->getType();
   1442     if (CountRSObjectTypes(QT.getTypePtr())) {
   1443       // Ignore non-object types
   1444       RSObjectRefCount::CreateParameterGuard(mCtx, FD, Param, NewStmts);
   1445       ObjParams.push_back(Param);
   1446     }
   1447   }
   1448 
   1449   clang::Stmt *OldBody = FD->getBody();
   1450   if (ObjParams.empty()) {
   1451     Visit(OldBody);
   1452     return;
   1453   }
   1454 
   1455   NewStmts.push_back(OldBody);
   1456 
   1457   clang::SourceLocation Loc = FD->getLocStart();
   1458   clang::CompoundStmt *NewBody = BuildCompoundStmt(mCtx, NewStmts, Loc);
   1459   Scope S(NewBody);
   1460   for (clang::ParmVarDecl *Param : ObjParams) {
   1461     S.addRSObject(Param);
   1462   }
   1463   mScopeStack.push_back(&S);
   1464 
   1465   // To avoid adding unnecessary ref counting artifacts to newly added temporary
   1466   // local variables for parameters, visits only the old function body here.
   1467   Visit(OldBody);
   1468 
   1469   FD->setBody(NewBody);
   1470 
   1471   S.InsertLocalVarDestructors();
   1472   mScopeStack.pop_back();
   1473 }
   1474 
   1475 clang::CompoundStmt* RSObjectRefCount::CreateRetStmtWithTempVar(
   1476     clang::ASTContext& C,
   1477     clang::DeclContext* DC,
   1478     clang::ReturnStmt* RS,
   1479     const unsigned id) {
   1480   std::vector<clang::Stmt*> NewStmts;
   1481   // Since we insert rsClearObj() calls before the return statement, we need
   1482   // to make sure none of the cleared RS objects are referenced in the
   1483   // return statement.
   1484   // For that, we create a new local variable named .rs.retval, assign the
   1485   // original return expression to it, make all necessary rsClearObj()
   1486   // calls, then return .rs.retval. Note rsClearObj() is not called on
   1487   // .rs.retval.
   1488   clang::SourceLocation Loc = RS->getLocStart();
   1489   clang::Expr* RetVal = RS->getRetValue();
   1490   const clang::QualType RetTy = RetVal->getType();
   1491   clang::DeclRefExpr *DRE = CreateGuard(C, DC, RetVal,
   1492                                         llvm::Twine(".rs.retval") + llvm::Twine(id),
   1493                                         NewStmts);
   1494 
   1495   // Creates a new return statement
   1496   clang::ReturnStmt* NewRet = new (C) clang::ReturnStmt(Loc);
   1497   clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
   1498       C,
   1499       RetTy,
   1500       clang::CK_LValueToRValue,
   1501       DRE,
   1502       nullptr,
   1503       clang::VK_RValue
   1504   );
   1505   NewRet->setRetValue(CastExpr);
   1506   NewStmts.push_back(NewRet);
   1507 
   1508   return BuildCompoundStmt(C, NewStmts, Loc);
   1509 }
   1510 
   1511 void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
   1512   VisitStmt(DS);
   1513   getCurrentScope()->setCurrentStmt(DS);
   1514   for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
   1515        I != E;
   1516        I++) {
   1517     clang::Decl *D = *I;
   1518     if (D->getKind() == clang::Decl::Var) {
   1519       clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
   1520       DataType DT = DataTypeUnknown;
   1521       clang::Expr *InitExpr = nullptr;
   1522       if (InitializeRSObject(VD, &DT, &InitExpr)) {
   1523         // We need to zero-init all RS object types (including matrices), ...
   1524         getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
   1525         // ... but, only add to the list of RS objects if we have some
   1526         // non-matrix RS object fields.
   1527         if (CountRSObjectTypes(VD->getType().getTypePtr())) {
   1528           getCurrentScope()->addRSObject(VD);
   1529         }
   1530       }
   1531     }
   1532   }
   1533 }
   1534 
   1535 void RSObjectRefCount::VisitCallExpr(clang::CallExpr* CE) {
   1536   clang::QualType RetTy;
   1537   const clang::FunctionDecl* FD = CE->getDirectCallee();
   1538 
   1539   if (FD) {
   1540     // Direct calls
   1541 
   1542     RetTy = FD->getReturnType();
   1543   } else {
   1544     // Indirect calls through function pointers
   1545 
   1546     const clang::Expr* Callee = CE->getCallee();
   1547     const clang::Type* CalleeType = Callee->getType().getTypePtr();
   1548     const clang::PointerType* PtrType = CalleeType->getAs<clang::PointerType>();
   1549 
   1550     if (!PtrType) {
   1551       return;
   1552     }
   1553 
   1554     const clang::Type* PointeeType = PtrType->getPointeeType().getTypePtr();
   1555     const clang::FunctionType* FuncType = PointeeType->getAs<clang::FunctionType>();
   1556 
   1557     if (!FuncType) {
   1558       return;
   1559     }
   1560 
   1561     RetTy = FuncType->getReturnType();
   1562   }
   1563 
   1564   // The RenderScript runtime API maintains the invariant that the sysRef of a new RS object would
   1565   // be 1, with the exception of rsGetAllocation() (deprecated in API 22), which leaves the sysRef
   1566   // 0 for a new allocation. It is the responsibility of the callee of the API to decrement the
   1567   // sysRef when a reference of the RS object goes out of scope. The compiler generates code to do
   1568   // just that, by creating a temporary variable named ".rs.tmpN" with the result of
   1569   // an RS-object-returning API directly assigned to it, and calling rsClearObject() on .rs.tmpN
   1570   // right before it exits the current scope. Such code generation is skipped for rsGetAllocation()
   1571   // to avoid decrementing its sysRef below zero.
   1572 
   1573   if (CountRSObjectTypes(RetTy.getTypePtr())==0 ||
   1574       (FD && FD->getName() == "rsGetAllocation")) {
   1575     return;
   1576   }
   1577 
   1578   clang::SourceLocation Loc = CE->getSourceRange().getBegin();
   1579   std::stringstream ss;
   1580   ss << ".rs.tmp" << getNextID();
   1581   llvm::StringRef VarName(ss.str());
   1582 
   1583   clang::VarDecl* TempVarDecl = clang::VarDecl::Create(
   1584       mCtx,                                  // AST context
   1585       GetDeclContext(),                      // Decl context
   1586       Loc,                                   // Start location
   1587       Loc,                                   // Id location
   1588       &mCtx.Idents.get(VarName),             // Id
   1589       RetTy,                                 // Type
   1590       mCtx.getTrivialTypeSourceInfo(RetTy),  // Type info
   1591       clang::SC_None                         // Storage class
   1592   );
   1593   TempVarDecl->setInit(CE);
   1594   TempVarDecl->markUsed(mCtx);
   1595   clang::Decl* Decls[] = { TempVarDecl };
   1596   const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
   1597       mCtx, Decls, sizeof(Decls) / sizeof(*Decls));
   1598   clang::DeclStmt* DS = new (mCtx) clang::DeclStmt(DGR, Loc, Loc);
   1599 
   1600   getCurrentScope()->InsertStmt(mCtx, DS);
   1601 
   1602   clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
   1603       mCtx,                                  // AST context
   1604       clang::NestedNameSpecifierLoc(),       // QualifierLoc
   1605       Loc,                                   // TemplateKWLoc
   1606       TempVarDecl,
   1607       false,                                 // RefersToEnclosingVariableOrCapture
   1608       Loc,                                   // NameLoc
   1609       RetTy,
   1610       clang::VK_LValue
   1611   );
   1612   clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
   1613       mCtx,
   1614       RetTy,
   1615       clang::CK_LValueToRValue,
   1616       DRE,
   1617       nullptr,
   1618       clang::VK_RValue
   1619   );
   1620 
   1621   getCurrentScope()->ReplaceExpr(mCtx, CE, CastExpr);
   1622 
   1623   // Register TempVarDecl for destruction call (rsClearObj).
   1624   getCurrentScope()->addRSObject(TempVarDecl);
   1625 }
   1626 
   1627 void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
   1628   if (!emptyScope()) {
   1629     getCurrentScope()->setCurrentStmt(CS);
   1630   }
   1631 
   1632   if (!CS->body_empty()) {
   1633     // Push a new scope
   1634     Scope *S = new Scope(CS);
   1635     mScopeStack.push_back(S);
   1636 
   1637     VisitStmt(CS);
   1638 
   1639     // Destroy the scope
   1640     slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
   1641     S->InsertLocalVarDestructors();
   1642     mScopeStack.pop_back();
   1643     delete S;
   1644   }
   1645 }
   1646 
   1647 void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
   1648   getCurrentScope()->setCurrentStmt(AS);
   1649   clang::QualType QT = AS->getType();
   1650 
   1651   if (CountRSObjectTypes(QT.getTypePtr())) {
   1652     getCurrentScope()->ReplaceRSObjectAssignment(AS);
   1653   }
   1654 }
   1655 
   1656 namespace {
   1657 
   1658 class FindRSObjRefVisitor : public clang::RecursiveASTVisitor<FindRSObjRefVisitor> {
   1659 public:
   1660   explicit FindRSObjRefVisitor() : mRefRSObj(false) {}
   1661   bool VisitExpr(clang::Expr* Expression) {
   1662     if (CountRSObjectTypes(Expression->getType().getTypePtr()) > 0) {
   1663       mRefRSObj = true;
   1664       // Found a reference to an RS object. Stop the AST traversal.
   1665       return false;
   1666     }
   1667     return true;
   1668   }
   1669 
   1670   bool foundRSObjRef() const { return mRefRSObj; }
   1671 
   1672 private:
   1673   bool mRefRSObj;
   1674 };
   1675 
   1676 }  // anonymous namespace
   1677 
   1678 void RSObjectRefCount::VisitReturnStmt(clang::ReturnStmt *RS) {
   1679   getCurrentScope()->setCurrentStmt(RS);
   1680 
   1681   // If there is no local rsObject declared so far, no need to transform the
   1682   // return statement.
   1683 
   1684   bool RSObjDeclared = false;
   1685 
   1686   for (const Scope* S : mScopeStack) {
   1687     if (S->hasRSObject()) {
   1688       RSObjDeclared = true;
   1689       break;
   1690     }
   1691   }
   1692 
   1693   if (!RSObjDeclared) {
   1694     return;
   1695   }
   1696 
   1697   FindRSObjRefVisitor visitor;
   1698 
   1699   visitor.TraverseStmt(RS);
   1700 
   1701   // If the return statement does not return anything, or if it does not reference
   1702   // a rsObject, no need to transform it.
   1703 
   1704   if (!visitor.foundRSObjRef()) {
   1705     return;
   1706   }
   1707 
   1708   // Transform the return statement so that it does not potentially return or
   1709   // reference a rsObject that has been cleared.
   1710 
   1711   clang::CompoundStmt* NewRS;
   1712   NewRS = CreateRetStmtWithTempVar(mCtx, GetDeclContext(), RS, getNextID());
   1713 
   1714   getCurrentScope()->ReplaceStmt(mCtx, NewRS);
   1715 }
   1716 
   1717 void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
   1718   getCurrentScope()->setCurrentStmt(S);
   1719   for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
   1720        I != E;
   1721        I++) {
   1722     if (clang::Stmt *Child = *I) {
   1723       Visit(Child);
   1724     }
   1725   }
   1726 }
   1727 
   1728 // This function walks the list of global variables and (potentially) creates
   1729 // a single global static destructor function that properly decrements
   1730 // reference counts on the contained RS object types.
   1731 clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
   1732   Init();
   1733 
   1734   clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
   1735   clang::SourceLocation loc;
   1736 
   1737   llvm::StringRef SR(".rs.dtor");
   1738   clang::IdentifierInfo &II = mCtx.Idents.get(SR);
   1739   clang::DeclarationName N(&II);
   1740   clang::FunctionProtoType::ExtProtoInfo EPI;
   1741   clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
   1742       llvm::ArrayRef<clang::QualType>(), EPI);
   1743   clang::FunctionDecl *FD = nullptr;
   1744 
   1745   // Generate rsClearObject() call chains for every global variable
   1746   // (whether static or extern).
   1747   std::vector<clang::Stmt *> StmtList;
   1748   for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
   1749           E = DC->decls_end(); I != E; I++) {
   1750     clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
   1751     if (VD) {
   1752       if (CountRSObjectTypes(VD->getType().getTypePtr())) {
   1753         if (!FD) {
   1754           // Only create FD if we are going to use it.
   1755           FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, nullptr,
   1756                                            clang::SC_None);
   1757         }
   1758         // Mark VD as used.  It might be unused, except for the destructor.
   1759         // 'markUsed' has side-effects that are caused only if VD is not already
   1760         // used.  Hence no need for an extra check here.
   1761         VD->markUsed(mCtx);
   1762         // Make sure to create any helpers within the function's DeclContext,
   1763         // not the one associated with the global translation unit.
   1764         clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
   1765         StmtList.push_back(RSClearObjectCall);
   1766       }
   1767     }
   1768   }
   1769 
   1770   // Nothing needs to be destroyed, so don't emit a dtor.
   1771   if (StmtList.empty()) {
   1772     return nullptr;
   1773   }
   1774 
   1775   clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
   1776 
   1777   FD->setBody(CS);
   1778   // We need some way to tell if this FD is generated by slang
   1779   FD->setImplicit();
   1780 
   1781   return FD;
   1782 }
   1783 
   1784 bool HasRSObjectType(const clang::Type *T) {
   1785   return CountRSObjectTypes(T) != 0;
   1786 }
   1787 
   1788 }  // namespace slang
   1789