slang_rs_object_ref_count.cpp revision 292e00a0259ac28cac1055cb6077cf6fc7c6743c
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"
294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs.h"
30292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines#include "slang_rs_ast_replace.h"
314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
33e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
35f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::FunctionDecl *RSObjectRefCount::
361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                  RSExportPrimitiveType::FirstRSObjectType + 1];
38f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::FunctionDecl *RSObjectRefCount::
391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                    RSExportPrimitiveType::FirstRSObjectType + 1];
411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
42f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesvoid RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (unsigned i = 0;
441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i++) {
461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[i] = NULL;
471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[i] = NULL;
481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = TUDecl->decls_end(); I != E; I++) {
541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((I->getKind() >= clang::Decl::firstFunction) &&
551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        (I->getKind() <= clang::Decl::lastFunction)) {
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // points to RSSetObjectFD or RSClearObjectFD
591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl **RSObjectFD;
601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      if (FD->getName() == "rsSetObject") {
626e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 2) &&
636e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsSetObject function prototype (# params)");
641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
666e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 1) &&
676e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsClearObject function prototype (# params)");
681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSClearObjectFD;
69e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      } else {
701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        continue;
711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType PVT = PVD->getOriginalType();
751bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The first parameter must be a pointer like rs_allocation*
766e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(PVT->isPointerType() &&
776e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines          "Invalid rs{Set,Clear}Object function prototype (pointer param)");
781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The rs object type passed to the FD
801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType RST = PVT->getPointeeType();
811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::DataType DT =
821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
836e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             && "must be RS object type");
851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
914464d825c11349068f2917f9ebee86b721423f3cStephen Hinesnamespace {
924464d825c11349068f2917f9ebee86b721423f3cStephen Hines
93292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// This function constructs a new CompoundStmt from the input StmtList.
94292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesstatic clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
95292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
96d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  unsigned NewStmtCount = StmtList.size();
97292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  unsigned CompoundStmtCount = 0;
981bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
99292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **CompoundStmtList;
100292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  CompoundStmtList = new clang::Stmt*[NewStmtCount];
1011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
102292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
103292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*>::const_iterator E = StmtList.end();
104292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; I != E; I++) {
105292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    CompoundStmtList[CompoundStmtCount++] = *I;
1061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
107292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CompoundStmtCount == NewStmtCount);
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
109292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(C,
110292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                                                       CompoundStmtList,
111292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                                                       CompoundStmtCount,
112292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                                                       Loc,
113292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                                                       Loc);
1141bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
115292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  delete [] CompoundStmtList;
1161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
117292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return CS;
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
120292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesstatic void AppendAfterStmt(clang::ASTContext &C,
121e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::CompoundStmt *CS,
122292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                            clang::Stmt *S,
123292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                            std::list<clang::Stmt*> &StmtList) {
124292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(CS);
125e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
126292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::CompoundStmt::body_iterator bE = CS->body_end();
127292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt **UpdatedStmtList =
128292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      new clang::Stmt*[CS->size() + StmtList.size()];
129e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
130e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned UpdatedStmtCount = 0;
131e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned Once = 0;
132292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  for ( ; bI != bE; bI++) {
133292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
134292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // If we come across a return here, we don't have anything we can
135292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // reasonably replace. We should have already inserted our destructor
136292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      // code in the proper spot, so we just clean up and return.
137292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      delete [] UpdatedStmtList;
138292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
139292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      return;
140e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    }
141e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
142292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
143c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
144292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if ((*bI == S) && !Once) {
145292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      Once++;
146292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
147292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      std::list<clang::Stmt*>::const_iterator E = StmtList.end();
148292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      for ( ; I != E; I++) {
149292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines        UpdatedStmtList[UpdatedStmtCount++] = *I;
150292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      }
151292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    }
152c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
153292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(Once <= 1);
154c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
155292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // When S is NULL, we are appending to the end of the CompoundStmt.
156292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (!S) {
157292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    slangAssert(Once == 0);
158292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
159292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*>::const_iterator E = StmtList.end();
160292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    for ( ; I != E; I++) {
161292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *I;
162c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    }
163c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
164c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
165c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
166c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
167c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  delete [] UpdatedStmtList;
168c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
169c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
170c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
171c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
172d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines// This class visits a compound statement and inserts the StmtList containing
1734464d825c11349068f2917f9ebee86b721423f3cStephen Hines// destructors in proper locations. This includes inserting them before any
1744464d825c11349068f2917f9ebee86b721423f3cStephen Hines// return statement in any sub-block, at the end of the logical enclosing
1754464d825c11349068f2917f9ebee86b721423f3cStephen Hines// scope (compound statement), and/or before any break/continue statement that
1764464d825c11349068f2917f9ebee86b721423f3cStephen Hines// would resume outside the declared scope. We will not handle the case for
1774464d825c11349068f2917f9ebee86b721423f3cStephen Hines// goto statements that leave a local scope.
178292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines//
179292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// To accomplish these goals, it collects a list of sub-Stmt's that
180292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// correspond to scope exit points. It then uses an RSASTReplace visitor to
181292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// transform the AST, inserting appropriate destructors before each of those
182292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// sub-Stmt's (and also before the exit of the outermost containing Stmt for
183292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// the scope).
1844464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
1854464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
1864464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::ASTContext &mC;
187292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
188292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The loop depth of the currently visited node.
189292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mLoopDepth;
190292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
191292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The switch statement depth of the currently visited node.
192292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // Note that this is tracked separately from the loop depth because
193292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // SwitchStmt-contained ContinueStmt's should have destructors for the
194292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // corresponding loop scope.
195292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  int mSwitchDepth;
196292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
197292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The outermost statement block that we are currently visiting.
198292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // This should always be a CompoundStmt.
199292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  clang::Stmt *mOuterStmt;
200292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
201292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The list of destructors to execute for this scope.
202d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> &mStmtList;
203292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
204292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // The stack of statements which should be replaced by a compound statement
205292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // containing the new destructor calls followed by the original Stmt.
206292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::stack<clang::Stmt*> mReplaceStmtStack;
207292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
2084464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
209292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  DestructorVisitor(clang::ASTContext &C,
210292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                    clang::Stmt* OuterStmt,
211292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                    std::list<clang::Stmt*> &StmtList);
212292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
213292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // This code walks the collected list of Stmts to replace and actually does
214292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // the replacement. It also finishes up by appending appropriate destructors
215292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  // to the current outermost CompoundStmt.
216292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void InsertDestructors() {
217292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    clang::Stmt *S = NULL;
218292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    while (!mReplaceStmtStack.empty()) {
219292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      S = mReplaceStmtStack.top();
220292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      mReplaceStmtStack.pop();
221292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
222292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      mStmtList.push_back(S);
223292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      clang::CompoundStmt *CS =
224292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines          BuildCompoundStmt(mC, mStmtList, S->getLocEnd());
225292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      mStmtList.pop_back();
226292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
227292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      RSASTReplace R(mC);
228292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      R.ReplaceStmt(mOuterStmt, S, CS);
229292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    }
230292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    clang::CompoundStmt *CS = dyn_cast<clang::CompoundStmt>(mOuterStmt);
231292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    slangAssert(CS);
232292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    if (CS) {
233292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines      AppendAfterStmt(mC, CS, NULL, mStmtList);
234292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    }
235292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
236292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
2374464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
2384464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitCompoundStmt(clang::CompoundStmt *CS);
239292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
240292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitBreakStmt(clang::BreakStmt *BS);
241292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitCaseStmt(clang::CaseStmt *CS);
242292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitContinueStmt(clang::ContinueStmt *CS);
243292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitDefaultStmt(clang::DefaultStmt *DS);
244292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitDoStmt(clang::DoStmt *DS);
245292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitForStmt(clang::ForStmt *FS);
246292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitIfStmt(clang::IfStmt *IS);
247292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitReturnStmt(clang::ReturnStmt *RS);
248292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitSwitchCase(clang::SwitchCase *SC);
249292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitSwitchStmt(clang::SwitchStmt *SS);
250292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  void VisitWhileStmt(clang::WhileStmt *WS);
2514464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
2524464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2534464d825c11349068f2917f9ebee86b721423f3cStephen HinesDestructorVisitor::DestructorVisitor(clang::ASTContext &C,
254292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                         clang::Stmt *OuterStmt,
255292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                         std::list<clang::Stmt*> &StmtList)
2564464d825c11349068f2917f9ebee86b721423f3cStephen Hines  : mC(C),
257292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mLoopDepth(0),
258292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mSwitchDepth(0),
259292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mOuterStmt(OuterStmt),
260292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mStmtList(StmtList) {
2614464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2624464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2634464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2644464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
2654464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
2664464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I != E;
2674464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I++) {
2684464d825c11349068f2917f9ebee86b721423f3cStephen Hines    if (clang::Stmt *Child = *I) {
2694464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
2704464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
2714464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2724464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2734464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2744464d825c11349068f2917f9ebee86b721423f3cStephen Hines
275292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
276292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(CS);
277292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
278292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
279292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
280292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
281292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(BS);
282292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
283292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mReplaceStmtStack.push(BS);
284292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
285292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
286292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
287292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
288292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) {
289292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(CS);
290292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
291292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
292292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
293292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
294292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(CS);
295292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  if (mLoopDepth == 0) {
296292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    // Switch statements can have nested continues.
297292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    mReplaceStmtStack.push(CS);
298292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  }
299292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
300292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
301292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
302292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) {
303292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(DS);
304292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
305292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
306292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
307292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
308292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
309292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(DS);
310292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
311292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
312292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
313292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
314292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
315292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
316292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(FS);
317292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
318292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
319292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
320292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
321292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) {
322292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(IS);
323292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
324292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
325292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
326292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
327292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mReplaceStmtStack.push(RS);
328292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
329292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
330292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
331292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) {
332292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  slangAssert(false && "Both case and default have specialized handlers");
333292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(SC);
334292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
335292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
336292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
337292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
338292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth++;
339292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(SS);
340292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mSwitchDepth--;
341292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
342292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
343292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
344292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hinesvoid DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
345292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth++;
346292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  VisitStmt(WS);
347292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  mLoopDepth--;
348292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  return;
349292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines}
350292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines
351f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::Expr *ClearSingleRSObject(clang::ASTContext &C,
352f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::Expr *RefRSVar,
353f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::SourceLocation Loc) {
354f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(RefRSVar);
355f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *T = RefRSVar->getType().getTypePtr();
356f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!T->isArrayType() &&
357f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should not be destroying arrays with this function");
358f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
359f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
360f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((ClearObjectFD != NULL) &&
361f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "rsClearObject doesn't cover all RS object types");
362f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
363f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
364f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDArgType =
365f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
366f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
367f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Example destructor for "rs_font localFont;"
368f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //
369f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // (CallExpr 'void'
370f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
371f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
372f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
373f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
374f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
375f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Get address of targeted RS object
376f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *AddrRefRSVar =
377f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
378f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  clang::UO_AddrOf,
379f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  ClearObjectFDArgType,
380be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
381be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
382f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  Loc);
383f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
384f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSClearObjectFD =
385f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclRefExpr::Create(C,
386be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
387f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD,
388f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getLocation(),
389be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 ClearObjectFDType,
390be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
391be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
392f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
393f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RSClearObjectFP =
394f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::ImplicitCastExpr::Create(C,
395f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      C.getPointerType(ClearObjectFDType),
396f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::CK_FunctionToPointerDecay,
397f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      RefRSClearObjectFD,
398f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      NULL,
399f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::VK_RValue);
40003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
401f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CallExpr *RSClearObjectCall =
402f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CallExpr(C,
403f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             RSClearObjectFP,
404f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             &AddrRefRSVar,
405f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             1,
406f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             ClearObjectFD->getCallResultType(),
407be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
408f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             Loc);
409f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
410f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSClearObjectCall;
411f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
412f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
413f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic int ArrayDim(const clang::Type *T) {
41403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
41503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
41603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
41703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
41803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
41903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
4209d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
42103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
423f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
424f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
425f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
426f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
427f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc);
428f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
429f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearArrayRSObject(
430f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
431f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
432f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSArr,
433f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
434f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
435f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(BaseType->isArrayType());
436f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
437f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  int NumArrayElements = ArrayDim(BaseType);
438f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Actually extract out the base RS object type for use later
439f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
44003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
44103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
44203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int StmtCtr = 0;
44303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
44403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
44503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return NULL;
44603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
44703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
44803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
44903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
45003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // (CompoundStmt
45103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (DeclStmt "int rsIntIter")
45203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (ForStmt
45303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '='
45403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
45503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 0))
45603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '<'
45703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
45803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 10)
45903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     NULL << CondVar >>
46003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (UnaryOperator 'int' postfix '++'
46103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
46203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (CallExpr 'void'
46303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
46403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
46503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (UnaryOperator 'rs_font *' prefix '&'
46603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (ArraySubscriptExpr 'rs_font':'rs_font'
46703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
46803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
46903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (DeclRefExpr 'int' Var='rsIntIter')))))))
47003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
47103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
47203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
47303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
47403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
475f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             DC,
47603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
47703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &II,
47803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
47903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
48003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None,
48103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
48203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
48303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
48403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
48503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
48603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
48703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
48803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
48903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
49003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
49103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Init -> "rsIntIter = 0"
49203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
49303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
494be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
49503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
49603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
497be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
498be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
499be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
50003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
50103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
50203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
50303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
50403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Init =
50503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
50603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Int0,
50703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_Assign,
50803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
509be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
510be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
51103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
51203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
51303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
51403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
51503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
51603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
51703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
51803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
51903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
52003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
52103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
522be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
523be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
52403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
52503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
52603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
52703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
52803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
52903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
53003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
531be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
532be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
53303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
53403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
53503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
53603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
53703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
538f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtr =
53903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
540f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
54103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
542f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          RefRSArr,
54303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          NULL,
54403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
54503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
546f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtrSubscript =
547f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
54803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       RefrsIntIter,
549f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       BaseType->getCanonicalTypeInternal(),
550be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
551be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
552f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       Loc);
55303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
554f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
555f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
556f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
557f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt *RSClearObjectCall = NULL;
558f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (BaseType->isArrayType()) {
559f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
560be27482cdeaf08576bc39b72a15d35d13014a636Logan        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, Loc);
561f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
562f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
563be27482cdeaf08576bc39b72a15d35d13014a636Logan        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, Loc);
564f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
565f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
566f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
56703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
56803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
56903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
57003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
57103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
57203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            NULL,  // no condVar
57303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
57403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
57503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
57603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
57703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
57803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
57903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
5806e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(StmtCtr == 2);
58103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
58203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CompoundStmt *CS =
58303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
58403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
58503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  return CS;
58603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
58703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
5882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic unsigned CountRSObjectTypes(const clang::Type *T) {
589f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(T);
590f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned RSObjectCount = 0;
591f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
592f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
5932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
594f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
595f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
596f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
597f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
598f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT != RSExportPrimitiveType::DataTypeUnknown) {
599f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
600f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
601f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
602f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (!T->isStructureType()) {
603f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return 0;
604f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
605f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
606f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
607f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
608f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
609f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
610f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
611f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
612f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::FieldDecl *FD = *FI;
613f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
6142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (CountRSObjectTypes(FT)) {
615f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // Sub-structs should only count once (as should arrays, etc.)
616f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSObjectCount++;
617f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
618f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
619f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
620f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSObjectCount;
621f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
622f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
623f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
624f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
625f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
626f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
627f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
628f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
629f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
630f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!BaseType->isArrayType());
631f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
632f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Structs should show up as unknown primitive types
6339be9360d8e02b52ed669afbd69f9becb575c3f0dAlex Sakhartchouk  slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
6349be9360d8e02b52ed669afbd69f9becb575c3f0dAlex Sakhartchouk              RSExportPrimitiveType::DataTypeUnknown);
635f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
6362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
637f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
638f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned StmtCount = 0;
639f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
6402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToDestroy; i++) {
6412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    StmtArray[i] = NULL;
6422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
643f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
644f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Populate StmtArray by creating a destructor for each RS object field
645f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
646f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
647f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
648f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
649f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
650f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
651f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // We just look through all field declarations to see if we find a
652f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // declaration for an RS object type (or an array of one).
653f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    bool IsArrayType = false;
654f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::FieldDecl *FD = *FI;
655f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
656f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *OrigType = FT;
657f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    while (FT && FT->isArrayType()) {
658f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
659f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      IsArrayType = true;
660f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
661f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
662f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
663f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
664f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
665f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
666f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
667f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
668f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
669be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
670f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
671f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
672f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
673f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
674be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
675be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
676be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
677f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
678f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      slangAssert(StmtCount < FieldsToDestroy);
679f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
680f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
681f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
682f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
683f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
684f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
685f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
686f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearSingleRSObject(C,
687f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
688f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
689f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
6902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
691f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // In this case, we have a nested struct. We may not end up filling all
692f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // of the spaces in StmtArray (sub-structs should handle themselves
693f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // with separate compound statements).
694f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
695f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
696f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
697f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
698f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
699f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
700be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
701f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
702f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
703f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
704f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
705be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
706be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
707be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
708f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
709f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
710f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
711f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
712f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
713f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
714f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
715f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearStructRSObject(C,
716f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     DC,
717f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
718f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
719f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
720f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
721f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
722f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
723f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(StmtCount > 0);
724f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CompoundStmt *CS =
725f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
726f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
727f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  delete [] StmtArray;
728f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
729f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return CS;
730f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
731f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
7322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
7332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Diagnostic *Diags,
7342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *DstExpr,
7352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *SrcExpr,
7362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc) {
7372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = DstExpr->getType().getTypePtr();
7382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
7396e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
7406e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
741c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
742c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
743c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
744c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
745c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
746c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
747c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
748c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
749be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
750c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
751c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
752be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
753be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
754be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
755c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
756c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
757c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
758c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
759c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
760c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
761c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      NULL,
762c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
763c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
764c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *ArgList[2];
7652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(DstExpr,
766c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           clang::UO_AddrOf,
767c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           SetObjectFDArgType[0],
768be27482cdeaf08576bc39b72a15d35d13014a636Logan                                           clang::VK_RValue,
769be27482cdeaf08576bc39b72a15d35d13014a636Logan                                           clang::OK_Ordinary,
770c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           Loc);
7712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  ArgList[1] = SrcExpr;
772c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
773c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CallExpr *RSSetObjectCall =
774c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      new(C) clang::CallExpr(C,
775c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             RSSetObjectFP,
776c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             ArgList,
777c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             2,
778c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             SetObjectFD->getCallResultType(),
779be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
780c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             Loc);
781c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
7822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return RSSetObjectCall;
7832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
7842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
7862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Diagnostic *Diags,
7872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *LHS,
7882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *RHS,
7892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc);
7902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
7922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Diagnostic *Diags,
7932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *DstArr,
7942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *SrcArr,
7952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::SourceLocation Loc) {
7962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclContext *DC = NULL;
7972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *BaseType = DstArr->getType().getTypePtr();
7982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(BaseType->isArrayType());
7992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int NumArrayElements = ArrayDim(BaseType);
8012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Actually extract out the base RS object type for use later
8022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
8032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
8052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int StmtCtr = 0;
8062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (NumArrayElements <= 0) {
8082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    return NULL;
8092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
8102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Create helper variable for iterating through elements
8122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
8132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::VarDecl *IIVD =
8142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::VarDecl::Create(C,
8152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             DC,
8162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             Loc,
8172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             &II,
8182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.IntTy,
8192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
8202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None,
8212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None);
8222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
8232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
8252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
8262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Form the actual loop
8282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // for (Init; Cond; Inc)
8292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  //   RSSetObjectCall;
8302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Init -> "rsIntIter = 0"
8322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
8332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::DeclRefExpr::Create(C,
834be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
8352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 IIVD,
8362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 Loc,
837be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
838be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
839be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
8402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
8422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
8432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Init =
8452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
8462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Int0,
8472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_Assign,
8482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
849be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
850be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
8512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
8522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
8542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
8552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
8562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Cond =
8582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
8592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   NumArrayElementsExpr,
8602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_LT,
8612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
862be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
863be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
8642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
8652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Inc -> "rsIntIter++"
8672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::UnaryOperator *Inc =
8682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
8692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::UO_PostInc,
8702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  C.IntTy,
871be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
872be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
8732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  Loc);
8742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
8762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Loop operates on individual array elements
8772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtr =
8792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
8802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
8812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
8822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          DstArr,
8832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          NULL,
8842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
8852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtrSubscript =
8872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(DstArrPtr,
8882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
8892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
890be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
891be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
8922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
8932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtr =
8952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
8962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
8972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
8982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          SrcArr,
8992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          NULL,
9002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
9012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtrSubscript =
9032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(SrcArrPtr,
9042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
9052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
906be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
907be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
9082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
9092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  RSExportPrimitiveType::DataType DT =
9112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
9122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt *RSSetObjectCall = NULL;
9142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (BaseType->isArrayType()) {
9152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSSetObjectCall = CreateArrayRSSetObject(C, Diags, DstArrPtrSubscript,
9162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                             SrcArrPtrSubscript, Loc);
9172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
9182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSSetObjectCall = CreateStructRSSetObject(C, Diags, DstArrPtrSubscript,
9192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                              SrcArrPtrSubscript, Loc);
9202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
9212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSSetObjectCall = CreateSingleRSSetObject(C, Diags, DstArrPtrSubscript,
9222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                              SrcArrPtrSubscript, Loc);
9232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
9242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ForStmt *DestructorLoop =
9262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ForStmt(C,
9272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Init,
9282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Cond,
9292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            NULL,  // no condVar
9302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Inc,
9312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            RSSetObjectCall,
9322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
9332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
9342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc);
9352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
9372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(StmtCtr == 2);
9382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::CompoundStmt *CS =
9402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
9412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
9432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
9442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
9462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Diagnostic *Diags,
9472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *LHS,
9482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *RHS,
9492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc) {
9502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = LHS->getType();
9512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = QT.getTypePtr();
9522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(T->isStructureType());
9532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
9542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Keep an extra slot for the original copy (memcpy)
9562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
9572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned StmtCount = 0;
9592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
9602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToSet; i++) {
9612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    StmtArray[i] = NULL;
9622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
9632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
9652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  RD = RD->getDefinition();
9662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
9672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines         FE = RD->field_end();
9682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI != FE;
9692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI++) {
9702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    bool IsArrayType = false;
9712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::FieldDecl *FD = *FI;
9722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
9732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *OrigType = FT;
9742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (!CountRSObjectTypes(FT)) {
9762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // Skip to next if we don't have any viable RS object types
9772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      continue;
9782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::DeclAccessPair FoundDecl =
9812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::DeclAccessPair::make(FD, clang::AS_none);
9822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *DstMember =
9832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
9842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  LHS,
9852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
986be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
9872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
9882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
9892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::DeclarationNameInfo(),
9902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  NULL,
991be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
992be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
993be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
9942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *SrcMember =
9962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
9972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  RHS,
9982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
999be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
10002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
10012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
10022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::DeclarationNameInfo(),
10032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  NULL,
1004be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
1005be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
1006be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
10072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (FT->isArrayType()) {
10092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
10102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      IsArrayType = true;
10112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
10122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSExportPrimitiveType::DataType DT =
10142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        RSExportPrimitiveType::GetRSSpecificType(FT);
10152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (IsArrayType) {
1017832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines      Diags->Report(clang::FullSourceLoc(Loc, C.getSourceManager()),
1018832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines          Diags->getCustomDiagID(clang::Diagnostic::Error,
1019832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines            "Arrays of RS object types within structures cannot be copied"));
10202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // TODO(srhines): Support setting arrays of RS objects
10212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // StmtArray[StmtCount++] =
10222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      //    CreateArrayRSSetObject(C, Diags, DstMember, SrcMember, Loc);
10232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
10242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
10252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          CreateStructRSSetObject(C, Diags, DstMember, SrcMember, Loc);
10262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
10272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
10282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          CreateSingleRSSetObject(C, Diags, DstMember, SrcMember, Loc);
10292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else {
10302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      slangAssert(false);
10312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
10322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
10332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(StmtCount > 0 && StmtCount < FieldsToSet);
10352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // We still need to actually do the overall struct copy. For simplicity,
10372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // we just do a straight-up assignment (which will still preserve all
10382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // the proper RS object reference counts).
10392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *CopyStruct =
1040be27482cdeaf08576bc39b72a15d35d13014a636Logan      new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
1041be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue, clang::OK_Ordinary, Loc);
10422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCount++] = CopyStruct;
10432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::CompoundStmt *CS =
10452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
10462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  delete [] StmtArray;
10482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
10502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
10512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}  // namespace
10532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesvoid RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
10552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::BinaryOperator *AS,
10562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::Diagnostic *Diags) {
10572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = AS->getType();
10592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
10612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
10622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
1063832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines  clang::SourceLocation Loc = AS->getExprLoc();
10642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt *UpdatedStmt = NULL;
10652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
10662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
10672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    // By definition, this is a struct assignment if we get here
10682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
10692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        CreateStructRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
10702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
10712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
10722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        CreateSingleRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
10732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
1074e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1075292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  RSASTReplace R(C);
1076292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  R.ReplaceStmt(mCS, AS, UpdatedStmt);
1077e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
1078e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
1079e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1080e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesvoid RSObjectRefCount::Scope::AppendRSObjectInit(
1081a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::Diagnostic *Diags,
1082e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::VarDecl *VD,
1083e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::DeclStmt *DS,
1084e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    RSExportPrimitiveType::DataType DT,
1085e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::Expr *InitExpr) {
10866e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD);
1087e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1088e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!InitExpr) {
1089e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return;
1090e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1091e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1092a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
1093a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines      RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
1094a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
1095a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines      RSExportPrimitiveType::DataTypeRSFont)->getLocation();
1096a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1097f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
1098a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1099a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::DeclRefExpr *RefRSVar =
1100a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines        clang::DeclRefExpr::Create(C,
1101be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::NestedNameSpecifierLoc(),
1102a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   VD,
1103a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   Loc,
1104be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   T->getCanonicalTypeInternal(),
1105be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
1106be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   NULL);
1107a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1108a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::Stmt *RSSetObjectOps =
1109a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines        CreateStructRSSetObject(C, Diags, RefRSVar, InitExpr, Loc);
1110a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1111292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    std::list<clang::Stmt*> StmtList;
1112292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    StmtList.push_back(RSSetObjectOps);
1113292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    AppendAfterStmt(C, mCS, DS, StmtList);
1114f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return;
1115f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1116f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
1117f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
11186e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
11196e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
1120e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1121e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
1122e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDArgType[2];
1123e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1124e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1125e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1126e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RefRSSetObjectFD =
1127e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1128be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
1129e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD,
1130e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1131be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
1132be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
1133be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
1134e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1135e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RSSetObjectFP =
1136e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::ImplicitCastExpr::Create(C,
1137e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      C.getPointerType(SetObjectFDType),
1138e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::CK_FunctionToPointerDecay,
1139e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      RefRSSetObjectFD,
1140e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      NULL,
1141e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::VK_RValue);
1142e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1143e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1144e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::DeclRefExpr *RefRSVar =
1145e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1146be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
1147e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD,
1148e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1149be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1150be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
1151be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
1152e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1153e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ArgList[2];
1154e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
1155e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           clang::UO_AddrOf,
1156e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           SetObjectFDArgType[0],
1157be27482cdeaf08576bc39b72a15d35d13014a636Logan                                           clang::VK_RValue,
1158be27482cdeaf08576bc39b72a15d35d13014a636Logan                                           clang::OK_Ordinary,
1159e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           Loc);
1160e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[1] = InitExpr;
1161e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1162e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CallExpr *RSSetObjectCall =
1163e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      new(C) clang::CallExpr(C,
1164e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             RSSetObjectFP,
1165e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             ArgList,
1166e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             2,
1167e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             SetObjectFD->getCallResultType(),
1168be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
1169e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             Loc);
1170e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1171292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  std::list<clang::Stmt*> StmtList;
1172292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  StmtList.push_back(RSSetObjectCall);
1173292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines  AppendAfterStmt(C, mCS, DS, StmtList);
1174c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
1175c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
1176c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
1177c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
11781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
1179d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> RSClearObjectCalls;
11801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
11811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
11821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
11831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
1184a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    clang::Stmt *S = ClearRSObject(*I);
1185a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    if (S) {
1186a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines      RSClearObjectCalls.push_back(S);
11871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
11881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
11891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
1190292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    DestructorVisitor DV((*mRSO.begin())->getASTContext(),
1191292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                         mCS,
1192292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines                         RSClearObjectCalls);
11934464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DV.Visit(mCS);
1194292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines    DV.InsertDestructors();
11951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
11961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
11971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
11981bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1199d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
1200f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(VD);
12011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
1202f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::DeclContext *DC = VD->getDeclContext();
12031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
12041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
120503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
12061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
12071bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
12081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
1209be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
12101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
12111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
1212be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1213be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
1214be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
12151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1216f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
1217be27482cdeaf08576bc39b72a15d35d13014a636Logan    return ClearArrayRSObject(C, DC, RefRSVar, Loc);
1218f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
12191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1220f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
1221f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
12221bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1223f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1224f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DT == RSExportPrimitiveType::DataTypeIsStruct) {
1225be27482cdeaf08576bc39b72a15d35d13014a636Logan    return ClearStructRSObject(C, DC, RefRSVar, Loc);
1226f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
12271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1228f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1229f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should be RS object");
12301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1231f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return ClearSingleRSObject(C, RefRSVar, Loc);
12321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
12331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1234e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1235e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          RSExportPrimitiveType::DataType *DT,
1236e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          clang::Expr **InitExpr) {
12376e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD && DT && InitExpr);
12384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
12392d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
12402d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
12412d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
12422d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
12432d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
12442d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
1245f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsStructWithRSObject = false;
1246e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
12474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1248e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
1249feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1250feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      *DT = RSExportPrimitiveType::DataTypeIsStruct;
1251f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DataTypeIsStructWithRSObject = true;
1252feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    } else {
1253feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      return false;
1254feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    }
12552d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
12564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1257f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsRSObject = false;
1258f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DataTypeIsStructWithRSObject) {
1259f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = true;
1260f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
1261f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1262f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1263e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *InitExpr = VD->getInit();
1264e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1265e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!DataTypeIsRSObject && *InitExpr) {
1266e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    // If we already have an initializer for a matrix type, we are done.
1267e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return DataTypeIsRSObject;
12684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
12694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1270e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ZeroInitializer =
1271e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      CreateZeroInitializerForRSSpecificType(*DT,
1272e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getASTContext(),
1273e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getLocation());
1274e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1275e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (ZeroInitializer) {
1276e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    ZeroInitializer->setType(T->getCanonicalTypeInternal());
1277e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    VD->setInit(ZeroInitializer);
1278e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1279e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1280e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return DataTypeIsRSObject;
12814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
12824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
12844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
12854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
12864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
12874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
12884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
1289feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    case RSExportPrimitiveType::DataTypeIsStruct:
12904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
12914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
12924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
12934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
12944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
12954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
12964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
12974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
12984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
12994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
13004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
13014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
13024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
13034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
13044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
13054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
13064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
13074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
13084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
13094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
13104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
13114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
13124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1313e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
13144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
13154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
13164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
13174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
13184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
13194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
13204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
13214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
13224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
13234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
13244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
13254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
13264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
13274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
13284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
13294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
13304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
13314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
13324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
13334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
13344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
13354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
13374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
13384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
13394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
13404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
13414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
13424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
13434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
13454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
13464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
13474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
13484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
1349e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
13504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
13514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
13524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
13534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
13544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1355e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
13564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
13574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
13584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
13594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
13604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
13614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
13624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
13634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
13644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
13654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
13664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
13674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
13684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
13694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
13704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
13714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
13724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
13734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
13744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
13756e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(false && "Not RS object type!");
13764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
13774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
13784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
13794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
13814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
13824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
13844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
13854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
13864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
13874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
13884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
13894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
1390e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      RSExportPrimitiveType::DataType DT =
1391e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines          RSExportPrimitiveType::DataTypeUnknown;
1392e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::Expr *InitExpr = NULL;
1393e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      if (InitializeRSObject(VD, &DT, &InitExpr)) {
13944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
1395a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines        getCurrentScope()->AppendRSObjectInit(mDiags, VD, DS, DT, InitExpr);
1396e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      }
13974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
13984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
13994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
14004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
14014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
14034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
14044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
14054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
14064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
14074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
14094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
14116e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
14121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
14134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
14144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
14154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
14164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
14174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
14184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
1420c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
1421c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
14222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (CountRSObjectTypes(QT.getTypePtr())) {
14232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    getCurrentScope()->ReplaceRSObjectAssignment(AS, mDiags);
1424c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
1425c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
14264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
14274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
14284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
14294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
14304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
14314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
14324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
14334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
14344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
14354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
14364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
14374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
14384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
14394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1440e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
1441