Skip to content

Commit

Permalink
[LLVM][DWARF] Fix accelerator table switching between CU and TU (#77511)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ayermolo committed Jan 12, 2024
1 parent 5417a5f commit d199ab4
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 2 deletions.
73 changes: 73 additions & 0 deletions clang/test/CodeGen/debug-names-compound-type-units.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
; REQUIRES: asserts

;; Tests that we use correct accelerator table when processing nested TUs.
;; Assert is not triggered.
;; File1
;; struct Foo {
;; char f;
;; };
;; struct Foo2 {
;; char f;
;; Foo f1;
;; };
;; void fooFunc() {
;; Foo2 global2;
;; }
;; clang++ <file>.cpp -O0 -g2 -fdebug-types-section -gpubnames -S -emit-llvm -o <file>.ll

; RUN: llc -O0 -dwarf-version=5 -generate-type-units -filetype=obj < %s -o %t.o
; RUN: llvm-readelf --sections %t.o | FileCheck --check-prefix=OBJ %s

; OBJ: debug_names

; ModuleID = 'main.cpp'
source_filename = "main.cpp"
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"
target triple = "x86_64-unknown-linux-gnu"

%struct.Foo2 = type { i8, %struct.Foo }
%struct.Foo = type { i8 }

; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local void @_Z7fooFuncv() #0 !dbg !10 {
entry:
%global2 = alloca %struct.Foo2, align 1
call void @llvm.dbg.declare(metadata ptr %global2, metadata !14, metadata !DIExpression()), !dbg !23
ret void, !dbg !24
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1

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" }
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

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

!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)
!1 = !DIFile(filename: "main.cpp", directory: "/smallMultipleTUs", checksumkind: CSK_MD5, checksum: "70bff4d50322126f3d8ca4178afad376")
!2 = !{i32 7, !"Dwarf Version", i32 5}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 8, !"PIC Level", i32 2}
!6 = !{i32 7, !"PIE Level", i32 2}
!7 = !{i32 7, !"uwtable", i32 2}
!8 = !{i32 7, !"frame-pointer", i32 2}
!9 = !{!"clang version 18.0.0git"}
!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)
!11 = !DISubroutineType(types: !12)
!12 = !{null}
!13 = !{}
!14 = !DILocalVariable(name: "global2", scope: !10, file: !1, line: 10, type: !15)
!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo2", file: !1, line: 4, size: 16, flags: DIFlagTypePassByValue, elements: !16, identifier: "_ZTS4Foo2")
!16 = !{!17, !19}
!17 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !15, file: !1, line: 5, baseType: !18, size: 8)
!18 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
!19 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !15, file: !1, line: 6, baseType: !20, size: 8, offset: 8)
!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !21, identifier: "_ZTS3Foo")
!21 = !{!22}
!22 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !20, file: !1, line: 2, baseType: !18, size: 8)
!23 = !DILocation(line: 10, column: 6, scope: !10)
!24 = !DILocation(line: 11, column: 1, scope: !10)
58 changes: 58 additions & 0 deletions clang/test/CodeGen/thinlto-debug-names-tu-reuse.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
; REQUIRES: asserts

;; Tests that accelerator table switches correctly from TU to CU when a top level TU is re-used.
;; Assert is not triggered.
;; File1
;; struct Foo {
;; char fChar;
;; };
;; Foo fGlobal;
;; FIle2
;; struct Foo {
;; char fChar;
;; };
;; Foo fGlobal2;
;; clang++ <file>.cpp -O0 -g2 -fdebug-types-section -gpubnames -S -emit-llvm -o <file>.ll
;; llvm-link file1.ll file2.ll -S -o thinlto-debug-names-tu-reuse.ll

; RUN: llc -O0 -dwarf-version=5 -generate-type-units -filetype=obj < %s -o %t.o
; RUN: llvm-readelf --sections %t.o | FileCheck --check-prefix=OBJ %s

; OBJ: debug_names

; ModuleID = 'llvm-link'
source_filename = "llvm-link"
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"
target triple = "x86_64-unknown-linux-gnu"

%struct.Foo = type { i8 }

@fGlobal = dso_local global %struct.Foo zeroinitializer, align 1, !dbg !0
@fGlobal2 = dso_local global %struct.Foo zeroinitializer, align 1, !dbg !9

!llvm.dbg.cu = !{!2, !11}
!llvm.ident = !{!14, !14}
!llvm.module.flags = !{!15, !16, !17, !18, !19, !20, !21}

!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "fGlobal", scope: !2, file: !3, line: 5, type: !5, isLocal: false, isDefinition: true)
!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)
!3 = !DIFile(filename: "main.cpp", directory: "/smallTUReuse", checksumkind: CSK_MD5, checksum: "4f1831504f0948b03880356fae49cb58")
!4 = !{!0}
!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !3, line: 2, size: 8, flags: DIFlagTypePassByValue, elements: !6, identifier: "_ZTS3Foo")
!6 = !{!7}
!7 = !DIDerivedType(tag: DW_TAG_member, name: "fChar", scope: !5, file: !3, line: 3, baseType: !8, size: 8)
!8 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression())
!10 = distinct !DIGlobalVariable(name: "fGlobal2", scope: !11, file: !12, line: 5, type: !5, isLocal: false, isDefinition: true)
!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)
!12 = !DIFile(filename: "helper.cpp", directory: "/smallTUReuse", checksumkind: CSK_MD5, checksum: "014145d46991fd1eb6a2192d382feb75")
!13 = !{!9}
!14 = !{!"clang version 18.0.0git"}
!15 = !{i32 7, !"Dwarf Version", i32 5}
!16 = !{i32 2, !"Debug Info Version", i32 3}
!17 = !{i32 1, !"wchar_size", i32 4}
!18 = !{i32 8, !"PIC Level", i32 2}
!19 = !{i32 7, !"PIE Level", i32 2}
!20 = !{i32 7, !"uwtable", i32 2}
!21 = !{i32 7, !"frame-pointer", i32 2}
12 changes: 10 additions & 2 deletions llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3455,7 +3455,6 @@ uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
StringRef Identifier, DIE &RefDie,
const DICompositeType *CTy) {
setCurrentDWARF5AccelTable(DWARF5AccelTableKind::TU);
// Fast path if we're building some type units and one has already used the
// address pool we know we're going to throw away all this work anyway, so
// don't bother building dependent types.
Expand All @@ -3468,6 +3467,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
return;
}

setCurrentDWARF5AccelTable(DWARF5AccelTableKind::TU);
bool TopLevelType = TypeUnitsUnderConstruction.empty();
AddrPool.resetUsedFlag();

Expand Down Expand Up @@ -3556,9 +3556,9 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
AccelTypeUnitsDebugNames.convertDieToOffset();
AccelDebugNames.addTypeEntries(AccelTypeUnitsDebugNames);
AccelTypeUnitsDebugNames.clear();
setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
}
CU.addDIETypeSignature(RefDie, Signature);
setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
}

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

0 comments on commit d199ab4

Please sign in to comment.