/*
 * Copyright 2015, 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 "bcc/Assert.h"
#include "bcc/Renderscript/RSTransforms.h"
#include "bcc/Support/Log.h"
#include "bcinfo/MetadataExtractor.h"

#include <llvm/Pass.h>
#include <llvm/IR/DIBuilder.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/InstIterator.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Module.h>

namespace {

const char DEBUG_SOURCE_PATH[] = "/opt/renderscriptdebugger/1";
const char DEBUG_GENERATED_FILE[] = "generated.rs";
const char DEBUG_PROTOTYPE_VAR_NAME[] = "rsDebugOuterForeachT";
const char DEBUG_COMPILE_UNIT_MDNAME[] = "llvm.dbg.cu";

/*
 * LLVM pass to attach debug information to the bits of code
 * generated by the compiler.
 */
class RSAddDebugInfoPass : public llvm::ModulePass {

public:
  // Pass ID
  static char ID;

  RSAddDebugInfoPass() : ModulePass(ID), kernelTypeMD(nullptr),
      sourceFileName(nullptr), emptyExpr(nullptr), abiMetaCU(nullptr),
      indexVarType(nullptr) {
  }

  virtual bool runOnModule(llvm::Module &Module) {
    // Gather information about this bcc module.
    bcinfo::MetadataExtractor me(&Module);
    if (!me.extract()) {
      ALOGE("Could not extract metadata from module!");
      return false;
    }

    size_t nForEachKernels = me.getExportForEachSignatureCount();
    const char **forEachKernels = me.getExportForEachNameList();

    // Set up the debug info builder.
    llvm::DIBuilder DebugInfo(Module);

    initializeDebugInfo(DebugInfo, Module);

    // Attach DI metadata to each generated function.
    for (size_t i = 0; i < nForEachKernels; ++i) {
      std::string expandedName = forEachKernels[i];
      expandedName += ".expand";

      if (llvm::Function *kernelFunc = Module.getFunction(expandedName))
        attachDebugInfo(DebugInfo, *kernelFunc);
    }

    DebugInfo.finalize();

    cleanupDebugInfo(Module);

    return true;
  }

private:

  // @brief Initialize the debug info generation.
  //
  // This method does a couple of things:
  // * Look up debug metadata for kernel ABI and store it if present.
  // * Store a couple of useful pieces of debug metadata in member
  //   variables so they do not have to be created multiple times.
  void initializeDebugInfo(llvm::DIBuilder &DebugInfo,
                           const llvm::Module &Module) {
    llvm::LLVMContext &ctx = Module.getContext();

    // Start generating debug information for bcc-generated code.
    DebugInfo.createCompileUnit(llvm::dwarf::DW_LANG_GOOGLE_RenderScript,
                                DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH,
                                "RS", false, "", 0);

    // Pre-generate and save useful pieces of debug metadata.
    sourceFileName = DebugInfo.createFile(DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH);
    emptyExpr = DebugInfo.createExpression();

    // Lookup compile unit with kernel ABI debug metadata.
    llvm::NamedMDNode *mdCompileUnitList =
        Module.getNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
    bccAssert(mdCompileUnitList != nullptr &&
        "DebugInfo pass could not find any existing compile units.");

    llvm::DIGlobalVariable *kernelPrototypeVarMD = nullptr;
    for (llvm::MDNode* CUNode : mdCompileUnitList->operands()) {
      if (auto *CU = llvm::dyn_cast<llvm::DICompileUnit>(CUNode)) {
        for (llvm::DIGlobalVariable* GV : CU->getGlobalVariables()) {
          if (GV->getDisplayName() == DEBUG_PROTOTYPE_VAR_NAME) {
            kernelPrototypeVarMD = GV;
            abiMetaCU = CU;
            break;
          }
        }
        if (kernelPrototypeVarMD != nullptr)
          break;
      }
    }

    // Lookup the expanded function interface type metadata.
    llvm::MDTuple *kernelPrototypeMD = nullptr;
    if (kernelPrototypeVarMD != nullptr) {
      // Dig into the metadata to look for function prototype.
      llvm::DIDerivedType *DT = nullptr;
      DT = llvm::cast<llvm::DIDerivedType>(kernelPrototypeVarMD->getType());
      DT = llvm::cast<llvm::DIDerivedType>(DT->getBaseType());
      llvm::DISubroutineType *ST = llvm::cast<llvm::DISubroutineType>(DT->getBaseType());
      kernelPrototypeMD = llvm::cast<llvm::MDTuple>(ST->getRawTypeArray());

      indexVarType = llvm::dyn_cast_or_null<llvm::DIType>(
          kernelPrototypeMD->getOperand(2));
    }
    // Fall back to the function type of void() if there is no proper debug info.
    if (kernelPrototypeMD == nullptr)
      kernelPrototypeMD = llvm::MDTuple::get(ctx, {nullptr});
    // Fall back to unspecified type if we don't have a proper index type.
    if (indexVarType == nullptr)
      indexVarType = DebugInfo.createBasicType("uint32_t", 32, 32,
          llvm::dwarf::DW_ATE_unsigned);

    // Capture the expanded kernel type debug info.
    kernelTypeMD = DebugInfo.createSubroutineType(kernelPrototypeMD);
  }

  /// @brief Add debug information to a generated function.
  ///
  /// This procedure adds the following pieces of debug information
  /// to the function specified by Func:
  /// * Entry for the function to the current compile unit.
  /// * Adds debug info entries for each function argument.
  /// * Adds debug info entry for the rsIndex local variable.
  /// * File/line information to each instruction set to generates.rs:1.
  void attachDebugInfo(llvm::DIBuilder &DebugInfo, llvm::Function &Func) {
    // Lookup the current thread coordinate variable.
    llvm::AllocaInst* indexVar = nullptr;
    for (llvm::Instruction &inst : llvm::instructions(Func)) {
      if (auto *allocaInst = llvm::dyn_cast<llvm::AllocaInst>(&inst)) {
        if (allocaInst->getName() == bcc::BCC_INDEX_VAR_NAME) {
          indexVar = allocaInst;
          break;
        }
      }
    }

    // Create function-level debug metadata.
    llvm::DISubprogram *ExpandedFunc = DebugInfo.createFunction(
        sourceFileName, // scope
        Func.getName(), Func.getName(),
        sourceFileName, 1, kernelTypeMD,
        false, true, 1, 0, false
    );
    Func.setSubprogram(ExpandedFunc);

    // IRBuilder for allocating variables for arguments.
    llvm::IRBuilder<> ir(&*Func.getEntryBlock().begin());

    // Walk through the argument list and expanded function prototype
    // debuginfo in lockstep to create debug entries for
    // the expanded function arguments.
    unsigned argIdx = 1;
    llvm::MDTuple *argTypes = kernelTypeMD->getTypeArray().get();
    for (llvm::Argument &arg : Func.getArgumentList()) {
      // Stop processing arguments if we run out of debug info.
      if (argIdx >= argTypes->getNumOperands())
        break;

      // Create debuginfo entry for the argument and advance.
      llvm::DILocalVariable *argVarDI = DebugInfo.createParameterVariable(
          ExpandedFunc, arg.getName(), argIdx, sourceFileName, 1,
          llvm::cast<llvm::DIType>(argTypes->getOperand(argIdx).get()),
          true, 0
      );

      // Annotate the argument variable in the IR.
      llvm::AllocaInst *argVar =
          ir.CreateAlloca(arg.getType(), nullptr, arg.getName() + ".var");
      llvm::StoreInst *argStore = ir.CreateStore(&arg, argVar);
      llvm::LoadInst *loadedVar = ir.CreateLoad(argVar, arg.getName() + ".l");
      DebugInfo.insertDeclare(argVar, argVarDI, emptyExpr,
          llvm::DebugLoc::get(1, 1, ExpandedFunc), loadedVar);
      for (llvm::Use &u : arg.uses())
        if (u.getUser() != argStore)
          u.set(loadedVar);
      argIdx++;
    }

    // Annotate the index variable with metadata.
    if (indexVar) {
      // Debug information for loop index variable.
      llvm::DILocalVariable *indexVarDI = DebugInfo.createAutoVariable(
          ExpandedFunc, bcc::BCC_INDEX_VAR_NAME, sourceFileName, 1,
          indexVarType, true
      );

      // Insert declaration annotation in the instruction stream.
      llvm::Instruction *decl = DebugInfo.insertDeclare(
          indexVar, indexVarDI, emptyExpr,
          llvm::DebugLoc::get(1, 1, ExpandedFunc), indexVar);
      indexVar->moveBefore(decl);
    }

    // Attach location information to each instruction in the function.
    for (llvm::Instruction &inst : llvm::instructions(Func)) {
      inst.setDebugLoc(llvm::DebugLoc::get(1, 1, ExpandedFunc));
    }
  }

  // @brief Clean up the debug info.
  //
  // At the moment, it only finds the compile unit for the expanded function
  // metadata generated by clang and removes it.
  void cleanupDebugInfo(llvm::Module& Module) {
    if (abiMetaCU == nullptr)
      return;

    // Remove the compile unit with the runtime interface DI.
    llvm::SmallVector<llvm::MDNode*, 4> unitsTmp;
    llvm::NamedMDNode *debugMD =
        Module.getNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
    for (llvm::MDNode *cu : debugMD->operands())
      if (cu != abiMetaCU)
        unitsTmp.push_back(cu);
    debugMD->eraseFromParent();
    debugMD = Module.getOrInsertNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
    for (llvm::MDNode *cu : unitsTmp)
      debugMD->addOperand(cu);
  }

private:
  // private attributes
  llvm::DISubroutineType* kernelTypeMD;
  llvm::DIFile *sourceFileName;
  llvm::DIExpression *emptyExpr;
  llvm::DICompileUnit *abiMetaCU;
  llvm::DIType *indexVarType;

}; // end class RSAddDebugInfoPass

char RSAddDebugInfoPass::ID = 0;
static llvm::RegisterPass<RSAddDebugInfoPass> X("addrsdi", "Add RS DebugInfo Pass");

} // end anonymous namespace

namespace bcc {

llvm::ModulePass * createRSAddDebugInfoPass() {
  return new RSAddDebugInfoPass();
}

} // end namespace bcc
