diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp')
| -rw-r--r-- | contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp | 617 | 
1 files changed, 0 insertions, 617 deletions
diff --git a/contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp b/contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp deleted file mode 100644 index f2f1738808be..000000000000 --- a/contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp +++ /dev/null @@ -1,617 +0,0 @@ -//===--- 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(); }  | 
