Index: llvm/include/llvm/BinaryFormat/Dwarf.h =================================================================== --- llvm/include/llvm/BinaryFormat/Dwarf.h +++ 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 Index: llvm/include/llvm/BinaryFormat/Dwarf.def =================================================================== --- llvm/include/llvm/BinaryFormat/Dwarf.def +++ llvm/include/llvm/BinaryFormat/Dwarf.def @@ -17,6 +17,7 @@ defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_DEFAULTED || \ defined HANDLE_DW_CC || defined HANDLE_DW_LNS || defined HANDLE_DW_LNE || \ defined HANDLE_DW_LNCT || defined HANDLE_DW_MACRO || \ + defined HANDLE_MACRO_FLAGS || \ defined HANDLE_DW_RLE || defined HANDLE_DW_LLE || \ (defined HANDLE_DW_CFA && defined HANDLE_DW_CFA_PRED) || \ defined HANDLE_DW_APPLE_PROPERTY || defined HANDLE_DW_UT || \ @@ -87,6 +88,10 @@ #define HANDLE_DW_MACRO(ID, NAME) #endif +#ifndef HANDLE_MACRO_FLAGS +#define HANDLE_MACRO_FLAGS(ID, NAME) +#endif + #ifndef HANDLE_DW_RLE #define HANDLE_DW_RLE(ID, NAME) #endif @@ -821,6 +826,11 @@ HANDLE_DW_MACRO(0x0a, import_sup) HANDLE_DW_MACRO(0x0b, define_strx) HANDLE_DW_MACRO(0x0c, undef_strx) +// DWARF v5 Macro header flags +HANDLE_MACRO_FLAGS(0x00, OFFSET_SIZE_32) +HANDLE_MACRO_FLAGS(0x01, OFFSET_SIZE_64) +HANDLE_MACRO_FLAGS(0x02, DEBUG_LINE_OFFSET) +HANDLE_MACRO_FLAGS(0x03, OPCODE_OPERANDS_TABLE) // DWARF v5 Range List Entry encoding values. HANDLE_DW_RLE(0x00, end_of_list) @@ -956,6 +966,7 @@ #undef HANDLE_DW_LNE #undef HANDLE_DW_LNCT #undef HANDLE_DW_MACRO +#undef HANDLE_MACRO_FLAGS #undef HANDLE_DW_RLE #undef HANDLE_DW_LLE #undef HANDLE_DW_CFA Index: llvm/include/llvm/MC/MCObjectFileInfo.h =================================================================== --- llvm/include/llvm/MC/MCObjectFileInfo.h +++ 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; @@ -275,6 +276,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; Index: llvm/lib/BinaryFormat/Dwarf.cpp =================================================================== --- llvm/lib/BinaryFormat/Dwarf.cpp +++ llvm/lib/BinaryFormat/Dwarf.cpp @@ -448,6 +448,24 @@ } } +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) +#define HANDLE_DW_MACRO(ID, NAME) .Case("DW_MACRO_" #NAME, ID) +#include "llvm/BinaryFormat/Dwarf.def" + .Default(DW_MACINFO_invalid); +} + StringRef llvm::dwarf::MacinfoString(unsigned Encoding) { switch (Encoding) { // Macinfo Type Encodings Index: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -523,6 +523,9 @@ void emitDebugMacinfoImpl(MCSection *Section); void emitMacro(DIMacro &M); void emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U); + void emitMacroFileImpl(DIMacroFile &F, DwarfCompileUnit &U, + unsigned StartFile, unsigned EndFile, + StringRef (*MacroFormToString)(unsigned Form)); void handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U); /// DWARF 5 Experimental Split Dwarf Emitters Index: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1217,18 +1217,29 @@ } auto *CUNode = cast(P.first); - // If compile Unit has macros, emit "DW_AT_macro_info" attribute. + // If compile Unit has macros, emit "DW_AT_macro_info/DW_AT_macros" + // attribute. if (CUNode->getMacros()) { - if (useSplitDwarf()) - TheCU.addSectionDelta(TheCU.getUnitDie(), dwarf::DW_AT_macro_info, + if (getDwarfVersion() >= 5) { + // FIXME: Add support for DWARFv5 DW_AT_macros attribute for split + // case. + if (!useSplitDwarf()) + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macros, U.getMacroLabelBegin(), - TLOF.getDwarfMacinfoDWOSection()->getBeginSymbol()); - else - U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macro_info, - U.getMacroLabelBegin(), - TLOF.getDwarfMacinfoSection()->getBeginSymbol()); + 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()); + } + } } - } // Emit all frontend-produced Skeleton CUs, i.e., Clang modules. for (auto *CUNode : MMI->getModule()->debug_compile_units()) @@ -1284,7 +1295,7 @@ // 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(); @@ -2785,6 +2796,35 @@ 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 { +#define HANDLE_MACRO_FLAGS(ID, NAME) MACRO_FLAG_##NAME = ID, +#include "llvm/BinaryFormat/Dwarf.def" + }; + dwarf::FormParams DwarfParams; + uint8_t Flags = 0; + Asm->OutStreamer->AddComment("Macro information version"); + Asm->emitInt16(5); + assert(DwarfParams.getDwarfOffsetByteSize() == 4 && "DWARF64 not supported!"); + // We are setting Offset and line offset flags unconditionally here, + // since we're only supporting DWARF32 and line offset should be mostly + // present. + Flags |= MACRO_FLAG_OFFSET_SIZE_32 | MACRO_FLAG_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)) @@ -2797,26 +2837,67 @@ } 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) { + unsigned Type = M.getMacinfoType() == dwarf::DW_MACINFO_define + ? dwarf::DW_MACRO_define_strp + : dwarf::DW_MACRO_undef_strp; + Asm->OutStreamer->AddComment(dwarf::MacroString(Type)); + Asm->EmitULEB128(Type); + Asm->OutStreamer->AddComment("Line Number"); + Asm->EmitULEB128(M.getLine()); + Asm->OutStreamer->AddComment("Macro String"); + Asm->OutStreamer->EmitSymbolValue( + this->InfoHolder.getStringPool() + .getEntry(*Asm, (Name + " " + Value).str()) + .getSymbol(), + 4); + } else { + Asm->OutStreamer->AddComment(dwarf::MacinfoString(M.getMacinfoType())); + Asm->EmitULEB128(M.getMacinfoType()); + Asm->OutStreamer->AddComment("Line Number"); + Asm->EmitULEB128(M.getLine()); + Asm->OutStreamer->AddComment("Macro String"); + Asm->OutStreamer->EmitBytes(Name); + if (!Value.empty()) { + // There should be one space between macro name and macro value. + Asm->emitInt8(' '); + Asm->OutStreamer->AddComment("Macro Value="); + Asm->OutStreamer->EmitBytes(Value); + } + Asm->emitInt8('\0'); } - Asm->emitInt8('\0'); } -void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) { - assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file); - Asm->EmitULEB128(dwarf::DW_MACINFO_start_file); +void DwarfDebug::emitMacroFileImpl( + DIMacroFile &F, DwarfCompileUnit &U, unsigned StartFile, unsigned EndFile, + StringRef (*MacroFormToString)(unsigned Form)) { + + Asm->OutStreamer->AddComment(MacroFormToString(StartFile)); + Asm->EmitULEB128(StartFile); + 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); + Asm->OutStreamer->AddComment(MacroFormToString(EndFile)); + Asm->EmitULEB128(EndFile); +} + +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); + bool UseMacro = getDwarfVersion() >= 5; + if (UseMacro) + emitMacroFileImpl(F, U, dwarf::DW_MACRO_start_file, + dwarf::DW_MACRO_end_file, dwarf::MacroString); + else + emitMacroFileImpl(F, U, dwarf::DW_MACINFO_start_file, + dwarf::DW_MACINFO_end_file, dwarf::MacinfoString); } void DwarfDebug::emitDebugMacinfoImpl(MCSection *Section) { @@ -2830,18 +2911,26 @@ 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); } } -/// Emit macros into a debug macinfo section. +/// Emit macros into a debug macinfo/macro section. void DwarfDebug::emitDebugMacinfo() { - emitDebugMacinfoImpl(Asm->getObjFileLowering().getDwarfMacinfoSection()); + auto &ObjLower = Asm->getObjFileLowering(); + emitDebugMacinfoImpl(getDwarfVersion() >= 5 + ? ObjLower.getDwarfMacroSection() + : ObjLower.getDwarfMacinfoSection()); } void DwarfDebug::emitDebugMacinfoDWO() { + // FIXME: Add support for macro.dwo section. + if (getDwarfVersion() >= 5) + return; emitDebugMacinfoImpl(Asm->getObjFileLowering().getDwarfMacinfoDWOSection()); } Index: llvm/lib/MC/MCObjectFileInfo.cpp =================================================================== --- llvm/lib/MC/MCObjectFileInfo.cpp +++ 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 @@ -635,6 +639,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 | @@ -771,6 +780,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());