LLVM API Documentation
00001 //===--- DebugIR.cpp - Transform debug metadata to allow debugging IR -----===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // A Module transform pass that emits a succinct version of the IR and replaces 00011 // the source file metadata to allow debuggers to step through the IR. 00012 // 00013 // FIXME: instead of replacing debug metadata, this pass should allow for 00014 // additional metadata to be used to point capable debuggers to the IR file 00015 // without destroying the mapping to the original source file. 00016 // 00017 //===----------------------------------------------------------------------===// 00018 00019 #include "llvm/IR/ValueMap.h" 00020 #include "DebugIR.h" 00021 #include "llvm/IR/AssemblyAnnotationWriter.h" 00022 #include "llvm/IR/DIBuilder.h" 00023 #include "llvm/IR/DataLayout.h" 00024 #include "llvm/IR/DebugInfo.h" 00025 #include "llvm/IR/InstVisitor.h" 00026 #include "llvm/IR/Instruction.h" 00027 #include "llvm/IR/LLVMContext.h" 00028 #include "llvm/IR/Module.h" 00029 #include "llvm/Support/Debug.h" 00030 #include "llvm/Support/FileSystem.h" 00031 #include "llvm/Support/FormattedStream.h" 00032 #include "llvm/Support/Path.h" 00033 #include "llvm/Support/ToolOutputFile.h" 00034 #include "llvm/Transforms/Instrumentation.h" 00035 #include "llvm/Transforms/Utils/Cloning.h" 00036 #include <string> 00037 00038 #define STR_HELPER(x) #x 00039 #define STR(x) STR_HELPER(x) 00040 00041 using namespace llvm; 00042 00043 #define DEBUG_TYPE "debug-ir" 00044 00045 namespace { 00046 00047 /// Builds a map of Value* to line numbers on which the Value appears in a 00048 /// textual representation of the IR by plugging into the AssemblyWriter by 00049 /// masquerading as an AssemblyAnnotationWriter. 00050 class ValueToLineMap : public AssemblyAnnotationWriter { 00051 ValueMap<const Value *, unsigned int> Lines; 00052 typedef ValueMap<const Value *, unsigned int>::const_iterator LineIter; 00053 00054 void addEntry(const Value *V, formatted_raw_ostream &Out) { 00055 Out.flush(); 00056 Lines.insert(std::make_pair(V, Out.getLine() + 1)); 00057 } 00058 00059 public: 00060 00061 /// Prints Module to a null buffer in order to build the map of Value pointers 00062 /// to line numbers. 00063 ValueToLineMap(const Module *M) { 00064 raw_null_ostream ThrowAway; 00065 M->print(ThrowAway, this); 00066 } 00067 00068 // This function is called after an Instruction, GlobalValue, or GlobalAlias 00069 // is printed. 00070 void printInfoComment(const Value &V, formatted_raw_ostream &Out) override { 00071 addEntry(&V, Out); 00072 } 00073 00074 void emitFunctionAnnot(const Function *F, 00075 formatted_raw_ostream &Out) override { 00076 addEntry(F, Out); 00077 } 00078 00079 /// If V appears on a line in the textual IR representation, sets Line to the 00080 /// line number and returns true, otherwise returns false. 00081 bool getLine(const Value *V, unsigned int &Line) const { 00082 LineIter i = Lines.find(V); 00083 if (i != Lines.end()) { 00084 Line = i->second; 00085 return true; 00086 } 00087 return false; 00088 } 00089 }; 00090 00091 /// Removes debug intrisncs like llvm.dbg.declare and llvm.dbg.value. 00092 class DebugIntrinsicsRemover : public InstVisitor<DebugIntrinsicsRemover> { 00093 void remove(Instruction &I) { I.eraseFromParent(); } 00094 00095 public: 00096 static void process(Module &M) { 00097 DebugIntrinsicsRemover Remover; 00098 Remover.visit(&M); 00099 } 00100 void visitDbgDeclareInst(DbgDeclareInst &I) { remove(I); } 00101 void visitDbgValueInst(DbgValueInst &I) { remove(I); } 00102 void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { remove(I); } 00103 }; 00104 00105 /// Removes debug metadata (!dbg) nodes from all instructions, and optionally 00106 /// metadata named "llvm.dbg.cu" if RemoveNamedInfo is true. 00107 class DebugMetadataRemover : public InstVisitor<DebugMetadataRemover> { 00108 bool RemoveNamedInfo; 00109 00110 public: 00111 static void process(Module &M, bool RemoveNamedInfo = true) { 00112 DebugMetadataRemover Remover(RemoveNamedInfo); 00113 Remover.run(&M); 00114 } 00115 00116 DebugMetadataRemover(bool RemoveNamedInfo) 00117 : RemoveNamedInfo(RemoveNamedInfo) {} 00118 00119 void visitInstruction(Instruction &I) { 00120 if (I.getMetadata(LLVMContext::MD_dbg)) 00121 I.setMetadata(LLVMContext::MD_dbg, nullptr); 00122 } 00123 00124 void run(Module *M) { 00125 // Remove debug metadata attached to instructions 00126 visit(M); 00127 00128 if (RemoveNamedInfo) { 00129 // Remove CU named metadata (and all children nodes) 00130 NamedMDNode *Node = M->getNamedMetadata("llvm.dbg.cu"); 00131 if (Node) 00132 M->eraseNamedMetadata(Node); 00133 } 00134 } 00135 }; 00136 00137 /// Updates debug metadata in a Module: 00138 /// - changes Filename/Directory to values provided on construction 00139 /// - adds/updates line number (DebugLoc) entries associated with each 00140 /// instruction to reflect the instruction's location in an LLVM IR file 00141 class DIUpdater : public InstVisitor<DIUpdater> { 00142 /// Builder of debug information 00143 DIBuilder Builder; 00144 00145 /// Helper for type attributes/sizes/etc 00146 DataLayout Layout; 00147 00148 /// Map of Value* to line numbers 00149 const ValueToLineMap LineTable; 00150 00151 /// Map of Value* (in original Module) to Value* (in optional cloned Module) 00152 const ValueToValueMapTy *VMap; 00153 00154 /// Directory of debug metadata 00155 DebugInfoFinder Finder; 00156 00157 /// Source filename and directory 00158 StringRef Filename; 00159 StringRef Directory; 00160 00161 // CU nodes needed when creating DI subprograms 00162 MDNode *FileNode; 00163 MDNode *LexicalBlockFileNode; 00164 const MDNode *CUNode; 00165 00166 ValueMap<const Function *, MDNode *> SubprogramDescriptors; 00167 DenseMap<const Type *, MDNode *> TypeDescriptors; 00168 00169 public: 00170 DIUpdater(Module &M, StringRef Filename = StringRef(), 00171 StringRef Directory = StringRef(), const Module *DisplayM = nullptr, 00172 const ValueToValueMapTy *VMap = nullptr) 00173 : Builder(M), Layout(&M), LineTable(DisplayM ? DisplayM : &M), VMap(VMap), 00174 Finder(), Filename(Filename), Directory(Directory), FileNode(nullptr), 00175 LexicalBlockFileNode(nullptr), CUNode(nullptr) { 00176 Finder.processModule(M); 00177 visit(&M); 00178 } 00179 00180 ~DIUpdater() { Builder.finalize(); } 00181 00182 void visitModule(Module &M) { 00183 if (Finder.compile_unit_count() > 1) 00184 report_fatal_error("DebugIR pass supports only a signle compile unit per " 00185 "Module."); 00186 createCompileUnit(Finder.compile_unit_count() == 1 ? 00187 (MDNode*)*Finder.compile_units().begin() : nullptr); 00188 } 00189 00190 void visitFunction(Function &F) { 00191 if (F.isDeclaration() || findDISubprogram(&F)) 00192 return; 00193 00194 StringRef MangledName = F.getName(); 00195 DICompositeType Sig = createFunctionSignature(&F); 00196 00197 // find line of function declaration 00198 unsigned Line = 0; 00199 if (!findLine(&F, Line)) { 00200 DEBUG(dbgs() << "WARNING: No line for Function " << F.getName().str() 00201 << "\n"); 00202 return; 00203 } 00204 00205 Instruction *FirstInst = F.begin()->begin(); 00206 unsigned ScopeLine = 0; 00207 if (!findLine(FirstInst, ScopeLine)) { 00208 DEBUG(dbgs() << "WARNING: No line for 1st Instruction in Function " 00209 << F.getName().str() << "\n"); 00210 return; 00211 } 00212 00213 bool Local = F.hasInternalLinkage(); 00214 bool IsDefinition = !F.isDeclaration(); 00215 bool IsOptimized = false; 00216 00217 int FuncFlags = llvm::DIDescriptor::FlagPrototyped; 00218 assert(CUNode && FileNode); 00219 DISubprogram Sub = Builder.createFunction( 00220 DICompileUnit(CUNode), F.getName(), MangledName, DIFile(FileNode), Line, 00221 Sig, Local, IsDefinition, ScopeLine, FuncFlags, IsOptimized, &F); 00222 assert(Sub.isSubprogram()); 00223 DEBUG(dbgs() << "create subprogram mdnode " << *Sub << ": " 00224 << "\n"); 00225 00226 SubprogramDescriptors.insert(std::make_pair(&F, Sub)); 00227 } 00228 00229 void visitInstruction(Instruction &I) { 00230 DebugLoc Loc(I.getDebugLoc()); 00231 00232 /// If a ValueToValueMap is provided, use it to get the real instruction as 00233 /// the line table was generated on a clone of the module on which we are 00234 /// operating. 00235 Value *RealInst = nullptr; 00236 if (VMap) 00237 RealInst = VMap->lookup(&I); 00238 00239 if (!RealInst) 00240 RealInst = &I; 00241 00242 unsigned Col = 0; // FIXME: support columns 00243 unsigned Line; 00244 if (!LineTable.getLine(RealInst, Line)) { 00245 // Instruction has no line, it may have been removed (in the module that 00246 // will be passed to the debugger) so there is nothing to do here. 00247 DEBUG(dbgs() << "WARNING: no LineTable entry for instruction " << RealInst 00248 << "\n"); 00249 DEBUG(RealInst->dump()); 00250 return; 00251 } 00252 00253 DebugLoc NewLoc; 00254 if (!Loc.isUnknown()) 00255 // I had a previous debug location: re-use the DebugLoc 00256 NewLoc = DebugLoc::get(Line, Col, Loc.getScope(RealInst->getContext()), 00257 Loc.getInlinedAt(RealInst->getContext())); 00258 else if (MDNode *scope = findScope(&I)) 00259 NewLoc = DebugLoc::get(Line, Col, scope, nullptr); 00260 else { 00261 DEBUG(dbgs() << "WARNING: no valid scope for instruction " << &I 00262 << ". no DebugLoc will be present." 00263 << "\n"); 00264 return; 00265 } 00266 00267 addDebugLocation(I, NewLoc); 00268 } 00269 00270 private: 00271 00272 void createCompileUnit(MDNode *CUToReplace) { 00273 std::string Flags; 00274 bool IsOptimized = false; 00275 StringRef Producer; 00276 unsigned RuntimeVersion(0); 00277 StringRef SplitName; 00278 00279 if (CUToReplace) { 00280 // save fields from existing CU to re-use in the new CU 00281 DICompileUnit ExistingCU(CUToReplace); 00282 Producer = ExistingCU.getProducer(); 00283 IsOptimized = ExistingCU.isOptimized(); 00284 Flags = ExistingCU.getFlags(); 00285 RuntimeVersion = ExistingCU.getRunTimeVersion(); 00286 SplitName = ExistingCU.getSplitDebugFilename(); 00287 } else { 00288 Producer = 00289 "LLVM Version " STR(LLVM_VERSION_MAJOR) "." STR(LLVM_VERSION_MINOR); 00290 } 00291 00292 CUNode = 00293 Builder.createCompileUnit(dwarf::DW_LANG_C99, Filename, Directory, 00294 Producer, IsOptimized, Flags, RuntimeVersion); 00295 00296 if (CUToReplace) 00297 CUToReplace->replaceAllUsesWith(const_cast<MDNode *>(CUNode)); 00298 00299 DICompileUnit CU(CUNode); 00300 FileNode = Builder.createFile(Filename, Directory); 00301 LexicalBlockFileNode = Builder.createLexicalBlockFile(CU, DIFile(FileNode)); 00302 } 00303 00304 /// Returns the MDNode* that represents the DI scope to associate with I 00305 MDNode *findScope(const Instruction *I) { 00306 const Function *F = I->getParent()->getParent(); 00307 if (MDNode *ret = findDISubprogram(F)) 00308 return ret; 00309 00310 DEBUG(dbgs() << "WARNING: Using fallback lexical block file scope " 00311 << LexicalBlockFileNode << " as scope for instruction " << I 00312 << "\n"); 00313 return LexicalBlockFileNode; 00314 } 00315 00316 /// Returns the MDNode* that is the descriptor for F 00317 MDNode *findDISubprogram(const Function *F) { 00318 typedef ValueMap<const Function *, MDNode *>::const_iterator FuncNodeIter; 00319 FuncNodeIter i = SubprogramDescriptors.find(F); 00320 if (i != SubprogramDescriptors.end()) 00321 return i->second; 00322 00323 DEBUG(dbgs() << "searching for DI scope node for Function " << F 00324 << " in a list of " << Finder.subprogram_count() 00325 << " subprogram nodes" 00326 << "\n"); 00327 00328 for (DISubprogram S : Finder.subprograms()) { 00329 if (S.getFunction() == F) { 00330 DEBUG(dbgs() << "Found DISubprogram " << S << " for function " 00331 << S.getFunction() << "\n"); 00332 return S; 00333 } 00334 } 00335 DEBUG(dbgs() << "unable to find DISubprogram node for function " 00336 << F->getName().str() << "\n"); 00337 return nullptr; 00338 } 00339 00340 /// Sets Line to the line number on which V appears and returns true. If a 00341 /// line location for V is not found, returns false. 00342 bool findLine(const Value *V, unsigned &Line) { 00343 if (LineTable.getLine(V, Line)) 00344 return true; 00345 00346 if (VMap) { 00347 Value *mapped = VMap->lookup(V); 00348 if (mapped && LineTable.getLine(mapped, Line)) 00349 return true; 00350 } 00351 return false; 00352 } 00353 00354 std::string getTypeName(Type *T) { 00355 std::string TypeName; 00356 raw_string_ostream TypeStream(TypeName); 00357 if (T) 00358 T->print(TypeStream); 00359 else 00360 TypeStream << "Printing <null> Type"; 00361 TypeStream.flush(); 00362 return TypeName; 00363 } 00364 00365 /// Returns the MDNode that represents type T if it is already created, or 0 00366 /// if it is not. 00367 MDNode *getType(const Type *T) { 00368 typedef DenseMap<const Type *, MDNode *>::const_iterator TypeNodeIter; 00369 TypeNodeIter i = TypeDescriptors.find(T); 00370 if (i != TypeDescriptors.end()) 00371 return i->second; 00372 return nullptr; 00373 } 00374 00375 /// Returns a DebugInfo type from an LLVM type T. 00376 DIDerivedType getOrCreateType(Type *T) { 00377 MDNode *N = getType(T); 00378 if (N) 00379 return DIDerivedType(N); 00380 else if (T->isVoidTy()) 00381 return DIDerivedType(nullptr); 00382 else if (T->isStructTy()) { 00383 N = Builder.createStructType( 00384 DIScope(LexicalBlockFileNode), T->getStructName(), DIFile(FileNode), 00385 0, Layout.getTypeSizeInBits(T), Layout.getABITypeAlignment(T), 0, 00386 DIType(nullptr), DIArray(nullptr)); // filled in later 00387 00388 // N is added to the map (early) so that element search below can find it, 00389 // so as to avoid infinite recursion for structs that contain pointers to 00390 // their own type. 00391 TypeDescriptors[T] = N; 00392 DICompositeType StructDescriptor(N); 00393 00394 SmallVector<Value *, 4> Elements; 00395 for (unsigned i = 0; i < T->getStructNumElements(); ++i) 00396 Elements.push_back(getOrCreateType(T->getStructElementType(i))); 00397 00398 // set struct elements 00399 StructDescriptor.setArrays(Builder.getOrCreateArray(Elements)); 00400 } else if (T->isPointerTy()) { 00401 Type *PointeeTy = T->getPointerElementType(); 00402 if (!(N = getType(PointeeTy))) 00403 N = Builder.createPointerType( 00404 getOrCreateType(PointeeTy), Layout.getPointerTypeSizeInBits(T), 00405 Layout.getPrefTypeAlignment(T), getTypeName(T)); 00406 } else if (T->isArrayTy()) { 00407 SmallVector<Value *, 1> Subrange; 00408 Subrange.push_back( 00409 Builder.getOrCreateSubrange(0, T->getArrayNumElements() - 1)); 00410 00411 N = Builder.createArrayType(Layout.getTypeSizeInBits(T), 00412 Layout.getPrefTypeAlignment(T), 00413 getOrCreateType(T->getArrayElementType()), 00414 Builder.getOrCreateArray(Subrange)); 00415 } else { 00416 int encoding = llvm::dwarf::DW_ATE_signed; 00417 if (T->isIntegerTy()) 00418 encoding = llvm::dwarf::DW_ATE_unsigned; 00419 else if (T->isFloatingPointTy()) 00420 encoding = llvm::dwarf::DW_ATE_float; 00421 00422 N = Builder.createBasicType(getTypeName(T), T->getPrimitiveSizeInBits(), 00423 0, encoding); 00424 } 00425 TypeDescriptors[T] = N; 00426 return DIDerivedType(N); 00427 } 00428 00429 /// Returns a DebugInfo type that represents a function signature for Func. 00430 DICompositeType createFunctionSignature(const Function *Func) { 00431 SmallVector<Value *, 4> Params; 00432 DIDerivedType ReturnType(getOrCreateType(Func->getReturnType())); 00433 Params.push_back(ReturnType); 00434 00435 const Function::ArgumentListType &Args(Func->getArgumentList()); 00436 for (Function::ArgumentListType::const_iterator i = Args.begin(), 00437 e = Args.end(); 00438 i != e; ++i) { 00439 Type *T(i->getType()); 00440 Params.push_back(getOrCreateType(T)); 00441 } 00442 00443 DITypeArray ParamArray = Builder.getOrCreateTypeArray(Params); 00444 return Builder.createSubroutineType(DIFile(FileNode), ParamArray); 00445 } 00446 00447 /// Associates Instruction I with debug location Loc. 00448 void addDebugLocation(Instruction &I, DebugLoc Loc) { 00449 MDNode *MD = Loc.getAsMDNode(I.getContext()); 00450 I.setMetadata(LLVMContext::MD_dbg, MD); 00451 } 00452 }; 00453 00454 /// Sets Filename/Directory from the Module identifier and returns true, or 00455 /// false if source information is not present. 00456 bool getSourceInfoFromModule(const Module &M, std::string &Directory, 00457 std::string &Filename) { 00458 std::string PathStr(M.getModuleIdentifier()); 00459 if (PathStr.length() == 0 || PathStr == "<stdin>") 00460 return false; 00461 00462 Filename = sys::path::filename(PathStr); 00463 SmallVector<char, 16> Path(PathStr.begin(), PathStr.end()); 00464 sys::path::remove_filename(Path); 00465 Directory = StringRef(Path.data(), Path.size()); 00466 return true; 00467 } 00468 00469 // Sets Filename/Directory from debug information in M and returns true, or 00470 // false if no debug information available, or cannot be parsed. 00471 bool getSourceInfoFromDI(const Module &M, std::string &Directory, 00472 std::string &Filename) { 00473 NamedMDNode *CUNode = M.getNamedMetadata("llvm.dbg.cu"); 00474 if (!CUNode || CUNode->getNumOperands() == 0) 00475 return false; 00476 00477 DICompileUnit CU(CUNode->getOperand(0)); 00478 if (!CU.Verify()) 00479 return false; 00480 00481 Filename = CU.getFilename(); 00482 Directory = CU.getDirectory(); 00483 return true; 00484 } 00485 00486 } // anonymous namespace 00487 00488 namespace llvm { 00489 00490 bool DebugIR::getSourceInfo(const Module &M) { 00491 ParsedPath = getSourceInfoFromDI(M, Directory, Filename) || 00492 getSourceInfoFromModule(M, Directory, Filename); 00493 return ParsedPath; 00494 } 00495 00496 bool DebugIR::updateExtension(StringRef NewExtension) { 00497 size_t dot = Filename.find_last_of("."); 00498 if (dot == std::string::npos) 00499 return false; 00500 00501 Filename.erase(dot); 00502 Filename += NewExtension.str(); 00503 return true; 00504 } 00505 00506 void DebugIR::generateFilename(std::unique_ptr<int> &fd) { 00507 SmallVector<char, 16> PathVec; 00508 fd.reset(new int); 00509 sys::fs::createTemporaryFile("debug-ir", "ll", *fd, PathVec); 00510 StringRef Path(PathVec.data(), PathVec.size()); 00511 Filename = sys::path::filename(Path); 00512 sys::path::remove_filename(PathVec); 00513 Directory = StringRef(PathVec.data(), PathVec.size()); 00514 00515 GeneratedPath = true; 00516 } 00517 00518 std::string DebugIR::getPath() { 00519 SmallVector<char, 16> Path; 00520 sys::path::append(Path, Directory, Filename); 00521 Path.resize(Filename.size() + Directory.size() + 2); 00522 Path[Filename.size() + Directory.size() + 1] = '\0'; 00523 return std::string(Path.data()); 00524 } 00525 00526 void DebugIR::writeDebugBitcode(const Module *M, int *fd) { 00527 std::unique_ptr<raw_fd_ostream> Out; 00528 std::error_code EC; 00529 00530 if (!fd) { 00531 std::string Path = getPath(); 00532 Out.reset(new raw_fd_ostream(Path, EC, sys::fs::F_Text)); 00533 DEBUG(dbgs() << "WRITING debug bitcode from Module " << M << " to file " 00534 << Path << "\n"); 00535 } else { 00536 DEBUG(dbgs() << "WRITING debug bitcode from Module " << M << " to fd " 00537 << *fd << "\n"); 00538 Out.reset(new raw_fd_ostream(*fd, true)); 00539 } 00540 00541 M->print(*Out, nullptr); 00542 Out->close(); 00543 } 00544 00545 void DebugIR::createDebugInfo(Module &M, std::unique_ptr<Module> &DisplayM) { 00546 if (M.getFunctionList().size() == 0) 00547 // no functions -- no debug info needed 00548 return; 00549 00550 std::unique_ptr<ValueToValueMapTy> VMap; 00551 00552 if (WriteSourceToDisk && (HideDebugIntrinsics || HideDebugMetadata)) { 00553 VMap.reset(new ValueToValueMapTy); 00554 DisplayM.reset(CloneModule(&M, *VMap)); 00555 00556 if (HideDebugIntrinsics) 00557 DebugIntrinsicsRemover::process(*DisplayM); 00558 00559 if (HideDebugMetadata) 00560 DebugMetadataRemover::process(*DisplayM); 00561 } 00562 00563 DIUpdater R(M, Filename, Directory, DisplayM.get(), VMap.get()); 00564 } 00565 00566 bool DebugIR::isMissingPath() { return Filename.empty() || Directory.empty(); } 00567 00568 bool DebugIR::runOnModule(Module &M) { 00569 std::unique_ptr<int> fd; 00570 00571 if (isMissingPath() && !getSourceInfo(M)) { 00572 if (!WriteSourceToDisk) 00573 report_fatal_error("DebugIR unable to determine file name in input. " 00574 "Ensure Module contains an identifier, a valid " 00575 "DICompileUnit, or construct DebugIR with " 00576 "non-empty Filename/Directory parameters."); 00577 else 00578 generateFilename(fd); 00579 } 00580 00581 if (!GeneratedPath && WriteSourceToDisk) 00582 updateExtension(".debug-ll"); 00583 00584 // Clear line numbers. Keep debug info (if any) if we were able to read the 00585 // file name from the DICompileUnit descriptor. 00586 DebugMetadataRemover::process(M, !ParsedPath); 00587 00588 std::unique_ptr<Module> DisplayM; 00589 createDebugInfo(M, DisplayM); 00590 if (WriteSourceToDisk) { 00591 Module *OutputM = DisplayM.get() ? DisplayM.get() : &M; 00592 writeDebugBitcode(OutputM, fd.get()); 00593 } 00594 00595 DEBUG(M.dump()); 00596 return true; 00597 } 00598 00599 bool DebugIR::runOnModule(Module &M, std::string &Path) { 00600 bool result = runOnModule(M); 00601 Path = getPath(); 00602 return result; 00603 } 00604 00605 } // llvm namespace 00606 00607 char DebugIR::ID = 0; 00608 INITIALIZE_PASS(DebugIR, "debug-ir", "Enable debugging IR", false, false) 00609 00610 ModulePass *llvm::createDebugIRPass(bool HideDebugIntrinsics, 00611 bool HideDebugMetadata, StringRef Directory, 00612 StringRef Filename) { 00613 return new DebugIR(HideDebugIntrinsics, HideDebugMetadata, Directory, 00614 Filename); 00615 } 00616 00617 ModulePass *llvm::createDebugIRPass() { return new DebugIR(); }