slang_rs_object_ref_count.cpp revision 4464d825c11349068f2917f9ebee86b721423f3c
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
274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs.h"
284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
30e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::FunctionDecl *RSObjectRefCount::Scope::
331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                  RSExportPrimitiveType::FirstRSObjectType + 1];
351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::FunctionDecl *RSObjectRefCount::Scope::
361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                    RSExportPrimitiveType::FirstRSObjectType + 1];
381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::GetRSRefCountingFunctions(
401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    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") {
601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        assert((FD->getNumParams() == 2) &&
611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines               "Invalid rsSetObject function prototype (# params)");
621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        assert((FD->getNumParams() == 1) &&
651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen 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*
741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      assert(PVT->isPointerType() &&
751bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen 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());
811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      assert(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,
934464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                      std::list<clang::Expr*> &ExprList,
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();
1014464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::CompoundStmt::body_iterator bE = CS->body_end();
1021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned OldStmtCount = 0;
1044464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (bI = CS->body_begin(); bI != bE; bI++) {
1051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    OldStmtCount++;
1061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1071bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned NewExprCount = ExprList.size();
1091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Stmt **StmtList;
1111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  StmtList = new clang::Stmt*[OldStmtCount+NewExprCount];
1121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned UpdatedStmtCount = 0;
1144464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool FoundReturn = false;
1154464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (bI = CS->body_begin(); bI != bE; bI++) {
1161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
1174464d825c11349068f2917f9ebee86b721423f3cStephen Hines      FoundReturn = true;
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      break;
1191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
1201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    StmtList[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) {
1264464d825c11349068f2917f9ebee86b721423f3cStephen Hines    std::list<clang::Expr*>::const_iterator E = ExprList.end();
1274464d825c11349068f2917f9ebee86b721423f3cStephen Hines    for (std::list<clang::Expr*>::const_iterator I = ExprList.begin(),
1284464d825c11349068f2917f9ebee86b721423f3cStephen Hines            E = ExprList.end();
1294464d825c11349068f2917f9ebee86b721423f3cStephen Hines         I != E;
1304464d825c11349068f2917f9ebee86b721423f3cStephen Hines         I++) {
1314464d825c11349068f2917f9ebee86b721423f3cStephen Hines      StmtList[UpdatedStmtCount++] = *I;
1324464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
1331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Pick up anything left over after a return statement
1361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for ( ; bI != bE; bI++) {
1371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    StmtList[UpdatedStmtCount++] = *bI;
1381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1404464d825c11349068f2917f9ebee86b721423f3cStephen Hines  CS->setStmts(C, StmtList, UpdatedStmtCount);
1411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  delete [] StmtList;
1431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
1451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1474464d825c11349068f2917f9ebee86b721423f3cStephen Hines// This class visits a compound statement and inserts the ExprList containing
1484464d825c11349068f2917f9ebee86b721423f3cStephen Hines// destructors in proper locations. This includes inserting them before any
1494464d825c11349068f2917f9ebee86b721423f3cStephen Hines// return statement in any sub-block, at the end of the logical enclosing
1504464d825c11349068f2917f9ebee86b721423f3cStephen Hines// scope (compound statement), and/or before any break/continue statement that
1514464d825c11349068f2917f9ebee86b721423f3cStephen Hines// would resume outside the declared scope. We will not handle the case for
1524464d825c11349068f2917f9ebee86b721423f3cStephen Hines// goto statements that leave a local scope.
1534464d825c11349068f2917f9ebee86b721423f3cStephen Hines// TODO(srhines): Make this work properly for break/continue.
1544464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
1554464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
1564464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::ASTContext &mC;
1574464d825c11349068f2917f9ebee86b721423f3cStephen Hines  std::list<clang::Expr*> &mExprList;
1584464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool mTopLevel;
1594464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
1604464d825c11349068f2917f9ebee86b721423f3cStephen Hines  DestructorVisitor(clang::ASTContext &C, std::list<clang::Expr*> &ExprList);
1614464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
1624464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitCompoundStmt(clang::CompoundStmt *CS);
1634464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
1644464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1654464d825c11349068f2917f9ebee86b721423f3cStephen HinesDestructorVisitor::DestructorVisitor(clang::ASTContext &C,
1664464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                     std::list<clang::Expr*> &ExprList)
1674464d825c11349068f2917f9ebee86b721423f3cStephen Hines  : mC(C),
1684464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mExprList(ExprList),
1694464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel(true) {
1704464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
1714464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
1724464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1734464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
1744464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (!CS->body_empty()) {
1754464d825c11349068f2917f9ebee86b721423f3cStephen Hines    AppendToCompoundStatement(mC, CS, mExprList, mTopLevel);
1764464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel = false;
1774464d825c11349068f2917f9ebee86b721423f3cStephen Hines    VisitStmt(CS);
1784464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
1794464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
1804464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
1814464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1824464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
1834464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1844464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I != E;
1854464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I++) {
1864464d825c11349068f2917f9ebee86b721423f3cStephen Hines    if (clang::Stmt *Child = *I) {
1874464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
1884464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
1894464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
1904464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
1914464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
1924464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1934464d825c11349068f2917f9ebee86b721423f3cStephen Hines}  // namespace
1944464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
1961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  std::list<clang::Expr*> RSClearObjectCalls;
1971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1981bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
1991bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
2001bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
2011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    clang::Expr *E = ClearRSObject(*I);
2021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if (E) {
2031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectCalls.push_back(E);
2041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
2051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
2061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
2074464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
2084464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DV.Visit(mCS);
2091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
2101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
2111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
2121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::Expr *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
2141bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
2151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
2161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
2171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  RSExportPrimitiveType::DataType DT =
2181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
2191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
2211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "Should be RS object");
2221bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2231bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Find the rsClearObject() for VD of RS object type DT
2241bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::FunctionDecl *ClearObjectFD =
2251bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
2261bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((ClearObjectFD != NULL) &&
2271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "rsClearObject doesn't cover all RS object types");
2281bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2291bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
2301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDArgType =
2311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
2321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // We generate a call to rsClearObject passing &VD as the parameter
2341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // (CallExpr 'void'
2351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
2361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
2371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
2381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='[var name]')))
2391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
2411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
2421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
2431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
2441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD->getQualifierRange(),
2451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
2461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
2471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 T->getCanonicalTypeInternal(),
2481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL);
2491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Get address of RSObject in VD
2511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *AddrRefRSVar =
252e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
253e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  clang::UO_AddrOf,
254e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  ClearObjectFDArgType,
255e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  Loc);
2561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RefRSClearObjectFD =
2581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
2591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
2601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getQualifierRange(),
2611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD,
2621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getLocation(),
2631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFDType,
2641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL);
2651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RSClearObjectFP =
2671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::ImplicitCastExpr::Create(C,
2681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      C.getPointerType(ClearObjectFDType),
2691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::CK_FunctionToPointerDecay,
2701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      RefRSClearObjectFD,
2711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      NULL,
2721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::VK_RValue);
2731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CallExpr *RSClearObjectCall =
275e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::CallExpr(C,
276e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             RSClearObjectFP,
277e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             &AddrRefRSVar,
278e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             1,
279e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             ClearObjectFD->getCallResultType(),
280e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             clang::SourceLocation());
2811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return RSClearObjectCall;
2831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
2841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) {
2864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
2874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  RSExportPrimitiveType::DataType DT =
2884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
2894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeUnknown)
2914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    return false;
2924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (VD->hasInit()) {
294e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    // TODO(srhines): Update the reference count of RS object in initializer.
2954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // This can potentially be done as part of the assignment pass.
2964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  } else {
2974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Expr *ZeroInitializer =
2984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        CreateZeroInitializerForRSSpecificType(DT,
2994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               VD->getASTContext(),
3004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               VD->getLocation());
3014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (ZeroInitializer) {
3034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      ZeroInitializer->setType(T->getCanonicalTypeInternal());
3044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      VD->setInit(ZeroInitializer);
3054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
3074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return RSExportPrimitiveType::IsRSObjectType(DT);
3094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
3104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
3124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
3134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
3144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
3154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
3164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
3174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
3184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
3194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
3204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
3214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
3224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
3234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
3244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
3254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
3264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
3274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
3284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
3294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
3304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
3314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
3324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
3334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
3344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
3354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
3364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
3374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
3384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
3394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
340e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
3414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
3424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
3444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
3454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
3464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
3474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
3484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
3494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
3504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
3514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
3524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
3534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
3544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
3554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
3564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
3574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
3584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
3594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
3604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
3614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
3624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
3644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
3654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
3664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
3674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
3684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
3694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
3704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
3724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
3734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
3744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
3754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
376e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
3774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
3784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
3794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
3804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
3814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
382e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
3834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
3844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
3864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
3874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
3884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
3894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
3904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
3914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
3924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
3934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
3944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
3954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
3964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
3974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
3984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
3994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
4004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
4014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
4024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      assert(false && "Not RS object type!");
4034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
4044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
4054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
4064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
4084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
4094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
4114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
4124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
4134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
4144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
4154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
4164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
4174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (InitializeRSObject(VD))
4184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
4194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
4204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
4214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
4224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
4234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
4254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
4264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
4274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
4284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
4294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
4314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
433e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    // TODO(srhines): Update reference count of the RS object refenced by
434e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    //                getCurrentScope().
4354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    assert((getCurrentScope() == S) && "Corrupted scope stack!");
4361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
4374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
4384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
4394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
4404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
4414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
4424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
444e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  // TODO(srhines): Update reference count
4454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
4464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
4474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
4494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
4504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
4514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
4524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
4534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
4544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
4554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
4564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
4574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
4584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
459e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
460