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     slangAssert(FT);
    590     const clang::Type *OrigType = FT;
    591     while (FT->isArrayType()) {
    592       FT = FT->getArrayElementTypeNoTypeQual();
    593       slangAssert(FT);
    594       IsArrayType = true;
    595     }
    596 
    597     // Pass a DeclarationNameInfo with a valid DeclName, since name equality
    598     // gets asserted during CodeGen.
    599     clang::DeclarationNameInfo FDDeclNameInfo(FD->getDeclName(),
    600                                               FD->getLocation());
    601 
    602     if (RSExportPrimitiveType::IsRSObjectType(FT)) {
    603       clang::DeclAccessPair FoundDecl =
    604           clang::DeclAccessPair::make(FD, clang::AS_none);
    605       clang::MemberExpr *RSObjectMember =
    606           clang::MemberExpr::Create(C,
    607                                     RefRSStruct,
    608                                     false,
    609                                     clang::SourceLocation(),
    610                                     clang::NestedNameSpecifierLoc(),
    611                                     clang::SourceLocation(),
    612                                     FD,
    613                                     FoundDecl,
    614                                     FDDeclNameInfo,
    615                                     nullptr,
    616                                     OrigType->getCanonicalTypeInternal(),
    617                                     clang::VK_RValue,
    618                                     clang::OK_Ordinary);
    619 
    620       slangAssert(StmtCount < FieldsToDestroy);
    621 
    622       if (IsArrayType) {
    623         StmtArray[StmtCount++] = ClearArrayRSObject(C,
    624                                                     DC,
    625                                                     RSObjectMember,
    626                                                     StartLoc,
    627                                                     Loc);
    628       } else {
    629         StmtArray[StmtCount++] = ClearSingleRSObject(C,
    630                                                      RSObjectMember,
    631                                                      Loc);
    632       }
    633     } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
    634       // In this case, we have a nested struct. We may not end up filling all
    635       // of the spaces in StmtArray (sub-structs should handle themselves
    636       // with separate compound statements).
    637       clang::DeclAccessPair FoundDecl =
    638           clang::DeclAccessPair::make(FD, clang::AS_none);
    639       clang::MemberExpr *RSObjectMember =
    640           clang::MemberExpr::Create(C,
    641                                     RefRSStruct,
    642                                     false,
    643                                     clang::SourceLocation(),
    644                                     clang::NestedNameSpecifierLoc(),
    645                                     clang::SourceLocation(),
    646                                     FD,
    647                                     FoundDecl,
    648                                     clang::DeclarationNameInfo(),
    649                                     nullptr,
    650                                     OrigType->getCanonicalTypeInternal(),
    651                                     clang::VK_RValue,
    652                                     clang::OK_Ordinary);
    653 
    654       if (IsArrayType) {
    655         StmtArray[StmtCount++] = ClearArrayRSObject(C,
    656                                                     DC,
    657                                                     RSObjectMember,
    658                                                     StartLoc,
    659                                                     Loc);
    660       } else {
    661         StmtArray[StmtCount++] = ClearStructRSObject(C,
    662                                                      DC,
    663                                                      RSObjectMember,
    664                                                      StartLoc,
    665                                                      Loc);
    666       }
    667     }
    668   }
    669 
    670   slangAssert(StmtCount > 0);
    671   clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
    672       C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
    673 
    674   delete [] StmtArray;
    675 
    676   return CS;
    677 }
    678 
    679 clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
    680                                      clang::Expr *DstExpr,
    681                                      clang::Expr *SrcExpr,
    682                                      clang::SourceLocation StartLoc,
    683                                      clang::SourceLocation Loc) {
    684   const clang::Type *T = DstExpr->getType().getTypePtr();
    685   clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
    686   slangAssert((SetObjectFD != nullptr) &&
    687               "rsSetObject doesn't cover all RS object types");
    688 
    689   clang::QualType SetObjectFDType = SetObjectFD->getType();
    690   clang::QualType SetObjectFDArgType[2];
    691   SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
    692   SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
    693 
    694   clang::Expr *RefRSSetObjectFD =
    695       clang::DeclRefExpr::Create(C,
    696                                  clang::NestedNameSpecifierLoc(),
    697                                  clang::SourceLocation(),
    698                                  SetObjectFD,
    699                                  false,
    700                                  Loc,
    701                                  SetObjectFDType,
    702                                  clang::VK_RValue,
    703                                  nullptr);
    704 
    705   clang::Expr *RSSetObjectFP =
    706       clang::ImplicitCastExpr::Create(C,
    707                                       C.getPointerType(SetObjectFDType),
    708                                       clang::CK_FunctionToPointerDecay,
    709                                       RefRSSetObjectFD,
    710                                       nullptr,
    711                                       clang::VK_RValue);
    712 
    713   llvm::SmallVector<clang::Expr*, 2> ArgList;
    714   ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
    715                                                 clang::UO_AddrOf,
    716                                                 SetObjectFDArgType[0],
    717                                                 clang::VK_RValue,
    718                                                 clang::OK_Ordinary,
    719                                                 Loc));
    720   ArgList.push_back(SrcExpr);
    721 
    722   clang::CallExpr *RSSetObjectCall =
    723       new(C) clang::CallExpr(C,
    724                              RSSetObjectFP,
    725                              ArgList,
    726                              SetObjectFD->getCallResultType(),
    727                              clang::VK_RValue,
    728                              Loc);
    729 
    730   return RSSetObjectCall;
    731 }
    732 
    733 clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
    734                                      clang::Expr *LHS,
    735                                      clang::Expr *RHS,
    736                                      clang::SourceLocation StartLoc,
    737                                      clang::SourceLocation Loc);
    738 
    739 /*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
    740                                            clang::Expr *DstArr,
    741                                            clang::Expr *SrcArr,
    742                                            clang::SourceLocation StartLoc,
    743                                            clang::SourceLocation Loc) {
    744   clang::DeclContext *DC = nullptr;
    745   const clang::Type *BaseType = DstArr->getType().getTypePtr();
    746   slangAssert(BaseType->isArrayType());
    747 
    748   int NumArrayElements = ArrayDim(BaseType);
    749   // Actually extract out the base RS object type for use later
    750   BaseType = BaseType->getArrayElementTypeNoTypeQual();
    751 
    752   clang::Stmt *StmtArray[2] = {nullptr};
    753   int StmtCtr = 0;
    754 
    755   if (NumArrayElements <= 0) {
    756     return nullptr;
    757   }
    758 
    759   // Create helper variable for iterating through elements
    760   clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
    761   clang::VarDecl *IIVD =
    762       clang::VarDecl::Create(C,
    763                              DC,
    764                              StartLoc,
    765                              Loc,
    766                              &II,
    767                              C.IntTy,
    768                              C.getTrivialTypeSourceInfo(C.IntTy),
    769                              clang::SC_None,
    770                              clang::SC_None);
    771   clang::Decl *IID = (clang::Decl *)IIVD;
    772 
    773   clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
    774   StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
    775 
    776   // Form the actual loop
    777   // for (Init; Cond; Inc)
    778   //   RSSetObjectCall;
    779 
    780   // Init -> "rsIntIter = 0"
    781   clang::DeclRefExpr *RefrsIntIter =
    782       clang::DeclRefExpr::Create(C,
    783                                  clang::NestedNameSpecifierLoc(),
    784                                  IIVD,
    785                                  Loc,
    786                                  C.IntTy,
    787                                  clang::VK_RValue,
    788                                  nullptr);
    789 
    790   clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
    791       llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
    792 
    793   clang::BinaryOperator *Init =
    794       new(C) clang::BinaryOperator(RefrsIntIter,
    795                                    Int0,
    796                                    clang::BO_Assign,
    797                                    C.IntTy,
    798                                    clang::VK_RValue,
    799                                    clang::OK_Ordinary,
    800                                    Loc);
    801 
    802   // Cond -> "rsIntIter < NumArrayElements"
    803   clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
    804       llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
    805 
    806   clang::BinaryOperator *Cond =
    807       new(C) clang::BinaryOperator(RefrsIntIter,
    808                                    NumArrayElementsExpr,
    809                                    clang::BO_LT,
    810                                    C.IntTy,
    811                                    clang::VK_RValue,
    812                                    clang::OK_Ordinary,
    813                                    Loc);
    814 
    815   // Inc -> "rsIntIter++"
    816   clang::UnaryOperator *Inc =
    817       new(C) clang::UnaryOperator(RefrsIntIter,
    818                                   clang::UO_PostInc,
    819                                   C.IntTy,
    820                                   clang::VK_RValue,
    821                                   clang::OK_Ordinary,
    822                                   Loc);
    823 
    824   // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
    825   // Loop operates on individual array elements
    826 
    827   clang::Expr *DstArrPtr =
    828       clang::ImplicitCastExpr::Create(C,
    829           C.getPointerType(BaseType->getCanonicalTypeInternal()),
    830           clang::CK_ArrayToPointerDecay,
    831           DstArr,
    832           nullptr,
    833           clang::VK_RValue);
    834 
    835   clang::Expr *DstArrPtrSubscript =
    836       new(C) clang::ArraySubscriptExpr(DstArrPtr,
    837                                        RefrsIntIter,
    838                                        BaseType->getCanonicalTypeInternal(),
    839                                        clang::VK_RValue,
    840                                        clang::OK_Ordinary,
    841                                        Loc);
    842 
    843   clang::Expr *SrcArrPtr =
    844       clang::ImplicitCastExpr::Create(C,
    845           C.getPointerType(BaseType->getCanonicalTypeInternal()),
    846           clang::CK_ArrayToPointerDecay,
    847           SrcArr,
    848           nullptr,
    849           clang::VK_RValue);
    850 
    851   clang::Expr *SrcArrPtrSubscript =
    852       new(C) clang::ArraySubscriptExpr(SrcArrPtr,
    853                                        RefrsIntIter,
    854                                        BaseType->getCanonicalTypeInternal(),
    855                                        clang::VK_RValue,
    856                                        clang::OK_Ordinary,
    857                                        Loc);
    858 
    859   DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
    860 
    861   clang::Stmt *RSSetObjectCall = nullptr;
    862   if (BaseType->isArrayType()) {
    863     RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
    864                                              SrcArrPtrSubscript,
    865                                              StartLoc, Loc);
    866   } else if (DT == DataTypeUnknown) {
    867     RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
    868                                               SrcArrPtrSubscript,
    869                                               StartLoc, Loc);
    870   } else {
    871     RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
    872                                               SrcArrPtrSubscript,
    873                                               StartLoc, Loc);
    874   }
    875 
    876   clang::ForStmt *DestructorLoop =
    877       new(C) clang::ForStmt(C,
    878                             Init,
    879                             Cond,
    880                             nullptr,  // no condVar
    881                             Inc,
    882                             RSSetObjectCall,
    883                             Loc,
    884                             Loc,
    885                             Loc);
    886 
    887   StmtArray[StmtCtr++] = DestructorLoop;
    888   slangAssert(StmtCtr == 2);
    889 
    890   clang::CompoundStmt *CS =
    891       new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
    892 
    893   return CS;
    894 } */
    895 
    896 clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
    897                                      clang::Expr *LHS,
    898                                      clang::Expr *RHS,
    899                                      clang::SourceLocation StartLoc,
    900                                      clang::SourceLocation Loc) {
    901   clang::QualType QT = LHS->getType();
    902   const clang::Type *T = QT.getTypePtr();
    903   slangAssert(T->isStructureType());
    904   slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
    905 
    906   // Keep an extra slot for the original copy (memcpy)
    907   unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
    908 
    909   unsigned StmtCount = 0;
    910   clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
    911   for (unsigned i = 0; i < FieldsToSet; i++) {
    912     StmtArray[i] = nullptr;
    913   }
    914 
    915   clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
    916   RD = RD->getDefinition();
    917   for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    918          FE = RD->field_end();
    919        FI != FE;
    920        FI++) {
    921     bool IsArrayType = false;
    922     clang::FieldDecl *FD = *FI;
    923     const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    924     const clang::Type *OrigType = FT;
    925 
    926     if (!CountRSObjectTypes(FT)) {
    927       // Skip to next if we don't have any viable RS object types
    928       continue;
    929     }
    930 
    931     clang::DeclAccessPair FoundDecl =
    932         clang::DeclAccessPair::make(FD, clang::AS_none);
    933     clang::MemberExpr *DstMember =
    934         clang::MemberExpr::Create(C,
    935                                   LHS,
    936                                   false,
    937                                   clang::SourceLocation(),
    938                                   clang::NestedNameSpecifierLoc(),
    939                                   clang::SourceLocation(),
    940                                   FD,
    941                                   FoundDecl,
    942                                   clang::DeclarationNameInfo(
    943                                       FD->getDeclName(),
    944                                       clang::SourceLocation()),
    945                                   nullptr,
    946                                   OrigType->getCanonicalTypeInternal(),
    947                                   clang::VK_RValue,
    948                                   clang::OK_Ordinary);
    949 
    950     clang::MemberExpr *SrcMember =
    951         clang::MemberExpr::Create(C,
    952                                   RHS,
    953                                   false,
    954                                   clang::SourceLocation(),
    955                                   clang::NestedNameSpecifierLoc(),
    956                                   clang::SourceLocation(),
    957                                   FD,
    958                                   FoundDecl,
    959                                   clang::DeclarationNameInfo(
    960                                       FD->getDeclName(),
    961                                       clang::SourceLocation()),
    962                                   nullptr,
    963                                   OrigType->getCanonicalTypeInternal(),
    964                                   clang::VK_RValue,
    965                                   clang::OK_Ordinary);
    966 
    967     if (FT->isArrayType()) {
    968       FT = FT->getArrayElementTypeNoTypeQual();
    969       IsArrayType = true;
    970     }
    971 
    972     DataType DT = RSExportPrimitiveType::GetRSSpecificType(FT);
    973 
    974     if (IsArrayType) {
    975       clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
    976       DiagEngine.Report(
    977         clang::FullSourceLoc(Loc, C.getSourceManager()),
    978         DiagEngine.getCustomDiagID(
    979           clang::DiagnosticsEngine::Error,
    980           "Arrays of RS object types within structures cannot be copied"));
    981       // TODO(srhines): Support setting arrays of RS objects
    982       // StmtArray[StmtCount++] =
    983       //    CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
    984     } else if (DT == DataTypeUnknown) {
    985       StmtArray[StmtCount++] =
    986           CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
    987     } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
    988       StmtArray[StmtCount++] =
    989           CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
    990     } else {
    991       slangAssert(false);
    992     }
    993   }
    994 
    995   slangAssert(StmtCount < FieldsToSet);
    996 
    997   // We still need to actually do the overall struct copy. For simplicity,
    998   // we just do a straight-up assignment (which will still preserve all
    999   // the proper RS object reference counts).
   1000   clang::BinaryOperator *CopyStruct =
   1001       new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
   1002                                    clang::VK_RValue, clang::OK_Ordinary, Loc,
   1003                                    false);
   1004   StmtArray[StmtCount++] = CopyStruct;
   1005 
   1006   clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
   1007       C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
   1008 
   1009   delete [] StmtArray;
   1010 
   1011   return CS;
   1012 }
   1013 
   1014 }  // namespace
   1015 
   1016 void RSObjectRefCount::Scope::InsertStmt(const clang::ASTContext &C,
   1017                                          clang::Stmt *NewStmt) {
   1018   std::vector<clang::Stmt*> newBody;
   1019   for (clang::Stmt* S1 : mCS->body()) {
   1020     if (S1 == mCurrent) {
   1021       newBody.push_back(NewStmt);
   1022     }
   1023     newBody.push_back(S1);
   1024   }
   1025   mCS->setStmts(C, newBody);
   1026 }
   1027 
   1028 void RSObjectRefCount::Scope::ReplaceStmt(const clang::ASTContext &C,
   1029                                           clang::Stmt *NewStmt) {
   1030   std::vector<clang::Stmt*> newBody;
   1031   for (clang::Stmt* S1 : mCS->body()) {
   1032     if (S1 == mCurrent) {
   1033       newBody.push_back(NewStmt);
   1034     } else {
   1035       newBody.push_back(S1);
   1036     }
   1037   }
   1038   mCS->setStmts(C, newBody);
   1039 }
   1040 
   1041 void RSObjectRefCount::Scope::ReplaceExpr(const clang::ASTContext& C,
   1042                                           clang::Expr* OldExpr,
   1043                                           clang::Expr* NewExpr) {
   1044   RSASTReplace R(C);
   1045   R.ReplaceStmt(mCurrent, OldExpr, NewExpr);
   1046 }
   1047 
   1048 void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
   1049     clang::BinaryOperator *AS) {
   1050 
   1051   clang::QualType QT = AS->getType();
   1052 
   1053   clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
   1054       DataTypeRSAllocation)->getASTContext();
   1055 
   1056   clang::SourceLocation Loc = AS->getExprLoc();
   1057   clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
   1058   clang::Stmt *UpdatedStmt = nullptr;
   1059 
   1060   if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
   1061     // By definition, this is a struct assignment if we get here
   1062     UpdatedStmt =
   1063         CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
   1064   } else {
   1065     UpdatedStmt =
   1066         CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
   1067   }
   1068 
   1069   RSASTReplace R(C);
   1070   R.ReplaceStmt(mCS, AS, UpdatedStmt);
   1071 }
   1072 
   1073 void RSObjectRefCount::Scope::AppendRSObjectInit(
   1074     clang::VarDecl *VD,
   1075     clang::DeclStmt *DS,
   1076     DataType DT,
   1077     clang::Expr *InitExpr) {
   1078   slangAssert(VD);
   1079 
   1080   if (!InitExpr) {
   1081     return;
   1082   }
   1083 
   1084   clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
   1085       DataTypeRSAllocation)->getASTContext();
   1086   clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
   1087       DataTypeRSAllocation)->getLocation();
   1088   clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
   1089       DataTypeRSAllocation)->getInnerLocStart();
   1090 
   1091   if (DT == DataTypeIsStruct) {
   1092     const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1093     clang::DeclRefExpr *RefRSVar =
   1094         clang::DeclRefExpr::Create(C,
   1095                                    clang::NestedNameSpecifierLoc(),
   1096                                    clang::SourceLocation(),
   1097                                    VD,
   1098                                    false,
   1099                                    Loc,
   1100                                    T->getCanonicalTypeInternal(),
   1101                                    clang::VK_RValue,
   1102                                    nullptr);
   1103 
   1104     clang::Stmt *RSSetObjectOps =
   1105         CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
   1106     // Fix for b/37363420; consider:
   1107     //
   1108     // struct foo { rs_matrix m; };
   1109     // void bar() {
   1110     //   struct foo M = {...};
   1111     // }
   1112     //
   1113     // slang modifies that declaration with initialization to a
   1114     // declaration plus an assignment of the initialization values.
   1115     //
   1116     // void bar() {
   1117     //   struct foo M = {};
   1118     //   M = {...}; // by CreateStructRSSetObject() above
   1119     // }
   1120     //
   1121     // the slang-generated statement (M = {...}) is a use of M, and we
   1122     // need to mark M (clang::VarDecl *VD) as used.
   1123     VD->markUsed(C);
   1124 
   1125     std::list<clang::Stmt*> StmtList;
   1126     StmtList.push_back(RSSetObjectOps);
   1127     AppendAfterStmt(C, mCS, DS, StmtList);
   1128     return;
   1129   }
   1130 
   1131   clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
   1132   slangAssert((SetObjectFD != nullptr) &&
   1133               "rsSetObject doesn't cover all RS object types");
   1134 
   1135   clang::QualType SetObjectFDType = SetObjectFD->getType();
   1136   clang::QualType SetObjectFDArgType[2];
   1137   SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
   1138   SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
   1139 
   1140   clang::Expr *RefRSSetObjectFD =
   1141       clang::DeclRefExpr::Create(C,
   1142                                  clang::NestedNameSpecifierLoc(),
   1143                                  clang::SourceLocation(),
   1144                                  SetObjectFD,
   1145                                  false,
   1146                                  Loc,
   1147                                  SetObjectFDType,
   1148                                  clang::VK_RValue,
   1149                                  nullptr);
   1150 
   1151   clang::Expr *RSSetObjectFP =
   1152       clang::ImplicitCastExpr::Create(C,
   1153                                       C.getPointerType(SetObjectFDType),
   1154                                       clang::CK_FunctionToPointerDecay,
   1155                                       RefRSSetObjectFD,
   1156                                       nullptr,
   1157                                       clang::VK_RValue);
   1158 
   1159   const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1160   clang::DeclRefExpr *RefRSVar =
   1161       clang::DeclRefExpr::Create(C,
   1162                                  clang::NestedNameSpecifierLoc(),
   1163                                  clang::SourceLocation(),
   1164                                  VD,
   1165                                  false,
   1166                                  Loc,
   1167                                  T->getCanonicalTypeInternal(),
   1168                                  clang::VK_RValue,
   1169                                  nullptr);
   1170 
   1171   llvm::SmallVector<clang::Expr*, 2> ArgList;
   1172   ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
   1173                                                 clang::UO_AddrOf,
   1174                                                 SetObjectFDArgType[0],
   1175                                                 clang::VK_RValue,
   1176                                                 clang::OK_Ordinary,
   1177                                                 Loc));
   1178   ArgList.push_back(InitExpr);
   1179 
   1180   clang::CallExpr *RSSetObjectCall =
   1181       new(C) clang::CallExpr(C,
   1182                              RSSetObjectFP,
   1183                              ArgList,
   1184                              SetObjectFD->getCallResultType(),
   1185                              clang::VK_RValue,
   1186                              Loc);
   1187 
   1188   std::list<clang::Stmt*> StmtList;
   1189   StmtList.push_back(RSSetObjectCall);
   1190   AppendAfterStmt(C, mCS, DS, StmtList);
   1191 }
   1192 
   1193 void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
   1194   if (mRSO.empty()) {
   1195     return;
   1196   }
   1197 
   1198   clang::DeclContext* DC = mRSO.front()->getDeclContext();
   1199   clang::ASTContext& C = DC->getParentASTContext();
   1200   clang::SourceManager& SM = C.getSourceManager();
   1201 
   1202   const auto& OccursBefore = [&SM] (clang::SourceLocation L1, clang::SourceLocation L2)->bool {
   1203     return SM.isBeforeInTranslationUnit(L1, L2);
   1204   };
   1205   typedef std::map<clang::SourceLocation, clang::Stmt*, decltype(OccursBefore)> DMap;
   1206 
   1207   DMap dtors(OccursBefore);
   1208 
   1209   // Create rsClearObject calls. Note the DMap entries are sorted by the SourceLocation.
   1210   for (clang::VarDecl* VD : mRSO) {
   1211     clang::SourceLocation Loc = VD->getSourceRange().getBegin();
   1212     clang::Stmt* RSClearObjectCall = ClearRSObject(VD, DC);
   1213     dtors.insert(std::make_pair(Loc, RSClearObjectCall));
   1214   }
   1215 
   1216   DestructorVisitor Visitor;
   1217   Visitor.Visit(mCS);
   1218 
   1219   // Replace each exiting statement with a block that contains the original statement
   1220   // and added rsClearObject() calls before it.
   1221   for (clang::Stmt* S : Visitor.getExitingStmts()) {
   1222 
   1223     const clang::SourceLocation currentLoc = S->getLocStart();
   1224 
   1225     DMap::iterator firstDtorIter = dtors.begin();
   1226     DMap::iterator currentDtorIter = firstDtorIter;
   1227     DMap::iterator lastDtorIter = dtors.end();
   1228 
   1229     while (currentDtorIter != lastDtorIter &&
   1230            OccursBefore(currentDtorIter->first, currentLoc)) {
   1231       currentDtorIter++;
   1232     }
   1233 
   1234     if (currentDtorIter == firstDtorIter) {
   1235       continue;
   1236     }
   1237 
   1238     std::vector<clang::Stmt*> Stmts;
   1239 
   1240     // Insert rsClearObject() calls for all rsObjects declared before the current statement
   1241     for(DMap::iterator it = firstDtorIter; it != currentDtorIter; it++) {
   1242       Stmts.push_back(it->second);
   1243     }
   1244     Stmts.push_back(S);
   1245 
   1246     RSASTReplace R(C);
   1247     clang::CompoundStmt* CS = BuildCompoundStmt(C, Stmts, S->getLocEnd());
   1248     R.ReplaceStmt(mCS, S, CS);
   1249   }
   1250 
   1251   std::list<clang::Stmt*> Stmts;
   1252   for(auto LocCallPair : dtors) {
   1253     Stmts.push_back(LocCallPair.second);
   1254   }
   1255   AppendAfterStmt(C, mCS, nullptr, Stmts);
   1256 }
   1257 
   1258 clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
   1259     clang::VarDecl *VD,
   1260     clang::DeclContext *DC) {
   1261   slangAssert(VD);
   1262   clang::ASTContext &C = VD->getASTContext();
   1263   clang::SourceLocation Loc = VD->getLocation();
   1264   clang::SourceLocation StartLoc = VD->getInnerLocStart();
   1265   const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1266 
   1267   // Reference expr to target RS object variable
   1268   clang::DeclRefExpr *RefRSVar =
   1269       clang::DeclRefExpr::Create(C,
   1270                                  clang::NestedNameSpecifierLoc(),
   1271                                  clang::SourceLocation(),
   1272                                  VD,
   1273                                  false,
   1274                                  Loc,
   1275                                  T->getCanonicalTypeInternal(),
   1276                                  clang::VK_RValue,
   1277                                  nullptr);
   1278 
   1279   if (T->isArrayType()) {
   1280     return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
   1281   }
   1282 
   1283   DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
   1284 
   1285   if (DT == DataTypeUnknown ||
   1286       DT == DataTypeIsStruct) {
   1287     return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
   1288   }
   1289 
   1290   slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
   1291               "Should be RS object");
   1292 
   1293   return ClearSingleRSObject(C, RefRSVar, Loc);
   1294 }
   1295 
   1296 bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
   1297                                           DataType *DT,
   1298                                           clang::Expr **InitExpr) {
   1299   slangAssert(VD && DT && InitExpr);
   1300   const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1301 
   1302   // Loop through array types to get to base type
   1303   slangAssert(T);
   1304   while (T->isArrayType()) {
   1305     T = T->getArrayElementTypeNoTypeQual();
   1306     slangAssert(T);
   1307   }
   1308 
   1309   bool DataTypeIsStructWithRSObject = false;
   1310   *DT = RSExportPrimitiveType::GetRSSpecificType(T);
   1311 
   1312   if (*DT == DataTypeUnknown) {
   1313     if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
   1314       *DT = DataTypeIsStruct;
   1315       DataTypeIsStructWithRSObject = true;
   1316     } else {
   1317       return false;
   1318     }
   1319   }
   1320 
   1321   bool DataTypeIsRSObject = false;
   1322   if (DataTypeIsStructWithRSObject) {
   1323     DataTypeIsRSObject = true;
   1324   } else {
   1325     DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
   1326   }
   1327   *InitExpr = VD->getInit();
   1328 
   1329   if (!DataTypeIsRSObject && *InitExpr) {
   1330     // If we already have an initializer for a matrix type, we are done.
   1331     return DataTypeIsRSObject;
   1332   }
   1333 
   1334   clang::Expr *ZeroInitializer =
   1335       CreateEmptyInitListExpr(VD->getASTContext(), VD->getLocation());
   1336 
   1337   if (ZeroInitializer) {
   1338     ZeroInitializer->setType(T->getCanonicalTypeInternal());
   1339     VD->setInit(ZeroInitializer);
   1340   }
   1341 
   1342   return DataTypeIsRSObject;
   1343 }
   1344 
   1345 clang::Expr *RSObjectRefCount::CreateEmptyInitListExpr(
   1346     clang::ASTContext &C,
   1347     const clang::SourceLocation &Loc) {
   1348 
   1349   // We can cheaply construct a zero initializer by just creating an empty
   1350   // initializer list. Clang supports this extension to C(99), and will create
   1351   // any necessary constructs to zero out the entire variable.
   1352   llvm::SmallVector<clang::Expr*, 1> EmptyInitList;
   1353   return new(C) clang::InitListExpr(C, Loc, EmptyInitList, Loc);
   1354 }
   1355 
   1356 clang::DeclRefExpr *RSObjectRefCount::CreateGuard(clang::ASTContext &C,
   1357                                                   clang::DeclContext *DC,
   1358                                                   clang::Expr *E,
   1359                                                   const llvm::Twine &VarName,
   1360                                                   std::vector<clang::Stmt*> &NewStmts) {
   1361   clang::SourceLocation Loc = E->getLocStart();
   1362   const clang::QualType Ty = E->getType();
   1363   clang::VarDecl* TmpDecl = clang::VarDecl::Create(
   1364       C,                                     // AST context
   1365       DC,                                    // Decl context
   1366       Loc,                                   // Start location
   1367       Loc,                                   // Id location
   1368       &C.Idents.get(VarName.str()),          // Id
   1369       Ty,                                    // Type
   1370       C.getTrivialTypeSourceInfo(Ty),        // Type info
   1371       clang::SC_None                         // Storage class
   1372   );
   1373   const clang::Type *T = Ty.getTypePtr();
   1374   clang::Expr *ZeroInitializer =
   1375       RSObjectRefCount::CreateEmptyInitListExpr(C, Loc);
   1376   ZeroInitializer->setType(T->getCanonicalTypeInternal());
   1377   TmpDecl->setInit(ZeroInitializer);
   1378   TmpDecl->markUsed(C);
   1379   clang::Decl* Decls[] = { TmpDecl };
   1380   const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
   1381       C, Decls, sizeof(Decls) / sizeof(*Decls));
   1382   clang::DeclStmt* DS = new (C) clang::DeclStmt(DGR, Loc, Loc);
   1383   NewStmts.push_back(DS);
   1384 
   1385   clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
   1386       C,
   1387       clang::NestedNameSpecifierLoc(),       // QualifierLoc
   1388       Loc,                                   // TemplateKWLoc
   1389       TmpDecl,
   1390       false,                                 // RefersToEnclosingVariableOrCapture
   1391       Loc,                                   // NameLoc
   1392       Ty,
   1393       clang::VK_LValue
   1394   );
   1395 
   1396   clang::Stmt *UpdatedStmt = nullptr;
   1397   if (CountRSObjectTypes(Ty.getTypePtr()) == 0) {
   1398     // The expression E is not an RS object itself. Instead of calling
   1399     // rsSetObject(), create an assignment statement to set the value of the
   1400     // temporary "guard" variable to the expression.
   1401     // This can happen if called from RSObjectRefCount::VisitReturnStmt(),
   1402     // when the return expression is not an RS object but references one.
   1403     UpdatedStmt =
   1404       new(C) clang::BinaryOperator(DRE, E, clang::BO_Assign, Ty,
   1405                                    clang::VK_RValue, clang::OK_Ordinary, Loc,
   1406                                    false);
   1407 
   1408   } else if (!RSExportPrimitiveType::IsRSObjectType(Ty.getTypePtr())) {
   1409     // By definition, this is a struct assignment if we get here
   1410     UpdatedStmt =
   1411         CreateStructRSSetObject(C, DRE, E, Loc, Loc);
   1412   } else {
   1413     UpdatedStmt =
   1414         CreateSingleRSSetObject(C, DRE, E, Loc, Loc);
   1415   }
   1416   NewStmts.push_back(UpdatedStmt);
   1417 
   1418   return DRE;
   1419 }
   1420 
   1421 void RSObjectRefCount::CreateParameterGuard(clang::ASTContext &C,
   1422                                             clang::DeclContext *DC,
   1423                                             clang::ParmVarDecl *PD,
   1424                                             std::vector<clang::Stmt*> &NewStmts) {
   1425   clang::SourceLocation Loc = PD->getLocStart();
   1426   clang::DeclRefExpr* ParamDRE = clang::DeclRefExpr::Create(
   1427       C,
   1428       clang::NestedNameSpecifierLoc(),       // QualifierLoc
   1429       Loc,                                   // TemplateKWLoc
   1430       PD,
   1431       false,                                 // RefersToEnclosingVariableOrCapture
   1432       Loc,                                   // NameLoc
   1433       PD->getType(),
   1434       clang::VK_RValue
   1435   );
   1436 
   1437   CreateGuard(C, DC, ParamDRE,
   1438               llvm::Twine(".rs.param.") + llvm::Twine(PD->getName()), NewStmts);
   1439 }
   1440 
   1441 void RSObjectRefCount::HandleParamsAndLocals(clang::FunctionDecl *FD) {
   1442   std::vector<clang::Stmt*> NewStmts;
   1443   std::list<clang::ParmVarDecl*> ObjParams;
   1444   for (clang::ParmVarDecl *Param : FD->parameters()) {
   1445     clang::QualType QT = Param->getType();
   1446     if (CountRSObjectTypes(QT.getTypePtr())) {
   1447       // Ignore non-object types
   1448       RSObjectRefCount::CreateParameterGuard(mCtx, FD, Param, NewStmts);
   1449       ObjParams.push_back(Param);
   1450     }
   1451   }
   1452 
   1453   clang::Stmt *OldBody = FD->getBody();
   1454   if (ObjParams.empty()) {
   1455     Visit(OldBody);
   1456     return;
   1457   }
   1458 
   1459   NewStmts.push_back(OldBody);
   1460 
   1461   clang::SourceLocation Loc = FD->getLocStart();
   1462   clang::CompoundStmt *NewBody = BuildCompoundStmt(mCtx, NewStmts, Loc);
   1463   Scope S(NewBody);
   1464   for (clang::ParmVarDecl *Param : ObjParams) {
   1465     S.addRSObject(Param);
   1466   }
   1467   mScopeStack.push_back(&S);
   1468 
   1469   // To avoid adding unnecessary ref counting artifacts to newly added temporary
   1470   // local variables for parameters, visits only the old function body here.
   1471   Visit(OldBody);
   1472 
   1473   FD->setBody(NewBody);
   1474 
   1475   S.InsertLocalVarDestructors();
   1476   mScopeStack.pop_back();
   1477 }
   1478 
   1479 clang::CompoundStmt* RSObjectRefCount::CreateRetStmtWithTempVar(
   1480     clang::ASTContext& C,
   1481     clang::DeclContext* DC,
   1482     clang::ReturnStmt* RS,
   1483     const unsigned id) {
   1484   std::vector<clang::Stmt*> NewStmts;
   1485   // Since we insert rsClearObj() calls before the return statement, we need
   1486   // to make sure none of the cleared RS objects are referenced in the
   1487   // return statement.
   1488   // For that, we create a new local variable named .rs.retval, assign the
   1489   // original return expression to it, make all necessary rsClearObj()
   1490   // calls, then return .rs.retval. Note rsClearObj() is not called on
   1491   // .rs.retval.
   1492   clang::SourceLocation Loc = RS->getLocStart();
   1493   clang::Expr* RetVal = RS->getRetValue();
   1494   const clang::QualType RetTy = RetVal->getType();
   1495   clang::DeclRefExpr *DRE = CreateGuard(C, DC, RetVal,
   1496                                         llvm::Twine(".rs.retval") + llvm::Twine(id),
   1497                                         NewStmts);
   1498 
   1499   // Creates a new return statement
   1500   clang::ReturnStmt* NewRet = new (C) clang::ReturnStmt(Loc);
   1501   clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
   1502       C,
   1503       RetTy,
   1504       clang::CK_LValueToRValue,
   1505       DRE,
   1506       nullptr,
   1507       clang::VK_RValue
   1508   );
   1509   NewRet->setRetValue(CastExpr);
   1510   NewStmts.push_back(NewRet);
   1511 
   1512   return BuildCompoundStmt(C, NewStmts, Loc);
   1513 }
   1514 
   1515 void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
   1516   VisitStmt(DS);
   1517   getCurrentScope()->setCurrentStmt(DS);
   1518   for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
   1519        I != E;
   1520        I++) {
   1521     clang::Decl *D = *I;
   1522     if (D->getKind() == clang::Decl::Var) {
   1523       clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
   1524       DataType DT = DataTypeUnknown;
   1525       clang::Expr *InitExpr = nullptr;
   1526       if (InitializeRSObject(VD, &DT, &InitExpr)) {
   1527         // We need to zero-init all RS object types (including matrices), ...
   1528         getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
   1529         // ... but, only add to the list of RS objects if we have some
   1530         // non-matrix RS object fields.
   1531         if (CountRSObjectTypes(VD->getType().getTypePtr())) {
   1532           getCurrentScope()->addRSObject(VD);
   1533         }
   1534       }
   1535     }
   1536   }
   1537 }
   1538 
   1539 void RSObjectRefCount::VisitCallExpr(clang::CallExpr* CE) {
   1540   clang::QualType RetTy;
   1541   const clang::FunctionDecl* FD = CE->getDirectCallee();
   1542 
   1543   if (FD) {
   1544     // Direct calls
   1545 
   1546     RetTy = FD->getReturnType();
   1547   } else {
   1548     // Indirect calls through function pointers
   1549 
   1550     const clang::Expr* Callee = CE->getCallee();
   1551     const clang::Type* CalleeType = Callee->getType().getTypePtr();
   1552     const clang::PointerType* PtrType = CalleeType->getAs<clang::PointerType>();
   1553 
   1554     if (!PtrType) {
   1555       return;
   1556     }
   1557 
   1558     const clang::Type* PointeeType = PtrType->getPointeeType().getTypePtr();
   1559     const clang::FunctionType* FuncType = PointeeType->getAs<clang::FunctionType>();
   1560 
   1561     if (!FuncType) {
   1562       return;
   1563     }
   1564 
   1565     RetTy = FuncType->getReturnType();
   1566   }
   1567 
   1568   // The RenderScript runtime API maintains the invariant that the sysRef of a new RS object would
   1569   // be 1, with the exception of rsGetAllocation() (deprecated in API 22), which leaves the sysRef
   1570   // 0 for a new allocation. It is the responsibility of the callee of the API to decrement the
   1571   // sysRef when a reference of the RS object goes out of scope. The compiler generates code to do
   1572   // just that, by creating a temporary variable named ".rs.tmpN" with the result of
   1573   // an RS-object-returning API directly assigned to it, and calling rsClearObject() on .rs.tmpN
   1574   // right before it exits the current scope. Such code generation is skipped for rsGetAllocation()
   1575   // to avoid decrementing its sysRef below zero.
   1576 
   1577   if (CountRSObjectTypes(RetTy.getTypePtr())==0 ||
   1578       (FD && FD->getName() == "rsGetAllocation")) {
   1579     return;
   1580   }
   1581 
   1582   clang::SourceLocation Loc = CE->getSourceRange().getBegin();
   1583   std::stringstream ss;
   1584   ss << ".rs.tmp" << getNextID();
   1585   clang::IdentifierInfo *II = &mCtx.Idents.get(ss.str());
   1586 
   1587   clang::VarDecl* TempVarDecl = clang::VarDecl::Create(
   1588       mCtx,                                  // AST context
   1589       GetDeclContext(),                      // Decl context
   1590       Loc,                                   // Start location
   1591       Loc,                                   // Id location
   1592       II,                                    // Id
   1593       RetTy,                                 // Type
   1594       mCtx.getTrivialTypeSourceInfo(RetTy),  // Type info
   1595       clang::SC_None                         // Storage class
   1596   );
   1597   TempVarDecl->setInit(CE);
   1598   TempVarDecl->markUsed(mCtx);
   1599   clang::Decl* Decls[] = { TempVarDecl };
   1600   const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
   1601       mCtx, Decls, sizeof(Decls) / sizeof(*Decls));
   1602   clang::DeclStmt* DS = new (mCtx) clang::DeclStmt(DGR, Loc, Loc);
   1603 
   1604   getCurrentScope()->InsertStmt(mCtx, DS);
   1605 
   1606   clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
   1607       mCtx,                                  // AST context
   1608       clang::NestedNameSpecifierLoc(),       // QualifierLoc
   1609       Loc,                                   // TemplateKWLoc
   1610       TempVarDecl,
   1611       false,                                 // RefersToEnclosingVariableOrCapture
   1612       Loc,                                   // NameLoc
   1613       RetTy,
   1614       clang::VK_LValue
   1615   );
   1616   clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
   1617       mCtx,
   1618       RetTy,
   1619       clang::CK_LValueToRValue,
   1620       DRE,
   1621       nullptr,
   1622       clang::VK_RValue
   1623   );
   1624 
   1625   getCurrentScope()->ReplaceExpr(mCtx, CE, CastExpr);
   1626 
   1627   // Register TempVarDecl for destruction call (rsClearObj).
   1628   getCurrentScope()->addRSObject(TempVarDecl);
   1629 }
   1630 
   1631 void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
   1632   if (!emptyScope()) {
   1633     getCurrentScope()->setCurrentStmt(CS);
   1634   }
   1635 
   1636   if (!CS->body_empty()) {
   1637     // Push a new scope
   1638     Scope *S = new Scope(CS);
   1639     mScopeStack.push_back(S);
   1640 
   1641     VisitStmt(CS);
   1642 
   1643     // Destroy the scope
   1644     slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
   1645     S->InsertLocalVarDestructors();
   1646     mScopeStack.pop_back();
   1647     delete S;
   1648   }
   1649 }
   1650 
   1651 void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
   1652   getCurrentScope()->setCurrentStmt(AS);
   1653   clang::QualType QT = AS->getType();
   1654 
   1655   if (CountRSObjectTypes(QT.getTypePtr())) {
   1656     getCurrentScope()->ReplaceRSObjectAssignment(AS);
   1657   }
   1658 }
   1659 
   1660 namespace {
   1661 
   1662 class FindRSObjRefVisitor : public clang::RecursiveASTVisitor<FindRSObjRefVisitor> {
   1663 public:
   1664   explicit FindRSObjRefVisitor() : mRefRSObj(false) {}
   1665   bool VisitExpr(clang::Expr* Expression) {
   1666     if (CountRSObjectTypes(Expression->getType().getTypePtr()) > 0) {
   1667       mRefRSObj = true;
   1668       // Found a reference to an RS object. Stop the AST traversal.
   1669       return false;
   1670     }
   1671     return true;
   1672   }
   1673 
   1674   bool foundRSObjRef() const { return mRefRSObj; }
   1675 
   1676 private:
   1677   bool mRefRSObj;
   1678 };
   1679 
   1680 }  // anonymous namespace
   1681 
   1682 void RSObjectRefCount::VisitReturnStmt(clang::ReturnStmt *RS) {
   1683   getCurrentScope()->setCurrentStmt(RS);
   1684 
   1685   // If there is no local rsObject declared so far, no need to transform the
   1686   // return statement.
   1687 
   1688   bool RSObjDeclared = false;
   1689 
   1690   for (const Scope* S : mScopeStack) {
   1691     if (S->hasRSObject()) {
   1692       RSObjDeclared = true;
   1693       break;
   1694     }
   1695   }
   1696 
   1697   if (!RSObjDeclared) {
   1698     return;
   1699   }
   1700 
   1701   FindRSObjRefVisitor visitor;
   1702 
   1703   visitor.TraverseStmt(RS);
   1704 
   1705   // If the return statement does not return anything, or if it does not reference
   1706   // a rsObject, no need to transform it.
   1707 
   1708   if (!visitor.foundRSObjRef()) {
   1709     return;
   1710   }
   1711 
   1712   // Transform the return statement so that it does not potentially return or
   1713   // reference a rsObject that has been cleared.
   1714 
   1715   clang::CompoundStmt* NewRS;
   1716   NewRS = CreateRetStmtWithTempVar(mCtx, GetDeclContext(), RS, getNextID());
   1717 
   1718   getCurrentScope()->ReplaceStmt(mCtx, NewRS);
   1719 }
   1720 
   1721 void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
   1722   getCurrentScope()->setCurrentStmt(S);
   1723   for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
   1724        I != E;
   1725        I++) {
   1726     if (clang::Stmt *Child = *I) {
   1727       Visit(Child);
   1728     }
   1729   }
   1730 }
   1731 
   1732 // This function walks the list of global variables and (potentially) creates
   1733 // a single global static destructor function that properly decrements
   1734 // reference counts on the contained RS object types.
   1735 clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
   1736   Init();
   1737 
   1738   clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
   1739   clang::SourceLocation loc;
   1740 
   1741   llvm::StringRef SR(".rs.dtor");
   1742   clang::IdentifierInfo &II = mCtx.Idents.get(SR);
   1743   clang::DeclarationName N(&II);
   1744   clang::FunctionProtoType::ExtProtoInfo EPI;
   1745   clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
   1746       llvm::ArrayRef<clang::QualType>(), EPI);
   1747   clang::FunctionDecl *FD = nullptr;
   1748 
   1749   // Generate rsClearObject() call chains for every global variable
   1750   // (whether static or extern).
   1751   std::vector<clang::Stmt *> StmtList;
   1752   for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
   1753           E = DC->decls_end(); I != E; I++) {
   1754     clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
   1755     if (VD) {
   1756       if (CountRSObjectTypes(VD->getType().getTypePtr())) {
   1757         if (!FD) {
   1758           // Only create FD if we are going to use it.
   1759           FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, nullptr,
   1760                                            clang::SC_None);
   1761         }
   1762         // Mark VD as used.  It might be unused, except for the destructor.
   1763         // 'markUsed' has side-effects that are caused only if VD is not already
   1764         // used.  Hence no need for an extra check here.
   1765         VD->markUsed(mCtx);
   1766         // Make sure to create any helpers within the function's DeclContext,
   1767         // not the one associated with the global translation unit.
   1768         clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
   1769         StmtList.push_back(RSClearObjectCall);
   1770       }
   1771     }
   1772   }
   1773 
   1774   // Nothing needs to be destroyed, so don't emit a dtor.
   1775   if (StmtList.empty()) {
   1776     return nullptr;
   1777   }
   1778 
   1779   clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
   1780 
   1781   slangAssert(FD);
   1782   FD->setBody(CS);
   1783   // We need some way to tell if this FD is generated by slang
   1784   FD->setImplicit();
   1785 
   1786   return FD;
   1787 }
   1788 
   1789 bool HasRSObjectType(const clang::Type *T) {
   1790   return CountRSObjectTypes(T) != 0;
   1791 }
   1792 
   1793 }  // namespace slang
   1794