Skip to content

Commit be5c96b

Browse files
authored
[CodeGen][COFF] Always emit CodeView compiler info on Windows targets (#142970)
MSVC always emits minimal CodeView metadata with compiler information, even when debug info is otherwise disabled. Other tools may rely on this metadata being present. For example, linkers use it to determine whether hotpatching is enabled for the object file.
1 parent 60d0004 commit be5c96b

19 files changed

+219
-47
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ CodeGenModule::CodeGenModule(ASTContext &C,
414414
CodeGenOpts.CoverageNotesFile.size() ||
415415
CodeGenOpts.CoverageDataFile.size())
416416
DebugInfo.reset(new CGDebugInfo(*this));
417+
else if (getTriple().isOSWindows())
418+
// On Windows targets, we want to emit compiler info even if debug info is
419+
// otherwise disabled. Use a temporary CGDebugInfo instance to emit only
420+
// basic compiler metadata.
421+
CGDebugInfo(*this);
417422

418423
Block.GlobalUniqueCount = 0;
419424

@@ -1051,7 +1056,7 @@ void CodeGenModule::Release() {
10511056
"StrictVTablePointersRequirement",
10521057
llvm::MDNode::get(VMContext, Ops));
10531058
}
1054-
if (getModuleDebugInfo())
1059+
if (getModuleDebugInfo() || getTriple().isOSWindows())
10551060
// We support a single version in the linked module. The LLVM
10561061
// parser will drop debug info with a different version number
10571062
// (and warn about it, too).
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// REQUIRES: x86-registered-target
2+
// RUN: %clang --target=x86_64-windows -g -S -emit-llvm -o - %s | FileCheck %s
3+
// RUN: %clang --target=x86_64-windows -S -emit-llvm -o - %s | FileCheck %s
4+
int main (void) {
5+
return 0;
6+
}
7+
8+
// CHECK: i32 2, !"Debug Info Version", i32 3}

clang/test/CodeGen/debug-info-version.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// REQUIRES: !system-windows
12
// RUN: %clang -g -S -emit-llvm -o - %s | FileCheck %s
23
// RUN: %clang -S -emit-llvm -o - %s | FileCheck %s --check-prefix=NO_DEBUG
34
int main (void) {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// REQUIRES: x86-registered-target
2+
3+
// Check that CodeView compiler version is emitted even when debug info is otherwise disabled.
4+
5+
// RUN: %clang --target=i686-pc-windows-msvc -S -emit-llvm %s -o - | FileCheck --check-prefix=IR %s
6+
// IR: !llvm.dbg.cu = !{!0}
7+
// IR: !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, splitDebugInlining: false, nameTableKind: None)
8+
9+
// RUN: %clang --target=i686-pc-windows-msvc -c %s -o %t.o
10+
// RUN: llvm-readobj --codeview %t.o | FileCheck %s
11+
// CHECK: CodeViewDebugInfo [
12+
// CHECK-NEXT: Section: .debug$S (4)
13+
// CHECK-NEXT: Magic: 0x4
14+
// CHECK-NEXT: Subsection [
15+
// CHECK-NEXT: SubSectionType: Symbols (0xF1)
16+
// CHECK-NEXT: SubSectionSize:
17+
// CHECK-NEXT: ObjNameSym {
18+
// CHECK-NEXT: Kind: S_OBJNAME (0x1101)
19+
// CHECK-NEXT: Signature: 0x0
20+
// CHECK-NEXT: ObjectName:
21+
// CHECK-NEXT: }
22+
// CHECK-NEXT: Compile3Sym {
23+
// CHECK-NEXT: Kind: S_COMPILE3 (0x113C)
24+
// CHECK-NEXT: Language: Cpp (0x1)
25+
// CHECK-NEXT: Flags [ (0x0)
26+
// CHECK-NEXT: ]
27+
// CHECK-NEXT: Machine: Pentium3 (0x7)
28+
// CHECK-NEXT: FrontendVersion:
29+
// CHECK-NEXT: BackendVersion:
30+
// CHECK-NEXT: VersionName: clang version
31+
// CHECK-NEXT: }
32+
// CHECK-NEXT: ]
33+
// CHECK-NEXT: ]
34+
35+
int main() {
36+
return 0;
37+
}

clang/test/CodeGenCXX/debug-info-hotpatch-aarch64.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,9 @@
1111
// RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck %s --check-prefix=HOTPATCH
1212
// HOTPATCH: S_COMPILE3 [size = [[#]]]
1313
// HOTPATCH: flags = hot patchable
14-
///
15-
/// Unfortunately we need /Z7, Clang does not systematically generate S_COMPILE3.
16-
///
14+
//
1715
// RUN: %clang_cl --target=aarch64-pc-windows-msvc /c -o %t.obj -- %s
18-
// RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck %s --check-prefix=NO-HOTPATCH
19-
// NO-HOTPATCH-NOT: flags = hot patchable
16+
// RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck %s --check-prefix=HOTPATCH
2017

2118
int main() {
2219
return 0;

clang/test/CodeGenCXX/debug-info-hotpatch-arm.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,9 @@
1111
// RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck %s --check-prefix=HOTPATCH
1212
// HOTPATCH: S_COMPILE3 [size = [[#]]]
1313
// HOTPATCH: flags = hot patchable
14-
///
15-
/// Unfortunately we need /Z7, Clang does not systematically generate S_COMPILE3.
16-
///
14+
//
1715
// RUN: %clang_cl --target=arm-pc-windows-msvc /c -o %t.obj -- %s
18-
// RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck %s --check-prefix=NO-HOTPATCH
19-
// NO-HOTPATCH-NOT: flags = hot patchable
16+
// RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck %s --check-prefix=HOTPATCH
2017

2118
int main() {
2219
return 0;

clang/test/Frontend/ast-main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t1.ll -x c - < %s
1+
// RUN: env SDKROOT="/" %clang -emit-llvm -S -o - -x c - < %s | grep -v DIFile > %t1.ll
22
// RUN: env SDKROOT="/" %clang -emit-ast -o %t.ast %s
3-
// RUN: env SDKROOT="/" %clang -emit-llvm -S -o %t2.ll -x ast - < %t.ast
3+
// RUN: env SDKROOT="/" %clang -emit-llvm -S -o - -x ast - < %t.ast | grep -v DIFile > %t2.ll
44
// RUN: diff %t1.ll %t2.ll
55

66
int main(void) {

clang/test/Frontend/ast-main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: env SDKROOT="/" %clang -Wno-error=return-type -emit-llvm -S -o %t1.ll -x c++ - < %s
1+
// RUN: env SDKROOT="/" %clang -Wno-error=return-type -emit-llvm -S -o - -x c++ - < %s | grep -v DIFile > %t1.ll
22
// RUN: env SDKROOT="/" %clang -Wno-error=return-type -fno-delayed-template-parsing -emit-ast -o %t.ast %s
3-
// RUN: env SDKROOT="/" %clang -Wno-error=return-type -emit-llvm -S -o %t2.ll -x ast - < %t.ast
3+
// RUN: env SDKROOT="/" %clang -Wno-error=return-type -emit-llvm -S -o - -x ast - < %t.ast | grep -v DIFile > %t2.ll
44
// RUN: diff %t1.ll %t2.ll
55

66
// http://llvm.org/bugs/show_bug.cgi?id=15377

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,11 @@ bool AsmPrinter::doInitialization(Module &M) {
565565

566566
if (MAI->doesSupportDebugInformation()) {
567567
bool EmitCodeView = M.getCodeViewFlag();
568-
if (EmitCodeView &&
569-
(TM.getTargetTriple().isOSWindows() || TM.getTargetTriple().isUEFI()))
568+
// On Windows targets, emit minimal CodeView compiler info even when debug
569+
// info is disabled.
570+
if ((TM.getTargetTriple().isOSWindows() &&
571+
M.getNamedMetadata("llvm.dbg.cu")) ||
572+
(TM.getTargetTriple().isUEFI() && EmitCodeView))
570573
Handlers.push_back(std::make_unique<CodeViewDebug>(this));
571574
if (!EmitCodeView || M.getDwarfVersion()) {
572575
if (hasDebugInfo()) {

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ static CPUType mapArchToCVCPUType(Triple::ArchType Type) {
125125
return CPUType::ARM64;
126126
case Triple::ArchType::mipsel:
127127
return CPUType::MIPS;
128+
case Triple::ArchType::UnknownArch:
129+
return CPUType::Unknown;
128130
default:
129131
report_fatal_error("target architecture doesn't map to a CodeView CPUType");
130132
}
@@ -611,21 +613,33 @@ static SourceLanguage MapDWLangToCVLang(unsigned DWLang) {
611613
}
612614

613615
void CodeViewDebug::beginModule(Module *M) {
614-
// If module doesn't have named metadata anchors or COFF debug section
615-
// is not available, skip any debug info related stuff.
616-
if (!Asm->hasDebugInfo() ||
617-
!Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) {
616+
// If COFF debug section is not available, skip any debug info related stuff.
617+
if (!Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) {
618618
Asm = nullptr;
619619
return;
620620
}
621621

622+
CompilerInfoAsm = Asm;
622623
TheCPU = mapArchToCVCPUType(M->getTargetTriple().getArch());
623624

624625
// Get the current source language.
625-
const MDNode *Node = *M->debug_compile_units_begin();
626+
const MDNode *Node;
627+
if (Asm->hasDebugInfo()) {
628+
Node = *M->debug_compile_units_begin();
629+
} else {
630+
// When emitting only compiler information, we may have only NoDebug CUs,
631+
// which would be skipped by debug_compile_units_begin.
632+
NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
633+
Node = *CUs->operands().begin();
634+
}
626635
const auto *CU = cast<DICompileUnit>(Node);
627636

628637
CurrentSourceLanguage = MapDWLangToCVLang(CU->getSourceLanguage());
638+
if (!M->getCodeViewFlag() ||
639+
CU->getEmissionKind() == DICompileUnit::NoDebug) {
640+
Asm = nullptr;
641+
return;
642+
}
629643

630644
collectGlobalVariableInfo();
631645

@@ -636,7 +650,7 @@ void CodeViewDebug::beginModule(Module *M) {
636650
}
637651

638652
void CodeViewDebug::endModule() {
639-
if (!Asm || !Asm->hasDebugInfo())
653+
if (!CompilerInfoAsm)
640654
return;
641655

642656
// The COFF .debug$S section consists of several subsections, each starting
@@ -652,6 +666,8 @@ void CodeViewDebug::endModule() {
652666
emitObjName();
653667
emitCompilerInformation();
654668
endCVSubsection(CompilerInfo);
669+
if (!Asm)
670+
return;
655671

656672
emitInlineeLinesSubsection();
657673

@@ -788,7 +804,7 @@ void CodeViewDebug::emitTypeGlobalHashes() {
788804
void CodeViewDebug::emitObjName() {
789805
MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
790806

791-
StringRef PathRef(Asm->TM.Options.ObjectFilenameForDebug);
807+
StringRef PathRef(CompilerInfoAsm->TM.Options.ObjectFilenameForDebug);
792808
llvm::SmallString<256> PathStore(PathRef);
793809

794810
if (PathRef.empty() || PathRef == "-") {
@@ -846,7 +862,7 @@ void CodeViewDebug::emitCompilerInformation() {
846862
}
847863
using ArchType = llvm::Triple::ArchType;
848864
ArchType Arch = MMI->getModule()->getTargetTriple().getArch();
849-
if (Asm->TM.Options.Hotpatch || Arch == ArchType::thumb ||
865+
if (CompilerInfoAsm->TM.Options.Hotpatch || Arch == ArchType::thumb ||
850866
Arch == ArchType::aarch64) {
851867
Flags |= static_cast<uint32_t>(CompileSym3Flags::HotPatch);
852868
}
@@ -1015,7 +1031,7 @@ void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
10151031
const MCSymbol *KeySym = GVSec ? GVSec->getCOMDATSymbol() : nullptr;
10161032

10171033
MCSectionCOFF *DebugSec = cast<MCSectionCOFF>(
1018-
Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
1034+
CompilerInfoAsm->getObjFileLowering().getCOFFDebugSymbolsSection());
10191035
DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
10201036

10211037
OS.switchSection(DebugSec);

0 commit comments

Comments
 (0)