/*
 * Copyright 2010, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "slang_rs_object_ref_count.h"

#include <list>

#include "clang/AST/DeclGroup.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"

#include "slang_assert.h"
#include "slang.h"
#include "slang_rs_ast_replace.h"
#include "slang_rs_export_type.h"

namespace slang {

/* Even though those two arrays are of size DataTypeMax, only entries that
 * correspond to object types will be set.
 */
clang::FunctionDecl *
RSObjectRefCount::RSSetObjectFD[DataTypeMax];
clang::FunctionDecl *
RSObjectRefCount::RSClearObjectFD[DataTypeMax];

void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
  for (unsigned i = 0; i < DataTypeMax; i++) {
    RSSetObjectFD[i] = nullptr;
    RSClearObjectFD[i] = nullptr;
  }

  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();

  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
          E = TUDecl->decls_end(); I != E; I++) {
    if ((I->getKind() >= clang::Decl::firstFunction) &&
        (I->getKind() <= clang::Decl::lastFunction)) {
      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);

      // points to RSSetObjectFD or RSClearObjectFD
      clang::FunctionDecl **RSObjectFD;

      if (FD->getName() == "rsSetObject") {
        slangAssert((FD->getNumParams() == 2) &&
                    "Invalid rsSetObject function prototype (# params)");
        RSObjectFD = RSSetObjectFD;
      } else if (FD->getName() == "rsClearObject") {
        slangAssert((FD->getNumParams() == 1) &&
                    "Invalid rsClearObject function prototype (# params)");
        RSObjectFD = RSClearObjectFD;
      } else {
        continue;
      }

      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
      clang::QualType PVT = PVD->getOriginalType();
      // The first parameter must be a pointer like rs_allocation*
      slangAssert(PVT->isPointerType() &&
          "Invalid rs{Set,Clear}Object function prototype (pointer param)");

      // The rs object type passed to the FD
      clang::QualType RST = PVT->getPointeeType();
      DataType DT = RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
      slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
             && "must be RS object type");

      if (DT >= 0 && DT < DataTypeMax) {
          RSObjectFD[DT] = FD;
      } else {
          slangAssert(false && "incorrect type");
      }
    }
  }
}

namespace {

unsigned CountRSObjectTypes(const clang::Type *T);

clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
                                     clang::Expr *DstExpr,
                                     clang::Expr *SrcExpr,
                                     clang::SourceLocation StartLoc,
                                     clang::SourceLocation Loc);

// This function constructs a new CompoundStmt from the input StmtList.
clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
      std::list<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
  unsigned NewStmtCount = StmtList.size();
  unsigned CompoundStmtCount = 0;

  clang::Stmt **CompoundStmtList;
  CompoundStmtList = new clang::Stmt*[NewStmtCount];

  std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
  std::list<clang::Stmt*>::const_iterator E = StmtList.end();
  for ( ; I != E; I++) {
    CompoundStmtList[CompoundStmtCount++] = *I;
  }
  slangAssert(CompoundStmtCount == NewStmtCount);

  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
      C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);

  delete [] CompoundStmtList;

  return CS;
}

void AppendAfterStmt(clang::ASTContext &C,
                     clang::CompoundStmt *CS,
                     clang::Stmt *S,
                     std::list<clang::Stmt*> &StmtList) {
  slangAssert(CS);
  clang::CompoundStmt::body_iterator bI = CS->body_begin();
  clang::CompoundStmt::body_iterator bE = CS->body_end();
  clang::Stmt **UpdatedStmtList =
      new clang::Stmt*[CS->size() + StmtList.size()];

  unsigned UpdatedStmtCount = 0;
  unsigned Once = 0;
  for ( ; bI != bE; bI++) {
    if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
      // If we come across a return here, we don't have anything we can
      // reasonably replace. We should have already inserted our destructor
      // code in the proper spot, so we just clean up and return.
      delete [] UpdatedStmtList;

      return;
    }

    UpdatedStmtList[UpdatedStmtCount++] = *bI;

    if ((*bI == S) && !Once) {
      Once++;
      std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
      std::list<clang::Stmt*>::const_iterator E = StmtList.end();
      for ( ; I != E; I++) {
        UpdatedStmtList[UpdatedStmtCount++] = *I;
      }
    }
  }
  slangAssert(Once <= 1);

  // When S is nullptr, we are appending to the end of the CompoundStmt.
  if (!S) {
    slangAssert(Once == 0);
    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
    std::list<clang::Stmt*>::const_iterator E = StmtList.end();
    for ( ; I != E; I++) {
      UpdatedStmtList[UpdatedStmtCount++] = *I;
    }
  }

  CS->setStmts(C, llvm::makeArrayRef(UpdatedStmtList, UpdatedStmtCount));

  delete [] UpdatedStmtList;
}

// This class visits a compound statement and collects a list of all the exiting
// statements, such as any return statement in any sub-block, and any
// break/continue statement that would resume outside the current scope.
// We do not handle the case for goto statements that leave a local scope.
class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
 private:
  // The loop depth of the currently visited node.
  int mLoopDepth;

  // The switch statement depth of the currently visited node.
  // Note that this is tracked separately from the loop depth because
  // SwitchStmt-contained ContinueStmt's should have destructors for the
  // corresponding loop scope.
  int mSwitchDepth;

  // Output of the visitor: the statements that should be replaced by compound
  // statements, each of which contains rsClearObject() calls followed by the
  // original statement.
  std::vector<clang::Stmt*> mExitingStmts;

 public:
  DestructorVisitor() : mLoopDepth(0), mSwitchDepth(0) {}

  const std::vector<clang::Stmt*>& getExitingStmts() const {
    return mExitingStmts;
  }

  void VisitStmt(clang::Stmt *S);
  void VisitBreakStmt(clang::BreakStmt *BS);
  void VisitContinueStmt(clang::ContinueStmt *CS);
  void VisitDoStmt(clang::DoStmt *DS);
  void VisitForStmt(clang::ForStmt *FS);
  void VisitReturnStmt(clang::ReturnStmt *RS);
  void VisitSwitchStmt(clang::SwitchStmt *SS);
  void VisitWhileStmt(clang::WhileStmt *WS);
};

void DestructorVisitor::VisitStmt(clang::Stmt *S) {
  for (clang::Stmt* Child : S->children()) {
    if (Child) {
      Visit(Child);
    }
  }
}

void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
  VisitStmt(BS);
  if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
    mExitingStmts.push_back(BS);
  }
}

void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
  VisitStmt(CS);
  if (mLoopDepth == 0) {
    // Switch statements can have nested continues.
    mExitingStmts.push_back(CS);
  }
}

void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
  mLoopDepth++;
  VisitStmt(DS);
  mLoopDepth--;
}

void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
  mLoopDepth++;
  VisitStmt(FS);
  mLoopDepth--;
}

void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
  mExitingStmts.push_back(RS);
}

void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
  mSwitchDepth++;
  VisitStmt(SS);
  mSwitchDepth--;
}

void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
  mLoopDepth++;
  VisitStmt(WS);
  mLoopDepth--;
}

clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
                                 clang::Expr *RefRSVar,
                                 clang::SourceLocation Loc) {
  slangAssert(RefRSVar);
  const clang::Type *T = RefRSVar->getType().getTypePtr();
  slangAssert(!T->isArrayType() &&
              "Should not be destroying arrays with this function");

  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
  slangAssert((ClearObjectFD != nullptr) &&
              "rsClearObject doesn't cover all RS object types");

  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
  clang::QualType ClearObjectFDArgType =
      ClearObjectFD->getParamDecl(0)->getOriginalType();

  // Example destructor for "rs_font localFont;"
  //
  // (CallExpr 'void'
  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
  //   (UnaryOperator 'rs_font *' prefix '&'
  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))

  // Get address of targeted RS object
  clang::Expr *AddrRefRSVar =
      new(C) clang::UnaryOperator(RefRSVar,
                                  clang::UO_AddrOf,
                                  ClearObjectFDArgType,
                                  clang::VK_RValue,
                                  clang::OK_Ordinary,
                                  Loc);

  clang::Expr *RefRSClearObjectFD =
      clang::DeclRefExpr::Create(C,
                                 clang::NestedNameSpecifierLoc(),
                                 clang::SourceLocation(),
                                 ClearObjectFD,
                                 false,
                                 ClearObjectFD->getLocation(),
                                 ClearObjectFDType,
                                 clang::VK_RValue,
                                 nullptr);

  clang::Expr *RSClearObjectFP =
      clang::ImplicitCastExpr::Create(C,
                                      C.getPointerType(ClearObjectFDType),
                                      clang::CK_FunctionToPointerDecay,
                                      RefRSClearObjectFD,
                                      nullptr,
                                      clang::VK_RValue);

  llvm::SmallVector<clang::Expr*, 1> ArgList;
  ArgList.push_back(AddrRefRSVar);

  clang::CallExpr *RSClearObjectCall =
      new(C) clang::CallExpr(C,
                             RSClearObjectFP,
                             ArgList,
                             ClearObjectFD->getCallResultType(),
                             clang::VK_RValue,
                             Loc);

  return RSClearObjectCall;
}

static int ArrayDim(const clang::Type *T) {
  if (!T || !T->isArrayType()) {
    return 0;
  }

  const clang::ConstantArrayType *CAT =
    static_cast<const clang::ConstantArrayType *>(T);
  return static_cast<int>(CAT->getSize().getSExtValue());
}

clang::Stmt *ClearStructRSObject(
    clang::ASTContext &C,
    clang::DeclContext *DC,
    clang::Expr *RefRSStruct,
    clang::SourceLocation StartLoc,
    clang::SourceLocation Loc);

clang::Stmt *ClearArrayRSObject(
    clang::ASTContext &C,
    clang::DeclContext *DC,
    clang::Expr *RefRSArr,
    clang::SourceLocation StartLoc,
    clang::SourceLocation Loc) {
  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
  slangAssert(BaseType->isArrayType());

  int NumArrayElements = ArrayDim(BaseType);
  // Actually extract out the base RS object type for use later
  BaseType = BaseType->getArrayElementTypeNoTypeQual();

  if (NumArrayElements <= 0) {
    return nullptr;
  }

  // Example destructor loop for "rs_font fontArr[10];"
  //
  // (ForStmt
  //   (DeclStmt
  //     (VarDecl used rsIntIter 'int' cinit
  //       (IntegerLiteral 'int' 0)))
  //   (BinaryOperator 'int' '<'
  //     (ImplicitCastExpr int LValueToRValue
  //       (DeclRefExpr 'int' Var='rsIntIter'))
  //     (IntegerLiteral 'int' 10)
  //   nullptr << CondVar >>
  //   (UnaryOperator 'int' postfix '++'
  //     (DeclRefExpr 'int' Var='rsIntIter'))
  //   (CallExpr 'void'
  //     (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
  //       (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
  //     (UnaryOperator 'rs_font *' prefix '&'
  //       (ArraySubscriptExpr 'rs_font':'rs_font'
  //         (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
  //           (DeclRefExpr 'rs_font [10]' Var='fontArr'))
  //         (DeclRefExpr 'int' Var='rsIntIter'))))))

  // Create helper variable for iterating through elements
  static unsigned sIterCounter = 0;
  std::stringstream UniqueIterName;
  UniqueIterName << "rsIntIter" << sIterCounter++;
  clang::IdentifierInfo *II = &C.Idents.get(UniqueIterName.str());
  clang::VarDecl *IIVD =
      clang::VarDecl::Create(C,
                             DC,
                             StartLoc,
                             Loc,
                             II,
                             C.IntTy,
                             C.getTrivialTypeSourceInfo(C.IntTy),
                             clang::SC_None);
  // Mark "rsIntIter" as used
  IIVD->markUsed(C);

  // Form the actual destructor loop
  // for (Init; Cond; Inc)
  //   RSClearObjectCall;

  // Init -> "int rsIntIter = 0"
  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
  IIVD->setInit(Int0);

  clang::Decl *IID = (clang::Decl *)IIVD;
  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
  clang::Stmt *Init = new(C) clang::DeclStmt(DGR, Loc, Loc);

  // Cond -> "rsIntIter < NumArrayElements"
  clang::DeclRefExpr *RefrsIntIterLValue =
      clang::DeclRefExpr::Create(C,
                                 clang::NestedNameSpecifierLoc(),
                                 clang::SourceLocation(),
                                 IIVD,
                                 false,
                                 Loc,
                                 C.IntTy,
                                 clang::VK_LValue,
                                 nullptr);

  clang::Expr *RefrsIntIterRValue =
      clang::ImplicitCastExpr::Create(C,
                                      RefrsIntIterLValue->getType(),
                                      clang::CK_LValueToRValue,
                                      RefrsIntIterLValue,
                                      nullptr,
                                      clang::VK_RValue);

  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);

  clang::BinaryOperator *Cond =
      new(C) clang::BinaryOperator(RefrsIntIterRValue,
                                   NumArrayElementsExpr,
                                   clang::BO_LT,
                                   C.IntTy,
                                   clang::VK_RValue,
                                   clang::OK_Ordinary,
                                   Loc,
                                   false);

  // Inc -> "rsIntIter++"
  clang::UnaryOperator *Inc =
      new(C) clang::UnaryOperator(RefrsIntIterLValue,
                                  clang::UO_PostInc,
                                  C.IntTy,
                                  clang::VK_RValue,
                                  clang::OK_Ordinary,
                                  Loc);

  // Body -> "rsClearObject(&VD[rsIntIter]);"
  // Destructor loop operates on individual array elements

  clang::Expr *RefRSArrPtr =
      clang::ImplicitCastExpr::Create(C,
          C.getPointerType(BaseType->getCanonicalTypeInternal()),
          clang::CK_ArrayToPointerDecay,
          RefRSArr,
          nullptr,
          clang::VK_RValue);

  clang::Expr *RefRSArrPtrSubscript =
      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
                                       RefrsIntIterRValue,
                                       BaseType->getCanonicalTypeInternal(),
                                       clang::VK_RValue,
                                       clang::OK_Ordinary,
                                       Loc);

  DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);

  clang::Stmt *RSClearObjectCall = nullptr;
  if (BaseType->isArrayType()) {
    RSClearObjectCall =
        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
  } else if (DT == DataTypeUnknown) {
    RSClearObjectCall =
        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
  } else {
    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
  }

  clang::ForStmt *DestructorLoop =
      new(C) clang::ForStmt(C,
                            Init,
                            Cond,
                            nullptr,  // no condVar
                            Inc,
                            RSClearObjectCall,
                            Loc,
                            Loc,
                            Loc);

  return DestructorLoop;
}

unsigned CountRSObjectTypes(const clang::Type *T) {
  slangAssert(T);
  unsigned RSObjectCount = 0;

  if (T->isArrayType()) {
    return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
  }

  DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
  if (DT != DataTypeUnknown) {
    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
  }

  if (T->isUnionType()) {
    clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
    RD = RD->getDefinition();
    for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
           FE = RD->field_end();
         FI != FE;
         FI++) {
      const clang::FieldDecl *FD = *FI;
      const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
      if (CountRSObjectTypes(FT)) {
        slangAssert(false && "can't have unions with RS object types!");
        return 0;
      }
    }
  }

  if (!T->isStructureType()) {
    return 0;
  }

  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
  RD = RD->getDefinition();
  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
         FE = RD->field_end();
       FI != FE;
       FI++) {
    const clang::FieldDecl *FD = *FI;
    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    if (CountRSObjectTypes(FT)) {
      // Sub-structs should only count once (as should arrays, etc.)
      RSObjectCount++;
    }
  }

  return RSObjectCount;
}

clang::Stmt *ClearStructRSObject(
    clang::ASTContext &C,
    clang::DeclContext *DC,
    clang::Expr *RefRSStruct,
    clang::SourceLocation StartLoc,
    clang::SourceLocation Loc) {
  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();

  slangAssert(!BaseType->isArrayType());

  // Structs should show up as unknown primitive types
  slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
              DataTypeUnknown);

  unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
  slangAssert(FieldsToDestroy != 0);

  unsigned StmtCount = 0;
  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
  for (unsigned i = 0; i < FieldsToDestroy; i++) {
    StmtArray[i] = nullptr;
  }

  // Populate StmtArray by creating a destructor for each RS object field
  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
  RD = RD->getDefinition();
  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
         FE = RD->field_end();
       FI != FE;
       FI++) {
    // We just look through all field declarations to see if we find a
    // declaration for an RS object type (or an array of one).
    bool IsArrayType = false;
    clang::FieldDecl *FD = *FI;
    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    const clang::Type *OrigType = FT;
    while (FT && FT->isArrayType()) {
      FT = FT->getArrayElementTypeNoTypeQual();
      IsArrayType = true;
    }

    // Pass a DeclarationNameInfo with a valid DeclName, since name equality
    // gets asserted during CodeGen.
    clang::DeclarationNameInfo FDDeclNameInfo(FD->getDeclName(),
                                              FD->getLocation());

    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
      clang::DeclAccessPair FoundDecl =
          clang::DeclAccessPair::make(FD, clang::AS_none);
      clang::MemberExpr *RSObjectMember =
          clang::MemberExpr::Create(C,
                                    RefRSStruct,
                                    false,
                                    clang::SourceLocation(),
                                    clang::NestedNameSpecifierLoc(),
                                    clang::SourceLocation(),
                                    FD,
                                    FoundDecl,
                                    FDDeclNameInfo,
                                    nullptr,
                                    OrigType->getCanonicalTypeInternal(),
                                    clang::VK_RValue,
                                    clang::OK_Ordinary);

      slangAssert(StmtCount < FieldsToDestroy);

      if (IsArrayType) {
        StmtArray[StmtCount++] = ClearArrayRSObject(C,
                                                    DC,
                                                    RSObjectMember,
                                                    StartLoc,
                                                    Loc);
      } else {
        StmtArray[StmtCount++] = ClearSingleRSObject(C,
                                                     RSObjectMember,
                                                     Loc);
      }
    } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
      // In this case, we have a nested struct. We may not end up filling all
      // of the spaces in StmtArray (sub-structs should handle themselves
      // with separate compound statements).
      clang::DeclAccessPair FoundDecl =
          clang::DeclAccessPair::make(FD, clang::AS_none);
      clang::MemberExpr *RSObjectMember =
          clang::MemberExpr::Create(C,
                                    RefRSStruct,
                                    false,
                                    clang::SourceLocation(),
                                    clang::NestedNameSpecifierLoc(),
                                    clang::SourceLocation(),
                                    FD,
                                    FoundDecl,
                                    clang::DeclarationNameInfo(),
                                    nullptr,
                                    OrigType->getCanonicalTypeInternal(),
                                    clang::VK_RValue,
                                    clang::OK_Ordinary);

      if (IsArrayType) {
        StmtArray[StmtCount++] = ClearArrayRSObject(C,
                                                    DC,
                                                    RSObjectMember,
                                                    StartLoc,
                                                    Loc);
      } else {
        StmtArray[StmtCount++] = ClearStructRSObject(C,
                                                     DC,
                                                     RSObjectMember,
                                                     StartLoc,
                                                     Loc);
      }
    }
  }

  slangAssert(StmtCount > 0);
  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
      C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);

  delete [] StmtArray;

  return CS;
}

clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
                                     clang::Expr *DstExpr,
                                     clang::Expr *SrcExpr,
                                     clang::SourceLocation StartLoc,
                                     clang::SourceLocation Loc) {
  const clang::Type *T = DstExpr->getType().getTypePtr();
  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
  slangAssert((SetObjectFD != nullptr) &&
              "rsSetObject doesn't cover all RS object types");

  clang::QualType SetObjectFDType = SetObjectFD->getType();
  clang::QualType SetObjectFDArgType[2];
  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();

  clang::Expr *RefRSSetObjectFD =
      clang::DeclRefExpr::Create(C,
                                 clang::NestedNameSpecifierLoc(),
                                 clang::SourceLocation(),
                                 SetObjectFD,
                                 false,
                                 Loc,
                                 SetObjectFDType,
                                 clang::VK_RValue,
                                 nullptr);

  clang::Expr *RSSetObjectFP =
      clang::ImplicitCastExpr::Create(C,
                                      C.getPointerType(SetObjectFDType),
                                      clang::CK_FunctionToPointerDecay,
                                      RefRSSetObjectFD,
                                      nullptr,
                                      clang::VK_RValue);

  llvm::SmallVector<clang::Expr*, 2> ArgList;
  ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
                                                clang::UO_AddrOf,
                                                SetObjectFDArgType[0],
                                                clang::VK_RValue,
                                                clang::OK_Ordinary,
                                                Loc));
  ArgList.push_back(SrcExpr);

  clang::CallExpr *RSSetObjectCall =
      new(C) clang::CallExpr(C,
                             RSSetObjectFP,
                             ArgList,
                             SetObjectFD->getCallResultType(),
                             clang::VK_RValue,
                             Loc);

  return RSSetObjectCall;
}

clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
                                     clang::Expr *LHS,
                                     clang::Expr *RHS,
                                     clang::SourceLocation StartLoc,
                                     clang::SourceLocation Loc);

/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
                                           clang::Expr *DstArr,
                                           clang::Expr *SrcArr,
                                           clang::SourceLocation StartLoc,
                                           clang::SourceLocation Loc) {
  clang::DeclContext *DC = nullptr;
  const clang::Type *BaseType = DstArr->getType().getTypePtr();
  slangAssert(BaseType->isArrayType());

  int NumArrayElements = ArrayDim(BaseType);
  // Actually extract out the base RS object type for use later
  BaseType = BaseType->getArrayElementTypeNoTypeQual();

  clang::Stmt *StmtArray[2] = {nullptr};
  int StmtCtr = 0;

  if (NumArrayElements <= 0) {
    return nullptr;
  }

  // Create helper variable for iterating through elements
  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
  clang::VarDecl *IIVD =
      clang::VarDecl::Create(C,
                             DC,
                             StartLoc,
                             Loc,
                             &II,
                             C.IntTy,
                             C.getTrivialTypeSourceInfo(C.IntTy),
                             clang::SC_None,
                             clang::SC_None);
  clang::Decl *IID = (clang::Decl *)IIVD;

  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);

  // Form the actual loop
  // for (Init; Cond; Inc)
  //   RSSetObjectCall;

  // Init -> "rsIntIter = 0"
  clang::DeclRefExpr *RefrsIntIter =
      clang::DeclRefExpr::Create(C,
                                 clang::NestedNameSpecifierLoc(),
                                 IIVD,
                                 Loc,
                                 C.IntTy,
                                 clang::VK_RValue,
                                 nullptr);

  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);

  clang::BinaryOperator *Init =
      new(C) clang::BinaryOperator(RefrsIntIter,
                                   Int0,
                                   clang::BO_Assign,
                                   C.IntTy,
                                   clang::VK_RValue,
                                   clang::OK_Ordinary,
                                   Loc);

  // Cond -> "rsIntIter < NumArrayElements"
  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);

  clang::BinaryOperator *Cond =
      new(C) clang::BinaryOperator(RefrsIntIter,
                                   NumArrayElementsExpr,
                                   clang::BO_LT,
                                   C.IntTy,
                                   clang::VK_RValue,
                                   clang::OK_Ordinary,
                                   Loc);

  // Inc -> "rsIntIter++"
  clang::UnaryOperator *Inc =
      new(C) clang::UnaryOperator(RefrsIntIter,
                                  clang::UO_PostInc,
                                  C.IntTy,
                                  clang::VK_RValue,
                                  clang::OK_Ordinary,
                                  Loc);

  // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
  // Loop operates on individual array elements

  clang::Expr *DstArrPtr =
      clang::ImplicitCastExpr::Create(C,
          C.getPointerType(BaseType->getCanonicalTypeInternal()),
          clang::CK_ArrayToPointerDecay,
          DstArr,
          nullptr,
          clang::VK_RValue);

  clang::Expr *DstArrPtrSubscript =
      new(C) clang::ArraySubscriptExpr(DstArrPtr,
                                       RefrsIntIter,
                                       BaseType->getCanonicalTypeInternal(),
                                       clang::VK_RValue,
                                       clang::OK_Ordinary,
                                       Loc);

  clang::Expr *SrcArrPtr =
      clang::ImplicitCastExpr::Create(C,
          C.getPointerType(BaseType->getCanonicalTypeInternal()),
          clang::CK_ArrayToPointerDecay,
          SrcArr,
          nullptr,
          clang::VK_RValue);

  clang::Expr *SrcArrPtrSubscript =
      new(C) clang::ArraySubscriptExpr(SrcArrPtr,
                                       RefrsIntIter,
                                       BaseType->getCanonicalTypeInternal(),
                                       clang::VK_RValue,
                                       clang::OK_Ordinary,
                                       Loc);

  DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);

  clang::Stmt *RSSetObjectCall = nullptr;
  if (BaseType->isArrayType()) {
    RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
                                             SrcArrPtrSubscript,
                                             StartLoc, Loc);
  } else if (DT == DataTypeUnknown) {
    RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
                                              SrcArrPtrSubscript,
                                              StartLoc, Loc);
  } else {
    RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
                                              SrcArrPtrSubscript,
                                              StartLoc, Loc);
  }

  clang::ForStmt *DestructorLoop =
      new(C) clang::ForStmt(C,
                            Init,
                            Cond,
                            nullptr,  // no condVar
                            Inc,
                            RSSetObjectCall,
                            Loc,
                            Loc,
                            Loc);

  StmtArray[StmtCtr++] = DestructorLoop;
  slangAssert(StmtCtr == 2);

  clang::CompoundStmt *CS =
      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);

  return CS;
} */

clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
                                     clang::Expr *LHS,
                                     clang::Expr *RHS,
                                     clang::SourceLocation StartLoc,
                                     clang::SourceLocation Loc) {
  clang::QualType QT = LHS->getType();
  const clang::Type *T = QT.getTypePtr();
  slangAssert(T->isStructureType());
  slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));

  // Keep an extra slot for the original copy (memcpy)
  unsigned FieldsToSet = CountRSObjectTypes(T) + 1;

  unsigned StmtCount = 0;
  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
  for (unsigned i = 0; i < FieldsToSet; i++) {
    StmtArray[i] = nullptr;
  }

  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
  RD = RD->getDefinition();
  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
         FE = RD->field_end();
       FI != FE;
       FI++) {
    bool IsArrayType = false;
    clang::FieldDecl *FD = *FI;
    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
    const clang::Type *OrigType = FT;

    if (!CountRSObjectTypes(FT)) {
      // Skip to next if we don't have any viable RS object types
      continue;
    }

    clang::DeclAccessPair FoundDecl =
        clang::DeclAccessPair::make(FD, clang::AS_none);
    clang::MemberExpr *DstMember =
        clang::MemberExpr::Create(C,
                                  LHS,
                                  false,
                                  clang::SourceLocation(),
                                  clang::NestedNameSpecifierLoc(),
                                  clang::SourceLocation(),
                                  FD,
                                  FoundDecl,
                                  clang::DeclarationNameInfo(
                                      FD->getDeclName(),
                                      clang::SourceLocation()),
                                  nullptr,
                                  OrigType->getCanonicalTypeInternal(),
                                  clang::VK_RValue,
                                  clang::OK_Ordinary);

    clang::MemberExpr *SrcMember =
        clang::MemberExpr::Create(C,
                                  RHS,
                                  false,
                                  clang::SourceLocation(),
                                  clang::NestedNameSpecifierLoc(),
                                  clang::SourceLocation(),
                                  FD,
                                  FoundDecl,
                                  clang::DeclarationNameInfo(
                                      FD->getDeclName(),
                                      clang::SourceLocation()),
                                  nullptr,
                                  OrigType->getCanonicalTypeInternal(),
                                  clang::VK_RValue,
                                  clang::OK_Ordinary);

    if (FT->isArrayType()) {
      FT = FT->getArrayElementTypeNoTypeQual();
      IsArrayType = true;
    }

    DataType DT = RSExportPrimitiveType::GetRSSpecificType(FT);

    if (IsArrayType) {
      clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
      DiagEngine.Report(
        clang::FullSourceLoc(Loc, C.getSourceManager()),
        DiagEngine.getCustomDiagID(
          clang::DiagnosticsEngine::Error,
          "Arrays of RS object types within structures cannot be copied"));
      // TODO(srhines): Support setting arrays of RS objects
      // StmtArray[StmtCount++] =
      //    CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
    } else if (DT == DataTypeUnknown) {
      StmtArray[StmtCount++] =
          CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
    } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
      StmtArray[StmtCount++] =
          CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
    } else {
      slangAssert(false);
    }
  }

  slangAssert(StmtCount < FieldsToSet);

  // We still need to actually do the overall struct copy. For simplicity,
  // we just do a straight-up assignment (which will still preserve all
  // the proper RS object reference counts).
  clang::BinaryOperator *CopyStruct =
      new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
                                   clang::VK_RValue, clang::OK_Ordinary, Loc,
                                   false);
  StmtArray[StmtCount++] = CopyStruct;

  clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
      C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);

  delete [] StmtArray;

  return CS;
}

}  // namespace

void RSObjectRefCount::Scope::InsertStmt(const clang::ASTContext &C,
                                         clang::Stmt *NewStmt) {
  std::vector<clang::Stmt*> newBody;
  for (clang::Stmt* S1 : mCS->body()) {
    if (S1 == mCurrent) {
      newBody.push_back(NewStmt);
    }
    newBody.push_back(S1);
  }
  mCS->setStmts(C, newBody);
}

void RSObjectRefCount::Scope::ReplaceStmt(const clang::ASTContext &C,
                                          clang::Stmt *NewStmt) {
  std::vector<clang::Stmt*> newBody;
  for (clang::Stmt* S1 : mCS->body()) {
    if (S1 == mCurrent) {
      newBody.push_back(NewStmt);
    } else {
      newBody.push_back(S1);
    }
  }
  mCS->setStmts(C, newBody);
}

void RSObjectRefCount::Scope::ReplaceExpr(const clang::ASTContext& C,
                                          clang::Expr* OldExpr,
                                          clang::Expr* NewExpr) {
  RSASTReplace R(C);
  R.ReplaceStmt(mCurrent, OldExpr, NewExpr);
}

void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
    clang::BinaryOperator *AS) {

  clang::QualType QT = AS->getType();

  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
      DataTypeRSAllocation)->getASTContext();

  clang::SourceLocation Loc = AS->getExprLoc();
  clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
  clang::Stmt *UpdatedStmt = nullptr;

  if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
    // By definition, this is a struct assignment if we get here
    UpdatedStmt =
        CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
  } else {
    UpdatedStmt =
        CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
  }

  RSASTReplace R(C);
  R.ReplaceStmt(mCS, AS, UpdatedStmt);
}

void RSObjectRefCount::Scope::AppendRSObjectInit(
    clang::VarDecl *VD,
    clang::DeclStmt *DS,
    DataType DT,
    clang::Expr *InitExpr) {
  slangAssert(VD);

  if (!InitExpr) {
    return;
  }

  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
      DataTypeRSAllocation)->getASTContext();
  clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
      DataTypeRSAllocation)->getLocation();
  clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
      DataTypeRSAllocation)->getInnerLocStart();

  if (DT == DataTypeIsStruct) {
    const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
    clang::DeclRefExpr *RefRSVar =
        clang::DeclRefExpr::Create(C,
                                   clang::NestedNameSpecifierLoc(),
                                   clang::SourceLocation(),
                                   VD,
                                   false,
                                   Loc,
                                   T->getCanonicalTypeInternal(),
                                   clang::VK_RValue,
                                   nullptr);

    clang::Stmt *RSSetObjectOps =
        CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
    // Fix for b/37363420; consider:
    //
    // struct foo { rs_matrix m; };
    // void bar() {
    //   struct foo M = {...};
    // }
    //
    // slang modifies that declaration with initialization to a
    // declaration plus an assignment of the initialization values.
    //
    // void bar() {
    //   struct foo M = {};
    //   M = {...}; // by CreateStructRSSetObject() above
    // }
    //
    // the slang-generated statement (M = {...}) is a use of M, and we
    // need to mark M (clang::VarDecl *VD) as used.
    VD->markUsed(C);

    std::list<clang::Stmt*> StmtList;
    StmtList.push_back(RSSetObjectOps);
    AppendAfterStmt(C, mCS, DS, StmtList);
    return;
  }

  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
  slangAssert((SetObjectFD != nullptr) &&
              "rsSetObject doesn't cover all RS object types");

  clang::QualType SetObjectFDType = SetObjectFD->getType();
  clang::QualType SetObjectFDArgType[2];
  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();

  clang::Expr *RefRSSetObjectFD =
      clang::DeclRefExpr::Create(C,
                                 clang::NestedNameSpecifierLoc(),
                                 clang::SourceLocation(),
                                 SetObjectFD,
                                 false,
                                 Loc,
                                 SetObjectFDType,
                                 clang::VK_RValue,
                                 nullptr);

  clang::Expr *RSSetObjectFP =
      clang::ImplicitCastExpr::Create(C,
                                      C.getPointerType(SetObjectFDType),
                                      clang::CK_FunctionToPointerDecay,
                                      RefRSSetObjectFD,
                                      nullptr,
                                      clang::VK_RValue);

  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
  clang::DeclRefExpr *RefRSVar =
      clang::DeclRefExpr::Create(C,
                                 clang::NestedNameSpecifierLoc(),
                                 clang::SourceLocation(),
                                 VD,
                                 false,
                                 Loc,
                                 T->getCanonicalTypeInternal(),
                                 clang::VK_RValue,
                                 nullptr);

  llvm::SmallVector<clang::Expr*, 2> ArgList;
  ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
                                                clang::UO_AddrOf,
                                                SetObjectFDArgType[0],
                                                clang::VK_RValue,
                                                clang::OK_Ordinary,
                                                Loc));
  ArgList.push_back(InitExpr);

  clang::CallExpr *RSSetObjectCall =
      new(C) clang::CallExpr(C,
                             RSSetObjectFP,
                             ArgList,
                             SetObjectFD->getCallResultType(),
                             clang::VK_RValue,
                             Loc);

  std::list<clang::Stmt*> StmtList;
  StmtList.push_back(RSSetObjectCall);
  AppendAfterStmt(C, mCS, DS, StmtList);
}

void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
  if (mRSO.empty()) {
    return;
  }

  clang::DeclContext* DC = mRSO.front()->getDeclContext();
  clang::ASTContext& C = DC->getParentASTContext();
  clang::SourceManager& SM = C.getSourceManager();

  const auto& OccursBefore = [&SM] (clang::SourceLocation L1, clang::SourceLocation L2)->bool {
    return SM.isBeforeInTranslationUnit(L1, L2);
  };
  typedef std::map<clang::SourceLocation, clang::Stmt*, decltype(OccursBefore)> DMap;

  DMap dtors(OccursBefore);

  // Create rsClearObject calls. Note the DMap entries are sorted by the SourceLocation.
  for (clang::VarDecl* VD : mRSO) {
    clang::SourceLocation Loc = VD->getSourceRange().getBegin();
    clang::Stmt* RSClearObjectCall = ClearRSObject(VD, DC);
    dtors.insert(std::make_pair(Loc, RSClearObjectCall));
  }

  DestructorVisitor Visitor;
  Visitor.Visit(mCS);

  // Replace each exiting statement with a block that contains the original statement
  // and added rsClearObject() calls before it.
  for (clang::Stmt* S : Visitor.getExitingStmts()) {

    const clang::SourceLocation currentLoc = S->getLocStart();

    DMap::iterator firstDtorIter = dtors.begin();
    DMap::iterator currentDtorIter = firstDtorIter;
    DMap::iterator lastDtorIter = dtors.end();

    while (currentDtorIter != lastDtorIter &&
           OccursBefore(currentDtorIter->first, currentLoc)) {
      currentDtorIter++;
    }

    if (currentDtorIter == firstDtorIter) {
      continue;
    }

    std::list<clang::Stmt*> Stmts;

    // Insert rsClearObject() calls for all rsObjects declared before the current statement
    for(DMap::iterator it = firstDtorIter; it != currentDtorIter; it++) {
      Stmts.push_back(it->second);
    }
    Stmts.push_back(S);

    RSASTReplace R(C);
    clang::CompoundStmt* CS = BuildCompoundStmt(C, Stmts, S->getLocEnd());
    R.ReplaceStmt(mCS, S, CS);
  }

  std::list<clang::Stmt*> Stmts;
  for(auto LocCallPair : dtors) {
    Stmts.push_back(LocCallPair.second);
  }
  AppendAfterStmt(C, mCS, nullptr, Stmts);
}

clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
    clang::VarDecl *VD,
    clang::DeclContext *DC) {
  slangAssert(VD);
  clang::ASTContext &C = VD->getASTContext();
  clang::SourceLocation Loc = VD->getLocation();
  clang::SourceLocation StartLoc = VD->getInnerLocStart();
  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);

  // Reference expr to target RS object variable
  clang::DeclRefExpr *RefRSVar =
      clang::DeclRefExpr::Create(C,
                                 clang::NestedNameSpecifierLoc(),
                                 clang::SourceLocation(),
                                 VD,
                                 false,
                                 Loc,
                                 T->getCanonicalTypeInternal(),
                                 clang::VK_RValue,
                                 nullptr);

  if (T->isArrayType()) {
    return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
  }

  DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);

  if (DT == DataTypeUnknown ||
      DT == DataTypeIsStruct) {
    return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
  }

  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
              "Should be RS object");

  return ClearSingleRSObject(C, RefRSVar, Loc);
}

bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
                                          DataType *DT,
                                          clang::Expr **InitExpr) {
  slangAssert(VD && DT && InitExpr);
  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);

  // Loop through array types to get to base type
  while (T && T->isArrayType()) {
    T = T->getArrayElementTypeNoTypeQual();
  }

  bool DataTypeIsStructWithRSObject = false;
  *DT = RSExportPrimitiveType::GetRSSpecificType(T);

  if (*DT == DataTypeUnknown) {
    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
      *DT = DataTypeIsStruct;
      DataTypeIsStructWithRSObject = true;
    } else {
      return false;
    }
  }

  bool DataTypeIsRSObject = false;
  if (DataTypeIsStructWithRSObject) {
    DataTypeIsRSObject = true;
  } else {
    DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
  }
  *InitExpr = VD->getInit();

  if (!DataTypeIsRSObject && *InitExpr) {
    // If we already have an initializer for a matrix type, we are done.
    return DataTypeIsRSObject;
  }

  clang::Expr *ZeroInitializer =
      CreateEmptyInitListExpr(VD->getASTContext(), VD->getLocation());

  if (ZeroInitializer) {
    ZeroInitializer->setType(T->getCanonicalTypeInternal());
    VD->setInit(ZeroInitializer);
  }

  return DataTypeIsRSObject;
}

clang::Expr *RSObjectRefCount::CreateEmptyInitListExpr(
    clang::ASTContext &C,
    const clang::SourceLocation &Loc) {

  // We can cheaply construct a zero initializer by just creating an empty
  // initializer list. Clang supports this extension to C(99), and will create
  // any necessary constructs to zero out the entire variable.
  llvm::SmallVector<clang::Expr*, 1> EmptyInitList;
  return new(C) clang::InitListExpr(C, Loc, EmptyInitList, Loc);
}

clang::CompoundStmt* RSObjectRefCount::CreateRetStmtWithTempVar(
    clang::ASTContext& C,
    clang::DeclContext* DC,
    clang::ReturnStmt* RS,
    const unsigned id) {
  std::list<clang::Stmt*> NewStmts;
  // Since we insert rsClearObj() calls before the return statement, we need
  // to make sure none of the cleared RS objects are referenced in the
  // return statement.
  // For that, we create a new local variable named .rs.retval, assign the
  // original return expression to it, make all necessary rsClearObj()
  // calls, then return .rs.retval. Note rsClearObj() is not called on
  // .rs.retval.

  clang::SourceLocation Loc = RS->getLocStart();
  std::stringstream ss;
  ss << ".rs.retval" << id;
  llvm::StringRef VarName(ss.str());

  clang::Expr* RetVal = RS->getRetValue();
  const clang::QualType RetTy = RetVal->getType();
  clang::VarDecl* RSRetValDecl = clang::VarDecl::Create(
      C,                                     // AST context
      DC,                                    // Decl context
      Loc,                                   // Start location
      Loc,                                   // Id location
      &C.Idents.get(VarName),                // Id
      RetTy,                                 // Type
      C.getTrivialTypeSourceInfo(RetTy),     // Type info
      clang::SC_None                         // Storage class
  );
  const clang::Type *T = RetTy.getTypePtr();
  clang::Expr *ZeroInitializer =
      RSObjectRefCount::CreateEmptyInitListExpr(C, Loc);
  ZeroInitializer->setType(T->getCanonicalTypeInternal());
  RSRetValDecl->setInit(ZeroInitializer);
  RSRetValDecl->markUsed(C);
  clang::Decl* Decls[] = { RSRetValDecl };
  const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
      C, Decls, sizeof(Decls) / sizeof(*Decls));
  clang::DeclStmt* DS = new (C) clang::DeclStmt(DGR, Loc, Loc);
  NewStmts.push_back(DS);

  clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
      C,
      clang::NestedNameSpecifierLoc(),       // QualifierLoc
      Loc,                                   // TemplateKWLoc
      RSRetValDecl,
      false,                                 // RefersToEnclosingVariableOrCapture
      Loc,                                   // NameLoc
      RetTy,
      clang::VK_LValue
  );
  clang::Stmt* SetRetTempVar = CreateSingleRSSetObject(C, DRE, RetVal, Loc, Loc);
  NewStmts.push_back(SetRetTempVar);

  // Creates a new return statement
  clang::ReturnStmt* NewRet = new (C) clang::ReturnStmt(RS->getReturnLoc());
  clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
      C,
      RetTy,
      clang::CK_LValueToRValue,
      DRE,
      nullptr,
      clang::VK_RValue
  );
  NewRet->setRetValue(CastExpr);
  NewStmts.push_back(NewRet);

  return BuildCompoundStmt(C, NewStmts, Loc);
}

void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
  VisitStmt(DS);
  getCurrentScope()->setCurrentStmt(DS);
  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
       I != E;
       I++) {
    clang::Decl *D = *I;
    if (D->getKind() == clang::Decl::Var) {
      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
      DataType DT = DataTypeUnknown;
      clang::Expr *InitExpr = nullptr;
      if (InitializeRSObject(VD, &DT, &InitExpr)) {
        // We need to zero-init all RS object types (including matrices), ...
        getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
        // ... but, only add to the list of RS objects if we have some
        // non-matrix RS object fields.
        if (CountRSObjectTypes(VD->getType().getTypePtr())) {
          getCurrentScope()->addRSObject(VD);
        }
      }
    }
  }
}

void RSObjectRefCount::VisitCallExpr(clang::CallExpr* CE) {
  clang::QualType RetTy;
  const clang::FunctionDecl* FD = CE->getDirectCallee();

  if (FD) {
    // Direct calls

    RetTy = FD->getReturnType();
  } else {
    // Indirect calls through function pointers

    const clang::Expr* Callee = CE->getCallee();
    const clang::Type* CalleeType = Callee->getType().getTypePtr();
    const clang::PointerType* PtrType = CalleeType->getAs<clang::PointerType>();

    if (!PtrType) {
      return;
    }

    const clang::Type* PointeeType = PtrType->getPointeeType().getTypePtr();
    const clang::FunctionType* FuncType = PointeeType->getAs<clang::FunctionType>();

    if (!FuncType) {
      return;
    }

    RetTy = FuncType->getReturnType();
  }

  // The RenderScript runtime API maintains the invariant that the sysRef of a new RS object would
  // be 1, with the exception of rsGetAllocation() (deprecated in API 22), which leaves the sysRef
  // 0 for a new allocation. It is the responsibility of the callee of the API to decrement the
  // sysRef when a reference of the RS object goes out of scope. The compiler generates code to do
  // just that, by creating a temporary variable named ".rs.tmpN" with the result of
  // an RS-object-returning API directly assigned to it, and calling rsClearObject() on .rs.tmpN
  // right before it exits the current scope. Such code generation is skipped for rsGetAllocation()
  // to avoid decrementing its sysRef below zero.

  if (CountRSObjectTypes(RetTy.getTypePtr())==0 ||
      (FD && FD->getName() == "rsGetAllocation")) {
    return;
  }

  clang::SourceLocation Loc = CE->getSourceRange().getBegin();
  std::stringstream ss;
  ss << ".rs.tmp" << getNextID();
  llvm::StringRef VarName(ss.str());

  clang::VarDecl* TempVarDecl = clang::VarDecl::Create(
      mCtx,                                  // AST context
      GetDeclContext(),                      // Decl context
      Loc,                                   // Start location
      Loc,                                   // Id location
      &mCtx.Idents.get(VarName),             // Id
      RetTy,                                 // Type
      mCtx.getTrivialTypeSourceInfo(RetTy),  // Type info
      clang::SC_None                         // Storage class
  );
  TempVarDecl->setInit(CE);
  TempVarDecl->markUsed(mCtx);
  clang::Decl* Decls[] = { TempVarDecl };
  const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
      mCtx, Decls, sizeof(Decls) / sizeof(*Decls));
  clang::DeclStmt* DS = new (mCtx) clang::DeclStmt(DGR, Loc, Loc);

  getCurrentScope()->InsertStmt(mCtx, DS);

  clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
      mCtx,                                  // AST context
      clang::NestedNameSpecifierLoc(),       // QualifierLoc
      Loc,                                   // TemplateKWLoc
      TempVarDecl,
      false,                                 // RefersToEnclosingVariableOrCapture
      Loc,                                   // NameLoc
      RetTy,
      clang::VK_LValue
  );
  clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
      mCtx,
      RetTy,
      clang::CK_LValueToRValue,
      DRE,
      nullptr,
      clang::VK_RValue
  );

  getCurrentScope()->ReplaceExpr(mCtx, CE, CastExpr);

  // Register TempVarDecl for destruction call (rsClearObj).
  getCurrentScope()->addRSObject(TempVarDecl);
}

void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
  if (!emptyScope()) {
    getCurrentScope()->setCurrentStmt(CS);
  }

  if (!CS->body_empty()) {
    // Push a new scope
    Scope *S = new Scope(CS);
    mScopeStack.push_back(S);

    VisitStmt(CS);

    // Destroy the scope
    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
    S->InsertLocalVarDestructors();
    mScopeStack.pop_back();
    delete S;
  }
}

void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
  getCurrentScope()->setCurrentStmt(AS);
  clang::QualType QT = AS->getType();

  if (CountRSObjectTypes(QT.getTypePtr())) {
    getCurrentScope()->ReplaceRSObjectAssignment(AS);
  }
}

void RSObjectRefCount::VisitReturnStmt(clang::ReturnStmt *RS) {
  getCurrentScope()->setCurrentStmt(RS);

  // If there is no local rsObject declared so far, no need to transform the
  // return statement.

  bool RSObjDeclared = false;

  for (const Scope* S : mScopeStack) {
    if (S->hasRSObject()) {
      RSObjDeclared = true;
      break;
    }
  }

  if (!RSObjDeclared) {
    return;
  }

  // If the return statement does not return anything, or if it does not return
  // a rsObject, no need to transform it.

  clang::Expr* RetVal = RS->getRetValue();
  if (!RetVal || CountRSObjectTypes(RetVal->getType().getTypePtr()) == 0) {
    return;
  }

  // Transform the return statement so that it does not potentially return or
  // reference a rsObject that has been cleared.

  clang::CompoundStmt* NewRS;
  NewRS = CreateRetStmtWithTempVar(mCtx, GetDeclContext(), RS, getNextID());

  getCurrentScope()->ReplaceStmt(mCtx, NewRS);
}

void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
  getCurrentScope()->setCurrentStmt(S);
  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
       I != E;
       I++) {
    if (clang::Stmt *Child = *I) {
      Visit(Child);
    }
  }
}

// This function walks the list of global variables and (potentially) creates
// a single global static destructor function that properly decrements
// reference counts on the contained RS object types.
clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
  Init();

  clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
  clang::SourceLocation loc;

  llvm::StringRef SR(".rs.dtor");
  clang::IdentifierInfo &II = mCtx.Idents.get(SR);
  clang::DeclarationName N(&II);
  clang::FunctionProtoType::ExtProtoInfo EPI;
  clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
      llvm::ArrayRef<clang::QualType>(), EPI);
  clang::FunctionDecl *FD = nullptr;

  // Generate rsClearObject() call chains for every global variable
  // (whether static or extern).
  std::list<clang::Stmt *> StmtList;
  for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
          E = DC->decls_end(); I != E; I++) {
    clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
    if (VD) {
      if (CountRSObjectTypes(VD->getType().getTypePtr())) {
        if (!FD) {
          // Only create FD if we are going to use it.
          FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, nullptr,
                                           clang::SC_None);
        }
        // Mark VD as used.  It might be unused, except for the destructor.
        // 'markUsed' has side-effects that are caused only if VD is not already
        // used.  Hence no need for an extra check here.
        VD->markUsed(mCtx);
        // Make sure to create any helpers within the function's DeclContext,
        // not the one associated with the global translation unit.
        clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
        StmtList.push_back(RSClearObjectCall);
      }
    }
  }

  // Nothing needs to be destroyed, so don't emit a dtor.
  if (StmtList.empty()) {
    return nullptr;
  }

  clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);

  FD->setBody(CS);
  // We need some way to tell if this FD is generated by slang
  FD->setImplicit();

  return FD;
}

bool HasRSObjectType(const clang::Type *T) {
  return CountRSObjectTypes(T) != 0;
}

}  // namespace slang
