diff --git a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h --- a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -213,6 +213,15 @@ bool determineTarget(); std::unique_ptr createTargetMachine(); + // Checks to see if the llvm backend integrated assembler is available. + bool hasIntegratedAssembler(); + + // Sets up the LTO configuration to run the system assembler. + void setupForSystemAssembler(); + + // Runs the system assembler to generate object file. + bool runSystemAssembler(SmallString<128> &Name); + void emitError(const std::string &ErrMsg); void emitWarning(const std::string &ErrMsg); diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -51,6 +51,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" @@ -64,6 +65,13 @@ #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include +#if defined(HAVE_UNISTD_H) +#include +#define GETPID getpid() +#else +#define GETPID 0 +#endif + using namespace llvm; const char* LTOCodeGenerator::getVersionString() { @@ -114,6 +122,15 @@ "lto-stats-file", cl::desc("Save statistics to the specified file"), cl::Hidden); + +cl::opt SaveTemps( + "lto-save-temps", cl::init(false), + cl::desc("Save temporary LTO files in the current working directory.")); + +cl::opt SystemAssemblerPath( + "lto-system-assembler", + cl::desc("Absolute path to the system assembler, picked up on AIX only"), + cl::value_desc("path")); } LTOCodeGenerator::LTOCodeGenerator(LLVMContext &Context) @@ -237,7 +254,75 @@ return true; } +bool LTOCodeGenerator::hasIntegratedAssembler() { + const auto &Triple = TargetMach->getTargetTriple(); + return !Triple.isOSAIX(); +} + +void LTOCodeGenerator::setupForSystemAssembler() { + setFileType(CGFT_AssemblyFile); +} + +bool LTOCodeGenerator::runSystemAssembler(SmallString<128> &Name) { + assert(!hasIntegratedAssembler() && + "Runing system assembler when integrated assembler is available!"); + + if (llvm::SaveTemps) + llvm::sys::fs::copy_file(Name, "ld-temp." + llvm::Twine(getpid()) + ".s"); + + // Set the system assembler path. + std::string AssemblerPath(llvm::SystemAssemblerPath.empty() + ? "/usr/bin/as" + : llvm::SystemAssemblerPath.c_str()); + + // Prepare inputs for the assember. + const auto &Triple = TargetMach->getTargetTriple(); + const char *Arch = Triple.isArch64Bit() ? "-a64" : "-a32"; + std::string ObjectFileName(Name); + ObjectFileName[ObjectFileName.size() - 1] = 'o'; + SmallVector Args = { + "/bin/env", "LDR_CNTRL=MAXDATA32=0x80000000@${LDR_CNTRL}", + AssemblerPath, Arch, + "-many", "-o", + ObjectFileName, Name}; + + // Invoke the assembler. + int RC = sys::ExecuteAndWait(Args[0], Args); + + // Handle errors. + if (RC < -1) { + emitError("LTO assembler exited abnormally"); + return false; + } + + if (RC < 0) { + emitError("Unable to invoke LTO assembler"); + return false; + } + + if (RC > 0) { + emitError("LTO assembler invocation returned non-zero"); + return false; + } + + // Cleanup. + remove(Name.c_str()); + + if (llvm::SaveTemps) + llvm::sys::fs::copy_file(ObjectFileName, + "ld-temp." + llvm::Twine(getpid()) + ".postlto.o"); + + // Fix the output file name. + Name = ObjectFileName; + + return true; +} + bool LTOCodeGenerator::compileOptimizedToFile(const char **Name) { + if (!hasIntegratedAssembler()) { + setupForSystemAssembler(); + } + // make unique temp output file to put generated code SmallString<128> Filename; @@ -268,6 +353,10 @@ else if (AreStatisticsEnabled()) PrintStatistics(); + if (!hasIntegratedAssembler()) + if (!runSystemAssembler(Filename)) + return false; + NativeObjectPath = Filename.c_str(); *Name = NativeObjectPath.c_str(); return true;