//===--- DebugIR.cpp - Transform debug metadata to allow debugging IR -----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// A Module transform pass that emits a succinct version of the IR and replaces
// the source file metadata to allow debuggers to step through the IR.
//
// FIXME: instead of replacing debug metadata, this pass should allow for
// additional metadata to be used to point capable debuggers to the IR file
// without destroying the mapping to the original source file.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/ValueMap.h"
#include "DebugIR.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <string>

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

using namespace llvm;

#define DEBUG_TYPE "debug-ir"

namespace {

/// Builds a map of Value* to line numbers on which the Value appears in a
/// textual representation of the IR by plugging into the AssemblyWriter by
/// masquerading as an AssemblyAnnotationWriter.
class ValueToLineMap : public AssemblyAnnotationWriter {
  ValueMap<const Value *, unsigned int> Lines;
  typedef ValueMap<const Value *, unsigned int>::const_iterator LineIter;

  void addEntry(const Value *V, formatted_raw_ostream &Out) {
    Out.flush();
    Lines.insert(std::make_pair(V, Out.getLine() + 1));
  }

public:

  /// Prints Module to a null buffer in order to build the map of Value pointers
  /// to line numbers.
  ValueToLineMap(const Module *M) {
    raw_null_ostream ThrowAway;
    M->print(ThrowAway, this);
  }

  // This function is called after an Instruction, GlobalValue, or GlobalAlias
  // is printed.
  void printInfoComment(const Value &V, formatted_raw_ostream &Out) override {
    addEntry(&V, Out);
  }

  void emitFunctionAnnot(const Function *F,
                         formatted_raw_ostream &Out) override {
    addEntry(F, Out);
  }

  /// If V appears on a line in the textual IR representation, sets Line to the
  /// line number and returns true, otherwise returns false.
  bool getLine(const Value *V, unsigned int &Line) const {
    LineIter i = Lines.find(V);
    if (i != Lines.end()) {
      Line = i->second;
      return true;
    }
    return false;
  }
};

/// Removes debug intrisncs like llvm.dbg.declare and llvm.dbg.value.
class DebugIntrinsicsRemover : public InstVisitor<DebugIntrinsicsRemover> {
  void remove(Instruction &I) { I.eraseFromParent(); }

public:
  static void process(Module &M) {
    DebugIntrinsicsRemover Remover;
    Remover.visit(&M);
  }
  void visitDbgDeclareInst(DbgDeclareInst &I) { remove(I); }
  void visitDbgValueInst(DbgValueInst &I) { remove(I); }
  void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { remove(I); }
};

/// Removes debug metadata (!dbg) nodes from all instructions, and optionally
/// metadata named "llvm.dbg.cu" if RemoveNamedInfo is true.
class DebugMetadataRemover : public InstVisitor<DebugMetadataRemover> {
  bool RemoveNamedInfo;

public:
  static void process(Module &M, bool RemoveNamedInfo = true) {
    DebugMetadataRemover Remover(RemoveNamedInfo);
    Remover.run(&M);
  }

  DebugMetadataRemover(bool RemoveNamedInfo)
      : RemoveNamedInfo(RemoveNamedInfo) {}

  void visitInstruction(Instruction &I) {
    if (I.getMetadata(LLVMContext::MD_dbg))
      I.setMetadata(LLVMContext::MD_dbg, nullptr);
  }

  void run(Module *M) {
    // Remove debug metadata attached to instructions
    visit(M);

    if (RemoveNamedInfo) {
      // Remove CU named metadata (and all children nodes)
      NamedMDNode *Node = M->getNamedMetadata("llvm.dbg.cu");
      if (Node)
        M->eraseNamedMetadata(Node);
    }
  }
};

/// Updates debug metadata in a Module:
///   - changes Filename/Directory to values provided on construction
///   - adds/updates line number (DebugLoc) entries associated with each
///     instruction to reflect the instruction's location in an LLVM IR file
class DIUpdater : public InstVisitor<DIUpdater> {
  /// Builder of debug information
  DIBuilder Builder;

  /// Helper for type attributes/sizes/etc
  DataLayout Layout;

  /// Map of Value* to line numbers
  const ValueToLineMap LineTable;

  /// Map of Value* (in original Module) to Value* (in optional cloned Module)
  const ValueToValueMapTy *VMap;

  /// Directory of debug metadata
  DebugInfoFinder Finder;

  /// Source filename and directory
  StringRef Filename;
  StringRef Directory;

  // CU nodes needed when creating DI subprograms
  MDNode *FileNode;
  MDNode *LexicalBlockFileNode;
  const MDNode *CUNode;

  ValueMap<const Function *, MDNode *> SubprogramDescriptors;
  DenseMap<const Type *, MDNode *> TypeDescriptors;

public:
  DIUpdater(Module &M, StringRef Filename = StringRef(),
            StringRef Directory = StringRef(), const Module *DisplayM = nullptr,
            const ValueToValueMapTy *VMap = nullptr)
      : Builder(M), Layout(&M), LineTable(DisplayM ? DisplayM : &M), VMap(VMap),
        Finder(), Filename(Filename), Directory(Directory), FileNode(nullptr),
        LexicalBlockFileNode(nullptr), CUNode(nullptr) {
    Finder.processModule(M);
    visit(&M);
  }

  ~DIUpdater() { Builder.finalize(); }

  void visitModule(Module &M) {
    if (Finder.compile_unit_count() > 1)
      report_fatal_error("DebugIR pass supports only a signle compile unit per "
                         "Module.");
    createCompileUnit(Finder.compile_unit_count() == 1 ?
                      (MDNode*)*Finder.compile_units().begin() : nullptr);
  }

  void visitFunction(Function &F) {
    if (F.isDeclaration() || findDISubprogram(&F))
      return;

    StringRef MangledName = F.getName();
    DICompositeType Sig = createFunctionSignature(&F);

    // find line of function declaration
    unsigned Line = 0;
    if (!findLine(&F, Line)) {
      DEBUG(dbgs() << "WARNING: No line for Function " << F.getName().str()
                   << "\n");
      return;
    }

    Instruction *FirstInst = F.begin()->begin();
    unsigned ScopeLine = 0;
    if (!findLine(FirstInst, ScopeLine)) {
      DEBUG(dbgs() << "WARNING: No line for 1st Instruction in Function "
                   << F.getName().str() << "\n");
      return;
    }

    bool Local = F.hasInternalLinkage();
    bool IsDefinition = !F.isDeclaration();
    bool IsOptimized = false;

    int FuncFlags = llvm::DIDescriptor::FlagPrototyped;
    assert(CUNode && FileNode);
    DISubprogram Sub = Builder.createFunction(
        DICompileUnit(CUNode), F.getName(), MangledName, DIFile(FileNode), Line,
        Sig, Local, IsDefinition, ScopeLine, FuncFlags, IsOptimized, &F);
    assert(Sub.isSubprogram());
    DEBUG(dbgs() << "create subprogram mdnode " << *Sub << ": "
                 << "\n");

    SubprogramDescriptors.insert(std::make_pair(&F, Sub));
  }

  void visitInstruction(Instruction &I) {
    DebugLoc Loc(I.getDebugLoc());

    /// If a ValueToValueMap is provided, use it to get the real instruction as
    /// the line table was generated on a clone of the module on which we are
    /// operating.
    Value *RealInst = nullptr;
    if (VMap)
      RealInst = VMap->lookup(&I);

    if (!RealInst)
      RealInst = &I;

    unsigned Col = 0; // FIXME: support columns
    unsigned Line;
    if (!LineTable.getLine(RealInst, Line)) {
      // Instruction has no line, it may have been removed (in the module that
      // will be passed to the debugger) so there is nothing to do here.
      DEBUG(dbgs() << "WARNING: no LineTable entry for instruction " << RealInst
                   << "\n");
      DEBUG(RealInst->dump());
      return;
    }

    DebugLoc NewLoc;
    if (!Loc.isUnknown())
      // I had a previous debug location: re-use the DebugLoc
      NewLoc = DebugLoc::get(Line, Col, Loc.getScope(RealInst->getContext()),
                             Loc.getInlinedAt(RealInst->getContext()));
    else if (MDNode *scope = findScope(&I))
      NewLoc = DebugLoc::get(Line, Col, scope, nullptr);
    else {
      DEBUG(dbgs() << "WARNING: no valid scope for instruction " << &I
                   << ". no DebugLoc will be present."
                   << "\n");
      return;
    }

    addDebugLocation(I, NewLoc);
  }

private:

  void createCompileUnit(MDNode *CUToReplace) {
    std::string Flags;
    bool IsOptimized = false;
    StringRef Producer;
    unsigned RuntimeVersion(0);
    StringRef SplitName;

    if (CUToReplace) {
      // save fields from existing CU to re-use in the new CU
      DICompileUnit ExistingCU(CUToReplace);
      Producer = ExistingCU.getProducer();
      IsOptimized = ExistingCU.isOptimized();
      Flags = ExistingCU.getFlags();
      RuntimeVersion = ExistingCU.getRunTimeVersion();
      SplitName = ExistingCU.getSplitDebugFilename();
    } else {
      Producer =
          "LLVM Version " STR(LLVM_VERSION_MAJOR) "." STR(LLVM_VERSION_MINOR);
    }

    CUNode =
        Builder.createCompileUnit(dwarf::DW_LANG_C99, Filename, Directory,
                                  Producer, IsOptimized, Flags, RuntimeVersion);

    if (CUToReplace)
      CUToReplace->replaceAllUsesWith(const_cast<MDNode *>(CUNode));

    DICompileUnit CU(CUNode);
    FileNode = Builder.createFile(Filename, Directory);
    LexicalBlockFileNode = Builder.createLexicalBlockFile(CU, DIFile(FileNode));
  }

  /// Returns the MDNode* that represents the DI scope to associate with I
  MDNode *findScope(const Instruction *I) {
    const Function *F = I->getParent()->getParent();
    if (MDNode *ret = findDISubprogram(F))
      return ret;

    DEBUG(dbgs() << "WARNING: Using fallback lexical block file scope "
                 << LexicalBlockFileNode << " as scope for instruction " << I
                 << "\n");
    return LexicalBlockFileNode;
  }

  /// Returns the MDNode* that is the descriptor for F
  MDNode *findDISubprogram(const Function *F) {
    typedef ValueMap<const Function *, MDNode *>::const_iterator FuncNodeIter;
    FuncNodeIter i = SubprogramDescriptors.find(F);
    if (i != SubprogramDescriptors.end())
      return i->second;

    DEBUG(dbgs() << "searching for DI scope node for Function " << F
                 << " in a list of " << Finder.subprogram_count()
                 << " subprogram nodes"
                 << "\n");

    for (DISubprogram S : Finder.subprograms()) {
      if (S.getFunction() == F) {
        DEBUG(dbgs() << "Found DISubprogram " << S << " for function "
                     << S.getFunction() << "\n");
        return S;
      }
    }
    DEBUG(dbgs() << "unable to find DISubprogram node for function "
                 << F->getName().str() << "\n");
    return nullptr;
  }

  /// Sets Line to the line number on which V appears and returns true. If a
  /// line location for V is not found, returns false.
  bool findLine(const Value *V, unsigned &Line) {
    if (LineTable.getLine(V, Line))
      return true;

    if (VMap) {
      Value *mapped = VMap->lookup(V);
      if (mapped && LineTable.getLine(mapped, Line))
        return true;
    }
    return false;
  }

  std::string getTypeName(Type *T) {
    std::string TypeName;
    raw_string_ostream TypeStream(TypeName);
    if (T)
      T->print(TypeStream);
    else
      TypeStream << "Printing <null> Type";
    TypeStream.flush();
    return TypeName;
  }

  /// Returns the MDNode that represents type T if it is already created, or 0
  /// if it is not.
  MDNode *getType(const Type *T) {
    typedef DenseMap<const Type *, MDNode *>::const_iterator TypeNodeIter;
    TypeNodeIter i = TypeDescriptors.find(T);
    if (i != TypeDescriptors.end())
      return i->second;
    return nullptr;
  }

  /// Returns a DebugInfo type from an LLVM type T.
  DIDerivedType getOrCreateType(Type *T) {
    MDNode *N = getType(T);
    if (N)
      return DIDerivedType(N);
    else if (T->isVoidTy())
      return DIDerivedType(nullptr);
    else if (T->isStructTy()) {
      N = Builder.createStructType(
          DIScope(LexicalBlockFileNode), T->getStructName(), DIFile(FileNode),
          0, Layout.getTypeSizeInBits(T), Layout.getABITypeAlignment(T), 0,
          DIType(nullptr), DIArray(nullptr)); // filled in later

      // N is added to the map (early) so that element search below can find it,
      // so as to avoid infinite recursion for structs that contain pointers to
      // their own type.
      TypeDescriptors[T] = N;
      DICompositeType StructDescriptor(N);

      SmallVector<Value *, 4> Elements;
      for (unsigned i = 0; i < T->getStructNumElements(); ++i)
        Elements.push_back(getOrCreateType(T->getStructElementType(i)));

      // set struct elements
      StructDescriptor.setTypeArray(Builder.getOrCreateArray(Elements));
    } else if (T->isPointerTy()) {
      Type *PointeeTy = T->getPointerElementType();
      if (!(N = getType(PointeeTy)))
        N = Builder.createPointerType(
            getOrCreateType(PointeeTy), Layout.getPointerTypeSizeInBits(T),
            Layout.getPrefTypeAlignment(T), getTypeName(T));
    } else if (T->isArrayTy()) {
      SmallVector<Value *, 1> Subrange;
      Subrange.push_back(
          Builder.getOrCreateSubrange(0, T->getArrayNumElements() - 1));

      N = Builder.createArrayType(Layout.getTypeSizeInBits(T),
                                  Layout.getPrefTypeAlignment(T),
                                  getOrCreateType(T->getArrayElementType()),
                                  Builder.getOrCreateArray(Subrange));
    } else {
      int encoding = llvm::dwarf::DW_ATE_signed;
      if (T->isIntegerTy())
        encoding = llvm::dwarf::DW_ATE_unsigned;
      else if (T->isFloatingPointTy())
        encoding = llvm::dwarf::DW_ATE_float;

      N = Builder.createBasicType(getTypeName(T), T->getPrimitiveSizeInBits(),
                                  0, encoding);
    }
    TypeDescriptors[T] = N;
    return DIDerivedType(N);
  }

  /// Returns a DebugInfo type that represents a function signature for Func.
  DICompositeType createFunctionSignature(const Function *Func) {
    SmallVector<Value *, 4> Params;
    DIDerivedType ReturnType(getOrCreateType(Func->getReturnType()));
    Params.push_back(ReturnType);

    const Function::ArgumentListType &Args(Func->getArgumentList());
    for (Function::ArgumentListType::const_iterator i = Args.begin(),
                                                    e = Args.end();
         i != e; ++i) {
      Type *T(i->getType());
      Params.push_back(getOrCreateType(T));
    }

    DIArray ParamArray = Builder.getOrCreateArray(Params);
    return Builder.createSubroutineType(DIFile(FileNode), ParamArray);
  }

  /// Associates Instruction I with debug location Loc.
  void addDebugLocation(Instruction &I, DebugLoc Loc) {
    MDNode *MD = Loc.getAsMDNode(I.getContext());
    I.setMetadata(LLVMContext::MD_dbg, MD);
  }
};

/// Sets Filename/Directory from the Module identifier and returns true, or
/// false if source information is not present.
bool getSourceInfoFromModule(const Module &M, std::string &Directory,
                             std::string &Filename) {
  std::string PathStr(M.getModuleIdentifier());
  if (PathStr.length() == 0 || PathStr == "<stdin>")
    return false;

  Filename = sys::path::filename(PathStr);
  SmallVector<char, 16> Path(PathStr.begin(), PathStr.end());
  sys::path::remove_filename(Path);
  Directory = StringRef(Path.data(), Path.size());
  return true;
}

// Sets Filename/Directory from debug information in M and returns true, or
// false if no debug information available, or cannot be parsed.
bool getSourceInfoFromDI(const Module &M, std::string &Directory,
                         std::string &Filename) {
  NamedMDNode *CUNode = M.getNamedMetadata("llvm.dbg.cu");
  if (!CUNode || CUNode->getNumOperands() == 0)
    return false;

  DICompileUnit CU(CUNode->getOperand(0));
  if (!CU.Verify())
    return false;

  Filename = CU.getFilename();
  Directory = CU.getDirectory();
  return true;
}

} // anonymous namespace

namespace llvm {

bool DebugIR::getSourceInfo(const Module &M) {
  ParsedPath = getSourceInfoFromDI(M, Directory, Filename) ||
               getSourceInfoFromModule(M, Directory, Filename);
  return ParsedPath;
}

bool DebugIR::updateExtension(StringRef NewExtension) {
  size_t dot = Filename.find_last_of(".");
  if (dot == std::string::npos)
    return false;

  Filename.erase(dot);
  Filename += NewExtension.str();
  return true;
}

void DebugIR::generateFilename(std::unique_ptr<int> &fd) {
  SmallVector<char, 16> PathVec;
  fd.reset(new int);
  sys::fs::createTemporaryFile("debug-ir", "ll", *fd, PathVec);
  StringRef Path(PathVec.data(), PathVec.size());
  Filename = sys::path::filename(Path);
  sys::path::remove_filename(PathVec);
  Directory = StringRef(PathVec.data(), PathVec.size());

  GeneratedPath = true;
}

std::string DebugIR::getPath() {
  SmallVector<char, 16> Path;
  sys::path::append(Path, Directory, Filename);
  Path.resize(Filename.size() + Directory.size() + 2);
  Path[Filename.size() + Directory.size() + 1] = '\0';
  return std::string(Path.data());
}

void DebugIR::writeDebugBitcode(const Module *M, int *fd) {
  std::unique_ptr<raw_fd_ostream> Out;
  std::string error;

  if (!fd) {
    std::string Path = getPath();
    Out.reset(new raw_fd_ostream(Path.c_str(), error, sys::fs::F_Text));
    DEBUG(dbgs() << "WRITING debug bitcode from Module " << M << " to file "
                 << Path << "\n");
  } else {
    DEBUG(dbgs() << "WRITING debug bitcode from Module " << M << " to fd "
                 << *fd << "\n");
    Out.reset(new raw_fd_ostream(*fd, true));
  }

  M->print(*Out, nullptr);
  Out->close();
}

void DebugIR::createDebugInfo(Module &M, std::unique_ptr<Module> &DisplayM) {
  if (M.getFunctionList().size() == 0)
    // no functions -- no debug info needed
    return;

  std::unique_ptr<ValueToValueMapTy> VMap;

  if (WriteSourceToDisk && (HideDebugIntrinsics || HideDebugMetadata)) {
    VMap.reset(new ValueToValueMapTy);
    DisplayM.reset(CloneModule(&M, *VMap));

    if (HideDebugIntrinsics)
      DebugIntrinsicsRemover::process(*DisplayM);

    if (HideDebugMetadata)
      DebugMetadataRemover::process(*DisplayM);
  }

  DIUpdater R(M, Filename, Directory, DisplayM.get(), VMap.get());
}

bool DebugIR::isMissingPath() { return Filename.empty() || Directory.empty(); }

bool DebugIR::runOnModule(Module &M) {
  std::unique_ptr<int> fd;

  if (isMissingPath() && !getSourceInfo(M)) {
    if (!WriteSourceToDisk)
      report_fatal_error("DebugIR unable to determine file name in input. "
                         "Ensure Module contains an identifier, a valid "
                         "DICompileUnit, or construct DebugIR with "
                         "non-empty Filename/Directory parameters.");
    else
      generateFilename(fd);
  }

  if (!GeneratedPath && WriteSourceToDisk)
    updateExtension(".debug-ll");

  // Clear line numbers. Keep debug info (if any) if we were able to read the
  // file name from the DICompileUnit descriptor.
  DebugMetadataRemover::process(M, !ParsedPath);

  std::unique_ptr<Module> DisplayM;
  createDebugInfo(M, DisplayM);
  if (WriteSourceToDisk) {
    Module *OutputM = DisplayM.get() ? DisplayM.get() : &M;
    writeDebugBitcode(OutputM, fd.get());
  }

  DEBUG(M.dump());
  return true;
}

bool DebugIR::runOnModule(Module &M, std::string &Path) {
  bool result = runOnModule(M);
  Path = getPath();
  return result;
}

} // llvm namespace

char DebugIR::ID = 0;
INITIALIZE_PASS(DebugIR, "debug-ir", "Enable debugging IR", false, false)

ModulePass *llvm::createDebugIRPass(bool HideDebugIntrinsics,
                                    bool HideDebugMetadata, StringRef Directory,
                                    StringRef Filename) {
  return new DebugIR(HideDebugIntrinsics, HideDebugMetadata, Directory,
                     Filename);
}

ModulePass *llvm::createDebugIRPass() { return new DebugIR(); }
