/*
 * 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(nullptr),
      mLLVMContext(llvm::getGlobalContext()),
      mLicenseNote(nullptr),
      mRSPackageName("android.renderscript"),
      version(0),
      mMangleCtx(Ctx.createMangleContext()),
      mIs64Bit(Target.getPointerWidth(0) == 64),
      mNextSlot(1) {

  AddPragmaHandlers(PP, this);

  // Prepare target data
  mDataLayout = new llvm::DataLayout(Target.getDataLayoutString());

  // 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::KernelAttr>()) {
      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::dyn_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::dyn_cast<clang::FunctionDecl>(D);
      if (FD->getFormalLinkage() == clang::ExternalLinkage) {
        if (!processExportFunc(FD)) {
          valid = false;
        }
      }
      break;
    }
    default:
      break;
    }
  }

  // Create a dummy 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 dummy 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 dummy 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;
  delete mDataLayout;
  for (ExportableList::iterator I = mExportables.begin(),
          E = mExportables.end();
       I != E;
       I++) {
    if (!(*I)->isKeep())
      delete *I;
  }
}

}  // namespace slang
