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
19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <list>
20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/DeclGroup.h"
224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Expr.h"
23be27482cdeaf08576bc39b72a15d35d13014a636Logan#include "clang/AST/NestedNameSpecifier.h"
244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/OperationKinds.h"
254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Stmt.h"
264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h"
274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
286e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
298024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang.h"
30292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines#include "slang_rs_ast_replace.h"
314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
33e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
35474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet/* Even though those two arrays are of size DataTypeMax, only entries that
36474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet * correspond to object types will be set.
37474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet */
38474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouilletclang::FunctionDecl *
39cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc BrouilletRSObjectRefCount::RSSetObjectFD[DataTypeMax];
40474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouilletclang::FunctionDecl *
41cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc BrouilletRSObjectRefCount::RSClearObjectFD[DataTypeMax];
421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
43f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesvoid RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
44cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  for (unsigned i = 0; i < DataTypeMax; i++) {
455abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    RSSetObjectFD[i] = nullptr;
465abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    RSClearObjectFD[i] = nullptr;
471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = TUDecl->decls_end(); I != E; I++) {
531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((I->getKind() >= clang::Decl::firstFunction) &&
541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        (I->getKind() <= clang::Decl::lastFunction)) {
551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // points to RSSetObjectFD or RSClearObjectFD
581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl **RSObjectFD;
591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      if (FD->getName() == "rsSetObject") {
616e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 2) &&
626e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsSetObject function prototype (# params)");
631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
656e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 1) &&
666e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsClearObject function prototype (# params)");
671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSClearObjectFD;
68e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      } else {
691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        continue;
701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType PVT = PVD->getOriginalType();
741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The first parameter must be a pointer like rs_allocation*
756e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(PVT->isPointerType() &&
766e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines          "Invalid rs{Set,Clear}Object function prototype (pointer param)");
771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The rs object type passed to the FD
791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType RST = PVT->getPointeeType();
80cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      DataType DT = RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
816e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             && "must be RS object type");
831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
84cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      if (DT >= 0 && DT < DataTypeMax) {
85474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet          RSObjectFD[DT] = FD;
86474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      } else {
87474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet          slangAssert(false && "incorrect type");
88474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      }
891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
911bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
921bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
934464d825c11349068f2917f9ebee86b721423f3cStephen Hinesnamespace {
944464d825c11349068f2917f9ebee86b721423f3cStephen Hines
95283a6cf32b808c703b219862ac491df3c9fc8b4bYang Niunsigned CountRSObjectTypes(const clang::Type *T);
96283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
97283a6cf32b808c703b219862ac491df3c9fc8b4bYang Niclang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
98283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                     clang::Expr *DstExpr,
99283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                     clang::Expr *SrcExpr,
100283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                     clang::SourceLocation StartLoc,
101283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                     clang::SourceLocation Loc);
102283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
103292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// This function constructs a new CompoundStmt from the input StmtList.
104283a6cf32b808c703b219862ac491df3c9fc8b4bYang Niclang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
105292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
106d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  unsigned NewStmtCount = StmtList.size();
107292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  unsigned CompoundStmtCount = 0;
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
109292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **CompoundStmtList;
110292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  CompoundStmtList = new clang::Stmt*[NewStmtCount];
1111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
112292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
113292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*>::const_iterator E = StmtList.end();
114292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; I != E; I++) {
115292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    CompoundStmtList[CompoundStmtCount++] = *I;
1161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
117292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CompoundStmtCount == NewStmtCount);
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
11923c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
12023c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);
1211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
122292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  delete [] CompoundStmtList;
1231bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
124292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return CS;
1251bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1261bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
127283a6cf32b808c703b219862ac491df3c9fc8b4bYang Nivoid AppendAfterStmt(clang::ASTContext &C,
128283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                     clang::CompoundStmt *CS,
129283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                     clang::Stmt *S,
130283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                     std::list<clang::Stmt*> &StmtList) {
131292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CS);
132e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
133292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::CompoundStmt::body_iterator bE = CS->body_end();
134292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **UpdatedStmtList =
135292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      new clang::Stmt*[CS->size() + StmtList.size()];
136e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
137e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned UpdatedStmtCount = 0;
138e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned Once = 0;
139292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; bI != bE; bI++) {
140292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
141292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // If we come across a return here, we don't have anything we can
142292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // reasonably replace. We should have already inserted our destructor
143292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // code in the proper spot, so we just clean up and return.
144292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      delete [] UpdatedStmtList;
145292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
146292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      return;
147e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    }
148e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
149292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
150c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
151292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if ((*bI == S) && !Once) {
152292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      Once++;
153292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
154292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator E = StmtList.end();
155292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      for ( ; I != E; I++) {
156292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines        UpdatedStmtList[UpdatedStmtCount++] = *I;
157292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      }
158292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    }
159c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
160292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(Once <= 1);
161c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
1625abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  // When S is nullptr, we are appending to the end of the CompoundStmt.
163292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (!S) {
164292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    slangAssert(Once == 0);
165292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
166292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator E = StmtList.end();
167292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    for ( ; I != E; I++) {
168292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *I;
169c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    }
170c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
171c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
1728f093e05e28046b6fc74175b66a06152f72e0c66Pirama Arumuga Nainar  CS->setStmts(C, llvm::makeArrayRef(UpdatedStmtList, UpdatedStmtCount));
173c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
174c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  delete [] UpdatedStmtList;
175c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
176c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
177283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// This class visits a compound statement and collects a list of all the exiting
178283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// statements, such as any return statement in any sub-block, and any
179283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// break/continue statement that would resume outside the current scope.
180283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// We do not handle the case for goto statements that leave a local scope.
1814464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
1824464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
183292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The loop depth of the currently visited node.
184292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mLoopDepth;
185292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
186292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The switch statement depth of the currently visited node.
187292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // Note that this is tracked separately from the loop depth because
188292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // SwitchStmt-contained ContinueStmt's should have destructors for the
189292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // corresponding loop scope.
190292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mSwitchDepth;
191292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
192283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  // Output of the visitor: the statements that should be replaced by compound
193283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  // statements, each of which contains rsClearObject() calls followed by the
194283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  // original statement.
195283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  std::vector<clang::Stmt*> mExitingStmts;
196a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines
1974464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
198283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  DestructorVisitor() : mLoopDepth(0), mSwitchDepth(0) {}
199292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
200283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  const std::vector<clang::Stmt*>& getExitingStmts() const {
201283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    return mExitingStmts;
202292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
203292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
2044464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
205292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitBreakStmt(clang::BreakStmt *BS);
206292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitContinueStmt(clang::ContinueStmt *CS);
207292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitDoStmt(clang::DoStmt *DS);
208292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitForStmt(clang::ForStmt *FS);
209292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitReturnStmt(clang::ReturnStmt *RS);
210292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitSwitchStmt(clang::SwitchStmt *SS);
211292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitWhileStmt(clang::WhileStmt *WS);
2124464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
2134464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2144464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
21556916bec2734a6059e1d0f58959514c825c746f7Yang Ni  for (clang::Stmt* Child : S->children()) {
21656916bec2734a6059e1d0f58959514c825c746f7Yang Ni    if (Child) {
2174464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
2184464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
2194464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2204464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2214464d825c11349068f2917f9ebee86b721423f3cStephen Hines
222292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
223292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(BS);
224292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
225283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    mExitingStmts.push_back(BS);
226292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
227292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
228292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
229292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
230292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(CS);
231292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (mLoopDepth == 0) {
232292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    // Switch statements can have nested continues.
233283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    mExitingStmts.push_back(CS);
234292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
235292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
236292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
237292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
238292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
239292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(DS);
240292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
241292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
242292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
243292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
244292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
245292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(FS);
246292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
247292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
248292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
249292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
250283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  mExitingStmts.push_back(RS);
251292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
252292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
253292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
254292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth++;
255292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(SS);
256292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth--;
257292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
258292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
259292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
260292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
261292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(WS);
262292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
263292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
264292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
265f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::Expr *ClearSingleRSObject(clang::ASTContext &C,
266f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::Expr *RefRSVar,
267f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::SourceLocation Loc) {
268f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(RefRSVar);
269f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *T = RefRSVar->getType().getTypePtr();
270f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!T->isArrayType() &&
271f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should not be destroying arrays with this function");
272f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
273f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
2745abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((ClearObjectFD != nullptr) &&
275f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "rsClearObject doesn't cover all RS object types");
276f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
277f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
278f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDArgType =
279f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
280f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
281f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Example destructor for "rs_font localFont;"
282f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //
283f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // (CallExpr 'void'
284f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
285f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
286f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
287f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
288f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
289f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Get address of targeted RS object
290f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *AddrRefRSVar =
291f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
292f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  clang::UO_AddrOf,
293f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  ClearObjectFDArgType,
294be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
295be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
296f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  Loc);
297f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
298f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSClearObjectFD =
299f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclRefExpr::Create(C,
300be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
3010444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
302f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD,
303e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
304f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getLocation(),
305be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 ClearObjectFDType,
306be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
3075abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
308f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
309f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RSClearObjectFP =
310f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::ImplicitCastExpr::Create(C,
311f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      C.getPointerType(ClearObjectFDType),
312f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::CK_FunctionToPointerDecay,
313f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      RefRSClearObjectFD,
3145abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
315f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::VK_RValue);
31603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
3171dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 1> ArgList;
3181dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(AddrRefRSVar);
3191dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines
320f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CallExpr *RSClearObjectCall =
321f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CallExpr(C,
322f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             RSClearObjectFP,
3231dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                             ArgList,
324f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             ClearObjectFD->getCallResultType(),
325be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
326f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             Loc);
327f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
328f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSClearObjectCall;
329f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
330f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
331f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic int ArrayDim(const clang::Type *T) {
33203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
33303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
33403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
33503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
33603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
33703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
3389d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
33903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
34003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
341283a6cf32b808c703b219862ac491df3c9fc8b4bYang Niclang::Stmt *ClearStructRSObject(
342f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
343f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
344f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
345d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::SourceLocation StartLoc,
346f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc);
347f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
348283a6cf32b808c703b219862ac491df3c9fc8b4bYang Niclang::Stmt *ClearArrayRSObject(
349f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
350f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
351f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSArr,
352cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    clang::SourceLocation StartLoc,
353f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
354f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
355f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(BaseType->isArrayType());
356f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
357f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  int NumArrayElements = ArrayDim(BaseType);
358f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Actually extract out the base RS object type for use later
359f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
36003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
36103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
3625abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
36303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
36403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
36503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
36603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
367cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // (ForStmt
368cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (DeclStmt
369cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (VarDecl used rsIntIter 'int' cinit
370cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (IntegerLiteral 'int' 0)))
371cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (BinaryOperator 'int' '<'
372cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (ImplicitCastExpr int LValueToRValue
37303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
374cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (IntegerLiteral 'int' 10)
375cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   nullptr << CondVar >>
376cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (UnaryOperator 'int' postfix '++'
377cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (DeclRefExpr 'int' Var='rsIntIter'))
378cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (CallExpr 'void'
379cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
380cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
381cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (UnaryOperator 'rs_font *' prefix '&'
382cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (ArraySubscriptExpr 'rs_font':'rs_font'
383cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //         (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
384cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //           (DeclRefExpr 'rs_font [10]' Var='fontArr'))
385cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //         (DeclRefExpr 'int' Var='rsIntIter'))))))
38603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
388cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  static unsigned sIterCounter = 0;
389cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  std::stringstream UniqueIterName;
390cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  UniqueIterName << "rsIntIter" << sIterCounter++;
391cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::IdentifierInfo *II = &C.Idents.get(UniqueIterName.str());
39203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
39303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
394f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             DC,
395cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                             StartLoc,
39603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
397cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                             II,
39803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
39903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
40003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
401cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar  // Mark "rsIntIter" as used
402cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar  IIVD->markUsed(C);
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
40503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
40603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
40703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
408cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // Init -> "int rsIntIter = 0"
409cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
410cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
411cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  IIVD->setInit(Int0);
412cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines
413cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
414cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
415cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Stmt *Init = new(C) clang::DeclStmt(DGR, Loc, Loc);
416cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines
417cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // Cond -> "rsIntIter < NumArrayElements"
418cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::DeclRefExpr *RefrsIntIterLValue =
41903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
420be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
4210444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
423e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
42403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
425be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
426cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                 clang::VK_LValue,
4275abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
42803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
429cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Expr *RefrsIntIterRValue =
430cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      clang::ImplicitCastExpr::Create(C,
431cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      RefrsIntIterLValue->getType(),
432cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      clang::CK_LValueToRValue,
433cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      RefrsIntIterLValue,
434cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      nullptr,
435cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      clang::VK_RValue);
43603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
43803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
43903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
44003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
441cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      new(C) clang::BinaryOperator(RefrsIntIterRValue,
44203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
44303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
44403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
445be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
446be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
44723c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   Loc,
44823c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   false);
44903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
45003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
45103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
452cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      new(C) clang::UnaryOperator(RefrsIntIterLValue,
45303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
45403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
455be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
456be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
45703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
45803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
45903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
46003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
46103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
462f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtr =
46303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
464f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
46503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
466f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          RefRSArr,
4675abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
46803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
46903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
470f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtrSubscript =
471f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
472cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                       RefrsIntIterRValue,
473f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       BaseType->getCanonicalTypeInternal(),
474be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
475be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
476f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       Loc);
47703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
478cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
479f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
4805abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *RSClearObjectCall = nullptr;
481f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (BaseType->isArrayType()) {
482f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
483cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
484cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  } else if (DT == DataTypeUnknown) {
485f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
486cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
487f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
488f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
489f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
49003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
49103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
49203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
49303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
49403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
4955abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                            nullptr,  // no condVar
49603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
49703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
49803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
49903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
50003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
50103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
502cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  return DestructorLoop;
50303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
50403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
505283a6cf32b808c703b219862ac491df3c9fc8b4bYang Niunsigned CountRSObjectTypes(const clang::Type *T) {
506f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(T);
507f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned RSObjectCount = 0;
508f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
509f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
51065f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
511f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
512f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
513cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
514cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT != DataTypeUnknown) {
515f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
516f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
517f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
518d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  if (T->isUnionType()) {
519d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
520d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RD = RD->getDefinition();
521d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
522d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines           FE = RD->field_end();
523d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines         FI != FE;
524d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines         FI++) {
525d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      const clang::FieldDecl *FD = *FI;
526d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
52765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      if (CountRSObjectTypes(FT)) {
52878e69cb06b9b0683b2ac9dcafde87b867690ef2fStephen Hines        slangAssert(false && "can't have unions with RS object types!");
529d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        return 0;
530d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      }
531d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    }
532d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  }
533d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines
534f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (!T->isStructureType()) {
535f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return 0;
536f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
537f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
538f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
539f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
540f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
541f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
542f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
543f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
544f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::FieldDecl *FD = *FI;
545f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
54665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (CountRSObjectTypes(FT)) {
547f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // Sub-structs should only count once (as should arrays, etc.)
548f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSObjectCount++;
549f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
550f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
551f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
552f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSObjectCount;
553f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
554f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
555283a6cf32b808c703b219862ac491df3c9fc8b4bYang Niclang::Stmt *ClearStructRSObject(
556f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
557f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
558f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
559cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    clang::SourceLocation StartLoc,
560f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
561f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
562f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
563f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!BaseType->isArrayType());
564f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
565f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Structs should show up as unknown primitive types
5669be9360d8e02b52ed669afbd69f9becb575c3f0dAlex Sakhartchouk  slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
567cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet              DataTypeUnknown);
568f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
56965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
570b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines  slangAssert(FieldsToDestroy != 0);
571f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
572f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned StmtCount = 0;
573f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
5742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToDestroy; i++) {
5755abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    StmtArray[i] = nullptr;
5762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
577f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
578f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Populate StmtArray by creating a destructor for each RS object field
579f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
580f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
581f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
582f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
583f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
584f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
585f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // We just look through all field declarations to see if we find a
586f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // declaration for an RS object type (or an array of one).
587f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    bool IsArrayType = false;
588f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::FieldDecl *FD = *FI;
589f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
590f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *OrigType = FT;
591f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    while (FT && FT->isArrayType()) {
592f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
593f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      IsArrayType = true;
594f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
595f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
596cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    // Pass a DeclarationNameInfo with a valid DeclName, since name equality
597cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    // gets asserted during CodeGen.
598cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    clang::DeclarationNameInfo FDDeclNameInfo(FD->getDeclName(),
599cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar                                              FD->getLocation());
600cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar
601f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
602f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
603f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
604f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
605f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
606f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
607f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
6080b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                    clang::SourceLocation(),
609be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
6100444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                    clang::SourceLocation(),
611f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
612f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
613cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar                                    FDDeclNameInfo,
6145abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                    nullptr,
615be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
616be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
617be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
618f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
619f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      slangAssert(StmtCount < FieldsToDestroy);
620f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
621f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
622f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
623f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
624f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
625cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                    StartLoc,
626f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
627f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
628f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearSingleRSObject(C,
629f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
630f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
631f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
63265f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
633f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // In this case, we have a nested struct. We may not end up filling all
634f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // of the spaces in StmtArray (sub-structs should handle themselves
635f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // with separate compound statements).
636f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
637f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
638f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
639f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
640f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
641f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
6420b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                    clang::SourceLocation(),
643be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
6440444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                    clang::SourceLocation(),
645f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
646f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
647f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
6485abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                    nullptr,
649be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
650be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
651be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
652f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
653f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
654f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
655f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
656f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
657cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                    StartLoc,
658f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
659f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
660f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearStructRSObject(C,
661f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     DC,
662f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
663cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                     StartLoc,
664f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
665f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
666f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
667f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
668f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
669f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(StmtCount > 0);
67023c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
67123c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
672f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
673f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  delete [] StmtArray;
674f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
675f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return CS;
676f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
677f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
678283a6cf32b808c703b219862ac491df3c9fc8b4bYang Niclang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
679283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                     clang::Expr *DstExpr,
680283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                     clang::Expr *SrcExpr,
681283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                     clang::SourceLocation StartLoc,
682283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                     clang::SourceLocation Loc) {
6832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = DstExpr->getType().getTypePtr();
6842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
6855abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((SetObjectFD != nullptr) &&
6866e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
687c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
688c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
689c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
690c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
691c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
692c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
693c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
694c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
695be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
6960444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
697c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
698e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
699c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
700be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
701be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
7025abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
703c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
704c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
705c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
706c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
707c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
708c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
7095abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
710c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
711c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
7121dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 2> ArgList;
7131dfc415431ddd360354fecfcd9b12dcaf686355aSt