diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h --- a/llvm/include/llvm/BinaryFormat/Dwarf.h +++ b/llvm/include/llvm/BinaryFormat/Dwarf.h @@ -470,6 +470,7 @@ StringRef LNStandardString(unsigned Standard); StringRef LNExtendedString(unsigned Encoding); StringRef MacinfoString(unsigned Encoding); +StringRef MacroString(unsigned Encoding); StringRef RangeListEncodingString(unsigned Encoding); StringRef LocListEncodingString(unsigned Encoding); StringRef CallFrameString(unsigned Encoding, Triple::ArchType Arch); @@ -498,6 +499,7 @@ unsigned getCallingConvention(StringRef LanguageString); unsigned getAttributeEncoding(StringRef EncodingString); unsigned getMacinfo(StringRef MacinfoString); +unsigned getMacro(StringRef MacroString); /// @} /// \defgroup DwarfConstantsVersioning Dwarf version for constants diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h @@ -49,6 +49,7 @@ virtual const DWARFSection &getRnglistsSection() const { return Dummy; } virtual StringRef getMacinfoSection() const { return ""; } virtual StringRef getMacinfoDWOSection() const { return ""; } + virtual StringRef getMacroSection() const { return ""; } virtual const DWARFSection &getPubnamesSection() const { return Dummy; } virtual const DWARFSection &getPubtypesSection() const { return Dummy; } virtual const DWARFSection &getGnuPubnamesSection() const { return Dummy; } diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h --- a/llvm/include/llvm/MC/MCObjectFileInfo.h +++ b/llvm/include/llvm/MC/MCObjectFileInfo.h @@ -89,6 +89,7 @@ MCSection *DwarfARangesSection = nullptr; MCSection *DwarfRangesSection = nullptr; MCSection *DwarfMacinfoSection = nullptr; + MCSection *DwarfMacroSection = nullptr; // The pubnames section is no longer generated by default. The generation // can be enabled by a compiler flag. MCSection *DwarfPubNamesSection = nullptr; @@ -272,6 +273,7 @@ MCSection *getDwarfRnglistsSection() const { return DwarfRnglistsSection; } MCSection *getDwarfLoclistsSection() const { return DwarfLoclistsSection; } MCSection *getDwarfMacinfoSection() const { return DwarfMacinfoSection; } + MCSection *getDwarfMacroSection() const { return DwarfMacroSection; } MCSection *getDwarfDebugNamesSection() const { return DwarfDebugNamesSection; diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp --- a/llvm/lib/BinaryFormat/Dwarf.cpp +++ b/llvm/lib/BinaryFormat/Dwarf.cpp @@ -448,6 +448,34 @@ } } +StringRef llvm::dwarf::MacroString(unsigned Encoding) { + switch (Encoding) { + default: + return StringRef(); +#define HANDLE_DW_MACRO(ID, NAME) \ + case DW_MACRO_##NAME: \ + return "DW_MACRO_" #NAME; +#include "llvm/BinaryFormat/Dwarf.def" + } +} + +unsigned llvm::dwarf::getMacro(StringRef MacroString) { + return StringSwitch(MacroString) + .Case("DW_MACRO_define", DW_MACRO_define) + .Case("DW_MACRO_undef", DW_MACRO_undef) + .Case("DW_MACRO_start_file", DW_MACRO_start_file) + .Case("DW_MACRO_end_file", DW_MACRO_end_file) + .Case("DW_MACRO_define_strp", DW_MACRO_define_strp) + .Case("DW_MACRO_undef_strp", DW_MACRO_undef_strp) + .Case("DW_MACRO_import", DW_MACRO_import) + .Case("DW_MACRO_define_sup", DW_MACRO_define_sup) + .Case("DW_MACRO_undef_sup", DW_MACRO_undef_sup) + .Case("DW_MACRO_import_sup", DW_MACRO_import_sup) + .Case("DW_MACRO_define_strx", DW_MACRO_define_strx) + .Case("DW_MACRO_undef_strx", DW_MACRO_undef_strx) + .Default(DW_MACINFO_invalid); +} + StringRef llvm::dwarf::MacinfoString(unsigned Encoding) { switch (Encoding) { // Macinfo Type Encodings diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1181,16 +1181,29 @@ } auto *CUNode = cast(P.first); - // If compile Unit has macros, emit "DW_AT_macro_info" attribute. if (CUNode->getMacros()) { - if (useSplitDwarf()) - TheCU.addSectionDelta(TheCU.getUnitDie(), dwarf::DW_AT_macro_info, - U.getMacroLabelBegin(), - TLOF.getDwarfMacinfoDWOSection()->getBeginSymbol()); - else - U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macro_info, - U.getMacroLabelBegin(), - TLOF.getDwarfMacinfoSection()->getBeginSymbol()); + // If compile Unit has macros, emit "DW_AT_macro_info/DW_AT_macros" + // attribute. + if (CUNode->getMacros()) { + if (getDwarfVersion() >= 5) { + // FIXME: Add support for DWARFv5 DW_AT_macros attribute for split + // case. + if (!useSplitDwarf()) + U.addSectionDelta(U.getUnitDie(), dwarf::DW_AT_macros, + U.getMacroLabelBegin(), + TLOF.getDwarfMacroSection()->getBeginSymbol()); + } else { + if (useSplitDwarf()) + TheCU.addSectionDelta( + TheCU.getUnitDie(), dwarf::DW_AT_macro_info, + U.getMacroLabelBegin(), + TLOF.getDwarfMacinfoDWOSection()->getBeginSymbol()); + else + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macro_info, + U.getMacroLabelBegin(), + TLOF.getDwarfMacinfoSection()->getBeginSymbol()); + } + } } } @@ -1224,7 +1237,6 @@ // Finalize the debug info for the module. finalizeModuleInfo(); - emitDebugStr(); if (useSplitDwarf()) // Emit debug_loc.dwo/debug_loclists.dwo section. @@ -1250,9 +1262,11 @@ // Emit info into a debug macinfo.dwo section. emitDebugMacinfoDWO(); else - // Emit info into a debug macinfo section. + // Emit info into a debug macinfo/macro section. emitDebugMacinfo(); + emitDebugStr(); + if (useSplitDwarf()) { emitDebugStrDWO(); emitDebugInfoDWO(); @@ -2755,6 +2769,36 @@ Asm->getObjFileLowering().getDwarfRnglistsDWOSection()); } +// Emit the header of a DWARF 5 macro section. +static void emitMacroHeader(AsmPrinter *Asm, const DwarfDebug &DD, + const DwarfCompileUnit &CU) { + enum HeaderFlagMask { + OFFSET_SIZE_32 = 0, + OFFSET_SIZE_64 = 1, + DEBUG_LINE_OFFSET = 2, + OPCODE_OPERANDS_TABLE = 3 + }; + dwarf::FormParams DwarfParams; + uint8_t Flags = 0; + Asm->OutStreamer->AddComment("Macro information version"); + Asm->emitInt16(5); + if (DwarfParams.getDwarfOffsetByteSize() == 4) + Flags |= OFFSET_SIZE_32; + if (Asm->getObjFileLowering().getDwarfLineSection()) + Flags |= DEBUG_LINE_OFFSET; + // FIXME: We are not setting opcode_operands_table_flag, since we're not + // emitting opcode_operands_table + Asm->OutStreamer->AddComment("Flags: 32 bit, lineptr present"); + Asm->emitInt8(Flags); + Asm->OutStreamer->AddComment("lineptr"); + if (DD.useSectionsAsReferences()) + Asm->OutStreamer->EmitSymbolValue( + Asm->getObjFileLowering().getDwarfLineSection()->getBeginSymbol(), 4); + else + Asm->OutStreamer->EmitSymbolValue( + Asm->OutStreamer->getDwarfLineTableSymbol(CU.getUniqueID()), 4); +} + void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) { for (auto *MN : Nodes) { if (auto *M = dyn_cast(MN)) @@ -2767,26 +2811,64 @@ } void DwarfDebug::emitMacro(DIMacro &M) { - Asm->EmitULEB128(M.getMacinfoType()); - Asm->EmitULEB128(M.getLine()); StringRef Name = M.getName(); StringRef Value = M.getValue(); - Asm->OutStreamer->EmitBytes(Name); - if (!Value.empty()) { - // There should be one space between macro name and macro value. - Asm->emitInt8(' '); - Asm->OutStreamer->EmitBytes(Value); + bool UseMacro = getDwarfVersion() >= 5; + + if (UseMacro) { + if (M.getMacinfoType() == llvm::dwarf::DW_MACINFO_define) { + Asm->OutStreamer->AddComment( + dwarf::MacroString(dwarf::DW_MACRO_define_strp)); + Asm->EmitULEB128(dwarf::getMacro("DW_MACRO_define_strp")); + } else { + Asm->OutStreamer->AddComment( + dwarf::MacroString(dwarf::DW_MACRO_undef_strp)); + Asm->EmitULEB128(dwarf::getMacro("DW_MACRO_undef_strp")); + } + Asm->OutStreamer->AddComment("Line Number"); + Asm->EmitULEB128(M.getLine()); + Asm->OutStreamer->AddComment("Macro String"); + Asm->OutStreamer->EmitSymbolValue( + this->InfoHolder.getStringPool() + .getEntry(*Asm, Name.str() + ' ' + Value.str()) + .getSymbol(), + 4); + } else { + Asm->EmitULEB128(M.getMacinfoType()); + Asm->EmitULEB128(M.getLine()); + Asm->OutStreamer->EmitBytes(Name); + if (!Value.empty()) { + // There should be one space between macro name and macro value. + Asm->emitInt8(' '); + Asm->OutStreamer->EmitBytes(Value); + } + Asm->emitInt8('\0'); } - Asm->emitInt8('\0'); } void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) { + // DWARFv5 macro and DWARFv4 macinfo share some common encodings, + // so for readibility/uniformity, We are explicitly emitting those. assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file); - Asm->EmitULEB128(dwarf::DW_MACINFO_start_file); + bool UseMacro = getDwarfVersion() >= 5; + if (UseMacro) { + Asm->OutStreamer->AddComment( + dwarf::MacroString(dwarf::DW_MACRO_start_file)); + Asm->EmitULEB128(dwarf::DW_MACRO_start_file); + } else { + Asm->EmitULEB128(dwarf::DW_MACINFO_start_file); + } + Asm->OutStreamer->AddComment("Line Number"); Asm->EmitULEB128(F.getLine()); + Asm->OutStreamer->AddComment("File Number"); Asm->EmitULEB128(U.getOrCreateSourceID(F.getFile())); handleMacroNodes(F.getElements(), U); - Asm->EmitULEB128(dwarf::DW_MACINFO_end_file); + if (UseMacro) { + Asm->OutStreamer->AddComment(dwarf::MacroString(dwarf::DW_MACRO_end_file)); + Asm->EmitULEB128(dwarf::getMacro("DW_MACRO_end_file")); + } else { + Asm->EmitULEB128(dwarf::DW_MACINFO_end_file); + } } void DwarfDebug::emitDebugMacinfoImpl(MCSection *Section) { @@ -2800,6 +2882,8 @@ continue; Asm->OutStreamer->SwitchSection(Section); Asm->OutStreamer->EmitLabel(U.getMacroLabelBegin()); + if (getDwarfVersion() >= 5) + emitMacroHeader(Asm, *this, U); handleMacroNodes(Macros, U); Asm->OutStreamer->AddComment("End Of Macro List Mark"); Asm->emitInt8(0); @@ -2808,10 +2892,17 @@ /// Emit macros into a debug macinfo section. void DwarfDebug::emitDebugMacinfo() { + if (getDwarfVersion() >= 5) { + emitDebugMacinfoImpl(Asm->getObjFileLowering().getDwarfMacroSection()); + return; + } emitDebugMacinfoImpl(Asm->getObjFileLowering().getDwarfMacinfoSection()); } void DwarfDebug::emitDebugMacinfoDWO() { + // FIXME: Add support for macro.dwo section. + if (getDwarfVersion() >= 5) + return; emitDebugMacinfoImpl(Asm->getObjFileLowering().getDwarfMacinfoDWOSection()); } diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -276,6 +276,9 @@ DwarfMacinfoSection = Ctx->getMachOSection("__DWARF", "__debug_macinfo", MachO::S_ATTR_DEBUG, SectionKind::getMetadata(), "debug_macinfo"); + DwarfMacroSection = + Ctx->getMachOSection("__DWARF", "__debug_macro", MachO::S_ATTR_DEBUG, + SectionKind::getMetadata(), "debug_macro"); DwarfDebugInlineSection = Ctx->getMachOSection("__DWARF", "__debug_inlined", MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); @@ -427,6 +430,7 @@ Ctx->getELFSection(".debug_ranges", DebugSecType, 0); DwarfMacinfoSection = Ctx->getELFSection(".debug_macinfo", DebugSecType, 0); + DwarfMacroSection = Ctx->getELFSection(".debug_macro", DebugSecType, 0); // DWARF5 Experimental Debug Info @@ -625,6 +629,11 @@ COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata(), "debug_macinfo"); + DwarfMacroSection = Ctx->getCOFFSection( + ".debug_macro", + COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata(), "debug_macro"); DwarfMacinfoDWOSection = Ctx->getCOFFSection( ".debug_macinfo.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -761,6 +770,8 @@ Ctx->getWasmSection(".debug_ranges", SectionKind::getMetadata()); DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", SectionKind::getMetadata()); + DwarfMacroSection = + Ctx->getWasmSection(".debug_macro", SectionKind::getMetadata()); DwarfAddrSection = Ctx->getWasmSection(".debug_addr", SectionKind::getMetadata()); DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", SectionKind::getMetadata()); DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", SectionKind::getMetadata()); diff --git a/llvm/test/DebugInfo/MIR/X86/dbg-stack-value-range.mir b/llvm/test/DebugInfo/MIR/X86/dbg-stack-value-range.mir --- a/llvm/test/DebugInfo/MIR/X86/dbg-stack-value-range.mir +++ b/llvm/test/DebugInfo/MIR/X86/dbg-stack-value-range.mir @@ -18,9 +18,6 @@ # CHECK-NEXT: .Ltmp6: # CHECK: .Lfunc_end0: # -# CHECK: .Linfo_string7: -# CHECK-NEXT: .asciz "local1" -# # CHECK: .Ldebug_loc2: # CHECK-NEXT: .quad .Ltmp1-.Lfunc_begin0 # CHECK-NEXT: .quad .Ltmp4-.Lfunc_begin0 @@ -34,8 +31,9 @@ # # CHECK: .long .Ldebug_loc2 # DW_AT_location # CHECK-NEXT: .long .Linfo_string7 # DW_AT_name - - +# +# CHECK: .Linfo_string7: +# CHECK-NEXT: .asciz "local1" --- | ; ModuleID = 'dbg-stack-value-range.ll' source_filename = "dbg-stack-value-range.c" diff --git a/llvm/test/DebugInfo/X86/stringpool.ll b/llvm/test/DebugInfo/X86/stringpool.ll --- a/llvm/test/DebugInfo/X86/stringpool.ll +++ b/llvm/test/DebugInfo/X86/stringpool.ll @@ -14,11 +14,6 @@ !3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang version 3.1 (trunk 143009)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5) !5 = !{} -; Verify that "yyyy" ended up in the stringpool. -; LINUX: .section .debug_str,"MS",@progbits,1 -; LINUX: yyyy -; DARWIN: .section __DWARF,__debug_str,regular,debug -; DARWIN: .asciz "yyyy" ## string offset=[[YYYY:[0-9]+]] ; Verify that we refer to 'yyyy' with a relocation. ; LINUX: .long .Linfo_string3 # DW_AT_name @@ -30,14 +25,21 @@ ; LINUX-NEXT: .byte 3 ; LINUX-NEXT: .quad yyyy +; Verify that "yyyy" ended up in the stringpool. +; LINUX: .section .debug_str,"MS",@progbits,1 +; LINUX: yyyy + ; Verify that we refer to 'yyyy' with a direct offset. -; DARWIN: .long [[YYYY]] -; DARWIN-NEXT: .long {{[0-9]+}} ## DW_AT_type +; DARWIN: .long {{[0-9]+}} ## DW_AT_type ; DARWIN-NEXT: ## DW_AT_external ; DARWIN-NEXT: .byte 1 ## DW_AT_decl_file ; DARWIN-NEXT: .byte 1 ## DW_AT_decl_line ; DARWIN-NEXT: .byte 9 ## DW_AT_location ; DARWIN-NEXT: .byte 3 ; DARWIN-NEXT: .quad _yyyy + +; Verify that "yyyy" ended up in the stringpool. +; DARWIN: .section __DWARF,__debug_str,regular,debug +; DARWIN: .asciz "yyyy" ## string offset=[[YYYY:[0-9]+]] !6 = !{!0} !7 = !{i32 1, !"Debug Info Version", i32 3}