diff --git a/clang/include/clang/CodeGen/BackendUtil.h b/clang/include/clang/CodeGen/BackendUtil.h --- a/clang/include/clang/CodeGen/BackendUtil.h +++ b/clang/include/clang/CodeGen/BackendUtil.h @@ -41,7 +41,8 @@ const TargetOptions &TOpts, const LangOptions &LOpts, const llvm::DataLayout &TDesc, llvm::Module *M, BackendAction Action, - std::unique_ptr OS); + std::unique_ptr OS, + const std::string &OutputFile); void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, llvm::MemoryBufferRef Buf); diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -700,7 +700,7 @@ /// atomically replace the target output on success). /// /// \return - Null on error. - std::unique_ptr + std::tuple, std::string> createDefaultOutputFile(bool Binary = true, StringRef BaseInput = "", StringRef Extension = ""); @@ -708,7 +708,7 @@ /// optionally deriving the output path name. /// /// \return - Null on error. - std::unique_ptr + std::tuple, std::string> createOutputFile(StringRef OutputPath, bool Binary, bool RemoveFileOnSignal, StringRef BaseInput, StringRef Extension, bool UseTemporary, bool CreateMissingDirectories = false); diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -97,15 +97,14 @@ /// Creates file to write the PCH into and returns a stream to write it /// into. On error, returns null. - static std::unique_ptr - CreateOutputFile(CompilerInstance &CI, StringRef InFile, - std::string &OutputFile); + static std::tuple, std::string> + CreateOutputFile(CompilerInstance &CI, StringRef InFile); bool BeginSourceFileAction(CompilerInstance &CI) override; }; class GenerateModuleAction : public ASTFrontendAction { - virtual std::unique_ptr + virtual std::tuple, std::string> CreateOutputFile(CompilerInstance &CI, StringRef InFile) = 0; protected: @@ -132,7 +131,7 @@ private: bool BeginSourceFileAction(CompilerInstance &CI) override; - std::unique_ptr + std::tuple, std::string> CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; }; @@ -140,7 +139,7 @@ private: bool BeginSourceFileAction(CompilerInstance &CI) override; - std::unique_ptr + std::tuple, std::string> CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; }; @@ -153,7 +152,7 @@ bool PrepareToExecuteAction(CompilerInstance &CI) override; bool BeginSourceFileAction(CompilerInstance &CI) override; - std::unique_ptr + std::tuple, std::string> CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; }; 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 @@ -121,7 +121,7 @@ /// In this case, we allow this method to fail and not report an error. /// When MustCreateTM is used, we print an error if we are unable to load /// the requested target. - void CreateTargetMachine(bool MustCreateTM); + void CreateTargetMachine(bool MustCreateTM, const std::string &OutputFile); /// Add passes necessary to emit assembly or LLVM IR. /// @@ -157,11 +157,12 @@ std::unique_ptr TM; - void EmitAssembly(BackendAction Action, - std::unique_ptr OS); + void EmitAssembly(BackendAction Action, std::unique_ptr OS, + const std::string &OSFile); void EmitAssemblyWithNewPassManager(BackendAction Action, - std::unique_ptr OS); + std::unique_ptr OS, + const std::string &OutputFile); }; // We need this wrapper to access LangOpts and CGOpts from extension functions @@ -433,7 +434,8 @@ const CodeGenOptions &CodeGenOpts, const clang::TargetOptions &TargetOpts, const LangOptions &LangOpts, - const HeaderSearchOptions &HSOpts) { + const HeaderSearchOptions &HSOpts, + const std::string &OutputPathName) { Options.ThreadModel = llvm::StringSwitch(CodeGenOpts.ThreadModel) .Case("posix", llvm::ThreadModel::POSIX) @@ -499,6 +501,7 @@ Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection; Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo; + Options.MCOptions.OutputPathName = OutputPathName; Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile; Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels; @@ -783,7 +786,8 @@ BackendArgs.data()); } -void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { +void EmitAssemblyHelper::CreateTargetMachine( + bool MustCreateTM, const std::string &OutputPathName) { // Create the TargetMachine for generating code. std::string Error; std::string Triple = TheModule->getTargetTriple(); @@ -801,7 +805,8 @@ CodeGenOpt::Level OptLevel = getCGOptLevel(CodeGenOpts); llvm::TargetOptions Options; - initTargetOptions(Options, CodeGenOpts, TargetOpts, LangOpts, HSOpts); + initTargetOptions(Options, CodeGenOpts, TargetOpts, LangOpts, HSOpts, + OutputPathName); TM.reset(TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr, Options, RM, CM, OptLevel)); } @@ -836,7 +841,8 @@ } void EmitAssemblyHelper::EmitAssembly(BackendAction Action, - std::unique_ptr OS) { + std::unique_ptr OS, + const std::string &OutputFile) { TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr); setCommandLineOpts(CodeGenOpts); @@ -844,7 +850,7 @@ bool UsesCodeGen = (Action != Backend_EmitNothing && Action != Backend_EmitBC && Action != Backend_EmitLL); - CreateTargetMachine(UsesCodeGen); + CreateTargetMachine(UsesCodeGen, OutputFile); if (UsesCodeGen && !TM) return; @@ -1048,14 +1054,15 @@ /// This API is planned to have its functionality finished and then to replace /// `EmitAssembly` at some point in the future when the default switches. void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( - BackendAction Action, std::unique_ptr OS) { + BackendAction Action, std::unique_ptr OS, + const std::string &OutputFile) { TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr); setCommandLineOpts(CodeGenOpts); bool RequiresCodeGen = (Action != Backend_EmitNothing && Action != Backend_EmitBC && Action != Backend_EmitLL); - CreateTargetMachine(RequiresCodeGen); + CreateTargetMachine(RequiresCodeGen, OutputFile); if (RequiresCodeGen && !TM) return; @@ -1462,15 +1469,14 @@ return nullptr; } -static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, - const HeaderSearchOptions &HeaderOpts, - const CodeGenOptions &CGOpts, - const clang::TargetOptions &TOpts, - const LangOptions &LOpts, - std::unique_ptr OS, - std::string SampleProfile, - std::string ProfileRemapping, - BackendAction Action) { +static void +runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, + const HeaderSearchOptions &HeaderOpts, + const CodeGenOptions &CGOpts, + const clang::TargetOptions &TOpts, const LangOptions &LOpts, + std::unique_ptr OS, + const std::string &OutputFile, std::string SampleProfile, + std::string ProfileRemapping, BackendAction Action) { StringMap> ModuleToDefinedGVSummaries; CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); @@ -1522,7 +1528,7 @@ OwnedImports.push_back(std::move(*MBOrErr)); } auto AddStream = [&](size_t Task) { - return std::make_unique(std::move(OS)); + return std::make_unique(std::move(OS), OutputFile); }; lto::Config Conf; if (CGOpts.SaveTempsFilePrefix != "") { @@ -1540,7 +1546,7 @@ Conf.RelocModel = CGOpts.RelocationModel; Conf.CGOptLevel = getCGOptLevel(CGOpts); Conf.OptLevel = CGOpts.OptimizationLevel; - initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); + initTargetOptions(Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts, OutputFile); Conf.SampleProfile = std::move(SampleProfile); Conf.PTO.LoopUnrolling = CGOpts.UnrollLoops; // For historical reasons, loop interleaving is set to mirror setting for loop @@ -1599,14 +1605,12 @@ } } -void clang::EmitBackendOutput(DiagnosticsEngine &Diags, - const HeaderSearchOptions &HeaderOpts, - const CodeGenOptions &CGOpts, - const clang::TargetOptions &TOpts, - const LangOptions &LOpts, - const llvm::DataLayout &TDesc, Module *M, - BackendAction Action, - std::unique_ptr OS) { +void clang::EmitBackendOutput( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HeaderOpts, + const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, + const LangOptions &LOpts, const llvm::DataLayout &TDesc, Module *M, + BackendAction Action, std::unique_ptr OS, + const std::string &OutputFile) { llvm::TimeTraceScope TimeScope("Backend"); @@ -1631,8 +1635,9 @@ if (CombinedIndex) { if (!CombinedIndex->skipModuleByDistributedBackend()) { runThinLTOBackend(CombinedIndex.get(), M, HeaderOpts, CGOpts, TOpts, - LOpts, std::move(OS), CGOpts.SampleProfileFile, - CGOpts.ProfileRemappingFile, Action); + LOpts, std::move(OS), OutputFile, + CGOpts.SampleProfileFile, CGOpts.ProfileRemappingFile, + Action); return; } // Distributed indexing detected that nothing from the module is needed @@ -1650,9 +1655,9 @@ EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M); if (CGOpts.ExperimentalNewPassManager) - AsmHelper.EmitAssemblyWithNewPassManager(Action, std::move(OS)); + AsmHelper.EmitAssemblyWithNewPassManager(Action, std::move(OS), OutputFile); else - AsmHelper.EmitAssembly(Action, std::move(OS)); + AsmHelper.EmitAssembly(Action, std::move(OS), OutputFile); // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's // DataLayout. diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -111,6 +111,7 @@ const TargetOptions &TargetOpts; const LangOptions &LangOpts; std::unique_ptr AsmOutStream; + std::string AsmOutputPathName; ASTContext *Context; Timer LLVMIRGeneration; @@ -138,11 +139,13 @@ const LangOptions &LangOpts, bool TimePasses, const std::string &InFile, SmallVector LinkModules, - std::unique_ptr OS, LLVMContext &C, + std::unique_ptr OS, + const std::string &OutputPathName, LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr) : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), - AsmOutStream(std::move(OS)), Context(nullptr), + AsmOutStream(std::move(OS)), AsmOutputPathName(OutputPathName), + Context(nullptr), LLVMIRGeneration("irgen", "LLVM IR Generation Time"), LLVMIRGenerationRefCount(0), Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, @@ -334,7 +337,8 @@ EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts, C.getTargetInfo().getDataLayout(), - getModule(), Action, std::move(AsmOutStream)); + getModule(), Action, std::move(AsmOutStream), + AsmOutputPathName); Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); @@ -932,7 +936,7 @@ return VMContext; } -static std::unique_ptr +static std::tuple, std::string> GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) { switch (Action) { case Backend_EmitAssembly: @@ -942,9 +946,9 @@ case Backend_EmitBC: return CI.createDefaultOutputFile(true, InFile, "bc"); case Backend_EmitNothing: - return nullptr; + return {nullptr, ""}; case Backend_EmitMCNull: - return CI.createNullOutputFile(); + return {CI.createNullOutputFile(), ""}; case Backend_EmitObj: return CI.createDefaultOutputFile(true, InFile, "o"); } @@ -955,9 +959,10 @@ std::unique_ptr CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { BackendAction BA = static_cast(Act); + std::string OutputPathName; std::unique_ptr OS = CI.takeOutputStream(); if (!OS) - OS = GetOutputStream(CI, InFile, BA); + std::tie(OS, OutputPathName) = GetOutputStream(CI, InFile, BA); if (BA != Backend_EmitNothing && !OS) return nullptr; @@ -1000,7 +1005,8 @@ BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, std::string(InFile), - std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo)); + std::move(LinkModules), std::move(OS), OutputPathName, *VMContext, + CoverageInfo)); BEConsumer = Result.get(); // Enable generating macro debug info only when debug info is not disabled and @@ -1113,8 +1119,9 @@ CompilerInstance &CI = getCompilerInstance(); auto &CodeGenOpts = CI.getCodeGenOpts(); auto &Diagnostics = CI.getDiagnostics(); - std::unique_ptr OS = - GetOutputStream(CI, getCurrentFile(), BA); + std::string OutputPathName; + std::unique_ptr OS; + std::tie(OS, OutputPathName) = GetOutputStream(CI, getCurrentFile(), BA); if (BA != Backend_EmitNothing && !OS) return; @@ -1173,7 +1180,7 @@ EmitBackendOutput(Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts, TargetOpts, CI.getLangOpts(), CI.getTarget().getDataLayout(), TheModule.get(), BA, - std::move(OS)); + std::move(OS), OutputPathName); if (OptRecordFile) OptRecordFile->keep(); diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp --- a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -297,7 +297,7 @@ Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts, Ctx.getTargetInfo().getDataLayout(), M.get(), BackendAction::Backend_EmitLL, - std::make_unique(Buffer)); + std::make_unique(Buffer), OutputFileName); llvm::dbgs() << Buffer; }); @@ -305,7 +305,7 @@ clang::EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts, Ctx.getTargetInfo().getDataLayout(), M.get(), BackendAction::Backend_EmitObj, - std::move(OS)); + std::move(OS), OutputFileName); // Free the memory for the temporary buffer. llvm::SmallVector Empty; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -646,15 +646,10 @@ if (EraseFiles) { llvm::sys::fs::remove(OF.TempFilename); } else { - SmallString<128> NewOutFile(OF.Filename); - - // If '-working-directory' was passed, the output filename should be - // relative to that. - FileMgr->FixupRelativePath(NewOutFile); if (std::error_code ec = - llvm::sys::fs::rename(OF.TempFilename, NewOutFile)) { + llvm::sys::fs::rename(OF.TempFilename, OF.Filename)) { getDiagnostics().Report(diag::err_unable_to_rename_temp) - << OF.TempFilename << OF.Filename << ec.message(); + << OF.TempFilename << OF.Filename << ec.message(); llvm::sys::fs::remove(OF.TempFilename); } @@ -671,7 +666,7 @@ NonSeekStream.reset(); } -std::unique_ptr +std::tuple, std::string> CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile, StringRef Extension) { return createOutputFile(getFrontendOpts().OutputFile, Binary, @@ -683,7 +678,7 @@ return std::make_unique(); } -std::unique_ptr +std::tuple, std::string> CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary, bool RemoveFileOnSignal, StringRef InFile, StringRef Extension, bool UseTemporary, @@ -696,7 +691,15 @@ if (!OS) { getDiagnostics().Report(diag::err_fe_unable_to_open_output) << OutputPath << EC.message(); - return nullptr; + return {nullptr, ""}; + } + + // If '-working-directory' was passed, the output filename should be + // relative to that. + if (OutputPathName != "-") { + SmallString<128> NewOutFile(OutputPathName); + FileMgr->makeAbsolutePath(NewOutFile); + OutputPathName = NewOutFile.str().str(); } // Add the output file -- but don't try to remove "-", since this means we are @@ -704,7 +707,8 @@ addOutputFile( OutputFile((OutputPathName != "-") ? OutputPathName : "", TempPathName)); - return OS; + return std::tuple, std::string>( + std::move(OS), OutputPathName); } std::unique_ptr CompilerInstance::createOutputFile( diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -68,8 +68,10 @@ std::unique_ptr ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - if (std::unique_ptr OS = - CI.createDefaultOutputFile(false, InFile)) + std::string OutputPathName; + std::unique_ptr OS; + std::tie(OS, OutputPathName) = CI.createDefaultOutputFile(false, InFile); + if (OS) return CreateASTPrinter(std::move(OS), CI.getFrontendOpts().ASTDumpFilter); return nullptr; } @@ -99,8 +101,8 @@ return nullptr; std::string OutputFile; - std::unique_ptr OS = - CreateOutputFile(CI, InFile, /*ref*/ OutputFile); + std::unique_ptr OS; + std::tie(OS, OutputFile) = CreateOutputFile(CI, InFile); if (!OS) return nullptr; @@ -132,21 +134,15 @@ return true; } -std::unique_ptr -GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile, - std::string &OutputFile) { +std::tuple, std::string> +GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. - std::unique_ptr OS = - CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, - /*RemoveFileOnSignal=*/false, InFile, - /*Extension=*/"", CI.getFrontendOpts().UseTemporary); - if (!OS) - return nullptr; - - OutputFile = CI.getFrontendOpts().OutputFile; - return OS; + return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, + /*RemoveFileOnSignal=*/false, InFile, + /*Extension=*/"", + CI.getFrontendOpts().UseTemporary); } bool GeneratePCHAction::shouldEraseOutputFiles() { @@ -163,11 +159,12 @@ std::unique_ptr GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - std::unique_ptr OS = CreateOutputFile(CI, InFile); + std::unique_ptr OS; + std::string OutputFile; + std::tie(OS, OutputFile) = CreateOutputFile(CI, InFile); if (!OS) return nullptr; - std::string OutputFile = CI.getFrontendOpts().OutputFile; std::string Sysroot; auto Buffer = std::make_shared(); @@ -196,7 +193,7 @@ return GenerateModuleAction::BeginSourceFileAction(CI); } -std::unique_ptr +std::tuple, std::string> GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { // If no output file was provided, figure out where this module would go @@ -233,7 +230,7 @@ return GenerateModuleAction::BeginSourceFileAction(CI); } -std::unique_ptr +std::tuple, std::string> GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm"); @@ -303,7 +300,7 @@ return GenerateModuleAction::BeginSourceFileAction(CI); } -std::unique_ptr +std::tuple, std::string> GenerateHeaderModuleAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm"); @@ -827,7 +824,9 @@ } } - std::unique_ptr OS = + std::unique_ptr OS; + std::string OutputPathName; + std::tie(OS, OutputPathName) = CI.createDefaultOutputFile(BinaryMode, getCurrentFileOrBufferName()); if (!OS) return; @@ -882,7 +881,9 @@ void DumpCompilerOptionsAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); - std::unique_ptr OSP = + std::unique_ptr OSP; + std::string OutputPathName; + std::tie(OSP, OutputPathName) = CI.createDefaultOutputFile(false, getCurrentFile()); if (!OSP) return; diff --git a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp --- a/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp +++ b/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp @@ -266,7 +266,10 @@ v.TraverseDecl(context.getTranslationUnitDecl()); MangledSymbols Symbols; - auto OS = Instance.createDefaultOutputFile(/*Binary=*/false, InFile, "ifs"); + std::unique_ptr OS; + std::string OutputPathName; + std::tie(OS, OutputPathName) = + Instance.createDefaultOutputFile(/*Binary=*/false, InFile, "ifs"); if (!OS) return; diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -206,7 +206,7 @@ OS = std::make_unique(*InMemStorage); } else { std::string OutputFile; - OS = GeneratePCHAction::CreateOutputFile(CI, InFile, OutputFile); + std::tie(OS, OutputFile) = GeneratePCHAction::CreateOutputFile(CI, InFile); } if (!OS) return nullptr; diff --git a/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/clang/lib/Frontend/Rewrite/FrontendActions.cpp --- a/clang/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/clang/lib/Frontend/Rewrite/FrontendActions.cpp @@ -39,8 +39,10 @@ std::unique_ptr HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - if (std::unique_ptr OS = - CI.createDefaultOutputFile(false, InFile)) + std::string OutputPathName; + std::unique_ptr OS; + std::tie(OS, OutputPathName) = CI.createDefaultOutputFile(false, InFile); + if (OS) return CreateHTMLPrinter(std::move(OS), CI.getPreprocessor()); return nullptr; } @@ -162,8 +164,11 @@ std::unique_ptr RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - if (std::unique_ptr OS = - CI.createDefaultOutputFile(false, InFile, "cpp")) { + std::string OutputPathName; + std::unique_ptr OS; + std::tie(OS, OutputPathName) = + CI.createDefaultOutputFile(false, InFile, "cpp"); + if (OS) { if (CI.getLangOpts().ObjCRuntime.isNonFragile()) return CreateModernObjCRewriter( std::string(InFile), std::move(OS), CI.getDiagnostics(), @@ -184,16 +189,21 @@ void RewriteMacrosAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); - std::unique_ptr OS = + std::string OutputPathName; + std::unique_ptr OS; + std::tie(OS, OutputPathName) = CI.createDefaultOutputFile(true, getCurrentFileOrBufferName()); - if (!OS) return; + if (!OS) + return; RewriteMacrosInInput(CI.getPreprocessor(), OS.get()); } void RewriteTestAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); - std::unique_ptr OS = + std::string OutputPathName; + std::unique_ptr OS; + std::tie(OS, OutputPathName) = CI.createDefaultOutputFile(false, getCurrentFileOrBufferName()); if (!OS) return; @@ -269,7 +279,8 @@ bool RewriteIncludesAction::BeginSourceFileAction(CompilerInstance &CI) { if (!OutputStream) { - OutputStream = + std::string OutputPathName; + std::tie(OutputStream, OutputPathName) = CI.createDefaultOutputFile(true, getCurrentFileOrBufferName()); if (!OutputStream) return false; diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -248,16 +248,18 @@ if (llvm::timeTraceProfilerEnabled()) { SmallString<128> Path(Clang->getFrontendOpts().OutputFile); llvm::sys::path::replace_extension(Path, "json"); - if (auto profilerOutput = - Clang->createOutputFile(Path.str(), - /*Binary=*/false, - /*RemoveFileOnSignal=*/false, "", - /*Extension=*/"json", - /*useTemporary=*/false)) { - - llvm::timeTraceProfilerWrite(*profilerOutput); + std::unique_ptr ProfilerOS; + std::string ProfilerOutputFilePath; + std::tie(ProfilerOS, ProfilerOutputFilePath) = + Clang->createOutputFile(Path.str(), + /*Binary=*/false, + /*RemoveFileOnSignal=*/false, "", + /*Extension=*/"json", + /*useTemporary=*/false); + if (ProfilerOS) { + llvm::timeTraceProfilerWrite(*ProfilerOS); // FIXME(ibiryukov): make profilerOutput flush in destructor instead. - profilerOutput->flush(); + ProfilerOS->flush(); llvm::timeTraceProfilerCleanup(); Clang->clearOutputFiles(false); } diff --git a/lld/COFF/LTO.h b/lld/COFF/LTO.h --- a/lld/COFF/LTO.h +++ b/lld/COFF/LTO.h @@ -50,6 +50,7 @@ private: std::unique_ptr ltoObj; std::vector> buf; + std::vector objFilePath; std::vector> files; std::unique_ptr indexFile; llvm::DenseSet thinIndices; diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp --- a/lld/COFF/LTO.cpp +++ b/lld/COFF/LTO.cpp @@ -148,6 +148,7 @@ std::vector BitcodeCompiler::compile() { unsigned maxTasks = ltoObj->getMaxTasks(); buf.resize(maxTasks); + objFilePath.resize(maxTasks); files.resize(maxTasks); // The /lldltocache option specifies the path to a directory in which to cache @@ -160,10 +161,31 @@ files[task] = std::move(mb); })); + // Compute the target file names in advance, because we might need to write + // them into the S_OBJNAME CodeView record. + if (config->thinLTOIndexOnly) { + if (!config->ltoObjPath.empty()) + objFilePath[0] = config->ltoObjPath.str(); + } else { + for (unsigned i = 0; i != maxTasks; ++i) { + // Assign unique names to LTO objects. This ensures they have unique names + // in the PDB if one is produced. The names should look like: + // - foo.exe.lto.obj + // - foo.exe.lto.1.obj + // - ... + objFilePath[i] = + saver + .save(Twine(config->outputFile) + ".lto" + + (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ".obj") + .str(); + } + } + checkError(ltoObj->run( [&](size_t task) { return std::make_unique( - std::make_unique(buf[task])); + std::make_unique(buf[task]), + objFilePath[task]); }, cache)); @@ -180,7 +202,7 @@ // distributed environment. if (config->thinLTOIndexOnly) { if (!config->ltoObjPath.empty()) - saveBuffer(buf[0], config->ltoObjPath); + saveBuffer(buf[0], objFilePath[0]); if (indexFile) indexFile->close(); return {}; @@ -191,15 +213,6 @@ std::vector ret; for (unsigned i = 0; i != maxTasks; ++i) { - // Assign unique names to LTO objects. This ensures they have unique names - // in the PDB if one is produced. The names should look like: - // - foo.exe.lto.obj - // - foo.exe.lto.1.obj - // - ... - StringRef ltoObjName = - saver.save(Twine(config->outputFile) + ".lto" + - (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ".obj"); - // Get the native object contents either from the cache or from memory. Do // not use the cached MemoryBuffer directly, or the PDB will not be // deterministic. @@ -212,8 +225,8 @@ continue; if (config->saveTemps) - saveBuffer(buf[i], ltoObjName); - ret.push_back(make(MemoryBufferRef(objBuf, ltoObjName))); + saveBuffer(buf[i], objFilePath[i]); + ret.push_back(make(MemoryBufferRef(objBuf, objFilePath[i]))); } return ret; diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -291,7 +291,8 @@ checkError(ltoObj->run( [&](size_t task) { return std::make_unique( - std::make_unique(buf[task])); + std::make_unique(buf[task]), + /*OSPath=*/""); }, cache)); diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp --- a/lld/wasm/LTO.cpp +++ b/lld/wasm/LTO.cpp @@ -136,7 +136,7 @@ checkError(ltoObj->run( [&](size_t task) { return std::make_unique( - std::make_unique(buf[task])); + std::make_unique(buf[task]), /*OSPath=*/""); }, cache)); diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -187,8 +187,10 @@ /// destructor. class NativeObjectStream { public: - NativeObjectStream(std::unique_ptr OS) : OS(std::move(OS)) {} + NativeObjectStream(std::unique_ptr OS, std::string OSPath) + : OS(std::move(OS)), ObjectPathName(OSPath) {} std::unique_ptr OS; + std::string ObjectPathName; virtual ~NativeObjectStream() = default; }; diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h --- a/llvm/include/llvm/MC/MCTargetOptions.h +++ b/llvm/include/llvm/MC/MCTargetOptions.h @@ -58,6 +58,7 @@ std::string ABIName; std::string AssemblyLanguage; std::string SplitDwarfFile; + std::string OutputPathName; /// Additional paths to search for `.include` directives when using the /// integrated assembler. diff --git a/llvm/include/llvm/Support/ToolOutputFile.h b/llvm/include/llvm/Support/ToolOutputFile.h --- a/llvm/include/llvm/Support/ToolOutputFile.h +++ b/llvm/include/llvm/Support/ToolOutputFile.h @@ -28,9 +28,10 @@ /// raw_fd_ostream is destructed. It installs cleanups in its constructor and /// uninstalls them in its destructor. class CleanupInstaller { + public: /// The name of the file. std::string Filename; - public: + /// The flag which indicates whether we should not delete the file. bool Keep; @@ -55,6 +56,8 @@ /// Indicate that the tool's job wrt this output file has been successful and /// the file should not be deleted. void keep() { Installer.Keep = true; } + + const std::string &outputFilename() { return Installer.Filename; } }; } // end llvm namespace diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -296,6 +296,8 @@ void emitTypeGlobalHashes(); + void emitObjName(); + void emitCompilerInformation(); void emitBuildInfo(); 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 @@ -590,6 +590,7 @@ switchToDebugSectionForSymbol(nullptr); MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols); + emitObjName(); emitCompilerInformation(); endCVSubsection(CompilerInfo); @@ -757,6 +758,44 @@ } } +static void unescapeSlashes(SmallVectorImpl &Str) { + auto Read = Str.begin(); + auto Write = Read; + while (Read != Str.end()) { + bool WasSlash = (*Read == '\\'); + *Write++ = *Read++; + if (WasSlash && Read != Str.end() && *Read == '\\') + ++Read; + } + Str.resize(Write - Str.begin()); +} + +void CodeViewDebug::emitObjName() { + MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME); + + StringRef PathRef(Asm->TM.Options.MCOptions.OutputPathName); + assert(PathRef == "-" || !PathRef.empty()); + llvm::SmallString<256> Path(PathRef); + + if (Path == "-") { + // Don't emit the filename if we're writing to stdout. + Path.clear(); + } else { + llvm::sys::fs::make_absolute(Path); + llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true); + unescapeSlashes(Path); + assert(llvm::sys::path::is_absolute(Path)); + } + + OS.AddComment("Signature"); + OS.emitInt32(0); + + OS.AddComment("Object name"); + emitNullTerminatedSymbolName(OS, Path); + + endSymbolRecord(CompilerEnd); +} + namespace { struct Version { int Part[4]; diff --git a/llvm/lib/LTO/Caching.cpp b/llvm/lib/LTO/Caching.cpp --- a/llvm/lib/LTO/Caching.cpp +++ b/llvm/lib/LTO/Caching.cpp @@ -72,14 +72,13 @@ struct CacheStream : NativeObjectStream { AddBufferFn AddBuffer; sys::fs::TempFile TempFile; - std::string EntryPath; unsigned Task; CacheStream(std::unique_ptr OS, AddBufferFn AddBuffer, sys::fs::TempFile TempFile, std::string EntryPath, unsigned Task) - : NativeObjectStream(std::move(OS)), AddBuffer(std::move(AddBuffer)), - TempFile(std::move(TempFile)), EntryPath(std::move(EntryPath)), + : NativeObjectStream(std::move(OS), std::move(EntryPath)), + AddBuffer(std::move(AddBuffer)), TempFile(std::move(TempFile)), Task(Task) {} ~CacheStream() { @@ -105,14 +104,14 @@ // AddBuffer a copy of the bytes we wrote in that case. We do this // instead of just using the existing file, because the pruner might // delete the file before we get a chance to use it. - Error E = TempFile.keep(EntryPath); + Error E = TempFile.keep(ObjectPathName); E = handleErrors(std::move(E), [&](const ECError &E) -> Error { std::error_code EC = E.convertToErrorCode(); if (EC != errc::permission_denied) return errorCodeToError(EC); auto MBCopy = MemoryBuffer::getMemBufferCopy((*MBOrErr)->getBuffer(), - EntryPath); + ObjectPathName); MBOrErr = std::move(MBCopy); // FIXME: should we consume the discard error? @@ -123,7 +122,7 @@ if (E) report_fatal_error(Twine("Failed to rename temporary file ") + - TempFile.TmpName + " to " + EntryPath + ": " + + TempFile.TmpName + " to " + ObjectPathName + ": " + toString(std::move(E)) + "\n"); AddBuffer(Task, std::move(*MBOrErr)); diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -391,6 +391,8 @@ } auto Stream = AddStream(Task); + TM->Options.MCOptions.OutputPathName = Stream->ObjectPathName; + legacy::PassManager CodeGenPasses; if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS, DwoOut ? &DwoOut->os() : nullptr, diff --git a/llvm/test/DebugInfo/COFF/globals.ll b/llvm/test/DebugInfo/COFF/globals.ll --- a/llvm/test/DebugInfo/COFF/globals.ll +++ b/llvm/test/DebugInfo/COFF/globals.ll @@ -1,7 +1,9 @@ ; RUN: llc < %s | FileCheck %s --check-prefix=ASM ; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s --check-prefix=OBJ ; RUN: llc < %s | llvm-mc -filetype=obj --triple=x86_64-windows | llvm-readobj - --codeview | FileCheck %s --check-prefix=OBJ -; RUN: llc < %s -filetype=obj | obj2yaml | FileCheck %s --check-prefix=YAML +; RUN: llc < %s -filetype=obj | obj2yaml | FileCheck %s --check-prefixes=YAML,YAML-STDOUT +; RUN: llc < %s -filetype=obj -o %t +; RUN: obj2yaml < %t | FileCheck %s --check-prefixes=YAML,YAML-FILE ; C++ source to regenerate: ; $ cat a.cpp @@ -246,6 +248,11 @@ ; YAML: Subsections: ; YAML: - !Symbols ; YAML: Records: +; YAML: - Kind: S_OBJNAME +; YAML: ObjNameSym: +; YAML: Signature: 0 +; YAML-STDOUT ObjectName: '' +; YAML-FILE ObjectName: '{{.*}}' ; YAML: - Kind: S_COMPILE3 ; YAML: Compile3Sym: diff --git a/llvm/test/DebugInfo/COFF/multifunction.ll b/llvm/test/DebugInfo/COFF/multifunction.ll --- a/llvm/test/DebugInfo/COFF/multifunction.ll +++ b/llvm/test/DebugInfo/COFF/multifunction.ll @@ -498,18 +498,18 @@ ; OBJ64: Characteristics [ (0x42300040) ; OBJ64: ] ; OBJ64: Relocations [ -; OBJ64-NEXT: 0x64 IMAGE_REL_AMD64_SECREL x -; OBJ64-NEXT: 0x68 IMAGE_REL_AMD64_SECTION x -; OBJ64-NEXT: 0x9C IMAGE_REL_AMD64_SECREL x -; OBJ64-NEXT: 0xA0 IMAGE_REL_AMD64_SECTION x -; OBJ64-NEXT: 0x100 IMAGE_REL_AMD64_SECREL y -; OBJ64-NEXT: 0x104 IMAGE_REL_AMD64_SECTION y -; OBJ64-NEXT: 0x138 IMAGE_REL_AMD64_SECREL y -; OBJ64-NEXT: 0x13C IMAGE_REL_AMD64_SECTION y -; OBJ64-NEXT: 0x19C IMAGE_REL_AMD64_SECREL f -; OBJ64-NEXT: 0x1A0 IMAGE_REL_AMD64_SECTION f -; OBJ64-NEXT: 0x1D4 IMAGE_REL_AMD64_SECREL f -; OBJ64-NEXT: 0x1D8 IMAGE_REL_AMD64_SECTION f +; OBJ64-NEXT: 0x70 IMAGE_REL_AMD64_SECREL x +; OBJ64-NEXT: 0x74 IMAGE_REL_AMD64_SECTION x +; OBJ64-NEXT: 0xA8 IMAGE_REL_AMD64_SECREL x +; OBJ64-NEXT: 0xAC IMAGE_REL_AMD64_SECTION x +; OBJ64-NEXT: 0x10C IMAGE_REL_AMD64_SECREL y +; OBJ64-NEXT: 0x110 IMAGE_REL_AMD64_SECTION y +; OBJ64-NEXT: 0x144 IMAGE_REL_AMD64_SECREL y +; OBJ64-NEXT: 0x148 IMAGE_REL_AMD64_SECTION y +; OBJ64-NEXT: 0x1A8 IMAGE_REL_AMD64_SECREL f +; OBJ64-NEXT: 0x1AC IMAGE_REL_AMD64_SECTION f +; OBJ64-NEXT: 0x1E0 IMAGE_REL_AMD64_SECREL f +; OBJ64-NEXT: 0x1E4 IMAGE_REL_AMD64_SECTION f ; OBJ64-NEXT: ] ; OBJ64: Subsection [ ; OBJ64-NEXT: SubSectionType: Symbols (0xF1) diff --git a/llvm/test/DebugInfo/COFF/pr28747.ll b/llvm/test/DebugInfo/COFF/pr28747.ll --- a/llvm/test/DebugInfo/COFF/pr28747.ll +++ b/llvm/test/DebugInfo/COFF/pr28747.ll @@ -5,8 +5,10 @@ ; CHECK-NEXT: .long 241 ; CHECK-NEXT: .long [[SUBSEC_END:.*]]-[[SUBSEC_START:.*]] # Subsection size ; CHECK-NEXT: [[SUBSEC_START]]: -; CHECK-NEXT: .short [[C1_END:.*]]-[[C1_START:.*]] # Record length -; CHECK: [[C1_END]]: +; CHECK-NEXT: .short [[OBJNAME_END:.*]]-[[OBJNAME_START:.*]] # Record length +; CHECK: [[OBJNAME_END]]: +; CHECK-NEXT: .short [[COMPILE3_END:.*]]-[[COMPILE3_START:.*]] # Record length +; CHECK: [[COMPILE3_END]]: ; CHECK-NEXT: [[SUBSEC_END]]: ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: .cv_filechecksums diff --git a/llvm/test/DebugInfo/COFF/simple.ll b/llvm/test/DebugInfo/COFF/simple.ll --- a/llvm/test/DebugInfo/COFF/simple.ll +++ b/llvm/test/DebugInfo/COFF/simple.ll @@ -36,8 +36,10 @@ ; X86-NEXT: .long [[COMPILE_END:.*]]-[[COMPILE_START:.*]] # ; Compiler information record ; X86-NEXT: [[COMPILE_START]]: -; X86-NEXT: .short [[C1_END:.*]]-[[C1_START:.*]] # -; X86: [[C1_END]]: +; X86-NEXT: .short [[OBJNAME_END:.*]]-[[OBJNAME_START:.*]] # +; X86: [[OBJNAME_END]]: +; X86-NEXT: .short [[COMPILE3_END:.*]]-[[COMPILE3_START:.*]] # +; X86: [[COMPILE3_END]]: ; X86-NEXT: [[COMPILE_END]]: ; X86-NEXT: .p2align 2 ; X86-NEXT: .cv_fpo_data _f @@ -88,11 +90,11 @@ ; OBJ32: Characteristics [ (0x42300040) ; OBJ32: ] ; OBJ32: Relocations [ -; OBJ32-NEXT: 0x44 IMAGE_REL_I386_DIR32NB _f -; OBJ32-NEXT: 0x90 IMAGE_REL_I386_SECREL _f -; OBJ32-NEXT: 0x94 IMAGE_REL_I386_SECTION _f -; OBJ32-NEXT: 0xC8 IMAGE_REL_I386_SECREL _f -; OBJ32-NEXT: 0xCC IMAGE_REL_I386_SECTION _f +; OBJ32-NEXT: 0x50 IMAGE_REL_I386_DIR32NB _f +; OBJ32-NEXT: 0x9C IMAGE_REL_I386_SECREL _f +; OBJ32-NEXT: 0xA0 IMAGE_REL_I386_SECTION _f +; OBJ32-NEXT: 0xD4 IMAGE_REL_I386_SECREL _f +; OBJ32-NEXT: 0xD8 IMAGE_REL_I386_SECTION _f ; OBJ32-NEXT: ] ; OBJ32: Subsection [ ; OBJ32-NEXT: SubSectionType: Symbols (0xF1) @@ -165,8 +167,10 @@ ; X64-NEXT: .long [[COMPILE_END:.*]]-[[COMPILE_START:.*]] # ; Compiler information record ; X64-NEXT: [[COMPILE_START]]: -; X64-NEXT: .short [[C1_END:.*]]-[[C1_START:.*]] # -; X64: [[C1_END]]: +; X64-NEXT: .short [[OBJNAME_END:.*]]-[[OBJNAME_START:.*]] # +; X64: [[OBJNAME_END]]: +; X64-NEXT: .short [[COMPILE3_END:.*]]-[[COMPILE3_START:.*]] # +; X64: [[COMPILE3_END]]: ; X64-NEXT: [[COMPILE_END]]: ; X64-NEXT: .p2align 2 ; X64-NEXT: .long 241 # Symbol subsection for f @@ -216,10 +220,10 @@ ; OBJ64: Characteristics [ (0x42300040) ; OBJ64: ] ; OBJ64: Relocations [ -; OBJ64-NEXT: 0x64 IMAGE_REL_AMD64_SECREL f -; OBJ64-NEXT: 0x68 IMAGE_REL_AMD64_SECTION f -; OBJ64-NEXT: 0x9C IMAGE_REL_AMD64_SECREL f -; OBJ64-NEXT: 0xA0 IMAGE_REL_AMD64_SECTION f +; OBJ64-NEXT: 0x70 IMAGE_REL_AMD64_SECREL f +; OBJ64-NEXT: 0x74 IMAGE_REL_AMD64_SECTION f +; OBJ64-NEXT: 0xA8 IMAGE_REL_AMD64_SECREL f +; OBJ64-NEXT: 0xAC IMAGE_REL_AMD64_SECTION f ; OBJ64-NEXT: ] ; OBJ64: Subsection [ ; OBJ64-NEXT: SubSectionType: Symbols (0xF1) diff --git a/llvm/test/DebugInfo/COFF/vframe-fpo.ll b/llvm/test/DebugInfo/COFF/vframe-fpo.ll --- a/llvm/test/DebugInfo/COFF/vframe-fpo.ll +++ b/llvm/test/DebugInfo/COFF/vframe-fpo.ll @@ -65,7 +65,9 @@ ; CODEVIEW-NEXT: Subsection [ ; CODEVIEW-NEXT: SubSectionType: Symbols (0xF1) ; CODEVIEW-NEXT: SubSectionSize: -; CODEVIEW-NEXT: Compile3Sym { +; CODEVIEW-NEXT: ObjNameSym { +; CODEVIEW-NEXT: Kind: S_OBJNAME (0x1101) +; CODEVIEW: Compile3Sym { ; CODEVIEW-NEXT: Kind: S_COMPILE3 (0x113C) ; CODEVIEW: } ; CODEVIEW: ] diff --git a/llvm/test/MC/AArch64/coff-debug.ll b/llvm/test/MC/AArch64/coff-debug.ll --- a/llvm/test/MC/AArch64/coff-debug.ll +++ b/llvm/test/MC/AArch64/coff-debug.ll @@ -1,5 +1,7 @@ ; RUN: llc -mtriple=aarch64-windows -filetype=obj -o - %s | \ -; RUN: llvm-readobj --codeview - | FileCheck %s +; RUN: llvm-readobj --codeview - | FileCheck %s --check-prefixes=CHECK,STDOUT +; RUN: llc -mtriple=aarch64-windows -filetype=obj -o %t %s +; RUN: llvm-readobj --codeview %t | FileCheck %s --check-prefixes=CHECK,FILE ; ModuleID = 'a.c' source_filename = "a.c" @@ -66,6 +68,12 @@ ; CHECK: Magic: 0x4 ; CHECK: Subsection [ ; CHECK: SubSectionType: Symbols (0xF1) +; CHECK: ObjNameSym { +; CHECK: Kind: S_OBJNAME (0x1101) +; CHECK: Signature: 0x0 +; CHECK: ObjectName: +; FILE-SAME: {{.*}} +; CHECK: } ; CHECK: Compile3Sym { ; CHECK: Kind: S_COMPILE3 (0x113C) ; CHECK: Language: C (0x0) diff --git a/llvm/test/MC/ARM/coff-debugging-secrel.ll b/llvm/test/MC/ARM/coff-debugging-secrel.ll --- a/llvm/test/MC/ARM/coff-debugging-secrel.ll +++ b/llvm/test/MC/ARM/coff-debugging-secrel.ll @@ -42,10 +42,10 @@ ; CHECK-MSVC: Relocations [ ; CHECK-MSVC: Section {{.*}} .debug$S { -; CHECK-MSVC: 0x64 IMAGE_REL_ARM_SECREL function -; CHECK-MSVC: 0x68 IMAGE_REL_ARM_SECTION function -; CHECK-MSVC: 0xA0 IMAGE_REL_ARM_SECREL function -; CHECK-MSVC: 0xA4 IMAGE_REL_ARM_SECTION function +; CHECK-MSVC: 0x70 IMAGE_REL_ARM_SECREL function +; CHECK-MSVC: 0x74 IMAGE_REL_ARM_SECTION function +; CHECK-MSVC: 0xAC IMAGE_REL_ARM_SECREL function +; CHECK-MSVC: 0xB0 IMAGE_REL_ARM_SECTION function ; CHECK-MSVC: } ; CHECK-MSVC: ] diff --git a/llvm/test/MC/COFF/cv-compiler-info.ll b/llvm/test/MC/COFF/cv-compiler-info.ll --- a/llvm/test/MC/COFF/cv-compiler-info.ll +++ b/llvm/test/MC/COFF/cv-compiler-info.ll @@ -1,4 +1,5 @@ -; RUN: llc -mtriple i686-pc-windows-msvc < %s | FileCheck %s +; RUN: llc -mtriple i686-pc-windows-msvc < %s | FileCheck %s --check-prefixes=CHECK,STDOUT +; RUN: llc -mtriple i686-pc-windows-msvc < %s -o %t | FileCheck %s --input-file=%t --check-prefixes=CHECK,FILE ; 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" @@ -20,19 +21,23 @@ ; 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. ; CHECK: .section .debug$S,"dr" +; CHECK: .short 4353 # Record kind: S_OBJNAME +; CHECK-NEXT: .long 0 # Signature +; STDOUT-NEXT: .byte 0 # Object name +; FILE-NEXT: .asciz "{{.*}}{{\\\\|/}}cv-compiler-info.ll.tmp" # Object name ; CHECK: .short 4412 # Record kind: S_COMPILE3 -; CHECK: .long 1 # Flags and language -; CHECK: .short 7 # CPUType -; CHECK: .short 4 # Frontend version -; CHECK: .short 0 -; CHECK: .short 0 -; CHECK: .short 0 -; CHECK: .short [[BACKEND_VERSION:[0-9]+]] # Backend version -; CHECK: .short 0 -; CHECK: .short 0 -; CHECK: .short 0 -; CHECK: .asciz "clang version 4.0.0 " # Null-terminated compiler version string -; CHECK-NOT: .short 4412 # Record kind: S_COMPILE3 +; CHECK-NEXT: .long 1 # Flags and language +; CHECK-NEXT: .short 7 # CPUType +; CHECK-NEXT: .short 4 # Frontend version +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .short [[BACKEND_VERSION:[0-9]+]] # Backend version +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .asciz "clang version 4.0.0 " # Null-terminated compiler version string +; CHECK-NOT: .short 4412 # Record kind: S_COMPILE3 !1 = !DIFile(filename: "D:\5Csrc\5Cscopes\5Cfoo.cpp", directory: "D:\5Csrc\5Cscopes\5Cclang") !2 = !{} !7 = !{i32 2, !"CodeView", i32 1} diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -530,6 +530,9 @@ GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]); if (!Out) return 1; + // Ensure the filename is passed down to CodeViewDebug. + Target->Options.MCOptions.OutputPathName = Out->outputFilename(); + std::unique_ptr DwoOut; if (!SplitDwarfOutputFile.empty()) { std::error_code EC; diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp --- a/llvm/tools/llvm-lto2/llvm-lto2.cpp +++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp @@ -352,7 +352,7 @@ std::error_code EC; auto S = std::make_unique(Path, EC, sys::fs::OF_None); check(EC, Path); - return std::make_unique(std::move(S)); + return std::make_unique(std::move(S), Path); }; auto AddBuffer = [&](size_t Task, std::unique_ptr MB) {