[llvm] r271957 - [codeview] Emit information about global variables
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 6 16:23:47 PDT 2016
Author: rnk
Date: Mon Jun 6 18:23:47 2016
New Revision: 271957
URL: http://llvm.org/viewvc/llvm-project?rev=271957&view=rev
Log:
[codeview] Emit information about global variables
This currently emits everything as S_GDATA32, which isn't right for
things like thread locals, but it's a start.
Added:
llvm/trunk/test/DebugInfo/COFF/globals.ll
Modified:
llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
llvm/trunk/test/DebugInfo/COFF/asm.ll
llvm/trunk/test/DebugInfo/COFF/multifile.ll
llvm/trunk/test/DebugInfo/COFF/simple.ll
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=271957&r1=271956&r2=271957&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Mon Jun 6 18:23:47 2016
@@ -232,7 +232,7 @@ void CodeViewDebug::emitCodeViewMagicVer
}
void CodeViewDebug::endModule() {
- if (FnDebugInfo.empty())
+ if (!Asm || !MMI->hasDebugInfo())
return;
assert(Asm != nullptr);
@@ -242,13 +242,18 @@ void CodeViewDebug::endModule() {
// of the payload followed by the payload itself. The subsections are 4-byte
// aligned.
- // Make a subsection for all the inlined subprograms.
+ // Use the generic .debug$S section, and make a subsection for all the inlined
+ // subprograms.
+ switchToDebugSectionForSymbol(nullptr);
emitInlineeLinesSubsection();
// Emit per-function debug information.
for (auto &P : FnDebugInfo)
emitDebugInfoForFunction(P.first, P.second);
+ // Emit global variable debug information.
+ emitDebugInfoForGlobals();
+
// Switch back to the generic .debug$S section after potentially processing
// comdat symbol sections.
switchToDebugSectionForSymbol(nullptr);
@@ -326,17 +331,9 @@ void CodeViewDebug::emitInlineeLinesSubs
if (InlinedSubprograms.empty())
return;
- // Use the generic .debug$S section.
- switchToDebugSectionForSymbol(nullptr);
-
- MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(),
- *InlineEnd = MMI->getContext().createTempSymbol();
OS.AddComment("Inlinee lines subsection");
- OS.EmitIntValue(unsigned(ModuleSubstreamKind::InlineeLines), 4);
- OS.AddComment("Subsection size");
- OS.emitAbsoluteSymbolDiff(InlineEnd, InlineBegin, 4);
- OS.EmitLabel(InlineBegin);
+ MCSymbol *InlineEnd = beginCVSubsection(ModuleSubstreamKind::InlineeLines);
// We don't provide any extra file info.
// FIXME: Find out if debuggers use this info.
@@ -363,7 +360,7 @@ void CodeViewDebug::emitInlineeLinesSubs
OS.EmitIntValue(SP->getLine(), 4);
}
- OS.EmitLabel(InlineEnd);
+ endCVSubsection(InlineEnd);
}
void CodeViewDebug::collectInlineSiteChildren(
@@ -467,13 +464,8 @@ void CodeViewDebug::emitDebugInfoForFunc
FuncName = GlobalValue::getRealLinkageName(GV->getName());
// Emit a symbol subsection, required by VS2012+ to find function boundaries.
- MCSymbol *SymbolsBegin = MMI->getContext().createTempSymbol(),
- *SymbolsEnd = MMI->getContext().createTempSymbol();
OS.AddComment("Symbol subsection for " + Twine(FuncName));
- OS.EmitIntValue(unsigned(ModuleSubstreamKind::Symbols), 4);
- OS.AddComment("Subsection size");
- OS.emitAbsoluteSymbolDiff(SymbolsEnd, SymbolsBegin, 4);
- OS.EmitLabel(SymbolsBegin);
+ MCSymbol *SymbolsEnd = beginCVSubsection(ModuleSubstreamKind::Symbols);
{
MCSymbol *ProcRecordBegin = MMI->getContext().createTempSymbol(),
*ProcRecordEnd = MMI->getContext().createTempSymbol();
@@ -532,9 +524,7 @@ void CodeViewDebug::emitDebugInfoForFunc
OS.AddComment("Record kind: S_PROC_ID_END");
OS.EmitIntValue(unsigned(SymbolKind::S_PROC_ID_END), 2);
}
- OS.EmitLabel(SymbolsEnd);
- // Every subsection must be aligned to a 4-byte boundary.
- OS.EmitValueToAlignment(4);
+ endCVSubsection(SymbolsEnd);
// We have an assembler directive that takes care of the whole line table.
OS.EmitCVLinetableDirective(FI.FuncId, Fn, FI.End);
@@ -1272,3 +1262,76 @@ void CodeViewDebug::beginInstruction(con
return;
maybeRecordLocation(DL, Asm->MF);
}
+
+MCSymbol *CodeViewDebug::beginCVSubsection(ModuleSubstreamKind Kind) {
+ MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(),
+ *EndLabel = MMI->getContext().createTempSymbol();
+ OS.EmitIntValue(unsigned(Kind), 4);
+ OS.AddComment("Subsection size");
+ OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4);
+ OS.EmitLabel(BeginLabel);
+ return EndLabel;
+}
+
+void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) {
+ OS.EmitLabel(EndLabel);
+ // Every subsection must be aligned to a 4-byte boundary.
+ OS.EmitValueToAlignment(4);
+}
+
+void CodeViewDebug::emitDebugInfoForGlobals() {
+ NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
+ for (const MDNode *Node : CUs->operands()) {
+ const auto *CU = cast<DICompileUnit>(Node);
+
+ // First, emit all globals that are not in a comdat in a single symbol
+ // substream.
+ switchToDebugSectionForSymbol(nullptr);
+ OS.AddComment("Symbol subsection for globals");
+ MCSymbol *EndLabel = beginCVSubsection(ModuleSubstreamKind::Symbols);
+ for (const DIGlobalVariable *G : CU->getGlobalVariables()) {
+ if (const auto *GV = dyn_cast<GlobalVariable>(G->getVariable()))
+ if (!GV->hasComdat())
+ emitDebugInfoForGlobal(G, Asm->getSymbol(GV));
+ }
+ endCVSubsection(EndLabel);
+
+ // Second, emit each global that is in a comdat into its own .debug$S
+ // section along with its own symbol substream.
+ for (const DIGlobalVariable *G : CU->getGlobalVariables()) {
+ if (const auto *GV = dyn_cast<GlobalVariable>(G->getVariable())) {
+ if (GV->hasComdat()) {
+ MCSymbol *GVSym = Asm->getSymbol(GV);
+ OS.AddComment("Symbol subsection for " +
+ Twine(GlobalValue::getRealLinkageName(GV->getName())));
+ switchToDebugSectionForSymbol(GVSym);
+ EndLabel = beginCVSubsection(ModuleSubstreamKind::Symbols);
+ emitDebugInfoForGlobal(G, GVSym);
+ endCVSubsection(EndLabel);
+ }
+ }
+ }
+ }
+}
+
+void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
+ MCSymbol *GVSym) {
+ // DataSym record, see SymbolRecord.h for more info.
+ // FIXME: Thread local data, etc
+ MCSymbol *DataBegin = MMI->getContext().createTempSymbol(),
+ *DataEnd = MMI->getContext().createTempSymbol();
+ OS.AddComment("Record length");
+ OS.emitAbsoluteSymbolDiff(DataEnd, DataBegin, 2);
+ OS.EmitLabel(DataBegin);
+ OS.AddComment("Record kind: S_GDATA32");
+ OS.EmitIntValue(unsigned(SymbolKind::S_GDATA32), 2);
+ OS.AddComment("Type");
+ OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4);
+ OS.AddComment("DataOffset");
+ OS.EmitCOFFSecRel32(GVSym);
+ OS.AddComment("Segment");
+ OS.EmitCOFFSectionIndex(GVSym);
+ OS.AddComment("Name");
+ emitNullTerminatedSymbolName(OS, DIGV->getName());
+ OS.EmitLabel(DataEnd);
+}
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h?rev=271957&r1=271956&r2=271957&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h Mon Jun 6 18:23:47 2016
@@ -169,6 +169,17 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
+ void emitDebugInfoForGlobals();
+
+ void emitDebugInfoForGlobal(const DIGlobalVariable *DIGV, MCSymbol *GVSym);
+
+ /// Opens a subsection of the given kind in a .debug$S codeview section.
+ /// Returns an end label for use with endCVSubsection when the subsection is
+ /// finished.
+ MCSymbol *beginCVSubsection(codeview::ModuleSubstreamKind Kind);
+
+ void endCVSubsection(MCSymbol *EndLabel);
+
void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt,
const InlineSite &Site);
Modified: llvm/trunk/test/DebugInfo/COFF/asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/asm.ll?rev=271957&r1=271956&r2=271957&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/asm.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/asm.ll Mon Jun 6 18:23:47 2016
@@ -49,10 +49,11 @@
; X86-NEXT: .p2align 2
; Line table
; X86-NEXT: .cv_linetable 0, _f, [[END_OF_F]]
+
; File index to string table offset subsection
-; X86-NEXT: .cv_filechecksums
+; X86: .cv_filechecksums
; String table
-; X86-NEXT: .cv_stringtable
+; X86: .cv_stringtable
; OBJ32: Section {
; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53)
@@ -142,10 +143,12 @@
; X64-NEXT: .p2align 2
; Line table
; X64-NEXT: .cv_linetable 0, f, [[END_OF_F]]
+; X64: .p2align 2
+
; File index to string table offset subsection
-; X64-NEXT: .cv_filechecksums
+; X64: .cv_filechecksums
; String table
-; X64-NEXT: .cv_stringtable
+; X64: .cv_stringtable
; OBJ64: Section {
; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53)
Added: llvm/trunk/test/DebugInfo/COFF/globals.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/globals.ll?rev=271957&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/globals.ll (added)
+++ llvm/trunk/test/DebugInfo/COFF/globals.ll Mon Jun 6 18:23:47 2016
@@ -0,0 +1,146 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s --check-prefix=OBJ
+
+; C++ source to regenerate:
+; $ cat t.cpp
+; int first;
+; template <typename T> struct A { static const int comdat = 3; };
+; const int *middle = &A<void>::comdat;
+; int last;
+; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
+
+; ASM: .section .debug$S,"dr"
+; ASM: .p2align 2
+; ASM: .long 4 # Debug section magic
+
+; ASM: .short {{.*-.*}} # Record length
+; ASM: .short 4365 # Record kind: S_GDATA32
+; ASM: .long 116 # Type
+; ASM: .secrel32 "?first@@3HA" # DataOffset
+; ASM: .secidx "?first@@3HA" # Segment
+; ASM: .asciz "first" # Name
+
+; ASM: .short {{.*-.*}} # Record length
+; ASM: .short 4365 # Record kind: S_GDATA32
+; ASM: .long 4097 # Type
+; ASM: .secrel32 "?middle@@3PEBHEB" # DataOffset
+; ASM: .secidx "?middle@@3PEBHEB" # Segment
+; ASM: .asciz "middle" # Name
+
+; ASM: .short {{.*-.*}} # Record length
+; ASM: .short 4365 # Record kind: S_GDATA32
+; ASM: .long 116 # Type
+; ASM: .secrel32 "?last@@3HA" # DataOffset
+; ASM: .secidx "?last@@3HA" # Segment
+; ASM: .asciz "last" # Name
+
+; ASM: .section .debug$S,"dr",associative,"?comdat@?$A at X@@2HB"
+; ASM: .p2align 2
+; ASM: .long 4 # Debug section magic
+
+; ASM: .short {{.*-.*}} # Record length
+; ASM: .short 4365 # Record kind: S_GDATA32
+; ASM: .long 4096 # Type
+; ASM: .secrel32 "?comdat@?$A at X@@2HB" # DataOffset
+; ASM: .secidx "?comdat@?$A at X@@2HB" # Segment
+; ASM: .asciz "comdat" # Name
+
+; OBJ: CodeViewTypes [
+; OBJ: Section: .debug$T
+; OBJ: Magic: 0x4
+; OBJ: Modifier (0x1000) {
+; OBJ: TypeLeafKind: LF_MODIFIER (0x1001)
+; OBJ: ModifiedType: int (0x74)
+; OBJ: Modifiers [ (0x1)
+; OBJ: Const (0x1)
+; OBJ: ]
+; OBJ: }
+; OBJ: Pointer (0x1001) {
+; OBJ: TypeLeafKind: LF_POINTER (0x1002)
+; OBJ: PointeeType: const int (0x1000)
+; OBJ: PointerAttributes: 0x1000C
+; OBJ: PtrType: Near64 (0xC)
+; OBJ: PtrMode: Pointer (0x0)
+; OBJ: IsFlat: 0
+; OBJ: IsConst: 0
+; OBJ: IsVolatile: 0
+; OBJ: IsUnaligned: 0
+; OBJ: }
+; OBJ: ]
+
+; OBJ: CodeViewDebugInfo [
+; OBJ: Section: .debug$S
+; OBJ: Magic: 0x4
+; OBJ: Subsection [
+; OBJ: SubSectionType: Symbols (0xF1)
+; OBJ: DataSym {
+; OBJ: DataOffset: ?first@@3HA+0x0
+; OBJ: Type: int (0x74)
+; OBJ: DisplayName: first
+; OBJ: LinkageName: ?first@@3HA
+; OBJ: }
+; OBJ: DataSym {
+; OBJ: DataOffset: ?middle@@3PEBHEB+0x0
+; OBJ: Type: const int* (0x1001)
+; OBJ: DisplayName: middle
+; OBJ: LinkageName: ?middle@@3PEBHEB
+; OBJ: }
+; OBJ: DataSym {
+; OBJ: DataOffset: ?last@@3HA+0x0
+; OBJ: Type: int (0x74)
+; OBJ: DisplayName: last
+; OBJ: LinkageName: ?last@@3HA
+; OBJ: }
+; OBJ: ]
+; OBJ: ]
+; OBJ: CodeViewDebugInfo [
+; OBJ: Section: .debug$S (6)
+; OBJ: Magic: 0x4
+; OBJ: Subsection [
+; OBJ: SubSectionType: Symbols (0xF1)
+; OBJ: SubSectionSize: 0x15
+; OBJ: DataSym {
+; OBJ: DataOffset: ?comdat@?$A at X@@2HB+0x0
+; OBJ: Type: const int (0x1000)
+; OBJ: DisplayName: comdat
+; OBJ: LinkageName: ?comdat@?$A at X@@2HB
+; OBJ: }
+; OBJ: ]
+; OBJ: ]
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.23918"
+
+$"\01?comdat@?$A at X@@2HB" = comdat any
+
+@"\01?first@@3HA" = global i32 0, align 4
+@"\01?comdat@?$A at X@@2HB" = linkonce_odr constant i32 3, comdat, align 4
+@"\01?middle@@3PEBHEB" = global i32* @"\01?comdat@?$A at X@@2HB", align 8
+@"\01?last@@3HA" = global i32 0, align 4
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!16, !17, !18}
+!llvm.ident = !{!19}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 271937)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
+!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
+!2 = !{}
+!3 = !{!4, !6, !13, !15}
+!4 = distinct !DIGlobalVariable(name: "first", linkageName: "\01?first@@3HA", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, variable: i32* @"\01?first@@3HA")
+!5 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!6 = distinct !DIGlobalVariable(name: "comdat", linkageName: "\01?comdat@?$A at X@@2HB", scope: !0, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, variable: i32* @"\01?comdat@?$A at X@@2HB", declaration: !8)
+!7 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !5)
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "comdat", scope: !9, file: !1, line: 2, baseType: !7, flags: DIFlagStaticMember, extraData: i32 3)
+!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A<void>", file: !1, line: 2, size: 8, align: 8, elements: !10, templateParams: !11)
+!10 = !{!8}
+!11 = !{!12}
+!12 = !DITemplateTypeParameter(name: "T", type: null)
+!13 = distinct !DIGlobalVariable(name: "middle", linkageName: "\01?middle@@3PEBHEB", scope: !0, file: !1, line: 3, type: !14, isLocal: false, isDefinition: true, variable: i32** @"\01?middle@@3PEBHEB")
+!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64)
+!15 = distinct !DIGlobalVariable(name: "last", linkageName: "\01?last@@3HA", scope: !0, file: !1, line: 4, type: !5, isLocal: false, isDefinition: true, variable: i32* @"\01?last@@3HA")
+!16 = !{i32 2, !"CodeView", i32 1}
+!17 = !{i32 2, !"Debug Info Version", i32 3}
+!18 = !{i32 1, !"PIC Level", i32 2}
+!19 = !{!"clang version 3.9.0 (trunk 271937)"}
Modified: llvm/trunk/test/DebugInfo/COFF/multifile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/multifile.ll?rev=271957&r1=271956&r2=271957&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/multifile.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/multifile.ll Mon Jun 6 18:23:47 2016
@@ -59,9 +59,9 @@
; Line table
; X86-NEXT: .cv_linetable 0, _f, [[END_OF_F]]
; File index to string table offset subsection
-; X86-NEXT: .cv_filechecksums
+; X86: .cv_filechecksums
; String table
-; X86-NEXT: .cv_stringtable
+; X86: .cv_stringtable
; OBJ32: Section {
; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53)
Modified: llvm/trunk/test/DebugInfo/COFF/simple.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/simple.ll?rev=271957&r1=271956&r2=271957&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/simple.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/simple.ll Mon Jun 6 18:23:47 2016
@@ -36,7 +36,7 @@
; X86-NEXT: .long [[END_OF_F]]-_f
; X86-NEXT: .long 0
; X86-NEXT: .long 0
-; X86-NEXT: .long 4098
+; X86-NEXT: .long 4098 # Function type index
; X86-NEXT: .secrel32 _f
; X86-NEXT: .secidx _f
; X86-NEXT: .byte 0
@@ -48,10 +48,11 @@
; X86-NEXT: .p2align 2
; Line table
; X86-NEXT: .cv_linetable 0, _f, [[END_OF_F]]
+
; File index to string table offset subsection
-; X86-NEXT: .cv_filechecksums
+; X86: .cv_filechecksums
; String table
-; X86-NEXT: .cv_stringtable
+; X86: .cv_stringtable
; OBJ32: Section {
; OBJ32: Name: .debug$S (2E 64 65 62 75 67 24 53)
@@ -126,7 +127,7 @@
; X64-NEXT: .long [[END_OF_F]]-f
; X64-NEXT: .long 0
; X64-NEXT: .long 0
-; X64-NEXT: .long 4098
+; X64-NEXT: .long 4098 # Function type index
; X64-NEXT: .secrel32 f
; X64-NEXT: .secidx f
; X64-NEXT: .byte 0
@@ -138,10 +139,11 @@
; X64-NEXT: .p2align 2
; Line table
; X64-NEXT: .cv_linetable 0, f, [[END_OF_F]]
+
; File index to string table offset subsection
-; X64-NEXT: .cv_filechecksums
+; X64: .cv_filechecksums
; String table
-; X64-NEXT: .cv_stringtable
+; X64: .cv_stringtable
; OBJ64: Section {
; OBJ64: Name: .debug$S (2E 64 65 62 75 67 24 53)
More information about the llvm-commits
mailing list