diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp')
-rw-r--r-- | contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp | 618 |
1 files changed, 618 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp b/contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp new file mode 100644 index 0000000..f50a044 --- /dev/null +++ b/contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp @@ -0,0 +1,618 @@ +//===--- 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. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "debug-ir" + +#include "llvm/ADT/ValueMap.h" +#include "llvm/Assembly/AssemblyAnnotationWriter.h" +#include "llvm/DebugInfo.h" +#include "llvm/DIBuilder.h" +#include "llvm/InstVisitor.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +#include "DebugIR.h" + +#include <string> + +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + +using namespace llvm; + +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) { + addEntry(&V, Out); + } + + void emitFunctionAnnot(const Function *F, formatted_raw_ostream &Out) { + 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, 0); + } + + 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 = 0, + const ValueToValueMapTy *VMap = 0) + : Builder(M), Layout(&M), LineTable(DisplayM ? DisplayM : &M), VMap(VMap), + Finder(), Filename(Filename), Directory(Directory), FileNode(0), + LexicalBlockFileNode(0), CUNode(0) { + 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 ? *Finder.compile_unit_begin() : 0); + } + + 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 = 0; + 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, 0); + 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 (DebugInfoFinder::iterator i = Finder.subprogram_begin(), + e = Finder.subprogram_end(); + i != e; ++i) { + DISubprogram S(*i); + if (S.getFunction() == F) { + DEBUG(dbgs() << "Found DISubprogram " << *i << " for function " + << S.getFunction() << "\n"); + return *i; + } + } + DEBUG(dbgs() << "unable to find DISubprogram node for function " + << F->getName().str() << "\n"); + return 0; + } + + /// 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); + T->print(TypeStream); + 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 0; + } + + /// 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(0); + else if (T->isStructTy()) { + N = Builder.createStructType( + DIScope(LexicalBlockFileNode), T->getStructName(), DIFile(FileNode), + 0, Layout.getTypeSizeInBits(T), Layout.getABITypeAlignment(T), 0, + DIType(0), DIArray(0)); // 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(OwningPtr<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) { + OwningPtr<raw_fd_ostream> Out; + std::string error; + + if (!fd) { + std::string Path = getPath(); + Out.reset(new raw_fd_ostream(Path.c_str(), error)); + 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, 0); + Out->close(); +} + +void DebugIR::createDebugInfo(Module &M, OwningPtr<Module> &DisplayM) { + if (M.getFunctionList().size() == 0) + // no functions -- no debug info needed + return; + + OwningPtr<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) { + OwningPtr<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); + + OwningPtr<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(); } |