mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
Added support for macro emission in dwarf (supporting DWARF version 4).
Differential Revision: http://reviews.llvm.org/D15495 llvm-svn: 257060
This commit is contained in:
parent
36113b2917
commit
a54507b1df
@ -29,6 +29,48 @@ class MCSymbol;
|
||||
class raw_ostream;
|
||||
class DwarfTypeUnit;
|
||||
|
||||
// AsmStreamerBase - A base abstract interface class defines methods that
|
||||
// can be implemented to stream objects or can be implemented to
|
||||
// calculate the size of the streamed objects.
|
||||
// The derived classes will use an AsmPrinter to implement the methods.
|
||||
//
|
||||
// TODO: complete this interface and use it to merge EmitValue and SizeOf
|
||||
// methods in the DIE classes below.
|
||||
class AsmStreamerBase {
|
||||
protected:
|
||||
const AsmPrinter *AP;
|
||||
AsmStreamerBase(const AsmPrinter *AP) : AP(AP) {}
|
||||
|
||||
public:
|
||||
virtual ~AsmStreamerBase() {}
|
||||
virtual unsigned emitULEB128(uint64_t Value, const char *Desc = nullptr,
|
||||
unsigned PadTo = 0) = 0;
|
||||
virtual unsigned emitInt8(unsigned char Value) = 0;
|
||||
virtual unsigned emitBytes(StringRef Data) = 0;
|
||||
};
|
||||
|
||||
/// EmittingAsmStreamer - Implements AbstractAsmStreamer to stream objects.
|
||||
/// Notice that the return value is not the actual size of the streamed object.
|
||||
/// For size calculation use SizeReporterAsmStreamer.
|
||||
class EmittingAsmStreamer : public AsmStreamerBase {
|
||||
public:
|
||||
EmittingAsmStreamer(const AsmPrinter *AP) : AsmStreamerBase(AP) {}
|
||||
unsigned emitULEB128(uint64_t Value, const char *Desc = nullptr,
|
||||
unsigned PadTo = 0) override;
|
||||
unsigned emitInt8(unsigned char Value) override;
|
||||
unsigned emitBytes(StringRef Data) override;
|
||||
};
|
||||
|
||||
/// SizeReporterAsmStreamer - Only reports the size of the streamed objects.
|
||||
class SizeReporterAsmStreamer : public AsmStreamerBase {
|
||||
public:
|
||||
SizeReporterAsmStreamer(const AsmPrinter *AP) : AsmStreamerBase(AP) {}
|
||||
unsigned emitULEB128(uint64_t Value, const char *Desc = nullptr,
|
||||
unsigned PadTo = 0) override;
|
||||
unsigned emitInt8(unsigned char Value) override;
|
||||
unsigned emitBytes(StringRef Data) override;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a
|
||||
/// Dwarf abbreviation.
|
||||
|
@ -92,6 +92,7 @@ protected:
|
||||
MCSection *DwarfLocSection;
|
||||
MCSection *DwarfARangesSection;
|
||||
MCSection *DwarfRangesSection;
|
||||
MCSection *DwarfMacinfoSection;
|
||||
// The pubnames section is no longer generated by default. The generation
|
||||
// can be enabled by a compiler flag.
|
||||
MCSection *DwarfPubNamesSection;
|
||||
@ -245,6 +246,7 @@ public:
|
||||
MCSection *getDwarfLocSection() const { return DwarfLocSection; }
|
||||
MCSection *getDwarfARangesSection() const { return DwarfARangesSection; }
|
||||
MCSection *getDwarfRangesSection() const { return DwarfRangesSection; }
|
||||
MCSection *getDwarfMacinfoSection() const { return DwarfMacinfoSection; }
|
||||
|
||||
// DWARF5 Experimental Debug Info Sections
|
||||
MCSection *getDwarfAccelNamesSection() const {
|
||||
|
@ -31,6 +31,39 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// EmittingAsmStreamer Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
unsigned EmittingAsmStreamer::emitULEB128(uint64_t Value, const char *Desc,
|
||||
unsigned PadTo) {
|
||||
AP->EmitULEB128(Value, Desc, PadTo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned EmittingAsmStreamer::emitInt8(unsigned char Value) {
|
||||
AP->EmitInt8(Value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned EmittingAsmStreamer::emitBytes(StringRef Data) {
|
||||
AP->OutStreamer->EmitBytes(Data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SizeReporterAsmStreamer Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
unsigned SizeReporterAsmStreamer::emitULEB128(uint64_t Value, const char *Desc,
|
||||
unsigned PadTo) {
|
||||
return getULEB128Size(Value);
|
||||
}
|
||||
|
||||
unsigned SizeReporterAsmStreamer::emitInt8(unsigned char Value) { return 1; }
|
||||
|
||||
unsigned SizeReporterAsmStreamer::emitBytes(StringRef Data) {
|
||||
return Data.size();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DIEAbbrevData Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -561,6 +561,8 @@ void DwarfDebug::finalizeModuleInfo() {
|
||||
// Collect info for variables that were optimized out.
|
||||
collectDeadVariables();
|
||||
|
||||
unsigned MacroOffset = 0;
|
||||
std::unique_ptr<AsmStreamerBase> AS(new SizeReporterAsmStreamer(Asm));
|
||||
// Handle anything that needs to be done on a per-unit basis after
|
||||
// all other generation.
|
||||
for (const auto &P : CUMap) {
|
||||
@ -613,6 +615,15 @@ void DwarfDebug::finalizeModuleInfo() {
|
||||
U.setBaseAddress(TheCU.getRanges().front().getStart());
|
||||
U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges());
|
||||
}
|
||||
|
||||
auto *CUNode = cast<DICompileUnit>(P.first);
|
||||
if (CUNode->getMacros()) {
|
||||
// Compile Unit has macros, emit "DW_AT_macro_info" attribute.
|
||||
U.addUInt(U.getUnitDie(), dwarf::DW_AT_macro_info,
|
||||
dwarf::DW_FORM_sec_offset, MacroOffset);
|
||||
// Update macro section offset
|
||||
MacroOffset += handleMacroNodes(AS.get(), CUNode->getMacros(), U);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute DIE offsets and sizes.
|
||||
@ -656,6 +667,9 @@ void DwarfDebug::endModule() {
|
||||
// Emit info into a debug ranges section.
|
||||
emitDebugRanges();
|
||||
|
||||
// Emit info into a debug macinfo section.
|
||||
emitDebugMacinfo();
|
||||
|
||||
if (useSplitDwarf()) {
|
||||
emitDebugStrDWO();
|
||||
emitDebugInfoDWO();
|
||||
@ -1833,6 +1847,70 @@ void DwarfDebug::emitDebugRanges() {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned DwarfDebug::handleMacroNodes(AsmStreamerBase *AS,
|
||||
DIMacroNodeArray Nodes,
|
||||
DwarfCompileUnit &U) {
|
||||
unsigned Size = 0;
|
||||
for (auto *MN : Nodes) {
|
||||
if (auto *M = dyn_cast<DIMacro>(MN))
|
||||
Size += emitMacro(AS, *M);
|
||||
else if (auto *F = dyn_cast<DIMacroFile>(MN))
|
||||
Size += emitMacroFile(AS, *F, U);
|
||||
else
|
||||
llvm_unreachable("Unexpected DI type!");
|
||||
}
|
||||
return Size;
|
||||
}
|
||||
|
||||
unsigned DwarfDebug::emitMacro(AsmStreamerBase *AS, DIMacro &M) {
|
||||
int Size = 0;
|
||||
Size += AS->emitULEB128(M.getMacinfoType());
|
||||
Size += AS->emitULEB128(M.getLine());
|
||||
StringRef Name = M.getName();
|
||||
StringRef Value = M.getValue();
|
||||
Size += AS->emitBytes(Name);
|
||||
if (!Value.empty()) {
|
||||
// There should be one space between macro name and macro value.
|
||||
Size += AS->emitInt8(' ');
|
||||
Size += AS->emitBytes(Value);
|
||||
}
|
||||
Size += AS->emitInt8('\0');
|
||||
return Size;
|
||||
}
|
||||
|
||||
unsigned DwarfDebug::emitMacroFile(AsmStreamerBase *AS, DIMacroFile &F,
|
||||
DwarfCompileUnit &U) {
|
||||
int Size = 0;
|
||||
assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file);
|
||||
Size += AS->emitULEB128(dwarf::DW_MACINFO_start_file);
|
||||
Size += AS->emitULEB128(F.getLine());
|
||||
DIFile *File = F.getFile();
|
||||
unsigned FID =
|
||||
U.getOrCreateSourceID(File->getFilename(), File->getDirectory());
|
||||
Size += AS->emitULEB128(FID);
|
||||
Size += handleMacroNodes(AS, F.getElements(), U);
|
||||
Size += AS->emitULEB128(dwarf::DW_MACINFO_end_file);
|
||||
return Size;
|
||||
}
|
||||
|
||||
// Emit visible names into a debug macinfo section.
|
||||
void DwarfDebug::emitDebugMacinfo() {
|
||||
if (MCSection *Macinfo = Asm->getObjFileLowering().getDwarfMacinfoSection()) {
|
||||
// Start the dwarf macinfo section.
|
||||
Asm->OutStreamer->SwitchSection(Macinfo);
|
||||
}
|
||||
std::unique_ptr<AsmStreamerBase> AS(new EmittingAsmStreamer(Asm));
|
||||
for (const auto &P : CUMap) {
|
||||
auto &TheCU = *P.second;
|
||||
auto *SkCU = TheCU.getSkeleton();
|
||||
DwarfCompileUnit &U = SkCU ? *SkCU : TheCU;
|
||||
auto *CUNode = cast<DICompileUnit>(P.first);
|
||||
handleMacroNodes(AS.get(), CUNode->getMacros(), U);
|
||||
}
|
||||
Asm->OutStreamer->AddComment("End Of Macro List Mark");
|
||||
Asm->EmitInt8(0);
|
||||
}
|
||||
|
||||
// DWARF5 Experimental Separate Dwarf emitters.
|
||||
|
||||
void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,
|
||||
|
@ -400,18 +400,26 @@ class DwarfDebug : public AsmPrinterHandler {
|
||||
/// Emit visible names into a debug str section.
|
||||
void emitDebugStr();
|
||||
|
||||
/// Emit visible names into a debug loc section.
|
||||
/// Emit variable locations into a debug loc section.
|
||||
void emitDebugLoc();
|
||||
|
||||
/// Emit visible names into a debug loc dwo section.
|
||||
/// Emit variable locations into a debug loc dwo section.
|
||||
void emitDebugLocDWO();
|
||||
|
||||
/// Emit visible names into a debug aranges section.
|
||||
/// Emit address ranges into a debug aranges section.
|
||||
void emitDebugARanges();
|
||||
|
||||
/// Emit visible names into a debug ranges section.
|
||||
/// Emit address ranges into a debug ranges section.
|
||||
void emitDebugRanges();
|
||||
|
||||
/// Emit macros into a debug macinfo section.
|
||||
void emitDebugMacinfo();
|
||||
unsigned emitMacro(AsmStreamerBase *AS, DIMacro &M);
|
||||
unsigned emitMacroFile(AsmStreamerBase *AS, DIMacroFile &F,
|
||||
DwarfCompileUnit &U);
|
||||
unsigned handleMacroNodes(AsmStreamerBase *AS, DIMacroNodeArray Nodes,
|
||||
DwarfCompileUnit &U);
|
||||
|
||||
/// DWARF 5 Experimental Split Dwarf Emitters
|
||||
|
||||
/// Initialize common features of skeleton units.
|
||||
|
@ -984,6 +984,9 @@ void Verifier::visitDIMacro(const DIMacro &N) {
|
||||
N.getMacinfoType() == dwarf::DW_MACINFO_undef,
|
||||
"invalid macinfo type", &N);
|
||||
Assert(!N.getName().empty(), "anonymous macro", &N);
|
||||
if (!N.getValue().empty()) {
|
||||
assert(N.getValue().data()[0] != ' ' && "Macro value has a space prefix");
|
||||
}
|
||||
}
|
||||
|
||||
void Verifier::visitDIMacroFile(const DIMacroFile &N) {
|
||||
|
@ -256,6 +256,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) {
|
||||
DwarfRangesSection =
|
||||
Ctx->getMachOSection("__DWARF", "__debug_ranges", MachO::S_ATTR_DEBUG,
|
||||
SectionKind::getMetadata(), "debug_range");
|
||||
DwarfMacinfoSection =
|
||||
Ctx->getMachOSection("__DWARF", "__debug_macinfo", MachO::S_ATTR_DEBUG,
|
||||
SectionKind::getMetadata());
|
||||
DwarfDebugInlineSection =
|
||||
Ctx->getMachOSection("__DWARF", "__debug_inlined", MachO::S_ATTR_DEBUG,
|
||||
SectionKind::getMetadata());
|
||||
@ -505,6 +508,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) {
|
||||
Ctx->getELFSection(".debug_aranges", ELF::SHT_PROGBITS, 0);
|
||||
DwarfRangesSection =
|
||||
Ctx->getELFSection(".debug_ranges", ELF::SHT_PROGBITS, 0, "debug_range");
|
||||
DwarfMacinfoSection =
|
||||
Ctx->getELFSection(".debug_macinfo", ELF::SHT_PROGBITS, 0);
|
||||
|
||||
// DWARF5 Experimental Debug Info
|
||||
|
||||
@ -684,6 +689,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) {
|
||||
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
COFF::IMAGE_SCN_MEM_READ,
|
||||
SectionKind::getMetadata(), "debug_range");
|
||||
DwarfMacinfoSection = Ctx->getCOFFSection(
|
||||
".debug_macinfo",
|
||||
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
COFF::IMAGE_SCN_MEM_READ,
|
||||
SectionKind::getMetadata());
|
||||
DwarfInfoDWOSection = Ctx->getCOFFSection(
|
||||
".debug_info.dwo",
|
||||
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
|
@ -4549,6 +4549,7 @@ NVPTXTargetObjectFile::~NVPTXTargetObjectFile() {
|
||||
delete static_cast<NVPTXSection *>(DwarfLocSection);
|
||||
delete static_cast<NVPTXSection *>(DwarfARangesSection);
|
||||
delete static_cast<NVPTXSection *>(DwarfRangesSection);
|
||||
delete static_cast<NVPTXSection *>(DwarfMacinfoSection);
|
||||
}
|
||||
|
||||
MCSection *
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
DwarfLocSection = nullptr;
|
||||
DwarfARangesSection = nullptr;
|
||||
DwarfRangesSection = nullptr;
|
||||
DwarfMacinfoSection = nullptr;
|
||||
}
|
||||
|
||||
virtual ~NVPTXTargetObjectFile();
|
||||
@ -81,6 +82,8 @@ public:
|
||||
new NVPTXSection(MCSection::SV_ELF, SectionKind::getMetadata());
|
||||
DwarfRangesSection =
|
||||
new NVPTXSection(MCSection::SV_ELF, SectionKind::getMetadata());
|
||||
DwarfMacinfoSection =
|
||||
new NVPTXSection(MCSection::SV_ELF, SectionKind::getMetadata());
|
||||
}
|
||||
|
||||
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
|
||||
|
67
test/DebugInfo/X86/debug-macro.ll
Normal file
67
test/DebugInfo/X86/debug-macro.ll
Normal file
@ -0,0 +1,67 @@
|
||||
; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-dump=info - | FileCheck --check-prefix=CHECK-INFO %s
|
||||
; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-dump=macro - | FileCheck --check-prefix=CHECK-MACRO %s
|
||||
; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-dump=line - | FileCheck --check-prefix=CHECK-LINE %s
|
||||
|
||||
|
||||
; CHECK-INFO: .debug_info contents:
|
||||
; CHECK-INFO: DW_TAG_compile_unit
|
||||
; CHECK-INFO-NOT: DW_TAG
|
||||
; CHECK-INFO: DW_AT_name {{.*}}"debug-macro.cpp")
|
||||
; CHECK-INFO: DW_AT_macro_info {{.*}}(0x00000000)
|
||||
; CHECK-INFO: DW_TAG_compile_unit
|
||||
; CHECK-INFO-NOT: DW_TAG
|
||||
; CHECK-INFO: DW_AT_name {{.*}}"debug-macro1.cpp")
|
||||
; CHECK-INFO: DW_AT_macro_info {{.*}}(0x00000044)
|
||||
; CHECK-INFO: DW_TAG_compile_unit
|
||||
; CHECK-INFO-NOT: DW_TAG
|
||||
; CHECK-INFO: DW_AT_name {{.*}}"debug-macro2.cpp")
|
||||
; CHECK-INFO-NOT: DW_AT_macro_info
|
||||
|
||||
; CHECK-MACRO: .debug_macinfo contents:
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_define - lineno: 0 macro: NameCMD ValueCMD
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_start_file - lineno: 0 filenum: 1
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_start_file - lineno: 9 filenum: 2
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_define - lineno: 1 macro: NameDef Value
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_undef - lineno: 11 macro: NameUndef
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_end_file
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_undef - lineno: 10 macro: NameUndef2
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_end_file
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_start_file - lineno: 0 filenum: 1
|
||||
; CHECK-MACRO-NEXT: DW_MACINFO_end_file
|
||||
|
||||
; CHECK-LINE: .debug_line contents:
|
||||
; CHECK-LINE: Dir Mod Time File Len File Name
|
||||
; CHECK-LINE: file_names[ 1] {{.*}}debug-macro.cpp
|
||||
; CHECK-LINE: file_names[ 2] {{.*}}debug-macro.h
|
||||
; CHECK-LINE: Dir Mod Time File Len File Name
|
||||
; CHECK-LINE: file_names[ 1] {{.*}}debug-macro1.cpp
|
||||
|
||||
!llvm.dbg.cu = !{!0, !16, !20}
|
||||
!llvm.module.flags = !{!13, !14}
|
||||
!llvm.ident = !{!15}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: 1, file: !1, enums: !2, retainedTypes: !2, subprograms: !2, globals: !2, imports: !2, macros: !3)
|
||||
!1 = !DIFile(filename: "debug-macro.cpp", directory: "/")
|
||||
!2 = !{}
|
||||
!3 = !{!4, !5}
|
||||
!4 = !DIMacro(type: DW_MACINFO_define, line: 0, name: "NameCMD", value: "ValueCMD")
|
||||
!5 = !DIMacroFile(line: 0, file: !1, nodes: !6)
|
||||
!6 = !{!7, !12}
|
||||
!7 = !DIMacroFile(line: 9, file: !8, nodes: !9)
|
||||
!8 = !DIFile(filename: "debug-macro.h", directory: "/")
|
||||
!9 = !{!10, !11}
|
||||
!10 = !DIMacro(type: DW_MACINFO_define, line: 1, name: "NameDef", value: "Value")
|
||||
!11 = !DIMacro(type: DW_MACINFO_undef, line: 11, name: "NameUndef")
|
||||
!12 = !DIMacro(type: DW_MACINFO_undef, line: 10, name: "NameUndef2")
|
||||
|
||||
!13 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!14 = !{i32 1, !"Debug Info Version", i32 3}
|
||||
!15 = !{!"clang version 3.5.0 "}
|
||||
|
||||
!16 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: 1, file: !17, enums: !2, retainedTypes: !2, subprograms: !2, globals: !2, imports: !2, macros: !18)
|
||||
!17 = !DIFile(filename: "debug-macro1.cpp", directory: "/")
|
||||
!18 = !{!19}
|
||||
!19 = !DIMacroFile(line: 0, file: !17, nodes: !2)
|
||||
|
||||
!20 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: 1, file: !21, enums: !2, retainedTypes: !2, subprograms: !2, globals: !2, imports: !2)
|
||||
!21 = !DIFile(filename: "debug-macro2.cpp", directory: "/")
|
Loading…
Reference in New Issue
Block a user