/*
 * Copyright 2010-2012, 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_context.h"

#include <string>

#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/Type.h"

#include "clang/Basic/Linkage.h"
#include "clang/Basic/TargetInfo.h"

#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/DataLayout.h"

#include "slang.h"
#include "slang_assert.h"
#include "slang_backend.h"
#include "slang_rs_export_foreach.h"
#include "slang_rs_export_func.h"
#include "slang_rs_export_reduce.h"
#include "slang_rs_export_type.h"
#include "slang_rs_export_var.h"
#include "slang_rs_exportable.h"
#include "slang_rs_pragma_handler.h"
#include "slang_rs_reflection.h"
#include "slang_rs_special_func.h"

namespace slang {

RSContext::RSContext(clang::Preprocessor &PP,
                     clang::ASTContext &Ctx,
                     const clang::TargetInfo &Target,
                     PragmaList *Pragmas,
                     unsigned int TargetAPI,
                     bool Verbose)
    : mPP(PP),
      mCtx(Ctx),
      mPragmas(Pragmas),
      mTargetAPI(TargetAPI),
      mVerbose(Verbose),
      mDataLayout(Target.getDataLayout()),
      mLLVMContext(slang::getGlobalLLVMContext()),
      mLicenseNote(nullptr),
      mRSPackageName("android.renderscript"),
      version(0),
      mMangleCtx(Ctx.createMangleContext()),
      mIs64Bit(Target.getPointerWidth(0) == 64),
      mNextSlot(1),
      mNextForEachOrdinal(0) {

  AddPragmaHandlers(PP, this);

  // Prepare target data
  // mDataLayout = Target.getDataLayout();

  // Reserve slot 0 for the root kernel.
  mExportForEach.push_back(nullptr);
  mFirstOldStyleKernel = mExportForEach.end();
}

bool RSContext::processExportVar(const clang::VarDecl *VD) {
  slangAssert(!VD->getName().empty() && "Variable name should not be empty");

  RSExportType *ET = RSExportType::CreateFromDecl(this, VD);
  if (!ET)
    return false;

  RSExportVar *EV = new RSExportVar(this, VD, ET);
  if (EV == nullptr)
    return false;
  else
    mExportVars.push_back(EV);

  return true;
}

int RSContext::getForEachSlotNumber(const clang::FunctionDecl* FD) {
  const clang::StringRef& funcName = FD->getName();
  return getForEachSlotNumber(funcName);
}

int RSContext::getForEachSlotNumber(const clang::StringRef& funcName) {
  auto it = mExportForEachMap.find(funcName);
  if (it == mExportForEachMap.end()) {
    return -1;
  }
  return it->second;
}

bool RSContext::processExportFunc(const clang::FunctionDecl *FD) {
  slangAssert(!FD->getName().empty() && "Function name should not be empty");

  if (!FD->isThisDeclarationADefinition()) {
    return true;
  }

  slangAssert(FD->getStorageClass() == clang::SC_None);

  // Specialized function
  if (RSSpecialFunc::isSpecialRSFunc(mTargetAPI, FD)) {
    // Do not reflect specialized functions like init, dtor, or graphics root.
    return RSSpecialFunc::validateSpecialFuncDecl(mTargetAPI, this, FD);
  }

  // Foreach kernel
  if (RSExportForEach::isRSForEachFunc(mTargetAPI, FD)) {
    RSExportForEach *EFE = RSExportForEach::Create(this, FD);
    if (EFE == nullptr) {
      return false;
    }

    // The root function should be at index 0 in the list
    if (FD->getName().equals("root")) {
      mExportForEach[0] = EFE;
      return true;
    }

    // New-style kernels with attribute "kernel" should come first in the list
    if (FD->hasAttr<clang::RenderScriptKernelAttr>()) {
      mFirstOldStyleKernel = mExportForEach.insert(mFirstOldStyleKernel, EFE) + 1;
      slangAssert((mTargetAPI < SLANG_FEATURE_SINGLE_SOURCE_API ||
                   getForEachSlotNumber(FD->getName()) ==
                   mFirstOldStyleKernel - mExportForEach.begin() - 1) &&
                  "Inconsistent slot number assignment");
      return true;
    }

    // Old-style kernels should appear in the end of the list
    mFirstOldStyleKernel = mExportForEach.insert(mFirstOldStyleKernel, EFE);
    return true;
  }

  // Invokable
  if (auto *EF = RSExportFunc::Create(this, FD)) {
    mExportFuncs.push_back(EF);
    return true;
  }

  return false;
}

bool RSContext::addForEach(const clang::FunctionDecl* FD) {
  const llvm::StringRef& funcName = FD->getName();

  if (funcName.equals("root")) {
    // The root kernel should always be in slot 0.
    mExportForEachMap.insert(std::make_pair(funcName, 0));
  } else {
    mExportForEachMap.insert(std::make_pair(funcName, mNextSlot++));
  }

  return true;
}

bool RSContext::processExportType(const llvm::StringRef &Name) {
  clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();

  slangAssert(TUDecl != nullptr && "Translation unit declaration (top-level "
                                   "declaration) is null object");

  const clang::IdentifierInfo *II = mPP.getIdentifierInfo(Name);
  if (II == nullptr)
    // TODO(zonr): alert identifier @Name mark as an exportable type cannot be
    //             found
    return false;

  clang::DeclContext::lookup_result R = TUDecl->lookup(II);
  RSExportType *ET = nullptr;

  for (clang::DeclContext::lookup_iterator I = R.begin(), E = R.end();
       I != E;
       I++) {
    clang::NamedDecl *const ND = *I;
    const clang::Type *T = nullptr;

    switch (ND->getKind()) {
      case clang::Decl::Typedef: {
        T = static_cast<const clang::TypedefDecl*>(
            ND)->getCanonicalDecl()->getUnderlyingType().getTypePtr();
        break;
      }
      case clang::Decl::Record: {
        T = static_cast<const clang::RecordDecl*>(ND)->getTypeForDecl();
        break;
      }
      default: {
        // unsupported, skip
        break;
      }
    }

    if (T != nullptr)
      ET = RSExportType::Create(this, T, NotLegacyKernelArgument);
  }

  return (ET != nullptr);
}

void RSContext::setAllocationType(const clang::TypeDecl* TD) {
  mAllocationType = mCtx.getTypeDeclType(TD);
}

void RSContext::setScriptCallType(const clang::TypeDecl* TD) {
  mScriptCallType = mCtx.getTypeDeclType(TD);
}

bool RSContext::processExports() {
  bool valid = true;

  if (getDiagnostics()->hasErrorOccurred()) {
    return false;
  }

  clang::TranslationUnitDecl *TUDecl = mCtx.getTranslationUnitDecl();
  for (auto I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; I++) {
    clang::Decl* D = *I;
    switch (D->getKind()) {
    case clang::Decl::Var: {
      clang::VarDecl* VD = llvm::cast<clang::VarDecl>(D);
      bool ShouldExportVariable = true;
      if (VD->getFormalLinkage() == clang::ExternalLinkage) {
        clang::QualType QT = VD->getTypeSourceInfo()->getType();
        if (QT.isConstQualified() && !VD->hasInit()) {
          if (Slang::IsLocInRSHeaderFile(VD->getLocation(),
                                         *getSourceManager())) {
            // We don't export variables internal to the runtime's
            // implementation.
            ShouldExportVariable = false;
          } else {
            clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
            DiagEngine->Report(VD->getLocation(), DiagEngine->getCustomDiagID(
                clang::DiagnosticsEngine::Error,
                "invalid declaration of uninitialized constant variable '%0'"))
              << VD->getName();
            valid = false;
          }
        }
        if (valid && ShouldExportVariable && isSyntheticName(VD->getName()))
          ShouldExportVariable = false;
        if (valid && ShouldExportVariable && !processExportVar(VD)) {
          valid = false;
        }
      }
      break;
    }
    case clang::Decl::Function: {
      clang::FunctionDecl* FD = llvm::cast<clang::FunctionDecl>(D);
      if (FD->getFormalLinkage() == clang::ExternalLinkage) {
        if (!processExportFunc(FD)) {
          valid = false;
        }
      }
      break;
    }
    default:
      break;
    }
  }

  // Create a placeholder root in slot 0 if a root kernel is not seen
  // and there exists a non-root kernel.
  if (valid && mExportForEach[0] == nullptr) {
    const size_t numExportedForEach = mExportForEach.size();
    if (numExportedForEach > 1) {
      mExportForEach[0] = RSExportForEach::CreateDummyRoot(this);
    } else {
      slangAssert(numExportedForEach == 1);
      mExportForEach.pop_back();
    }
  }

  // Finally, export type forcely set to be exported by user
  for (NeedExportTypeSet::const_iterator EI = mNeedExportTypes.begin(),
           EE = mNeedExportTypes.end();
       EI != EE;
       EI++) {
    if (!processExportType(EI->getKey())) {
      valid = false;
    }
  }

  return valid;
}

bool RSContext::processReducePragmas(Backend *BE) {
  // This is needed to ensure that the placeholder variable is emitted into
  // the bitcode -- which in turn forces the function to be emitted
  // into the bitcode.  We couldn't do this at
  // markUsedByReducePragma() time because we had to wait until the
  // Backend is available.
  for (auto DummyVar : mUsedByReducePragmaDummyVars)
    BE->HandleTopLevelDecl(clang::DeclGroupRef(DummyVar));

  bool valid = true;
  for (auto I = export_reduce_begin(), E = export_reduce_end(); I != E; ++I) {
    if (! (*I)->analyzeTranslationUnit())
      valid = false;
  }
  return valid;
}

void RSContext::markUsedByReducePragma(clang::FunctionDecl *FD, CheckName Check) {
  if (mUsedByReducePragmaFns.find(FD) != mUsedByReducePragmaFns.end())
    return;  // already marked used

  if (Check == CheckNameYes) {
    // This is an inefficient linear search.  If this turns out to be a
    // problem in practice, then processReducePragmas() could build a
    // set or hash table or something similar containing all function
    // names mentioned in a reduce pragma and searchable in O(c) or
    // O(log(n)) time rather than the currently-implemented O(n) search.
    auto NameMatches = [this, FD]() {
      for (auto I = export_reduce_begin(), E = export_reduce_end(); I != E; ++I) {
        if ((*I)->matchName(FD->getName()))
          return true;
      }
      return false;
    };
    if (!NameMatches())
      return;
  }

  mUsedByReducePragmaFns.insert(FD);

  // This is needed to prevent clang from warning that the function is
  // unused (in the case where it is only referenced by #pragma rs
  // reduce).
  FD->setIsUsed();

  // Each constituent function "f" of a reduction kernel gets a placeholder variable generated for it:
  //   void *.rs.reduce_fn.f = (void*)&f;
  // This is a trick to ensure that clang will not delete "f" as unused.

  // `-VarDecl 0x87cb558 <line:3:1, col:30> col:7 var 'void *' cinit
  //     `-CStyleCastExpr 0x87cb630 <col:19, col:26> 'void *' <BitCast>
  //       `-ImplicitCastExpr 0x87cb618 <col:26> 'void (*)(int *, float, double)' <FunctionToPointerDecay>
  //         `-DeclRefExpr 0x87cb5b8 <col:26> 'void (int *, float, double)' Function 0x8784e10 'foo' 'void (int *, float, double)

  const clang::QualType VoidPtrType = mCtx.getPointerType(mCtx.VoidTy);

  clang::DeclContext *const DC = FD->getDeclContext();
  const clang::SourceLocation Loc = FD->getLocation();

  clang::VarDecl *const VD = clang::VarDecl::Create(
      mCtx, DC, Loc, Loc,
      &mCtx.Idents.get(std::string(".rs.reduce_fn.") + FD->getNameAsString()),
      VoidPtrType,
      mCtx.getTrivialTypeSourceInfo(VoidPtrType),
      clang::SC_None);
  VD->setLexicalDeclContext(DC);
  DC->addDecl(VD);

  clang::DeclRefExpr *const DRE = clang::DeclRefExpr::Create(mCtx,
                                                             clang::NestedNameSpecifierLoc(),
                                                             Loc,
                                                             FD, false, Loc, FD->getType(),
                                                             clang::VK_RValue);
  clang::ImplicitCastExpr *const ICE = clang::ImplicitCastExpr::Create(mCtx, mCtx.getPointerType(FD->getType()),
                                                                       clang::CK_FunctionToPointerDecay, DRE,
                                                                       nullptr, clang::VK_RValue);
  clang::CStyleCastExpr *const CSCE = clang::CStyleCastExpr::Create(mCtx, VoidPtrType, clang::VK_RValue, clang::CK_BitCast,
                                                                    ICE, nullptr, nullptr,
                                                                    Loc, Loc);
  VD->setInit(CSCE);

  mUsedByReducePragmaDummyVars.push_back(VD);
}

bool RSContext::insertExportType(const llvm::StringRef &TypeName,
                                 RSExportType *ET) {
  ExportTypeMap::value_type *NewItem =
      ExportTypeMap::value_type::Create(TypeName,
                                        mExportTypes.getAllocator(),
                                        ET);

  if (mExportTypes.insert(NewItem)) {
    return true;
  } else {
    NewItem->Destroy(mExportTypes.getAllocator());
    return false;
  }
}

RSContext::~RSContext() {
  delete mLicenseNote;
  for (ExportableList::iterator I = mExportables.begin(),
          E = mExportables.end();
       I != E;
       I++) {
    if (!(*I)->isKeep())
      delete *I;
  }
}

}  // namespace slang
