/*
 * 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.
 */

#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_  // NOLINT
#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_

#include <list>
#include <stack>

#include "clang/AST/StmtVisitor.h"

#include "slang_assert.h"
#include "slang_rs_export_type.h"

namespace clang {
  class Expr;
  class Stmt;
}

namespace slang {

// This class provides the overall reference counting mechanism for handling
// local variables of RS object types (rs_font, rs_allocation, ...). This
// class ensures that appropriate functions (rsSetObject, rsClearObject) are
// called at proper points in the object's lifetime.
// 1) Each local object of appropriate type must be zero-initialized (to
// prevent corruption) during subsequent rsSetObject()/rsClearObject() calls.
// 2) Assignments using these types must also be converted into the
// appropriate (possibly a series of) rsSetObject() calls.
// 3) Finally, each local object must call rsClearObject() when it goes out
// of scope.
class RSObjectRefCount : public clang::StmtVisitor<RSObjectRefCount> {
 private:
  class Scope {
   private:
    clang::CompoundStmt *mCS;      // Associated compound statement ({ ... })
    std::list<clang::VarDecl*> mRSO;  // Declared RS objects in this scope

   public:
    explicit Scope(clang::CompoundStmt *CS) : mCS(CS) {
    }

    inline void addRSObject(clang::VarDecl* VD) {
      mRSO.push_back(VD);
    }

    void ReplaceRSObjectAssignment(clang::BinaryOperator *AS);

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

    void InsertLocalVarDestructors();

    static clang::Stmt *ClearRSObject(clang::VarDecl *VD,
                                      clang::DeclContext *DC);
  };

  clang::ASTContext &mCtx;
  std::stack<Scope*> mScopeStack;
  bool RSInitFD;

  // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject()
  // and rsClearObject() in the current ASTContext.
  static clang::FunctionDecl *RSSetObjectFD[];
  static clang::FunctionDecl *RSClearObjectFD[];

  inline Scope *getCurrentScope() {
    return mScopeStack.top();
  }

  // Initialize RSSetObjectFD and RSClearObjectFD.
  static void GetRSRefCountingFunctions(clang::ASTContext &C);

  // Return false if the type of variable declared in VD does not contain
  // an RS object type.
  static bool InitializeRSObject(clang::VarDecl *VD,
                                 DataType *DT,
                                 clang::Expr **InitExpr);

  // Return a zero-initializer expr of the type DT. This processes both
  // RS matrix type and RS object type.
  static clang::Expr *CreateZeroInitializerForRSSpecificType(
      DataType DT,
      clang::ASTContext &C,
      const clang::SourceLocation &Loc);

 public:
  explicit RSObjectRefCount(clang::ASTContext &C)
      : mCtx(C),
        RSInitFD(false) {
  }

  void Init() {
    if (!RSInitFD) {
      GetRSRefCountingFunctions(mCtx);
      RSInitFD = true;
    }
  }

  static clang::FunctionDecl *GetRSSetObjectFD(DataType DT) {
    slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
    if (DT >= 0 && DT < DataTypeMax) {
      return RSSetObjectFD[DT];
    } else {
      slangAssert(false && "incorrect type");
      return nullptr;
    }
  }

  static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) {
    return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
  }

  static clang::FunctionDecl *GetRSClearObjectFD(DataType DT) {
    slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
    if (DT >= 0 && DT < DataTypeMax) {
      return RSClearObjectFD[DT];
    } else {
      slangAssert(false && "incorrect type");
      return nullptr;
    }
  }

  static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) {
    return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
  }

  void VisitStmt(clang::Stmt *S);
  void VisitDeclStmt(clang::DeclStmt *DS);
  void VisitCompoundStmt(clang::CompoundStmt *CS);
  void VisitBinAssign(clang::BinaryOperator *AS);
  // We believe that RS objects are never involved in CompoundAssignOperator.
  // I.e., rs_allocation foo; foo += bar;

  // Emit a global destructor to clean up RS objects.
  clang::FunctionDecl *CreateStaticGlobalDtor();
};

}  // namespace slang

#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_  NOLINT
