slang_rs_object_ref_count.cpp revision f2174cfd6a556b51aadf2b8765e50df080e8f18e
14b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines/*
24b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Copyright 2010, The Android Open Source Project
34b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
44b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
54b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * you may not use this file except in compliance with the License.
64b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * You may obtain a copy of the License at
74b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
84b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *     http://www.apache.org/licenses/LICENSE-2.0
94b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Unless required by applicable law or agreed to in writing, software
114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * See the License for the specific language governing permissions and
144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * limitations under the License.
154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines */
164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_object_ref_count.h"
184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <list>
20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/DeclGroup.h"
224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Expr.h"
234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/OperationKinds.h"
244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Stmt.h"
254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h"
264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
276e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs.h"
294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
31e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
33f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::FunctionDecl *RSObjectRefCount::
341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                  RSExportPrimitiveType::FirstRSObjectType + 1];
36f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::FunctionDecl *RSObjectRefCount::
371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                    RSExportPrimitiveType::FirstRSObjectType + 1];
391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
40f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesvoid RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (unsigned i = 0;
421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i++) {
441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[i] = NULL;
451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[i] = NULL;
461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = TUDecl->decls_end(); I != E; I++) {
521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((I->getKind() >= clang::Decl::firstFunction) &&
531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        (I->getKind() <= clang::Decl::lastFunction)) {
541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // points to RSSetObjectFD or RSClearObjectFD
571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl **RSObjectFD;
581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      if (FD->getName() == "rsSetObject") {
606e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 2) &&
616e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsSetObject function prototype (# params)");
621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
646e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines        slangAssert((FD->getNumParams() == 1) &&
656e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines                    "Invalid rsClearObject function prototype (# params)");
661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSClearObjectFD;
67e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      } else {
681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        continue;
691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType PVT = PVD->getOriginalType();
731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The first parameter must be a pointer like rs_allocation*
746e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(PVT->isPointerType() &&
756e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines          "Invalid rs{Set,Clear}Object function prototype (pointer param)");
761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The rs object type passed to the FD
781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType RST = PVT->getPointeeType();
791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::DataType DT =
801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
816e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             && "must be RS object type");
831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
894464d825c11349068f2917f9ebee86b721423f3cStephen Hinesnamespace {
904464d825c11349068f2917f9ebee86b721423f3cStephen Hines
914464d825c11349068f2917f9ebee86b721423f3cStephen Hinesstatic void AppendToCompoundStatement(clang::ASTContext& C,
924464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                      clang::CompoundStmt *CS,
93d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines                                      std::list<clang::Stmt*> &StmtList,
944464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                      bool InsertAtEndOfBlock) {
951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Destructor code will be inserted before any return statement.
961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Any subsequent statements in the compound statement are then placed
971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // after our new code.
98e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  // TODO(srhines): This should also handle the case of goto/break/continue.
994464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1004464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
1011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned OldStmtCount = 0;
10303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
1041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    OldStmtCount++;
1051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
107d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  unsigned NewStmtCount = StmtList.size();
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
109d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  clang::Stmt **UpdatedStmtList;
110d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  UpdatedStmtList = new clang::Stmt*[OldStmtCount+NewStmtCount];
1111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned UpdatedStmtCount = 0;
1134464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool FoundReturn = false;
11403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
1151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
1164464d825c11349068f2917f9ebee86b721423f3cStephen Hines      FoundReturn = true;
1171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      break;
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
119d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
1201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1224464d825c11349068f2917f9ebee86b721423f3cStephen Hines  // Always insert before a return that we found, or if we are told
1234464d825c11349068f2917f9ebee86b721423f3cStephen Hines  // to insert at the end of the block
1244464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (FoundReturn || InsertAtEndOfBlock) {
12503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
12603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
12703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines         I != StmtList.end();
1284464d825c11349068f2917f9ebee86b721423f3cStephen Hines         I++) {
129d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *I;
1304464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
1311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Pick up anything left over after a return statement
13403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for ( ; bI != CS->body_end(); bI++) {
135d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
1361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
138d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
1391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
140d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  delete [] UpdatedStmtList;
1411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
1431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
145e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesstatic void AppendAfterStmt(clang::ASTContext& C,
146e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::CompoundStmt *CS,
147e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::Stmt *OldStmt,
148e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::Stmt *NewStmt) {
1496e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(CS && OldStmt && NewStmt);
150e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
151e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned StmtCount = 1;  // Take into account new statement
152e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
153e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    StmtCount++;
154e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
155e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
156e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
157e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
158e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned UpdatedStmtCount = 0;
159e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned Once = 0;
160e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
161e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
162e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    if (*bI == OldStmt) {
163e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      Once++;
1646e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(Once == 1);
165e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
166e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    }
167e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
168e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
169e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
170e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
171e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  delete [] UpdatedStmtList;
172e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
173e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
174e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
175e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
176e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesstatic void ReplaceInCompoundStmt(clang::ASTContext& C,
177c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::CompoundStmt *CS,
178c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::Stmt* OldStmt,
179c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::Stmt* NewStmt) {
180c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
181c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
182c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  unsigned StmtCount = 0;
183c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
184c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    StmtCount++;
185c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
186c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
187c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
188c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
189c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  unsigned UpdatedStmtCount = 0;
190c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
191c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    if (*bI == OldStmt) {
192c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
193c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    } else {
194c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *bI;
195c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    }
196c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
197c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
198c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
199c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
200c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  delete [] UpdatedStmtList;
201c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
202c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
203c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
204c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
205c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
206d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines// This class visits a compound statement and inserts the StmtList containing
2074464d825c11349068f2917f9ebee86b721423f3cStephen Hines// destructors in proper locations. This includes inserting them before any
2084464d825c11349068f2917f9ebee86b721423f3cStephen Hines// return statement in any sub-block, at the end of the logical enclosing
2094464d825c11349068f2917f9ebee86b721423f3cStephen Hines// scope (compound statement), and/or before any break/continue statement that
2104464d825c11349068f2917f9ebee86b721423f3cStephen Hines// would resume outside the declared scope. We will not handle the case for
2114464d825c11349068f2917f9ebee86b721423f3cStephen Hines// goto statements that leave a local scope.
2124464d825c11349068f2917f9ebee86b721423f3cStephen Hines// TODO(srhines): Make this work properly for break/continue.
2134464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
2144464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
2154464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::ASTContext &mC;
216d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> &mStmtList;
2174464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool mTopLevel;
2184464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
219d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList);
2204464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
2214464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitCompoundStmt(clang::CompoundStmt *CS);
2224464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
2234464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2244464d825c11349068f2917f9ebee86b721423f3cStephen HinesDestructorVisitor::DestructorVisitor(clang::ASTContext &C,
225d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines                                     std::list<clang::Stmt*> &StmtList)
2264464d825c11349068f2917f9ebee86b721423f3cStephen Hines  : mC(C),
227d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    mStmtList(StmtList),
2284464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel(true) {
2294464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2304464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2314464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2324464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
2334464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (!CS->body_empty()) {
234d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel);
2354464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel = false;
2364464d825c11349068f2917f9ebee86b721423f3cStephen Hines    VisitStmt(CS);
2374464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2384464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2394464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2404464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2414464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
2424464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
2434464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I != E;
2444464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I++) {
2454464d825c11349068f2917f9ebee86b721423f3cStephen Hines    if (clang::Stmt *Child = *I) {
2464464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
2474464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
2484464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2494464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2504464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2514464d825c11349068f2917f9ebee86b721423f3cStephen Hines
252f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesclang::Expr *ClearSingleRSObject(clang::ASTContext &C,
253f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::Expr *RefRSVar,
254f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 clang::SourceLocation Loc) {
255f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(RefRSVar);
256f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *T = RefRSVar->getType().getTypePtr();
257f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!T->isArrayType() &&
258f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should not be destroying arrays with this function");
259f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
260f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
261f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((ClearObjectFD != NULL) &&
262f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "rsClearObject doesn't cover all RS object types");
263f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
264f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
265f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::QualType ClearObjectFDArgType =
266f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
267f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
268f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Example destructor for "rs_font localFont;"
269f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //
270f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // (CallExpr 'void'
271f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
272f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
273f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
274f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
275f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
276f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Get address of targeted RS object
277f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *AddrRefRSVar =
278f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
279f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  clang::UO_AddrOf,
280f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  ClearObjectFDArgType,
281f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                  Loc);
282f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
283f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSClearObjectFD =
284f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclRefExpr::Create(C,
285f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 NULL,
286f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getQualifierRange(),
287f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD,
288f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFD->getLocation(),
289f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 ClearObjectFDType);
290f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
291f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RSClearObjectFP =
292f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::ImplicitCastExpr::Create(C,
293f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      C.getPointerType(ClearObjectFDType),
294f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::CK_FunctionToPointerDecay,
295f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      RefRSClearObjectFD,
296f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      NULL,
297f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                      clang::VK_RValue);
29803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
299f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CallExpr *RSClearObjectCall =
300f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CallExpr(C,
301f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             RSClearObjectFP,
302f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             &AddrRefRSVar,
303f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             1,
304f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             ClearObjectFD->getCallResultType(),
305f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             Loc);
306f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
307f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSClearObjectCall;
308f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
309f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
310f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic int ArrayDim(const clang::Type *T) {
31103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
31203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
31303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
31403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
31503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
31603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
3179d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
31803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
31903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
320f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
321f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
322f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
323f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
324f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceRange Range,
325f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc);
326f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
327f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearArrayRSObject(
328f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
329f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
330f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSArr,
331f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceRange Range,
332f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
333f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
334f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(BaseType->isArrayType());
335f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
336f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  int NumArrayElements = ArrayDim(BaseType);
337f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Actually extract out the base RS object type for use later
338f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  BaseType = BaseType->getArrayElementTypeNoTypeQual();
33903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
34103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int StmtCtr = 0;
34203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
34403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return NULL;
34503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
34603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
34803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
34903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // (CompoundStmt
35003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (DeclStmt "int rsIntIter")
35103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (ForStmt
35203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '='
35303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
35403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 0))
35503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '<'
35603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
35703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 10)
35803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     NULL << CondVar >>
35903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (UnaryOperator 'int' postfix '++'
36003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
36103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (CallExpr 'void'
36203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
36303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
36403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (UnaryOperator 'rs_font *' prefix '&'
36503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (ArraySubscriptExpr 'rs_font':'rs_font'
36603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
36703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
36803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (DeclRefExpr 'int' Var='rsIntIter')))))))
36903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
37003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
37103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
37203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
37303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
374f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                             DC,
37503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
37603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &II,
37703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
37803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
37903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None,
38003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
38103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
38203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
38403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
38503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
38703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
38803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
38903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
39003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Init -> "rsIntIter = 0"
39103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
39203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
39303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
39403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
39503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
39603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
39703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 C.IntTy);
39803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
39903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
40003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
40103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Init =
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
40403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Int0,
40503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_Assign,
40603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
40703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
40803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
41003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
41103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
41203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
41303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
41403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
41503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
41603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
41703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
41803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
41903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
42003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
42103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
42303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
42403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
42503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
42603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
42703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
42803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
42903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
430f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtr =
43103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
432f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          C.getPointerType(BaseType->getCanonicalTypeInternal()),
43303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
434f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          RefRSArr,
43503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          NULL,
43603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
43703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
438f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Expr *RefRSArrPtrSubscript =
439f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
44003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       RefrsIntIter,
441f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       BaseType->getCanonicalTypeInternal(),
442f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                       Loc);
44303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
444f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
445f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
446f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
447f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt *RSClearObjectCall = NULL;
448f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (BaseType->isArrayType()) {
449f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
450f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc);
451f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
452f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall =
453f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc);
454f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
455f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
456f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
45703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
45803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
45903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
46003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
46103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
46203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            NULL,  // no condVar
46303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
46403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
46503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
46603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
46703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
46803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
46903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
4706e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(StmtCtr == 2);
47103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
47203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CompoundStmt *CS =
47303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
47403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
47503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  return CS;
47603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
47703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
478f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic unsigned CountRSObjectTypesInStruct(const clang::Type *T) {
479f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(T);
480f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned RSObjectCount = 0;
481f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
482f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
483f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return CountRSObjectTypesInStruct(T->getArrayElementTypeNoTypeQual());
484f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
485f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
486f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
487f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
488f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT != RSExportPrimitiveType::DataTypeUnknown) {
489f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
490f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
491f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
492f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (!T->isStructureType()) {
493f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return 0;
494f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
495f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
496f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
497f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
498f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
499f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
500f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
501f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
502f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::FieldDecl *FD = *FI;
503f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
504f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    if (CountRSObjectTypesInStruct(FT)) {
505f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // Sub-structs should only count once (as should arrays, etc.)
506f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSObjectCount++;
507f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
508f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
509f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
510f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return RSObjectCount;
511f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
512f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
513f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hinesstatic clang::Stmt *ClearStructRSObject(
514f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::ASTContext &C,
515f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::DeclContext *DC,
516f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::Expr *RefRSStruct,
517f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceRange Range,
518f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::SourceLocation Loc) {
519f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
520f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
521f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(!BaseType->isArrayType());
522f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
523f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
524f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(BaseType);
525f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
526f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Structs should show up as unknown primitive types
527f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(DT == RSExportPrimitiveType::DataTypeUnknown);
528f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
529f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned FieldsToDestroy = CountRSObjectTypesInStruct(BaseType);
530f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
531f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  unsigned StmtCount = 0;
532f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
533f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
534f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Populate StmtArray by creating a destructor for each RS object field
535f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
536f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RD = RD->getDefinition();
537f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
538f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines         FE = RD->field_end();
539f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI != FE;
540f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines       FI++) {
541f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // We just look through all field declarations to see if we find a
542f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // declaration for an RS object type (or an array of one).
543f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    bool IsArrayType = false;
544f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    clang::FieldDecl *FD = *FI;
545f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
546f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    const clang::Type *OrigType = FT;
547f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    while (FT && FT->isArrayType()) {
548f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      FT = FT->getArrayElementTypeNoTypeQual();
549f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      IsArrayType = true;
550f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
551f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
552f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
553f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
554f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
555f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
556f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
557f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
558f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
559f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
560f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    Range,
561f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
562f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
563f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
564f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
565f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    OrigType->getCanonicalTypeInternal());
566f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
567f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      slangAssert(StmtCount < FieldsToDestroy);
568f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
569f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
570f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
571f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
572f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
573f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Range,
574f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
575f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
576f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearSingleRSObject(C,
577f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
578f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
579f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
580f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    } else if (FT->isStructureType() && CountRSObjectTypesInStruct(FT)) {
581f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // In this case, we have a nested struct. We may not end up filling all
582f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // of the spaces in StmtArray (sub-structs should handle themselves
583f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      // with separate compound statements).
584f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::DeclAccessPair FoundDecl =
585f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::DeclAccessPair::make(FD, clang::AS_none);
586f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      clang::MemberExpr *RSObjectMember =
587f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines          clang::MemberExpr::Create(C,
588f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    RefRSStruct,
589f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    false,
590f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
591f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    Range,
592f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FD,
593f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    FoundDecl,
594f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    clang::DeclarationNameInfo(),
595f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    NULL,
596f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                    OrigType->getCanonicalTypeInternal());
597f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
598f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      if (IsArrayType) {
599f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearArrayRSObject(C,
600f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    DC,
601f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    RSObjectMember,
602f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Range,
603f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                    Loc);
604f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      } else {
605f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines        StmtArray[StmtCount++] = ClearStructRSObject(C,
606f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     DC,
607f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     RSObjectMember,
608f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Range,
609f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                                     Loc);
610f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      }
611f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    }
612f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
613f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
614f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(StmtCount > 0);
615f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::CompoundStmt *CS =
616f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
617f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
618f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  delete [] StmtArray;
619f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
620f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return CS;
621f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines}
622f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
6234464d825c11349068f2917f9ebee86b721423f3cStephen Hines}  // namespace
6244464d825c11349068f2917f9ebee86b721423f3cStephen Hines
625c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hinesvoid RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
626c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    clang::BinaryOperator *AS) {
627c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
628c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
629c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
630f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(
631f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      QT.getTypePtr());
6326e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
6336e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
634c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::ASTContext &C = SetObjectFD->getASTContext();
635c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
636c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
637c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
638c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
639c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
640c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
641c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::SourceLocation Loc = SetObjectFD->getLocation();
642c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
643c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
644c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 NULL,
645c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD->getQualifierRange(),
646c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
647c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
648c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFDType);
649c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
650c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
651c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
652c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
653c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
654c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
655c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      NULL,
656c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
657c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
658c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *ArgList[2];
659c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(AS->getLHS(),
660c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           clang::UO_AddrOf,
661c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           SetObjectFDArgType[0],
662c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           Loc);
663c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  ArgList[1] = AS->getRHS();
664c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
665c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CallExpr *RSSetObjectCall =
666c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      new(C) clang::CallExpr(C,
667c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             RSSetObjectFP,
668c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             ArgList,
669c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             2,
670c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             SetObjectFD->getCallResultType(),
671c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             Loc);
672c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
673e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ReplaceInCompoundStmt(C, mCS, AS, RSSetObjectCall);
674e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
675e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
676e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
677e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
678e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesvoid RSObjectRefCount::Scope::AppendRSObjectInit(
679e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::VarDecl *VD,
680e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::DeclStmt *DS,
681e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    RSExportPrimitiveType::DataType DT,
682e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::Expr *InitExpr) {
6836e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD);
684e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
685e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!InitExpr) {
686e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return;
687e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
688e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
689f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
690f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    // TODO(srhines): Skip struct initialization right now
691f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return;
692f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
693f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
694f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
6956e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
6966e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
697e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::ASTContext &C = SetObjectFD->getASTContext();
698e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
699e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
700e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDArgType[2];
701e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
702e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
703e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
704e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::SourceLocation Loc = SetObjectFD->getLocation();
705e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RefRSSetObjectFD =
706e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
707e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 NULL,
708e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD->getQualifierRange(),
709e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD,
710e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
711e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFDType);
712e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
713e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RSSetObjectFP =
714e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::ImplicitCastExpr::Create(C,
715e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      C.getPointerType(SetObjectFDType),
716e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::CK_FunctionToPointerDecay,
717e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      RefRSSetObjectFD,
718e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      NULL,
719e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::VK_RValue);
720e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
721e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
722e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::DeclRefExpr *RefRSVar =
723e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
724e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 NULL,
725e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD->getQualifierRange(),
726e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD,
727e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
728e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 T->getCanonicalTypeInternal());
729e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
730e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ArgList[2];
731e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
732e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           clang::UO_AddrOf,
733e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           SetObjectFDArgType[0],
734e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           Loc);
735e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[1] = InitExpr;
736e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
737e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CallExpr *RSSetObjectCall =
738e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      new(C) clang::CallExpr(C,
739e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             RSSetObjectFP,
740e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             ArgList,
741e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             2,
742e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             SetObjectFD->getCallResultType(),
743e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             Loc);
744e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
745e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  AppendAfterStmt(C, mCS, DS, RSSetObjectCall);
746c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
747c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
748c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
749c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
7501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
751d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> RSClearObjectCalls;
7521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
7531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
7541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
7551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
756a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    clang::Stmt *S = ClearRSObject(*I);
757a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    if (S) {
758a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines      RSClearObjectCalls.push_back(S);
7591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
7601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
7611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
7624464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
7634464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DV.Visit(mCS);
7641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
7651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
7661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
7671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
768d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
769f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert(VD);
7701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
771f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::DeclContext *DC = VD->getDeclContext();
772f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  clang::SourceRange Range = VD->getQualifierRange();
7731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
7741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
77503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
7761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
7771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
7781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
7791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
780f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines                                 Range,
7811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
7821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
78303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 T->getCanonicalTypeInternal());
7841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
785f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (T->isArrayType()) {
786f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return ClearArrayRSObject(C, DC, RefRSVar, Range, Loc);
787f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
7881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
789f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  RSExportPrimitiveType::DataType DT =
790f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
7911bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
792f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeUnknown ||
793f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DT == RSExportPrimitiveType::DataTypeIsStruct) {
794f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return ClearStructRSObject(C, DC, RefRSVar, Range, Loc);
795f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
7961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
797f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
798f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines              "Should be RS object");
7991bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
800f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  return ClearSingleRSObject(C, RefRSVar, Loc);
8011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
8021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
803e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
804e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          RSExportPrimitiveType::DataType *DT,
805e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          clang::Expr **InitExpr) {
8066e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD && DT && InitExpr);
8074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
8082d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
8092d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
8102d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
8112d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
8122d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
8132d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
814f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsStructWithRSObject = false;
815e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
8164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
817e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
818feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
819feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      *DT = RSExportPrimitiveType::DataTypeIsStruct;
820f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines      DataTypeIsStructWithRSObject = true;
821feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    } else {
822feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      return false;
823feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    }
8242d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
8254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
826f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  bool DataTypeIsRSObject = false;
827f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (DataTypeIsStructWithRSObject) {
828f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = true;
829f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  } else {
830f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
831f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
832e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *InitExpr = VD->getInit();
833e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
834e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!DataTypeIsRSObject && *InitExpr) {
835e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    // If we already have an initializer for a matrix type, we are done.
836e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return DataTypeIsRSObject;
8374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
8384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
839e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ZeroInitializer =
840e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      CreateZeroInitializerForRSSpecificType(*DT,
841e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getASTContext(),
842e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getLocation());
843e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
844e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (ZeroInitializer) {
845e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    ZeroInitializer->setType(T->getCanonicalTypeInternal());
846e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    VD->setInit(ZeroInitializer);
847e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
848e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
849e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return DataTypeIsRSObject;
8504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
8534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
8544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
8554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
8564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
8574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
858feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    case RSExportPrimitiveType::DataTypeIsStruct:
8594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
8604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
8614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
8624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
8634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
8644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
8654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
8664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
8674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
8684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
8694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
8704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
8714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
8724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
8734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
8744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
8754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
8764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
8774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
8784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
8794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
8804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
8814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
882e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
8834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
8844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
8854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
8864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
8874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
8884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
8894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
8904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
8914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
8924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
8934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
8944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
8954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
8964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
8974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
8984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
8994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
9004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
9014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
9024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
9034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
9044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
9054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
9064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
9074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
9084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
9094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
9104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
9114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
9124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
9134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
9144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
9154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
9164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
9174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
918e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
9194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
9204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
9214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
9224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
9234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
924e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
9254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
9264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
9274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
9284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
9294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
9304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
9314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
9324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
9334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
9344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
9354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
9364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
9374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
9384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
9394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
9404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
9414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
9424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
9434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
9446e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(false && "Not RS object type!");
9454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
9464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
9474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
9484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
9494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
9504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
9514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
9524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
9534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
9544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
9554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
9564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
9574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
9584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
959e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      RSExportPrimitiveType::DataType DT =
960e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines          RSExportPrimitiveType::DataTypeUnknown;
961e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::Expr *InitExpr = NULL;
962e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      if (InitializeRSObject(VD, &DT, &InitExpr)) {
9634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
964e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines        getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
965e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      }
9664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
9674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
9684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
9694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
9704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
9714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
9724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
9734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
9744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
9754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
9764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
9774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
9784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
9794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
9806e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
9811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
9824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
9834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
9844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
9854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
9864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
9874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
9884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
989c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
990c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
991f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  if (RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
992c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    getCurrentScope()->ReplaceRSObjectAssignment(AS);
993c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
994c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
9954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
9964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
9974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
9984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
9994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
10004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
10014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
10024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
10034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
10044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
10054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
10064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
10074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
10084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
1009e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
1010