1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

Add support for a CU to output a set of ranges for the CU. This is useful

when you want to have the full list of addresses for a particular CU or
when you have multiple modules linked together and can't depend upon the
ordering of a single CU for begin/end ranges.

llvm-svn: 197776
This commit is contained in:
Eric Christopher 2013-12-20 04:16:18 +00:00
parent f28ad7e5bf
commit 4e108f47b7
3 changed files with 124 additions and 20 deletions

View File

@ -108,6 +108,11 @@ static cl::opt<unsigned>
DwarfVersionNumber("dwarf-version", cl::Hidden,
cl::desc("Generate DWARF for dwarf version."), cl::init(0));
static cl::opt<bool>
DwarfCURanges("generate-dwarf-cu-ranges", cl::Hidden,
cl::desc("Generate DW_AT_ranges for compile units"),
cl::init(false));
static const char *const DWARFGroupName = "DWARF Emission";
static const char *const DbgTimerName = "DWARF Debug Writer";
@ -426,6 +431,10 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU,
SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc, FunctionBeginSym);
SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc, FunctionEndSym);
// Add this range to the list of ranges for the CU.
RangeSpan Span(FunctionBeginSym, FunctionEndSym);
SPCU->addRange(llvm_move(Span));
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
@ -1070,24 +1079,32 @@ void DwarfDebug::finalizeModuleInfo() {
// vtable holding type.
TheU->constructContainingTypeDIEs();
// Add CU specific attributes if we need to add any.
if (TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) {
// If we're splitting the dwarf out now that we've got the entire
// CU then construct a skeleton CU based upon it.
if (useSplitDwarf() &&
TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) {
if (useSplitDwarf()) {
// This should be a unique identifier when we want to build .dwp files.
uint64_t ID = 0;
if (GenerateCUHash) {
DIEHash CUHash;
ID = CUHash.computeCUSignature(*TheU->getUnitDie());
}
// This should be a unique identifier when we want to build .dwp files.
TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
dwarf::DW_FORM_data8, ID);
// Now construct the skeleton CU associated.
DwarfCompileUnit *SkCU =
constructSkeletonCU(static_cast<DwarfCompileUnit *>(TheU));
// This should be a unique identifier when we want to build .dwp files.
SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
dwarf::DW_FORM_data8, ID);
} else {
// Attribute if we've emitted a range list for the compile unit, this
// will get constructed for the skeleton CU separately if we have one.
if (DwarfCURanges && TheU->getRanges().size())
addSectionLabel(Asm, TheU, TheU->getUnitDie(), dwarf::DW_AT_ranges,
Asm->GetTempSymbol("cu_ranges", TheU->getUniqueID()),
DwarfDebugRangeSectionSym);
}
}
}
@ -2935,6 +2952,28 @@ void DwarfDebug::emitDebugRanges() {
Asm->OutStreamer.EmitIntValue(0, Size);
Asm->OutStreamer.EmitIntValue(0, Size);
}
// Now emit a range for the CU itself.
if (DwarfCURanges) {
Asm->OutStreamer.EmitLabel(
Asm->GetTempSymbol("cu_ranges", TheCU->getUniqueID()));
const SmallVectorImpl<RangeSpan> &Ranges = TheCU->getRanges();
for (uint32_t i = 0, e = Ranges.size(); i != e; ++i) {
RangeSpan Range = Ranges[i];
// We occasionally have ranges without begin/end labels.
// FIXME: Verify and fix.
const MCSymbol *Begin = Range.getStart();
const MCSymbol *End = Range.getEnd();
Begin ? Asm->OutStreamer.EmitSymbolValue(Begin, Size)
: Asm->OutStreamer.EmitIntValue(0, Size);
End ? Asm->OutStreamer.EmitSymbolValue(End, Size)
: Asm->OutStreamer.EmitIntValue(0, Size);
}
// And terminate the list with two 0 values.
Asm->OutStreamer.EmitIntValue(0, Size);
Asm->OutStreamer.EmitIntValue(0, Size);
}
}
}
@ -2963,8 +3002,13 @@ DwarfCompileUnit *DwarfDebug::constructSkeletonCU(const DwarfCompileUnit *CU) {
else
NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0);
// 2.17.1 requires that we use DW_AT_low_pc for a single entry point
// into an entity. We're using 0, or a NULL label for this.
// Attribute if we've emitted a range list for the compile unit, this
// will get constructed for the skeleton CU separately if we have one.
if (DwarfCURanges && CU->getRanges().size())
addSectionLabel(Asm, NewCU, Die, dwarf::DW_AT_ranges,
Asm->GetTempSymbol("cu_ranges", CU->getUniqueID()),
DwarfDebugRangeSectionSym);
else
NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
// DW_AT_stmt_list is a offset of line number information for this

View File

@ -118,6 +118,9 @@ protected:
/// corresponds to the MDNode mapped with the subprogram DIE.
DenseMap<DIE *, const MDNode *> ContainingTypeMap;
// List of ranges for a given compile unit.
SmallVector<RangeSpan, 1> CURanges;
// List of range lists for a given compile unit, separate from the ranges for
// the CU itself.
SmallVector<RangeSpanList, 1> CURangeLists;
@ -216,6 +219,13 @@ public:
/// hasContent - Return true if this compile unit has something to write out.
bool hasContent() const { return !UnitDie->getChildren().empty(); }
/// addRange - Add an address range to the list of ranges for this unit.
void addRange(RangeSpan Range) { CURanges.push_back(Range); }
/// getRanges - Get the list of ranges for this unit.
const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; }
SmallVectorImpl<RangeSpan> &getRanges() { return CURanges; }
/// addRangeList - Add an address range list to the list of range lists.
void addRangeList(RangeSpanList Ranges) { CURangeLists.push_back(Ranges); }

View File

@ -0,0 +1,50 @@
; RUN: llc -O0 -filetype=obj -generate-dwarf-cu-ranges %s -o %t
; RUN: llvm-dwarfdump %t | FileCheck %s
; Check that we emit ranges for this when the -generate-dwarf-cu-ranges flag is passed.
; CHECK: DW_TAG_compile_unit
; CHECK: DW_AT_ranges
; CHECK: DW_TAG_subprogram
; CHECK: .debug_ranges contents:
; FIXME: When we get better dumping facilities we'll want to elaborate here.
; CHECK: 00000000 <End of list>
; CHECK: 00000010 <End of list>
; Function Attrs: nounwind uwtable
define i32 @f(i32 %a) #0 {
entry:
%a.addr = alloca i32, align 4
store i32 %a, i32* %a.addr, align 4
call void @llvm.dbg.declare(metadata !{i32* %a.addr}, metadata !12), !dbg !13
%0 = load i32* %a.addr, align 4, !dbg !14
%add = add nsw i32 %0, 4, !dbg !14
ret i32 %add, !dbg !14
}
; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata) #1
attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind readnone }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!9, !10}
!llvm.ident = !{!11}
!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 (trunk 197756) (llvm/trunk 197768)", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/echristo/tmp/foo.c] [DW_LANG_C99]
!1 = metadata !{metadata !"foo.c", metadata !"/usr/local/google/home/echristo/tmp"}
!2 = metadata !{i32 0}
!3 = metadata !{metadata !4}
!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f", metadata !"f", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @f, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [f]
!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/usr/local/google/home/echristo/tmp/foo.c]
!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
!7 = metadata !{metadata !8, metadata !8}
!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
!10 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
!11 = metadata !{metadata !"clang version 3.5 (trunk 197756) (llvm/trunk 197768)"}
!12 = metadata !{i32 786689, metadata !4, metadata !"a", metadata !5, i32 16777217, metadata !8, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [a] [line 1]
!13 = metadata !{i32 1, i32 0, metadata !4, null}
!14 = metadata !{i32 2, i32 0, metadata !4, null}