Skip to content

Commit d199ab4

Browse files
authored
[LLVM][DWARF] Fix accelerator table switching between CU and TU (#77511)
Bug 1 is triggered when a TU is already created, and we process the same DICompositeType at a top level. We would switch to TU accelerator table, but would not switch back on early exit. As the result we would add CU entries to the TU accelerator table. When we try to write out TUs and normalize entries, the offsets for DIEs that are part of a CU would not have been computed, and it would assert on getOffset(). Bug 2 is triggered when processing nested TUs. When we exit from addDwarfTypeUnitType we switched back to CU accelerator table. If we were processing nested TUs, the rest of the entries from TUs would be added to CU accelerator table. When we write out TUs, all the DIE pointers will become invalid. Eventually it will assert during normalization step after CU is processed.
1 parent 5417a5f commit d199ab4

File tree

3 files changed

+141
-2
lines changed

3 files changed

+141
-2
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
; REQUIRES: asserts
2+
3+
;; Tests that we use correct accelerator table when processing nested TUs.
4+
;; Assert is not triggered.
5+
;; File1
6+
;; struct Foo {
7+
;; char f;
8+
;; };
9+
;; struct Foo2 {
10+
;; char f;
11+
;; Foo f1;
12+
;; };
13+
;; void fooFunc() {
14+
;; Foo2 global2;
15+
;; }
16+
;; clang++ <file>.cpp -O0 -g2 -fdebug-types-section -gpubnames -S -emit-llvm -o <file>.ll
17+
18+
; RUN: llc -O0 -dwarf-version=5 -generate-type-units -filetype=obj < %s -o %t.o
19+
; RUN: llvm-readelf --sections %t.o | FileCheck --check-prefix=OBJ %s
20+
21+
; OBJ: debug_names
22+
23+
; ModuleID = 'main.cpp'
24+
source_filename = "main.cpp"
25+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
26+
target triple = "x86_64-unknown-linux-gnu"
27+
28+
%struct.Foo2 = type { i8, %struct.Foo }
29+
%struct.Foo = type { i8 }
30+
31+
; Function Attrs: mustprogress noinline nounwind optnone uwtable
32+
define dso_local void @_Z7fooFuncv() #0 !dbg !10 {
33+
entry:
34+
%global2 = alloca %struct.Foo2, align 1
35+
call void @llvm.dbg.declare(metadata ptr %global2, metadata !14, metadata !DIExpression()), !dbg !23
36+
ret void, !dbg !24
37+
}
38+
39+
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
40+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
41+
42+
attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
43+
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
44+
45+
!llvm.dbg.cu = !{!0}
46+
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
47+
!llvm.ident = !{!9}
48+
49+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false)
50+
!1 = !DIFile(filename: "main.cpp", directory: "/smallMultipleTUs", checksumkind: CSK_MD5, checksum: "70bff4d50322126f3d8ca4178afad376")
51+
!2 = !{i32 7, !"Dwarf Version", i32 5}
52+
!3 = !{i32 2, !"Debug Info Version", i32 3}
53+
!4 = !{i32 1, !"wchar_size", i32 4}
54+
!5 = !{i32 8, !"PIC Level", i32 2}
55+
!6 = !{i32 7, !"PIE Level", i32 2}
56+
!7 = !{i32 7, !"uwtable", i32 2}
57+
!8 = !{i32 7, !"frame-pointer", i32 2}
58+
!9 = !{!"clang version 18.0.0git"}
59+
!10 = distinct !DISubprogram(name: "fooFunc", linkageName: "_Z7fooFuncv", scope: !1, file: !1, line: 9, type: !11, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13)
60+
!11 = !DISubroutineType(types: !12)
61+
!12 = !{null}
62+
!13 = !{}
63+
!14 = !DILocalVariable(name: "global2", scope: !10, file: !1, line: 10, type: !15)
64+
!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo2", file: !1, line: 4, size: 16, flags: DIFlagTypePassByValue, elements: !16, identifier: "_ZTS4Foo2")
65+
!16 = !{!17, !19}
66+
!17 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !15, file: !1, line: 5, baseType: !18, size: 8)
67+
!18 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
68+
!19 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !15, file: !1, line: 6, baseType: !20, size: 8, offset: 8)
69+
!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !21, identifier: "_ZTS3Foo")
70+
!21 = !{!22}
71+
!22 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !20, file: !1, line: 2, baseType: !18, size: 8)
72+
!23 = !DILocation(line: 10, column: 6, scope: !10)
73+
!24 = !DILocation(line: 11, column: 1, scope: !10)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
; REQUIRES: asserts
2+
3+
;; Tests that accelerator table switches correctly from TU to CU when a top level TU is re-used.
4+
;; Assert is not triggered.
5+
;; File1
6+
;; struct Foo {
7+
;; char fChar;
8+
;; };
9+
;; Foo fGlobal;
10+
;; FIle2
11+
;; struct Foo {
12+
;; char fChar;
13+
;; };
14+
;; Foo fGlobal2;
15+
;; clang++ <file>.cpp -O0 -g2 -fdebug-types-section -gpubnames -S -emit-llvm -o <file>.ll
16+
;; llvm-link file1.ll file2.ll -S -o thinlto-debug-names-tu-reuse.ll
17+
18+
; RUN: llc -O0 -dwarf-version=5 -generate-type-units -filetype=obj < %s -o %t.o
19+
; RUN: llvm-readelf --sections %t.o | FileCheck --check-prefix=OBJ %s
20+
21+
; OBJ: debug_names
22+
23+
; ModuleID = 'llvm-link'
24+
source_filename = "llvm-link"
25+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
26+
target triple = "x86_64-unknown-linux-gnu"
27+
28+
%struct.Foo = type { i8 }
29+
30+
@fGlobal = dso_local global %struct.Foo zeroinitializer, align 1, !dbg !0
31+
@fGlobal2 = dso_local global %struct.Foo zeroinitializer, align 1, !dbg !9
32+
33+
!llvm.dbg.cu = !{!2, !11}
34+
!llvm.ident = !{!14, !14}
35+
!llvm.module.flags = !{!15, !16, !17, !18, !19, !20, !21}
36+
37+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
38+
!1 = distinct !DIGlobalVariable(name: "fGlobal", scope: !2, file: !3, line: 5, type: !5, isLocal: false, isDefinition: true)
39+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 18.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false)
40+
!3 = !DIFile(filename: "main.cpp", directory: "/smallTUReuse", checksumkind: CSK_MD5, checksum: "4f1831504f0948b03880356fae49cb58")
41+
!4 = !{!0}
42+
!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !3, line: 2, size: 8, flags: DIFlagTypePassByValue, elements: !6, identifier: "_ZTS3Foo")
43+
!6 = !{!7}
44+
!7 = !DIDerivedType(tag: DW_TAG_member, name: "fChar", scope: !5, file: !3, line: 3, baseType: !8, size: 8)
45+
!8 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
46+
!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression())
47+
!10 = distinct !DIGlobalVariable(name: "fGlobal2", scope: !11, file: !12, line: 5, type: !5, isLocal: false, isDefinition: true)
48+
!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !12, producer: "clang version 18.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !13, splitDebugInlining: false)
49+
!12 = !DIFile(filename: "helper.cpp", directory: "/smallTUReuse", checksumkind: CSK_MD5, checksum: "014145d46991fd1eb6a2192d382feb75")
50+
!13 = !{!9}
51+
!14 = !{!"clang version 18.0.0git"}
52+
!15 = !{i32 7, !"Dwarf Version", i32 5}
53+
!16 = !{i32 2, !"Debug Info Version", i32 3}
54+
!17 = !{i32 1, !"wchar_size", i32 4}
55+
!18 = !{i32 8, !"PIC Level", i32 2}
56+
!19 = !{i32 7, !"PIE Level", i32 2}
57+
!20 = !{i32 7, !"uwtable", i32 2}
58+
!21 = !{i32 7, !"frame-pointer", i32 2}

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,7 +3455,6 @@ uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
34553455
void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
34563456
StringRef Identifier, DIE &RefDie,
34573457
const DICompositeType *CTy) {
3458-
setCurrentDWARF5AccelTable(DWARF5AccelTableKind::TU);
34593458
// Fast path if we're building some type units and one has already used the
34603459
// address pool we know we're going to throw away all this work anyway, so
34613460
// don't bother building dependent types.
@@ -3468,6 +3467,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
34683467
return;
34693468
}
34703469

3470+
setCurrentDWARF5AccelTable(DWARF5AccelTableKind::TU);
34713471
bool TopLevelType = TypeUnitsUnderConstruction.empty();
34723472
AddrPool.resetUsedFlag();
34733473

@@ -3556,9 +3556,9 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
35563556
AccelTypeUnitsDebugNames.convertDieToOffset();
35573557
AccelDebugNames.addTypeEntries(AccelTypeUnitsDebugNames);
35583558
AccelTypeUnitsDebugNames.clear();
3559+
setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
35593560
}
35603561
CU.addDIETypeSignature(RefDie, Signature);
3561-
setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
35623562
}
35633563

35643564
// Add the Name along with its companion DIE to the appropriate accelerator
@@ -3587,6 +3587,14 @@ void DwarfDebug::addAccelNameImpl(
35873587
break;
35883588
case AccelTableKind::Dwarf: {
35893589
DWARF5AccelTable &Current = getCurrentDWARF5AccelTable();
3590+
assert((&Current == &AccelTypeUnitsDebugNames) ||
3591+
((&Current == &AccelDebugNames) &&
3592+
(Unit.getUnitDie().getTag() != dwarf::DW_TAG_type_unit)) &&
3593+
"Kind is CU but TU is being processed.");
3594+
assert((&Current == &AccelDebugNames) ||
3595+
((&Current == &AccelTypeUnitsDebugNames) &&
3596+
(Unit.getUnitDie().getTag() == dwarf::DW_TAG_type_unit)) &&
3597+
"Kind is TU but CU is being processed.");
35903598
// The type unit can be discarded, so need to add references to final
35913599
// acceleration table once we know it's complete and we emit it.
35923600
Current.addName(Ref, Die, Unit.getUniqueID());

0 commit comments

Comments
 (0)