slang_rs_object_ref_count.cpp revision 579e4f481774275980d6e3fbb7978c674da6d302
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"
234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Stmt.h"
244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h"
254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
266e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
278024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang.h"
28292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines#include "slang_rs_ast_replace.h"
294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
31e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
33474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet/* Even though those two arrays are of size DataTypeMax, only entries that
34474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet * correspond to object types will be set.
35474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet */
36474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouilletclang::FunctionDecl *
37cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc BrouilletRSObjectRefCount::RSSetObjectFD[DataTypeMax];
38474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouilletclang::FunctionDecl *
39cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc BrouilletRSObjectRefCount::RSClearObjectFD[DataTypeMax];
401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
41f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesvoid RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
42cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  for (unsigned i = 0; i < DataTypeMax; i++) {
435abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    RSSetObjectFD[i] = nullptr;
445abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    RSClearObjectFD[i] = nullptr;
451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = TUDecl->decls_end(); I != E; I++) {
511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((I->getKind() >= clang::Decl::firstFunction) &&
521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        (I->getKind() <= clang::Decl::lastFunction)) {
531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // points to RSSetObjectFD or RSClearObjectFD
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl **RSObjectFD;
571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      if (FD->getName() == "rsSetObject") {
596e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 2) &&
606e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsSetObject function prototype (# params)");
611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
636e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 1) &&
646e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsClearObject function prototype (# params)");
651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSClearObjectFD;
66e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      } else {
671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        continue;
681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType PVT = PVD->getOriginalType();
721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The first parameter must be a pointer like rs_allocation*
736e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(PVT->isPointerType() &&
746e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines          "Invalid rs{Set,Clear}Object function prototype (pointer param)");
751bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The rs object type passed to the FD
771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType RST = PVT->getPointeeType();
78cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      DataType DT = RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
796e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             && "must be RS object type");
811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
82cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      if (DT >= 0 && DT < DataTypeMax) {
83474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet          RSObjectFD[DT] = FD;
84474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      } else {
85474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet          slangAssert(false && "incorrect type");
86474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      }
871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
914464d825c11349068f2917f9ebee86b721423f3cStephen Hinesnamespace {
924464d825c11349068f2917f9ebee86b721423f3cStephen Hines
93b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niunsigned CountRSObjectTypes(const clang::Type *T);
94b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
95b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
96b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *DstExpr,
97b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *SrcExpr,
98b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation StartLoc,
99b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation Loc);
100b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
101292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// This function constructs a new CompoundStmt from the input StmtList.
102b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
103579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      std::vector<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
104d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  unsigned NewStmtCount = StmtList.size();
105292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  unsigned CompoundStmtCount = 0;
1061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
107292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **CompoundStmtList;
108292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  CompoundStmtList = new clang::Stmt*[NewStmtCount];
1091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
110579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt*>::const_iterator I = StmtList.begin();
111579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt*>::const_iterator E = StmtList.end();
112292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; I != E; I++) {
113292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    CompoundStmtList[CompoundStmtCount++] = *I;
1141bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
115292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CompoundStmtCount == NewStmtCount);
1161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
11723c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
11823c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);
1191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
120292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  delete [] CompoundStmtList;
1211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
122292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return CS;
1231bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1241bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
125b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid AppendAfterStmt(clang::ASTContext &C,
126b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                     clang::CompoundStmt *CS,
127b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                     clang::Stmt *S,
128b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                     std::list<clang::Stmt*> &StmtList) {
129292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CS);
130e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
131292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::CompoundStmt::body_iterator bE = CS->body_end();
132292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **UpdatedStmtList =
133292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      new clang::Stmt*[CS->size() + StmtList.size()];
134e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
135e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned UpdatedStmtCount = 0;
136e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned Once = 0;
137292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; bI != bE; bI++) {
138292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
139292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // If we come across a return here, we don't have anything we can
140292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // reasonably replace. We should have already inserted our destructor
141292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // code in the proper spot, so we just clean up and return.
142292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      delete [] UpdatedStmtList;
143292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
144292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      return;
145e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    }
146e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
147292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
148c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
149292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if ((*bI == S) && !Once) {
150292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      Once++;
151292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
152292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator E = StmtList.end();
153292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      for ( ; I != E; I++) {
154292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines        UpdatedStmtList[UpdatedStmtCount++] = *I;
155292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      }
156292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    }
157c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
158292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(Once <= 1);
159c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
1605abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  // When S is nullptr, we are appending to the end of the CompoundStmt.
161292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (!S) {
162292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    slangAssert(Once == 0);
163292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
164292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator E = StmtList.end();
165292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    for ( ; I != E; I++) {
166292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *I;
167c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    }
168c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
169c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
17098cfae456bb1831336bce2b21979a04e2e31fed4Pirama Arumuga Nainar  CS->setStmts(C, llvm::makeArrayRef(UpdatedStmtList, UpdatedStmtCount));
171c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
172c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  delete [] UpdatedStmtList;
173c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
174c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
175b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// This class visits a compound statement and collects a list of all the exiting
176b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// statements, such as any return statement in any sub-block, and any
177b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// break/continue statement that would resume outside the current scope.
178b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni// We do not handle the case for goto statements that leave a local scope.
1794464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
1804464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
181292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The loop depth of the currently visited node.
182292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mLoopDepth;
183292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
184292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The switch statement depth of the currently visited node.
185292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // Note that this is tracked separately from the loop depth because
186292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // SwitchStmt-contained ContinueStmt's should have destructors for the
187292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // corresponding loop scope.
188292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mSwitchDepth;
189292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
190b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Output of the visitor: the statements that should be replaced by compound
191b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // statements, each of which contains rsClearObject() calls followed by the
192b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // original statement.
193b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::vector<clang::Stmt*> mExitingStmts;
194a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines
1954464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
196b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  DestructorVisitor() : mLoopDepth(0), mSwitchDepth(0) {}
197292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
198b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  const std::vector<clang::Stmt*>& getExitingStmts() const {
199b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return mExitingStmts;
200292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
201292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
2024464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
203292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitBreakStmt(clang::BreakStmt *BS);
204292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitContinueStmt(clang::ContinueStmt *CS);
205292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitDoStmt(clang::DoStmt *DS);
206292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitForStmt(clang::ForStmt *FS);
207292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitReturnStmt(clang::ReturnStmt *RS);
208292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitSwitchStmt(clang::SwitchStmt *SS);
209292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitWhileStmt(clang::WhileStmt *WS);
2104464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
2114464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2124464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
21356916bec2734a6059e1d0f58959514c825c746f7Yang Ni  for (clang::Stmt* Child : S->children()) {
21456916bec2734a6059e1d0f58959514c825c746f7Yang Ni    if (Child) {
2154464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
2164464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
2174464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2184464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2194464d825c11349068f2917f9ebee86b721423f3cStephen Hines
220292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
221292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(BS);
222292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
223b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    mExitingStmts.push_back(BS);
224292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
225292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
226292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
227292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
228292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(CS);
229292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (mLoopDepth == 0) {
230292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    // Switch statements can have nested continues.
231b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    mExitingStmts.push_back(CS);
232292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
233292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
234292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
235292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
236292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
237292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(DS);
238292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
239292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
240292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
241292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
242292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
243292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(FS);
244292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
245292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
246292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
247292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
248b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  mExitingStmts.push_back(RS);
249292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
250292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
251292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
252292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth++;
253292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(SS);
254292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth--;
255292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
256292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
257292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
258292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
259292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(WS);
260292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
261292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
262292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
263f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::Expr *ClearSingleRSObject(clang::ASTContext &C,
264f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::Expr *RefRSVar,
265f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::SourceLocation Loc) {
266f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(RefRSVar);
267f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *T = RefRSVar->getType().getTypePtr();
268f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!T->isArrayType() &&
269f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should not be destroying arrays with this function");
270f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
271f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
2725abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((ClearObjectFD != nullptr) &&
273f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "rsClearObject doesn't cover all RS object types");
274f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
275f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
276f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDArgType =
277f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
278f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
279f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Example destructor for "rs_font localFont;"
280f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //
281f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // (CallExpr 'void'
282f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
283f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
284f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
285f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
286f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
287f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Get address of targeted RS object
288f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *AddrRefRSVar =
289f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
290f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  clang::UO_AddrOf,
291f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  ClearObjectFDArgType,
292be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
293be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
294f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  Loc);
295f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
296f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSClearObjectFD =
297f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclRefExpr::Create(C,
298be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
2990444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
300f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD,
301e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
302f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getLocation(),
303be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 ClearObjectFDType,
304be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
3055abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
306f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
307f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RSClearObjectFP =
308f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::ImplicitCastExpr::Create(C,
309f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      C.getPointerType(ClearObjectFDType),
310f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::CK_FunctionToPointerDecay,
311f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      RefRSClearObjectFD,
3125abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
313f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::VK_RValue);
31403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
3151dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 1> ArgList;
3161dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(AddrRefRSVar);
3171dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines
318f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CallExpr *RSClearObjectCall =
319f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CallExpr(C,
320f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             RSClearObjectFP,
3211dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                             ArgList,
322f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             ClearObjectFD->getCallResultType(),
323be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
324f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             Loc);
325f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
326f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSClearObjectCall;
327f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
328f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
329f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic int ArrayDim(const clang::Type *T) {
33003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
33103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
33203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
33303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
33403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
33503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
3369d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
33703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
33803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
339b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *ClearStructRSObject(
340f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
341f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
342f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
343d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::SourceLocation StartLoc,
344f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc);
345f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
346b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *ClearArrayRSObject(
347f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
348f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
349f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSArr,
350cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    clang::SourceLocation StartLoc,
351f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
352f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
353f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(BaseType->isArrayType());
354f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
355f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  int NumArrayElements = ArrayDim(BaseType);
356f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Actually extract out the base RS object type for use later
357f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
35803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
35903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
3605abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
36103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
36203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
36303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
36403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
365cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // (ForStmt
366cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (DeclStmt
367cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (VarDecl used rsIntIter 'int' cinit
368cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (IntegerLiteral 'int' 0)))
369cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (BinaryOperator 'int' '<'
370cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (ImplicitCastExpr int LValueToRValue
37103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
372cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (IntegerLiteral 'int' 10)
373cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   nullptr << CondVar >>
374cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (UnaryOperator 'int' postfix '++'
375cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (DeclRefExpr 'int' Var='rsIntIter'))
376cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (CallExpr 'void'
377cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
378cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
379cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (UnaryOperator 'rs_font *' prefix '&'
380cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (ArraySubscriptExpr 'rs_font':'rs_font'
381cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //         (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
382cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //           (DeclRefExpr 'rs_font [10]' Var='fontArr'))
383cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //         (DeclRefExpr 'int' Var='rsIntIter'))))))
38403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
386cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  static unsigned sIterCounter = 0;
387cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  std::stringstream UniqueIterName;
388cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  UniqueIterName << "rsIntIter" << sIterCounter++;
389cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::IdentifierInfo *II = &C.Idents.get(UniqueIterName.str());
39003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
39103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
392f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             DC,
393cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                             StartLoc,
39403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
395cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                             II,
39603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
39703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
39803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
399cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar  // Mark "rsIntIter" as used
400cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar  IIVD->markUsed(C);
40103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
40403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
40503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
406cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // Init -> "int rsIntIter = 0"
407cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
408cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
409cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  IIVD->setInit(Int0);
410cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines
411cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
412cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
413cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Stmt *Init = new(C) clang::DeclStmt(DGR, Loc, Loc);
414cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines
415cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // Cond -> "rsIntIter < NumArrayElements"
416cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::DeclRefExpr *RefrsIntIterLValue =
41703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
418be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
4190444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
42003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
421e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
423be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
424cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                 clang::VK_LValue,
4255abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
42603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
427cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Expr *RefrsIntIterRValue =
428cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      clang::ImplicitCastExpr::Create(C,
429cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      RefrsIntIterLValue->getType(),
430cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      clang::CK_LValueToRValue,
431cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      RefrsIntIterLValue,
432cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      nullptr,
433cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      clang::VK_RValue);
43403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
43603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
43703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
439cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      new(C) clang::BinaryOperator(RefrsIntIterRValue,
44003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
44103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
44203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
443be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
444be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
44523c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   Loc,
44623c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   false);
44703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
44803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
44903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
450cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      new(C) clang::UnaryOperator(RefrsIntIterLValue,
45103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
45203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
453be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
454be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
45503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
45603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
45703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
45803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
45903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
460f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtr =
46103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
462f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
46303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
464f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          RefRSArr,
4655abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
46603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
46703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
468f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtrSubscript =
469f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
470cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                       RefrsIntIterRValue,
471f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       BaseType->getCanonicalTypeInternal(),
472be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
473be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
474f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       Loc);
47503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
476cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
477f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
4785abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *RSClearObjectCall = nullptr;
479f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (BaseType->isArrayType()) {
480f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
481cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
482cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  } else if (DT == DataTypeUnknown) {
483f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
484cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
485f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
486f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
487f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
48803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
48903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
49003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
49103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
49203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
4935abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                            nullptr,  // no condVar
49403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
49503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
49603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
49703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
49803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
49903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
500cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  return DestructorLoop;
50103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
50203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
503b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niunsigned CountRSObjectTypes(const clang::Type *T) {
504f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(T);
505f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned RSObjectCount = 0;
506f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
507f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
50865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
509f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
510f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
511cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
512cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT != DataTypeUnknown) {
513f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
514f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
515f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
516d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  if (T->isUnionType()) {
517d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
518d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RD = RD->getDefinition();
519d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
520d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines           FE = RD->field_end();
521d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines         FI != FE;
522d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines         FI++) {
523d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      const clang::FieldDecl *FD = *FI;
524d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
52565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      if (CountRSObjectTypes(FT)) {
52678e69cb06b9b0683b2ac9dcafde87b867690ef2fStephen Hines        slangAssert(false && "can't have unions with RS object types!");
527d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        return 0;
528d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      }
529d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    }
530d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  }
531d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines
532f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (!T->isStructureType()) {
533f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return 0;
534f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
535f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
536f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
537f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
538f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
539f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
540f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
541f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
542f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::FieldDecl *FD = *FI;
543f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
54465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (CountRSObjectTypes(FT)) {
545f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // Sub-structs should only count once (as should arrays, etc.)
546f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSObjectCount++;
547f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
548f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
549f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
550f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSObjectCount;
551f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
552f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
553b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *ClearStructRSObject(
554f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
555f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
556f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
557cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    clang::SourceLocation StartLoc,
558f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
559f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
560f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
561f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!BaseType->isArrayType());
562f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
563f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Structs should show up as unknown primitive types
5649be9360d8e02b52ed669afbd69f9becb575c3f0dAlex Sakhartchouk  slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
565cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet              DataTypeUnknown);
566f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
56765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
568b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines  slangAssert(FieldsToDestroy != 0);
569f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
570f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned StmtCount = 0;
571f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
5722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToDestroy; i++) {
5735abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    StmtArray[i] = nullptr;
5742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
575f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
576f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Populate StmtArray by creating a destructor for each RS object field
577f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
578f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
579f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
580f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
581f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
582f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
583f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // We just look through all field declarations to see if we find a
584f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // declaration for an RS object type (or an array of one).
585f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    bool IsArrayType = false;
586f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::FieldDecl *FD = *FI;
587f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
588f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *OrigType = FT;
589f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    while (FT && FT->isArrayType()) {
590f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
591f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      IsArrayType = true;
592f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
593f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
594cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    // Pass a DeclarationNameInfo with a valid DeclName, since name equality
595cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    // gets asserted during CodeGen.
596cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    clang::DeclarationNameInfo FDDeclNameInfo(FD->getDeclName(),
597cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar                                              FD->getLocation());
598cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar
599f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
600f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
601f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
602f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
603f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
604f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
605f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
6060b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                    clang::SourceLocation(),
607be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
6080444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                    clang::SourceLocation(),
609f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
610f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
611cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar                                    FDDeclNameInfo,
6125abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                    nullptr,
613be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
614be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
615be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
616f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
617f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      slangAssert(StmtCount < FieldsToDestroy);
618f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
619f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
620f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
621f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
622f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
623cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                    StartLoc,
624f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
625f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
626f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearSingleRSObject(C,
627f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
628f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
629f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
63065f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
631f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // In this case, we have a nested struct. We may not end up filling all
632f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // of the spaces in StmtArray (sub-structs should handle themselves
633f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // with separate compound statements).
634f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
635f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
636f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
637f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
638f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
639f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
6400b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                    clang::SourceLocation(),
641be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
6420444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                    clang::SourceLocation(),
643f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
644f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
645f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
6465abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                    nullptr,
647be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
648be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
649be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
650f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
651f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
652f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
653f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
654f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
655cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                    StartLoc,
656f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
657f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
658f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearStructRSObject(C,
659f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     DC,
660f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
661cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                     StartLoc,
662f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
663f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
664f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
665f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
666f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
667f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(StmtCount > 0);
66823c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
66923c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
670f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
671f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  delete [] StmtArray;
672f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
673f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return CS;
674f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
675f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
676b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
677b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *DstExpr,
678b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *SrcExpr,
679b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation StartLoc,
680b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation Loc) {
6812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = DstExpr->getType().getTypePtr();
6822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
6835abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((SetObjectFD != nullptr) &&
6846e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
685c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
686c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
687c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
688c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
689c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
690c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
691c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
692c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
693be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
6940444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
695c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
696e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
697c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
698be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
699be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
7005abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
701c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
702c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
703c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
704c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
705c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
706c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
7075abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
708c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
709c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
7101dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 2> ArgList;
7111dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
7121dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::UO_AddrOf,
7131dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                SetObjectFDArgType[0],
7141dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::VK_RValue,
7151dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::OK_Ordinary,
7161dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                Loc));
7171dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(SrcExpr);
718c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
719c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CallExpr *RSSetObjectCall =
720c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      new(C) clang::CallExpr(C,
721c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             RSSetObjectFP,
722c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             ArgList,
723c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             SetObjectFD->getCallResultType(),
724be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
725c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             Loc);
726c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
7272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return RSSetObjectCall;
7282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
7292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
730b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
731b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *LHS,
732b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *RHS,
733b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation StartLoc,
734b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation Loc);
7352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
736246fa17206bf78c59a64b2f7d98a6716d5345b81Al Sutton/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
7372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *DstArr,
7382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *SrcArr,
739cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                           clang::SourceLocation StartLoc,
7402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::SourceLocation Loc) {
7415abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::DeclContext *DC = nullptr;
7422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *BaseType = DstArr->getType().getTypePtr();
7432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(BaseType->isArrayType());
7442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int NumArrayElements = ArrayDim(BaseType);
7462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Actually extract out the base RS object type for use later
7472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
7482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7495abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *StmtArray[2] = {nullptr};
7502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int StmtCtr = 0;
7512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (NumArrayElements <= 0) {
7535abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
7542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
7552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Create helper variable for iterating through elements
7572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
7582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::VarDecl *IIVD =
7592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::VarDecl::Create(C,
7602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             DC,
761cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                             StartLoc,
7622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             Loc,
7632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             &II,
7642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.IntTy,
7652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
7662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None,
7672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None);
7682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
7692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
7712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
7722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Form the actual loop
7742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // for (Init; Cond; Inc)
7752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  //   RSSetObjectCall;
7762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Init -> "rsIntIter = 0"
7782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
7792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::DeclRefExpr::Create(C,
780be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
7812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 IIVD,
7822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 Loc,
783be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
784be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
7855abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
7862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
7882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
7892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Init =
7912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
7922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Int0,
7932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_Assign,
7942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
795be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
796be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
7972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
7982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
8002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
8012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
8022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Cond =
8042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
8052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   NumArrayElementsExpr,
8062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_LT,
8072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
808be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
809be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
8102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
8112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Inc -> "rsIntIter++"
8132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::UnaryOperator *Inc =
8142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
8152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::UO_PostInc,
8162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  C.IntTy,
817be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
818be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
8192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  Loc);
8202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
8222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Loop operates on individual array elements
8232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtr =
8252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
8262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
8272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
8282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          DstArr,
8295abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
8302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
8312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtrSubscript =
8332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(DstArrPtr,
8342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
8352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
836be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
837be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
8382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
8392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtr =
8412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
8422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
8432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
8442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          SrcArr,
8455abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
8462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
8472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtrSubscript =
8492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(SrcArrPtr,
8502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
8512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
852be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
853be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
8542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
8552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
856cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
8572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8585abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *RSSetObjectCall = nullptr;
8592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (BaseType->isArrayType()) {
860d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
861cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                             SrcArrPtrSubscript,
862cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                             StartLoc, Loc);
863cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  } else if (DT == DataTypeUnknown) {
864d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
865cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              SrcArrPtrSubscript,
866cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              StartLoc, Loc);
8672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
868d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
869cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              SrcArrPtrSubscript,
870cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              StartLoc, Loc);
8712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
8722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ForStmt *DestructorLoop =
8742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ForStmt(C,
8752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Init,
8762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Cond,
8775abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                            nullptr,  // no condVar
8782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Inc,
8792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            RSSetObjectCall,
8802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
8812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
8822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc);
8832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
8852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(StmtCtr == 2);
8862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::CompoundStmt *CS =
8882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
8892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
891246fa17206bf78c59a64b2f7d98a6716d5345b81Al Sutton} */
8922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
893b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Niclang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
894b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *LHS,
895b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::Expr *RHS,
896b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation StartLoc,
897b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                     clang::SourceLocation Loc) {
8982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = LHS->getType();
8992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = QT.getTypePtr();
9002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(T->isStructureType());
9012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
9022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Keep an extra slot for the original copy (memcpy)
90465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
9052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned StmtCount = 0;
9072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
9082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToSet; i++) {
9095abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    StmtArray[i] = nullptr;
9102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
9112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
9132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  RD = RD->getDefinition();
9142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
9152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines         FE = RD->field_end();
9162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI != FE;
9172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI++) {
9182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    bool IsArrayType = false;
9192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::FieldDecl *FD = *FI;
9202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
9212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *OrigType = FT;
9222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
92365f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (!CountRSObjectTypes(FT)) {
9242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // Skip to next if we don't have any viable RS object types
9252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      continue;
9262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::DeclAccessPair FoundDecl =
9292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::DeclAccessPair::make(FD, clang::AS_none);
9302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *DstMember =
9312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
9322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  LHS,
9332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
9340b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                  clang::SourceLocation(),
935be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
9360444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                  clang::SourceLocation(),
9372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
9382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
939c9344ace5050b7d5ee9a677ce996fc0b731c0830I-Jui (Ray) Sung                                  clang::DeclarationNameInfo(
940c9344ace5050b7d5ee9a677ce996fc0b731c0830I-Jui (Ray) Sung                                      FD->getDeclName(),
941c9344ace5050b7d5ee9a677ce996fc0b731c0830I-Jui (Ray) Sung                                      clang::SourceLocation()),
9425abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                  nullptr,
943be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
944be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
945be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
9462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *SrcMember =
9482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
9492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  RHS,
9502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
9510b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                  clang::SourceLocation(),
952be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
9530444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                  clang::SourceLocation(),
9542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
9552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
956824b3ce35d55cc8b1f7f33874d22d328e05bd497I-Jui (Ray) Sung                                  clang::DeclarationNameInfo(
957824b3ce35d55cc8b1f7f33874d22d328e05bd497I-Jui (Ray) Sung                                      FD->getDeclName(),
958824b3ce35d55cc8b1f7f33874d22d328e05bd497I-Jui (Ray) Sung                                      clang::SourceLocation()),
9595abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                  nullptr,
960be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
961be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
962be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
9632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (FT->isArrayType()) {
9652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
9662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      IsArrayType = true;
9672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
969cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    DataType DT = RSExportPrimitiveType::GetRSSpecificType(FT);
9702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (IsArrayType) {
9729207a2e495c8363606861e4f034504ec5c153dabLogan Chien      clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
9739207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine.Report(
9749207a2e495c8363606861e4f034504ec5c153dabLogan Chien        clang::FullSourceLoc(Loc, C.getSourceManager()),
9759207a2e495c8363606861e4f034504ec5c153dabLogan Chien        DiagEngine.getCustomDiagID(
9769207a2e495c8363606861e4f034504ec5c153dabLogan Chien          clang::DiagnosticsEngine::Error,
9779207a2e495c8363606861e4f034504ec5c153dabLogan Chien          "Arrays of RS object types within structures cannot be copied"));
9782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // TODO(srhines): Support setting arrays of RS objects
9792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // StmtArray[StmtCount++] =
980d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      //    CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
981cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    } else if (DT == DataTypeUnknown) {
9822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
983d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines          CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
9842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
9852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
986d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines          CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
9872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else {
9882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      slangAssert(false);
9892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
9912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
992b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines  slangAssert(StmtCount < FieldsToSet);
9932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // We still need to actually do the overall struct copy. For simplicity,
9952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // we just do a straight-up assignment (which will still preserve all
9962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // the proper RS object reference counts).
9972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *CopyStruct =
998be27482cdeaf08576bc39b72a15d35d13014a636Logan      new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
99923c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   clang::VK_RValue, clang::OK_Ordinary, Loc,
100023c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   false);
10012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCount++] = CopyStruct;
10022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
100323c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
100423c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
10052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  delete [] StmtArray;
10072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
10092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
10102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}  // namespace
10122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
1013b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::Scope::InsertStmt(const clang::ASTContext &C,
1014b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                         clang::Stmt *NewStmt) {
1015b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::vector<clang::Stmt*> newBody;
1016b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (clang::Stmt* S1 : mCS->body()) {
1017b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (S1 == mCurrent) {
1018b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      newBody.push_back(NewStmt);
1019b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1020b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    newBody.push_back(S1);
1021b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
102298cfae456bb1831336bce2b21979a04e2e31fed4Pirama Arumuga Nainar  mCS->setStmts(C, newBody);
1023b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1024b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1025b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::Scope::ReplaceStmt(const clang::ASTContext &C,
1026b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                          clang::Stmt *NewStmt) {
1027b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::vector<clang::Stmt*> newBody;
1028b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (clang::Stmt* S1 : mCS->body()) {
1029b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (S1 == mCurrent) {
1030b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      newBody.push_back(NewStmt);
1031b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    } else {
1032b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      newBody.push_back(S1);
1033b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1034b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
103598cfae456bb1831336bce2b21979a04e2e31fed4Pirama Arumuga Nainar  mCS->setStmts(C, newBody);
1036b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1037b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1038b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::Scope::ReplaceExpr(const clang::ASTContext& C,
1039b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                          clang::Expr* OldExpr,
1040b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni                                          clang::Expr* NewExpr) {
1041b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  RSASTReplace R(C);
1042b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  R.ReplaceStmt(mCurrent, OldExpr, NewExpr);
1043b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1044b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
10452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesvoid RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
1046d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::BinaryOperator *AS) {
10472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = AS->getType();
10492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
10519ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getASTContext();
10522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
1053832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines  clang::SourceLocation Loc = AS->getExprLoc();
10549f1d0aa55669b75a718ad2e962fc8c3d8df1a5f4Stephen Hines  clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
10555abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *UpdatedStmt = nullptr;
10562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
10582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    // By definition, this is a struct assignment if we get here
10592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
1060d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
10612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
10622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
1063d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
10642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
1065e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1066292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  RSASTReplace R(C);
1067292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  R.ReplaceStmt(mCS, AS, UpdatedStmt);
1068e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
1069e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1070e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesvoid RSObjectRefCount::Scope::AppendRSObjectInit(
1071e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::VarDecl *VD,
1072e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::DeclStmt *DS,
1073cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    DataType DT,
1074e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::Expr *InitExpr) {
10756e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD);
1076e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1077e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!InitExpr) {
1078e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return;
1079e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1080e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1081a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
10829ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getASTContext();
1083a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
10849ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getLocation();
1085cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao  clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
10869ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getInnerLocStart();
1087a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1088cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT == DataTypeIsStruct) {
1089a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1090a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::DeclRefExpr *RefRSVar =
1091a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines        clang::DeclRefExpr::Create(C,
1092be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::NestedNameSpecifierLoc(),
10930444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                   clang::SourceLocation(),
1094a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   VD,
1095e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                   false,
1096a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   Loc,
1097be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   T->getCanonicalTypeInternal(),
1098be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
10995abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                   nullptr);
1100a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1101a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::Stmt *RSSetObjectOps =
1102d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
1103cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // Fix for b/37363420; consider:
1104cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //
1105cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // struct foo { rs_matrix m; };
1106cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // void bar() {
1107cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //   struct foo M = {...};
1108cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // }
1109cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //
1110cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // slang modifies that declaration with initialization to a
1111cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // declaration plus an assignment of the initialization values.
1112cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //
1113cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // void bar() {
1114cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //   struct foo M = {};
1115cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //   M = {...}; // by CreateStructRSSetObject() above
1116cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // }
1117cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    //
1118cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // the slang-generated statement (M = {...}) is a use of M, and we
1119cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    // need to mark M (clang::VarDecl *VD) as used.
1120cdb3b2cd64b380eabae8be265a3aa8eae30d9b46I-Jui (Ray) Sung    VD->markUsed(C);
1121a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1122292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*> StmtList;
1123292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    StmtList.push_back(RSSetObjectOps);
1124292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    AppendAfterStmt(C, mCS, DS, StmtList);
1125f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return;
1126f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1127f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
1128f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
11295abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((SetObjectFD != nullptr) &&
11306e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
1131e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1132e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
1133e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDArgType[2];
1134e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1135e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1136e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1137e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RefRSSetObjectFD =
1138e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1139be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
11400444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
1141e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD,
1142e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
1143e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1144be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
1145be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
11465abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
1147e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1148e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RSSetObjectFP =
1149e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::ImplicitCastExpr::Create(C,
1150e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      C.getPointerType(SetObjectFDType),
1151e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::CK_FunctionToPointerDecay,
1152e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      RefRSSetObjectFD,
11535abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
1154e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::VK_RValue);
1155e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1156e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1157e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::DeclRefExpr *RefRSVar =
1158e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1159be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
11600444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
1161e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD,
1162e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
1163e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1164be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1165be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
11665abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
1167e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
11681dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 2> ArgList;
11691dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
11701dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::UO_AddrOf,
11711dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                SetObjectFDArgType[0],
11721dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::VK_RValue,
11731dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::OK_Ordinary,
11741dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                Loc));
11751dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(InitExpr);
1176e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1177e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CallExpr *RSSetObjectCall =
1178e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      new(C) clang::CallExpr(C,
1179e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             RSSetObjectFP,
1180e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             ArgList,
1181e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             SetObjectFD->getCallResultType(),
1182be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
1183e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             Loc);
1184e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1185292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*> StmtList;
1186292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  StmtList.push_back(RSSetObjectCall);
1187292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  AppendAfterStmt(C, mCS, DS, StmtList);
1188c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
1189c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
11901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
1191b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  if (mRSO.empty()) {
1192b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return;
1193b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1194b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1195b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::DeclContext* DC = mRSO.front()->getDeclContext();
1196b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::ASTContext& C = DC->getParentASTContext();
1197b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::SourceManager& SM = C.getSourceManager();
1198b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1199b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  const auto& OccursBefore = [&SM] (clang::SourceLocation L1, clang::SourceLocation L2)->bool {
1200b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return SM.isBeforeInTranslationUnit(L1, L2);
1201b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  };
1202b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  typedef std::map<clang::SourceLocation, clang::Stmt*, decltype(OccursBefore)> DMap;
1203b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1204b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  DMap dtors(OccursBefore);
1205b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1206b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Create rsClearObject calls. Note the DMap entries are sorted by the SourceLocation.
1207b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (clang::VarDecl* VD : mRSO) {
1208b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    clang::SourceLocation Loc = VD->getSourceRange().getBegin();
1209b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    clang::Stmt* RSClearObjectCall = ClearRSObject(VD, DC);
1210b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    dtors.insert(std::make_pair(Loc, RSClearObjectCall));
1211b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1212b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1213b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  DestructorVisitor Visitor;
1214b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  Visitor.Visit(mCS);
1215b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1216b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Replace each exiting statement with a block that contains the original statement
1217b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // and added rsClearObject() calls before it.
1218b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (clang::Stmt* S : Visitor.getExitingStmts()) {
1219b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1220b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::SourceLocation currentLoc = S->getLocStart();
1221b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1222b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    DMap::iterator firstDtorIter = dtors.begin();
1223b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    DMap::iterator currentDtorIter = firstDtorIter;
1224b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    DMap::iterator lastDtorIter = dtors.end();
1225b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1226b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    while (currentDtorIter != lastDtorIter &&
1227b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni           OccursBefore(currentDtorIter->first, currentLoc)) {
1228b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      currentDtorIter++;
12291bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
1230b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1231b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (currentDtorIter == firstDtorIter) {
1232b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      continue;
1233b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1234b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1235579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    std::vector<clang::Stmt*> Stmts;
1236b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1237b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    // Insert rsClearObject() calls for all rsObjects declared before the current statement
1238b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    for(DMap::iterator it = firstDtorIter; it != currentDtorIter; it++) {
1239b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Stmts.push_back(it->second);
1240b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1241b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    Stmts.push_back(S);
1242b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1243b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    RSASTReplace R(C);
1244b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    clang::CompoundStmt* CS = BuildCompoundStmt(C, Stmts, S->getLocEnd());
1245b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    R.ReplaceStmt(mCS, S, CS);
12461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1247b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1248b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::list<clang::Stmt*> Stmts;
1249b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for(auto LocCallPair : dtors) {
1250b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    Stmts.push_back(LocCallPair.second);
1251b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1252b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  AppendAfterStmt(C, mCS, nullptr, Stmts);
12531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
12541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
12553f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
12563f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines    clang::VarDecl *VD,
12573f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines    clang::DeclContext *DC) {
1258f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(VD);
12591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
12601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
1261cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao  clang::SourceLocation StartLoc = VD->getInnerLocStart();
12621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
126303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
12641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
12651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
12661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
1267be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
12680444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
12691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
1270e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
12711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
1272be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1273be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
12745abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
12751bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1276f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
1277cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
1278f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
12791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1280cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
12811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1282cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT == DataTypeUnknown ||
1283cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      DT == DataTypeIsStruct) {
1284cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
1285f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
12861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1287f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1288f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should be RS object");
12891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1290f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return ClearSingleRSObject(C, RefRSVar, Loc);
12911bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
12921bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1293e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1294cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet                                          DataType *DT,
1295e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          clang::Expr **InitExpr) {
12966e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD && DT && InitExpr);
12974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
12982d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
12992d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
13002d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
13012d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
13022d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
13032d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
1304f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsStructWithRSObject = false;
1305e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
13064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1307cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (*DT == DataTypeUnknown) {
1308feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1309cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      *DT = DataTypeIsStruct;
1310f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DataTypeIsStructWithRSObject = true;
1311feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    } else {
1312feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      return false;
1313feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    }
13142d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
13154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1316f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsRSObject = false;
1317f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DataTypeIsStructWithRSObject) {
1318f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = true;
1319f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
1320f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1321f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1322e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *InitExpr = VD->getInit();
1323e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1324e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!DataTypeIsRSObject && *InitExpr) {
1325e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    // If we already have an initializer for a matrix type, we are done.
1326e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return DataTypeIsRSObject;
13274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
13284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1329e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ZeroInitializer =
1330d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines      CreateEmptyInitListExpr(VD->getASTContext(), VD->getLocation());
1331e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1332e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (ZeroInitializer) {
1333e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    ZeroInitializer->setType(T->getCanonicalTypeInternal());
1334e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    VD->setInit(ZeroInitializer);
1335e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1336e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1337e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return DataTypeIsRSObject;
13384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
13394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1340d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hinesclang::Expr *RSObjectRefCount::CreateEmptyInitListExpr(
13414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
13424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
13434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1344d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  // We can cheaply construct a zero initializer by just creating an empty
1345d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  // initializer list. Clang supports this extension to C(99), and will create
1346d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  // any necessary constructs to zero out the entire variable.
1347d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  llvm::SmallVector<clang::Expr*, 1> EmptyInitList;
1348d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines  return new(C) clang::InitListExpr(C, Loc, EmptyInitList, Loc);
13494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
13504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1351579e4f481774275980d6e3fbb7978c674da6d302Yang Niclang::DeclRefExpr *RSObjectRefCount::CreateGuard(clang::ASTContext &C,
1352579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                                  clang::DeclContext *DC,
1353579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                                  clang::Expr *E,
1354579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                                  const llvm::Twine &VarName,
1355579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                                  std::vector<clang::Stmt*> &NewStmts) {
1356579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::SourceLocation Loc = E->getLocStart();
1357579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  const clang::QualType Ty = E->getType();
1358579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::VarDecl* TmpDecl = clang::VarDecl::Create(
13595767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      C,                                     // AST context
13605767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      DC,                                    // Decl context
13615767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      Loc,                                   // Start location
13625767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      Loc,                                   // Id location
1363579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      &C.Idents.get(VarName.str()),          // Id
1364579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      Ty,                                    // Type
1365579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      C.getTrivialTypeSourceInfo(Ty),        // Type info
13665767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::SC_None                         // Storage class
13675767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  );
1368579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  const clang::Type *T = Ty.getTypePtr();
13695767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  clang::Expr *ZeroInitializer =
1370d9ed6b51a3fe997aefdcd360f8bfc40b17c9ab91Stephen Hines      RSObjectRefCount::CreateEmptyInitListExpr(C, Loc);
13715767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  ZeroInitializer->setType(T->getCanonicalTypeInternal());
1372579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  TmpDecl->setInit(ZeroInitializer);
1373579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  TmpDecl->markUsed(C);
1374579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::Decl* Decls[] = { TmpDecl };
13755767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
13765767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      C, Decls, sizeof(Decls) / sizeof(*Decls));
13775767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  clang::DeclStmt* DS = new (C) clang::DeclStmt(DGR, Loc, Loc);
13785767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  NewStmts.push_back(DS);
13795767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni
13805767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
13815767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      C,
13825767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::NestedNameSpecifierLoc(),       // QualifierLoc
13835767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      Loc,                                   // TemplateKWLoc
1384579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      TmpDecl,
13855767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      false,                                 // RefersToEnclosingVariableOrCapture
13865767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      Loc,                                   // NameLoc
1387579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      Ty,
13885767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::VK_LValue
13895767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  );
1390579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1391579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::Stmt *UpdatedStmt = nullptr;
1392579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  if (!RSExportPrimitiveType::IsRSObjectType(Ty.getTypePtr())) {
1393579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    // By definition, this is a struct assignment if we get here
1394579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    UpdatedStmt =
1395579e4f481774275980d6e3fbb7978c674da6d302Yang Ni        CreateStructRSSetObject(C, DRE, E, Loc, Loc);
1396579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  } else {
1397579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    UpdatedStmt =
1398579e4f481774275980d6e3fbb7978c674da6d302Yang Ni        CreateSingleRSSetObject(C, DRE, E, Loc, Loc);
1399579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  }
1400579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  NewStmts.push_back(UpdatedStmt);
1401579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1402579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  return DRE;
1403579e4f481774275980d6e3fbb7978c674da6d302Yang Ni}
1404579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1405579e4f481774275980d6e3fbb7978c674da6d302Yang Nivoid RSObjectRefCount::CreateParameterGuard(clang::ASTContext &C,
1406579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                            clang::DeclContext *DC,
1407579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                            clang::ParmVarDecl *PD,
1408579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                            std::vector<clang::Stmt*> &NewStmts) {
1409579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::SourceLocation Loc = PD->getLocStart();
1410579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::DeclRefExpr* ParamDRE = clang::DeclRefExpr::Create(
1411579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      C,
1412579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      clang::NestedNameSpecifierLoc(),       // QualifierLoc
1413579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      Loc,                                   // TemplateKWLoc
1414579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      PD,
1415579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      false,                                 // RefersToEnclosingVariableOrCapture
1416579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      Loc,                                   // NameLoc
1417579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      PD->getType(),
1418579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      clang::VK_RValue
1419579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  );
1420579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1421579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  CreateGuard(C, DC, ParamDRE,
1422579e4f481774275980d6e3fbb7978c674da6d302Yang Ni              llvm::Twine(".rs.param.") + llvm::Twine(PD->getName()), NewStmts);
1423579e4f481774275980d6e3fbb7978c674da6d302Yang Ni}
1424579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1425579e4f481774275980d6e3fbb7978c674da6d302Yang Nivoid RSObjectRefCount::HandleParamsAndLocals(clang::FunctionDecl *FD) {
1426579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt*> NewStmts;
1427579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::list<clang::ParmVarDecl*> ObjParams;
1428579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  for (clang::ParmVarDecl *Param : FD->parameters()) {
1429579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    clang::QualType QT = Param->getType();
1430579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    if (CountRSObjectTypes(QT.getTypePtr())) {
1431579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      // Ignore non-object types
1432579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      RSObjectRefCount::CreateParameterGuard(mCtx, FD, Param, NewStmts);
1433579e4f481774275980d6e3fbb7978c674da6d302Yang Ni      ObjParams.push_back(Param);
1434579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    }
1435579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  }
1436579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1437579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::Stmt *OldBody = FD->getBody();
1438579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  if (ObjParams.empty()) {
1439579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    Visit(OldBody);
1440579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    return;
1441579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  }
1442579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1443579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  NewStmts.push_back(OldBody);
1444579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1445579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::SourceLocation Loc = FD->getLocStart();
1446579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::CompoundStmt *NewBody = BuildCompoundStmt(mCtx, NewStmts, Loc);
1447579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  Scope S(NewBody);
1448579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  for (clang::ParmVarDecl *Param : ObjParams) {
1449579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    S.addRSObject(Param);
1450579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  }
1451579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  mScopeStack.push_back(&S);
1452579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1453579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // To avoid adding unnecessary ref counting artifacts to newly added temporary
1454579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // local variables for parameters, visits only the old function body here.
1455579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  Visit(OldBody);
1456579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1457579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  FD->setBody(NewBody);
1458579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1459579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  S.InsertLocalVarDestructors();
1460579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  mScopeStack.pop_back();
1461579e4f481774275980d6e3fbb7978c674da6d302Yang Ni}
1462579e4f481774275980d6e3fbb7978c674da6d302Yang Ni
1463579e4f481774275980d6e3fbb7978c674da6d302Yang Niclang::CompoundStmt* RSObjectRefCount::CreateRetStmtWithTempVar(
1464579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    clang::ASTContext& C,
1465579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    clang::DeclContext* DC,
1466579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    clang::ReturnStmt* RS,
1467579e4f481774275980d6e3fbb7978c674da6d302Yang Ni    const unsigned id) {
1468579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt*> NewStmts;
1469579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // Since we insert rsClearObj() calls before the return statement, we need
1470579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // to make sure none of the cleared RS objects are referenced in the
1471579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // return statement.
1472579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // For that, we create a new local variable named .rs.retval, assign the
1473579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // original return expression to it, make all necessary rsClearObj()
1474579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // calls, then return .rs.retval. Note rsClearObj() is not called on
1475579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  // .rs.retval.
1476579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::SourceLocation Loc = RS->getLocStart();
1477579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::Expr* RetVal = RS->getRetValue();
1478579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  const clang::QualType RetTy = RetVal->getType();
1479579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::DeclRefExpr *DRE = CreateGuard(C, DC, RetVal,
1480579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                        llvm::Twine(".rs.retval") + llvm::Twine(id),
1481579e4f481774275980d6e3fbb7978c674da6d302Yang Ni                                        NewStmts);
14825767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni
14835767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  // Creates a new return statement
1484579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  clang::ReturnStmt* NewRet = new (C) clang::ReturnStmt(Loc);
14855767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
14865767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      C,
14875767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      RetTy,
14885767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::CK_LValueToRValue,
14895767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      DRE,
14905767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      nullptr,
14915767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni      clang::VK_RValue
14925767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  );
14935767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  NewRet->setRetValue(CastExpr);
14945767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  NewStmts.push_back(NewRet);
14955767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni
14965767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni  return BuildCompoundStmt(C, NewStmts, Loc);
14975767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni}
14985767c359bac779b5d76d668ca5699fd5a0e3efc5Yang Ni
14994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1500b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  VisitStmt(DS);
1501b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->setCurrentStmt(DS);
15024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
15034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
15044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
15054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
15064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
15074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
1508cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      DataType DT = DataTypeUnknown;
15095abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes      clang::Expr *InitExpr = nullptr;
1510e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      if (InitializeRSObject(VD, &DT, &InitExpr)) {
1511b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        // We need to zero-init all RS object types (including matrices), ...
1512d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
1513b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        // ... but, only add to the list of RS objects if we have some
1514b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        // non-matrix RS object fields.
151565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross        if (CountRSObjectTypes(VD->getType().getTypePtr())) {
1516b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines          getCurrentScope()->addRSObject(VD);
1517b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        }
1518e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      }
15194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
15204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
15214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
15224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1523b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::VisitCallExpr(clang::CallExpr* CE) {
1524b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::QualType RetTy;
1525b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  const clang::FunctionDecl* FD = CE->getDirectCallee();
1526b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1527b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  if (FD) {
1528b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    // Direct calls
1529b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1530b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    RetTy = FD->getReturnType();
1531b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  } else {
1532b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    // Indirect calls through function pointers
1533b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1534b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::Expr* Callee = CE->getCallee();
1535b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::Type* CalleeType = Callee->getType().getTypePtr();
1536b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::PointerType* PtrType = CalleeType->getAs<clang::PointerType>();
1537b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1538b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (!PtrType) {
1539b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      return;
1540b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1541b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1542b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::Type* PointeeType = PtrType->getPointeeType().getTypePtr();
1543b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    const clang::FunctionType* FuncType = PointeeType->getAs<clang::FunctionType>();
1544b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1545b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (!FuncType) {
1546b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      return;
1547b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1548b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1549b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    RetTy = FuncType->getReturnType();
1550b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1551b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
15529e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // The RenderScript runtime API maintains the invariant that the sysRef of a new RS object would
15539e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // be 1, with the exception of rsGetAllocation() (deprecated in API 22), which leaves the sysRef
15549e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // 0 for a new allocation. It is the responsibility of the callee of the API to decrement the
15559e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // sysRef when a reference of the RS object goes out of scope. The compiler generates code to do
15569e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // just that, by creating a temporary variable named ".rs.tmpN" with the result of
15579e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // an RS-object-returning API directly assigned to it, and calling rsClearObject() on .rs.tmpN
15589e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // right before it exits the current scope. Such code generation is skipped for rsGetAllocation()
15599e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  // to avoid decrementing its sysRef below zero.
15609e580014469e0c87e95fcb31e78738a336b1f200Yang Ni
15619e580014469e0c87e95fcb31e78738a336b1f200Yang Ni  if (CountRSObjectTypes(RetTy.getTypePtr())==0 ||
15629e580014469e0c87e95fcb31e78738a336b1f200Yang Ni      (FD && FD->getName() == "rsGetAllocation")) {
1563b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return;
1564b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1565b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1566b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::SourceLocation Loc = CE->getSourceRange().getBegin();
1567b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  std::stringstream ss;
1568b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  ss << ".rs.tmp" << getNextID();
1569b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  llvm::StringRef VarName(ss.str());
1570b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1571b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::VarDecl* TempVarDecl = clang::VarDecl::Create(
1572b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx,                                  // AST context
1573b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      GetDeclContext(),                      // Decl context
1574b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Loc,                                   // Start location
1575b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Loc,                                   // Id location
1576b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      &mCtx.Idents.get(VarName),             // Id
1577b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      RetTy,                                 // Type
1578b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx.getTrivialTypeSourceInfo(RetTy),  // Type info
1579b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::SC_None                         // Storage class
1580b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  );
1581b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  TempVarDecl->setInit(CE);
1582041656a24663cb4f7a61a598e848f217c893cebfStephen Hines  TempVarDecl->markUsed(mCtx);
1583b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::Decl* Decls[] = { TempVarDecl };
1584b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
1585b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx, Decls, sizeof(Decls) / sizeof(*Decls));
1586b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::DeclStmt* DS = new (mCtx) clang::DeclStmt(DGR, Loc, Loc);
1587b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1588b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->InsertStmt(mCtx, DS);
1589b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1590b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
1591b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx,                                  // AST context
1592b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::NestedNameSpecifierLoc(),       // QualifierLoc
1593b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Loc,                                   // TemplateKWLoc
1594b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      TempVarDecl,
1595b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      false,                                 // RefersToEnclosingVariableOrCapture
1596b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      Loc,                                   // NameLoc
1597b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      RetTy,
1598b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::VK_LValue
1599b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  );
1600b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
1601b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      mCtx,
1602b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      RetTy,
1603b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::CK_LValueToRValue,
1604b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      DRE,
1605b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      nullptr,
1606b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      clang::VK_RValue
1607b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  );
1608b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1609b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->ReplaceExpr(mCtx, CE, CastExpr);
1610b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1611b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Register TempVarDecl for destruction call (rsClearObj).
1612b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->addRSObject(TempVarDecl);
1613b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1614b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
16154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1616b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  if (!emptyScope()) {
1617b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    getCurrentScope()->setCurrentStmt(CS);
1618b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1619b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
16204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
16214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
16224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
1623b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    mScopeStack.push_back(S);
16244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
16254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
16264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
16274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
16286e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
16291bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
1630b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    mScopeStack.pop_back();
16314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
16324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
16334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
16344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
16354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
1636b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->setCurrentStmt(AS);
1637c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
1638c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
163965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  if (CountRSObjectTypes(QT.getTypePtr())) {
1640d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    getCurrentScope()->ReplaceRSObjectAssignment(AS);
1641c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
16424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
16434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1644b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Nivoid RSObjectRefCount::VisitReturnStmt(clang::ReturnStmt *RS) {
1645b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->setCurrentStmt(RS);
1646b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1647b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // If there is no local rsObject declared so far, no need to transform the
1648b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // return statement.
1649b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1650b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  bool RSObjDeclared = false;
1651b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1652b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  for (const Scope* S : mScopeStack) {
1653b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    if (S->hasRSObject()) {
1654b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      RSObjDeclared = true;
1655b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni      break;
1656b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    }
1657b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1658b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1659b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  if (!RSObjDeclared) {
1660b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return;
1661b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1662b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1663b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // If the return statement does not return anything, or if it does not return
1664b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // a rsObject, no need to transform it.
1665b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1666b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::Expr* RetVal = RS->getRetValue();
1667b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  if (!RetVal || CountRSObjectTypes(RetVal->getType().getTypePtr()) == 0) {
1668b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni    return;
1669b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  }
1670b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1671b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // Transform the return statement so that it does not potentially return or
1672b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  // reference a rsObject that has been cleared.
1673b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1674b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  clang::CompoundStmt* NewRS;
1675b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  NewRS = CreateRetStmtWithTempVar(mCtx, GetDeclContext(), RS, getNextID());
1676b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
1677b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->ReplaceStmt(mCtx, NewRS);
1678b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni}
1679b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni
16804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1681b478c3dd0a47dc4c0c884d911819c9cf53c46649Yang Ni  getCurrentScope()->setCurrentStmt(S);
16824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
16834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
16844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
16854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
16864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
16874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
16884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
16894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
16904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1691688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines// This function walks the list of global variables and (potentially) creates
1692688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines// a single global static destructor function that properly decrements
1693688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines// reference counts on the contained RS object types.
1694688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hinesclang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
1695688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  Init();
1696688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1697688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
1698688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::SourceLocation loc;
1699688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
17003f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  llvm::StringRef SR(".rs.dtor");
17013f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  clang::IdentifierInfo &II = mCtx.Idents.get(SR);
17023f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  clang::DeclarationName N(&II);
17033f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  clang::FunctionProtoType::ExtProtoInfo EPI;
170482d7288620fade361dd8f7408b5db54a55c2c794Stephen Hines  clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
170582d7288620fade361dd8f7408b5db54a55c2c794Stephen Hines      llvm::ArrayRef<clang::QualType>(), EPI);
17065abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::FunctionDecl *FD = nullptr;
17073f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines
1708688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // Generate rsClearObject() call chains for every global variable
1709688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // (whether static or extern).
1710579e4f481774275980d6e3fbb7978c674da6d302Yang Ni  std::vector<clang::Stmt *> StmtList;
1711688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
1712688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines          E = DC->decls_end(); I != E; I++) {
1713688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
1714688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    if (VD) {
171565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      if (CountRSObjectTypes(VD->getType().getTypePtr())) {
17163f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        if (!FD) {
17173f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines          // Only create FD if we are going to use it.
17185abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, nullptr,
17194b3f3bada7155de983e7d92fa8b20091629b3bb3Stephen Hines                                           clang::SC_None);
17203f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        }
1721cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        // Mark VD as used.  It might be unused, except for the destructor.
1722cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        // 'markUsed' has side-effects that are caused only if VD is not already
1723cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        // used.  Hence no need for an extra check here.
1724cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        VD->markUsed(mCtx);
17253f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        // Make sure to create any helpers within the function's DeclContext,
17263f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        // not the one associated with the global translation unit.
17273f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
1728688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines        StmtList.push_back(RSClearObjectCall);
1729688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines      }
1730688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    }
1731688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  }
1732688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1733688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // Nothing needs to be destroyed, so don't emit a dtor.
1734688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  if (StmtList.empty()) {
17355abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
1736688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  }
1737688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1738688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
1739688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1740688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  FD->setBody(CS);
1741c8f5b2dad5c4ad2294d180b562d486342f29fb55I-Jui (Ray) Sung  // We need some way to tell if this FD is generated by slang
1742c8f5b2dad5c4ad2294d180b562d486342f29fb55I-Jui (Ray) Sung  FD->setImplicit();
1743688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1744688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  return FD;
1745688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines}
1746688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
174765f23ed862e1a1e16477ba740f295ff4a83ac822David Grossbool HasRSObjectType(const clang::Type *T) {
174865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  return CountRSObjectTypes(T) != 0;
174965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross}
175065f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
1751e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
1752