Skip to content

Fix cas-friendly line table emission in llvm #6718

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/include/llvm/MC/MCDwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ class MCLineSection {

// Add an end entry by cloning the last entry, if exists, for the section
// the given EndLabel belongs to. The label is replaced by the given EndLabel.
void addEndEntry(MCSymbol *EndLabel);
void addEndEntry(MCSymbol *EndLabel, bool CasFriendlyDebugInfo = false);

using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>;
using iterator = MCDwarfLineEntryCollection::iterator;
Expand Down
10 changes: 10 additions & 0 deletions llvm/include/llvm/MC/MCStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,9 @@ class MCStreamer {
/// discussion for future inclusion.
bool AllowAutoPadding = false;

/// Generate debug info that is Cas Friendly
bool GenerateCasFriendlyDebugInfo = false;

protected:
MCStreamer(MCContext &Ctx);

Expand Down Expand Up @@ -308,6 +311,13 @@ class MCStreamer {
void setAllowAutoPadding(bool v) { AllowAutoPadding = v; }
bool getAllowAutoPadding() const { return AllowAutoPadding; }

void setGenerateCasFriendlyDebugInfo(bool v) {
GenerateCasFriendlyDebugInfo = v;
}
bool getGenerateCasFriendlyDebugInfo() const {
return GenerateCasFriendlyDebugInfo;
}

/// When emitting an object file, create and emit a real label. When emitting
/// textual assembly, this should do nothing to avoid polluting our output.
virtual MCSymbol *emitCFILabel();
Expand Down
7 changes: 4 additions & 3 deletions llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ DwarfDebug::DwarfDebug(AsmPrinter *A)
Asm->OutStreamer->getContext().setDwarfFormat(Dwarf64 ? dwarf::DWARF64
: dwarf::DWARF32);

GenerateCasFriendlyDebugInfo = CasFriendlyDebugInfo;
Asm->OutStreamer->setGenerateCasFriendlyDebugInfo(CasFriendlyDebugInfo);
}

// Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h.
Expand Down Expand Up @@ -2215,7 +2215,8 @@ void DwarfDebug::terminateLineTable(const DwarfCompileUnit *CU) {
getDwarfCompileUnitIDForLineTable(*CU));
// Add the last range label for the given CU.
LineTable.getMCLineSections().addEndEntry(
const_cast<MCSymbol *>(CURanges.back().End));
const_cast<MCSymbol *>(CURanges.back().End),
Asm->OutStreamer->getGenerateCasFriendlyDebugInfo());
}

void DwarfDebug::skippedNonDebugFunction() {
Expand Down Expand Up @@ -2311,7 +2312,7 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
// we want to split up the line tables by function. To do this, we want to
// emit a DW_LNE_end_sequence at the end of a function's contribution to the
// line table.
if (GenerateCasFriendlyDebugInfo) {
if (Asm->OutStreamer->getGenerateCasFriendlyDebugInfo()) {
MCSymbol *LineSym = Asm->OutStreamer->getContext().createTempSymbol();
Asm->OutStreamer->emitLabel(LineSym);
MCDwarfLoc DwarfLoc(
Expand Down
3 changes: 0 additions & 3 deletions llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,6 @@ class DwarfDebug : public DebugHandlerBase {
/// Avoid using DW_OP_convert due to consumer incompatibilities.
bool EnableOpConvert;

/// Generate debug info that is Cas Friendly
bool GenerateCasFriendlyDebugInfo;

public:
enum class MinimizeAddrInV5 {
Default,
Expand Down
30 changes: 15 additions & 15 deletions llvm/lib/MC/MCDwarf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,21 +144,26 @@ makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
return Res;
}

void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
void MCLineSection::addEndEntry(MCSymbol *EndLabel, bool CasFriendlyDebugInfo) {
auto *Sec = &EndLabel->getSection();
// The line table may be empty, which we should skip adding an end entry.
// There are two cases:
// There are three cases:
// (1) MCAsmStreamer - emitDwarfLocDirective emits a location directive in
// place instead of adding a line entry if the target has
// usesDwarfFileAndLocDirectives.
// (2) MCObjectStreamer - if a function has incomplete debug info where
// instructions don't have DILocations, the line entries are missing.
// (3) If the debug info is cas friendly, there is an end_sequence after every
// function and another one doesn't have to be emitted at the end of the line
// table.
auto I = MCLineDivisions.find(Sec);
if (I != MCLineDivisions.end()) {
auto &Entries = I->second;
auto EndEntry = Entries.back();
EndEntry.setEndLabel(EndLabel);
Entries.push_back(EndEntry);
if (!CasFriendlyDebugInfo) {
EndEntry.setEndLabel(EndLabel);
Entries.push_back(EndEntry);
}
}
}

Expand All @@ -173,7 +178,9 @@ void MCDwarfLineTable::emitOne(
unsigned FileNum, LastLine, Column, Flags, Isa, Discriminator;
MCSymbol *LastLabel;
auto init = [&]() {
FileNum = 1;
// Force emission of DW_LNS_set_file for every function's contribution to
// the line table to maximize deduplication.
FileNum = MCOS->getGenerateCasFriendlyDebugInfo() ? 0 : 1;
LastLine = 1;
Column = 0;
Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
Expand All @@ -188,29 +195,22 @@ void MCDwarfLineTable::emitOne(
for (const MCDwarfLineEntry &LineEntry : LineEntries) {
MCSymbol *Label = LineEntry.getLabel();
const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
if (LineEntry.IsEndEntry) {
if (LineEntry.IsEndEntry || LineEntry.IsEndOfFunction) {
MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, Label,
asmInfo->getCodePointerSize());
init();
EndEntryEmitted = true;
continue;
}
if (LineEntry.IsEndOfFunction) {
MCOS->emitInt8(char(dwarf::DW_LNS_extended_op));
MCOS->emitInt8(char(1));
MCOS->emitInt8(char(dwarf::DW_LNE_end_sequence));
init();
continue;
}

int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;

if (FileNum != LineEntry.getFileNum() || LineEntry.IsEndOfFunction) {
Copy link

@felipepiovezan felipepiovezan May 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about the previous code: was this || LineEntry.IsEndOfFunction ever relevant? Because right above we continue for this state 🤔

But I see now that most removals here are actually restoring the code to its upstream state

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that part was not needed, and I have removed it. I am sorry for the confusion on that.

if (FileNum != LineEntry.getFileNum()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like there could be some NFC refactoring done upstream first? Such as moving the LineEntry.IsEndOfFunction higher up? Might make maintaining the patch easier.

FileNum = LineEntry.getFileNum();
MCOS->emitInt8(dwarf::DW_LNS_set_file);
MCOS->emitULEB128IntValue(FileNum);
}
if (Column != LineEntry.getColumn() || LineEntry.IsEndOfFunction) {
if (Column != LineEntry.getColumn()) {
Column = LineEntry.getColumn();
MCOS->emitInt8(dwarf::DW_LNS_set_column);
MCOS->emitULEB128IntValue(Column);
Expand Down
160 changes: 95 additions & 65 deletions llvm/test/DebugInfo/CAS/AArch64/debug_line_and_info_dedupe.test
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ CHECK-NEXT: DW_TAG_compile_unit
CHECK: CAS Block: llvmcas://[[SUBPROGRAM_FOO:[a-z0-9]+]]
CHECK-NEXT: DW_TAG_subprogram
CHECK: mc:debug_line llvmcas://
CHECK-NEXT: mc:debug_line llvmcas://
CHECK-NEXT: mc:debug_line llvmcas://[[LINETABLECASID:[a-z0-9]+]]
CHECK-NEXT: mc:debug_line llvmcas://


CHECK: mc:assembler
Expand All @@ -22,79 +22,109 @@ CHECK: CAS Block: llvmcas://[[SUBPROGRAM_FOO]]
CHECK-NEXT: DW_TAG_subprogram
CHECK: mc:debug_line llvmcas://
CHECK-NEXT: mc:debug_line llvmcas://
CHECK-NEXT: mc:debug_line llvmcas://
CHECK-NEXT: mc:debug_line llvmcas://[[LINETABLECASID]]
CHECK-NEXT: mc:debug_line llvmcas://

//--- a.ll

target triple = "arm64-apple-macosx12.0.0"
define void @foo() #0 !dbg !9 {
ret void, !dbg !14
; ModuleID = 'a.cpp'
source_filename = "a.cpp"
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-macosx13.0.0"

; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
define i32 @_Z3foov() #0 !dbg !10 {
ret i32 3, !dbg !16
}
define void @bar(i32 noundef %x) #0 !dbg !15 {
ret void, !dbg !23

; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
define i32 @_Z4foo2v() #0 !dbg !17 {
ret i32 4, !dbg !18
}
attributes #0 = { noinline nounwind optnone ssp uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 16.0.0 (https://github.com/apple/llvm-project.git d74d0d9fde90cccba7bf18066ac56e55e4402948)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None, sysroot: "/")
!1 = !DIFile(filename: "a.c", directory: "/Users/shubham/Development/CASDelta")
!2 = !{i32 7, !"Dwarf Version", i32 4}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 7, !"PIC Level", i32 2}
!6 = !{i32 7, !"uwtable", i32 2}
!7 = !{i32 7, !"frame-pointer", i32 2}
!9 = distinct !DISubprogram(name: "foo", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13)
!10 = !DIFile(filename: "./foo.h", directory: "/Users/shubham/Development/CASDelta")
!11 = !DISubroutineType(types: !12)
!12 = !{null}
!13 = !{}
!14 = !DILocation(line: 2, column: 3, scope: !9)
!15 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 2, type: !16, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13)
!16 = !DISubroutineType(types: !17)
!17 = !{!18, !18}
!18 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!23 = !DILocation(line: 3, column: 3, scope: !15)

; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
define i32 @_Z3barv() #0 !dbg !19 {
ret i32 2, !dbg !20
}

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6}
!llvm.dbg.cu = !{!7}
!llvm.ident = !{!9}

!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 14, i32 0]}
!1 = !{i32 7, !"Dwarf Version", i32 4}
!2 = !{i32 2, !"Debug Info Version", i32 3}
!3 = !{i32 1, !"wchar_size", i32 4}
!4 = !{i32 8, !"PIC Level", i32 2}
!5 = !{i32 7, !"uwtable", i32 1}
!6 = !{i32 7, !"frame-pointer", i32 1}
!7 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !8, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None, sysroot: "/Users/somepath", sdk: "MacOSX.sdk")
!8 = !DIFile(filename: "a.cpp", directory: "/Users/shubham/Development/testclang")
!9 = !{!"clang"}
!10 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !11, file: !11, line: 1, type: !12, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !15)
!11 = !DIFile(filename: "./foo.h", directory: "/Users/shubham/Development/testclang")
!12 = !DISubroutineType(types: !13)
!13 = !{!14}
!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!15 = !{}
!16 = !DILocation(line: 2, column: 3, scope: !10)
!17 = distinct !DISubprogram(name: "foo2", linkageName: "_Z4foo2v", scope: !11, file: !11, line: 4, type: !12, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !15)
!18 = !DILocation(line: 5, column: 3, scope: !17)
!19 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !8, file: !8, line: 2, type: !12, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !15)
!20 = !DILocation(line: 3, column: 3, scope: !19)


//--- b.ll

target triple = "arm64-apple-macosx12.0.0"
define i32 @baz() #0 !dbg !9 {
ret i32 1, !dbg !14
; ModuleID = 'b.cpp'
source_filename = "b.cpp"
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-macosx13.0.0"

; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
define i32 @_Z3bazv() #0 !dbg !10 {
ret i32 1, !dbg !15
}

; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
define i32 @_Z3foov() #0 !dbg !16 {
ret i32 3, !dbg !18
}
define void @foo() #0 !dbg !15 {
ret void, !dbg !19

; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
define i32 @_Z4foo2v() #0 !dbg !19 {
ret i32 4, !dbg !20
}
define void @bar(i32 noundef %x) #0 !dbg !20 {
entry:
ret void, !dbg !27

; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
define i32 @_Z3barv() #0 !dbg !21 {
ret i32 2, !dbg !22
}
attributes #0 = { noinline nounwind optnone ssp uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 16.0.0 (https://github.com/apple/llvm-project.git d74d0d9fde90cccba7bf18066ac56e55e4402948)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None, sysroot: "/")
!1 = !DIFile(filename: "b.c", directory: "/Users/shubham/Development/CASDelta")
!2 = !{i32 7, !"Dwarf Version", i32 4}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 7, !"PIC Level", i32 2}
!6 = !{i32 7, !"uwtable", i32 2}
!7 = !{i32 7, !"frame-pointer", i32 2}
!9 = distinct !DISubprogram(name: "baz", scope: !1, file: !1, line: 1, type: !10, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13)
!10 = !DISubroutineType(types: !11)
!11 = !{!12}
!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!13 = !{}
!14 = !DILocation(line: 2, column: 5, scope: !9)
!15 = distinct !DISubprogram(name: "foo", scope: !16, file: !16, line: 1, type: !17, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13)
!16 = !DIFile(filename: "./foo.h", directory: "/Users/shubham/Development/CASDelta")
!17 = !DISubroutineType(types: !18)
!18 = !{null}
!19 = !DILocation(line: 2, column: 3, scope: !15)
!20 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 6, type: !21, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13)
!21 = !DISubroutineType(types: !22)
!22 = !{!12, !12}
!25 = !DILocation(line: 7, column: 10, scope: !20)
!26 = !DILocation(line: 7, column: 11, scope: !20)
!27 = !DILocation(line: 7, column: 3, scope: !20)

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6}
!llvm.dbg.cu = !{!7}
!llvm.ident = !{!9}

!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 14, i32 0]}
!1 = !{i32 7, !"Dwarf Version", i32 4}
!2 = !{i32 2, !"Debug Info Version", i32 3}
!3 = !{i32 1, !"wchar_size", i32 4}
!4 = !{i32 8, !"PIC Level", i32 2}
!5 = !{i32 7, !"uwtable", i32 1}
!6 = !{i32 7, !"frame-pointer", i32 1}
!7 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !8, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None, sysroot: "/Users/somepath", sdk: "MacOSX.some.sdk")
!8 = !DIFile(filename: "b.cpp", directory: "/Users/shubham/Development/testclang")
!9 = !{!"clang"}
!10 = distinct !DISubprogram(name: "baz", linkageName: "_Z3bazv", scope: !8, file: !8, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !14)
!11 = !DISubroutineType(types: !12)
!12 = !{!13}
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!14 = !{}
!15 = !DILocation(line: 2, column: 5, scope: !10)
!16 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !17, file: !17, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !14)
!17 = !DIFile(filename: "./foo.h", directory: "/Users/shubham/Development/testclang")
!18 = !DILocation(line: 2, column: 3, scope: !16)
!19 = distinct !DISubprogram(name: "foo2", linkageName: "_Z4foo2v", scope: !17, file: !17, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !14)
!20 = !DILocation(line: 5, column: 3, scope: !19)
!21 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !8, file: !8, line: 5, type: !11, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !14)
!22 = !DILocation(line: 6, column: 5, scope: !21)
1 change: 0 additions & 1 deletion llvm/test/DebugInfo/X86/cas-friendly.ll
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
; CHECK-NEXT: 0x{{[0-9a-z]+}} 10 2 1 0 0
; CHECK-NEXT: 0x{{[0-9a-z]+}} 10 2 1 0 0 epilogue_begin
; CHECK-NEXT: 0x{{[0-9a-z]+}} 10 2 1 0 0 end_sequence
; CHECK-NEXT: 0x{{[0-9a-z]+}} 1 0 1 0 0 is_stmt end_sequence

; ModuleID = './test.c'
source_filename = "./test.c"
Expand Down
4 changes: 1 addition & 3 deletions llvm/test/tools/llvm-cas-dump/basic_debug_test.ll
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
; DWARF: version: 4
; DWARF: prologue_length: 0x000000{{[0-9a-f]+}}
; DWARF: 0x0000000000000000 3 3 1 0 0 is_stmt prologue_end
; DWARF: 0x0000000000000000 3 3 1 0 0 is_stmt end_sequence
; DWARF: 0x0000000000000008 1 0 1 0 0 is_stmt end_sequence
; DWARF: 0x0000000000000008 3 3 1 0 0 is_stmt end_sequence

; CHECK: mc:assembler llvmcas://{{.*}}
; CHECK-NEXT: mc:header llvmcas://{{.*}}
Expand All @@ -44,7 +43,6 @@
; CHECK-NEXT: mc:debug_line_section llvmcas://{{.*}}
; CHECK-NEXT: mc:debug_line_distinct_data llvmcas://{{.*}}
; CHECK-NEXT: mc:debug_line llvmcas://{{.*}}
; CHECK-NEXT: mc:debug_line llvmcas://{{.*}}
; CHECK-NEXT: mc:padding llvmcas://{{.*}}
; CHECK-NEXT: mc:data_in_code llvmcas://{{.*}}
; CHECK-NEXT: mc:symbol_table llvmcas://{{.*}}
Expand Down