slang_rs_object_ref_count.cpp revision 2bb67db8364162b30e6920baddf6c2e890b3ce79
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"
234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/OperationKinds.h"
244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Stmt.h"
254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h"
264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
276e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs.h"
294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
31e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
33f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::FunctionDecl *RSObjectRefCount::
341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                  RSExportPrimitiveType::FirstRSObjectType + 1];
36f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::FunctionDecl *RSObjectRefCount::
371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                    RSExportPrimitiveType::FirstRSObjectType + 1];
391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
40f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesvoid RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (unsigned i = 0;
421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i++) {
441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[i] = NULL;
451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[i] = NULL;
461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = TUDecl->decls_end(); I != E; I++) {
521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((I->getKind() >= clang::Decl::firstFunction) &&
531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        (I->getKind() <= clang::Decl::lastFunction)) {
541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // points to RSSetObjectFD or RSClearObjectFD
571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl **RSObjectFD;
581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      if (FD->getName() == "rsSetObject") {
606e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 2) &&
616e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsSetObject function prototype (# params)");
621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
646e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 1) &&
656e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsClearObject function prototype (# params)");
661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSClearObjectFD;
67e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      } else {
681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        continue;
691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType PVT = PVD->getOriginalType();
731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The first parameter must be a pointer like rs_allocation*
746e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(PVT->isPointerType() &&
756e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines          "Invalid rs{Set,Clear}Object function prototype (pointer param)");
761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The rs object type passed to the FD
781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType RST = PVT->getPointeeType();
791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::DataType DT =
801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
816e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             && "must be RS object type");
831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
894464d825c11349068f2917f9ebee86b721423f3cStephen Hinesnamespace {
904464d825c11349068f2917f9ebee86b721423f3cStephen Hines
914464d825c11349068f2917f9ebee86b721423f3cStephen Hinesstatic void AppendToCompoundStatement(clang::ASTContext& C,
924464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                      clang::CompoundStmt *CS,
93d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines                                      std::list<clang::Stmt*> &StmtList,
944464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                      bool InsertAtEndOfBlock) {
951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Destructor code will be inserted before any return statement.
961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Any subsequent statements in the compound statement are then placed
971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // after our new code.
98e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  // TODO(srhines): This should also handle the case of goto/break/continue.
994464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1004464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
1011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned OldStmtCount = 0;
10303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
1041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    OldStmtCount++;
1051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
107d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  unsigned NewStmtCount = StmtList.size();
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
109d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  clang::Stmt **UpdatedStmtList;
110d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  UpdatedStmtList = new clang::Stmt*[OldStmtCount+NewStmtCount];
1111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned UpdatedStmtCount = 0;
1134464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool FoundReturn = false;
11403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
1151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
1164464d825c11349068f2917f9ebee86b721423f3cStephen Hines      FoundReturn = true;
1171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      break;
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
119d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
1201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1224464d825c11349068f2917f9ebee86b721423f3cStephen Hines  // Always insert before a return that we found, or if we are told
1234464d825c11349068f2917f9ebee86b721423f3cStephen Hines  // to insert at the end of the block
1244464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (FoundReturn || InsertAtEndOfBlock) {
12503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
12603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
12703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines         I != StmtList.end();
1284464d825c11349068f2917f9ebee86b721423f3cStephen Hines         I++) {
129d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *I;
1304464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
1311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Pick up anything left over after a return statement
13403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for ( ; bI != CS->body_end(); bI++) {
135d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
1361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
138d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
1391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
140d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  delete [] UpdatedStmtList;
1411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
1431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
145e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesstatic void AppendAfterStmt(clang::ASTContext& C,
146e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::CompoundStmt *CS,
147e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::Stmt *OldStmt,
148e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::Stmt *NewStmt) {
1496e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(CS && OldStmt && NewStmt);
150e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
151e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned StmtCount = 1;  // Take into account new statement
152e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
153e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    StmtCount++;
154e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
155e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
156e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
157e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
158e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned UpdatedStmtCount = 0;
159e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned Once = 0;
160e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
161e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
162e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    if (*bI == OldStmt) {
163e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      Once++;
1646e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(Once == 1);
165e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
166e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    }
167e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
168e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
169e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
170e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
171e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  delete [] UpdatedStmtList;
172e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
173e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
174e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
175e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
176e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesstatic void ReplaceInCompoundStmt(clang::ASTContext& C,
177c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::CompoundStmt *CS,
178c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::Stmt* OldStmt,
179c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::Stmt* NewStmt) {
180c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
181c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
182c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  unsigned StmtCount = 0;
183c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
184c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    StmtCount++;
185c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
186c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
187c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
188c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
189c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  unsigned UpdatedStmtCount = 0;
190c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
191c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    if (*bI == OldStmt) {
192c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
193c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    } else {
194c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *bI;
195c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    }
196c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
197c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
198c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
199c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
200c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  delete [] UpdatedStmtList;
201c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
202c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
203c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
204c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
205c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
206d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines// This class visits a compound statement and inserts the StmtList containing
2074464d825c11349068f2917f9ebee86b721423f3cStephen Hines// destructors in proper locations. This includes inserting them before any
2084464d825c11349068f2917f9ebee86b721423f3cStephen Hines// return statement in any sub-block, at the end of the logical enclosing
2094464d825c11349068f2917f9ebee86b721423f3cStephen Hines// scope (compound statement), and/or before any break/continue statement that
2104464d825c11349068f2917f9ebee86b721423f3cStephen Hines// would resume outside the declared scope. We will not handle the case for
2114464d825c11349068f2917f9ebee86b721423f3cStephen Hines// goto statements that leave a local scope.
2124464d825c11349068f2917f9ebee86b721423f3cStephen Hines// TODO(srhines): Make this work properly for break/continue.
2134464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
2144464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
2154464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::ASTContext &mC;
216d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> &mStmtList;
2174464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool mTopLevel;
2184464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
219d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList);
2204464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
2214464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitCompoundStmt(clang::CompoundStmt *CS);
2224464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
2234464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2244464d825c11349068f2917f9ebee86b721423f3cStephen HinesDestructorVisitor::DestructorVisitor(clang::ASTContext &C,
225d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines                                     std::list<clang::Stmt*> &StmtList)
2264464d825c11349068f2917f9ebee86b721423f3cStephen Hines  : mC(C),
227d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    mStmtList(StmtList),
2284464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel(true) {
2294464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2304464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2314464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2324464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
2334464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (!CS->body_empty()) {
234d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel);
2354464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel = false;
2364464d825c11349068f2917f9ebee86b721423f3cStephen Hines    VisitStmt(CS);
2374464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2384464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2394464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2404464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2414464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
2424464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
2434464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I != E;
2444464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I++) {
2454464d825c11349068f2917f9ebee86b721423f3cStephen Hines    if (clang::Stmt *Child = *I) {
2464464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
2474464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
2484464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2494464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2504464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2514464d825c11349068f2917f9ebee86b721423f3cStephen Hines
252f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::Expr *ClearSingleRSObject(clang::ASTContext &C,
253f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::Expr *RefRSVar,
254f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::SourceLocation Loc) {
255f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(RefRSVar);
256f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *T = RefRSVar->getType().getTypePtr();
257f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!T->isArrayType() &&
258f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should not be destroying arrays with this function");
259f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
260f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
261f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((ClearObjectFD != NULL) &&
262f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "rsClearObject doesn't cover all RS object types");
263f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
264f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
265f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDArgType =
266f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
267f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
268f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Example destructor for "rs_font localFont;"
269f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //
270f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // (CallExpr 'void'
271f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
272f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
273f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
274f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
275f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
276f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Get address of targeted RS object
277f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *AddrRefRSVar =
278f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
279f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  clang::UO_AddrOf,
280f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  ClearObjectFDArgType,
281f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  Loc);
282f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
283f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSClearObjectFD =
284f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclRefExpr::Create(C,
285f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 NULL,
286f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getQualifierRange(),
287f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD,
288f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getLocation(),
289f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFDType);
290f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
291f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RSClearObjectFP =
292f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::ImplicitCastExpr::Create(C,
293f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      C.getPointerType(ClearObjectFDType),
294f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::CK_FunctionToPointerDecay,
295f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      RefRSClearObjectFD,
296f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      NULL,
297f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::VK_RValue);
29803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
299f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CallExpr *RSClearObjectCall =
300f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CallExpr(C,
301f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             RSClearObjectFP,
302f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             &AddrRefRSVar,
303f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             1,
304f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             ClearObjectFD->getCallResultType(),
305f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             Loc);
306f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
307f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSClearObjectCall;
308f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
309f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
310f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic int ArrayDim(const clang::Type *T) {
31103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
31203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
31303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
31403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
31503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
31603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
3179d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
31803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
31903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
320f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
321f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
322f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
323f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
324f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceRange Range,
325f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc);
326f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
327f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearArrayRSObject(
328f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
329f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
330f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSArr,
331f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceRange Range,
332f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
333f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
334f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(BaseType->isArrayType());
335f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
336f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  int NumArrayElements = ArrayDim(BaseType);
337f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Actually extract out the base RS object type for use later
338f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
33903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
34103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int StmtCtr = 0;
34203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
34403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return NULL;
34503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
34603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
34803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
34903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // (CompoundStmt
35003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (DeclStmt "int rsIntIter")
35103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (ForStmt
35203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '='
35303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
35403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 0))
35503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '<'
35603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
35703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 10)
35803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     NULL << CondVar >>
35903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (UnaryOperator 'int' postfix '++'
36003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
36103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (CallExpr 'void'
36203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
36303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
36403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (UnaryOperator 'rs_font *' prefix '&'
36503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (ArraySubscriptExpr 'rs_font':'rs_font'
36603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
36703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
36803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (DeclRefExpr 'int' Var='rsIntIter')))))))
36903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
37003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
37103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
37203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
37303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
374f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             DC,
37503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
37603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &II,
37703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
37803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
37903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None,
38003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
38103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
38203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
38403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
38503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
38703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
38803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
38903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
39003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Init -> "rsIntIter = 0"
39103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
39203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
39303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
39403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
39503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
39603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
39703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 C.IntTy);
39803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
39903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
40003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
40103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Init =
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
40403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Int0,
40503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_Assign,
40603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
40703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
40803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
41003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
41103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
41203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
41303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
41403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
41503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
41603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
41703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
41803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
41903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
42003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
42103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
42303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
42403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
42503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
42603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
42703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
42803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
42903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
430f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtr =
43103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
432f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
43303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
434f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          RefRSArr,
43503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          NULL,
43603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
43703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
438f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtrSubscript =
439f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
44003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       RefrsIntIter,
441f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       BaseType->getCanonicalTypeInternal(),
442f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       Loc);
44303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
444f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
445f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
446f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
447f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt *RSClearObjectCall = NULL;
448f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (BaseType->isArrayType()) {
449f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
450f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc);
451f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
452f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
453f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc);
454f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
455f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
456f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
45703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
45803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
45903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
46003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
46103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
46203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            NULL,  // no condVar
46303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
46403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
46503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
46603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
46703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
46803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
46903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
4706e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(StmtCtr == 2);
47103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
47203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CompoundStmt *CS =
47303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
47403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
47503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  return CS;
47603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
47703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
4782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic unsigned CountRSObjectTypes(const clang::Type *T) {
479f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(T);
480f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned RSObjectCount = 0;
481f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
482f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
4832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
484f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
485f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
486f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
487f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
488f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT != RSExportPrimitiveType::DataTypeUnknown) {
489f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
490f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
491f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
492f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (!T->isStructureType()) {
493f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return 0;
494f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
495f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
496f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
497f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
498f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
499f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
500f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
501f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
502f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::FieldDecl *FD = *FI;
503f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
5042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (CountRSObjectTypes(FT)) {
505f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // Sub-structs should only count once (as should arrays, etc.)
506f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSObjectCount++;
507f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
508f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
509f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
510f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSObjectCount;
511f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
512f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
513f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
514f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
515f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
516f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
517f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceRange Range,
518f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
519f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
520f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
521f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!BaseType->isArrayType());
522f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
523f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
524f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
525f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
526f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Structs should show up as unknown primitive types
527f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(DT == RSExportPrimitiveType::DataTypeUnknown);
528f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
5292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
530f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
531f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned StmtCount = 0;
532f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
5332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToDestroy; i++) {
5342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    StmtArray[i] = NULL;
5352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
536f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
537f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Populate StmtArray by creating a destructor for each RS object field
538f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
539f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
540f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
541f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
542f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
543f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
544f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // We just look through all field declarations to see if we find a
545f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // declaration for an RS object type (or an array of one).
546f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    bool IsArrayType = false;
547f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::FieldDecl *FD = *FI;
548f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
549f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *OrigType = FT;
550f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    while (FT && FT->isArrayType()) {
551f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
552f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      IsArrayType = true;
553f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
554f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
555f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
556f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
557f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
558f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
559f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
560f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
561f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
562f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
563f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    Range,
564f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
565f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
566f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
567f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
568f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    OrigType->getCanonicalTypeInternal());
569f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
570f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      slangAssert(StmtCount < FieldsToDestroy);
571f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
572f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
573f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
574f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
575f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
576f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Range,
577f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
578f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
579f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearSingleRSObject(C,
580f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
581f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
582f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
5832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
584f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // In this case, we have a nested struct. We may not end up filling all
585f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // of the spaces in StmtArray (sub-structs should handle themselves
586f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // with separate compound statements).
587f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
588f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
589f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
590f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
591f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
592f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
593f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
594f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    Range,
595f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
596f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
597f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
598f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
599f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    OrigType->getCanonicalTypeInternal());
600f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
601f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
602f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
603f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
604f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
605f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Range,
606f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
607f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
608f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearStructRSObject(C,
609f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     DC,
610f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
611f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Range,
612f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
613f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
614f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
615f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
616f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
617f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(StmtCount > 0);
618f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CompoundStmt *CS =
619f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
620f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
621f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  delete [] StmtArray;
622f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
623f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return CS;
624f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
625f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
6262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
6272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Diagnostic *Diags,
6282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *DstExpr,
6292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *SrcExpr,
6302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc) {
6312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = DstExpr->getType().getTypePtr();
6322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
6336e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
6346e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
635c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
636c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
637c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
638c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
639c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
640c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
641c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
642c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
643c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 NULL,
644c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD->getQualifierRange(),
645c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
646c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
647c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFDType);
648c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
649c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
650c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
651c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
652c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
653c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
654c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      NULL,
655c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
656c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
657c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *ArgList[2];
6582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(DstExpr,
659c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           clang::UO_AddrOf,
660c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           SetObjectFDArgType[0],
661c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           Loc);
6622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  ArgList[1] = SrcExpr;
663c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
664c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CallExpr *RSSetObjectCall =
665c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      new(C) clang::CallExpr(C,
666c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             RSSetObjectFP,
667c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             ArgList,
668c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             2,
669c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             SetObjectFD->getCallResultType(),
670c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             Loc);
671c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
6722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return RSSetObjectCall;
6732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
6742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
6752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
6762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Diagnostic *Diags,
6772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *LHS,
6782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *RHS,
6792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc);
6802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
6812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
6822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Diagnostic *Diags,
6832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *DstArr,
6842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *SrcArr,
6852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::SourceLocation Loc) {
6862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclContext *DC = NULL;
6872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::SourceRange Range;
6882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *BaseType = DstArr->getType().getTypePtr();
6892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(BaseType->isArrayType());
6902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
6912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int NumArrayElements = ArrayDim(BaseType);
6922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Actually extract out the base RS object type for use later
6932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
6942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
6952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
6962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int StmtCtr = 0;
6972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
6982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (NumArrayElements <= 0) {
6992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    return NULL;
7002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
7012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Create helper variable for iterating through elements
7032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
7042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::VarDecl *IIVD =
7052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::VarDecl::Create(C,
7062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             DC,
7072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             Loc,
7082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             &II,
7092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.IntTy,
7102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
7112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None,
7122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None);
7132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
7142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
7162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
7172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Form the actual loop
7192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // for (Init; Cond; Inc)
7202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  //   RSSetObjectCall;
7212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Init -> "rsIntIter = 0"
7232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
7242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::DeclRefExpr::Create(C,
7252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 NULL,
7262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 Range,
7272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 IIVD,
7282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 Loc,
7292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 C.IntTy);
7302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
7322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
7332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Init =
7352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
7362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Int0,
7372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_Assign,
7382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
7392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
7402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
7422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
7432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
7442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Cond =
7462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
7472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   NumArrayElementsExpr,
7482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_LT,
7492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
7502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
7512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Inc -> "rsIntIter++"
7532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::UnaryOperator *Inc =
7542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
7552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::UO_PostInc,
7562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  C.IntTy,
7572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  Loc);
7582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
7602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Loop operates on individual array elements
7612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtr =
7632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
7642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
7652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
7662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          DstArr,
7672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          NULL,
7682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
7692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtrSubscript =
7712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(DstArrPtr,
7722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
7732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
7742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
7752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtr =
7772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
7782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
7792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
7802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          SrcArr,
7812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          NULL,
7822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
7832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtrSubscript =
7852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(SrcArrPtr,
7862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
7872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
7882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
7892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  RSExportPrimitiveType::DataType DT =
7912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
7922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt *RSSetObjectCall = NULL;
7942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (BaseType->isArrayType()) {
7952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSSetObjectCall = CreateArrayRSSetObject(C, Diags, DstArrPtrSubscript,
7962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                             SrcArrPtrSubscript, Loc);
7972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
7982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSSetObjectCall = CreateStructRSSetObject(C, Diags, DstArrPtrSubscript,
7992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                              SrcArrPtrSubscript, Loc);
8002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
8012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSSetObjectCall = CreateSingleRSSetObject(C, Diags, DstArrPtrSubscript,
8022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                              SrcArrPtrSubscript, Loc);
8032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
8042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ForStmt *DestructorLoop =
8062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ForStmt(C,
8072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Init,
8082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Cond,
8092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            NULL,  // no condVar
8102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Inc,
8112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            RSSetObjectCall,
8122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
8132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
8142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc);
8152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
8172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(StmtCtr == 2);
8182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::CompoundStmt *CS =
8202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
8212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
8232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
8242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
8262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Diagnostic *Diags,
8272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *LHS,
8282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *RHS,
8292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc) {
8302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::SourceRange Range;
8312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = LHS->getType();
8322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = QT.getTypePtr();
8332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(T->isStructureType());
8342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
8352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Keep an extra slot for the original copy (memcpy)
8372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
8382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned StmtCount = 0;
8402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
8412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToSet; i++) {
8422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    StmtArray[i] = NULL;
8432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
8442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
8462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  RD = RD->getDefinition();
8472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
8482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines         FE = RD->field_end();
8492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI != FE;
8502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI++) {
8512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    bool IsArrayType = false;
8522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::FieldDecl *FD = *FI;
8532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
8542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *OrigType = FT;
8552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (!CountRSObjectTypes(FT)) {
8572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // Skip to next if we don't have any viable RS object types
8582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      continue;
8592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
8602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::DeclAccessPair FoundDecl =
8622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::DeclAccessPair::make(FD, clang::AS_none);
8632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *DstMember =
8642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
8652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  LHS,
8662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
8672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  NULL,
8682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  Range,
8692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
8702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
8712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::DeclarationNameInfo(),
8722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  NULL,
8732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  OrigType->getCanonicalTypeInternal());
8742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *SrcMember =
8762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
8772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  RHS,
8782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
8792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  NULL,
8802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  Range,
8812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
8822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
8832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::DeclarationNameInfo(),
8842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  NULL,
8852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  OrigType->getCanonicalTypeInternal());
8862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (FT->isArrayType()) {
8882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
8892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      IsArrayType = true;
8902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
8912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSExportPrimitiveType::DataType DT =
8932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        RSExportPrimitiveType::GetRSSpecificType(FT);
8942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (IsArrayType) {
8962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      Diags->Report(Diags->getCustomDiagID(clang::Diagnostic::Error,
8972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines           "Arrays of RS object types within structures cannot be copied"));
8982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // TODO(srhines): Support setting arrays of RS objects
8992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // StmtArray[StmtCount++] =
9002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      //    CreateArrayRSSetObject(C, Diags, DstMember, SrcMember, Loc);
9012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
9022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
9032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          CreateStructRSSetObject(C, Diags, DstMember, SrcMember, Loc);
9042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
9052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
9062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          CreateSingleRSSetObject(C, Diags, DstMember, SrcMember, Loc);
9072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else {
9082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      slangAssert(false);
9092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
9112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(StmtCount > 0 && StmtCount < FieldsToSet);
9132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // We still need to actually do the overall struct copy. For simplicity,
9152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // we just do a straight-up assignment (which will still preserve all
9162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // the proper RS object reference counts).
9172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *CopyStruct =
9182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT, Loc);
9192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCount++] = CopyStruct;
9202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::CompoundStmt *CS =
9222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
9232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  delete [] StmtArray;
9252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
9272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
9282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}  // namespace
9302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesvoid RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
9322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::BinaryOperator *AS,
9332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::Diagnostic *Diags) {
9342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = AS->getType();
9362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
9382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
9392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::SourceLocation Loc = AS->getLocEnd();
9412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt *UpdatedStmt = NULL;
9422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
9442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    // By definition, this is a struct assignment if we get here
9452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
9462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        CreateStructRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
9472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
9482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
9492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        CreateSingleRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
9502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
951e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
9522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  ReplaceInCompoundStmt(C, mCS, AS, UpdatedStmt);
953e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
954e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
955e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
956e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesvoid RSObjectRefCount::Scope::AppendRSObjectInit(
957e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::VarDecl *VD,
958e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::DeclStmt *DS,
959e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    RSExportPrimitiveType::DataType DT,
960e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::Expr *InitExpr) {
9616e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD);
962e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
963e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!InitExpr) {
964e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return;
965e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
966e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
967f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
968f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // TODO(srhines): Skip struct initialization right now
969f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return;
970f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
971f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
972f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
9736e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
9746e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
975e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::ASTContext &C = SetObjectFD->getASTContext();
976e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
977e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
978e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDArgType[2];
979e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
980e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
981e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
982e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::SourceLocation Loc = SetObjectFD->getLocation();
983e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RefRSSetObjectFD =
984e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
985e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 NULL,
986e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD->getQualifierRange(),
987e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD,
988e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
989e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFDType);
990e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
991e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RSSetObjectFP =
992e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::ImplicitCastExpr::Create(C,
993e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      C.getPointerType(SetObjectFDType),
994e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::CK_FunctionToPointerDecay,
995e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      RefRSSetObjectFD,
996e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      NULL,
997e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::VK_RValue);
998e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
999e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1000e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::DeclRefExpr *RefRSVar =
1001e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1002e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 NULL,
1003e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD->getQualifierRange(),
1004e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD,
1005e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1006e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 T->getCanonicalTypeInternal());
1007e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1008e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ArgList[2];
1009e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
1010e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           clang::UO_AddrOf,
1011e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           SetObjectFDArgType[0],
1012e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           Loc);
1013e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[1] = InitExpr;
1014e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1015e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CallExpr *RSSetObjectCall =
1016e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      new(C) clang::CallExpr(C,
1017e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             RSSetObjectFP,
1018e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             ArgList,
1019e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             2,
1020e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             SetObjectFD->getCallResultType(),
1021e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             Loc);
1022e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1023e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  AppendAfterStmt(C, mCS, DS, RSSetObjectCall);
1024c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
1025c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
1026c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
1027c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
10281bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
1029d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> RSClearObjectCalls;
10301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
10311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
10321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
10331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
1034a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    clang::Stmt *S = ClearRSObject(*I);
1035a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    if (S) {
1036a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines      RSClearObjectCalls.push_back(S);
10371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
10381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
10391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
10404464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
10414464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DV.Visit(mCS);
10421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
10431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
10441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
10451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1046d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
1047f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(VD);
10481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
1049f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::DeclContext *DC = VD->getDeclContext();
1050f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::SourceRange Range = VD->getQualifierRange();
10511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
10521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
105303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
10541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
10551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
10561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
10571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
1058f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 Range,
10591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
10601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
106103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 T->getCanonicalTypeInternal());
10621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1063f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
1064f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return ClearArrayRSObject(C, DC, RefRSVar, Range, Loc);
1065f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
10661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1067f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
1068f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
10691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1070f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1071f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DT == RSExportPrimitiveType::DataTypeIsStruct) {
1072f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return ClearStructRSObject(C, DC, RefRSVar, Range, Loc);
1073f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
10741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1075f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1076f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should be RS object");
10771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1078f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return ClearSingleRSObject(C, RefRSVar, Loc);
10791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
10801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1081e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1082e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          RSExportPrimitiveType::DataType *DT,
1083e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          clang::Expr **InitExpr) {
10846e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD && DT && InitExpr);
10854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
10862d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
10872d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
10882d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
10892d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
10902d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
10912d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
1092f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsStructWithRSObject = false;
1093e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
10944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1095e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
1096feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1097feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      *DT = RSExportPrimitiveType::DataTypeIsStruct;
1098f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DataTypeIsStructWithRSObject = true;
1099feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    } else {
1100feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      return false;
1101feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    }
11022d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
11034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1104f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsRSObject = false;
1105f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DataTypeIsStructWithRSObject) {
1106f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = true;
1107f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
1108f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1109f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1110e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *InitExpr = VD->getInit();
1111e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1112e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!DataTypeIsRSObject && *InitExpr) {
1113e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    // If we already have an initializer for a matrix type, we are done.
1114e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return DataTypeIsRSObject;
11154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
11164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1117e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ZeroInitializer =
1118e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      CreateZeroInitializerForRSSpecificType(*DT,
1119e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getASTContext(),
1120e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getLocation());
1121e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1122e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (ZeroInitializer) {
1123e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    ZeroInitializer->setType(T->getCanonicalTypeInternal());
1124e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    VD->setInit(ZeroInitializer);
1125e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1126e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1127e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return DataTypeIsRSObject;
11284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
11294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
11304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
11314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
11324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
11334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
11344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
11354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
1136feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    case RSExportPrimitiveType::DataTypeIsStruct:
11374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
11384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
11394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
11404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
11414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
11424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
11434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
11444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
11454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
11464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
11474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
11484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
11494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
11504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
11514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
11524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
11534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
11544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
11554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
11564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
11574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
11584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
11594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1160e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
11614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
11624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
11634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
11644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
11654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
11664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
11674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
11684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
11694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
11704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
11714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
11724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
11734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
11744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
11754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
11764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
11774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
11784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
11794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
11804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
11814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
11824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
11834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
11844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
11854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
11864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
11874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
11884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
11894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
11904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
11914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
11924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
11934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
11944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
11954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
1196e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
11974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
11984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
11994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
12004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
12014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1202e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
12034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
12044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
12054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
12064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
12074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
12084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
12094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
12104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
12114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
12124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
12134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
12144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
12154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
12164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
12174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
12184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
12194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
12204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
12214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
12226e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(false && "Not RS object type!");
12234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
12244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
12254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
12264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
12284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
12294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
12314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
12324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
12334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
12344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
12354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
12364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
1237e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      RSExportPrimitiveType::DataType DT =
1238e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines          RSExportPrimitiveType::DataTypeUnknown;
1239e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::Expr *InitExpr = NULL;
1240e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      if (InitializeRSObject(VD, &DT, &InitExpr)) {
12414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
1242e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines        getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
1243e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      }
12444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
12454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
12464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
12474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
12484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
12504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
12514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
12524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
12534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
12544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
12564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
12586e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
12591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
12604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
12614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
12624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
12634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
12644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
12654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
1267c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
1268c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
12692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (CountRSObjectTypes(QT.getTypePtr())) {
12702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    getCurrentScope()->ReplaceRSObjectAssignment(AS, mDiags);
1271c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
1272c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
12734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
12744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
12754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
12774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
12784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
12794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
12804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
12814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
12824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
12834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
12844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
12854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
12864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1287e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
1288