slang_rs_object_ref_count.cpp revision cd57c5447d831a237d0917a0d687749e6348a46d
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
95292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// This function constructs a new CompoundStmt from the input StmtList.
96292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesstatic clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
97292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
98d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  unsigned NewStmtCount = StmtList.size();
99292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  unsigned CompoundStmtCount = 0;
1001bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
101292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **CompoundStmtList;
102292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  CompoundStmtList = new clang::Stmt*[NewStmtCount];
1031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
104292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
105292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*>::const_iterator E = StmtList.end();
106292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; I != E; I++) {
107292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    CompoundStmtList[CompoundStmtCount++] = *I;
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
109292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CompoundStmtCount == NewStmtCount);
1101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
11123c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
11223c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);
1131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
114292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  delete [] CompoundStmtList;
1151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
116292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return CS;
1171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
119292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesstatic void AppendAfterStmt(clang::ASTContext &C,
120e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::CompoundStmt *CS,
121292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                            clang::Stmt *S,
122292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                            std::list<clang::Stmt*> &StmtList) {
123292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CS);
124e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
125292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::CompoundStmt::body_iterator bE = CS->body_end();
126292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **UpdatedStmtList =
127292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      new clang::Stmt*[CS->size() + StmtList.size()];
128e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
129e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned UpdatedStmtCount = 0;
130e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned Once = 0;
131292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; bI != bE; bI++) {
132292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
133292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // If we come across a return here, we don't have anything we can
134292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // reasonably replace. We should have already inserted our destructor
135292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // code in the proper spot, so we just clean up and return.
136292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      delete [] UpdatedStmtList;
137292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
138292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      return;
139e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    }
140e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
141292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
142c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
143292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if ((*bI == S) && !Once) {
144292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      Once++;
145292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
146292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator E = StmtList.end();
147292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      for ( ; I != E; I++) {
148292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines        UpdatedStmtList[UpdatedStmtCount++] = *I;
149292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      }
150292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    }
151c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
152292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(Once <= 1);
153c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
1545abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  // When S is nullptr, we are appending to the end of the CompoundStmt.
155292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (!S) {
156292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    slangAssert(Once == 0);
157292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
158292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator E = StmtList.end();
159292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    for ( ; I != E; I++) {
160292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *I;
161c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    }
162c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
163c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
164c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
165c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
166c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  delete [] UpdatedStmtList;
167c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
168c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
169a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines// This class visits a compound statement and inserts DtorStmt
170a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines// in proper locations. This includes inserting it before any
1714464d825c11349068f2917f9ebee86b721423f3cStephen Hines// return statement in any sub-block, at the end of the logical enclosing
1724464d825c11349068f2917f9ebee86b721423f3cStephen Hines// scope (compound statement), and/or before any break/continue statement that
1734464d825c11349068f2917f9ebee86b721423f3cStephen Hines// would resume outside the declared scope. We will not handle the case for
1744464d825c11349068f2917f9ebee86b721423f3cStephen Hines// goto statements that leave a local scope.
175292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines//
176292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// To accomplish these goals, it collects a list of sub-Stmt's that
177292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// correspond to scope exit points. It then uses an RSASTReplace visitor to
178292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// transform the AST, inserting appropriate destructors before each of those
179292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// sub-Stmt's (and also before the exit of the outermost containing Stmt for
180292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// the scope).
1814464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
1824464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
183d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  clang::ASTContext &mCtx;
184292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
185292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The loop depth of the currently visited node.
186292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mLoopDepth;
187292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
188292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The switch statement depth of the currently visited node.
189292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // Note that this is tracked separately from the loop depth because
190292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // SwitchStmt-contained ContinueStmt's should have destructors for the
191292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // corresponding loop scope.
192292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mSwitchDepth;
193292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
194292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The outermost statement block that we are currently visiting.
195292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // This should always be a CompoundStmt.
196292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt *mOuterStmt;
197292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
198a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  // The destructor to execute for this scope/variable.
199a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  clang::Stmt* mDtorStmt;
200292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
201292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The stack of statements which should be replaced by a compound statement
202a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  // containing the new destructor call followed by the original Stmt.
203292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::stack<clang::Stmt*> mReplaceStmtStack;
204292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
205a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  // The source location for the variable declaration that we are trying to
206a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  // insert destructors for. Note that InsertDestructors() will not generate
207a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  // destructor calls for source locations that occur lexically before this
208a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  // location.
209a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  clang::SourceLocation mVarLoc;
210a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines
2114464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
212292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  DestructorVisitor(clang::ASTContext &C,
213292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                    clang::Stmt* OuterStmt,
214a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines                    clang::Stmt* DtorStmt,
215a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines                    clang::SourceLocation VarLoc);
216292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
217292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // This code walks the collected list of Stmts to replace and actually does
218a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  // the replacement. It also finishes up by appending the destructor to the
219a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines  // current outermost CompoundStmt.
220292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void InsertDestructors() {
2215abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    clang::Stmt *S = nullptr;
222a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines    clang::SourceManager &SM = mCtx.getSourceManager();
223a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines    std::list<clang::Stmt *> StmtList;
224a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines    StmtList.push_back(mDtorStmt);
225a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines
226292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    while (!mReplaceStmtStack.empty()) {
227292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      S = mReplaceStmtStack.top();
228292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      mReplaceStmtStack.pop();
229292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
230a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines      // Skip all source locations that occur before the variable's
231a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines      // declaration, since it won't have been initialized yet.
232a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines      if (SM.isBeforeInTranslationUnit(S->getLocStart(), mVarLoc)) {
233a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines        continue;
234a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines      }
235a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines
236a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines      StmtList.push_back(S);
237292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      clang::CompoundStmt *CS =
238a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines          BuildCompoundStmt(mCtx, StmtList, S->getLocEnd());
239a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines      StmtList.pop_back();
240292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
241d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      RSASTReplace R(mCtx);
242292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      R.ReplaceStmt(mOuterStmt, S, CS);
243292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    }
244ab992e59a36a18df49bf4878968ef0598299afd3Logan Chien    clang::CompoundStmt *CS =
245ab992e59a36a18df49bf4878968ef0598299afd3Logan Chien      llvm::dyn_cast<clang::CompoundStmt>(mOuterStmt);
246292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    slangAssert(CS);
2475abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    AppendAfterStmt(mCtx, CS, nullptr, StmtList);
248292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
249292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
2504464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
2514464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitCompoundStmt(clang::CompoundStmt *CS);
252292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
253292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitBreakStmt(clang::BreakStmt *BS);
254292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitCaseStmt(clang::CaseStmt *CS);
255292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitContinueStmt(clang::ContinueStmt *CS);
256292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitDefaultStmt(clang::DefaultStmt *DS);
257292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitDoStmt(clang::DoStmt *DS);
258292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitForStmt(clang::ForStmt *FS);
259292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitIfStmt(clang::IfStmt *IS);
260292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitReturnStmt(clang::ReturnStmt *RS);
261292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitSwitchCase(clang::SwitchCase *SC);
262292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitSwitchStmt(clang::SwitchStmt *SS);
263292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitWhileStmt(clang::WhileStmt *WS);
2644464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
2654464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2664464d825c11349068f2917f9ebee86b721423f3cStephen HinesDestructorVisitor::DestructorVisitor(clang::ASTContext &C,
267292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                         clang::Stmt *OuterStmt,
268a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines                         clang::Stmt *DtorStmt,
269a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines                         clang::SourceLocation VarLoc)
270d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  : mCtx(C),
271292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mLoopDepth(0),
272292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mSwitchDepth(0),
273292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mOuterStmt(OuterStmt),
274a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines    mDtorStmt(DtorStmt),
275a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines    mVarLoc(VarLoc) {
2764464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2774464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2784464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
2794464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
2804464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I != E;
2814464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I++) {
2824464d825c11349068f2917f9ebee86b721423f3cStephen Hines    if (clang::Stmt *Child = *I) {
2834464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
2844464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
2854464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2864464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2874464d825c11349068f2917f9ebee86b721423f3cStephen Hines
288292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
289292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(CS);
290292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
291292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
292292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
293292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(BS);
294292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
295292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mReplaceStmtStack.push(BS);
296292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
297292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
298292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
299292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) {
300292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(CS);
301292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
302292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
303292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
304292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(CS);
305292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (mLoopDepth == 0) {
306292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    // Switch statements can have nested continues.
307292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mReplaceStmtStack.push(CS);
308292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
309292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
310292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
311292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) {
312292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(DS);
313292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
314292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
315292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
316292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
317292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(DS);
318292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
319292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
320292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
321292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
322292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
323292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(FS);
324292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
325292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
326292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
327292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) {
328292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(IS);
329292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
330292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
331292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
332292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mReplaceStmtStack.push(RS);
333292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
334292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
335292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) {
336292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(false && "Both case and default have specialized handlers");
337292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(SC);
338292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
339292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
340292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
341292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth++;
342292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(SS);
343292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth--;
344292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
345292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
346292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
347292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
348292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(WS);
349292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
350292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
351292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
352f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::Expr *ClearSingleRSObject(clang::ASTContext &C,
353f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::Expr *RefRSVar,
354f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::SourceLocation Loc) {
355f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(RefRSVar);
356f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *T = RefRSVar->getType().getTypePtr();
357f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!T->isArrayType() &&
358f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should not be destroying arrays with this function");
359f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
360f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
3615abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((ClearObjectFD != nullptr) &&
362f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "rsClearObject doesn't cover all RS object types");
363f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
364f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
365f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDArgType =
366f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
367f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
368f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Example destructor for "rs_font localFont;"
369f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //
370f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // (CallExpr 'void'
371f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
372f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
373f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
374f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
375f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
376f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Get address of targeted RS object
377f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *AddrRefRSVar =
378f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
379f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  clang::UO_AddrOf,
380f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  ClearObjectFDArgType,
381be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
382be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
383f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  Loc);
384f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
385f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSClearObjectFD =
386f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclRefExpr::Create(C,
387be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
3880444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
389f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD,
390e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
391f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getLocation(),
392be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 ClearObjectFDType,
393be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
3945abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
395f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
396f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RSClearObjectFP =
397f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::ImplicitCastExpr::Create(C,
398f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      C.getPointerType(ClearObjectFDType),
399f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::CK_FunctionToPointerDecay,
400f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      RefRSClearObjectFD,
4015abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
402f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::VK_RValue);
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
4041dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 1> ArgList;
4051dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(AddrRefRSVar);
4061dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines
407f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CallExpr *RSClearObjectCall =
408f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CallExpr(C,
409f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             RSClearObjectFP,
4101dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                             ArgList,
411f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             ClearObjectFD->getCallResultType(),
412be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
413f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             Loc);
414f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
415f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSClearObjectCall;
416f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
417f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
418f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic int ArrayDim(const clang::Type *T) {
41903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
42003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
42103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
42303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
42403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
4259d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
42603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
42703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
428f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
429f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
430f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
431f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
432d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::SourceLocation StartLoc,
433f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc);
434f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
435f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearArrayRSObject(
436f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
437f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
438f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSArr,
439cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    clang::SourceLocation StartLoc,
440f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
441f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
442f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(BaseType->isArrayType());
443f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
444f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  int NumArrayElements = ArrayDim(BaseType);
445f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Actually extract out the base RS object type for use later
446f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
44703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
44803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
4495abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
45003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
45103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
45203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
45303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
454cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // (ForStmt
455cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (DeclStmt
456cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (VarDecl used rsIntIter 'int' cinit
457cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (IntegerLiteral 'int' 0)))
458cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (BinaryOperator 'int' '<'
459cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (ImplicitCastExpr int LValueToRValue
46003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
461cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (IntegerLiteral 'int' 10)
462cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   nullptr << CondVar >>
463cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (UnaryOperator 'int' postfix '++'
464cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (DeclRefExpr 'int' Var='rsIntIter'))
465cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //   (CallExpr 'void'
466cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
467cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
468cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //     (UnaryOperator 'rs_font *' prefix '&'
469cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //       (ArraySubscriptExpr 'rs_font':'rs_font'
470cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //         (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
471cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //           (DeclRefExpr 'rs_font [10]' Var='fontArr'))
472cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  //         (DeclRefExpr 'int' Var='rsIntIter'))))))
47303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
47403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
475cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  static unsigned sIterCounter = 0;
476cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  std::stringstream UniqueIterName;
477cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  UniqueIterName << "rsIntIter" << sIterCounter++;
478cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::IdentifierInfo *II = &C.Idents.get(UniqueIterName.str());
47903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
48003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
481f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             DC,
482cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                             StartLoc,
48303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
484cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                             II,
48503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
48603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
48703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
488cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar  // Mark "rsIntIter" as used
489cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar  IIVD->markUsed(C);
49003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
49103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
49203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
49303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
49403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
495cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // Init -> "int rsIntIter = 0"
496cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
497cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
498cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  IIVD->setInit(Int0);
499cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines
500cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
501cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
502cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Stmt *Init = new(C) clang::DeclStmt(DGR, Loc, Loc);
503cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines
504cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  // Cond -> "rsIntIter < NumArrayElements"
505cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::DeclRefExpr *RefrsIntIterLValue =
50603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
507be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
5080444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
50903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
510e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
51103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
512be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
513cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                 clang::VK_LValue,
5145abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
51503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
516cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  clang::Expr *RefrsIntIterRValue =
517cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      clang::ImplicitCastExpr::Create(C,
518cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      RefrsIntIterLValue->getType(),
519cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      clang::CK_LValueToRValue,
520cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      RefrsIntIterLValue,
521cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      nullptr,
522cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                      clang::VK_RValue);
52303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
52403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
52503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
52603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
52703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
528cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      new(C) clang::BinaryOperator(RefrsIntIterRValue,
52903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
53003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
53103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
532be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
533be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
53423c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   Loc,
53523c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   false);
53603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
53703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
53803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
539cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines      new(C) clang::UnaryOperator(RefrsIntIterLValue,
54003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
54103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
542be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
543be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
54403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
54503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
54603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
54703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
54803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
549f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtr =
55003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
551f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
55203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
553f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          RefRSArr,
5545abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
55503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
55603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
557f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtrSubscript =
558f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
559cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines                                       RefrsIntIterRValue,
560f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       BaseType->getCanonicalTypeInternal(),
561be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
562be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
563f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       Loc);
56403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
565cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
566f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
5675abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *RSClearObjectCall = nullptr;
568f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (BaseType->isArrayType()) {
569f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
570cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
571cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  } else if (DT == DataTypeUnknown) {
572f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
573cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
574f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
575f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
576f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
57703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
57803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
57903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
58003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
58103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
5825abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                            nullptr,  // no condVar
58303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
58403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
58503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
58603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
58703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
58803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
589cd57c5447d831a237d0917a0d687749e6348a46dStephen Hines  return DestructorLoop;
59003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
59103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
592d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hinesstatic unsigned CountRSObjectTypes(clang::ASTContext &C,
593d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines                                   const clang::Type *T,
594d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines                                   clang::SourceLocation Loc) {
595f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(T);
596f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned RSObjectCount = 0;
597f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
598f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
599d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    return CountRSObjectTypes(C, T->getArrayElementTypeNoTypeQual(), Loc);
600f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
601f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
602cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
603cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT != DataTypeUnknown) {
604f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
605f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
606f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
607d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  if (T->isUnionType()) {
608d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
609d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RD = RD->getDefinition();
610d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
611d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines           FE = RD->field_end();
612d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines         FI != FE;
613d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines         FI++) {
614d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      const clang::FieldDecl *FD = *FI;
615d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
616d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      if (CountRSObjectTypes(C, FT, Loc)) {
61778e69cb06b9b0683b2ac9dcafde87b867690ef2fStephen Hines        slangAssert(false && "can't have unions with RS object types!");
618d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        return 0;
619d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      }
620d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    }
621d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  }
622d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines
623f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (!T->isStructureType()) {
624f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return 0;
625f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
626f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
627f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
628f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
629f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
630f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
631f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
632f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
633f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::FieldDecl *FD = *FI;
634f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
635d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    if (CountRSObjectTypes(C, FT, Loc)) {
636f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // Sub-structs should only count once (as should arrays, etc.)
637f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSObjectCount++;
638f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
639f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
640f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
641f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSObjectCount;
642f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
643f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
644f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
645f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
646f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
647f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
648cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    clang::SourceLocation StartLoc,
649f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
650f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
651f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
652f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!BaseType->isArrayType());
653f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
654f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Structs should show up as unknown primitive types
6559be9360d8e02b52ed669afbd69f9becb575c3f0dAlex Sakhartchouk  slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
656cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet              DataTypeUnknown);
657f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
658d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  unsigned FieldsToDestroy = CountRSObjectTypes(C, BaseType, Loc);
659b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines  slangAssert(FieldsToDestroy != 0);
660f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
661f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned StmtCount = 0;
662f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
6632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToDestroy; i++) {
6645abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    StmtArray[i] = nullptr;
6652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
666f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
667f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Populate StmtArray by creating a destructor for each RS object field
668f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
669f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
670f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
671f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
672f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
673f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
674f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // We just look through all field declarations to see if we find a
675f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // declaration for an RS object type (or an array of one).
676f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    bool IsArrayType = false;
677f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::FieldDecl *FD = *FI;
678f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
679f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *OrigType = FT;
680f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    while (FT && FT->isArrayType()) {
681f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
682f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      IsArrayType = true;
683f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
684f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
685cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    // Pass a DeclarationNameInfo with a valid DeclName, since name equality
686cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    // gets asserted during CodeGen.
687cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar    clang::DeclarationNameInfo FDDeclNameInfo(FD->getDeclName(),
688cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar                                              FD->getLocation());
689cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar
690f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
691f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
692f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
693f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
694f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
695f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
696f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
6970b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                    clang::SourceLocation(),
698be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
6990444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                    clang::SourceLocation(),
700f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
701f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
702cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar                                    FDDeclNameInfo,
7035abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                    nullptr,
704be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
705be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
706be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
707f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
708f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      slangAssert(StmtCount < FieldsToDestroy);
709f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
710f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
711f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
712f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
713f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
714cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                    StartLoc,
715f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
716f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
717f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearSingleRSObject(C,
718f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
719f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
720f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
721d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    } else if (FT->isStructureType() && CountRSObjectTypes(C, FT, Loc)) {
722f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // In this case, we have a nested struct. We may not end up filling all
723f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // of the spaces in StmtArray (sub-structs should handle themselves
724f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // with separate compound statements).
725f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
726f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
727f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
728f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
729f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
730f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
7310b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                    clang::SourceLocation(),
732be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
7330444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                    clang::SourceLocation(),
734f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
735f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
736f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
7375abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                    nullptr,
738be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
739be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
740be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
741f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
742f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
743f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
744f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
745f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
746cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                    StartLoc,
747f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
748f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
749f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearStructRSObject(C,
750f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     DC,
751f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
752cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                                     StartLoc,
753f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
754f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
755f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
756f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
757f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
758f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(StmtCount > 0);
75923c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
76023c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
761f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
762f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  delete [] StmtArray;
763f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
764f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return CS;
765f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
766f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
7672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
7682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *DstExpr,
7692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *SrcExpr,
770cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                            clang::SourceLocation StartLoc,
7712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc) {
7722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = DstExpr->getType().getTypePtr();
7732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
7745abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((SetObjectFD != nullptr) &&
7756e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
776c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
777c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
778c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
779c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
780c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
781c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
782c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
783c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
784be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
7850444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
786c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
787e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
788c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
789be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
790be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
7915abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
792c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
793c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
794c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
795c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
796c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
797c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
7985abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
799c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
800c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
8011dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 2> ArgList;
8021dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
8031dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::UO_AddrOf,
8041dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                SetObjectFDArgType[0],
8051dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::VK_RValue,
8061dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::OK_Ordinary,
8071dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                Loc));
8081dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(SrcExpr);
809c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
810c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CallExpr *RSSetObjectCall =
811c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      new(C) clang::CallExpr(C,
812c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             RSSetObjectFP,
813c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             ArgList,
814c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             SetObjectFD->getCallResultType(),
815be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
816c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             Loc);
817c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
8182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return RSSetObjectCall;
8192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
8202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
8222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *LHS,
8232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *RHS,
824cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                            clang::SourceLocation StartLoc,
8252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc);
8262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
827246fa17206bf78c59a64b2f7d98a6716d5345b81Al Sutton/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
8282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *DstArr,
8292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *SrcArr,
830cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                           clang::SourceLocation StartLoc,
8312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::SourceLocation Loc) {
8325abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::DeclContext *DC = nullptr;
8332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *BaseType = DstArr->getType().getTypePtr();
8342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(BaseType->isArrayType());
8352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int NumArrayElements = ArrayDim(BaseType);
8372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Actually extract out the base RS object type for use later
8382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
8392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8405abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *StmtArray[2] = {nullptr};
8412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int StmtCtr = 0;
8422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (NumArrayElements <= 0) {
8445abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
8452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
8462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Create helper variable for iterating through elements
8482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
8492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::VarDecl *IIVD =
8502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::VarDecl::Create(C,
8512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             DC,
852cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                             StartLoc,
8532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             Loc,
8542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             &II,
8552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.IntTy,
8562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
8572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None,
8582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None);
8592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
8602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
8622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
8632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Form the actual loop
8652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // for (Init; Cond; Inc)
8662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  //   RSSetObjectCall;
8672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Init -> "rsIntIter = 0"
8692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
8702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::DeclRefExpr::Create(C,
871be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
8722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 IIVD,
8732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 Loc,
874be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
875be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
8765abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
8772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
8792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
8802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Init =
8822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
8832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Int0,
8842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_Assign,
8852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
886be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
887be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
8882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
8892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
8912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
8922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
8932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Cond =
8952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
8962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   NumArrayElementsExpr,
8972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_LT,
8982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
899be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
900be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
9012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
9022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Inc -> "rsIntIter++"
9042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::UnaryOperator *Inc =
9052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
9062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::UO_PostInc,
9072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  C.IntTy,
908be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
909be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
9102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  Loc);
9112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
9132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Loop operates on individual array elements
9142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtr =
9162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
9172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
9182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
9192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          DstArr,
9205abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
9212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
9222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtrSubscript =
9242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(DstArrPtr,
9252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
9262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
927be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
928be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
9292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
9302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtr =
9322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
9332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
9342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
9352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          SrcArr,
9365abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          nullptr,
9372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
9382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtrSubscript =
9402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(SrcArrPtr,
9412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
9422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
943be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
944be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
9452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
9462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
947cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
9482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9495abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *RSSetObjectCall = nullptr;
9502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (BaseType->isArrayType()) {
951d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
952cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                             SrcArrPtrSubscript,
953cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                             StartLoc, Loc);
954cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  } else if (DT == DataTypeUnknown) {
955d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
956cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              SrcArrPtrSubscript,
957cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              StartLoc, Loc);
9582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
959d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
960cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              SrcArrPtrSubscript,
961cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                              StartLoc, Loc);
9622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
9632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ForStmt *DestructorLoop =
9652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ForStmt(C,
9662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Init,
9672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Cond,
9685abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                            nullptr,  // no condVar
9692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Inc,
9702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            RSSetObjectCall,
9712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
9722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
9732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc);
9742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
9762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(StmtCtr == 2);
9772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::CompoundStmt *CS =
9792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
9802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
982246fa17206bf78c59a64b2f7d98a6716d5345b81Al Sutton} */
9832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
9852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *LHS,
9862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *RHS,
987cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao                                            clang::SourceLocation StartLoc,
9882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc) {
9892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = LHS->getType();
9902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = QT.getTypePtr();
9912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(T->isStructureType());
9922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
9932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Keep an extra slot for the original copy (memcpy)
995d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  unsigned FieldsToSet = CountRSObjectTypes(C, T, Loc) + 1;
9962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned StmtCount = 0;
9982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
9992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToSet; i++) {
10005abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    StmtArray[i] = nullptr;
10012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
10022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
10042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  RD = RD->getDefinition();
10052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
10062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines         FE = RD->field_end();
10072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI != FE;
10082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI++) {
10092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    bool IsArrayType = false;
10102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::FieldDecl *FD = *FI;
10112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
10122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *OrigType = FT;
10132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
1014d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    if (!CountRSObjectTypes(C, FT, Loc)) {
10152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // Skip to next if we don't have any viable RS object types
10162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      continue;
10172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
10182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::DeclAccessPair FoundDecl =
10202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::DeclAccessPair::make(FD, clang::AS_none);
10212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *DstMember =
10222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
10232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  LHS,
10242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
10250b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                  clang::SourceLocation(),
1026be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
10270444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                  clang::SourceLocation(),
10282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
10292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
10302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::DeclarationNameInfo(),
10315abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                  nullptr,
1032be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
1033be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
1034be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
10352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *SrcMember =
10372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
10382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  RHS,
10392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
10400b7545898dcfe2979f2c13afd12d276fc736412dStephen Hines                                  clang::SourceLocation(),
1041be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
10420444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                  clang::SourceLocation(),
10432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
10442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
10452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::DeclarationNameInfo(),
10465abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                  nullptr,
1047be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
1048be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
1049be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
10502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (FT->isArrayType()) {
10522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
10532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      IsArrayType = true;
10542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
10552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
1056cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    DataType DT = RSExportPrimitiveType::GetRSSpecificType(FT);
10572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (IsArrayType) {
10599207a2e495c8363606861e4f034504ec5c153dabLogan Chien      clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
10609207a2e495c8363606861e4f034504ec5c153dabLogan Chien      DiagEngine.Report(
10619207a2e495c8363606861e4f034504ec5c153dabLogan Chien        clang::FullSourceLoc(Loc, C.getSourceManager()),
10629207a2e495c8363606861e4f034504ec5c153dabLogan Chien        DiagEngine.getCustomDiagID(
10639207a2e495c8363606861e4f034504ec5c153dabLogan Chien          clang::DiagnosticsEngine::Error,
10649207a2e495c8363606861e4f034504ec5c153dabLogan Chien          "Arrays of RS object types within structures cannot be copied"));
10652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // TODO(srhines): Support setting arrays of RS objects
10662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // StmtArray[StmtCount++] =
1067d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      //    CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
1068cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    } else if (DT == DataTypeUnknown) {
10692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
1070d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines          CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
10712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
10722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
1073d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines          CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
10742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else {
10752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      slangAssert(false);
10762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
10772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
10782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
1079b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines  slangAssert(StmtCount < FieldsToSet);
10802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // We still need to actually do the overall struct copy. For simplicity,
10822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // we just do a straight-up assignment (which will still preserve all
10832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // the proper RS object reference counts).
10842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *CopyStruct =
1085be27482cdeaf08576bc39b72a15d35d13014a636Logan      new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
108623c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   clang::VK_RValue, clang::OK_Ordinary, Loc,
108723c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines                                   false);
10882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCount++] = CopyStruct;
10892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
109023c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
109123c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines      C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
10922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  delete [] StmtArray;
10942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
10962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
10972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}  // namespace
10992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
11002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesvoid RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
1101d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    clang::BinaryOperator *AS) {
11022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
11032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = AS->getType();
11042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
11052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
11069ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getASTContext();
11072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
1108832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines  clang::SourceLocation Loc = AS->getExprLoc();
11099f1d0aa55669b75a718ad2e962fc8c3d8df1a5f4Stephen Hines  clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
11105abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Stmt *UpdatedStmt = nullptr;
11112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
11122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
11132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    // By definition, this is a struct assignment if we get here
11142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
1115d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
11162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
11172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
1118d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
11192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
1120e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1121292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  RSASTReplace R(C);
1122292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  R.ReplaceStmt(mCS, AS, UpdatedStmt);
1123e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
1124e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1125e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesvoid RSObjectRefCount::Scope::AppendRSObjectInit(
1126e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::VarDecl *VD,
1127e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::DeclStmt *DS,
1128cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    DataType DT,
1129e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::Expr *InitExpr) {
11306e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD);
1131e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1132e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!InitExpr) {
1133e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return;
1134e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1135e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1136a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
11379ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getASTContext();
1138a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
11399ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getLocation();
1140cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao  clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
11419ae18b2bbee0b08afd400542e863dd665ff76059Stephen Hines      DataTypeRSAllocation)->getInnerLocStart();
1142a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1143cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT == DataTypeIsStruct) {
1144a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1145a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::DeclRefExpr *RefRSVar =
1146a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines        clang::DeclRefExpr::Create(C,
1147be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::NestedNameSpecifierLoc(),
11480444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                   clang::SourceLocation(),
1149a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   VD,
1150e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                   false,
1151a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   Loc,
1152be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   T->getCanonicalTypeInternal(),
1153be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
11545abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                   nullptr);
1155a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1156a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::Stmt *RSSetObjectOps =
1157d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
1158a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1159292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*> StmtList;
1160292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    StmtList.push_back(RSSetObjectOps);
1161292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    AppendAfterStmt(C, mCS, DS, StmtList);
1162f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return;
1163f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1164f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
1165f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
11665abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  slangAssert((SetObjectFD != nullptr) &&
11676e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
1168e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1169e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
1170e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDArgType[2];
1171e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1172e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1173e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1174e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RefRSSetObjectFD =
1175e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1176be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
11770444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
1178e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD,
1179e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
1180e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1181be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
1182be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
11835abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
1184e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1185e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RSSetObjectFP =
1186e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::ImplicitCastExpr::Create(C,
1187e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      C.getPointerType(SetObjectFDType),
1188e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::CK_FunctionToPointerDecay,
1189e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      RefRSSetObjectFD,
11905abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                      nullptr,
1191e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::VK_RValue);
1192e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1193e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1194e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::DeclRefExpr *RefRSVar =
1195e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1196be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
11970444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
1198e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD,
1199e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
1200e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1201be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1202be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
12035abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
1204e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
12051dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  llvm::SmallVector<clang::Expr*, 2> ArgList;
12061dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
12071dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::UO_AddrOf,
12081dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                SetObjectFDArgType[0],
12091dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::VK_RValue,
12101dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                clang::OK_Ordinary,
12111dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                                Loc));
12121dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines  ArgList.push_back(InitExpr);
1213e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1214e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CallExpr *RSSetObjectCall =
1215e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      new(C) clang::CallExpr(C,
1216e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             RSSetObjectFP,
1217e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             ArgList,
1218e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             SetObjectFD->getCallResultType(),
1219be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
1220e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             Loc);
1221e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1222292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*> StmtList;
1223292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  StmtList.push_back(RSSetObjectCall);
1224292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  AppendAfterStmt(C, mCS, DS, StmtList);
1225c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
1226c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
12271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
12281bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
12291bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
12301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
12311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
1232a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines    clang::VarDecl *VD = *I;
12333f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines    clang::Stmt *RSClearObjectCall = ClearRSObject(VD, VD->getDeclContext());
1234a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines    if (RSClearObjectCall) {
1235cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar      clang::ASTContext &C = (*mRSO.begin())->getASTContext();
1236cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar      // Mark VD as used.  It might be unused, except for the destructor.
1237cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar      // 'markUsed' has side-effects that are caused only if VD is not already
1238cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar      // used.  Hence no need for an extra check here.
1239cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar      VD->markUsed(C);
1240cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar      DestructorVisitor DV(C,
1241a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines                           mCS,
1242a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines                           RSClearObjectCall,
1243a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines                           VD->getSourceRange().getBegin());
1244a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines      DV.Visit(mCS);
1245a883ce325281796dc7cc8fcf973a7ccd47a9a17eStephen Hines      DV.InsertDestructors();
12461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
12471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
12481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
12491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
12503f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
12513f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines    clang::VarDecl *VD,
12523f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines    clang::DeclContext *DC) {
1253f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(VD);
12541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
12551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
1256cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao  clang::SourceLocation StartLoc = VD->getInnerLocStart();
12571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
125803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
12591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
12601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
12611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
1262be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
12630444de0c0e7cfc8d8f8fed6f64cd97812bdd6a41Stephen Hines                                 clang::SourceLocation(),
12641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
1265e2597ac5a8ba7a45a1d5f342973cd43a3a1932cfShih-wei Liao                                 false,
12661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
1267be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1268be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
12695abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                 nullptr);
12701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1271f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
1272cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
1273f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
12741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1275cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
12761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1277cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (DT == DataTypeUnknown ||
1278cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      DT == DataTypeIsStruct) {
1279cc887ba8fe42cca706caae636932ae6a61a30ed2Shih-wei Liao    return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
1280f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
12811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1282f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1283f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should be RS object");
12841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1285f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return ClearSingleRSObject(C, RefRSVar, Loc);
12861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
12871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1288e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1289cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet                                          DataType *DT,
1290e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          clang::Expr **InitExpr) {
12916e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD && DT && InitExpr);
12924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
12932d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
12942d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
12952d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
12962d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
12972d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
12982d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
1299f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsStructWithRSObject = false;
1300e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
13014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1302cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  if (*DT == DataTypeUnknown) {
1303feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1304cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      *DT = DataTypeIsStruct;
1305f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DataTypeIsStructWithRSObject = true;
1306feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    } else {
1307feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      return false;
1308feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    }
13092d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
13104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1311f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsRSObject = false;
1312f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DataTypeIsStructWithRSObject) {
1313f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = true;
1314f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
1315f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1316f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1317e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *InitExpr = VD->getInit();
1318e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1319e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!DataTypeIsRSObject && *InitExpr) {
1320e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    // If we already have an initializer for a matrix type, we are done.
1321e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return DataTypeIsRSObject;
13224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
13234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1324e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ZeroInitializer =
1325e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      CreateZeroInitializerForRSSpecificType(*DT,
1326e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getASTContext(),
1327e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getLocation());
1328e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1329e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (ZeroInitializer) {
1330e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    ZeroInitializer->setType(T->getCanonicalTypeInternal());
1331e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    VD->setInit(ZeroInitializer);
1332e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1333e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1334e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return DataTypeIsRSObject;
13354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
13364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
1338cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    DataType DT,
13394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
13404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
13415abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::Expr *Res = nullptr;
13424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
1343cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeIsStruct:
1344cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSElement:
1345cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSType:
1346cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSAllocation:
1347cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSSampler:
1348cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSScript:
1349cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSMesh:
1350cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSPath:
1351cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSProgramFragment:
1352cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSProgramVertex:
1353cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSProgramRaster:
1354cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSProgramStore:
1355cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSFont: {
13564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
13574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
13584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
13594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
13604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
13614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
13624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
13634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
13644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
13655abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes                                          nullptr,
13664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
13674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13681dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      llvm::SmallVector<clang::Expr*, 1>InitList;
13691dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      InitList.push_back(CastToNull);
13701dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines
13711dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, InitList, Loc);
13724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
13734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
1374cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSMatrix2x2:
1375cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSMatrix3x3:
1376cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeRSMatrix4x4: {
13774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
13784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
13794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
13804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
13814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
13824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
13834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
13844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
13854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
13864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
13874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
13884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
13894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
13904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
13914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
13924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
13934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
1395cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      if (DT == DataTypeRSMatrix2x2)
13964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
1397cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      else if (DT == DataTypeRSMatrix3x3)
13984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
1399cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      else if (DT == DataTypeRSMatrix4x4)
14004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
14011dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      unsigned N_2 = N * N;
14024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14031dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      // Assume we are going to be allocating 16 elements, since 4x4 is max.
14041dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      llvm::SmallVector<clang::Expr*, 16> InitVals;
14051dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      for (unsigned i = 0; i < N_2; i++)
14061dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines        InitVals.push_back(Float0Val);
14074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
14081dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, Loc);
14094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
14101dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines                                               llvm::APInt(32, N_2),
14114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
14124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
14131dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      llvm::SmallVector<clang::Expr*, 1> InitExprVec;
14141dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      InitExprVec.push_back(InitExpr);
14154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14161dfc415431ddd360354fecfcd9b12dcaf686355aStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, InitExprVec, Loc);
14174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
14184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
1419cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeUnknown:
1420cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeFloat16:
1421cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeFloat32:
1422cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeFloat64:
1423cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeSigned8:
1424cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeSigned16:
1425cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeSigned32:
1426cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeSigned64:
1427cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeUnsigned8:
1428cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeUnsigned16:
1429cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeUnsigned32:
1430cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeUnsigned64:
1431cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeBoolean:
1432cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeUnsigned565:
1433cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeUnsigned5551:
1434cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeUnsigned4444:
1435cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    case DataTypeMax: {
14366e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(false && "Not RS object type!");
14374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
14384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
14394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
14404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
14424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
14434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
14454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
14464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
14474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
14484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
14494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
14504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
1451cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet      DataType DT = DataTypeUnknown;
14525abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes      clang::Expr *InitExpr = nullptr;
1453e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      if (InitializeRSObject(VD, &DT, &InitExpr)) {
1454b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        // We need to zero-init all RS object types (including matrices), ...
1455d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines        getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
1456b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        // ... but, only add to the list of RS objects if we have some
1457b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        // non-matrix RS object fields.
1458b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(),
1459b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines                               VD->getLocation())) {
1460b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines          getCurrentScope()->addRSObject(VD);
1461b0fabe574945bfa85e688e77e9dcb5341fe08840Stephen Hines        }
1462e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      }
14634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
14644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
14654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
14664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
14684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
14694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
14704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
14714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
14724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
14744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
14766e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
14771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
14784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
14794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
14804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
14814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
14824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
1484c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
1485c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
1486d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  if (CountRSObjectTypes(mCtx, QT.getTypePtr(), AS->getExprLoc())) {
1487d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    getCurrentScope()->ReplaceRSObjectAssignment(AS);
1488c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
14894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
14904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
14924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
14934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
14944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
14954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
14964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
14974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
14984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
14994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
15004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1501688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines// This function walks the list of global variables and (potentially) creates
1502688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines// a single global static destructor function that properly decrements
1503688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines// reference counts on the contained RS object types.
1504688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hinesclang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
1505688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  Init();
1506688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1507688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
1508688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::SourceLocation loc;
1509688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
15103f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  llvm::StringRef SR(".rs.dtor");
15113f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  clang::IdentifierInfo &II = mCtx.Idents.get(SR);
15123f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  clang::DeclarationName N(&II);
15133f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines  clang::FunctionProtoType::ExtProtoInfo EPI;
151482d7288620fade361dd8f7408b5db54a55c2c794Stephen Hines  clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
151582d7288620fade361dd8f7408b5db54a55c2c794Stephen Hines      llvm::ArrayRef<clang::QualType>(), EPI);
15165abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes  clang::FunctionDecl *FD = nullptr;
15173f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines
1518688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // Generate rsClearObject() call chains for every global variable
1519688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // (whether static or extern).
1520688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  std::list<clang::Stmt *> StmtList;
1521688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
1522688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines          E = DC->decls_end(); I != E; I++) {
1523688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
1524688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    if (VD) {
1525688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines      if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(), loc)) {
15263f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        if (!FD) {
15273f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines          // Only create FD if we are going to use it.
15285abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes          FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, nullptr,
15294b3f3bada7155de983e7d92fa8b20091629b3bb3Stephen Hines                                           clang::SC_None);
15303f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        }
1531cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        // Mark VD as used.  It might be unused, except for the destructor.
1532cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        // 'markUsed' has side-effects that are caused only if VD is not already
1533cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        // used.  Hence no need for an extra check here.
1534cc4d93488b344cbdb0d65c3af076f02dbf2ceb00Pirama Arumuga Nainar        VD->markUsed(mCtx);
15353f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        // Make sure to create any helpers within the function's DeclContext,
15363f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        // not the one associated with the global translation unit.
15373f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines        clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
1538688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines        StmtList.push_back(RSClearObjectCall);
1539688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines      }
1540688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines    }
1541688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  }
1542688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1543688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // Nothing needs to be destroyed, so don't emit a dtor.
1544688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  if (StmtList.empty()) {
15455abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes    return nullptr;
1546688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  }
1547688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1548688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
1549688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1550688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  FD->setBody(CS);
1551688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1552688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  return FD;
1553688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines}
1554688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
1555e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
1556