diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index 57ba40f7ac26f..3fc241b066b35 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -335,6 +335,8 @@ class MCContext { MCTargetOptions const *TargetOptions; + llvm::sys::path::Style PathStyle = llvm::sys::path::Style::native; + bool HadError = false; void reportCommon(SMLoc Loc, @@ -721,6 +723,8 @@ class MCContext { void setDwarfCompileUnitID(unsigned CUIndex) { DwarfCompileUnitID = CUIndex; } + llvm::sys::path::Style getPathStyle() const { return PathStyle; } + /// Specifies the "root" file and directory of the compilation unit. /// These are "file 0" and "directory 0" in DWARF v5. void setMCLineTableRootFile(unsigned CUID, StringRef CompilationDir, @@ -728,7 +732,7 @@ class MCContext { std::optional Checksum, std::optional Source) { getMCDwarfLineTable(CUID).setRootFile(CompilationDir, Filename, Checksum, - Source); + Source, PathStyle); } /// Reports whether MD5 checksum usage is consistent (all-or-none). diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h index 1392336968e74..58e93d790305c 100644 --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -21,6 +21,7 @@ #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Error.h" #include "llvm/Support/MD5.h" +#include "llvm/Support/Path.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/StringSaver.h" #include @@ -277,6 +278,7 @@ struct MCDwarfLineTableHeader { StringMap SourceIdMap; std::string CompilationDir; MCDwarfFile RootFile; + llvm::sys::path::Style PathStyle = llvm::sys::path::Style::native; bool HasAnySource = false; private: @@ -311,7 +313,9 @@ struct MCDwarfLineTableHeader { void setRootFile(StringRef Directory, StringRef FileName, std::optional Checksum, - std::optional Source) { + std::optional Source, + llvm::sys::path::Style S = llvm::sys::path::Style::native) { + PathStyle = S; CompilationDir = std::string(Directory); RootFile.Name = std::string(FileName); RootFile.DirIndex = 0; @@ -342,10 +346,11 @@ class MCDwarfDwoLineTable { public: void maybeSetRootFile(StringRef Directory, StringRef FileName, std::optional Checksum, - std::optional Source) { + std::optional Source, + llvm::sys::path::Style S) { if (!Header.RootFile.Name.empty()) return; - Header.setRootFile(Directory, FileName, Checksum, Source); + Header.setRootFile(Directory, FileName, Checksum, Source, S); } unsigned getFile(StringRef Directory, StringRef FileName, @@ -394,7 +399,9 @@ class MCDwarfLineTable { void setRootFile(StringRef Directory, StringRef FileName, std::optional Checksum, - std::optional Source) { + std::optional Source, + llvm::sys::path::Style S) { + Header.PathStyle = S; Header.CompilationDir = std::string(Directory); Header.RootFile.Name = std::string(FileName); Header.RootFile.DirIndex = 0; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 88ed3f5dc7b4b..3c3aaffeaba3d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -3429,7 +3429,8 @@ MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) { const DICompileUnit *DIUnit = CU.getCUNode(); SplitTypeUnitFileTable.maybeSetRootFile( DIUnit->getDirectory(), DIUnit->getFilename(), - getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource()); + getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource(), + Asm->OutStreamer->getContext().getPathStyle()); return &SplitTypeUnitFileTable; } diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index b97f9d9f5fed0..e1e3f9ddfeff7 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -59,6 +59,10 @@ using namespace llvm; +cl::opt ForceDWARFWindowsPathSeps ("force-dwarf-windows-path-seps", + cl::desc("Use Windows path separators when building DWARF linetables"), + cl::Hidden); + static void defaultDiagHandler(const SMDiagnostic &SMD, bool, const SourceMgr &, std::vector &) { SMD.print(nullptr, errs()); @@ -77,6 +81,9 @@ MCContext::MCContext(const Triple &TheTriple, const MCAsmInfo *mai, SaveTempLabels = TargetOptions && TargetOptions->MCSaveTempLabels; SecureLogFile = TargetOptions ? TargetOptions->AsSecureLogFile : ""; + if (ForceDWARFWindowsPathSeps || TheTriple.isPS()) + PathStyle = llvm::sys::path::Style::windows; + if (SrcMgr && SrcMgr->getNumBuffers()) MainFileName = std::string(SrcMgr->getMemoryBuffer(SrcMgr->getMainFileID()) ->getBufferIdentifier()); @@ -970,12 +977,12 @@ void MCContext::setGenDwarfRootFile(StringRef InputFileName, StringRef Buffer) { if (FileNameBuf.empty() || FileNameBuf == "-") FileNameBuf = ""; if (!getMainFileName().empty() && FileNameBuf != getMainFileName()) { - llvm::sys::path::remove_filename(FileNameBuf); - llvm::sys::path::append(FileNameBuf, getMainFileName()); + llvm::sys::path::remove_filename(FileNameBuf, PathStyle); + llvm::sys::path::append(FileNameBuf, PathStyle, getMainFileName()); } StringRef FileName = FileNameBuf; if (FileName.consume_front(getCompilationDir())) - if (llvm::sys::path::is_separator(FileName.front())) + if (llvm::sys::path::is_separator(FileName.front(), PathStyle)) FileName = FileName.drop_front(); assert(!FileName.empty()); setMCLineTableRootFile( diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index e058358fb8ad4..3df95d8a0f196 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -664,9 +664,9 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName, if (Directory.empty()) { // Separate the directory part from the basename of the FileName. - StringRef tFileName = sys::path::filename(FileName); + StringRef tFileName = sys::path::filename(FileName, PathStyle); if (!tFileName.empty()) { - Directory = sys::path::parent_path(FileName); + Directory = sys::path::parent_path(FileName, PathStyle); if (!Directory.empty()) FileName = tFileName; } @@ -939,7 +939,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, static void EmitGenDwarfInfo(MCStreamer *MCOS, const MCSymbol *AbbrevSectionSymbol, const MCSymbol *LineSectionSymbol, - const MCSymbol *RangesSymbol) { + const MCSymbol *RangesSymbol, + llvm::sys::path::Style Style) { MCContext &context = MCOS->getContext(); MCOS->switchSection(context.getObjectFileInfo()->getDwarfInfoSection()); @@ -1037,7 +1038,7 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, const SmallVectorImpl &MCDwarfDirs = context.getMCDwarfDirs(); if (MCDwarfDirs.size() > 0) { MCOS->emitBytes(MCDwarfDirs[0]); - MCOS->emitBytes(sys::path::get_separator()); + MCOS->emitBytes(sys::path::get_separator(Style)); } const SmallVectorImpl &MCDwarfFiles = context.getMCDwarfFiles(); // MCDwarfFiles might be empty if we have an empty source file. @@ -1225,7 +1226,8 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { EmitGenDwarfAbbrev(MCOS); // Output the data for .debug_info section. - EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, RangesSymbol); + EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, RangesSymbol, + context.getPathStyle()); } // diff --git a/llvm/test/DebugInfo/dir-table-path-separators.ll b/llvm/test/DebugInfo/dir-table-path-separators.ll new file mode 100644 index 0000000000000..a9c8e039af55f --- /dev/null +++ b/llvm/test/DebugInfo/dir-table-path-separators.ll @@ -0,0 +1,74 @@ +; RUN: llc %s -o - -filetype=obj -mtriple x86_64-pc-linux-gnu | llvm-dwarfdump - --debug-line | FileCheck %s --check-prefix=LINUX +; RUN: llc %s -o - -filetype=obj -mtriple x86_64-pc-linux-gnu -force-dwarf-windows-path-seps=true | llvm-dwarfdump - --debug-line | FileCheck %s --check-prefix=PS5 +; RUN: llc %s -o - -filetype=obj -mtriple x86_64-sie-ps5 | llvm-dwarfdump - --debug-line | FileCheck %s --check-prefix=PS5 +; +; UNSUPPORTED: system-windows +; +; Check that the DWARF-printing MC backend is willing to consider Windows '\' +; characters as path separators so that it can build the directory index table. +; On Linux, the Windows path separators below would been seen as part of the +; filename, and so wouldn't be combined into a directory entry. Wheras on +; Windows (or a target masquerading as Windows) they should be combined into a +; "foo\bar" directory. +; +; LINUX: include_directories[ 0] = "C:\\foobar" +; LINUX: file_names[ 0]: +; LINUX: name: "foo\\bar\\test.cpp" +; LINUX: dir_index: 0 +; LINUX: file_names[ 1]: +; LINUX: name: "foo\\bar\\bar.cpp" +; LINUX: dir_index: 0 +; LINUX: file_names[ 2]: +; LINUX: name: "foo\\bar\\baz.cpp" +; LINUX: dir_index: 0 +; +; PS5: include_directories[ 0] = "C:\\foobar" +; PS5-NEXT: include_directories[ 1] = "foo\\bar" +; PS5-NEXT: file_names[ 0]: +; PS5-NEXT: name: "foo\\bar\\test.cpp" +; PS5-NEXT: dir_index: 0 +; PS5-NEXT: file_names[ 1]: +; PS5-NEXT: name: "bar.cpp" +; PS5-NEXT: dir_index: 1 +; PS5-NEXT: file_names[ 2]: +; PS5-NEXT: name: "baz.cpp" +; PS5-NEXT: dir_index: 1 + +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" + +define dso_local noundef i32 @_Z3foov() local_unnamed_addr !dbg !9 { + ret i32 0, !dbg !14 +} + +define dso_local noundef i32 @_Z3barv() local_unnamed_addr !dbg !15 { + ret i32 0, !dbg !17 +} + +define dso_local noundef i32 @main() local_unnamed_addr !dbg !18 { + ret i32 0, !dbg !19 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "foo\\bar\\test.cpp", directory: "C:\\foobar") +!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 = !{!"clang"} +!9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!10 = !DIFile(filename: "foo\\bar\\bar.cpp", directory: "C:\\foobar") +!11 = !DISubroutineType(types: !12) +!12 = !{!13} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !DILocation(line: 2, column: 3, scope: !9) +!15 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !16, file: !16, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!16 = !DIFile(filename: "foo\\bar\\baz.cpp", directory: "C:\\foobar") +!17 = !DILocation(line: 2, column: 3, scope: !15) +!18 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !11, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!19 = !DILocation(line: 4, column: 3, scope: !18)