slang_rs_object_ref_count.cpp revision 6e6578a360497f78a181e63d7783422a9c9bfb15
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
331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::FunctionDecl *RSObjectRefCount::Scope::
341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                  RSExportPrimitiveType::FirstRSObjectType + 1];
361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::FunctionDecl *RSObjectRefCount::Scope::
371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                    RSExportPrimitiveType::FirstRSObjectType + 1];
391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::GetRSRefCountingFunctions(
411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    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
25303981a308201b9123512297c8b9562a0f29bdf31Stephen Hinesstatic int ArrayDim(clang::VarDecl *VD) {
25403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
25503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
25603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
25703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
25803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
25903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
26003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
26103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
2629d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
26303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
26403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
26503981a308201b9123512297c8b9562a0f29bdf31Stephen Hinesstatic clang::Stmt *ClearArrayRSObject(clang::VarDecl *VD,
26603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    const clang::Type *T,
26703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    clang::FunctionDecl *ClearObjectFD) {
26803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ASTContext &C = VD->getASTContext();
26903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::SourceRange Range = VD->getQualifierRange();
27003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::SourceLocation Loc = Range.getEnd();
27103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
27203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
27303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int StmtCtr = 0;
27403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
27503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int NumArrayElements = ArrayDim(VD);
27603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
27703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return NULL;
27803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
27903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
28003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
28103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
28203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // (CompoundStmt
28303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (DeclStmt "int rsIntIter")
28403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (ForStmt
28503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '='
28603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
28703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 0))
28803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '<'
28903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
29003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 10)
29103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     NULL << CondVar >>
29203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (UnaryOperator 'int' postfix '++'
29303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
29403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (CallExpr 'void'
29503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
29603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
29703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (UnaryOperator 'rs_font *' prefix '&'
29803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (ArraySubscriptExpr 'rs_font':'rs_font'
29903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
30003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
30103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (DeclRefExpr 'int' Var='rsIntIter')))))))
30203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
30303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
30403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
30503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
30603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
30703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             VD->getDeclContext(),
30803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
30903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &II,
31003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
31103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
31203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None,
31303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
31403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
31503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
31603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
31703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
31803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
31903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
32003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
32103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
32203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
32303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Init -> "rsIntIter = 0"
32403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
32503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
32603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
32703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
32803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
32903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
33003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 C.IntTy);
33103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
33203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
33303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
33403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
33503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Init =
33603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
33703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Int0,
33803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_Assign,
33903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
34003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
34103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
34303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
34403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
34503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
34703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
34803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
34903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
35003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
35103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
35203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
35303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
35403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
35503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
35603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
35703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
35803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
35903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
36003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
36103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
36203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
36303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::QualType ClearObjectFDArgType =
36403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
36503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
36603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::Type *VT = RSExportType::GetTypeOfDecl(VD);
36703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefRSVar =
36803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
36903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
37003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
37103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 VD,
37203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
37303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 VT->getCanonicalTypeInternal());
37403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
37503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RefRSVarPtr =
37603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
37703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          C.getPointerType(T->getCanonicalTypeInternal()),
37803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
37903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          RefRSVar,
38003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          NULL,
38103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
38203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RefRSVarPtrSubscript =
38403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ArraySubscriptExpr(RefRSVarPtr,
38503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       RefrsIntIter,
38603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       T->getCanonicalTypeInternal(),
38703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       VD->getLocation());
38803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *AddrRefRSVarPtrSubscript =
39003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefRSVarPtrSubscript,
39103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_AddrOf,
39203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  ClearObjectFDArgType,
39303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  VD->getLocation());
39403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
39503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RefRSClearObjectFD =
39603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
39703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
39803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
39903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 ClearObjectFD,
40003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
40103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 ClearObjectFDType);
40203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RSClearObjectFP =
40403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
40503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      C.getPointerType(ClearObjectFDType),
40603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      clang::CK_FunctionToPointerDecay,
40703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      RefRSClearObjectFD,
40803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      NULL,
40903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      clang::VK_RValue);
41003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
41103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CallExpr *RSClearObjectCall =
41203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CallExpr(C,
41303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             RSClearObjectFP,
41403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &AddrRefRSVarPtrSubscript,
41503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             1,
41603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             ClearObjectFD->getCallResultType(),
41703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc);
41803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
41903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
42003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
42103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
42303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            NULL,  // no condVar
42403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
42503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
42603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
42703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
42803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
42903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
4316e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(StmtCtr == 2);
43203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CompoundStmt *CS =
43403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
43503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  return CS;
43703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
43803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
4394464d825c11349068f2917f9ebee86b721423f3cStephen Hines}  // namespace
4404464d825c11349068f2917f9ebee86b721423f3cStephen Hines
441c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hinesvoid RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
442c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    clang::BinaryOperator *AS) {
443c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
444c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
445c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  RSExportPrimitiveType::DataType DT =
446c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(QT.getTypePtr());
447c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
448c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::FunctionDecl *SetObjectFD =
449c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      RSSetObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
4506e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
4516e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
452c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::ASTContext &C = SetObjectFD->getASTContext();
453c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
454c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
455c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
456c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
457c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
458c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
459c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::SourceLocation Loc = SetObjectFD->getLocation();
460c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
461c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
462c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 NULL,
463c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD->getQualifierRange(),
464c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
465c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
466c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFDType);
467c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
468c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
469c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
470c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
471c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
472c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
473c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      NULL,
474c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
475c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
476c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *ArgList[2];
477c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(AS->getLHS(),
478c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           clang::UO_AddrOf,
479c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           SetObjectFDArgType[0],
480c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           Loc);
481c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  ArgList[1] = AS->getRHS();
482c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
483c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CallExpr *RSSetObjectCall =
484c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      new(C) clang::CallExpr(C,
485c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             RSSetObjectFP,
486c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             ArgList,
487c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             2,
488c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             SetObjectFD->getCallResultType(),
489c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             Loc);
490c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
491e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ReplaceInCompoundStmt(C, mCS, AS, RSSetObjectCall);
492e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
493e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
494e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
495e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
496e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesvoid RSObjectRefCount::Scope::AppendRSObjectInit(
497e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::VarDecl *VD,
498e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::DeclStmt *DS,
499e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    RSExportPrimitiveType::DataType DT,
500e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::Expr *InitExpr) {
5016e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD);
502e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
503e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!InitExpr) {
504e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return;
505e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
506e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
507e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::FunctionDecl *SetObjectFD =
508e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      RSSetObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
5096e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((SetObjectFD != NULL) &&
5106e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsSetObject doesn't cover all RS object types");
511e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::ASTContext &C = SetObjectFD->getASTContext();
512e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
513e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
514e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDArgType[2];
515e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
516e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
517e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
518e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::SourceLocation Loc = SetObjectFD->getLocation();
519e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RefRSSetObjectFD =
520e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
521e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 NULL,
522e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD->getQualifierRange(),
523e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD,
524e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
525e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFDType);
526e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
527e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RSSetObjectFP =
528e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::ImplicitCastExpr::Create(C,
529e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      C.getPointerType(SetObjectFDType),
530e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::CK_FunctionToPointerDecay,
531e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      RefRSSetObjectFD,
532e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      NULL,
533e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::VK_RValue);
534e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
535e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
536e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::DeclRefExpr *RefRSVar =
537e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
538e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 NULL,
539e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD->getQualifierRange(),
540e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD,
541e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
542e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 T->getCanonicalTypeInternal());
543e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
544e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ArgList[2];
545e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
546e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           clang::UO_AddrOf,
547e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           SetObjectFDArgType[0],
548e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           Loc);
549e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[1] = InitExpr;
550e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
551e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CallExpr *RSSetObjectCall =
552e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      new(C) clang::CallExpr(C,
553e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             RSSetObjectFP,
554e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             ArgList,
555e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             2,
556e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             SetObjectFD->getCallResultType(),
557e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             Loc);
558e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
559e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  AppendAfterStmt(C, mCS, DS, RSSetObjectCall);
560c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
561c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
562c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
563c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
5641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
565d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> RSClearObjectCalls;
5661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
5671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
5681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
5691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
570a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    clang::Stmt *S = ClearRSObject(*I);
571a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    if (S) {
572a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines      RSClearObjectCalls.push_back(S);
5731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
5741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
5751bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
5764464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
5774464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DV.Visit(mCS);
5781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
5791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
5801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
5811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
582d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
58303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  bool IsArrayType = false;
5841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
5851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
5861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
58703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
58803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Loop through array types to get to base type
58903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  while (T && T->isArrayType()) {
59003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    T = T->getArrayElementTypeNoTypeQual();
59103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    IsArrayType = true;
59203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
59303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
5941bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  RSExportPrimitiveType::DataType DT =
5951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
5961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
5976e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
5986e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "Should be RS object");
5991bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6001bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Find the rsClearObject() for VD of RS object type DT
6011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::FunctionDecl *ClearObjectFD =
6021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
6036e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((ClearObjectFD != NULL) &&
6046e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "rsClearObject doesn't cover all RS object types");
6051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
60603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (IsArrayType) {
60703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return ClearArrayRSObject(VD, T, ClearObjectFD);
60803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
60903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
6101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
6111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDArgType =
6121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
6131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
61403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor for "rs_font localFont;"
61503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
6161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // (CallExpr 'void'
6171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
6181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
6191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
62003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
6211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6221bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
6231bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
6241bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
6251bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
6261bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD->getQualifierRange(),
6271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
6281bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
62903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 T->getCanonicalTypeInternal());
6301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Get address of RSObject in VD
6321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *AddrRefRSVar =
633e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
634e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  clang::UO_AddrOf,
635e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  ClearObjectFDArgType,
636e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  Loc);
6371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RefRSClearObjectFD =
6391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
6401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
6411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getQualifierRange(),
6421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD,
6431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getLocation(),
64403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 ClearObjectFDType);
6451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RSClearObjectFP =
6471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::ImplicitCastExpr::Create(C,
6481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      C.getPointerType(ClearObjectFDType),
6491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::CK_FunctionToPointerDecay,
6501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      RefRSClearObjectFD,
6511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      NULL,
6521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::VK_RValue);
6531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CallExpr *RSClearObjectCall =
655e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::CallExpr(C,
656e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             RSClearObjectFP,
657e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             &AddrRefRSVar,
658e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             1,
659e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             ClearObjectFD->getCallResultType(),
660e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             clang::SourceLocation());
6611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return RSClearObjectCall;
6631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
6641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
665e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
666e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          RSExportPrimitiveType::DataType *DT,
667e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          clang::Expr **InitExpr) {
6686e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert(VD && DT && InitExpr);
6694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
6702d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
6712d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
6722d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
6732d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
6742d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
6752d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
676e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
6774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
678e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
679feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
680feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      *DT = RSExportPrimitiveType::DataTypeIsStruct;
681feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    } else {
682feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines      return false;
683feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    }
6842d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
6854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
686e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  bool DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
687e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *InitExpr = VD->getInit();
688e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
689e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!DataTypeIsRSObject && *InitExpr) {
690e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    // If we already have an initializer for a matrix type, we are done.
691e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return DataTypeIsRSObject;
6924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
6934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
694e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ZeroInitializer =
695e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      CreateZeroInitializerForRSSpecificType(*DT,
696e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getASTContext(),
697e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getLocation());
698e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
699e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (ZeroInitializer) {
700e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    ZeroInitializer->setType(T->getCanonicalTypeInternal());
701e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    VD->setInit(ZeroInitializer);
702e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
703e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
704e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return DataTypeIsRSObject;
7054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
7064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
7074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
7084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
7094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
7104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
7114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
7124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
713feaca06fcb0772e9e972a0d61b17259fc5124d50Stephen Hines    case RSExportPrimitiveType::DataTypeIsStruct:
7144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
7154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
7164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
7174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
7184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
7194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
7204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
7214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
7224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
7234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
7244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
7254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
7264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
7274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
7284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
7294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
7304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
7314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
7324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
7334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
7344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
7354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
7364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
737e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
7384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
7394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
7404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
7414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
7424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
7434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
7444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
7454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
7464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
7474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
7484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
7494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
7504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
7514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
7524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
7534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
7544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
7554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
7564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
7574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
7584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
7594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
7604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
7614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
7624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
7634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
7644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
7654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
7664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
7674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
7684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
7694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
7704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
7714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
7724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
773e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
7744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
7754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
7764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
7774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
7784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
779e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
7804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
7814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
7824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
7834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
7844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
7854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
7864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
7874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
7884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
7894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
7904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
7914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
7924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
7934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
7944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
7954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
7964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
7974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
7984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
7996e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines      slangAssert(false && "Not RS object type!");
8004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
8014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
8024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
8034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
8054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
8084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
8094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
8104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
8114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
8124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
8134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
814e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      RSExportPrimitiveType::DataType DT =
815e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines          RSExportPrimitiveType::DataTypeUnknown;
816e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::Expr *InitExpr = NULL;
817e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      if (InitializeRSObject(VD, &DT, &InitExpr)) {
8184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
819e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines        getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
820e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      }
8214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
8224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
8234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
8244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
8274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
8284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
8294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
8304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
8314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
8334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
8356e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
8361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
8374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
8384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
8394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
8404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
8414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
844c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
845c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  RSExportPrimitiveType::DataType DT =
846c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(QT.getTypePtr());
847c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
848c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  if (RSExportPrimitiveType::IsRSObjectType(DT)) {
849c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    getCurrentScope()->ReplaceRSObjectAssignment(AS);
850c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
851c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
8524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
8534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
8564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
8574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
8584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
8594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
8604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
8614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
8624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
8634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
8644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
866e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
867