diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -500,6 +500,9 @@ cantFail(symData.readBytes(0, symData.getLength(), symsBuffer)); SmallVector scopes; + if (symsBuffer.empty()) + warn("empty symbols subsection in " + file->getName()); + // Iterate every symbol to check if any need to be realigned, and if so, how // much space we need to allocate for them. bool needsRealignment = false; diff --git a/lld/test/COFF/empty-subsection.s b/lld/test/COFF/empty-subsection.s new file mode 100644 --- /dev/null +++ b/lld/test/COFF/empty-subsection.s @@ -0,0 +1,20 @@ +# REQUIRES: x86 +# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s +# RUN: lld-link /entry:main /debug /out:%t.exe %t.obj 2>&1 | FileCheck %s + +# CHECK: warning: empty symbols subsection + +.globl main +.Lfunc_begin0: +main: + xorl %eax, %eax + retq +.Lfunc_end0: + +.section .debug$S,"dr" + .p2align 2 + .long 4 # Debug section magic + .long 241 # Symbol subsection for globals + .long .Ltmp5-.Ltmp4 # Subsection size +.Ltmp4: +.Ltmp5: diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -2150,10 +2150,13 @@ if (!DDTy->getName().empty()) { Info.Members.push_back({DDTy, 0}); - // Collect static const data members. + // Collect static const data members with values. if ((DDTy->getFlags() & DINode::FlagStaticMember) == - DINode::FlagStaticMember) - StaticConstMembers.push_back(DDTy); + DINode::FlagStaticMember) { + if (DDTy->getConstant() && (isa(DDTy->getConstant()) || + isa(DDTy->getConstant()))) + StaticConstMembers.push_back(DDTy); + } return; } @@ -3134,7 +3137,7 @@ dyn_cast_or_null(DTy->getConstant())) Value = APSInt(CFP->getValueAPF().bitcastToAPInt(), true); else - continue; + llvm_unreachable("cannot emit a constant without a value"); std::string QualifiedName = getFullyQualifiedName(Scope, DTy->getName()); diff --git a/llvm/test/DebugInfo/COFF/empty-globals-subsection.ll b/llvm/test/DebugInfo/COFF/empty-globals-subsection.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/empty-globals-subsection.ll @@ -0,0 +1,29 @@ +; RUN: llc < %s | FileCheck %s + +; The debug info contains a struct with a non-const static member. +; Check that we don't emit a symbol subsection for globals. + +; CHECK-NOT: Symbol subsection for globals + +; ModuleID = 'a.cpp' +source_filename = "a.cpp" +target triple = "x86_64-pc-windows-msvc19.25.28614" + +define dso_local i32 @main() { +entry: + ret i32 0 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!8, !9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None) +!1 = !DIFile(filename: "a.cpp", directory: "C:/path/to/test", checksumkind: CSK_MD5, checksum: "a1dbf3aabea9e8f9d1be48f60287942f") +!2 = !{} +!3 = !{!4} +!4 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !1, line: 5, size: 32, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !5, identifier: ".?AU?$A@J@@") +!5 = !{!6} +!6 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !4, file: !1, line: 6, baseType: !7, size: 32, flags: DIFlagStaticMember) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"CodeView", i32 1} +!9 = !{i32 2, !"Debug Info Version", i32 3}