Index: include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -124,6 +124,7 @@ uint32_t Length; uint16_t Version; const DWARFAbbreviationDeclarationSet *Abbrevs; + uint8_t UnitType; uint8_t AddrSize; uint64_t BaseAddr; // The compile unit debug information entry items. @@ -152,7 +153,7 @@ protected: virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); /// Size in bytes of the unit header. - virtual uint32_t getHeaderSize() const { return 11; } + virtual uint32_t getHeaderSize() const { return Version <= 4 ? 11 : 12; } public: DWARFUnit(DWARFContext &Context, const DWARFSection &Section, @@ -208,6 +209,7 @@ const DWARFAbbreviationDeclarationSet *getAbbreviations() const { return Abbrevs; } + uint8_t getUnitType() const { return UnitType; } uint8_t getAddressByteSize() const { return AddrSize; } uint8_t getRefAddrByteSize() const { if (Version == 2) Index: include/llvm/Support/Dwarf.h =================================================================== --- include/llvm/Support/Dwarf.h +++ include/llvm/Support/Dwarf.h @@ -305,6 +305,14 @@ #include "llvm/Support/Dwarf.def" }; +/// Constants for unit types in DWARF v5. +enum UnitType : unsigned char { +#define HANDLE_DW_UT(ID, NAME) DW_UT_##NAME = ID, +#include "llvm/Support/Dwarf.def" + DW_UT_lo_user = 0x80, + DW_UT_hi_user = 0xff +}; + // Constants for the DWARF5 Accelerator Table Proposal enum AcceleratorTable { // Data layout descriptors. @@ -373,6 +381,7 @@ StringRef MacinfoString(unsigned Encoding); StringRef CallFrameString(unsigned Encoding); StringRef ApplePropertyString(unsigned); +StringRef UnitTypeString(unsigned); StringRef AtomTypeString(unsigned Atom); StringRef GDBIndexEntryKindString(GDBIndexEntryKind Kind); StringRef GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage); Index: include/llvm/Support/Dwarf.def =================================================================== --- include/llvm/Support/Dwarf.def +++ include/llvm/Support/Dwarf.def @@ -19,7 +19,8 @@ defined HANDLE_DW_CC || defined HANDLE_DW_LNS || \ defined HANDLE_DW_LNE || defined HANDLE_DW_LNCT || \ defined HANDLE_DW_MACRO || defined HANDLE_DW_RLE || \ - defined HANDLE_DW_CFA || defined HANDLE_DW_APPLE_PROPERTY) + defined HANDLE_DW_CFA || defined HANDLE_DW_APPLE_PROPERTY || \ + defined HANDLE_DW_UT) #error "Missing macro definition of HANDLE_DW*" #endif @@ -87,6 +88,10 @@ #define HANDLE_DW_APPLE_PROPERTY(ID, NAME) #endif +#ifndef HANDLE_DW_UT +#define HANDLE_DW_UT(ID, NAME) +#endif + HANDLE_DW_TAG(0x0000, null) HANDLE_DW_TAG(0x0001, array_type) HANDLE_DW_TAG(0x0002, class_type) @@ -792,6 +797,13 @@ HANDLE_DW_APPLE_PROPERTY(0x2000, null_resettable) HANDLE_DW_APPLE_PROPERTY(0x4000, class) +// DWARF 5 Unit Types. +HANDLE_DW_UT(0x01, compile) +HANDLE_DW_UT(0x02, type) +HANDLE_DW_UT(0x03, partial) +HANDLE_DW_UT(0x04, skeleton) +HANDLE_DW_UT(0x05, split_compile) +HANDLE_DW_UT(0x06, split_type) #undef HANDLE_DW_TAG #undef HANDLE_DW_AT @@ -809,3 +821,4 @@ #undef HANDLE_DW_RLE #undef HANDLE_DW_CFA #undef HANDLE_DW_APPLE_PROPERTY +#undef HANDLE_DW_UT Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -690,7 +690,8 @@ Asm->OutStreamer->EmitLabel(LabelBegin); } - DwarfUnit::emitHeader(UseOffsets); + DwarfUnit::emitCommonHeader(UseOffsets, Skeleton ? dwarf::DW_UT_skeleton + : dwarf::DW_UT_compile); } /// addGlobalName - Add a new global name to the compile unit. Index: lib/CodeGen/AsmPrinter/DwarfUnit.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.h +++ lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -279,11 +279,13 @@ virtual unsigned getHeaderSize() const { return sizeof(int16_t) + // DWARF version number sizeof(int32_t) + // Offset Into Abbrev. Section - sizeof(int8_t); // Pointer Size (in bytes) + sizeof(int8_t) + // Pointer Size (in bytes) + (DD->getDwarfVersion() >= 5 ? sizeof(int8_t) + : 0); // DWARF 5 unit type } /// Emit the header for this unit, not including the initial length field. - virtual void emitHeader(bool UseOffsets); + virtual void emitHeader(bool UseOffsets) = 0; virtual DwarfCompileUnit &getCU() = 0; @@ -308,6 +310,9 @@ void updateAcceleratorTables(const DIScope *Context, const DIType *Ty, const DIE &TyDIE); + /// Emit the common part of the header for this unit. + void emitCommonHeader(bool UseOffsets, dwarf::UnitType UT); + private: void constructTypeDIE(DIE &Buffer, const DIBasicType *BTy); void constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy); Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1531,18 +1531,27 @@ return &StaticMemberDIE; } -void DwarfUnit::emitHeader(bool UseOffsets) { +void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) { // Emit size of content not including length itself Asm->OutStreamer->AddComment("Length of Unit"); Asm->EmitInt32(getHeaderSize() + getUnitDie().getSize()); Asm->OutStreamer->AddComment("DWARF version number"); - Asm->EmitInt16(DD->getDwarfVersion()); - Asm->OutStreamer->AddComment("Offset Into Abbrev. Section"); + unsigned Version = DD->getDwarfVersion(); + Asm->EmitInt16(Version); + + // DWARF 5 reorders the address size and adds a unit type. + if (Version >= 5) { + Asm->OutStreamer->AddComment("DWARF Unit Type"); + Asm->EmitInt8(UT); + Asm->OutStreamer->AddComment("Address Size (in bytes)"); + Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); + } // We share one abbreviations table across all units so it's always at the // start of the section. Use a relocatable offset where needed to ensure // linking doesn't invalidate that offset. + Asm->OutStreamer->AddComment("Offset Into Abbrev. Section"); const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); if (UseOffsets) Asm->EmitInt32(0); @@ -1550,12 +1559,14 @@ Asm->emitDwarfSymbolReference( TLOF.getDwarfAbbrevSection()->getBeginSymbol(), false); - Asm->OutStreamer->AddComment("Address Size (in bytes)"); - Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); + if (Version <= 4) { + Asm->OutStreamer->AddComment("Address Size (in bytes)"); + Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); + } } void DwarfTypeUnit::emitHeader(bool UseOffsets) { - DwarfUnit::emitHeader(UseOffsets); + DwarfUnit::emitCommonHeader(UseOffsets, dwarf::DW_UT_type); Asm->OutStreamer->AddComment("Type Signature"); Asm->OutStreamer->EmitIntValue(TypeSignature, sizeof(TypeSignature)); Asm->OutStreamer->AddComment("Type DIE Offset"); Index: lib/DebugInfo/DWARF/DWARFCompileUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -18,8 +18,10 @@ void DWARFCompileUnit::dump(raw_ostream &OS) { OS << format("0x%08x", getOffset()) << ": Compile Unit:" << " length = " << format("0x%08x", getLength()) - << " version = " << format("0x%04x", getVersion()) - << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset()) + << " version = " << format("0x%04x", getVersion()); + if (getVersion() >= 5) + OS << " unit_type = " << dwarf::UnitTypeString(getUnitType()); + OS << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset()) << " addr_size = " << format("0x%02x", getAddressByteSize()) << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n"; Index: lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFUnit.cpp +++ lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -88,7 +88,15 @@ bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { Length = debug_info.getU32(offset_ptr); Version = debug_info.getU16(offset_ptr); - uint64_t AbbrOffset = debug_info.getU32(offset_ptr); + uint64_t AbbrOffset; + if (Version >= 5) { + UnitType = debug_info.getU8(offset_ptr); + AddrSize = debug_info.getU8(offset_ptr); + AbbrOffset = debug_info.getU32(offset_ptr); + } else { + AbbrOffset = debug_info.getU32(offset_ptr); + AddrSize = debug_info.getU8(offset_ptr); + } if (IndexEntry) { if (AbbrOffset) return false; @@ -100,7 +108,6 @@ return false; AbbrOffset = AbbrEntry->Offset; } - AddrSize = debug_info.getU8(offset_ptr); bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); bool VersionOK = DWARFContext::isSupportedVersion(Version); Index: lib/Support/Dwarf.cpp =================================================================== --- lib/Support/Dwarf.cpp +++ lib/Support/Dwarf.cpp @@ -304,6 +304,17 @@ } } +StringRef llvm::dwarf::UnitTypeString(unsigned UT) { + switch (UT) { + default: + return StringRef(); +#define HANDLE_DW_UT(ID, NAME) \ + case DW_UT_##NAME: \ + return "DW_UT_" #NAME; +#include "llvm/Support/Dwarf.def" + } +} + StringRef llvm::dwarf::AtomTypeString(unsigned AT) { switch (AT) { case dwarf::DW_ATOM_null: Index: test/CodeGen/X86/dwarf-header.ll =================================================================== --- test/CodeGen/X86/dwarf-header.ll +++ test/CodeGen/X86/dwarf-header.ll @@ -0,0 +1,48 @@ +; RUN: %llc_dwarf -dwarf-version=4 < %s | FileCheck %s --check-prefixes=BOTH,DWARF4 +; RUN: %llc_dwarf -dwarf-version=5 < %s | FileCheck %s --check-prefixes=BOTH,DWARF5 +; +; Verify the full compile-unit header... +; BOTH: .section .debug_info +; BOTH-NEXT: .Lcu_begin0: +; BOTH-NEXT: .long {{.*}} # Length of Unit +; +; DWARF4-NEXT: .short 4 # DWARF version number +; DWARF4-NEXT: .long .debug_abbrev # Offset Into Abbrev. Section +; DWARF4-NEXT: .byte 8 # Address Size (in bytes) +; +; DWARF5-NEXT: .short 5 # DWARF version number +; DWARF5-NEXT: .byte 1 # DWARF Unit Type +; DWARF5-NEXT: .byte 8 # Address Size (in bytes) +; DWARF5-NEXT: .long .debug_abbrev # Offset Into Abbrev. Section +; +; ...immediately followed by the compile-unit DIE. +; BOTH-NEXT: .byte {{.*}} DW_TAG_compile_unit + +; ModuleID = 't.c' +source_filename = "t.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux" + +; Function Attrs: noinline nounwind uwtable +define i32 @five() #0 !dbg !6 { +entry: + ret i32 5, !dbg !10 +} + +attributes #0 = { noinline nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 5.0.0 (trunk 295294)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "t.c", directory: "/home/probinson/projects/scratch") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{!"clang version 5.0.0 (trunk 295294)"} +!6 = distinct !DISubprogram(name: "five", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, variables: !2) +!7 = !DISubroutineType(types: !8) +!8 = !{!9} +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DILocation(line: 2, column: 3, scope: !6) Index: unittests/DebugInfo/DWARF/DwarfGenerator.cpp =================================================================== --- unittests/DebugInfo/DWARF/DwarfGenerator.cpp +++ unittests/DebugInfo/DWARF/DwarfGenerator.cpp @@ -240,8 +240,14 @@ assert(Length != -1U); Asm->EmitInt32(Length); Asm->EmitInt16(Version); - Asm->EmitInt32(0); - Asm->EmitInt8(CU->getAddressSize()); + if (Version <= 4) { + Asm->EmitInt32(0); + Asm->EmitInt8(CU->getAddressSize()); + } else { + Asm->EmitInt8(dwarf::DW_UT_compile); + Asm->EmitInt8(CU->getAddressSize()); + Asm->EmitInt32(0); + } Asm->emitDwarfDIE(*CU->getUnitDIE().Die); }