mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
Dwarf: support for LTO where a single object file can have multiple line tables
We generate one line table for each compilation unit in the object file. Reviewed by Eric and Kevin. rdar://problem/13067005 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174445 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
baabdecbb9
commit
43213cf1ac
@ -144,6 +144,10 @@ namespace llvm {
|
||||
/// We need a deterministic iteration order, so we remember the order
|
||||
/// the elements were added.
|
||||
std::vector<const MCSection *> MCLineSectionOrder;
|
||||
/// The Compile Unit ID that we are currently processing.
|
||||
unsigned DwarfCompileUnitID;
|
||||
/// The line table start symbol for each Compile Unit.
|
||||
DenseMap<unsigned, MCSymbol *> MCLineTableSymbols;
|
||||
|
||||
void *MachOUniquingMap, *ELFUniquingMap, *COFFUniquingMap;
|
||||
|
||||
@ -304,6 +308,25 @@ namespace llvm {
|
||||
MCLineSections[Sec] = Line;
|
||||
MCLineSectionOrder.push_back(Sec);
|
||||
}
|
||||
unsigned getDwarfCompileUnitID() {
|
||||
return DwarfCompileUnitID;
|
||||
}
|
||||
void setDwarfCompileUnitID(unsigned CUIndex) {
|
||||
DwarfCompileUnitID = CUIndex;
|
||||
}
|
||||
const DenseMap<unsigned, MCSymbol *> &getMCLineTableSymbols() const {
|
||||
return MCLineTableSymbols;
|
||||
}
|
||||
MCSymbol *getMCLineTableSymbol(unsigned ID) const {
|
||||
DenseMap<unsigned, MCSymbol *>::const_iterator CIter =
|
||||
MCLineTableSymbols.find(ID);
|
||||
if (CIter == MCLineTableSymbols.end())
|
||||
return NULL;
|
||||
return CIter->second;
|
||||
}
|
||||
void setMCLineTableSymbol(MCSymbol *Sym, unsigned ID) {
|
||||
MCLineTableSymbols[ID] = Sym;
|
||||
}
|
||||
|
||||
/// setCurrentDwarfLoc - saves the information from the currently parsed
|
||||
/// dwarf .loc directive and sets DwarfLocSeen. When the next instruction
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
@ -186,29 +187,43 @@ namespace llvm {
|
||||
MCLineSection() {}
|
||||
|
||||
// addLineEntry - adds an entry to this MCLineSection's line entries
|
||||
void addLineEntry(const MCLineEntry &LineEntry) {
|
||||
MCLineEntries.push_back(LineEntry);
|
||||
void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) {
|
||||
MCLineDivisions[CUID].push_back(LineEntry);
|
||||
}
|
||||
|
||||
typedef std::vector<MCLineEntry> MCLineEntryCollection;
|
||||
typedef MCLineEntryCollection::iterator iterator;
|
||||
typedef MCLineEntryCollection::const_iterator const_iterator;
|
||||
typedef std::map<unsigned, MCLineEntryCollection> MCLineDivisionMap;
|
||||
|
||||
private:
|
||||
MCLineEntryCollection MCLineEntries;
|
||||
// A collection of MCLineEntry for each Compile Unit ID.
|
||||
MCLineDivisionMap MCLineDivisions;
|
||||
|
||||
public:
|
||||
const MCLineEntryCollection *getMCLineEntries() const {
|
||||
return &MCLineEntries;
|
||||
// Returns whether MCLineSection contains entries for a given Compile
|
||||
// Unit ID.
|
||||
bool containEntriesForID(unsigned CUID) const {
|
||||
return MCLineDivisions.count(CUID);
|
||||
}
|
||||
// Returns the collection of MCLineEntry for a given Compile Unit ID.
|
||||
const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const {
|
||||
MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID);
|
||||
assert(CIter != MCLineDivisions.end());
|
||||
return CIter->second;
|
||||
}
|
||||
};
|
||||
|
||||
class MCDwarfFileTable {
|
||||
public:
|
||||
//
|
||||
// This emits the Dwarf file and the line tables.
|
||||
// This emits the Dwarf file and the line tables for all Compile Units.
|
||||
//
|
||||
static const MCSymbol *Emit(MCStreamer *MCOS);
|
||||
//
|
||||
// This emits the Dwarf file and the line tables for a given Compile Unit.
|
||||
//
|
||||
static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID);
|
||||
};
|
||||
|
||||
class MCDwarfLineAddr {
|
||||
|
@ -662,13 +662,21 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
|
||||
// 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.
|
||||
NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL);
|
||||
|
||||
// Define start line table label for each Compile Unit.
|
||||
MCSymbol *LineTableStartSym = Asm->GetTempSymbol("line_table_start",
|
||||
NewCU->getUniqueID());
|
||||
Asm->OutStreamer.getContext().setMCLineTableSymbol(LineTableStartSym,
|
||||
NewCU->getUniqueID());
|
||||
|
||||
// DW_AT_stmt_list is a offset of line number information for this
|
||||
// compile unit in debug_line section.
|
||||
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||
NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
|
||||
Asm->GetTempSymbol("section_line"));
|
||||
LineTableStartSym);
|
||||
else
|
||||
NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
|
||||
NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
|
||||
LineTableStartSym, Asm->GetTempSymbol("section_line"));
|
||||
|
||||
if (!CompilationDir.empty())
|
||||
NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
|
||||
@ -1399,6 +1407,13 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
|
||||
if (LScopes.empty()) return;
|
||||
identifyScopeMarkers();
|
||||
|
||||
// Set DwarfCompileUnitID in MCContext to the Compile Unit this function
|
||||
// belongs to.
|
||||
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
|
||||
CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
|
||||
assert(TheCU && "Unable to find compile unit!");
|
||||
Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID());
|
||||
|
||||
FunctionBeginSym = Asm->GetTempSymbol("func_begin",
|
||||
Asm->getFunctionNumber());
|
||||
// Assumes in correct section after the entry point.
|
||||
@ -1583,6 +1598,8 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
|
||||
Asm->getFunctionNumber());
|
||||
// Assumes in correct section after the entry point.
|
||||
Asm->OutStreamer.EmitLabel(FunctionEndSym);
|
||||
// Set DwarfCompileUnitID in MCContext to default value.
|
||||
Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
|
||||
|
||||
SmallPtrSet<const MDNode *, 16> ProcessedVars;
|
||||
collectVariableInfo(MF, ProcessedVars);
|
||||
|
@ -40,7 +40,7 @@ MCContext::MCContext(const MCAsmInfo &mai, const MCRegisterInfo &mri,
|
||||
CompilationDir(llvm::sys::Path::GetCurrentDirectory().str()),
|
||||
CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0),
|
||||
DwarfLocSeen(false), GenDwarfForAssembly(false), GenDwarfFileNumber(0),
|
||||
AllowTemporaryLabels(true), AutoReset(DoAutoReset) {
|
||||
AllowTemporaryLabels(true), DwarfCompileUnitID(0), AutoReset(DoAutoReset) {
|
||||
|
||||
MachOUniquingMap = 0;
|
||||
ELFUniquingMap = 0;
|
||||
|
@ -101,7 +101,8 @@ void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) {
|
||||
}
|
||||
|
||||
// Add the line entry to this section's entries.
|
||||
LineSection->addLineEntry(LineEntry);
|
||||
LineSection->addLineEntry(LineEntry,
|
||||
MCOS->getContext().getDwarfCompileUnitID());
|
||||
}
|
||||
|
||||
//
|
||||
@ -131,7 +132,12 @@ static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS,
|
||||
//
|
||||
static inline void EmitDwarfLineTable(MCStreamer *MCOS,
|
||||
const MCSection *Section,
|
||||
const MCLineSection *LineSection) {
|
||||
const MCLineSection *LineSection,
|
||||
unsigned CUID) {
|
||||
// This LineSection does not contain any LineEntry for the given Compile Unit.
|
||||
if (!LineSection->containEntriesForID(CUID))
|
||||
return;
|
||||
|
||||
unsigned FileNum = 1;
|
||||
unsigned LastLine = 1;
|
||||
unsigned Column = 0;
|
||||
@ -141,8 +147,8 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS,
|
||||
|
||||
// Loop through each MCLineEntry and encode the dwarf line number table.
|
||||
for (MCLineSection::const_iterator
|
||||
it = LineSection->getMCLineEntries()->begin(),
|
||||
ie = LineSection->getMCLineEntries()->end(); it != ie; ++it) {
|
||||
it = LineSection->getMCLineEntries(CUID).begin(),
|
||||
ie = LineSection->getMCLineEntries(CUID).end(); it != ie; ++it) {
|
||||
|
||||
if (FileNum != it->getFileNum()) {
|
||||
FileNum = it->getFileNum();
|
||||
@ -215,9 +221,36 @@ const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) {
|
||||
// Switch to the section where the table will be emitted into.
|
||||
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
|
||||
|
||||
// Create a symbol at the beginning of this section.
|
||||
MCSymbol *LineStartSym = context.CreateTempSymbol();
|
||||
// Set the value of the symbol, as we are at the start of the section.
|
||||
const DenseMap<unsigned, MCSymbol *> &MCLineTableSymbols =
|
||||
MCOS->getContext().getMCLineTableSymbols();
|
||||
// CUID and MCLineTableSymbols are set in DwarfDebug, when DwarfDebug does
|
||||
// not exist, CUID will be 0 and MCLineTableSymbols will be empty.
|
||||
// Handle Compile Unit 0, the line table start symbol is the section symbol.
|
||||
const MCSymbol *LineStartSym = EmitCU(MCOS, 0);
|
||||
// Handle the rest of the Compile Units.
|
||||
for (unsigned Is = 1, Ie = MCLineTableSymbols.size(); Is < Ie; Is++)
|
||||
EmitCU(MCOS, Is);
|
||||
|
||||
// Now delete the MCLineSections that were created in MCLineEntry::Make()
|
||||
// and used to emit the line table.
|
||||
const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
|
||||
MCOS->getContext().getMCLineSections();
|
||||
for (DenseMap<const MCSection *, MCLineSection *>::const_iterator it =
|
||||
MCLineSections.begin(), ie = MCLineSections.end(); it != ie;
|
||||
++it)
|
||||
delete it->second;
|
||||
|
||||
return LineStartSym;
|
||||
}
|
||||
|
||||
const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) {
|
||||
MCContext &context = MCOS->getContext();
|
||||
|
||||
// Create a symbol at the beginning of the line table.
|
||||
MCSymbol *LineStartSym = MCOS->getContext().getMCLineTableSymbol(CUID);
|
||||
if (!LineStartSym)
|
||||
LineStartSym = context.CreateTempSymbol();
|
||||
// Set the value of the symbol, as we are at the start of the line table.
|
||||
MCOS->EmitLabel(LineStartSym);
|
||||
|
||||
// Create a symbol for the end of the section (to be set when we get there).
|
||||
@ -301,11 +334,7 @@ const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) {
|
||||
++it) {
|
||||
const MCSection *Sec = *it;
|
||||
const MCLineSection *Line = MCLineSections.lookup(Sec);
|
||||
EmitDwarfLineTable(MCOS, Sec, Line);
|
||||
|
||||
// Now delete the MCLineSections that were created in MCLineEntry::Make()
|
||||
// and used to emit the line table.
|
||||
delete Line;
|
||||
EmitDwarfLineTable(MCOS, Sec, Line, CUID);
|
||||
}
|
||||
|
||||
if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines()
|
||||
|
@ -17,7 +17,7 @@ target triple = "thumbv7-apple-darwin10"
|
||||
; DW_OP_constu
|
||||
; offset
|
||||
|
||||
;CHECK: .long Lset6
|
||||
;CHECK: .long Lset7
|
||||
;CHECK-NEXT: @ DW_AT_type
|
||||
;CHECK-NEXT: @ DW_AT_decl_file
|
||||
;CHECK-NEXT: @ DW_AT_decl_line
|
||||
|
@ -8,7 +8,7 @@
|
||||
; DW_OP_constu
|
||||
; offset
|
||||
|
||||
;CHECK: .long Lset33
|
||||
;CHECK: .long Lset34
|
||||
;CHECK-NEXT: @ DW_AT_type
|
||||
;CHECK-NEXT: @ DW_AT_decl_file
|
||||
;CHECK-NEXT: @ DW_AT_decl_line
|
||||
|
@ -18,5 +18,5 @@ entry:
|
||||
|
||||
; CHECK: .subsections_via_symbols
|
||||
; CHECK-NEXT: __debug_line
|
||||
; CHECK-NEXT: Ltmp
|
||||
; CHECK-NEXT: Lline_table_start0
|
||||
; CHECK-NEXT: Ltmp{{[0-9]}} = (Ltmp
|
||||
|
@ -4,7 +4,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
|
||||
target triple = "x86_64-apple-darwin10.0.0"
|
||||
|
||||
; Check debug info for variable z_s
|
||||
;CHECK: .long Lset13
|
||||
;CHECK: .long Lset14
|
||||
;CHECK-NEXT: ## DW_AT_decl_file
|
||||
;CHECK-NEXT: ## DW_AT_decl_line
|
||||
;CHECK-NEXT: ## DW_AT_type
|
||||
|
@ -4,7 +4,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
|
||||
target triple = "x86_64-apple-darwin10.0.0"
|
||||
;Radar 8950491
|
||||
|
||||
;CHECK: .long Lset5
|
||||
;CHECK: .long Lset6
|
||||
;CHECK-NEXT: ## DW_AT_decl_file
|
||||
;CHECK-NEXT: ## DW_AT_decl_line
|
||||
;CHECK-NEXT: ## DW_AT_type
|
||||
|
62
test/DebugInfo/X86/stmt-list-multiple-compile-units.ll
Normal file
62
test/DebugInfo/X86/stmt-list-multiple-compile-units.ll
Normal file
@ -0,0 +1,62 @@
|
||||
; RUN: llc -O0 %s -mtriple=x86_64-apple-darwin -filetype=obj -o %t
|
||||
; RUN: llvm-dwarfdump %t | FileCheck %s
|
||||
|
||||
; rdar://13067005
|
||||
; CHECK: .debug_info contents:
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
; CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x00000000)
|
||||
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
; CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x00000049)
|
||||
|
||||
; CHECK: .debug_line contents:
|
||||
; CHECK-NEXT: Line table prologue:
|
||||
; CHECK-NEXT: total_length: 0x00000045
|
||||
; CHECK: Line table prologue:
|
||||
; CHECK: total_length: 0x00000047
|
||||
|
||||
define i32 @test(i32 %a) nounwind uwtable ssp {
|
||||
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 !15), !dbg !16
|
||||
%0 = load i32* %a.addr, align 4, !dbg !17
|
||||
%call = call i32 @fn(i32 %0), !dbg !17
|
||||
ret i32 %call, !dbg !17
|
||||
}
|
||||
|
||||
declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
|
||||
|
||||
define i32 @fn(i32 %a) nounwind uwtable ssp {
|
||||
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 !19), !dbg !20
|
||||
%0 = load i32* %a.addr, align 4, !dbg !21
|
||||
ret i32 %0, !dbg !21
|
||||
}
|
||||
|
||||
!llvm.dbg.cu = !{!0, !10}
|
||||
!0 = metadata !{i32 786449, i32 0, i32 12, metadata !"simple.c", metadata !"/private/tmp", metadata !"clang version 3.3", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1} ; [ DW_TAG_compile_unit ]
|
||||
!1 = metadata !{metadata !2}
|
||||
!2 = metadata !{i32 0}
|
||||
!3 = metadata !{metadata !5}
|
||||
!5 = metadata !{i32 786478, i32 0, metadata !6, metadata !"test", metadata !"test", metadata !"", metadata !6, i32 2, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @test, null, null, metadata !1, i32 3} ; [ DW_TAG_subprogram ] [line 2] [def] [scope 3] [test]
|
||||
!6 = metadata !{i32 786473, metadata !"simple.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
|
||||
!7 = metadata !{i32 786453, i32 0, metadata !"", i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
|
||||
!8 = metadata !{metadata !9, metadata !9}
|
||||
!9 = metadata !{i32 786468, null, metadata !"int", null, 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]
|
||||
!10 = metadata !{i32 786449, i32 0, i32 12, metadata !"simple2.c", metadata !"/private/tmp", metadata !"clang version 3.3 (trunk 172862)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !11, metadata !1} ; [ DW_TAG_compile_unit ]
|
||||
!11 = metadata !{metadata !13}
|
||||
!13 = metadata !{i32 786478, i32 0, metadata !14, metadata !"fn", metadata !"fn", metadata !"", metadata !14, i32 1, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @fn, null, null, metadata !1, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [fn]
|
||||
!14 = metadata !{i32 786473, metadata !"simple2.c", metadata !"/private/tmp", null} ; [ DW_TAG_file_type ]
|
||||
!15 = metadata !{i32 786689, metadata !5, metadata !"a", metadata !6, i32 16777218, metadata !9, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [a] [line 2]
|
||||
!16 = metadata !{i32 2, i32 0, metadata !5, null}
|
||||
!17 = metadata !{i32 4, i32 0, metadata !18, null}
|
||||
!18 = metadata !{i32 786443, metadata !5, i32 3, i32 0, metadata !6, i32 0} ; [ DW_TAG_lexical_block ]
|
||||
!19 = metadata !{i32 786689, metadata !13, metadata !"a", metadata !14, i32 16777217, metadata !9, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [a] [line 1]
|
||||
!20 = metadata !{i32 1, i32 0, metadata !13, null}
|
||||
!21 = metadata !{i32 2, i32 0, metadata !22, null}
|
||||
!22 = metadata !{i32 786443, metadata !13, i32 1, i32 0, metadata !14, i32 0} ; [ DW_TAG_lexical_block ]
|
@ -3,7 +3,7 @@
|
||||
; CHECK: .section .debug_line,"",@progbits
|
||||
; CHECK-NEXT: .Lsection_line:
|
||||
|
||||
; CHECK: .long .Lsection_line # DW_AT_stmt_list
|
||||
; CHECK: .long .Lline_table_start0 # DW_AT_stmt_list
|
||||
|
||||
define void @f() {
|
||||
entry:
|
||||
|
@ -23,8 +23,8 @@
|
||||
; LINUX-NEXT: .quad yyyy
|
||||
|
||||
; Verify that we refer to 'yyyy' without a relocation.
|
||||
; DARWIN: Lset5 = Linfo_string3-Linfo_string ## DW_AT_name
|
||||
; DARWIN-NEXT: .long Lset5
|
||||
; DARWIN: Lset6 = Linfo_string3-Linfo_string ## DW_AT_name
|
||||
; DARWIN-NEXT: .long Lset6
|
||||
; DARWIN-NEXT: .long 39 ## DW_AT_type
|
||||
; DARWIN-NEXT: .byte 1 ## DW_AT_external
|
||||
; DARWIN-NEXT: .byte 1 ## DW_AT_decl_file
|
||||
|
Loading…
Reference in New Issue
Block a user