slang_rs_object_ref_count.cpp revision be27482cdeaf08576bc39b72a15d35d13014a636
14b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines/*
24b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Copyright 2010, The Android Open Source Project
34b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
44b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
54b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * you may not use this file except in compliance with the License.
64b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * You may obtain a copy of the License at
74b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
84b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *     http://www.apache.org/licenses/LICENSE-2.0
94b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Unless required by applicable law or agreed to in writing, software
114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * See the License for the specific language governing permissions and
144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * limitations under the License.
154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines */
164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_object_ref_count.h"
184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <list>
20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/DeclGroup.h"
224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Expr.h"
23be27482cdeaf08576bc39b72a15d35d13014a636Logan#include "clang/AST/NestedNameSpecifier.h"
244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/OperationKinds.h"
254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Stmt.h"
264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h"
274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
286e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs.h"
304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
32e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
34f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::FunctionDecl *RSObjectRefCount::
351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                  RSExportPrimitiveType::FirstRSObjectType + 1];
37f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::FunctionDecl *RSObjectRefCount::
381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                    RSExportPrimitiveType::FirstRSObjectType + 1];
401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
41f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesvoid RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (unsigned i = 0;
431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i++) {
451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[i] = NULL;
461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[i] = NULL;
471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = TUDecl->decls_end(); I != E; I++) {
531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((I->getKind() >= clang::Decl::firstFunction) &&
541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        (I->getKind() <= clang::Decl::lastFunction)) {
551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // points to RSSetObjectFD or RSClearObjectFD
581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl **RSObjectFD;
591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      if (FD->getName() == "rsSetObject") {
616e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 2) &&
626e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsSetObject function prototype (# params)");
631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
656e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 1) &&
666e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsClearObject function prototype (# params)");
671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSClearObjectFD;
68e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      } else {
691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        continue;
701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType PVT = PVD->getOriginalType();
741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The first parameter must be a pointer like rs_allocation*
756e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(PVT->isPointerType() &&
766e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines          "Invalid rs{Set,Clear}Object function prototype (pointer param)");
771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The rs object type passed to the FD
791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType RST = PVT->getPointeeType();
801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::DataType DT =
811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
826e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             && "must be RS object type");
841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
904464d825c11349068f2917f9ebee86b721423f3cStephen Hinesnamespace {
914464d825c11349068f2917f9ebee86b721423f3cStephen Hines
924464d825c11349068f2917f9ebee86b721423f3cStephen Hinesstatic void AppendToCompoundStatement(clang::ASTContext& C,
934464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                      clang::CompoundStmt *CS,
94d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines                                      std::list<clang::Stmt*> &StmtList,
954464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                      bool InsertAtEndOfBlock) {
961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Destructor code will be inserted before any return statement.
971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Any subsequent statements in the compound statement are then placed
981bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // after our new code.
99e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  // TODO(srhines): This should also handle the case of goto/break/continue.
1004464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1014464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
1021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned OldStmtCount = 0;
10403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
1051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    OldStmtCount++;
1061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1071bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
108d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  unsigned NewStmtCount = StmtList.size();
1091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
110d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  clang::Stmt **UpdatedStmtList;
111d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  UpdatedStmtList = new clang::Stmt*[OldStmtCount+NewStmtCount];
1121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned UpdatedStmtCount = 0;
1144464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool FoundReturn = false;
11503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
1161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
1174464d825c11349068f2917f9ebee86b721423f3cStephen Hines      FoundReturn = true;
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      break;
1191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
120d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
1211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1221bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1234464d825c11349068f2917f9ebee86b721423f3cStephen Hines  // Always insert before a return that we found, or if we are told
1244464d825c11349068f2917f9ebee86b721423f3cStephen Hines  // to insert at the end of the block
1254464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (FoundReturn || InsertAtEndOfBlock) {
12603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
12703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
12803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines         I != StmtList.end();
1294464d825c11349068f2917f9ebee86b721423f3cStephen Hines         I++) {
130d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *I;
1314464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
1321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Pick up anything left over after a return statement
13503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for ( ; bI != CS->body_end(); bI++) {
136d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
1371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
139d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
1401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
141d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  delete [] UpdatedStmtList;
1421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
1441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
146e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesstatic void AppendAfterStmt(clang::ASTContext& C,
147e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::CompoundStmt *CS,
148e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::Stmt *OldStmt,
149e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::Stmt *NewStmt) {
1506e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(CS && OldStmt && NewStmt);
151e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
152e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned StmtCount = 1;  // Take into account new statement
153e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
154e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    StmtCount++;
155e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
156e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
157e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
158e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
159e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned UpdatedStmtCount = 0;
160e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned Once = 0;
161e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
162e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
163e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    if (*bI == OldStmt) {
164e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      Once++;
1656e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(Once == 1);
166e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
167e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    }
168e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
169e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
170e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
171e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
172e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  delete [] UpdatedStmtList;
173e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
174e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
175e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
176e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
177e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesstatic void ReplaceInCompoundStmt(clang::ASTContext& C,
178c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::CompoundStmt *CS,
179c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::Stmt* OldStmt,
180c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::Stmt* NewStmt) {
181c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
182c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
183c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  unsigned StmtCount = 0;
184c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
185c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    StmtCount++;
186c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
187c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
188c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
189c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
190c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  unsigned UpdatedStmtCount = 0;
191c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
192c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    if (*bI == OldStmt) {
193c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
194c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    } else {
195c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *bI;
196c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    }
197c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
198c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
199c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
200c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
201c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  delete [] UpdatedStmtList;
202c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
203c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
204c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
205c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
206c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
207d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines// This class visits a compound statement and inserts the StmtList containing
2084464d825c11349068f2917f9ebee86b721423f3cStephen Hines// destructors in proper locations. This includes inserting them before any
2094464d825c11349068f2917f9ebee86b721423f3cStephen Hines// return statement in any sub-block, at the end of the logical enclosing
2104464d825c11349068f2917f9ebee86b721423f3cStephen Hines// scope (compound statement), and/or before any break/continue statement that
2114464d825c11349068f2917f9ebee86b721423f3cStephen Hines// would resume outside the declared scope. We will not handle the case for
2124464d825c11349068f2917f9ebee86b721423f3cStephen Hines// goto statements that leave a local scope.
2134464d825c11349068f2917f9ebee86b721423f3cStephen Hines// TODO(srhines): Make this work properly for break/continue.
2144464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
2154464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
2164464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::ASTContext &mC;
217d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> &mStmtList;
2184464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool mTopLevel;
2194464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
220d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList);
2214464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
2224464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitCompoundStmt(clang::CompoundStmt *CS);
2234464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
2244464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2254464d825c11349068f2917f9ebee86b721423f3cStephen HinesDestructorVisitor::DestructorVisitor(clang::ASTContext &C,
226d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines                                     std::list<clang::Stmt*> &StmtList)
2274464d825c11349068f2917f9ebee86b721423f3cStephen Hines  : mC(C),
228d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    mStmtList(StmtList),
2294464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel(true) {
2304464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2314464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2324464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2334464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
2344464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (!CS->body_empty()) {
235d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel);
2364464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel = false;
2374464d825c11349068f2917f9ebee86b721423f3cStephen Hines    VisitStmt(CS);
2384464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2394464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2404464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2414464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2424464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
2434464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
2444464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I != E;
2454464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I++) {
2464464d825c11349068f2917f9ebee86b721423f3cStephen Hines    if (clang::Stmt *Child = *I) {
2474464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
2484464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
2494464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2504464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2514464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2524464d825c11349068f2917f9ebee86b721423f3cStephen Hines
253f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::Expr *ClearSingleRSObject(clang::ASTContext &C,
254f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::Expr *RefRSVar,
255f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::SourceLocation Loc) {
256f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(RefRSVar);
257f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *T = RefRSVar->getType().getTypePtr();
258f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!T->isArrayType() &&
259f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should not be destroying arrays with this function");
260f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
261f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
262f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((ClearObjectFD != NULL) &&
263f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "rsClearObject doesn't cover all RS object types");
264f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
265f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
266f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDArgType =
267f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
268f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
269f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Example destructor for "rs_font localFont;"
270f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //
271f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // (CallExpr 'void'
272f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
273f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
274f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
275f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
276f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
277f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Get address of targeted RS object
278f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *AddrRefRSVar =
279f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
280f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  clang::UO_AddrOf,
281f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  ClearObjectFDArgType,
282be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
283be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
284f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  Loc);
285f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
286f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSClearObjectFD =
287f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclRefExpr::Create(C,
288be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
289f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD,
290f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getLocation(),
291be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 ClearObjectFDType,
292be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
293be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
294f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
295f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RSClearObjectFP =
296f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::ImplicitCastExpr::Create(C,
297f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      C.getPointerType(ClearObjectFDType),
298f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::CK_FunctionToPointerDecay,
299f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      RefRSClearObjectFD,
300f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      NULL,
301f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::VK_RValue);
30203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
303f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CallExpr *RSClearObjectCall =
304f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CallExpr(C,
305f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             RSClearObjectFP,
306f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             &AddrRefRSVar,
307f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             1,
308f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             ClearObjectFD->getCallResultType(),
309be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
310f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             Loc);
311f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
312f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSClearObjectCall;
313f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
314f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
315f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic int ArrayDim(const clang::Type *T) {
31603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
31703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
31803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
31903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
32003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
32103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
3229d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
32303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
32403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
325f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
326f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
327f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
328f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
329f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc);
330f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
331f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearArrayRSObject(
332f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
333f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
334f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSArr,
335f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
336f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
337f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(BaseType->isArrayType());
338f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
339f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  int NumArrayElements = ArrayDim(BaseType);
340f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Actually extract out the base RS object type for use later
341f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
34203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
34403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int StmtCtr = 0;
34503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
34703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return NULL;
34803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
34903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
35003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
35103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
35203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // (CompoundStmt
35303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (DeclStmt "int rsIntIter")
35403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (ForStmt
35503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '='
35603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
35703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 0))
35803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '<'
35903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
36003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 10)
36103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     NULL << CondVar >>
36203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (UnaryOperator 'int' postfix '++'
36303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
36403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (CallExpr 'void'
36503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
36603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
36703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (UnaryOperator 'rs_font *' prefix '&'
36803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (ArraySubscriptExpr 'rs_font':'rs_font'
36903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
37003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
37103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (DeclRefExpr 'int' Var='rsIntIter')))))))
37203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
37303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
37403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
37503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
37603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
377f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             DC,
37803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
37903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &II,
38003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
38103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
38203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None,
38303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
38403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
38503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
38703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
38803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
39003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
39103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
39203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
39303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Init -> "rsIntIter = 0"
39403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
39503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
396be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
39703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
39803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
399be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
400be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
401be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
40203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
40403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
40503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Init =
40703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
40803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Int0,
40903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_Assign,
41003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
411be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
412be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
41303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
41403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
41503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
41603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
41703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
41803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
41903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
42003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
42103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
42303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
424be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
425be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
42603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
42703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
42803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
42903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
43003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
43103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
43203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
433be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
434be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
43503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
43603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
43803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
43903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
440f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtr =
44103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
442f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
44303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
444f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          RefRSArr,
44503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          NULL,
44603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
44703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
448f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtrSubscript =
449f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
45003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       RefrsIntIter,
451f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       BaseType->getCanonicalTypeInternal(),
452be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
453be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
454f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       Loc);
45503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
456f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
457f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
458f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
459f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt *RSClearObjectCall = NULL;
460f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (BaseType->isArrayType()) {
461f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
462be27482cdeaf08576bc39b72a15d35d13014a636Logan        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, Loc);
463f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
464f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
465be27482cdeaf08576bc39b72a15d35d13014a636Logan        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, Loc);
466f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
467f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
468f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
46903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
47003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
47103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
47203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
47303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
47403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            NULL,  // no condVar
47503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
47603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
47703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
47803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
47903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
48003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
48103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
4826e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(StmtCtr == 2);
48303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
48403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CompoundStmt *CS =
48503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
48603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
48703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  return CS;
48803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
48903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
4902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic unsigned CountRSObjectTypes(const clang::Type *T) {
491f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(T);
492f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned RSObjectCount = 0;
493f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
494f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
4952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
496f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
497f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
498f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
499f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
500f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT != RSExportPrimitiveType::DataTypeUnknown) {
501f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
502f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
503f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
504f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (!T->isStructureType()) {
505f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return 0;
506f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
507f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
508f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
509f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
510f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
511f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
512f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
513f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
514f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::FieldDecl *FD = *FI;
515f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
5162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (CountRSObjectTypes(FT)) {
517f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // Sub-structs should only count once (as should arrays, etc.)
518f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSObjectCount++;
519f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
520f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
521f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
522f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSObjectCount;
523f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
524f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
525f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
526f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
527f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
528f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
529f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
530f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
531f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
532f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!BaseType->isArrayType());
533f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
534f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
535f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
536f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
537f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Structs should show up as unknown primitive types
538f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(DT == RSExportPrimitiveType::DataTypeUnknown);
539f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
5402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
541f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
542f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned StmtCount = 0;
543f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
5442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToDestroy; i++) {
5452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    StmtArray[i] = NULL;
5462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
547f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
548f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Populate StmtArray by creating a destructor for each RS object field
549f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
550f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
551f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
552f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
553f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
554f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
555f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // We just look through all field declarations to see if we find a
556f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // declaration for an RS object type (or an array of one).
557f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    bool IsArrayType = false;
558f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::FieldDecl *FD = *FI;
559f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
560f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *OrigType = FT;
561f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    while (FT && FT->isArrayType()) {
562f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
563f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      IsArrayType = true;
564f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
565f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
566f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
567f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
568f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
569f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
570f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
571f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
572f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
573be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
574f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
575f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
576f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
577f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
578be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
579be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
580be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
581f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
582f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      slangAssert(StmtCount < FieldsToDestroy);
583f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
584f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
585f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
586f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
587f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
588f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
589f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
590f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearSingleRSObject(C,
591f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
592f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
593f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
5942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
595f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // In this case, we have a nested struct. We may not end up filling all
596f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // of the spaces in StmtArray (sub-structs should handle themselves
597f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // with separate compound statements).
598f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
599f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
600f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
601f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
602f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
603f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
604be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::NestedNameSpecifierLoc(),
605f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
606f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
607f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
608f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
609be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    OrigType->getCanonicalTypeInternal(),
610be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::VK_RValue,
611be27482cdeaf08576bc39b72a15d35d13014a636Logan                                    clang::OK_Ordinary);
612f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
613f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
614f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
615f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
616f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
617f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
618f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
619f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearStructRSObject(C,
620f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     DC,
621f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
622f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
623f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
624f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
625f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
626f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
627f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(StmtCount > 0);
628f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CompoundStmt *CS =
629f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
630f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
631f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  delete [] StmtArray;
632f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
633f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return CS;
634f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
635f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
6362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
6372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Diagnostic *Diags,
6382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *DstExpr,
6392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *SrcExpr,
6402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc) {
6412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = DstExpr->getType().getTypePtr();
6422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
6436e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
6446e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
645c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
646c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
647c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
648c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
649c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
650c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
651c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
652c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
653be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
654c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
655c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
656be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
657be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
658be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
659c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
660c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
661c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
662c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
663c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
664c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
665c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      NULL,
666c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
667c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
668c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *ArgList[2];
6692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(DstExpr,
670c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           clang::UO_AddrOf,
671c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           SetObjectFDArgType[0],
672be27482cdeaf08576bc39b72a15d35d13014a636Logan                                           clang::VK_RValue,
673be27482cdeaf08576bc39b72a15d35d13014a636Logan                                           clang::OK_Ordinary,
674c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           Loc);
6752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  ArgList[1] = SrcExpr;
676c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
677c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CallExpr *RSSetObjectCall =
678c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      new(C) clang::CallExpr(C,
679c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             RSSetObjectFP,
680c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             ArgList,
681c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             2,
682c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             SetObjectFD->getCallResultType(),
683be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
684c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             Loc);
685c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
6862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return RSSetObjectCall;
6872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
6882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
6892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
6902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Diagnostic *Diags,
6912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *LHS,
6922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *RHS,
6932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc);
6942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
6952bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
6962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Diagnostic *Diags,
6972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *DstArr,
6982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::Expr *SrcArr,
6992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                           clang::SourceLocation Loc) {
7002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclContext *DC = NULL;
7012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *BaseType = DstArr->getType().getTypePtr();
7022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(BaseType->isArrayType());
7032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int NumArrayElements = ArrayDim(BaseType);
7052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Actually extract out the base RS object type for use later
7062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
7072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
7092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  int StmtCtr = 0;
7102bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (NumArrayElements <= 0) {
7122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    return NULL;
7132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
7142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Create helper variable for iterating through elements
7162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
7172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::VarDecl *IIVD =
7182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::VarDecl::Create(C,
7192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             DC,
7202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             Loc,
7212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             &II,
7222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.IntTy,
7232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
7242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None,
7252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                             clang::SC_None);
7262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
7272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
7292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
7302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Form the actual loop
7322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // for (Init; Cond; Inc)
7332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  //   RSSetObjectCall;
7342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Init -> "rsIntIter = 0"
7362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
7372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::DeclRefExpr::Create(C,
738be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
7392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 IIVD,
7402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                 Loc,
741be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 C.IntTy,
742be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
743be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
7442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
7462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
7472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Init =
7492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
7502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Int0,
7512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_Assign,
7522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
753be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
754be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
7552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
7562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
7582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
7592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
7602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *Cond =
7622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
7632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   NumArrayElementsExpr,
7642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   clang::BO_LT,
7652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   C.IntTy,
766be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
767be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::OK_Ordinary,
7682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                   Loc);
7692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Inc -> "rsIntIter++"
7712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::UnaryOperator *Inc =
7722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
7732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::UO_PostInc,
7742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  C.IntTy,
775be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
776be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary,
7772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  Loc);
7782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
7802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Loop operates on individual array elements
7812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtr =
7832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
7842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
7852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
7862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          DstArr,
7872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          NULL,
7882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
7892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7902bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *DstArrPtrSubscript =
7912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(DstArrPtr,
7922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
7932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
794be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
795be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
7962bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
7972bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
7982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtr =
7992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      clang::ImplicitCastExpr::Create(C,
8002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
8012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::CK_ArrayToPointerDecay,
8022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          SrcArr,
8032bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          NULL,
8042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          clang::VK_RValue);
8052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Expr *SrcArrPtrSubscript =
8072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ArraySubscriptExpr(SrcArrPtr,
8082bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       RefrsIntIter,
8092bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       BaseType->getCanonicalTypeInternal(),
810be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::VK_RValue,
811be27482cdeaf08576bc39b72a15d35d13014a636Logan                                       clang::OK_Ordinary,
8122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                       Loc);
8132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  RSExportPrimitiveType::DataType DT =
8152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
8162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt *RSSetObjectCall = NULL;
8182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (BaseType->isArrayType()) {
8192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSSetObjectCall = CreateArrayRSSetObject(C, Diags, DstArrPtrSubscript,
8202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                             SrcArrPtrSubscript, Loc);
8212bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
8222bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSSetObjectCall = CreateStructRSSetObject(C, Diags, DstArrPtrSubscript,
8232bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                              SrcArrPtrSubscript, Loc);
8242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
8252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSSetObjectCall = CreateSingleRSSetObject(C, Diags, DstArrPtrSubscript,
8262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                              SrcArrPtrSubscript, Loc);
8272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
8282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ForStmt *DestructorLoop =
8302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::ForStmt(C,
8312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Init,
8322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Cond,
8332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            NULL,  // no condVar
8342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Inc,
8352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            RSSetObjectCall,
8362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
8372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc,
8382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                            Loc);
8392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
8412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(StmtCtr == 2);
8422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::CompoundStmt *CS =
8442bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
8452bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
8472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
8482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesstatic clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
8502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Diagnostic *Diags,
8512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *LHS,
8522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::Expr *RHS,
8532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                            clang::SourceLocation Loc) {
8542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = LHS->getType();
8552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  const clang::Type *T = QT.getTypePtr();
8562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(T->isStructureType());
8572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
8582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // Keep an extra slot for the original copy (memcpy)
8602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
8612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  unsigned StmtCount = 0;
8632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
8642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (unsigned i = 0; i < FieldsToSet; i++) {
8652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    StmtArray[i] = NULL;
8662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
8672bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
8692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  RD = RD->getDefinition();
8702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
8712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines         FE = RD->field_end();
8722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI != FE;
8732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines       FI++) {
8742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    bool IsArrayType = false;
8752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::FieldDecl *FD = *FI;
8762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
8772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    const clang::Type *OrigType = FT;
8782bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (!CountRSObjectTypes(FT)) {
8802bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // Skip to next if we don't have any viable RS object types
8812bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      continue;
8822bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
8832bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8842bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::DeclAccessPair FoundDecl =
8852bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::DeclAccessPair::make(FD, clang::AS_none);
8862bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *DstMember =
8872bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
8882bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  LHS,
8892bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
890be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
8912bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
8922bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
8932bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::DeclarationNameInfo(),
8942bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  NULL,
895be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
896be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
897be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
8982bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
8992bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::MemberExpr *SrcMember =
9002bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        clang::MemberExpr::Create(C,
9012bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  RHS,
9022bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  false,
903be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::NestedNameSpecifierLoc(),
9042bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FD,
9052bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  FoundDecl,
9062bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  clang::DeclarationNameInfo(),
9072bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines                                  NULL,
908be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  OrigType->getCanonicalTypeInternal(),
909be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::VK_RValue,
910be27482cdeaf08576bc39b72a15d35d13014a636Logan                                  clang::OK_Ordinary);
9112bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9122bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (FT->isArrayType()) {
9132bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
9142bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      IsArrayType = true;
9152bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9162bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9172bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    RSExportPrimitiveType::DataType DT =
9182bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        RSExportPrimitiveType::GetRSSpecificType(FT);
9192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    if (IsArrayType) {
921832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines      Diags->Report(clang::FullSourceLoc(Loc, C.getSourceManager()),
922832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines          Diags->getCustomDiagID(clang::Diagnostic::Error,
923832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines            "Arrays of RS object types within structures cannot be copied"));
9242bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // TODO(srhines): Support setting arrays of RS objects
9252bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      // StmtArray[StmtCount++] =
9262bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      //    CreateArrayRSSetObject(C, Diags, DstMember, SrcMember, Loc);
9272bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
9282bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
9292bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          CreateStructRSSetObject(C, Diags, DstMember, SrcMember, Loc);
9302bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
9312bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      StmtArray[StmtCount++] =
9322bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines          CreateSingleRSSetObject(C, Diags, DstMember, SrcMember, Loc);
9332bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    } else {
9342bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      slangAssert(false);
9352bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    }
9362bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
9372bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9382bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  slangAssert(StmtCount > 0 && StmtCount < FieldsToSet);
9392bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9402bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // We still need to actually do the overall struct copy. For simplicity,
9412bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // we just do a straight-up assignment (which will still preserve all
9422bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  // the proper RS object reference counts).
9432bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::BinaryOperator *CopyStruct =
944be27482cdeaf08576bc39b72a15d35d13014a636Logan      new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
945be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue, clang::OK_Ordinary, Loc);
9462bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  StmtArray[StmtCount++] = CopyStruct;
9472bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9482bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::CompoundStmt *CS =
9492bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
9502bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9512bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  delete [] StmtArray;
9522bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9532bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  return CS;
9542bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}
9552bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9562bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines}  // namespace
9572bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9582bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hinesvoid RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
9592bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::BinaryOperator *AS,
9602bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    clang::Diagnostic *Diags) {
9612bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9622bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::QualType QT = AS->getType();
9632bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9642bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
9652bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines      RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
9662bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
967832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52Stephen Hines  clang::SourceLocation Loc = AS->getExprLoc();
9682bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  clang::Stmt *UpdatedStmt = NULL;
9692bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines
9702bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
9712bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    // By definition, this is a struct assignment if we get here
9722bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
9732bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        CreateStructRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
9742bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  } else {
9752bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    UpdatedStmt =
9762bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines        CreateSingleRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
9772bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  }
978e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
9792bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  ReplaceInCompoundStmt(C, mCS, AS, UpdatedStmt);
980e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
981e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
982e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
983e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesvoid RSObjectRefCount::Scope::AppendRSObjectInit(
984a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::Diagnostic *Diags,
985e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::VarDecl *VD,
986e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::DeclStmt *DS,
987e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    RSExportPrimitiveType::DataType DT,
988e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::Expr *InitExpr) {
9896e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD);
990e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
991e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!InitExpr) {
992e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return;
993e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
994e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
995a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
996a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines      RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
997a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines  clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
998a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines      RSExportPrimitiveType::DataTypeRSFont)->getLocation();
999a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1000f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
1001f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // TODO(srhines): Skip struct initialization right now
1002a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1003a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::DeclRefExpr *RefRSVar =
1004a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines        clang::DeclRefExpr::Create(C,
1005be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::NestedNameSpecifierLoc(),
1006a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   VD,
1007a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines                                   Loc,
1008be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   T->getCanonicalTypeInternal(),
1009be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   clang::VK_RValue,
1010be27482cdeaf08576bc39b72a15d35d13014a636Logan                                   NULL);
1011a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1012a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    clang::Stmt *RSSetObjectOps =
1013a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines        CreateStructRSSetObject(C, Diags, RefRSVar, InitExpr, Loc);
1014a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines
1015a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines    AppendAfterStmt(C, mCS, DS, RSSetObjectOps);
1016f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return;
1017f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1018f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
1019f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
10206e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
10216e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
1022e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1023e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
1024e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDArgType[2];
1025e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1026e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1027e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1028e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RefRSSetObjectFD =
1029e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1030be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
1031e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD,
1032e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1033be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 SetObjectFDType,
1034be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
1035be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
1036e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1037e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RSSetObjectFP =
1038e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::ImplicitCastExpr::Create(C,
1039e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      C.getPointerType(SetObjectFDType),
1040e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::CK_FunctionToPointerDecay,
1041e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      RefRSSetObjectFD,
1042e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      NULL,
1043e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::VK_RValue);
1044e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1045e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1046e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::DeclRefExpr *RefRSVar =
1047e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
1048be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
1049e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD,
1050e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
1051be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1052be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
1053be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
1054e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1055e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ArgList[2];
1056e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
1057e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           clang::UO_AddrOf,
1058e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           SetObjectFDArgType[0],
1059be27482cdeaf08576bc39b72a15d35d13014a636Logan                                           clang::VK_RValue,
1060be27482cdeaf08576bc39b72a15d35d13014a636Logan                                           clang::OK_Ordinary,
1061e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           Loc);
1062e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[1] = InitExpr;
1063e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1064e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CallExpr *RSSetObjectCall =
1065e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      new(C) clang::CallExpr(C,
1066e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             RSSetObjectFP,
1067e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             ArgList,
1068e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             2,
1069e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             SetObjectFD->getCallResultType(),
1070be27482cdeaf08576bc39b72a15d35d13014a636Logan                             clang::VK_RValue,
1071e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             Loc);
1072e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1073e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  AppendAfterStmt(C, mCS, DS, RSSetObjectCall);
1074c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
1075c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
1076c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
1077c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
10781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
1079d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> RSClearObjectCalls;
10801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
10811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
10821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
10831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
1084a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    clang::Stmt *S = ClearRSObject(*I);
1085a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    if (S) {
1086a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines      RSClearObjectCalls.push_back(S);
10871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
10881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
10891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
10904464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
10914464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DV.Visit(mCS);
10921bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
10931bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
10941bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
10951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1096d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
1097f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(VD);
10981bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
1099f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::DeclContext *DC = VD->getDeclContext();
11001bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
11011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
110203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
11031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
11041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
11051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
1106be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::NestedNameSpecifierLoc(),
11071bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
11081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
1109be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 T->getCanonicalTypeInternal(),
1110be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 clang::VK_RValue,
1111be27482cdeaf08576bc39b72a15d35d13014a636Logan                                 NULL);
11121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1113f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
1114be27482cdeaf08576bc39b72a15d35d13014a636Logan    return ClearArrayRSObject(C, DC, RefRSVar, Loc);
1115f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
11161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1117f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
1118f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
11191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1120f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1121f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DT == RSExportPrimitiveType::DataTypeIsStruct) {
1122be27482cdeaf08576bc39b72a15d35d13014a636Logan    return ClearStructRSObject(C, DC, RefRSVar, Loc);
1123f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
11241bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1125f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1126f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should be RS object");
11271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1128f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return ClearSingleRSObject(C, RefRSVar, Loc);
11291bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
11301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1131e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1132e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          RSExportPrimitiveType::DataType *DT,
1133e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          clang::Expr **InitExpr) {
11346e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD && DT && InitExpr);
11354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
11362d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
11372d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
11382d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
11392d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
11402d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
11412d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
1142f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsStructWithRSObject = false;
1143e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
11444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1145e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
1146feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1147feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      *DT = RSExportPrimitiveType::DataTypeIsStruct;
1148f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DataTypeIsStructWithRSObject = true;
1149feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    } else {
1150feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      return false;
1151feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    }
11522d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
11534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1154f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsRSObject = false;
1155f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DataTypeIsStructWithRSObject) {
1156f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = true;
1157f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
1158f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1159f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
1160e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *InitExpr = VD->getInit();
1161e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1162e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!DataTypeIsRSObject && *InitExpr) {
1163e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    // If we already have an initializer for a matrix type, we are done.
1164e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return DataTypeIsRSObject;
11654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
11664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1167e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ZeroInitializer =
1168e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      CreateZeroInitializerForRSSpecificType(*DT,
1169e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getASTContext(),
1170e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getLocation());
1171e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1172e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (ZeroInitializer) {
1173e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    ZeroInitializer->setType(T->getCanonicalTypeInternal());
1174e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    VD->setInit(ZeroInitializer);
1175e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
1176e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
1177e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return DataTypeIsRSObject;
11784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
11794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
11804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
11814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
11824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
11834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
11844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
11854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
1186feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    case RSExportPrimitiveType::DataTypeIsStruct:
11874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
11884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
11894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
11904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
11914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
11924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
11934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
11944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
11954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
11964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
11974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
11984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
11994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
12004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
12014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
12024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
12034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
12044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
12054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
12064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
12074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
12084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
12094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1210e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
12114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
12124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
12134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
12144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
12154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
12164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
12174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
12184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
12194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
12204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
12214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
12224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
12234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
12244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
12254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
12264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
12274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
12284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
12294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
12304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
12314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
12324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
12344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
12354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
12364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
12374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
12384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
12394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
12404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
12424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
12434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
12444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
12454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
1246e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
12474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
12484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
12494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
12504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
12514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1252e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
12534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
12544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
12554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
12564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
12574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
12584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
12594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
12604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
12614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
12624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
12634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
12644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
12654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
12664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
12674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
12684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
12694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
12704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
12714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
12726e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(false && "Not RS object type!");
12734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
12744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
12754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
12764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
12784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
12794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
12814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
12824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
12834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
12844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
12854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
12864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
1287e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      RSExportPrimitiveType::DataType DT =
1288e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines          RSExportPrimitiveType::DataTypeUnknown;
1289e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::Expr *InitExpr = NULL;
1290e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      if (InitializeRSObject(VD, &DT, &InitExpr)) {
12914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
1292a0611e66bec148b176404cf6afe4c9ec9b960414Stephen Hines        getCurrentScope()->AppendRSObjectInit(mDiags, VD, DS, DT, InitExpr);
1293e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      }
12944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
12954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
12964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
12974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
12984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
12994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
13004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
13014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
13024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
13034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
13044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
13064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
13086e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
13091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
13104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
13114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
13124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
13134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
13144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
13154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
1317c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
1318c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
13192bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines  if (CountRSObjectTypes(QT.getTypePtr())) {
13202bb67db8364162b30e6920baddf6c2e890b3ce79Stephen Hines    getCurrentScope()->ReplaceRSObjectAssignment(AS, mDiags);
1321c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
1322c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
13234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
13244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
13254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
13264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
13274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
13284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
13294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
13304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
13314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
13324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
13334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
13344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
13354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
13364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1337e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
1338