//===-- go-llvm-dibuildhelper.cpp - implementation of DIBuildHelper -------===//
//
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
//===----------------------------------------------------------------------===//
//
// Methods for DIBuildHelper class.
//
//===----------------------------------------------------------------------===//

#include "go-llvm-dibuildhelper.h"
#include "go-llvm-typemanager.h"
#include "go-llvm-bexpression.h"
#include "go-llvm-bstatement.h"
#include "go-llvm-bfunction.h"
#include "go-llvm-bvariable.h"

#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"

DIBuildHelper::DIBuildHelper(llvm::Module *module,
                             TypeManager *typemanager,
                             Llvm_linemap *linemap)
    : module_(module), typemanager_(typemanager), linemap_(linemap), moduleScope_(nullptr),
      dibuilder_(new llvm::DIBuilder(*module)), topblock_(nullptr),
      entryBlock_(nullptr), known_locations_(0)
{
}

void DIBuildHelper::createCompileUnitIfNeeded()
{
  if (moduleScope_)
    return;

  // Create compile unit
  llvm::SmallString<256> currentDir;
  llvm::sys::fs::current_path(currentDir);
  std::string filestr = applyDebugPrefix(linemap_->get_initial_file());
  auto primaryFile = dibuilder_->createFile(filestr, currentDir);
  bool isOptimized = true;
  std::string compileFlags; // FIXME
  unsigned runtimeVersion = 0; // not sure what would be for Go
  moduleScope_ =
      dibuilder_->createCompileUnit(llvm::dwarf::DW_LANG_Go, primaryFile,
                                    "llvm-goc", isOptimized,
                                    compileFlags, runtimeVersion);
  pushDIScope(moduleScope_);

  module_->addModuleFlag(llvm::Module::Warning, "Debug Info Version",
                         llvm::DEBUG_METADATA_VERSION);
  module_->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 4);
}

void DIBuildHelper::finalize()
{
  createCompileUnitIfNeeded();

  // Emit any globals we've collected along the way.
  for (auto it : globalsToProcess_) {
    Bvariable *v = it.first;
    bool isExported = it.second;
    llvm::DIFile *vfile = diFileFromLocation(v->location());
    unsigned vline = linemap()->location_line(v->location());
    llvm::DIType *vdit = typemanager()->buildDIType(v->btype(), *this);
    bool isLocalToUnit = !isExported;
    dibuilder().createGlobalVariableExpression(moduleScope_,
                                               v->name(), v->name(),
                                               vfile, vline, vdit,
                                               isLocalToUnit);
  }

  dibuilder_->finalize();
}



void DIBuildHelper::processGlobal(Bvariable *v, bool isExported)
{
  globalsToProcess_.push_back(std::make_pair(v, isExported));
}

void DIBuildHelper::beginFunction(Bfunction *function,
                                  Bnode *topnode,
                                  llvm::BasicBlock *entryBlock)
{
  createCompileUnitIfNeeded();

  assert(entryBlock_ == nullptr);
  assert(entryBlock != nullptr);
  entryBlock_ = entryBlock;

  assert(topblock_ == nullptr);
  assert(topnode->castToBblock());
  topblock_ = topnode->castToBblock();

  known_locations_ = 0;

  // Create proper DIType for function
  llvm::DIType *dit =
      typemanager()->buildDIType(function->fcnType(), *this);
  llvm::DISubroutineType *dst =
      llvm::cast<llvm::DISubroutineType>(dit);

  // Now the function entry itself
  unsigned fcnLine = linemap()->location_line(function->location());
  bool isLocalToUnit = !function->function()->hasExternalLinkage();
  unsigned scopeLine = fcnLine; // FIXME -- determine correct value here
  llvm::DIFile *difile = diFileFromLocation(function->location());
  llvm::DINode::DIFlags flags = llvm::DINode::FlagZero;
  llvm::DISubprogram::DISPFlags spflags = llvm::DISubprogram::SPFlagDefinition;
  if (isLocalToUnit)
    spflags |= llvm::DISubprogram::SPFlagLocalToUnit;
  auto difunc =
      dibuilder().createFunction(moduleScope(), function->name(),
                                 isLocalToUnit ? "" : function->asmName(),
                                 difile, fcnLine, dst, scopeLine, flags,
                                 spflags);
  pushDIScope(difunc);
}

void DIBuildHelper::processVarsInBLock(const std::vector<Bvariable*> &vars,
                                       llvm::DIScope *scope)
{
  for (auto &v : vars) {
    if (v->isTemporary())
      continue;
    if (declared_.find(v) != declared_.end())
      continue;
    declared_.insert(v);

    llvm::DIFile *vfile = diFileFromLocation(v->location());
    llvm::DIType *vdit =
        typemanager()->buildDIType(v->btype(), *this);
    unsigned vline = linemap()->location_line(v->location());
    llvm::DILocalVariable *dilv =
        dibuilder().createAutoVariable(scope, v->name(), vfile, vline, vdit);
    insertVarDecl(v, dilv);
  }
}

void DIBuildHelper::insertVarDecl(Bvariable *var,
                                  llvm::DILocalVariable *dilv)
{
  llvm::DIExpression *expr = dibuilder().createExpression();
  llvm::DILocation *vloc = debugLocFromLocation(var->location());

  // Don't emit declaration for dead variable.
  if(var->initializer() && !var->initializerInstruction()->getParent())
    return;

  // Create the declare instruction, giving it an initial position at
  // the end of the entry block (the insertDeclare call below doesn't
  // allow a NULL insert location, so we pick end-of-block arbitrarily).
  assert(entryBlock_);
  llvm::Instruction *decl =
      dibuilder().insertDeclare(var->value(), dilv, expr, vloc, entryBlock_);
  decl->removeFromParent();

  // Extract the decl from the end of the entry block and reposition
  // it according to the var properties.
  llvm::Instruction *insertionPoint = nullptr;
  if (var->initializer()) {
    assert(var->initializerInstruction()->getParent());
    insertionPoint = var->initializerInstruction();
  } else if (var->flavor() == ParamVar) {
    // parameters passing by reference may have no initializers.
    // declare them at function entry.
    entryBlock_->getInstList().push_front(decl);
    return;
  } else {
    // locals with no initializer should only be zero-sized vars.
    // make them available immediately after their alloca.
    assert(typemanager()->typeSize(var->btype()) == 0);
    llvm::Instruction *alloca = llvm::cast<llvm::Instruction>(var->value());
    insertionPoint = alloca;
  }

  assert(! llvm::isa<llvm::BranchInst>(insertionPoint));
  assert(insertionPoint != insertionPoint->getParent()->getTerminator());
  decl->insertAfter(insertionPoint);
}

void DIBuildHelper::endFunction(Bfunction *function)
{
  cleanFileScope();
  llvm::DISubprogram *fscope = llvm::cast<llvm::DISubprogram>(currentDIScope());

  // Create debug meta-data for parameter variables.
  unsigned argIdx = 0;
  for (auto &v : function->getParameterVars()) {
    llvm::DIFile *vfile = diFileFromLocation(v->location());
    llvm::DIType *vdit =
        typemanager()->buildDIType(v->btype(), *this);
    unsigned vline = linemap()->location_line(v->location());
    llvm::DILocalVariable *dilv =
        dibuilder().createParameterVariable(fscope, v->name(), ++argIdx,
                                            vfile, vline, vdit);
    insertVarDecl(v, dilv);
  }

  // Create debug meta-data for local variables. We wait to do this
  // here so as to insure that the initializer instructions for the
  // variables have been assigned to a basic block. Note that
  // block-scoped locals (as opposed to function-scoped locals) will
  // already have been processed at this point.
  processVarsInBLock(function->getFunctionLocalVars(), fscope);

  // If a given function has no debug locations at all, then don't
  // try to mark it as having debug info (without doing this we can
  // wind up having functions flagged as problematic by the verifier).
  if (known_locations_)
    function->function()->setSubprogram(fscope);

  // Done with this scope
  cleanFileScope();
  popDIScope();
  assert(diScopeStack_.size() == 1);

  // Clean up
  entryBlock_ = nullptr;
  topblock_ = nullptr;
  known_locations_ = 0;
  declared_.clear();
}

// Front end tends to declare more blocks than strictly required for
// debug generation purposes, so here we examine each block to see
// whether it makes sense to generate a DWARF lexical scope record for
// it. In particular, we look for blocks containing no user-visible
// variables (these can be omitted).
//
// Return TRUE if this is an interesting block (needs DWARF scope) or
// FALSE otherwise.

bool DIBuildHelper::interestingBlock(Bblock *block)
{
  assert(block);
  bool foundInteresting = false;
  for (auto &v : block->vars()) {
    if (! v->isTemporary()) {
      foundInteresting = true;
      break;
    }
  }
  return foundInteresting;
}

void DIBuildHelper::beginLexicalBlock(Bblock *block)
{
  if (! interestingBlock(block) || block == topblock_)
    return;

  // Register block with DIBuilder
  Location bloc = block->location();
  llvm::DIFile *file = diFileFromLocation(block->location());
  llvm::DILexicalBlock *dilb =
      dibuilder().createLexicalBlock(currentDIScope(), file,
                                     linemap()->location_line(bloc),
                                     linemap()->location_column(bloc));
  pushDIScope(dilb);
}

void DIBuildHelper::endLexicalBlock(Bblock *block)
{
  if (! interestingBlock(block))
    return;

  cleanFileScope();

  // In the case of the top block, we still want to process any local
  // variables it contains, but we'll want to insure that they are
  // parented by the function itself.
  //
  llvm::DIScope *scope =
      (block == topblock_ ? currentDIScope() : popDIScope());

  processVarsInBLock(block->vars(), scope);
}

void DIBuildHelper::processExprInst(Bstatement *stmt,
                                    Bexpression *expr,
                                    llvm::Instruction *inst)
{
  Location loc = expr->location();
  if (linemap()->is_unknown(loc)) {
    Location sloc = stmt->location();
    if (!linemap()->is_unknown(sloc))
      loc = sloc;
  }
  if (! linemap()->is_unknown(loc)) {
    known_locations_ += 1;
    inst->setDebugLoc(debugLocFromLocation(loc));
  }
}

void DIBuildHelper::addDebugPrefix(std::pair<llvm::StringRef, llvm::StringRef> pref)
{
  std::string from(pref.first);
  std::string to(pref.second);
  debugPrefixMap_[from] = to;
}

std::string DIBuildHelper::applyDebugPrefix(llvm::StringRef path) {
  for (const auto &remap : debugPrefixMap_)
    if (path.startswith(remap.first))
      return (llvm::Twine(remap.second) +
              path.substr(remap.first.size())).str();
  return path.str();
}

llvm::DIFile *DIBuildHelper::diFileFromLocation(Location location)
{
  std::string locfile = applyDebugPrefix(linemap()->location_file(location));
  llvm::StringRef locdir = llvm::sys::path::parent_path(locfile);
  llvm::StringRef locfilename = llvm::sys::path::filename(locfile);
  if (linemap()->is_predeclared(location))
    locdir = "";
  return dibuilder().createFile(locfilename, locdir);
}

llvm::DebugLoc DIBuildHelper::debugLocFromLocation(Location loc)
{
  llvm::LLVMContext &context = typemanager()->context();

  // In the (somewhat unusual) case of a file/line directive, create a new
  // pseudo-scope to capture the fact that the file has changed. Pop off
  // any previously created file scope prior to doing this.
  llvm::DIFile *curFile = currentDIScope()->getFile();
  llvm::DIFile *locFile = diFileFromLocation(loc);
  if (curFile != locFile) {
    cleanFileScope();
    llvm::DILexicalBlockFile *dilbf =
        dibuilder().createLexicalBlockFile(currentDIScope(), locFile);
    pushDIScope(dilbf);
  }

  return llvm::DILocation::get(context, linemap()->location_line(loc),
                               linemap()->location_column(loc),
                               currentDIScope());
}

llvm::DIScope *DIBuildHelper::currentDIScope()
{
  assert(diScopeStack_.size());
  return diScopeStack_.back();
}

llvm::DIScope *DIBuildHelper::popDIScope()
{
  assert(diScopeStack_.size());
  llvm::DIScope *popped = diScopeStack_.back();
  diScopeStack_.pop_back();
  return popped;
}

void DIBuildHelper::pushDIScope(llvm::DIScope *scope)
{
  assert(scope);
  diScopeStack_.push_back(scope);
}

void DIBuildHelper::cleanFileScope()
{
  assert(diScopeStack_.size());
  if (llvm::dyn_cast<llvm::DILexicalBlockFile>(diScopeStack_.back()) != nullptr)
    diScopeStack_.pop_back();
}
