14b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines/*
24b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Copyright 2010, The Android Open Source Project
34b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
44b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
54b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * you may not use this file except in compliance with the License.
64b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * You may obtain a copy of the License at
74b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
84b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *     http://www.apache.org/licenses/LICENSE-2.0
94b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Unless required by applicable law or agreed to in writing, software
114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * See the License for the specific language governing permissions and
144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * limitations under the License.
154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines */
164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_object_ref_count.h"
184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/DeclGroup.h"
204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Expr.h"
21be27482cdeaf08576bc39b72a15d35d13014a636Logan#include "clang/AST/NestedNameSpecifier.h"
224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/OperationKinds.h"
23f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni#include "clang/AST/RecursiveASTVisitor.h"
244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Stmt.h"
254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h"
264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
276e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
288024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang.h"
29292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines#include "slang_rs_ast_replace.h"
304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
32e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
34474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet/* Even though those two arrays are of size DataTypeMax, only entries that
35474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet * correspond to object types will be set.
36474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet */
37474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouilletclang::FunctionDecl *
38cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc BrouilletRSObjectRefCount::RSSetObjectFD[DataTypeMax];
39474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouilletclang::FunctionDecl *
40cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc BrouilletRSObjectRefCount::RSClearObjectFD[DataTypeMax];
411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
42f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesvoid RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
43cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  for (unsigned i = 0; i < DataTypeMax; i++) {
445abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    RSSetObjectFD[i] = nullptr;
455abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    RSClearObjectFD[i] = nullptr;
461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = TUDecl->decls_end(); I != E; I++) {
521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((I->getKind() >= clang::Decl::firstFunction) &&
531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        (I->getKind() <= clang::Decl::lastFunction)) {
541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // points to RSSetObjectFD or RSClearObjectFD
571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl **RSObjectFD;
581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      if (FD->getName() == "rsSetObject") {
606e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 2) &&
616e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsSetObject function prototype (# params)");
621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
646e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 1) &&
656e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsClearObject function prototype (# params)");
661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSClearObjectFD;
67e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      } else {
681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        continue;
691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType PVT = PVD->getOriginalType();
731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The first parameter must be a pointer like rs_allocation*
746e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(PVT->isPointerType() &&
756e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines          "Invalid rs{Set,Clear}Object function prototype (pointer param)");
761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The rs object type passed to the FD
781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType RST = PVT->getPointeeType();
79cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      DataType DT = RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
806e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             && "must be RS object type");
821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
83cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      if (DT >= 0 && DT < DataTypeMax) {
84474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet          RSObjectFD[DT] = FD;
85474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      } else {
86474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet          slangAssert(false && "incorrect type");
87474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      }
881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
911bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
924464d825c11349068f2917f9ebee86b721423f3cStephen Hinesnamespace {
934464d825c11349068f2917f9ebee86b721423f3cStephen Hines
94b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niunsigned CountRSObjectTypes(const clang::Type *T);
95b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
96b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
97b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *DstExpr,
98b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *SrcExpr,
99b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation StartLoc,
100b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation Loc);
101b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
102292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// This function constructs a new CompoundStmt from the input StmtList.
103b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
104579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      std::vector<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
105d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  unsigned NewStmtCount = StmtList.size();
106292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  unsigned CompoundStmtCount = 0;
1071bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
108292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **CompoundStmtList;
109292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  CompoundStmtList = new clang::Stmt*[NewStmtCount];
1101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
111579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt*>::const_iterator I = StmtList.begin();
112579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt*>::const_iterator E = StmtList.end();
113292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; I != E; I++) {
114292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    CompoundStmtList[CompoundStmtCount++] = *I;
1151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
116292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CompoundStmtCount == NewStmtCount);
1171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
11823c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
11923c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);
1201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
121292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  delete [] CompoundStmtList;
1221bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
123292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return CS;
1241bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1251bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
126b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid AppendAfterStmt(clang::ASTContext &C,
127b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                     clang::CompoundStmt *CS,
128b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                     clang::Stmt *S,
129b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                     std::list<clang::Stmt*> &StmtList) {
130292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CS);
131e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
132292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::CompoundStmt::body_iterator bE = CS->body_end();
133292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **UpdatedStmtList =
134292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      new clang::Stmt*[CS->size() + StmtList.size()];
135e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
136e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned UpdatedStmtCount = 0;
137e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned Once = 0;
138292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; bI != bE; bI++) {
139292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
140292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // If we come across a return here, we don't have anything we can
141292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // reasonably replace. We should have already inserted our destructor
142292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // code in the proper spot, so we just clean up and return.
143292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      delete [] UpdatedStmtList;
144292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
145292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      return;
146e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    }
147e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
148292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
149c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
150292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if ((*bI == S) && !Once) {
151292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      Once++;
152292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
153292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator E = StmtList.end();
154292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      for ( ; I != E; I++) {
155292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines        UpdatedStmtList[UpdatedStmtCount++] = *I;
156292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      }
157292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    }
158c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
159292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(Once <= 1);
160c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
1615abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  // When S is nullptr, we are appending to the end of the CompoundStmt.
162292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (!S) {
163292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    slangAssert(Once == 0);
164292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
165292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator E = StmtList.end();
166292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    for ( ; I != E; I++) {
167292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *I;
168c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    }
169c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
170c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
17198cfae456bb1831336bce2b21979a04e2e31fed4Pirama Arumuga Nainar  CS->setStmts(C, llvm::makeArrayRef(UpdatedStmtList, UpdatedStmtCount));
172c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
173c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  delete [] UpdatedStmtList;
174c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
175c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
176b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// This class visits a compound statement and collects a list of all the exiting
177b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// statements, such as any return statement in any sub-block, and any
178b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// break/continue statement that would resume outside the current scope.
179b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// We do not handle the case for goto statements that leave a local scope.
1804464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
1814464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
182292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The loop depth of the currently visited node.
183292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mLoopDepth;
184292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
185292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The switch statement depth of the currently visited node.
186292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // Note that this is tracked separately from the loop depth because
187292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // SwitchStmt-contained ContinueStmt's should have destructors for the
188292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // corresponding loop scope.
189292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mSwitchDepth;
190292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
191b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Output of the visitor: the statements that should be replaced by compound
192b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // statements, each of which contains rsClearObject() calls followed by the
193b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // original statement.
194b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::vector<clang::Stmt*> mExitingStmts;
195a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines
1964464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
197b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  DestructorVisitor() : mLoopDepth(0), mSwitchDepth(0) {}
198292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
199b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  const std::vector<clang::Stmt*>& getExitingStmts() const {
200b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return mExitingStmts;
201292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
202292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
2034464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
204292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitBreakStmt(clang::BreakStmt *BS);
205292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitContinueStmt(clang::ContinueStmt *CS);
206292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitDoStmt(clang::DoStmt *DS);
207292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitForStmt(clang::ForStmt *FS);
208292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitReturnStmt(clang::ReturnStmt *RS);
209292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitSwitchStmt(clang::SwitchStmt *SS);
210292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitWhileStmt(clang::WhileStmt *WS);
2114464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
2124464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2134464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
21456916bec2734a6059e1d0f58959514c825c746f7Yang Ni  for (clang::Stmt* Child : S->children()) {
21556916bec2734a6059e1d0f58959514c825c746f7Yang Ni    if (Child) {
2164464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
2174464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
2184464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2194464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2204464d825c11349068f2917f9ebee86b721423f3cStephen Hines
221292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
222292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(BS);
223292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
224b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    mExitingStmts.push_back(BS);
225292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
226292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
227292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
228292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
229292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(CS);
230292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (mLoopDepth == 0) {
231292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    // Switch statements can have nested continues.
232b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    mExitingStmts.push_back(CS);
233292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
234292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
235292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
236292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
237292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
238292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(DS);
239292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
240292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
241292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
242292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
243292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
244292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(FS);
245292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
246292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
247292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
248292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
249b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  mExitingStmts.push_back(RS);
250292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
251292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
252292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
253292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth++;
254292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(SS);
255292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth--;
256292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
257292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
258292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
259292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
260292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(WS);
261292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
262292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
263292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
264f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::Expr *ClearSingleRSObject(clang::ASTContext &C,
265f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::Expr *RefRSVar,
266f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::SourceLocation Loc) {
267f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(RefRSVar);
268f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *T = RefRSVar->getType().getTypePtr();
269f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!T->isArrayType() &&
270f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should not be destroying arrays with this function");
271f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
272f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
2735abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((ClearObjectFD != nullptr) &&
274f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "rsClearObject doesn't cover all RS object types");
275f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
276f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
277f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDArgType =
278f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
279f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
280f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Example destructor for "rs_font localFont;"
281f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //
282f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // (CallExpr 'void'
283f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
284f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
285f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
286f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
287f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
288f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Get address of targeted RS object
289f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *AddrRefRSVar =
290f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
291f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  clang::UO_AddrOf,
292f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  ClearObjectFDArgType,
293be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
294be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
295f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  Loc);
296f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
297f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSClearObjectFD =
298f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclRefExpr::Create(C,
299be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
3000444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
301f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD,
302e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
303f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getLocation(),
304be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 ClearObjectFDType,
305be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
3065abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
307f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
308f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RSClearObjectFP =
309f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::ImplicitCastExpr::Create(C,
310f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      C.getPointerType(ClearObjectFDType),
311f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::CK_FunctionToPointerDecay,
312f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      RefRSClearObjectFD,
3135abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
314f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::VK_RValue);
31503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
3161dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 1> ArgList;
3171dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(AddrRefRSVar);
3181dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines
319f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CallExpr *RSClearObjectCall =
320f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CallExpr(C,
321f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             RSClearObjectFP,
3221dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                             ArgList,
323f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             ClearObjectFD->getCallResultType(),
324be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
325f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             Loc);
326f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
327f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSClearObjectCall;
328f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
329f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
330f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic int ArrayDim(const clang::Type *T) {
33103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
33203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
33303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
33403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
33503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
33603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
3379d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
33803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
33903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
340b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *ClearStructRSObject(
341f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
342f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
343f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
344d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::SourceLocation StartLoc,
345f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc);
346f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
347b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *ClearArrayRSObject(
348f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
349f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
350f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSArr,
351cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    clang::SourceLocation StartLoc,
352f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
353f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
354f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(BaseType->isArrayType());
355f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
356f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  int NumArrayElements = ArrayDim(BaseType);
357f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Actually extract out the base RS object type for use later
358f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
35903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
36003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
3615abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
36203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
36303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
36403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
36503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
366cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // (ForStmt
367cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (DeclStmt
368cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (VarDecl used rsIntIter 'int' cinit
369cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (IntegerLiteral 'int' 0)))
370cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (BinaryOperator 'int' '<'
371cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (ImplicitCastExpr int LValueToRValue
37203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
373cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (IntegerLiteral 'int' 10)
374cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   nullptr << CondVar >>
375cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (UnaryOperator 'int' postfix '++'
376cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (DeclRefExpr 'int' Var='rsIntIter'))
377cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (CallExpr 'void'
378cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
379cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
380cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (UnaryOperator 'rs_font *' prefix '&'
381cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (ArraySubscriptExpr 'rs_font':'rs_font'
382cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //         (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
383cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //           (DeclRefExpr 'rs_font [10]' Var='fontArr'))
384cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //         (DeclRefExpr 'int' Var='rsIntIter'))))))
38503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
387cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  static unsigned sIterCounter = 0;
388cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  std::stringstream UniqueIterName;
389cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  UniqueIterName << "rsIntIter" << sIterCounter++;
390cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::IdentifierInfo *II = &C.Idents.get(UniqueIterName.str());
39103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
39203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
393f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             DC,
394cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                             StartLoc,
39503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
396cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                             II,
39703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
39803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
39903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
400cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar  // Mark "rsIntIter" as used
401cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar  IIVD->markUsed(C);
40203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
40403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
40503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
40603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
407cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // Init -> "int rsIntIter = 0"
408cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
409cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
410cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  IIVD->setInit(Int0);
411cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines
412cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
413cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
414cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Stmt *Init = new(C) clang::DeclStmt(DGR, Loc, Loc);
415cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines
416cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // Cond -> "rsIntIter < NumArrayElements"
417cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::DeclRefExpr *RefrsIntIterLValue =
41803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
419be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
4200444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
42103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
422e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
42303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
424be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
425cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                 clang::VK_LValue,
4265abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
42703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
428cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Expr *RefrsIntIterRValue =
429cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      clang::ImplicitCastExpr::Create(C,
430cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      RefrsIntIterLValue->getType(),
431cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      clang::CK_LValueToRValue,
432cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      RefrsIntIterLValue,
433cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      nullptr,
434cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      clang::VK_RValue);
43503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
43703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
43803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
440cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      new(C) clang::BinaryOperator(RefrsIntIterRValue,
44103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
44203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
44303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
444be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
445be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
44623c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   Loc,
44723c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   false);
44803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
44903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
45003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
451cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      new(C) clang::UnaryOperator(RefrsIntIterLValue,
45203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
45303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
454be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
455be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
45603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
45703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
45803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
45903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
46003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
461f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtr =
46203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
463f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
46403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
465f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          RefRSArr,
4665abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
46703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
46803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
469f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtrSubscript =
470f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
471cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                       RefrsIntIterRValue,
472f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       BaseType->getCanonicalTypeInternal(),
473be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
474be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
475f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       Loc);
47603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
477cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
478f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
4795abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *RSClearObjectCall = nullptr;
480f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (BaseType->isArrayType()) {
481f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
482cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
483cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  } else if (DT == DataTypeUnknown) {
484f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
485cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
486f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
487f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
488f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
48903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
49003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
49103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
49203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
49303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
4945abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                            nullptr,  // no condVar
49503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
49603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
49703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
49803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
49903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
50003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
501cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  return DestructorLoop;
50203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
50303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
504b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niunsigned CountRSObjectTypes(const clang::Type *T) {
505f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(T);
506f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned RSObjectCount = 0;
507f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
508f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
50965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
510f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
511f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
512cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
513cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT != DataTypeUnknown) {
514f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
515f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
516f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
517d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  if (T->isUnionType()) {
518d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
519d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RD = RD->getDefinition();
520d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
521d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines           FE = RD->field_end();
522d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines         FI != FE;
523d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines         FI++) {
524d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      const clang::FieldDecl *FD = *FI;
525d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
52665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      if (CountRSObjectTypes(FT)) {
52778e69cb06b9b0683b2ac9dcafde87b867690ef2fStephen Hines        slangAssert(false && "can't have unions with RS object types!");
528d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        return 0;
529d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      }
530d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    }
531d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  }
532d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines
533f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (!T->isStructureType()) {
534f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return 0;
535f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
536f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
537f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
538f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
539f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
540f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
541f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
542f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
543f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::FieldDecl *FD = *FI;
544f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
54565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (CountRSObjectTypes(FT)) {
546f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // Sub-structs should only count once (as should arrays, etc.)
547f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSObjectCount++;
548f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
549f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
550f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
551f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSObjectCount;
552f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
553f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
554b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *ClearStructRSObject(
555f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
556f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
557f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
558cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    clang::SourceLocation StartLoc,
559f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
560f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
561f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
562f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!BaseType->isArrayType());
563f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
564f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Structs should show up as unknown primitive types
5659be9360d8e02b52ed669afbd69f9becb575c3f0dAlex Sakhartchouk  slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
566cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet              DataTypeUnknown);
567f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
56865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
569b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines  slangAssert(FieldsToDestroy != 0);
570f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
571f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned StmtCount = 0;
572f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
5732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToDestroy; i++) {
5745abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    StmtArray[i] = nullptr;
5752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
576f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
577f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Populate StmtArray by creating a destructor for each RS object field
578f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
579f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
580f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
581f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
582f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
583f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
584f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // We just look through all field declarations to see if we find a
585f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // declaration for an RS object type (or an array of one).
586f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    bool IsArrayType = false;
587f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::FieldDecl *FD = *FI;
588f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
589f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *OrigType = FT;
590f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    while (FT && FT->isArrayType()) {
591f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
592f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      IsArrayType = true;
593f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
594f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
595cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    // Pass a DeclarationNameInfo with a valid DeclName, since name equality
596cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    // gets asserted during CodeGen.
597cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    clang::DeclarationNameInfo FDDeclNameInfo(FD->getDeclName(),
598cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar                                              FD->getLocation());
599cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar
600f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
601f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
602f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
603f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
604f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
605f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
606f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
6070b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                    clang::SourceLocation(),
608be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
6090444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                    clang::SourceLocation(),
610f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
611f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
612cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar                                    FDDeclNameInfo,
6135abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                    nullptr,
614be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
615be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
616be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
617f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
618f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      slangAssert(StmtCount < FieldsToDestroy);
619f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
620f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
621f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
622f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
623f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
624cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                    StartLoc,
625f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
626f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
627f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearSingleRSObject(C,
628f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
629f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
630f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
63165f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
632f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // In this case, we have a nested struct. We may not end up filling all
633f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // of the spaces in StmtArray (sub-structs should handle themselves
634f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // with separate compound statements).
635f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
636f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
637f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
638f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
639f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
640f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
6410b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                    clang::SourceLocation(),
642be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
6430444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                    clang::SourceLocation(),
644f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
645f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
646f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
6475abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                    nullptr,
648be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
649be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
650be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
651f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
652f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
653f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
654f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
655f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
656cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                    StartLoc,
657f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
658f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
659f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearStructRSObject(C,
660f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     DC,
661f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
662cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                     StartLoc,
663f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
664f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
665f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
666f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
667f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
668f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(StmtCount > 0);
66923c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
67023c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
671f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
672f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  delete [] StmtArray;
673f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
674f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return CS;
675f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
676f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
677b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
678b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *DstExpr,
679b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *SrcExpr,
680b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation StartLoc,
681b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation Loc) {
6822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = DstExpr->getType().getTypePtr();
6832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
6845abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((SetObjectFD != nullptr) &&
6856e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
686c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
687c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
688c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
689c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
690c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
691c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
692c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
693c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
694be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
6950444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
696c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
697e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
698c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
699be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
700be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
7015abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
702c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
703c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
704c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
705c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
706c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
707c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
7085abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
709c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
710c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
7111dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 2> ArgList;
7121dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
7131dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::UO_AddrOf,
7141dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                SetObjectFDArgType[0],
7151dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::VK_RValue,
7161dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::OK_Ordinary,
7171dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                Loc));
7181dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(SrcExpr);
719c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
720c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CallExpr *RSSetObjectCall =
721c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      new(C) clang::CallExpr(C,
722c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             RSSetObjectFP,
723c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             ArgList,
724c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             SetObjectFD->getCallResultType(),
725be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
726c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             Loc);
727c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
7282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return RSSetObjectCall;
7292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
7302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
731b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
732b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *LHS,
733b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *RHS,
734b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation StartLoc,
735b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation Loc);
7362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
737246fa17206bf78c59a64b2f7d98a6716d5345b81Al Sutton/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
7382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *DstArr,
7392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *SrcArr,
740cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                           clang::SourceLocation StartLoc,
7412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::SourceLocation Loc) {
7425abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::DeclContext *DC = nullptr;
7432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *BaseType = DstArr->getType().getTypePtr();
7442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(BaseType->isArrayType());
7452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int NumArrayElements = ArrayDim(BaseType);
7472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Actually extract out the base RS object type for use later
7482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
7492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7505abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *StmtArray[2] = {nullptr};
7512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int StmtCtr = 0;
7522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (NumArrayElements <= 0) {
7545abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
7552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
7562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Create helper variable for iterating through elements
7582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
7592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::VarDecl *IIVD =
7602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::VarDecl::Create(C,
7612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             DC,
762cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                             StartLoc,
7632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             Loc,
7642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             &II,
7652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.IntTy,
7662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
7672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None,
7682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None);
7692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
7702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
7722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
7732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Form the actual loop
7752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // for (Init; Cond; Inc)
7762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  //   RSSetObjectCall;
7772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Init -> "rsIntIter = 0"
7792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
7802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::DeclRefExpr::Create(C,
781be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
7822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 IIVD,
7832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 Loc,
784be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
785be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
7865abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
7872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
7892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
7902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Init =
7922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
7932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Int0,
7942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_Assign,
7952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
796be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
797be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
7982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
7992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
8012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
8022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
8032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Cond =
8052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
8062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   NumArrayElementsExpr,
8072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_LT,
8082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
809be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
810be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
8112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
8122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Inc -> "rsIntIter++"
8142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::UnaryOperator *Inc =
8152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
8162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::UO_PostInc,
8172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  C.IntTy,
818be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
819be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
8202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  Loc);
8212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
8232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Loop operates on individual array elements
8242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtr =
8262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
8272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
8282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
8292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          DstArr,
8305abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
8312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
8322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtrSubscript =
8342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(DstArrPtr,
8352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
8362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
837be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
838be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
8392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
8402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtr =
8422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
8432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
8442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
8452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          SrcArr,
8465abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
8472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
8482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtrSubscript =
8502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(SrcArrPtr,
8512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
8522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
853be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
854be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
8552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
8562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
857cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
8582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8595abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *RSSetObjectCall = nullptr;
8602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (BaseType->isArrayType()) {
861d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
862cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                             SrcArrPtrSubscript,
863cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                             StartLoc, Loc);
864cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  } else if (DT == DataTypeUnknown) {
865d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
866cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              SrcArrPtrSubscript,
867cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              StartLoc, Loc);
8682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
869d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
870cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              SrcArrPtrSubscript,
871cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              StartLoc, Loc);
8722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
8732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ForStmt *DestructorLoop =
8752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ForStmt(C,
8762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Init,
8772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Cond,
8785abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                            nullptr,  // no condVar
8792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Inc,
8802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            RSSetObjectCall,
8812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
8822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
8832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc);
8842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
8862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(StmtCtr == 2);
8872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::CompoundStmt *CS =
8892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
8902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
892246fa17206bf78c59a64b2f7d98a6716d5345b81Al Sutton} */
8932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
894b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
895b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *LHS,
896b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *RHS,
897b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation StartLoc,
898b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation Loc) {
8992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = LHS->getType();
9002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = QT.getTypePtr();
9012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(T->isStructureType());
9022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
9032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Keep an extra slot for the original copy (memcpy)
90565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
9062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned StmtCount = 0;
9082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
9092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToSet; i++) {
9105abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    StmtArray[i] = nullptr;
9112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
9122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
9142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  RD = RD->getDefinition();
9152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
9162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines         FE = RD->field_end();
9172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI != FE;
9182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI++) {
9192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    bool IsArrayType = false;
9202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::FieldDecl *FD = *FI;
9212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
9222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *OrigType = FT;
9232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
92465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (!CountRSObjectTypes(FT)) {
9252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // Skip to next if we don't have any viable RS object types
9262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      continue;
9272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::DeclAccessPair FoundDecl =
9302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::DeclAccessPair::make(FD, clang::AS_none);
9312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *DstMember =
9322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
9332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  LHS,
9342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
9350b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                  clang::SourceLocation(),
936be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
9370444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                  clang::SourceLocation(),
9382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
9392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
940c9344ace5050b7d5ee9a677ce996fc0b731c0830I-Jui (Ray) Sung                                  clang::DeclarationNameInfo(
941c9344ace5050b7d5ee9a677ce996fc0b731c0830I-Jui (Ray) Sung                                      FD->getDeclName(),
942c9344ace5050b7d5ee9a677ce996fc0b731c0830I-Jui (Ray) Sung                                      clang::SourceLocation()),
9435abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                  nullptr,
944be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
945be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
946be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
9472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *SrcMember =
9492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
9502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  RHS,
9512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
9520b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                  clang::SourceLocation(),
953be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
9540444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                  clang::SourceLocation(),
9552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
9562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
957824b3ce35d55cc8b1f7f33874d22d328e05bd497I-Jui (Ray) Sung                                  clang::DeclarationNameInfo(
958824b3ce35d55cc8b1f7f33874d22d328e05bd497I-Jui (Ray) Sung                                      FD->getDeclName(),
959824b3ce35d55cc8b1f7f33874d22d328e05bd497I-Jui (Ray) Sung                                      clang::SourceLocation()),
9605abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                  nullptr,
961be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
962be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
963be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
9642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (FT->isArrayType()) {
9662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
9672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      IsArrayType = true;
9682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
970cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    DataType DT = RSExportPrimitiveType::GetRSSpecificType(FT);
9712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (IsArrayType) {
9739207a2e495c8363606861e4f034504ec5c153dabLogan Chien      clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
9749207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine.Report(
9759207a2e495c8363606861e4f034504ec5c153dabLogan Chien        clang::FullSourceLoc(Loc, C.getSourceManager()),
9769207a2e495c8363606861e4f034504ec5c153dabLogan Chien        DiagEngine.getCustomDiagID(
9779207a2e495c8363606861e4f034504ec5c153dabLogan Chien          clang::DiagnosticsEngine::Error,
9789207a2e495c8363606861e4f034504ec5c153dabLogan Chien          "Arrays of RS object types within structures cannot be copied"));
9792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // TODO(srhines): Support setting arrays of RS objects
9802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // StmtArray[StmtCount++] =
981d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      //    CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
982cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    } else if (DT == DataTypeUnknown) {
9832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
984d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines          CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
9852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
9862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
987d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines          CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
9882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else {
9892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      slangAssert(false);
9902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
9922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
993b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines  slangAssert(StmtCount < FieldsToSet);
9942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // We still need to actually do the overall struct copy. For simplicity,
9962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // we just do a straight-up assignment (which will still preserve all
9972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // the proper RS object reference counts).
9982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *CopyStruct =
999be27482cdeaf08576bc39b72a15d35d13014a636Logan      new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
100023c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   clang::VK_RValue, clang::OK_Ordinary, Loc,
100123c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   false);
10022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCount++] = CopyStruct;
10032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
100423c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
100523c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
10062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  delete [] StmtArray;
10082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
10102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
10112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}  // namespace
10132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
1014b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::Scope::InsertStmt(const clang::ASTContext &C,
1015b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                         clang::Stmt *NewStmt) {
1016b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::vector<clang::Stmt*> newBody;
1017b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (clang::Stmt* S1 : mCS->body()) {
1018b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (S1 == mCurrent) {
1019b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      newBody.push_back(NewStmt);
1020b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1021b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    newBody.push_back(S1);
1022b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
102398cfae456bb1831336bce2b21979a04e2e31fed4Pirama Arumuga Nainar  mCS->setStmts(C, newBody);
1024b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1025b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1026b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::Scope::ReplaceStmt(const clang::ASTContext &C,
1027b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                          clang::Stmt *NewStmt) {
1028b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::vector<clang::Stmt*> newBody;
1029b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (clang::Stmt* S1 : mCS->body()) {
1030b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (S1 == mCurrent) {
1031b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      newBody.push_back(NewStmt);
1032b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    } else {
1033b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      newBody.push_back(S1);
1034b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1035b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
103698cfae456bb1831336bce2b21979a04e2e31fed4Pirama Arumuga Nainar  mCS->setStmts(C, newBody);
1037b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1038b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1039b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::Scope::ReplaceExpr(const clang::ASTContext& C,
1040b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                          clang::Expr* OldExpr,
1041b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                          clang::Expr* NewExpr) {
1042b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  RSASTReplace R(C);
1043b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  R.ReplaceStmt(mCurrent, OldExpr, NewExpr);
1044b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1045b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
10462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesvoid RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
1047d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::BinaryOperator *AS) {
10482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = AS->getType();
10502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
10529ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getASTContext();
10532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
1054832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines  clang::SourceLocation Loc = AS->getExprLoc();
10559f1d0aa55669b75a718ad2e962fc8c3d8df1a5f4Stephen Hines  clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
10565abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *UpdatedStmt = nullptr;
10572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
10592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    // By definition, this is a struct assignment if we get here
10602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
1061d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
10622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
10632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
1064d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
10652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
1066e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1067292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  RSASTReplace R(C);
1068292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  R.ReplaceStmt(mCS, AS, UpdatedStmt);
1069e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
1070e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1071e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesvoid RSObjectRefCount::Scope::AppendRSObjectInit(
1072e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::VarDecl *VD,
1073e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::DeclStmt *DS,
1074cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    DataType DT,
1075e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::Expr *InitExpr) {
10766e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD);
1077e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1078e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!InitExpr) {
1079e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return;
1080e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1081e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1082a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
10839ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getASTContext();
1084a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
10859ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getLocation();
1086cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao  clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
10879ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getInnerLocStart();
1088a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1089cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT == DataTypeIsStruct) {
1090a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1091a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::DeclRefExpr *RefRSVar =
1092a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines        clang::DeclRefExpr::Create(C,
1093be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::NestedNameSpecifierLoc(),
10940444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                   clang::SourceLocation(),
1095a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   VD,
1096e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                   false,
1097a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   Loc,
1098be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   T->getCanonicalTypeInternal(),
1099be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
11005abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                   nullptr);
1101a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1102a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::Stmt *RSSetObjectOps =
1103d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
1104cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // Fix for b/37363420; consider:
1105cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //
1106cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // struct foo { rs_matrix m; };
1107cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // void bar() {
1108cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //   struct foo M = {...};
1109cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // }
1110cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //
1111cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // slang modifies that declaration with initialization to a
1112cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // declaration plus an assignment of the initialization values.
1113cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //
1114cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // void bar() {
1115cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //   struct foo M = {};
1116cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //   M = {...}; // by CreateStructRSSetObject() above
1117cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // }
1118cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //
1119cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // the slang-generated statement (M = {...}) is a use of M, and we
1120cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // need to mark M (clang::VarDecl *VD) as used.
1121cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    VD->markUsed(C);
1122a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1123292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*> StmtList;
1124292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    StmtList.push_back(RSSetObjectOps);
1125292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    AppendAfterStmt(C, mCS, DS, StmtList);
1126f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return;
1127f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1128f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
1129f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
11305abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((SetObjectFD != nullptr) &&
11316e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
1132e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1133e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
1134e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDArgType[2];
1135e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1136e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1137e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1138e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RefRSSetObjectFD =
1139e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1140be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
11410444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
1142e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD,
1143e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
1144e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1145be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
1146be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
11475abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
1148e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1149e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RSSetObjectFP =
1150e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::ImplicitCastExpr::Create(C,
1151e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      C.getPointerType(SetObjectFDType),
1152e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::CK_FunctionToPointerDecay,
1153e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      RefRSSetObjectFD,
11545abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
1155e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::VK_RValue);
1156e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1157e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1158e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::DeclRefExpr *RefRSVar =
1159e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1160be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
11610444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
1162e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD,
1163e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
1164e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1165be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1166be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
11675abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
1168e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
11691dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 2> ArgList;
11701dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
11711dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::UO_AddrOf,
11721dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                SetObjectFDArgType[0],
11731dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::VK_RValue,
11741dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::OK_Ordinary,
11751dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                Loc));
11761dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(InitExpr);
1177e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1178e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CallExpr *RSSetObjectCall =
1179e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      new(C) clang::CallExpr(C,
1180e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             RSSetObjectFP,
1181e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             ArgList,
1182e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             SetObjectFD->getCallResultType(),
1183be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
1184e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             Loc);
1185e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1186292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*> StmtList;
1187292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  StmtList.push_back(RSSetObjectCall);
1188292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  AppendAfterStmt(C, mCS, DS, StmtList);
1189c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
1190c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
11911bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
1192b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  if (mRSO.empty()) {
1193b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return;
1194b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1195b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1196b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::DeclContext* DC = mRSO.front()->getDeclContext();
1197b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::ASTContext& C = DC->getParentASTContext();
1198b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::SourceManager& SM = C.getSourceManager();
1199b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1200b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  const auto& OccursBefore = [&SM] (clang::SourceLocation L1, clang::SourceLocation L2)->bool {
1201b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return SM.isBeforeInTranslationUnit(L1, L2);
1202b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  };
1203b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  typedef std::map<clang::SourceLocation, clang::Stmt*, decltype(OccursBefore)> DMap;
1204b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1205b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  DMap dtors(OccursBefore);
1206b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1207b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Create rsClearObject calls. Note the DMap entries are sorted by the SourceLocation.
1208b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (clang::VarDecl* VD : mRSO) {
1209b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    clang::SourceLocation Loc = VD->getSourceRange().getBegin();
1210b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    clang::Stmt* RSClearObjectCall = ClearRSObject(VD, DC);
1211b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    dtors.insert(std::make_pair(Loc, RSClearObjectCall));
1212b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1213b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1214b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  DestructorVisitor Visitor;
1215b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  Visitor.Visit(mCS);
1216b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1217b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Replace each exiting statement with a block that contains the original statement
1218b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // and added rsClearObject() calls before it.
1219b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (clang::Stmt* S : Visitor.getExitingStmts()) {
1220b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1221b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::SourceLocation currentLoc = S->getLocStart();
1222b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1223b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    DMap::iterator firstDtorIter = dtors.begin();
1224b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    DMap::iterator currentDtorIter = firstDtorIter;
1225b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    DMap::iterator lastDtorIter = dtors.end();
1226b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1227b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    while (currentDtorIter != lastDtorIter &&
1228b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni           OccursBefore(currentDtorIter->first, currentLoc)) {
1229b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      currentDtorIter++;
12301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
1231b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1232b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (currentDtorIter == firstDtorIter) {
1233b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      continue;
1234b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1235b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1236579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    std::vector<clang::Stmt*> Stmts;
1237b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1238b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    // Insert rsClearObject() calls for all rsObjects declared before the current statement
1239b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    for(DMap::iterator it = firstDtorIter; it != currentDtorIter; it++) {
1240b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Stmts.push_back(it->second);
1241b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1242b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    Stmts.push_back(S);
1243b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1244b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    RSASTReplace R(C);
1245b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    clang::CompoundStmt* CS = BuildCompoundStmt(C, Stmts, S->getLocEnd());
1246b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    R.ReplaceStmt(mCS, S, CS);
12471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1248b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1249b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::list<clang::Stmt*> Stmts;
1250b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for(auto LocCallPair : dtors) {
1251b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    Stmts.push_back(LocCallPair.second);
1252b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1253b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  AppendAfterStmt(C, mCS, nullptr, Stmts);
12541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
12551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
12563f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
12573f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines    clang::VarDecl *VD,
12583f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines    clang::DeclContext *DC) {
1259f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(VD);
12601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
12611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
1262cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao  clang::SourceLocation StartLoc = VD->getInnerLocStart();
12631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
126403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
12651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
12661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
12671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
1268be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
12690444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
12701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
1271e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
12721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
1273be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1274be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
12755abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
12761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1277f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
1278cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
1279f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
12801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1281cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
12821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1283cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT == DataTypeUnknown ||
1284cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      DT == DataTypeIsStruct) {
1285cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
1286f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
12871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1288f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1289f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should be RS object");
12901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1291f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return ClearSingleRSObject(C, RefRSVar, Loc);
12921bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
12931bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1294e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1295cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet                                          DataType *DT,
1296e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          clang::Expr **InitExpr) {
12976e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD && DT && InitExpr);
12984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
12992d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
13002d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
13012d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
13022d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
13032d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
13042d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
1305f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsStructWithRSObject = false;
1306e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
13074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1308cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (*DT == DataTypeUnknown) {
1309feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1310cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      *DT = DataTypeIsStruct;
1311f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DataTypeIsStructWithRSObject = true;
1312feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    } else {
1313feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      return false;
1314feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    }
13152d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
13164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1317f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsRSObject = false;
1318f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DataTypeIsStructWithRSObject) {
1319f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = true;
1320f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
1321f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1322f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1323e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *InitExpr = VD->getInit();
1324e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1325e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!DataTypeIsRSObject && *InitExpr) {
1326e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    // If we already have an initializer for a matrix type, we are done.
1327e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return DataTypeIsRSObject;
13284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
13294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1330e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ZeroInitializer =
1331d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines      CreateEmptyInitListExpr(VD->getASTContext(), VD->getLocation());
1332e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1333e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (ZeroInitializer) {
1334e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    ZeroInitializer->setType(T->getCanonicalTypeInternal());
1335e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    VD->setInit(ZeroInitializer);
1336e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1337e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1338e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return DataTypeIsRSObject;
13394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
13404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1341d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hinesclang::Expr *RSObjectRefCount::CreateEmptyInitListExpr(
13424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
13434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
13444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1345d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  // We can cheaply construct a zero initializer by just creating an empty
1346d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  // initializer list. Clang supports this extension to C(99), and will create
1347d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  // any necessary constructs to zero out the entire variable.
1348d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  llvm::SmallVector<clang::Expr*, 1> EmptyInitList;
1349d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  return new(C) clang::InitListExpr(C, Loc, EmptyInitList, Loc);
13504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
13514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1352579e4f481774275980d6e3fbb7978c674da6d302Yang Niclang::DeclRefExpr *RSObjectRefCount::CreateGuard(clang::ASTContext &C,
1353579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                                  clang::DeclContext *DC,
1354579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                                  clang::Expr *E,
1355579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                                  const llvm::Twine &VarName,
1356579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                                  std::vector<clang::Stmt*> &NewStmts) {
1357579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::SourceLocation Loc = E->getLocStart();
1358579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  const clang::QualType Ty = E->getType();
1359579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::VarDecl* TmpDecl = clang::VarDecl::Create(
13605767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      C,                                     // AST context
13615767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      DC,                                    // Decl context
13625767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      Loc,                                   // Start location
13635767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      Loc,                                   // Id location
1364579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      &C.Idents.get(VarName.str()),          // Id
1365579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      Ty,                                    // Type
1366579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      C.getTrivialTypeSourceInfo(Ty),        // Type info
13675767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::SC_None                         // Storage class
13685767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  );
1369579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  const clang::Type *T = Ty.getTypePtr();
13705767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  clang::Expr *ZeroInitializer =
1371d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines      RSObjectRefCount::CreateEmptyInitListExpr(C, Loc);
13725767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  ZeroInitializer->setType(T->getCanonicalTypeInternal());
1373579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  TmpDecl->setInit(ZeroInitializer);
1374579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  TmpDecl->markUsed(C);
1375579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::Decl* Decls[] = { TmpDecl };
13765767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
13775767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      C, Decls, sizeof(Decls) / sizeof(*Decls));
13785767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  clang::DeclStmt* DS = new (C) clang::DeclStmt(DGR, Loc, Loc);
13795767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  NewStmts.push_back(DS);
13805767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni
13815767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
13825767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      C,
13835767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::NestedNameSpecifierLoc(),       // QualifierLoc
13845767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      Loc,                                   // TemplateKWLoc
1385579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      TmpDecl,
13865767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      false,                                 // RefersToEnclosingVariableOrCapture
13875767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      Loc,                                   // NameLoc
1388579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      Ty,
13895767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::VK_LValue
13905767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  );
1391579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1392579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::Stmt *UpdatedStmt = nullptr;
1393f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  if (CountRSObjectTypes(Ty.getTypePtr()) == 0) {
1394f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni    // The expression E is not an RS object itself. Instead of calling
1395f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni    // rsSetObject(), create an assignment statement to set the value of the
1396f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni    // temporary "guard" variable to the expression.
1397f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni    // This can happen if called from RSObjectRefCount::VisitReturnStmt(),
1398f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni    // when the return expression is not an RS object but references one.
1399f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni    UpdatedStmt =
1400f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni      new(C) clang::BinaryOperator(DRE, E, clang::BO_Assign, Ty,
1401f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni                                   clang::VK_RValue, clang::OK_Ordinary, Loc,
1402f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni                                   false);
1403f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni
1404f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  } else if (!RSExportPrimitiveType::IsRSObjectType(Ty.getTypePtr())) {
1405579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    // By definition, this is a struct assignment if we get here
1406579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    UpdatedStmt =
1407579e4f481774275980d6e3fbb7978c674da6d302Yang Ni        CreateStructRSSetObject(C, DRE, E, Loc, Loc);
1408579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  } else {
1409579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    UpdatedStmt =
1410579e4f481774275980d6e3fbb7978c674da6d302Yang Ni        CreateSingleRSSetObject(C, DRE, E, Loc, Loc);
1411579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  }
1412579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  NewStmts.push_back(UpdatedStmt);
1413579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1414579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  return DRE;
1415579e4f481774275980d6e3fbb7978c674da6d302Yang Ni}
1416579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1417579e4f481774275980d6e3fbb7978c674da6d302Yang Nivoid RSObjectRefCount::CreateParameterGuard(clang::ASTContext &C,
1418579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                            clang::DeclContext *DC,
1419579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                            clang::ParmVarDecl *PD,
1420579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                            std::vector<clang::Stmt*> &NewStmts) {
1421579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::SourceLocation Loc = PD->getLocStart();
1422579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::DeclRefExpr* ParamDRE = clang::DeclRefExpr::Create(
1423579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      C,
1424579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      clang::NestedNameSpecifierLoc(),       // QualifierLoc
1425579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      Loc,                                   // TemplateKWLoc
1426579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      PD,
1427579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      false,                                 // RefersToEnclosingVariableOrCapture
1428579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      Loc,                                   // NameLoc
1429579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      PD->getType(),
1430579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      clang::VK_RValue
1431579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  );
1432579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1433579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  CreateGuard(C, DC, ParamDRE,
1434579e4f481774275980d6e3fbb7978c674da6d302Yang Ni              llvm::Twine(".rs.param.") + llvm::Twine(PD->getName()), NewStmts);
1435579e4f481774275980d6e3fbb7978c674da6d302Yang Ni}
1436579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1437579e4f481774275980d6e3fbb7978c674da6d302Yang Nivoid RSObjectRefCount::HandleParamsAndLocals(clang::FunctionDecl *FD) {
1438579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt*> NewStmts;
1439579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::list<clang::ParmVarDecl*> ObjParams;
1440579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  for (clang::ParmVarDecl *Param : FD->parameters()) {
1441579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    clang::QualType QT = Param->getType();
1442579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    if (CountRSObjectTypes(QT.getTypePtr())) {
1443579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      // Ignore non-object types
1444579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      RSObjectRefCount::CreateParameterGuard(mCtx, FD, Param, NewStmts);
1445579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      ObjParams.push_back(Param);
1446579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    }
1447579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  }
1448579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1449579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::Stmt *OldBody = FD->getBody();
1450579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  if (ObjParams.empty()) {
1451579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    Visit(OldBody);
1452579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    return;
1453579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  }
1454579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1455579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  NewStmts.push_back(OldBody);
1456579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1457579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::SourceLocation Loc = FD->getLocStart();
1458579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::CompoundStmt *NewBody = BuildCompoundStmt(mCtx, NewStmts, Loc);
1459579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  Scope S(NewBody);
1460579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  for (clang::ParmVarDecl *Param : ObjParams) {
1461579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    S.addRSObject(Param);
1462579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  }
1463579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  mScopeStack.push_back(&S);
1464579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1465579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // To avoid adding unnecessary ref counting artifacts to newly added temporary
1466579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // local variables for parameters, visits only the old function body here.
1467579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  Visit(OldBody);
1468579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1469579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  FD->setBody(NewBody);
1470579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1471579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  S.InsertLocalVarDestructors();
1472579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  mScopeStack.pop_back();
1473579e4f481774275980d6e3fbb7978c674da6d302Yang Ni}
1474579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1475579e4f481774275980d6e3fbb7978c674da6d302Yang Niclang::CompoundStmt* RSObjectRefCount::CreateRetStmtWithTempVar(
1476579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    clang::ASTContext& C,
1477579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    clang::DeclContext* DC,
1478579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    clang::ReturnStmt* RS,
1479579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    const unsigned id) {
1480579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt*> NewStmts;
1481579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // Since we insert rsClearObj() calls before the return statement, we need
1482579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // to make sure none of the cleared RS objects are referenced in the
1483579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // return statement.
1484579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // For that, we create a new local variable named .rs.retval, assign the
1485579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // original return expression to it, make all necessary rsClearObj()
1486579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // calls, then return .rs.retval. Note rsClearObj() is not called on
1487579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // .rs.retval.
1488579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::SourceLocation Loc = RS->getLocStart();
1489579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::Expr* RetVal = RS->getRetValue();
1490579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  const clang::QualType RetTy = RetVal->getType();
1491579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::DeclRefExpr *DRE = CreateGuard(C, DC, RetVal,
1492579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                        llvm::Twine(".rs.retval") + llvm::Twine(id),
1493579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                        NewStmts);
14945767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni
14955767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  // Creates a new return statement
1496579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::ReturnStmt* NewRet = new (C) clang::ReturnStmt(Loc);
14975767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
14985767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      C,
14995767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      RetTy,
15005767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::CK_LValueToRValue,
15015767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      DRE,
15025767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      nullptr,
15035767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::VK_RValue
15045767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  );
15055767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  NewRet->setRetValue(CastExpr);
15065767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  NewStmts.push_back(NewRet);
15075767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni
15085767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  return BuildCompoundStmt(C, NewStmts, Loc);
15095767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni}
15105767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni
15114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1512b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  VisitStmt(DS);
1513b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->setCurrentStmt(DS);
15144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
15154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
15164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
15174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
15184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
15194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
1520cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      DataType DT = DataTypeUnknown;
15215abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes      clang::Expr *InitExpr = nullptr;
1522e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      if (InitializeRSObject(VD, &DT, &InitExpr)) {
1523b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        // We need to zero-init all RS object types (including matrices), ...
1524d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
1525b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        // ... but, only add to the list of RS objects if we have some
1526b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        // non-matrix RS object fields.
152765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross        if (CountRSObjectTypes(VD->getType().getTypePtr())) {
1528b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines          getCurrentScope()->addRSObject(VD);
1529b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        }
1530e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      }
15314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
15324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
15334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
15344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1535b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::VisitCallExpr(clang::CallExpr* CE) {
1536b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::QualType RetTy;
1537b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  const clang::FunctionDecl* FD = CE->getDirectCallee();
1538b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1539b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  if (FD) {
1540b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    // Direct calls
1541b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1542b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    RetTy = FD->getReturnType();
1543b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  } else {
1544b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    // Indirect calls through function pointers
1545b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1546b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::Expr* Callee = CE->getCallee();
1547b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::Type* CalleeType = Callee->getType().getTypePtr();
1548b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::PointerType* PtrType = CalleeType->getAs<clang::PointerType>();
1549b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1550b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (!PtrType) {
1551b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      return;
1552b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1553b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1554b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::Type* PointeeType = PtrType->getPointeeType().getTypePtr();
1555b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::FunctionType* FuncType = PointeeType->getAs<clang::FunctionType>();
1556b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1557b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (!FuncType) {
1558b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      return;
1559b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1560b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1561b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    RetTy = FuncType->getReturnType();
1562b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1563b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
15649e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // The RenderScript runtime API maintains the invariant that the sysRef of a new RS object would
15659e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // be 1, with the exception of rsGetAllocation() (deprecated in API 22), which leaves the sysRef
15669e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // 0 for a new allocation. It is the responsibility of the callee of the API to decrement the
15679e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // sysRef when a reference of the RS object goes out of scope. The compiler generates code to do
15689e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // just that, by creating a temporary variable named ".rs.tmpN" with the result of
15699e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // an RS-object-returning API directly assigned to it, and calling rsClearObject() on .rs.tmpN
15709e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // right before it exits the current scope. Such code generation is skipped for rsGetAllocation()
15719e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // to avoid decrementing its sysRef below zero.
15729e580014469e0c87e95fcb31e78738a336b1f200Yang Ni
15739e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  if (CountRSObjectTypes(RetTy.getTypePtr())==0 ||
15749e580014469e0c87e95fcb31e78738a336b1f200Yang Ni      (FD && FD->getName() == "rsGetAllocation")) {
1575b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return;
1576b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1577b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1578b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::SourceLocation Loc = CE->getSourceRange().getBegin();
1579b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::stringstream ss;
1580b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  ss << ".rs.tmp" << getNextID();
1581b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  llvm::StringRef VarName(ss.str());
1582b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1583b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::VarDecl* TempVarDecl = clang::VarDecl::Create(
1584b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx,                                  // AST context
1585b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      GetDeclContext(),                      // Decl context
1586b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Loc,                                   // Start location
1587b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Loc,                                   // Id location
1588b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      &mCtx.Idents.get(VarName),             // Id
1589b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      RetTy,                                 // Type
1590b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx.getTrivialTypeSourceInfo(RetTy),  // Type info
1591b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::SC_None                         // Storage class
1592b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  );
1593b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  TempVarDecl->setInit(CE);
1594041656a24663cb4f7a61a598e848f217c893cebfStephen Hines  TempVarDecl->markUsed(mCtx);
1595b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::Decl* Decls[] = { TempVarDecl };
1596b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
1597b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx, Decls, sizeof(Decls) / sizeof(*Decls));
1598b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::DeclStmt* DS = new (mCtx) clang::DeclStmt(DGR, Loc, Loc);
1599b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1600b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->InsertStmt(mCtx, DS);
1601b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1602b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
1603b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx,                                  // AST context
1604b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::NestedNameSpecifierLoc(),       // QualifierLoc
1605b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Loc,                                   // TemplateKWLoc
1606b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      TempVarDecl,
1607b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      false,                                 // RefersToEnclosingVariableOrCapture
1608b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Loc,                                   // NameLoc
1609b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      RetTy,
1610b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::VK_LValue
1611b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  );
1612b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
1613b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx,
1614b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      RetTy,
1615b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::CK_LValueToRValue,
1616b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      DRE,
1617b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      nullptr,
1618b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::VK_RValue
1619b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  );
1620b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1621b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->ReplaceExpr(mCtx, CE, CastExpr);
1622b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1623b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Register TempVarDecl for destruction call (rsClearObj).
1624b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->addRSObject(TempVarDecl);
1625b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1626b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
16274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1628b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  if (!emptyScope()) {
1629b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    getCurrentScope()->setCurrentStmt(CS);
1630b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1631b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
16324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
16334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
16344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
1635b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    mScopeStack.push_back(S);
16364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
16374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
16384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
16394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
16406e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
16411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
1642b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    mScopeStack.pop_back();
16434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
16444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
16454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
16464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
16474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
1648b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->setCurrentStmt(AS);
1649c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
1650c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
165165f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  if (CountRSObjectTypes(QT.getTypePtr())) {
1652d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    getCurrentScope()->ReplaceRSObjectAssignment(AS);
1653c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
16544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
16554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1656f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ninamespace {
1657f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni
1658f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Niclass FindRSObjRefVisitor : public clang::RecursiveASTVisitor<FindRSObjRefVisitor> {
1659f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Nipublic:
1660f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  explicit FindRSObjRefVisitor() : mRefRSObj(false) {}
1661f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  bool VisitExpr(clang::Expr* Expression) {
1662f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni    if (CountRSObjectTypes(Expression->getType().getTypePtr()) > 0) {
1663f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni      mRefRSObj = true;
1664f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni      // Found a reference to an RS object. Stop the AST traversal.
1665f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni      return false;
1666f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni    }
1667f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni    return true;
1668f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  }
1669f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni
1670f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  bool foundRSObjRef() const { return mRefRSObj; }
1671f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni
1672f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Niprivate:
1673f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  bool mRefRSObj;
1674f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni};
1675f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni
1676f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni}  // anonymous namespace
1677f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni
1678b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::VisitReturnStmt(clang::ReturnStmt *RS) {
1679b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->setCurrentStmt(RS);
1680b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1681b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // If there is no local rsObject declared so far, no need to transform the
1682b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // return statement.
1683b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1684b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  bool RSObjDeclared = false;
1685b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1686b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (const Scope* S : mScopeStack) {
1687b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (S->hasRSObject()) {
1688b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      RSObjDeclared = true;
1689b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      break;
1690b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1691b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1692b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1693b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  if (!RSObjDeclared) {
1694b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return;
1695b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1696b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1697f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  FindRSObjRefVisitor visitor;
1698f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni
1699f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  visitor.TraverseStmt(RS);
1700f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni
1701f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  // If the return statement does not return anything, or if it does not reference
1702b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // a rsObject, no need to transform it.
1703b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1704f6d3e58d364ae3d97a9cf468ca926259193c9018Yang Ni  if (!visitor.foundRSObjRef()) {
1705b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return;
1706b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1707b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1708b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Transform the return statement so that it does not potentially return or
1709b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // reference a rsObject that has been cleared.
1710b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1711b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::CompoundStmt* NewRS;
1712b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  NewRS = CreateRetStmtWithTempVar(mCtx, GetDeclContext(), RS, getNextID());
1713b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1714b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->ReplaceStmt(mCtx, NewRS);
1715b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1716b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
17174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1718b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->setCurrentStmt(S);
17194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
17204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
17214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
17224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
17234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
17244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
17254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
17264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
17274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1728688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines// This function walks the list of global variables and (potentially) creates
1729688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines// a single global static destructor function that properly decrements
1730688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines// reference counts on the contained RS object types.
1731688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hinesclang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
1732688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  Init();
1733688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1734688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
1735688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::SourceLocation loc;
1736688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
17373f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  llvm::StringRef SR(".rs.dtor");
17383f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  clang::IdentifierInfo &II = mCtx.Idents.get(SR);
17393f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  clang::DeclarationName N(&II);
17403f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  clang::FunctionProtoType::ExtProtoInfo EPI;
174182d7288620fade361dd8f7408b5db54a55c2c794Stephen Hines  clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
174282d7288620fade361dd8f7408b5db54a55c2c794Stephen Hines      llvm::ArrayRef<clang::QualType>(), EPI);
17435abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::FunctionDecl *FD = nullptr;
17443f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines
1745688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // Generate rsClearObject() call chains for every global variable
1746688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // (whether static or extern).
1747579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt *> StmtList;
1748688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
1749688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines          E = DC->decls_end(); I != E; I++) {
1750688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
1751688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    if (VD) {
175265f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      if (CountRSObjectTypes(VD->getType().getTypePtr())) {
17533f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        if (!FD) {
17543f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines          // Only create FD if we are going to use it.
17555abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, nullptr,
17564b3f3bada7155de983e7d92fa8b20091629b3bb3Stephen Hines                                           clang::SC_None);
17573f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        }
1758cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        // Mark VD as used.  It might be unused, except for the destructor.
1759cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        // 'markUsed' has side-effects that are caused only if VD is not already
1760cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        // used.  Hence no need for an extra check here.
1761cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        VD->markUsed(mCtx);
17623f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        // Make sure to create any helpers within the function's DeclContext,
17633f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        // not the one associated with the global translation unit.
17643f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
1765688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines        StmtList.push_back(RSClearObjectCall);
1766688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines      }
1767688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    }
1768688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  }
1769688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1770688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // Nothing needs to be destroyed, so don't emit a dtor.
1771688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  if (StmtList.empty()) {
17725abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
1773688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  }
1774688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1775688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
1776688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1777688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  FD->setBody(CS);
1778c8f5b2dad5c4ad2294d180b562d486342f29fb55I-Jui (Ray) Sung  // We need some way to tell if this FD is generated by slang
1779c8f5b2dad5c4ad2294d180b562d486342f29fb55I-Jui (Ray) Sung  FD->setImplicit();
1780688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1781688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  return FD;
1782688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines}
1783688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
178465f23ed862e1a1e16477ba740f295ff4a83ac822David Grossbool HasRSObjectType(const clang::Type *T) {
178565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  return CountRSObjectTypes(T) != 0;
178665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross}
178765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
1788e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
1789