diff options
author | Adrian Prantl <aprantl@apple.com> | 2016-04-08 22:43:03 +0000 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2016-04-08 22:43:03 +0000 |
commit | 5992a72b4d21f3ea15a0ecbb593d92c9bc4fe1a0 (patch) | |
tree | e369ac2ee392142837ebf0b460286e0fe2bdda0a /llvm | |
parent | b24f4fb6171eaf2caa8f3cf6adcf11821ec1d27c (diff) | |
download | bcm5719-llvm-5992a72b4d21f3ea15a0ecbb593d92c9bc4fe1a0.tar.gz bcm5719-llvm-5992a72b4d21f3ea15a0ecbb593d92c9bc4fe1a0.zip |
Support the Nodebug emission kind for DICompileUnits.
Sample-based profiling and optimization remarks currently remove
DICompileUnits from llvm.dbg.cu to suppress the emission of debug info
from them. This is somewhat of a hack and only borderline legal IR.
This patch uses the recently introduced NoDebug emission kind in
DICompileUnit to achieve the same result without breaking the Verifier.
A nice side-effect of this change is that it is now possible to combine
NoDebug and regular compile units under LTO.
http://reviews.llvm.org/D18808
<rdar://problem/25427165>
llvm-svn: 265861
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/IR/DIBuilder.h | 12 | ||||
-rw-r--r-- | llvm/include/llvm/IR/DebugInfo.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/IR/Module.h | 53 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 33 | ||||
-rw-r--r-- | llvm/lib/IR/DIBuilder.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfo.cpp | 61 | ||||
-rw-r--r-- | llvm/lib/IR/Module.cpp | 14 | ||||
-rw-r--r-- | llvm/test/DebugInfo/X86/mixed-nodebug-cu.ll | 50 | ||||
-rw-r--r-- | llvm/tools/opt/BreakpointPrinter.cpp | 4 |
9 files changed, 171 insertions, 71 deletions
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 4a9a293bcfe..49c6fcb6fa3 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -92,23 +92,13 @@ namespace llvm { /// out into. /// \param Kind The kind of debug information to generate. /// \param DWOId The DWOId if this is a split skeleton compile unit. - /// \param EmitDebugInfo A boolean flag which indicates whether - /// debug information should be written to - /// the final output or not. When this is - /// false, debug information annotations will - /// be present in the IL but they are not - /// written to the final assembly or object - /// file. This supports tracking source - /// location information in the back end - /// without actually changing the output - /// (e.g., when using optimization remarks). DICompileUnit * createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName = StringRef(), DICompileUnit::DebugEmissionKind Kind = DICompileUnit::DebugEmissionKind::FullDebug, - uint64_t DWOId = 0, bool EmitDebugInfo = true); + uint64_t DWOId = 0); /// Create a file descriptor to hold debugging information /// for a file. diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h index 82227930403..dc5fd1a1a98 100644 --- a/llvm/include/llvm/IR/DebugInfo.h +++ b/llvm/include/llvm/IR/DebugInfo.h @@ -40,7 +40,7 @@ typedef DenseMap<const MDString *, DIType *> DITypeIdentifierMap; DISubprogram *getDISubprogram(const MDNode *Scope); /// \brief Generate map by visiting all retained types. -DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); +DITypeIdentifierMap generateDITypeIdentifierMap(const Module &M); /// \brief Strip debug info in the module if it exists. /// diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h index 118a8d19843..bdc5444507e 100644 --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -626,6 +626,58 @@ public: return make_range(named_metadata_begin(), named_metadata_end()); } + /// An iterator for DICompileUnits that skips those marked NoDebug. + class debug_compile_units_iterator + : public std::iterator<std::input_iterator_tag, DICompileUnit *> { + NamedMDNode *CUs; + unsigned Idx; + void SkipNoDebugCUs(); + public: + explicit debug_compile_units_iterator(NamedMDNode *CUs, unsigned Idx) + : CUs(CUs), Idx(Idx) { + SkipNoDebugCUs(); + } + debug_compile_units_iterator &operator++() { + ++Idx; + SkipNoDebugCUs(); + return *this; + } + debug_compile_units_iterator operator++(int) { + debug_compile_units_iterator T(*this); + ++Idx; + return T; + } + bool operator==(const debug_compile_units_iterator &I) const { + return Idx == I.Idx; + } + bool operator!=(const debug_compile_units_iterator &I) const { + return Idx != I.Idx; + } + DICompileUnit *operator*() const; + DICompileUnit *operator->() const; + }; + + debug_compile_units_iterator debug_compile_units_begin() const { + auto *CUs = getNamedMetadata("llvm.dbg.cu"); + return debug_compile_units_iterator(CUs, 0); + } + + debug_compile_units_iterator debug_compile_units_end() const { + auto *CUs = getNamedMetadata("llvm.dbg.cu"); + return debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0); + } + + /// Return an iterator for all DICompileUnits listed in this Module's + /// llvm.dbg.cu named metadata node and aren't explicitly marked as + /// NoDebug. + iterator_range<debug_compile_units_iterator> debug_compile_units() const { + auto *CUs = getNamedMetadata("llvm.dbg.cu"); + return make_range( + debug_compile_units_iterator(CUs, 0), + debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0)); + } +/// @} + /// Destroy ConstantArrays in LLVMContext if they are not used. /// ConstantArrays constructed during linking can cause quadratic memory /// explosion. Releasing all unused constants can cause a 20% LTO compile-time @@ -635,7 +687,6 @@ public: /// be called where all uses of the LLVMContext are understood. void dropTriviallyDeadConstantArrays(); -/// @} /// @name Utility functions for printing and dumping Module objects /// @{ diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 296a799d33c..d9d265ef2b9 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -466,15 +466,18 @@ void DwarfDebug::beginModule() { const Module *M = MMI->getModule(); - NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); - if (!CU_Nodes) - return; - TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes); + TypeIdentifierMap = generateDITypeIdentifierMap(*M); + unsigned NumDebugCUs = 0; + for (DICompileUnit *CUNode : M->debug_compile_units()) { + (void)CUNode; + ++NumDebugCUs; + } - SingleCU = CU_Nodes->getNumOperands() == 1; + // Tell MMI whether we have debug info. + MMI->setDebugInfoAvailability(NumDebugCUs > 0); + SingleCU = NumDebugCUs == 1; - for (MDNode *N : CU_Nodes->operands()) { - auto *CUNode = cast<DICompileUnit>(N); + for (DICompileUnit *CUNode : M->debug_compile_units()) { DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode); for (auto *IE : CUNode->getImportedEntities()) CU.addImportedEntity(IE); @@ -500,9 +503,6 @@ void DwarfDebug::beginModule() { for (auto *IE : CUNode->getImportedEntities()) constructAndAddImportedEntityDIE(CU, IE); } - - // Tell MMI that we have debug info. - MMI->setDebugInfoAvailability(true); } void DwarfDebug::finishVariableDefinitions() { @@ -538,6 +538,9 @@ void DwarfDebug::collectDeadVariables() { if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { for (MDNode *N : CU_Nodes->operands()) { auto *TheCU = cast<DICompileUnit>(N); + if (TheCU->getEmissionKind() == DICompileUnit::NoDebug) + continue; + // Construct subprogram DIE and add variables DIEs. DwarfCompileUnit *SPCU = static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU)); @@ -1090,7 +1093,10 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // includes the directory of the cpp file being built, even when the file name // is absolute (such as an <> lookup header))) DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); - assert(TheCU && "Unable to find compile unit!"); + if (!TheCU) + // Once DISubprogram points to the owning CU, we can assert that the CU has + // a NoDebug EmissionKind here. + return; if (Asm->OutStreamer->hasRawTextSupport()) // Use a single line table if we are generating assembly. Asm->OutStreamer->getContext().setDwarfCompileUnitID(0); @@ -1113,7 +1119,10 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { "endFunction should be called with the same function as beginFunction"); if (!MMI->hasDebugInfo() || LScopes.empty() || - !MF->getFunction()->getSubprogram()) { + !MF->getFunction()->getSubprogram() || + // Once DISubprogram points to the owning CU, we can check for a + // CU with a NoDebug EmissionKind here. + !SPMap.lookup(MF->getFunction()->getSubprogram())) { // If we don't have a lexical scope for this function then there will // be a hole in the range information. Keep note of this by setting the // previously used section to nullptr. diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index fa4b860a58a..aa9ffcf9f3c 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -137,7 +137,7 @@ static DIScope *getNonCompileUnitScope(DIScope *N) { DICompileUnit *DIBuilder::createCompileUnit( unsigned Lang, StringRef Filename, StringRef Directory, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RunTimeVer, StringRef SplitName, - DICompileUnit::DebugEmissionKind Kind, uint64_t DWOId, bool EmitDebugInfo) { + DICompileUnit::DebugEmissionKind Kind, uint64_t DWOId) { assert(((Lang <= dwarf::DW_LANG_Fortran08 && Lang >= dwarf::DW_LANG_C89) || (Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) && @@ -152,15 +152,8 @@ DICompileUnit *DIBuilder::createCompileUnit( nullptr, nullptr, nullptr, nullptr, nullptr, DWOId); // Create a named metadata so that it is easier to find cu in a module. - // Note that we only generate this when the caller wants to actually - // emit debug information. When we are only interested in tracking - // source line locations throughout the backend, we prevent codegen from - // emitting debug info in the final output by not generating llvm.dbg.cu. - if (EmitDebugInfo) { - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); - NMD->addOperand(CUNode); - } - + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); + NMD->addOperand(CUNode); trackIfUnresolved(CUNode); return CUNode; } diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 2a60af4b7f3..e63c25484a5 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -39,10 +39,9 @@ DISubprogram *llvm::getDISubprogram(const MDNode *Scope) { } DITypeIdentifierMap -llvm::generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes) { +llvm::generateDITypeIdentifierMap(const Module &M) { DITypeIdentifierMap Map; - for (unsigned CUi = 0, CUe = CU_Nodes->getNumOperands(); CUi != CUe; ++CUi) { - auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(CUi)); + for (DICompileUnit *CU : M.debug_compile_units()) { DINodeArray Retain = CU->getRetainedTypes(); for (unsigned Ti = 0, Te = Retain.size(); Ti != Te; ++Ti) { if (!isa<DICompositeType>(Retain[Ti])) @@ -79,42 +78,38 @@ void DebugInfoFinder::reset() { } void DebugInfoFinder::InitializeTypeMap(const Module &M) { - if (!TypeMapInitialized) - if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) { - TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes); - TypeMapInitialized = true; - } + if (TypeMapInitialized) + return; + TypeIdentifierMap = generateDITypeIdentifierMap(M); + TypeMapInitialized = true; } void DebugInfoFinder::processModule(const Module &M) { InitializeTypeMap(M); - if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) { - for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { - auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); - addCompileUnit(CU); - for (auto *DIG : CU->getGlobalVariables()) { - if (addGlobalVariable(DIG)) { - processScope(DIG->getScope()); - processType(DIG->getType().resolve(TypeIdentifierMap)); - } + for (auto *CU : M.debug_compile_units()) { + addCompileUnit(CU); + for (auto *DIG : CU->getGlobalVariables()) { + if (addGlobalVariable(DIG)) { + processScope(DIG->getScope()); + processType(DIG->getType().resolve(TypeIdentifierMap)); } - for (auto *SP : CU->getSubprograms()) + } + for (auto *SP : CU->getSubprograms()) + processSubprogram(SP); + for (auto *ET : CU->getEnumTypes()) + processType(ET); + for (auto *RT : CU->getRetainedTypes()) + processType(RT); + for (auto *Import : CU->getImportedEntities()) { + auto *Entity = Import->getEntity().resolve(TypeIdentifierMap); + if (auto *T = dyn_cast<DIType>(Entity)) + processType(T); + else if (auto *SP = dyn_cast<DISubprogram>(Entity)) processSubprogram(SP); - for (auto *ET : CU->getEnumTypes()) - processType(ET); - for (auto *RT : CU->getRetainedTypes()) - processType(RT); - for (auto *Import : CU->getImportedEntities()) { - auto *Entity = Import->getEntity().resolve(TypeIdentifierMap); - if (auto *T = dyn_cast<DIType>(Entity)) - processType(T); - else if (auto *SP = dyn_cast<DISubprogram>(Entity)) - processSubprogram(SP); - else if (auto *NS = dyn_cast<DINamespace>(Entity)) - processScope(NS->getScope()); - else if (auto *M = dyn_cast<DIModule>(Entity)) - processScope(M->getScope()); - } + else if (auto *NS = dyn_cast<DINamespace>(Entity)) + processScope(NS->getScope()); + else if (auto *M = dyn_cast<DIModule>(Entity)) + processScope(M->getScope()); } } } diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index 0a2dcc1dcf6..bc613ff63c9 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/LLVMContext.h" @@ -380,6 +381,19 @@ void Module::setDataLayout(const DataLayout &Other) { DL = Other; } const DataLayout &Module::getDataLayout() const { return DL; } +DICompileUnit *Module::debug_compile_units_iterator::operator*() const { + return cast<DICompileUnit>(CUs->getOperand(Idx)); +} +DICompileUnit *Module::debug_compile_units_iterator::operator->() const { + return cast<DICompileUnit>(CUs->getOperand(Idx)); +} + +void Module::debug_compile_units_iterator::SkipNoDebugCUs() { + while (CUs && (Idx < CUs->getNumOperands()) && + ((*this)->getEmissionKind() == DICompileUnit::NoDebug)) + ++Idx; +} + //===----------------------------------------------------------------------===// // Methods to control the materialization of GlobalValues in the Module. // diff --git a/llvm/test/DebugInfo/X86/mixed-nodebug-cu.ll b/llvm/test/DebugInfo/X86/mixed-nodebug-cu.ll new file mode 100644 index 00000000000..acf84b16abb --- /dev/null +++ b/llvm/test/DebugInfo/X86/mixed-nodebug-cu.ll @@ -0,0 +1,50 @@ +; RUN: llc %s -o %t -filetype=obj +; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s +; CHECK: DW_TAG_compile_unit +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name{{.*}}"f" +; CHECK-NOT: DW_TAG_compile_unit +; +; created from +; void f() {} // compile with -g +; void g() {} // compile with -Rpass=inline +; and llvm-linking the result. + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + +; Function Attrs: nounwind ssp uwtable +define void @f() #0 !dbg !4 { +entry: + ret void, !dbg !15 +} + +; Function Attrs: nounwind ssp uwtable +define void @g() #0 !dbg !9 { +entry: + ret void, !dbg !16 +} + +attributes #0 = { nounwind ssp uwtable } + +!llvm.dbg.cu = !{!0, !7} +!llvm.ident = !{!11, !11} +!llvm.module.flags = !{!12, !13, !14} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 265328) (llvm/trunk 265330)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, subprograms: !3) +!1 = !DIFile(filename: "test.c", directory: "/Volumes/Data/llvm") +!2 = !{} +!3 = !{!4} +!4 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, variables: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{null} +!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 265328) (llvm/trunk 265330)", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !2, subprograms: !8) +!8 = !{!9} +!9 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 1, type: !10, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, variables: !2) +!10 = !DISubroutineType(types: !2) +!11 = !{!"clang version 3.9.0 (trunk 265328) (llvm/trunk 265330)"} +!12 = !{i32 2, !"Dwarf Version", i32 2} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"PIC Level", i32 2} +!15 = !DILocation(line: 1, column: 12, scope: !4) +!16 = !DILocation(line: 1, column: 12, scope: !9) diff --git a/llvm/tools/opt/BreakpointPrinter.cpp b/llvm/tools/opt/BreakpointPrinter.cpp index 363a7cd8007..f76ad79fbe7 100644 --- a/llvm/tools/opt/BreakpointPrinter.cpp +++ b/llvm/tools/opt/BreakpointPrinter.cpp @@ -45,9 +45,7 @@ struct BreakpointPrinter : public ModulePass { bool runOnModule(Module &M) override { TypeIdentifierMap.clear(); - NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu"); - if (CU_Nodes) - TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes); + TypeIdentifierMap = generateDITypeIdentifierMap(M); StringSet<> Processed; if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp")) |