1
0
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:
Amjad Aboud 2016-01-07 14:28:20 +00:00
parent 36113b2917
commit a54507b1df
10 changed files with 251 additions and 4 deletions

View File

@ -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.

View File

@ -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 {

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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,

View File

@ -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.

View File

@ -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) {

View File

@ -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 |

View File

@ -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 *

View File

@ -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,

View 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: "/")