From bf499c58af3d3a96661f5c7ef81b264eac575541 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Sun, 16 Jan 2022 16:06:59 -0500 Subject: [PATCH] [OpenMP] Implement save temps functionality in linker wrapper Summary: This patch implements the `-save-temps` flag for the linker wrapper. This allows the user to inspect the intermeditary outpout that the linker wrapper creates. --- clang/lib/Driver/ToolChains/Clang.cpp | 2 + .../clang-linker-wrapper/ClangLinkerWrapper.cpp | 152 +++++++++++---------- 2 files changed, 85 insertions(+), 69 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1ddffcd..537b9ca 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8244,6 +8244,8 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ)) CmdArgs.push_back( Args.MakeArgString(Twine("-pass-remarks-analysis=") + A->getValue())); + if (Args.getLastArg(options::OPT_save_temps_EQ)) + CmdArgs.push_back("-save-temps"); // Add the linker arguments to be forwarded by the wrapper. CmdArgs.push_back("-linker-path"); diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 8331bda..56a1859 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -111,6 +111,10 @@ static cl::opt DebugInfo( "Direction information"), clEnumValN(FullDebugInfo, "g", "Full debugging support"))); +static cl::opt SaveTemps("save-temps", cl::ZeroOrMore, + cl::desc("Save intermediary results."), + cl::cat(ClangLinkerWrapperCategory)); + // Do not parse linker options. static cl::list HostLinkerArgs(cl::Positional, @@ -157,6 +161,21 @@ static StringRef getDeviceFileExtension(StringRef DeviceTriple, return "o"; } +Error createOutputFile(const Twine &Prefix, StringRef Extension, + SmallString<128> &NewFilename) { + if (!SaveTemps) { + if (std::error_code EC = + sys::fs::createTemporaryFile(Prefix, Extension, NewFilename)) + return createFileError(NewFilename, EC); + TempFiles.push_back(static_cast(NewFilename)); + } else { + const Twine &Filename = Prefix + "." + Extension; + Filename.toNullTerminatedStringRef(NewFilename); + } + + return Error::success(); +} + Error runLinker(std::string &LinkerPath, SmallVectorImpl &Args) { std::vector LinkerArgs; LinkerArgs.push_back(LinkerPath); @@ -204,11 +223,8 @@ void removeFromCompilerUsed(Module &M, GlobalValue &Value) { Expected> extractFromBinary(const ObjectFile &Obj, SmallVectorImpl &DeviceFiles) { - StringRef Extension = sys::path::extension(Obj.getFileName()).drop_front(); - StringRef Prefix = sys::path::stem(Obj.getFileName()).take_until([](char C) { - return C == '-'; - }); + StringRef Prefix = sys::path::stem(Obj.getFileName()); SmallVector ToBeStripped; // Extract data from sections of the form `.llvm.offloading..`. @@ -226,10 +242,9 @@ extractFromBinary(const ObjectFile &Obj, SmallString<128> TempFile; StringRef DeviceExtension = getDeviceFileExtension( DeviceTriple, identify_magic(*Contents) == file_magic::bitcode); - if (std::error_code EC = sys::fs::createTemporaryFile( - Prefix + "-device-" + DeviceTriple, DeviceExtension, TempFile)) - return createFileError(TempFile, EC); - TempFiles.push_back(static_cast(TempFile)); + if (Error Err = createOutputFile(Prefix + "-device-" + DeviceTriple, + DeviceExtension, TempFile)) + return std::move(Err); Expected> OutputOrErr = FileOutputBuffer::create(TempFile, Sec.getSize()); @@ -253,10 +268,9 @@ extractFromBinary(const ObjectFile &Obj, SmallString<128> StripFile = Obj.getFileName(); if (!sys::fs::exists(StripFile)) { SmallString<128> TempFile; - if (std::error_code EC = sys::fs::createTemporaryFile( - sys::path::stem(StripFile), "o", TempFile)) - return createFileError(TempFile, EC); - TempFiles.push_back(static_cast(TempFile)); + if (Error Err = createOutputFile(sys::path::stem(StripFile), + sys::path::extension(StripFile), TempFile)) + return std::move(Err); auto Contents = Obj.getMemoryBufferRef().getBuffer(); Expected> OutputOrErr = @@ -278,10 +292,8 @@ extractFromBinary(const ObjectFile &Obj, "Unable to find 'llvm-strip' in path"); SmallString<128> TempFile; - if (std::error_code EC = - sys::fs::createTemporaryFile(Prefix + "-host", Extension, TempFile)) - return createFileError(TempFile, EC); - TempFiles.push_back(static_cast(TempFile)); + if (Error Err = createOutputFile(Prefix + "-host", Extension, TempFile)) + return std::move(Err); SmallVector StripArgs; StripArgs.push_back(*StripPath); @@ -336,10 +348,9 @@ extractFromBitcode(std::unique_ptr Buffer, SmallString<128> TempFile; StringRef DeviceExtension = getDeviceFileExtension( DeviceTriple, identify_magic(Contents) == file_magic::bitcode); - if (std::error_code EC = sys::fs::createTemporaryFile( - Prefix + "-device-" + DeviceTriple, DeviceExtension, TempFile)) - return createFileError(TempFile, EC); - TempFiles.push_back(static_cast(TempFile)); + if (Error Err = createOutputFile(Prefix + "-device-" + DeviceTriple, + DeviceExtension, TempFile)) + return std::move(Err); Expected> OutputOrErr = FileOutputBuffer::create(TempFile, Contents.size()); @@ -368,10 +379,8 @@ extractFromBitcode(std::unique_ptr Buffer, } SmallString<128> TempFile; - if (std::error_code EC = - sys::fs::createTemporaryFile(Prefix + "-host", Extension, TempFile)) - return createFileError(TempFile, EC); - TempFiles.push_back(static_cast(TempFile)); + if (Error Err = createOutputFile(Prefix + "-host", Extension, TempFile)) + return std::move(Err); std::error_code EC; raw_fd_ostream HostOutput(TempFile, EC, sys::fs::OF_None); @@ -385,13 +394,6 @@ Expected> extractFromArchive(const Archive &Library, SmallVectorImpl &DeviceFiles) { - StringRef Extension = - sys::path::extension(Library.getFileName()).drop_front(); - StringRef Prefix = - sys::path::stem(Library.getFileName()).take_until([](char C) { - return C == '-'; - }); - bool NewMembers = false; SmallVector Members; @@ -440,10 +442,9 @@ extractFromArchive(const Archive &Library, // Create a new static library using the stripped host files. SmallString<128> TempFile; - if (std::error_code EC = - sys::fs::createTemporaryFile(Prefix + "-host", Extension, TempFile)) - return createFileError(TempFile, EC); - TempFiles.push_back(static_cast(TempFile)); + StringRef Prefix = sys::path::stem(Library.getFileName()); + if (Error Err = createOutputFile(Prefix + "-host", "a", TempFile)) + return std::move(Err); std::unique_ptr Buffer = MemoryBuffer::getMemBuffer(Library.getMemoryBufferRef(), false); @@ -500,10 +501,9 @@ Expected assemble(StringRef InputFile, Triple TheTriple, // Create a new file to write the linked device image to. SmallString<128> TempFile; - if (std::error_code EC = sys::fs::createTemporaryFile( + if (Error Err = createOutputFile( "lto-" + TheTriple.getArchName() + "-" + Arch, "cubin", TempFile)) - return createFileError(TempFile, EC); - TempFiles.push_back(static_cast(TempFile)); + return std::move(Err); // TODO: Pass in arguments like `-g` and `-v` from the driver. SmallVector CmdArgs; @@ -544,10 +544,9 @@ Expected link(ArrayRef InputFiles, // Create a new file to write the linked device image to. SmallString<128> TempFile; - if (std::error_code EC = sys::fs::createTemporaryFile( + if (Error Err = createOutputFile( TheTriple.getArchName() + "-" + Arch + "-image", "out", TempFile)) - return createFileError(TempFile, EC); - TempFiles.push_back(static_cast(TempFile)); + return std::move(Err); SmallVector CmdArgs; CmdArgs.push_back(*NvlinkPath); @@ -591,10 +590,9 @@ Expected link(ArrayRef InputFiles, // Create a new file to write the linked device image to. SmallString<128> TempFile; - if (std::error_code EC = sys::fs::createTemporaryFile( + if (Error Err = createOutputFile( TheTriple.getArchName() + "-" + Arch + "-image", "out", TempFile)) - return createFileError(TempFile, EC); - TempFiles.push_back(static_cast(TempFile)); + return std::move(Err); SmallVector CmdArgs; CmdArgs.push_back(*LLDPath); @@ -710,6 +708,26 @@ std::unique_ptr createLTO( Conf.PTO.LoopVectorization = Conf.OptLevel > 1; Conf.PTO.SLPVectorization = Conf.OptLevel > 1; + if (SaveTemps) { + auto HandleError = [&](Error Err) { + logAllUnhandledErrors(std::move(Err), + WithColor::error(errs(), LinkerExecutable)); + exit(1); + }; + Conf.PostInternalizeModuleHook = [&](size_t, const Module &M) { + SmallString<128> TempFile; + if (Error Err = + createOutputFile("lto-" + TheTriple.getTriple(), "bc", TempFile)) + HandleError(std::move(Err)); + + std::error_code EC; + raw_fd_ostream LinkedBitcode(TempFile, EC, sys::fs::OF_None); + if (EC) + HandleError(errorCodeToError(EC)); + WriteBitcodeToFile(M, LinkedBitcode); + return true; + }; + } Conf.PostOptModuleHook = Hook; if (TheTriple.isNVPTX()) Conf.CGFileType = CGFT_AssemblyFile; @@ -783,33 +801,33 @@ Error linkBitcodeFiles(SmallVectorImpl &InputFiles, assert(!BitcodeLibrary.empty() && "Bitcode linking without `-foffload-lto`"); - auto HandleError = [&](std::error_code EC) { - logAllUnhandledErrors(errorCodeToError(EC), + auto HandleError = [&](Error Err) { + logAllUnhandledErrors(std::move(Err), WithColor::error(errs(), LinkerExecutable)); exit(1); }; // LTO Module hook to output bitcode without running the backend. - auto LinkOnly = [&](size_t Task, const Module &M) { + auto OutputBitcode = [&](size_t Task, const Module &M) { SmallString<128> TempFile; - if (std::error_code EC = sys::fs::createTemporaryFile( - "jit-" + TheTriple.getTriple(), "bc", TempFile)) - HandleError(EC); + if (Error Err = + createOutputFile("jit-" + TheTriple.getTriple(), "bc", TempFile)) + HandleError(std::move(Err)); + std::error_code EC; raw_fd_ostream LinkedBitcode(TempFile, EC, sys::fs::OF_None); if (EC) - HandleError(EC); + HandleError(errorCodeToError(EC)); WriteBitcodeToFile(M, LinkedBitcode); - TempFiles.push_back(static_cast(TempFile)); NewInputFiles.push_back(static_cast(TempFile)); return false; }; // We assume visibility of the whole program if every input file was bitcode. bool WholeProgram = BitcodeFiles.size() == InputFiles.size(); - auto LTOBackend = (EmbedBitcode) - ? createLTO(TheTriple, Arch, WholeProgram, LinkOnly) - : createLTO(TheTriple, Arch, WholeProgram); + auto LTOBackend = + (EmbedBitcode) ? createLTO(TheTriple, Arch, WholeProgram, OutputBitcode) + : createLTO(TheTriple, Arch, WholeProgram); // We need to resolve the symbols so the LTO backend knows which symbols need // to be kept or can be internalized. This is a simplified symbol resolution @@ -869,9 +887,11 @@ Error linkBitcodeFiles(SmallVectorImpl &InputFiles, int FD = -1; auto &TempFile = Files[Task]; StringRef Extension = (TheTriple.isNVPTX()) ? "s" : "o"; - if (std::error_code EC = sys::fs::createTemporaryFile( - "lto-" + TheTriple.getTriple(), Extension, FD, TempFile)) - HandleError(EC); + if (Error Err = createOutputFile("lto-" + TheTriple.getTriple(), Extension, + TempFile)) + HandleError(std::move(Err)); + if (std::error_code EC = sys::fs::openFileForWrite(TempFile, FD)) + HandleError(errorCodeToError(EC)); TempFiles.push_back(static_cast(TempFile)); return std::make_unique( std::make_unique(FD, true)); @@ -947,17 +967,13 @@ Expected wrapDeviceImage(StringRef ImageFile) { // Create a new file to write the wrapped bitcode file to. SmallString<128> BitcodeFile; - if (std::error_code EC = - sys::fs::createTemporaryFile("wrapper", "bc", BitcodeFile)) - return createFileError(BitcodeFile, EC); - TempFiles.push_back(static_cast(BitcodeFile)); + if (Error Err = createOutputFile("offload-wrapper", "bc", BitcodeFile)) + return std::move(Err); - // TODO: Optionally pass the host triple in somewhere. - Triple HostTriple(sys::getDefaultTargetTriple()); SmallVector WrapperArgs; WrapperArgs.push_back(*WrapperPath); WrapperArgs.push_back("-target"); - WrapperArgs.push_back(HostTriple.getTriple()); + WrapperArgs.push_back(HostTriple); WrapperArgs.push_back("-o"); WrapperArgs.push_back(BitcodeFile); WrapperArgs.push_back(ImageFile); @@ -973,10 +989,8 @@ Expected wrapDeviceImage(StringRef ImageFile) { // Create a new file to write the wrapped bitcode file to. SmallString<128> ObjectFile; - if (std::error_code EC = - sys::fs::createTemporaryFile("image", "o", ObjectFile)) - return createFileError(BitcodeFile, EC); - TempFiles.push_back(static_cast(ObjectFile)); + if (Error Err = createOutputFile("offload-wrapper", "o", ObjectFile)) + return std::move(Err); SmallVector CompilerArgs; CompilerArgs.push_back(*CompilerPath); -- 2.7.4