diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -479,9 +479,9 @@ /// The seed used by the randomize structure layout feature. std::string RandstructSeed; - /// Indicates whether the __FILE__ macro should use the target's - /// platform-specific file separator or whether it should use the build - /// environment's platform-specific file separator. + /// Indicates whether to use target's platform-specific file separator when + /// __FILE__ macro is used and when concatenating filename with directory or + /// to use build environment environment's platform-specific file separator. /// /// The plaform-specific path separator is the backslash(\) for Windows and /// forward slash (/) elsewhere. diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -433,6 +433,7 @@ Options.XRayOmitFunctionIndex = CodeGenOpts.XRayOmitFunctionIndex; Options.LoopAlignment = CodeGenOpts.LoopAlignment; Options.DebugStrictDwarf = CodeGenOpts.DebugStrictDwarf; + Options.UseTargetPathSeparator = LangOpts.UseTargetPathSeparator; Options.ObjectFilenameForDebug = CodeGenOpts.ObjectFilenameForDebug; Options.Hotpatch = CodeGenOpts.HotPatch; Options.JMCInstrument = CodeGenOpts.JMCInstrument; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -528,6 +528,7 @@ // Get absolute path name. SourceManager &SM = CGM.getContext().getSourceManager(); auto &CGO = CGM.getCodeGenOpts(); + const LangOptions &LO = CGM.getLangOpts(); std::string MainFileName = CGO.MainFileName; if (MainFileName.empty()) MainFileName = ""; @@ -542,9 +543,15 @@ MainFileDir = std::string(MainFile->getDir().getName()); if (!llvm::sys::path::is_absolute(MainFileName)) { llvm::SmallString<1024> MainFileDirSS(MainFileDir); - llvm::sys::path::append(MainFileDirSS, MainFileName); - MainFileName = - std::string(llvm::sys::path::remove_leading_dotslash(MainFileDirSS)); + llvm::sys::path::Style Style = + LO.UseTargetPathSeparator + ? (CGM.getTarget().getTriple().isOSWindows() + ? llvm::sys::path::Style::windows_backslash + : llvm::sys::path::Style::posix) + : llvm::sys::path::Style::native; + llvm::sys::path::append(MainFileDirSS, Style, MainFileName); + MainFileName = std::string( + llvm::sys::path::remove_leading_dotslash(MainFileDirSS, Style)); } // If the main file name provided is identical to the input file name, and // if the input file is a preprocessed source, use the module name for @@ -560,7 +567,6 @@ } llvm::dwarf::SourceLanguage LangTag; - const LangOptions &LO = CGM.getLangOpts(); if (LO.CPlusPlus) { if (LO.ObjC) LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; diff --git a/clang/test/CodeGen/debug-info-slash.c b/clang/test/CodeGen/debug-info-slash.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/debug-info-slash.c @@ -0,0 +1,6 @@ +// RUN: %clang -target x86_64-pc-win32 -ffile-reproducible -emit-llvm -S -g %s -o - | FileCheck --check-prefix=WIN %s +// RUN: %clang -target x86_64-linux-gnu -ffile-reproducible -emit-llvm -S -g %s -o - | FileCheck --check-prefix=LINUX %s +int main() { return 0; } + +// WIN: !DIFile(filename: "{{.*}}\\debug-info-slash.c" +// LINUX: !DIFile(filename: "{{.*}}/debug-info-slash.c" diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h --- a/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/llvm/include/llvm/CodeGen/CommandFlags.h @@ -145,6 +145,8 @@ bool getXCOFFReadOnlyPointers(); +bool getUseTargetPathSeparator(); + /// Create this object with static storage to register codegen-related command /// line options. struct RegisterCodeGenFlags { diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/llvm/include/llvm/Target/TargetOptions.h @@ -127,7 +127,8 @@ : UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), NoTrappingFPMath(true), NoSignedZerosFPMath(false), ApproxFuncFPMath(false), EnableAIXExtendedAltivecABI(false), - HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false), + HonorSignDependentRoundingFPMathOption(false), + UseTargetPathSeparator(false), NoZerosInBSS(false), GuaranteedTailCallOpt(false), StackSymbolOrdering(true), EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false), DisableIntegratedAS(false), RelaxELFRelocations(true), @@ -206,6 +207,11 @@ unsigned HonorSignDependentRoundingFPMathOption : 1; bool HonorSignDependentRoundingFPMath() const; + /// UseTargetPathSeparator - This Indicates whether to use target's + /// platform-specific file separator when concatenating filename with + /// directory. + unsigned UseTargetPathSeparator : 1; + /// NoZerosInBSS - By default some codegens place zero-initialized data to /// .bss section. This flag disables such behaviour (necessary, e.g. for /// crt*.o compiling). 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 @@ -791,7 +791,15 @@ // Don't emit the filename if we're writing to stdout or to /dev/null. PathRef = {}; } else { - llvm::sys::path::remove_dots(PathStore, /*remove_dot_dot=*/true); + llvm::sys::path::Style Style = + (!llvm::sys::path::is_absolute(PathRef, + llvm::sys::path::Style::posix) && + Asm->TM.Options.UseTargetPathSeparator) + ? (Asm->TM.getTargetTriple().isOSWindows() + ? llvm::sys::path::Style::windows_backslash + : llvm::sys::path::Style::posix) + : llvm::sys::path::Style::native; + llvm::sys::path::remove_dots(PathStore, /*remove_dot_dot=*/true, Style); PathRef = PathStore; } diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -104,6 +104,7 @@ CGOPT(unsigned, AlignLoops) CGOPT(bool, JMCInstrument) CGOPT(bool, XCOFFReadOnlyPointers) +CGOPT(bool, UseTargetPathSeparator) codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { #define CGBINDOPT(NAME) \ @@ -486,6 +487,14 @@ cl::init(false)); CGBINDOPT(XCOFFReadOnlyPointers); + static cl::opt UseTargetPathSeparator( + "use-target-path-separator", + cl::desc( + "Use target's platform-specific file separator when concatenating " + "filename with directory."), + cl::init(false)); + CGBINDOPT(UseTargetPathSeparator); + #undef CGBINDOPT mc::RegisterMCTargetOptionsFlags(); @@ -563,6 +572,7 @@ Options.LoopAlignment = getAlignLoops(); Options.JMCInstrument = getJMCInstrument(); Options.XCOFFReadOnlyPointers = getXCOFFReadOnlyPointers(); + Options.UseTargetPathSeparator = getUseTargetPathSeparator(); Options.MCOptions = mc::InitMCTargetOptionsFromFlags(); diff --git a/llvm/test/DebugInfo/COFF/use-target-path-separator.ll b/llvm/test/DebugInfo/COFF/use-target-path-separator.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/use-target-path-separator.ll @@ -0,0 +1,35 @@ +; RUN: rm -rf %t-dir +; RUN: mkdir -p %t-dir/subdir +; RUN: cd %t-dir +; RUN: llc -filetype=obj -mtriple i686-pc-windows-msvc -use-target-path-separator %s -o subdir/win.obj +; RUN: llvm-readobj --codeview subdir/win.obj | FileCheck --check-prefix=WIN %s + +; WIN: ObjectName: subdir\win.obj + +; ModuleID = 'D:\src\scopes\foo.cpp' +source_filename = "D:\5Csrc\5Cscopes\5Cfoo.cpp" +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-pc-windows-msvc19.0.23918" + +define i32 @"?foo@@YAHXZ"() !dbg !10 { +entry: + ret i32 42, !dbg !14 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +; One .debug$S section should contain an S_COMPILE3 record that identifies the +; source language and the version of the compiler based on the DICompileUnit. +!1 = !DIFile(filename: "D:\5Csrc\5Cscopes\5Cfoo.cpp", directory: "D:\5Csrc\5Cscopes\5Cclang") +!2 = !{} +!7 = !{i32 2, !"CodeView", i32 1} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{!"clang version 4.0.0 "} +!10 = distinct !DISubprogram(name: "foo", linkageName: "\01?foo@@YAHXZ", scope: !1, file: !1, line: 1, type: !11, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) +!11 = !DISubroutineType(types: !12) +!12 = !{!13} +!13 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!14 = !DILocation(line: 2, scope: !10)