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 <list>
     20 
     21 #include "clang/AST/DeclGroup.h"
     22 #include "clang/AST/Expr.h"
     23 #include "clang/AST/NestedNameSpecifier.h"
     24 #include "clang/AST/OperationKinds.h"
     25 #include "clang/AST/Stmt.h"
     26 #include "clang/AST/StmtVisitor.h"
     27 
     28 #include "slang_assert.h"
     29 #include "slang_rs.h"
     30 #include "slang_rs_ast_replace.h"
     31 #include "slang_rs_export_type.h"
     32 
     33 namespace slang {
     34 
     35 clang::FunctionDecl *RSObjectRefCount::
     36     RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
     37                   RSExportPrimitiveType::FirstRSObjectType + 1];
     38 clang::FunctionDecl *RSObjectRefCount::
     39     RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
     40                     RSExportPrimitiveType::FirstRSObjectType + 1];
     41 
     42 void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
     43   for (unsigned i = 0;
     44        i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
     45        i++) {
     46     RSSetObjectFD[i] = NULL;
     47     RSClearObjectFD[i] = NULL;
     48   }
     49 
     50   clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
     51 
     52   for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
     53           E = TUDecl->decls_end(); I != E; I++) {
     54     if ((I->getKind() >= clang::Decl::firstFunction) &&
     55         (I->getKind() <= clang::Decl::lastFunction)) {
     56       clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
     57 
     58       // points to RSSetObjectFD or RSClearObjectFD
     59       clang::FunctionDecl **RSObjectFD;
     60 
     61       if (FD->getName() == "rsSetObject") {
     62         slangAssert((FD->getNumParams() == 2) &&
     63                     "Invalid rsSetObject function prototype (# params)");
     64         RSObjectFD = RSSetObjectFD;
     65       } else if (FD->getName() == "rsClearObject") {
     66         slangAssert((FD->getNumParams() == 1) &&
     67                     "Invalid rsClearObject function prototype (# params)");
     68         RSObjectFD = RSClearObjectFD;
     69       } else {
     70         continue;
     71       }
     72 
     73       const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
     74       clang::QualType PVT = PVD->getOriginalType();
     75       // The first parameter must be a pointer like rs_allocation*
     76       slangAssert(PVT->isPointerType() &&
     77           "Invalid rs{Set,Clear}Object function prototype (pointer param)");
     78 
     79       // The rs object type passed to the FD
     80       clang::QualType RST = PVT->getPointeeType();
     81       RSExportPrimitiveType::DataType DT =
     82           RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
     83       slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
     84              && "must be RS object type");
     85 
     86       RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
     87     }
     88   }
     89 }
     90 
     91 namespace {
     92 
     93 // This function constructs a new CompoundStmt from the input StmtList.
     94 static clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
     95       std::list<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
     96   unsigned NewStmtCount = StmtList.size();
     97   unsigned CompoundStmtCount = 0;
     98 
     99   clang::Stmt **CompoundStmtList;
    100   CompoundStmtList = new clang::Stmt*[NewStmtCount];
    101 
    102   std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
    103   std::list<clang::Stmt*>::const_iterator E = StmtList.end();
    104   for ( ; I != E; I++) {
    105     CompoundStmtList[CompoundStmtCount++] = *I;
    106   }
    107   slangAssert(CompoundStmtCount == NewStmtCount);
    108 
    109   clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
    110       C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);
    111 
    112   delete [] CompoundStmtList;
    113 
    114   return CS;
    115 }
    116 
    117 static void AppendAfterStmt(clang::ASTContext &C,
    118                             clang::CompoundStmt *CS,
    119                             clang::Stmt *S,
    120                             std::list<clang::Stmt*> &StmtList) {
    121   slangAssert(CS);
    122   clang::CompoundStmt::body_iterator bI = CS->body_begin();
    123   clang::CompoundStmt::body_iterator bE = CS->body_end();
    124   clang::Stmt **UpdatedStmtList =
    125       new clang::Stmt*[CS->size() + StmtList.size()];
    126 
    127   unsigned UpdatedStmtCount = 0;
    128   unsigned Once = 0;
    129   for ( ; bI != bE; bI++) {
    130     if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
    131       // If we come across a return here, we don't have anything we can
    132       // reasonably replace. We should have already inserted our destructor
    133       // code in the proper spot, so we just clean up and return.
    134       delete [] UpdatedStmtList;
    135 
    136       return;
    137     }
    138 
    139     UpdatedStmtList[UpdatedStmtCount++] = *bI;
    140 
    141     if ((*bI == S) && !Once) {
    142       Once++;
    143       std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
    144       std::list<clang::Stmt*>::const_iterator E = StmtList.end();
    145       for ( ; I != E; I++) {
    146         UpdatedStmtList[UpdatedStmtCount++] = *I;
    147       }
    148     }
    149   }
    150   slangAssert(Once <= 1);
    151 
    152   // When S is NULL, we are appending to the end of the CompoundStmt.
    153   if (!S) {
    154     slangAssert(Once == 0);
    155     std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
    156     std::list<clang::Stmt*>::const_iterator E = StmtList.end();
    157     for ( ; I != E; I++) {
    158       UpdatedStmtList[UpdatedStmtCount++] = *I;
    159     }
    160   }
    161 
    162   CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
    163 
    164   delete [] UpdatedStmtList;
    165 
    166   return;
    167 }
    168 
    169 // This class visits a compound statement and inserts DtorStmt
    170 // in proper locations. This includes inserting it before any
    171 // return statement in any sub-block, at the end of the logical enclosing
    172 // scope (compound statement), and/or before any break/continue statement that
    173 // would resume outside the declared scope. We will not handle the case for
    174 // goto statements that leave a local scope.
    175 //
    176 // To accomplish these goals, it collects a list of sub-Stmt's that
    177 // correspond to scope exit points. It then uses an RSASTReplace visitor to
    178 // transform the AST, inserting appropriate destructors before each of those
    179 // sub-Stmt's (and also before the exit of the outermost containing Stmt for
    180 // the scope).
    181 class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
    182  private:
    183   clang::ASTContext &mCtx;
    184 
    185   // The loop depth of the currently visited node.
    186   int mLoopDepth;
    187 
    188   // The switch statement depth of the currently visited node.
    189   // Note that this is tracked separately from the loop depth because
    190   // SwitchStmt-contained ContinueStmt's should have destructors for the
    191   // corresponding loop scope.
    192   int mSwitchDepth;
    193 
    194   // The outermost statement block that we are currently visiting.
    195   // This should always be a CompoundStmt.
    196   clang::Stmt *mOuterStmt;
    197 
    198   // The destructor to execute for this scope/variable.
    199   clang::Stmt* mDtorStmt;
    200 
    201   // The stack of statements which should be replaced by a compound statement
    202   // containing the new destructor call followed by the original Stmt.
    203   std::stack<clang::Stmt*> mReplaceStmtStack;
    204 
    205   // The source location for the variable declaration that we are trying to
    206   // insert destructors for. Note that InsertDestructors() will not generate
    207   // destructor calls for source locations that occur lexically before this
    208   // location.
    209   clang::SourceLocation mVarLoc;
    210 
    211  public:
    212   DestructorVisitor(clang::ASTContext &C,
    213                     clang::Stmt* OuterStmt,
    214                     clang::Stmt* DtorStmt,
    215                     clang::SourceLocation VarLoc);
    216 
    217   // This code walks the collected list of Stmts to replace and actually does
    218   // the replacement. It also finishes up by appending the destructor to the
    219   // current outermost CompoundStmt.
    220   void InsertDestructors() {
    221     clang::Stmt *S = NULL;
    222     clang::SourceManager &SM = mCtx.getSourceManager();
    223     std::list<clang::Stmt *> StmtList;
    224     StmtList.push_back(mDtorStmt);
    225 
    226     while (!mReplaceStmtStack.empty()) {
    227       S = mReplaceStmtStack.top();
    228       mReplaceStmtStack.pop();
    229 
    230       // Skip all source locations that occur before the variable's
    231       // declaration, since it won't have been initialized yet.
    232       if (SM.isBeforeInTranslationUnit(S->getLocStart(), mVarLoc)) {
    233         continue;
    234       }
    235 
    236       StmtList.push_back(S);
    237       clang::CompoundStmt *CS =
    238           BuildCompoundStmt(mCtx, StmtList, S->getLocEnd());
    239       StmtList.pop_back();
    240 
    241       RSASTReplace R(mCtx);
    242       R.ReplaceStmt(mOuterStmt, S, CS);
    243     }
    244     clang::CompoundStmt *CS =
    245       llvm::dyn_cast<clang::CompoundStmt>(mOuterStmt);
    246     slangAssert(CS);
    247     AppendAfterStmt(mCtx, CS, NULL, StmtList);
    248   }
    249 
    250   void VisitStmt(clang::Stmt *S);
    251   void VisitCompoundStmt(clang::CompoundStmt *CS);
    252 
    253   void VisitBreakStmt(clang::BreakStmt *BS);
    254   void VisitCaseStmt(clang::CaseStmt *CS);
    255   void VisitContinueStmt(clang::ContinueStmt *CS);
    256   void VisitDefaultStmt(clang::DefaultStmt *DS);
    257   void VisitDoStmt(clang::DoStmt *DS);
    258   void VisitForStmt(clang::ForStmt *FS);
    259   void VisitIfStmt(clang::IfStmt *IS);
    260   void VisitReturnStmt(clang::ReturnStmt *RS);
    261   void VisitSwitchCase(clang::SwitchCase *SC);
    262   void VisitSwitchStmt(clang::SwitchStmt *SS);
    263   void VisitWhileStmt(clang::WhileStmt *WS);
    264 };
    265 
    266 DestructorVisitor::DestructorVisitor(clang::ASTContext &C,
    267                          clang::Stmt *OuterStmt,
    268                          clang::Stmt *DtorStmt,
    269                          clang::SourceLocation VarLoc)
    270   : mCtx(C),
    271     mLoopDepth(0),
    272     mSwitchDepth(0),
    273     mOuterStmt(OuterStmt),
    274     mDtorStmt(DtorStmt),
    275     mVarLoc(VarLoc) {
    276   return;
    277 }
    278 
    279 void DestructorVisitor::VisitStmt(clang::Stmt *S) {
    280   for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
    281        I != E;
    282        I++) {
    283     if (clang::Stmt *Child = *I) {
    284       Visit(Child);
    285     }
    286   }
    287   return;
    288 }
    289 
    290 void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
    291   VisitStmt(CS);
    292   return;
    293 }
    294 
    295 void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
    296   VisitStmt(BS);
    297   if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
    298     mReplaceStmtStack.push(BS);
    299   }
    300   return;
    301 }
    302 
    303 void DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) {
    304   VisitStmt(CS);
    305   return;
    306 }
    307 
    308 void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
    309   VisitStmt(CS);
    310   if (mLoopDepth == 0) {
    311     // Switch statements can have nested continues.
    312     mReplaceStmtStack.push(CS);
    313   }
    314   return;
    315 }
    316 
    317 void DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) {
    318   VisitStmt(DS);
    319   return;
    320 }
    321 
    322 void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
    323   mLoopDepth++;
    324   VisitStmt(DS);
    325   mLoopDepth--;
    326   return;
    327 }
    328 
    329 void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
    330   mLoopDepth++;
    331   VisitStmt(FS);
    332   mLoopDepth--;
    333   return;
    334 }
    335 
    336 void DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) {
    337   VisitStmt(IS);
    338   return;
    339 }
    340 
    341 void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
    342   mReplaceStmtStack.push(RS);
    343   return;
    344 }
    345 
    346 void DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) {
    347   slangAssert(false && "Both case and default have specialized handlers");
    348   VisitStmt(SC);
    349   return;
    350 }
    351 
    352 void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
    353   mSwitchDepth++;
    354   VisitStmt(SS);
    355   mSwitchDepth--;
    356   return;
    357 }
    358 
    359 void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
    360   mLoopDepth++;
    361   VisitStmt(WS);
    362   mLoopDepth--;
    363   return;
    364 }
    365 
    366 clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
    367                                  clang::Expr *RefRSVar,
    368                                  clang::SourceLocation Loc) {
    369   slangAssert(RefRSVar);
    370   const clang::Type *T = RefRSVar->getType().getTypePtr();
    371   slangAssert(!T->isArrayType() &&
    372               "Should not be destroying arrays with this function");
    373 
    374   clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
    375   slangAssert((ClearObjectFD != NULL) &&
    376               "rsClearObject doesn't cover all RS object types");
    377 
    378   clang::QualType ClearObjectFDType = ClearObjectFD->getType();
    379   clang::QualType ClearObjectFDArgType =
    380       ClearObjectFD->getParamDecl(0)->getOriginalType();
    381 
    382   // Example destructor for "rs_font localFont;"
    383   //
    384   // (CallExpr 'void'
    385   //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
    386   //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
    387   //   (UnaryOperator 'rs_font *' prefix '&'
    388   //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
    389 
    390   // Get address of targeted RS object
    391   clang::Expr *AddrRefRSVar =
    392       new(C) clang::UnaryOperator(RefRSVar,
    393                                   clang::UO_AddrOf,
    394                                   ClearObjectFDArgType,
    395                                   clang::VK_RValue,
    396                                   clang::OK_Ordinary,
    397                                   Loc);
    398 
    399   clang::Expr *RefRSClearObjectFD =
    400       clang::DeclRefExpr::Create(C,
    401                                  clang::NestedNameSpecifierLoc(),
    402                                  clang::SourceLocation(),
    403                                  ClearObjectFD,
    404                                  false,
    405                                  ClearObjectFD->getLocation(),
    406                                  ClearObjectFDType,
    407                                  clang::VK_RValue,
    408                                  NULL);
    409 
    410   clang::Expr *RSClearObjectFP =
    411       clang::ImplicitCastExpr::Create(C,
    412                                       C.getPointerType(ClearObjectFDType),
    413                                       clang::CK_FunctionToPointerDecay,
    414                                       RefRSClearObjectFD,
    415                                       NULL,
    416                                       clang::VK_RValue);
    417 
    418   llvm::SmallVector<clang::Expr*, 1> ArgList;
    419   ArgList.push_back(AddrRefRSVar);
    420 
    421   clang::CallExpr *RSClearObjectCall =
    422       new(C) clang::CallExpr(C,
    423                              RSClearObjectFP,
    424                              ArgList,
    425                              ClearObjectFD->getCallResultType(),
    426                              clang::VK_RValue,
    427                              Loc);
    428 
    429   return RSClearObjectCall;
    430 }
    431 
    432 static int ArrayDim(const clang::Type *T) {
    433   if (!T || !T->isArrayType()) {
    434     return 0;
    435   }
    436 
    437   const clang::ConstantArrayType *CAT =
    438     static_cast<const clang::ConstantArrayType *>(T);
    439   return static_cast<int>(CAT->getSize().getSExtValue());
    440 }
    441 
    442 static clang::Stmt *ClearStructRSObject(
    443     clang::ASTContext &C,
    444     clang::DeclContext *DC,
    445     clang::Expr *RefRSStruct,
    446     clang::SourceLocation StartLoc,
    447     clang::SourceLocation Loc);
    448 
    449 static clang::Stmt *ClearArrayRSObject(
    450     clang::ASTContext &C,
    451     clang::DeclContext *DC,
    452     clang::Expr *RefRSArr,
    453     clang::SourceLocation StartLoc,
    454     clang::SourceLocation Loc) {
    455   const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
    456   slangAssert(BaseType->isArrayType());
    457 
    458   int NumArrayElements = ArrayDim(BaseType);
    459   // Actually extract out the base RS object type for use later
    460   BaseType = BaseType->getArrayElementTypeNoTypeQual();
    461 
    462   clang::Stmt *StmtArray[2] = {NULL};
    463   int StmtCtr = 0;
    464 
    465   if (NumArrayElements <= 0) {
    466     return NULL;
    467   }
    468 
    469   // Example destructor loop for "rs_font fontArr[10];"
    470   //
    471   // (CompoundStmt
    472   //   (DeclStmt "int rsIntIter")
    473   //   (ForStmt
    474   //     (BinaryOperator 'int' '='
    475   //       (DeclRefExpr 'int' Var='rsIntIter')
    476   //       (IntegerLiteral 'int' 0))
    477   //     (BinaryOperator 'int' '<'
    478   //       (DeclRefExpr 'int' Var='rsIntIter')
    479   //       (IntegerLiteral 'int' 10)
    480   //     NULL << CondVar >>
    481   //     (UnaryOperator 'int' postfix '++'
    482   //       (DeclRefExpr 'int' Var='rsIntIter'))
    483   //     (CallExpr 'void'
    484   //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
    485   //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
    486   //       (UnaryOperator 'rs_font *' prefix '&'
    487   //         (ArraySubscriptExpr 'rs_font':'rs_font'
    488   //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
    489   //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
    490   //           (DeclRefExpr 'int' Var='rsIntIter')))))))
    491 
    492   // Create helper variable for iterating through elements
    493   clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
    494   clang::VarDecl *IIVD =
    495       clang::VarDecl::Create(C,
    496                              DC,
    497                              StartLoc,
    498                              Loc,
    499                              &II,
    500                              C.IntTy,
    501                              C.getTrivialTypeSourceInfo(C.IntTy),
    502                              clang::SC_None);
    503   clang::Decl *IID = (clang::Decl *)IIVD;
    504 
    505   clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
    506   StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
    507 
    508   // Form the actual destructor loop
    509   // for (Init; Cond; Inc)
    510   //   RSClearObjectCall;
    511 
    512   // Init -> "rsIntIter = 0"
    513   clang::DeclRefExpr *RefrsIntIter =
    514       clang::DeclRefExpr::Create(C,
    515                                  clang::NestedNameSpecifierLoc(),
    516                                  clang::SourceLocation(),
    517                                  IIVD,
    518                                  false,
    519                                  Loc,
    520                                  C.IntTy,
    521                                  clang::VK_RValue,
    522                                  NULL);
    523 
    524   clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
    525       llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
    526 
    527   clang::BinaryOperator *Init =
    528       new(C) clang::BinaryOperator(RefrsIntIter,
    529                                    Int0,
    530                                    clang::BO_Assign,
    531                                    C.IntTy,
    532                                    clang::VK_RValue,
    533                                    clang::OK_Ordinary,
    534                                    Loc,
    535                                    false);
    536 
    537   // Cond -> "rsIntIter < NumArrayElements"
    538   clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
    539       llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
    540 
    541   clang::BinaryOperator *Cond =
    542       new(C) clang::BinaryOperator(RefrsIntIter,
    543                                    NumArrayElementsExpr,
    544                                    clang::BO_LT,
    545                                    C.IntTy,
    546                                    clang::VK_RValue,
    547                                    clang::OK_Ordinary,
    548                                    Loc,
    549                                    false);
    550 
    551   // Inc -> "rsIntIter++"
    552   clang::UnaryOperator *Inc =
    553       new(C) clang::UnaryOperator(RefrsIntIter,
    554                                   clang::UO_PostInc,
    555                                   C.IntTy,
    556                                   clang::VK_RValue,
    557                                   clang::OK_Ordinary,
    558                                   Loc);
    559 
    560   // Body -> "rsClearObject(&VD[rsIntIter]);"
    561   // Destructor loop operates on individual array elements
    562 
    563   clang::Expr *RefRSArrPtr =
    564       clang::ImplicitCastExpr::Create(C,
    565           C.getPointerType(BaseType->getCanonicalTypeInternal()),
    566           clang::CK_ArrayToPointerDecay,
    567           RefRSArr,
    568           NULL,
    569           clang::VK_RValue);
    570 
    571   clang::Expr *RefRSArrPtrSubscript =
    572       new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
    573                                        RefrsIntIter,
    574                                        BaseType->getCanonicalTypeInternal(),
    575                                        clang::VK_RValue,
    576                                        clang::OK_Ordinary,
    577                                        Loc);
    578 
    579   RSExportPrimitiveType::DataType DT =
    580       RSExportPrimitiveType::GetRSSpecificType(BaseType);
    581 
    582   clang::Stmt *RSClearObjectCall = NULL;
    583   if (BaseType->isArrayType()) {
    584     RSClearObjectCall =
    585         ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
    586   } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
    587     RSClearObjectCall =
    588         ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
    589   } else {
    590     RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
    591   }
    592 
    593   clang::ForStmt *DestructorLoop =
    594       new(C) clang::ForStmt(C,
    595                             Init,
    596                             Cond,
    597                             NULL,  // no condVar
    598                             Inc,
    599                             RSClearObjectCall,
    600                             Loc,
    601                             Loc,
    602                             Loc);
    603 
    604   StmtArray[StmtCtr++] = DestructorLoop;
    605   slangAssert(StmtCtr == 2);
    606 
    607   clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
    608       C, llvm::makeArrayRef(StmtArray, StmtCtr), Loc, Loc);
    609 
    610   return CS;
    611 }
    612 
    613 static unsigned CountRSObjectTypes(clang::ASTContext &C,
    614                                    const clang::Type *T,
    615                                    clang::SourceLocation Loc) {
    616   slangAssert(T);
    617   unsigned RSObjectCount = 0;
    618 
    619   if (T->isArrayType()) {
    620     return CountRSObjectTypes(C, T->getArrayElementTypeNoTypeQual(), Loc);
    621   }
    622 
    623   RSExportPrimitiveType::DataType DT =
    624       RSExportPrimitiveType::GetRSSpecificType(T);
    625   if (DT != RSExportPrimitiveType::DataTypeUnknown) {
    626     return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
    627   }
    628 
    629   if (T->isUnionType()) {
    630     clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
    631     RD = RD->getDefinition();
    632     for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    633            FE = RD->field_end();
    634          FI != FE;
    635          FI++) {
    636       const clang::FieldDecl *FD = *FI;
    637       const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    638       if (CountRSObjectTypes(C, FT, Loc)) {
    639         slangAssert(false && "can't have unions with RS object types!");
    640         return 0;
    641       }
    642     }
    643   }
    644 
    645   if (!T->isStructureType()) {
    646     return 0;
    647   }
    648 
    649   clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
    650   RD = RD->getDefinition();
    651   for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    652          FE = RD->field_end();
    653        FI != FE;
    654        FI++) {
    655     const clang::FieldDecl *FD = *FI;
    656     const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    657     if (CountRSObjectTypes(C, FT, Loc)) {
    658       // Sub-structs should only count once (as should arrays, etc.)
    659       RSObjectCount++;
    660     }
    661   }
    662 
    663   return RSObjectCount;
    664 }
    665 
    666 static clang::Stmt *ClearStructRSObject(
    667     clang::ASTContext &C,
    668     clang::DeclContext *DC,
    669     clang::Expr *RefRSStruct,
    670     clang::SourceLocation StartLoc,
    671     clang::SourceLocation Loc) {
    672   const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
    673 
    674   slangAssert(!BaseType->isArrayType());
    675 
    676   // Structs should show up as unknown primitive types
    677   slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
    678               RSExportPrimitiveType::DataTypeUnknown);
    679 
    680   unsigned FieldsToDestroy = CountRSObjectTypes(C, BaseType, Loc);
    681   slangAssert(FieldsToDestroy != 0);
    682 
    683   unsigned StmtCount = 0;
    684   clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
    685   for (unsigned i = 0; i < FieldsToDestroy; i++) {
    686     StmtArray[i] = NULL;
    687   }
    688 
    689   // Populate StmtArray by creating a destructor for each RS object field
    690   clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
    691   RD = RD->getDefinition();
    692   for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
    693          FE = RD->field_end();
    694        FI != FE;
    695        FI++) {
    696     // We just look through all field declarations to see if we find a
    697     // declaration for an RS object type (or an array of one).
    698     bool IsArrayType = false;
    699     clang::FieldDecl *FD = *FI;
    700     const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    701     const clang::Type *OrigType = FT;
    702     while (FT && FT->isArrayType()) {
    703       FT = FT->getArrayElementTypeNoTypeQual();
    704       IsArrayType = true;
    705     }
    706 
    707     if (RSExportPrimitiveType::IsRSObjectType(FT)) {
    708       clang::DeclAccessPair FoundDecl =
    709           clang::DeclAccessPair::make(FD, clang::AS_none);
    710       clang::MemberExpr *RSObjectMember =
    711           clang::MemberExpr::Create(C,
    712                                     RefRSStruct,
    713                                     false,
    714                                     clang::NestedNameSpecifierLoc(),
    715                                     clang::SourceLocation(),
    716                                     FD,
    717                                     FoundDecl,
    718                                     clang::DeclarationNameInfo(),
    719                                     NULL,
    720                                     OrigType->getCanonicalTypeInternal(),
    721                                     clang::VK_RValue,
    722                                     clang::OK_Ordinary);
    723 
    724       slangAssert(StmtCount < FieldsToDestroy);
    725 
    726       if (IsArrayType) {
    727         StmtArray[StmtCount++] = ClearArrayRSObject(C,
    728                                                     DC,
    729                                                     RSObjectMember,
    730                                                     StartLoc,
    731                                                     Loc);
    732       } else {
    733         StmtArray[StmtCount++] = ClearSingleRSObject(C,
    734                                                      RSObjectMember,
    735                                                      Loc);
    736       }
    737     } else if (FT->isStructureType() && CountRSObjectTypes(C, FT, Loc)) {
    738       // In this case, we have a nested struct. We may not end up filling all
    739       // of the spaces in StmtArray (sub-structs should handle themselves
    740       // with separate compound statements).
    741       clang::DeclAccessPair FoundDecl =
    742           clang::DeclAccessPair::make(FD, clang::AS_none);
    743       clang::MemberExpr *RSObjectMember =
    744           clang::MemberExpr::Create(C,
    745                                     RefRSStruct,
    746                                     false,
    747                                     clang::NestedNameSpecifierLoc(),
    748                                     clang::SourceLocation(),
    749                                     FD,
    750                                     FoundDecl,
    751                                     clang::DeclarationNameInfo(),
    752                                     NULL,
    753                                     OrigType->getCanonicalTypeInternal(),
    754                                     clang::VK_RValue,
    755                                     clang::OK_Ordinary);
    756 
    757       if (IsArrayType) {
    758         StmtArray[StmtCount++] = ClearArrayRSObject(C,
    759                                                     DC,
    760                                                     RSObjectMember,
    761                                                     StartLoc,
    762                                                     Loc);
    763       } else {
    764         StmtArray[StmtCount++] = ClearStructRSObject(C,
    765                                                      DC,
    766                                                      RSObjectMember,
    767                                                      StartLoc,
    768                                                      Loc);
    769       }
    770     }
    771   }
    772 
    773   slangAssert(StmtCount > 0);
    774   clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
    775       C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
    776 
    777   delete [] StmtArray;
    778 
    779   return CS;
    780 }
    781 
    782 static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
    783                                             clang::Expr *DstExpr,
    784                                             clang::Expr *SrcExpr,
    785                                             clang::SourceLocation StartLoc,
    786                                             clang::SourceLocation Loc) {
    787   const clang::Type *T = DstExpr->getType().getTypePtr();
    788   clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
    789   slangAssert((SetObjectFD != NULL) &&
    790               "rsSetObject doesn't cover all RS object types");
    791 
    792   clang::QualType SetObjectFDType = SetObjectFD->getType();
    793   clang::QualType SetObjectFDArgType[2];
    794   SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
    795   SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
    796 
    797   clang::Expr *RefRSSetObjectFD =
    798       clang::DeclRefExpr::Create(C,
    799                                  clang::NestedNameSpecifierLoc(),
    800                                  clang::SourceLocation(),
    801                                  SetObjectFD,
    802                                  false,
    803                                  Loc,
    804                                  SetObjectFDType,
    805                                  clang::VK_RValue,
    806                                  NULL);
    807 
    808   clang::Expr *RSSetObjectFP =
    809       clang::ImplicitCastExpr::Create(C,
    810                                       C.getPointerType(SetObjectFDType),
    811                                       clang::CK_FunctionToPointerDecay,
    812                                       RefRSSetObjectFD,
    813                                       NULL,
    814                                       clang::VK_RValue);
    815 
    816   llvm::SmallVector<clang::Expr*, 2> ArgList;
    817   ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
    818                                                 clang::UO_AddrOf,
    819                                                 SetObjectFDArgType[0],
    820                                                 clang::VK_RValue,
    821                                                 clang::OK_Ordinary,
    822                                                 Loc));
    823   ArgList.push_back(SrcExpr);
    824 
    825   clang::CallExpr *RSSetObjectCall =
    826       new(C) clang::CallExpr(C,
    827                              RSSetObjectFP,
    828                              ArgList,
    829                              SetObjectFD->getCallResultType(),
    830                              clang::VK_RValue,
    831                              Loc);
    832 
    833   return RSSetObjectCall;
    834 }
    835 
    836 static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
    837                                             clang::Expr *LHS,
    838                                             clang::Expr *RHS,
    839                                             clang::SourceLocation StartLoc,
    840                                             clang::SourceLocation Loc);
    841 
    842 /*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
    843                                            clang::Expr *DstArr,
    844                                            clang::Expr *SrcArr,
    845                                            clang::SourceLocation StartLoc,
    846                                            clang::SourceLocation Loc) {
    847   clang::DeclContext *DC = NULL;
    848   const clang::Type *BaseType = DstArr->getType().getTypePtr();
    849   slangAssert(BaseType->isArrayType());
    850 
    851   int NumArrayElements = ArrayDim(BaseType);
    852   // Actually extract out the base RS object type for use later
    853   BaseType = BaseType->getArrayElementTypeNoTypeQual();
    854 
    855   clang::Stmt *StmtArray[2] = {NULL};
    856   int StmtCtr = 0;
    857 
    858   if (NumArrayElements <= 0) {
    859     return NULL;
    860   }
    861 
    862   // Create helper variable for iterating through elements
    863   clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
    864   clang::VarDecl *IIVD =
    865       clang::VarDecl::Create(C,
    866                              DC,
    867                              StartLoc,
    868                              Loc,
    869                              &II,
    870                              C.IntTy,
    871                              C.getTrivialTypeSourceInfo(C.IntTy),
    872                              clang::SC_None,
    873                              clang::SC_None);
    874   clang::Decl *IID = (clang::Decl *)IIVD;
    875 
    876   clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
    877   StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
    878 
    879   // Form the actual loop
    880   // for (Init; Cond; Inc)
    881   //   RSSetObjectCall;
    882 
    883   // Init -> "rsIntIter = 0"
    884   clang::DeclRefExpr *RefrsIntIter =
    885       clang::DeclRefExpr::Create(C,
    886                                  clang::NestedNameSpecifierLoc(),
    887                                  IIVD,
    888                                  Loc,
    889                                  C.IntTy,
    890                                  clang::VK_RValue,
    891                                  NULL);
    892 
    893   clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
    894       llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
    895 
    896   clang::BinaryOperator *Init =
    897       new(C) clang::BinaryOperator(RefrsIntIter,
    898                                    Int0,
    899                                    clang::BO_Assign,
    900                                    C.IntTy,
    901                                    clang::VK_RValue,
    902                                    clang::OK_Ordinary,
    903                                    Loc);
    904 
    905   // Cond -> "rsIntIter < NumArrayElements"
    906   clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
    907       llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
    908 
    909   clang::BinaryOperator *Cond =
    910       new(C) clang::BinaryOperator(RefrsIntIter,
    911                                    NumArrayElementsExpr,
    912                                    clang::BO_LT,
    913                                    C.IntTy,
    914                                    clang::VK_RValue,
    915                                    clang::OK_Ordinary,
    916                                    Loc);
    917 
    918   // Inc -> "rsIntIter++"
    919   clang::UnaryOperator *Inc =
    920       new(C) clang::UnaryOperator(RefrsIntIter,
    921                                   clang::UO_PostInc,
    922                                   C.IntTy,
    923                                   clang::VK_RValue,
    924                                   clang::OK_Ordinary,
    925                                   Loc);
    926 
    927   // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
    928   // Loop operates on individual array elements
    929 
    930   clang::Expr *DstArrPtr =
    931       clang::ImplicitCastExpr::Create(C,
    932           C.getPointerType(BaseType->getCanonicalTypeInternal()),
    933           clang::CK_ArrayToPointerDecay,
    934           DstArr,
    935           NULL,
    936           clang::VK_RValue);
    937 
    938   clang::Expr *DstArrPtrSubscript =
    939       new(C) clang::ArraySubscriptExpr(DstArrPtr,
    940                                        RefrsIntIter,
    941                                        BaseType->getCanonicalTypeInternal(),
    942                                        clang::VK_RValue,
    943                                        clang::OK_Ordinary,
    944                                        Loc);
    945 
    946   clang::Expr *SrcArrPtr =
    947       clang::ImplicitCastExpr::Create(C,
    948           C.getPointerType(BaseType->getCanonicalTypeInternal()),
    949           clang::CK_ArrayToPointerDecay,
    950           SrcArr,
    951           NULL,
    952           clang::VK_RValue);
    953 
    954   clang::Expr *SrcArrPtrSubscript =
    955       new(C) clang::ArraySubscriptExpr(SrcArrPtr,
    956                                        RefrsIntIter,
    957                                        BaseType->getCanonicalTypeInternal(),
    958                                        clang::VK_RValue,
    959                                        clang::OK_Ordinary,
    960                                        Loc);
    961 
    962   RSExportPrimitiveType::DataType DT =
    963       RSExportPrimitiveType::GetRSSpecificType(BaseType);
    964 
    965   clang::Stmt *RSSetObjectCall = NULL;
    966   if (BaseType->isArrayType()) {
    967     RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
    968                                              SrcArrPtrSubscript,
    969                                              StartLoc, Loc);
    970   } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
    971     RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
    972                                               SrcArrPtrSubscript,
    973                                               StartLoc, Loc);
    974   } else {
    975     RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
    976                                               SrcArrPtrSubscript,
    977                                               StartLoc, Loc);
    978   }
    979 
    980   clang::ForStmt *DestructorLoop =
    981       new(C) clang::ForStmt(C,
    982                             Init,
    983                             Cond,
    984                             NULL,  // no condVar
    985                             Inc,
    986                             RSSetObjectCall,
    987                             Loc,
    988                             Loc,
    989                             Loc);
    990 
    991   StmtArray[StmtCtr++] = DestructorLoop;
    992   slangAssert(StmtCtr == 2);
    993 
    994   clang::CompoundStmt *CS =
    995       new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
    996 
    997   return CS;
    998 } */
    999 
   1000 static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
   1001                                             clang::Expr *LHS,
   1002                                             clang::Expr *RHS,
   1003                                             clang::SourceLocation StartLoc,
   1004                                             clang::SourceLocation Loc) {
   1005   clang::QualType QT = LHS->getType();
   1006   const clang::Type *T = QT.getTypePtr();
   1007   slangAssert(T->isStructureType());
   1008   slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
   1009 
   1010   // Keep an extra slot for the original copy (memcpy)
   1011   unsigned FieldsToSet = CountRSObjectTypes(C, T, Loc) + 1;
   1012 
   1013   unsigned StmtCount = 0;
   1014   clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
   1015   for (unsigned i = 0; i < FieldsToSet; i++) {
   1016     StmtArray[i] = NULL;
   1017   }
   1018 
   1019   clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
   1020   RD = RD->getDefinition();
   1021   for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
   1022          FE = RD->field_end();
   1023        FI != FE;
   1024        FI++) {
   1025     bool IsArrayType = false;
   1026     clang::FieldDecl *FD = *FI;
   1027     const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
   1028     const clang::Type *OrigType = FT;
   1029 
   1030     if (!CountRSObjectTypes(C, FT, Loc)) {
   1031       // Skip to next if we don't have any viable RS object types
   1032       continue;
   1033     }
   1034 
   1035     clang::DeclAccessPair FoundDecl =
   1036         clang::DeclAccessPair::make(FD, clang::AS_none);
   1037     clang::MemberExpr *DstMember =
   1038         clang::MemberExpr::Create(C,
   1039                                   LHS,
   1040                                   false,
   1041                                   clang::NestedNameSpecifierLoc(),
   1042                                   clang::SourceLocation(),
   1043                                   FD,
   1044                                   FoundDecl,
   1045                                   clang::DeclarationNameInfo(),
   1046                                   NULL,
   1047                                   OrigType->getCanonicalTypeInternal(),
   1048                                   clang::VK_RValue,
   1049                                   clang::OK_Ordinary);
   1050 
   1051     clang::MemberExpr *SrcMember =
   1052         clang::MemberExpr::Create(C,
   1053                                   RHS,
   1054                                   false,
   1055                                   clang::NestedNameSpecifierLoc(),
   1056                                   clang::SourceLocation(),
   1057                                   FD,
   1058                                   FoundDecl,
   1059                                   clang::DeclarationNameInfo(),
   1060                                   NULL,
   1061                                   OrigType->getCanonicalTypeInternal(),
   1062                                   clang::VK_RValue,
   1063                                   clang::OK_Ordinary);
   1064 
   1065     if (FT->isArrayType()) {
   1066       FT = FT->getArrayElementTypeNoTypeQual();
   1067       IsArrayType = true;
   1068     }
   1069 
   1070     RSExportPrimitiveType::DataType DT =
   1071         RSExportPrimitiveType::GetRSSpecificType(FT);
   1072 
   1073     if (IsArrayType) {
   1074       clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
   1075       DiagEngine.Report(
   1076         clang::FullSourceLoc(Loc, C.getSourceManager()),
   1077         DiagEngine.getCustomDiagID(
   1078           clang::DiagnosticsEngine::Error,
   1079           "Arrays of RS object types within structures cannot be copied"));
   1080       // TODO(srhines): Support setting arrays of RS objects
   1081       // StmtArray[StmtCount++] =
   1082       //    CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
   1083     } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
   1084       StmtArray[StmtCount++] =
   1085           CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
   1086     } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
   1087       StmtArray[StmtCount++] =
   1088           CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
   1089     } else {
   1090       slangAssert(false);
   1091     }
   1092   }
   1093 
   1094   slangAssert(StmtCount < FieldsToSet);
   1095 
   1096   // We still need to actually do the overall struct copy. For simplicity,
   1097   // we just do a straight-up assignment (which will still preserve all
   1098   // the proper RS object reference counts).
   1099   clang::BinaryOperator *CopyStruct =
   1100       new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
   1101                                    clang::VK_RValue, clang::OK_Ordinary, Loc,
   1102                                    false);
   1103   StmtArray[StmtCount++] = CopyStruct;
   1104 
   1105   clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
   1106       C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
   1107 
   1108   delete [] StmtArray;
   1109 
   1110   return CS;
   1111 }
   1112 
   1113 }  // namespace
   1114 
   1115 void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
   1116     clang::BinaryOperator *AS) {
   1117 
   1118   clang::QualType QT = AS->getType();
   1119 
   1120   clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
   1121       RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
   1122 
   1123   clang::SourceLocation Loc = AS->getExprLoc();
   1124   clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
   1125   clang::Stmt *UpdatedStmt = NULL;
   1126 
   1127   if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
   1128     // By definition, this is a struct assignment if we get here
   1129     UpdatedStmt =
   1130         CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
   1131   } else {
   1132     UpdatedStmt =
   1133         CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
   1134   }
   1135 
   1136   RSASTReplace R(C);
   1137   R.ReplaceStmt(mCS, AS, UpdatedStmt);
   1138   return;
   1139 }
   1140 
   1141 void RSObjectRefCount::Scope::AppendRSObjectInit(
   1142     clang::VarDecl *VD,
   1143     clang::DeclStmt *DS,
   1144     RSExportPrimitiveType::DataType DT,
   1145     clang::Expr *InitExpr) {
   1146   slangAssert(VD);
   1147 
   1148   if (!InitExpr) {
   1149     return;
   1150   }
   1151 
   1152   clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
   1153       RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
   1154   clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
   1155       RSExportPrimitiveType::DataTypeRSFont)->getLocation();
   1156   clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
   1157       RSExportPrimitiveType::DataTypeRSFont)->getInnerLocStart();
   1158 
   1159   if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
   1160     const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1161     clang::DeclRefExpr *RefRSVar =
   1162         clang::DeclRefExpr::Create(C,
   1163                                    clang::NestedNameSpecifierLoc(),
   1164                                    clang::SourceLocation(),
   1165                                    VD,
   1166                                    false,
   1167                                    Loc,
   1168                                    T->getCanonicalTypeInternal(),
   1169                                    clang::VK_RValue,
   1170                                    NULL);
   1171 
   1172     clang::Stmt *RSSetObjectOps =
   1173         CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
   1174 
   1175     std::list<clang::Stmt*> StmtList;
   1176     StmtList.push_back(RSSetObjectOps);
   1177     AppendAfterStmt(C, mCS, DS, StmtList);
   1178     return;
   1179   }
   1180 
   1181   clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
   1182   slangAssert((SetObjectFD != NULL) &&
   1183               "rsSetObject doesn't cover all RS object types");
   1184 
   1185   clang::QualType SetObjectFDType = SetObjectFD->getType();
   1186   clang::QualType SetObjectFDArgType[2];
   1187   SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
   1188   SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
   1189 
   1190   clang::Expr *RefRSSetObjectFD =
   1191       clang::DeclRefExpr::Create(C,
   1192                                  clang::NestedNameSpecifierLoc(),
   1193                                  clang::SourceLocation(),
   1194                                  SetObjectFD,
   1195                                  false,
   1196                                  Loc,
   1197                                  SetObjectFDType,
   1198                                  clang::VK_RValue,
   1199                                  NULL);
   1200 
   1201   clang::Expr *RSSetObjectFP =
   1202       clang::ImplicitCastExpr::Create(C,
   1203                                       C.getPointerType(SetObjectFDType),
   1204                                       clang::CK_FunctionToPointerDecay,
   1205                                       RefRSSetObjectFD,
   1206                                       NULL,
   1207                                       clang::VK_RValue);
   1208 
   1209   const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1210   clang::DeclRefExpr *RefRSVar =
   1211       clang::DeclRefExpr::Create(C,
   1212                                  clang::NestedNameSpecifierLoc(),
   1213                                  clang::SourceLocation(),
   1214                                  VD,
   1215                                  false,
   1216                                  Loc,
   1217                                  T->getCanonicalTypeInternal(),
   1218                                  clang::VK_RValue,
   1219                                  NULL);
   1220 
   1221   llvm::SmallVector<clang::Expr*, 2> ArgList;
   1222   ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
   1223                                                 clang::UO_AddrOf,
   1224                                                 SetObjectFDArgType[0],
   1225                                                 clang::VK_RValue,
   1226                                                 clang::OK_Ordinary,
   1227                                                 Loc));
   1228   ArgList.push_back(InitExpr);
   1229 
   1230   clang::CallExpr *RSSetObjectCall =
   1231       new(C) clang::CallExpr(C,
   1232                              RSSetObjectFP,
   1233                              ArgList,
   1234                              SetObjectFD->getCallResultType(),
   1235                              clang::VK_RValue,
   1236                              Loc);
   1237 
   1238   std::list<clang::Stmt*> StmtList;
   1239   StmtList.push_back(RSSetObjectCall);
   1240   AppendAfterStmt(C, mCS, DS, StmtList);
   1241 
   1242   return;
   1243 }
   1244 
   1245 void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
   1246   for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
   1247           E = mRSO.end();
   1248         I != E;
   1249         I++) {
   1250     clang::VarDecl *VD = *I;
   1251     clang::Stmt *RSClearObjectCall = ClearRSObject(VD, VD->getDeclContext());
   1252     if (RSClearObjectCall) {
   1253       DestructorVisitor DV((*mRSO.begin())->getASTContext(),
   1254                            mCS,
   1255                            RSClearObjectCall,
   1256                            VD->getSourceRange().getBegin());
   1257       DV.Visit(mCS);
   1258       DV.InsertDestructors();
   1259     }
   1260   }
   1261   return;
   1262 }
   1263 
   1264 clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
   1265     clang::VarDecl *VD,
   1266     clang::DeclContext *DC) {
   1267   slangAssert(VD);
   1268   clang::ASTContext &C = VD->getASTContext();
   1269   clang::SourceLocation Loc = VD->getLocation();
   1270   clang::SourceLocation StartLoc = VD->getInnerLocStart();
   1271   const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1272 
   1273   // Reference expr to target RS object variable
   1274   clang::DeclRefExpr *RefRSVar =
   1275       clang::DeclRefExpr::Create(C,
   1276                                  clang::NestedNameSpecifierLoc(),
   1277                                  clang::SourceLocation(),
   1278                                  VD,
   1279                                  false,
   1280                                  Loc,
   1281                                  T->getCanonicalTypeInternal(),
   1282                                  clang::VK_RValue,
   1283                                  NULL);
   1284 
   1285   if (T->isArrayType()) {
   1286     return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
   1287   }
   1288 
   1289   RSExportPrimitiveType::DataType DT =
   1290       RSExportPrimitiveType::GetRSSpecificType(T);
   1291 
   1292   if (DT == RSExportPrimitiveType::DataTypeUnknown ||
   1293       DT == RSExportPrimitiveType::DataTypeIsStruct) {
   1294     return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
   1295   }
   1296 
   1297   slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
   1298               "Should be RS object");
   1299 
   1300   return ClearSingleRSObject(C, RefRSVar, Loc);
   1301 }
   1302 
   1303 bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
   1304                                           RSExportPrimitiveType::DataType *DT,
   1305                                           clang::Expr **InitExpr) {
   1306   slangAssert(VD && DT && InitExpr);
   1307   const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
   1308 
   1309   // Loop through array types to get to base type
   1310   while (T && T->isArrayType()) {
   1311     T = T->getArrayElementTypeNoTypeQual();
   1312   }
   1313 
   1314   bool DataTypeIsStructWithRSObject = false;
   1315   *DT = RSExportPrimitiveType::GetRSSpecificType(T);
   1316 
   1317   if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
   1318     if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
   1319       *DT = RSExportPrimitiveType::DataTypeIsStruct;
   1320       DataTypeIsStructWithRSObject = true;
   1321     } else {
   1322       return false;
   1323     }
   1324   }
   1325 
   1326   bool DataTypeIsRSObject = false;
   1327   if (DataTypeIsStructWithRSObject) {
   1328     DataTypeIsRSObject = true;
   1329   } else {
   1330     DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
   1331   }
   1332   *InitExpr = VD->getInit();
   1333 
   1334   if (!DataTypeIsRSObject && *InitExpr) {
   1335     // If we already have an initializer for a matrix type, we are done.
   1336     return DataTypeIsRSObject;
   1337   }
   1338 
   1339   clang::Expr *ZeroInitializer =
   1340       CreateZeroInitializerForRSSpecificType(*DT,
   1341                                              VD->getASTContext(),
   1342                                              VD->getLocation());
   1343 
   1344   if (ZeroInitializer) {
   1345     ZeroInitializer->setType(T->getCanonicalTypeInternal());
   1346     VD->setInit(ZeroInitializer);
   1347   }
   1348 
   1349   return DataTypeIsRSObject;
   1350 }
   1351 
   1352 clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
   1353     RSExportPrimitiveType::DataType DT,
   1354     clang::ASTContext &C,
   1355     const clang::SourceLocation &Loc) {
   1356   clang::Expr *Res = NULL;
   1357   switch (DT) {
   1358     case RSExportPrimitiveType::DataTypeIsStruct:
   1359     case RSExportPrimitiveType::DataTypeRSElement:
   1360     case RSExportPrimitiveType::DataTypeRSType:
   1361     case RSExportPrimitiveType::DataTypeRSAllocation:
   1362     case RSExportPrimitiveType::DataTypeRSSampler:
   1363     case RSExportPrimitiveType::DataTypeRSScript:
   1364     case RSExportPrimitiveType::DataTypeRSMesh:
   1365     case RSExportPrimitiveType::DataTypeRSPath:
   1366     case RSExportPrimitiveType::DataTypeRSProgramFragment:
   1367     case RSExportPrimitiveType::DataTypeRSProgramVertex:
   1368     case RSExportPrimitiveType::DataTypeRSProgramRaster:
   1369     case RSExportPrimitiveType::DataTypeRSProgramStore:
   1370     case RSExportPrimitiveType::DataTypeRSFont: {
   1371       //    (ImplicitCastExpr 'nullptr_t'
   1372       //      (IntegerLiteral 0)))
   1373       llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
   1374       clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
   1375       clang::Expr *CastToNull =
   1376           clang::ImplicitCastExpr::Create(C,
   1377                                           C.NullPtrTy,
   1378                                           clang::CK_IntegralToPointer,
   1379                                           Int0,
   1380                                           NULL,
   1381                                           clang::VK_RValue);
   1382 
   1383       llvm::SmallVector<clang::Expr*, 1>InitList;
   1384       InitList.push_back(CastToNull);
   1385 
   1386       Res = new(C) clang::InitListExpr(C, Loc, InitList, Loc);
   1387       break;
   1388     }
   1389     case RSExportPrimitiveType::DataTypeRSMatrix2x2:
   1390     case RSExportPrimitiveType::DataTypeRSMatrix3x3:
   1391     case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
   1392       // RS matrix is not completely an RS object. They hold data by themselves.
   1393       // (InitListExpr rs_matrix2x2
   1394       //   (InitListExpr float[4]
   1395       //     (FloatingLiteral 0)
   1396       //     (FloatingLiteral 0)
   1397       //     (FloatingLiteral 0)
   1398       //     (FloatingLiteral 0)))
   1399       clang::QualType FloatTy = C.FloatTy;
   1400       // Constructor sets value to 0.0f by default
   1401       llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
   1402       clang::FloatingLiteral *Float0Val =
   1403           clang::FloatingLiteral::Create(C,
   1404                                          Val,
   1405                                          /* isExact = */true,
   1406                                          FloatTy,
   1407                                          Loc);
   1408 
   1409       unsigned N = 0;
   1410       if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
   1411         N = 2;
   1412       else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
   1413         N = 3;
   1414       else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
   1415         N = 4;
   1416       unsigned N_2 = N * N;
   1417 
   1418       // Assume we are going to be allocating 16 elements, since 4x4 is max.
   1419       llvm::SmallVector<clang::Expr*, 16> InitVals;
   1420       for (unsigned i = 0; i < N_2; i++)
   1421         InitVals.push_back(Float0Val);
   1422       clang::Expr *InitExpr =
   1423           new(C) clang::InitListExpr(C, Loc, InitVals, Loc);
   1424       InitExpr->setType(C.getConstantArrayType(FloatTy,
   1425                                                llvm::APInt(32, N_2),
   1426                                                clang::ArrayType::Normal,
   1427                                                /* EltTypeQuals = */0));
   1428       llvm::SmallVector<clang::Expr*, 1> InitExprVec;
   1429       InitExprVec.push_back(InitExpr);
   1430 
   1431       Res = new(C) clang::InitListExpr(C, Loc, InitExprVec, Loc);
   1432       break;
   1433     }
   1434     case RSExportPrimitiveType::DataTypeUnknown:
   1435     case RSExportPrimitiveType::DataTypeFloat16:
   1436     case RSExportPrimitiveType::DataTypeFloat32:
   1437     case RSExportPrimitiveType::DataTypeFloat64:
   1438     case RSExportPrimitiveType::DataTypeSigned8:
   1439     case RSExportPrimitiveType::DataTypeSigned16:
   1440     case RSExportPrimitiveType::DataTypeSigned32:
   1441     case RSExportPrimitiveType::DataTypeSigned64:
   1442     case RSExportPrimitiveType::DataTypeUnsigned8:
   1443     case RSExportPrimitiveType::DataTypeUnsigned16:
   1444     case RSExportPrimitiveType::DataTypeUnsigned32:
   1445     case RSExportPrimitiveType::DataTypeUnsigned64:
   1446     case RSExportPrimitiveType::DataTypeBoolean:
   1447     case RSExportPrimitiveType::DataTypeUnsigned565:
   1448     case RSExportPrimitiveType::DataTypeUnsigned5551:
   1449     case RSExportPrimitiveType::DataTypeUnsigned4444:
   1450     case RSExportPrimitiveType::DataTypeMax: {
   1451       slangAssert(false && "Not RS object type!");
   1452     }
   1453     // No default case will enable compiler detecting the missing cases
   1454   }
   1455 
   1456   return Res;
   1457 }
   1458 
   1459 void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
   1460   for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
   1461        I != E;
   1462        I++) {
   1463     clang::Decl *D = *I;
   1464     if (D->getKind() == clang::Decl::Var) {
   1465       clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
   1466       RSExportPrimitiveType::DataType DT =
   1467           RSExportPrimitiveType::DataTypeUnknown;
   1468       clang::Expr *InitExpr = NULL;
   1469       if (InitializeRSObject(VD, &DT, &InitExpr)) {
   1470         // We need to zero-init all RS object types (including matrices), ...
   1471         getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
   1472         // ... but, only add to the list of RS objects if we have some
   1473         // non-matrix RS object fields.
   1474         if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(),
   1475                                VD->getLocation())) {
   1476           getCurrentScope()->addRSObject(VD);
   1477         }
   1478       }
   1479     }
   1480   }
   1481   return;
   1482 }
   1483 
   1484 void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
   1485   if (!CS->body_empty()) {
   1486     // Push a new scope
   1487     Scope *S = new Scope(CS);
   1488     mScopeStack.push(S);
   1489 
   1490     VisitStmt(CS);
   1491 
   1492     // Destroy the scope
   1493     slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
   1494     S->InsertLocalVarDestructors();
   1495     mScopeStack.pop();
   1496     delete S;
   1497   }
   1498   return;
   1499 }
   1500 
   1501 void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
   1502   clang::QualType QT = AS->getType();
   1503 
   1504   if (CountRSObjectTypes(mCtx, QT.getTypePtr(), AS->getExprLoc())) {
   1505     getCurrentScope()->ReplaceRSObjectAssignment(AS);
   1506   }
   1507 
   1508   return;
   1509 }
   1510 
   1511 void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
   1512   for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
   1513        I != E;
   1514        I++) {
   1515     if (clang::Stmt *Child = *I) {
   1516       Visit(Child);
   1517     }
   1518   }
   1519   return;
   1520 }
   1521 
   1522 // This function walks the list of global variables and (potentially) creates
   1523 // a single global static destructor function that properly decrements
   1524 // reference counts on the contained RS object types.
   1525 clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
   1526   Init();
   1527 
   1528   clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
   1529   clang::SourceLocation loc;
   1530 
   1531   llvm::StringRef SR(".rs.dtor");
   1532   clang::IdentifierInfo &II = mCtx.Idents.get(SR);
   1533   clang::DeclarationName N(&II);
   1534   clang::FunctionProtoType::ExtProtoInfo EPI;
   1535   clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
   1536       llvm::ArrayRef<clang::QualType>(), EPI);
   1537   clang::FunctionDecl *FD = NULL;
   1538 
   1539   // Generate rsClearObject() call chains for every global variable
   1540   // (whether static or extern).
   1541   std::list<clang::Stmt *> StmtList;
   1542   for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
   1543           E = DC->decls_end(); I != E; I++) {
   1544     clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
   1545     if (VD) {
   1546       if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(), loc)) {
   1547         if (!FD) {
   1548           // Only create FD if we are going to use it.
   1549           FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, NULL,
   1550                                            clang::SC_None);
   1551         }
   1552         // Make sure to create any helpers within the function's DeclContext,
   1553         // not the one associated with the global translation unit.
   1554         clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
   1555         StmtList.push_back(RSClearObjectCall);
   1556       }
   1557     }
   1558   }
   1559 
   1560   // Nothing needs to be destroyed, so don't emit a dtor.
   1561   if (StmtList.empty()) {
   1562     return NULL;
   1563   }
   1564 
   1565   clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
   1566 
   1567   FD->setBody(CS);
   1568 
   1569   return FD;
   1570 }
   1571 
   1572 }  // namespace slang
   1573