X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FLTO%2FLTOCodeGenerator.cpp;h=6baaaa4b1395009db44bd1f333ebb404d25c7d06;hp=8df42772d5a231583e7e50a8e4e349532aa68ca1;hb=18f59c52f2641562978412e7c336f9ca9fe991c9;hpb=0b6cb7104b15504cd41f48cc2babcbcee70775f3 diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 8df42772d5a..6baaaa4b139 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -15,7 +15,10 @@ #include "llvm/LTO/LTOCodeGenerator.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/ParallelCG.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/Config/config.h" #include "llvm/IR/Constants.h" @@ -24,6 +27,7 @@ #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" @@ -33,10 +37,8 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/SubtargetFeature.h" -#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/FormattedStream.h" #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" @@ -44,14 +46,14 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" -#include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/ObjCARC.h" +#include using namespace llvm; const char* LTOCodeGenerator::getVersionString() { @@ -62,29 +64,15 @@ const char* LTOCodeGenerator::getVersionString() { #endif } -LTOCodeGenerator::LTOCodeGenerator() - : Context(getGlobalContext()), Linker(new Module("ld-temp.o", Context)), - TargetMach(nullptr), EmitDwarfDebugInfo(false), - ScopeRestrictionsDone(false), CodeModel(LTO_CODEGEN_PIC_MODEL_DEFAULT), - NativeObjectFile(nullptr), DiagHandler(nullptr), DiagContext(nullptr) { +LTOCodeGenerator::LTOCodeGenerator(LLVMContext &Context) + : Context(Context), MergedModule(new Module("ld-temp.o", Context)), + TheLinker(new Linker(*MergedModule)) { initializeLTOPasses(); } -LTOCodeGenerator::~LTOCodeGenerator() { - delete TargetMach; - delete NativeObjectFile; - TargetMach = nullptr; - NativeObjectFile = nullptr; +LTOCodeGenerator::~LTOCodeGenerator() {} - Linker.deleteModule(); - - for (std::vector::iterator I = CodegenOptions.begin(), - E = CodegenOptions.end(); - I != E; ++I) - free(*I); -} - -// Initialize LTO passes. Please keep this funciton in sync with +// Initialize LTO passes. Please keep this function in sync with // PassManagerBuilder::populateLTOPassManager(), and make sure all LTO // passes are initialized. void LTOCodeGenerator::initializeLTOPasses() { @@ -95,56 +83,58 @@ void LTOCodeGenerator::initializeLTOPasses() { initializeGlobalOptPass(R); initializeConstantMergePass(R); initializeDAHPass(R); - initializeInstCombinerPass(R); + initializeInstructionCombiningPassPass(R); initializeSimpleInlinerPass(R); initializePruneEHPass(R); initializeGlobalDCEPass(R); initializeArgPromotionPass(R); initializeJumpThreadingPass(R); - initializeSROAPass(R); + initializeSROALegacyPassPass(R); initializeSROA_DTPass(R); initializeSROA_SSAUpPass(R); initializeFunctionAttrsPass(R); - initializeGlobalsModRefPass(R); + initializeGlobalsAAWrapperPassPass(R); initializeLICMPass(R); + initializeMergedLoadStoreMotionPass(R); initializeGVNPass(R); initializeMemCpyOptPass(R); initializeDCEPass(R); initializeCFGSimplifyPassPass(R); } -bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { - bool ret = Linker.linkInModule(mod->getLLVVMModule(), &errMsg); +bool LTOCodeGenerator::addModule(LTOModule *Mod) { + assert(&Mod->getModule().getContext() == &Context && + "Expected module in same context"); + + bool ret = TheLinker->linkInModule(Mod->takeModule()); - const std::vector &undefs = mod->getAsmUndefinedRefs(); + const std::vector &undefs = Mod->getAsmUndefinedRefs(); for (int i = 0, e = undefs.size(); i != e; ++i) AsmUndefinedRefs[undefs[i]] = 1; return !ret; } -void LTOCodeGenerator::setTargetOptions(TargetOptions options) { - Options.LessPreciseFPMADOption = options.LessPreciseFPMADOption; - Options.NoFramePointerElim = options.NoFramePointerElim; - Options.AllowFPOpFusion = options.AllowFPOpFusion; - Options.UnsafeFPMath = options.UnsafeFPMath; - Options.NoInfsFPMath = options.NoInfsFPMath; - Options.NoNaNsFPMath = options.NoNaNsFPMath; - Options.HonorSignDependentRoundingFPMathOption = - options.HonorSignDependentRoundingFPMathOption; - Options.UseSoftFloat = options.UseSoftFloat; - Options.FloatABIType = options.FloatABIType; - Options.NoZerosInBSS = options.NoZerosInBSS; - Options.GuaranteedTailCallOpt = options.GuaranteedTailCallOpt; - Options.DisableTailCalls = options.DisableTailCalls; - Options.StackAlignmentOverride = options.StackAlignmentOverride; - Options.TrapFuncName = options.TrapFuncName; - Options.PositionIndependentExecutable = options.PositionIndependentExecutable; - Options.UseInitArray = options.UseInitArray; +void LTOCodeGenerator::setModule(std::unique_ptr Mod) { + assert(&Mod->getModule().getContext() == &Context && + "Expected module in same context"); + + AsmUndefinedRefs.clear(); + + MergedModule = Mod->takeModule(); + TheLinker = make_unique(*MergedModule); + + const std::vector &Undefs = Mod->getAsmUndefinedRefs(); + for (int I = 0, E = Undefs.size(); I != E; ++I) + AsmUndefinedRefs[Undefs[I]] = 1; } -void LTOCodeGenerator::setDebugInfo(lto_debug_model debug) { - switch (debug) { +void LTOCodeGenerator::setTargetOptions(TargetOptions Options) { + this->Options = Options; +} + +void LTOCodeGenerator::setDebugInfo(lto_debug_model Debug) { + switch (Debug) { case LTO_DEBUG_MODEL_NONE: EmitDwarfDebugInfo = false; return; @@ -156,42 +146,49 @@ void LTOCodeGenerator::setDebugInfo(lto_debug_model debug) { llvm_unreachable("Unknown debug format!"); } -void LTOCodeGenerator::setCodePICModel(lto_codegen_model model) { - switch (model) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - case LTO_CODEGEN_PIC_MODEL_DEFAULT: - CodeModel = model; - return; +void LTOCodeGenerator::setOptLevel(unsigned Level) { + OptLevel = Level; + switch (OptLevel) { + case 0: + CGOptLevel = CodeGenOpt::None; + break; + case 1: + CGOptLevel = CodeGenOpt::Less; + break; + case 2: + CGOptLevel = CodeGenOpt::Default; + break; + case 3: + CGOptLevel = CodeGenOpt::Aggressive; + break; } - llvm_unreachable("Unknown PIC model!"); } -bool LTOCodeGenerator::writeMergedModules(const char *path, - std::string &errMsg) { - if (!determineTarget(errMsg)) +bool LTOCodeGenerator::writeMergedModules(const char *Path) { + if (!determineTarget()) return false; // mark which symbols can not be internalized applyScopeRestrictions(); // create output file - std::string ErrInfo; - tool_output_file Out(path, ErrInfo, sys::fs::F_None); - if (!ErrInfo.empty()) { - errMsg = "could not open bitcode file for writing: "; - errMsg += path; + std::error_code EC; + tool_output_file Out(Path, EC, sys::fs::F_None); + if (EC) { + std::string ErrMsg = "could not open bitcode file for writing: "; + ErrMsg += Path; + emitError(ErrMsg); return false; } // write bitcode to it - WriteBitcodeToFile(Linker.getModule(), Out.os()); + WriteBitcodeToFile(MergedModule.get(), Out.os(), ShouldEmbedUselists); Out.os().close(); if (Out.os().has_error()) { - errMsg = "could not write bitcode file: "; - errMsg += path; + std::string ErrMsg = "could not write bitcode file: "; + ErrMsg += Path; + emitError(ErrMsg); Out.os().clear_error(); return false; } @@ -200,25 +197,25 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, return true; } -bool LTOCodeGenerator::compile_to_file(const char** name, - bool disableOpt, - bool disableInline, - bool disableGVNLoadPRE, - std::string& errMsg) { - // make unique temp .o file to put generated object file +bool LTOCodeGenerator::compileOptimizedToFile(const char **Name) { + // make unique temp output file to put generated code SmallString<128> Filename; int FD; - error_code EC = sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename); + + const char *Extension = + (FileType == TargetMachine::CGFT_AssemblyFile ? "s" : "o"); + + std::error_code EC = + sys::fs::createTemporaryFile("lto-llvm", Extension, FD, Filename); if (EC) { - errMsg = EC.message(); + emitError(EC.message()); return false; } // generate object file tool_output_file objFile(Filename.c_str(), FD); - bool genResult = generateObjectFile(objFile.os(), disableOpt, disableInline, - disableGVNLoadPRE, errMsg); + bool genResult = compileOptimized(&objFile.os()); objFile.os().close(); if (objFile.os().has_error()) { objFile.os().clear_error(); @@ -233,99 +230,97 @@ bool LTOCodeGenerator::compile_to_file(const char** name, } NativeObjectPath = Filename.c_str(); - *name = NativeObjectPath.c_str(); + *Name = NativeObjectPath.c_str(); return true; } -const void* LTOCodeGenerator::compile(size_t* length, - bool disableOpt, - bool disableInline, - bool disableGVNLoadPRE, - std::string& errMsg) { +std::unique_ptr +LTOCodeGenerator::compileOptimized() { const char *name; - if (!compile_to_file(&name, disableOpt, disableInline, disableGVNLoadPRE, - errMsg)) + if (!compileOptimizedToFile(&name)) return nullptr; - // remove old buffer if compile() called twice - delete NativeObjectFile; - // read .o file into memory buffer - std::unique_ptr BuffPtr; - if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) { - errMsg = ec.message(); + ErrorOr> BufferOrErr = + MemoryBuffer::getFile(name, -1, false); + if (std::error_code EC = BufferOrErr.getError()) { + emitError(EC.message()); sys::fs::remove(NativeObjectPath); return nullptr; } - NativeObjectFile = BuffPtr.release(); // remove temp files sys::fs::remove(NativeObjectPath); - // return buffer, unless error - if (!NativeObjectFile) + return std::move(*BufferOrErr); +} + +bool LTOCodeGenerator::compile_to_file(const char **Name, bool DisableVerify, + bool DisableInline, + bool DisableGVNLoadPRE, + bool DisableVectorization) { + if (!optimize(DisableVerify, DisableInline, DisableGVNLoadPRE, + DisableVectorization)) + return false; + + return compileOptimizedToFile(Name); +} + +std::unique_ptr +LTOCodeGenerator::compile(bool DisableVerify, bool DisableInline, + bool DisableGVNLoadPRE, bool DisableVectorization) { + if (!optimize(DisableVerify, DisableInline, DisableGVNLoadPRE, + DisableVectorization)) return nullptr; - *length = NativeObjectFile->getBufferSize(); - return NativeObjectFile->getBufferStart(); + + return compileOptimized(); } -bool LTOCodeGenerator::determineTarget(std::string &errMsg) { +bool LTOCodeGenerator::determineTarget() { if (TargetMach) return true; - std::string TripleStr = Linker.getModule()->getTargetTriple(); - if (TripleStr.empty()) + std::string TripleStr = MergedModule->getTargetTriple(); + if (TripleStr.empty()) { TripleStr = sys::getDefaultTargetTriple(); + MergedModule->setTargetTriple(TripleStr); + } llvm::Triple Triple(TripleStr); // create target machine from info for merged modules - const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); - if (!march) + std::string ErrMsg; + const Target *march = TargetRegistry::lookupTarget(TripleStr, ErrMsg); + if (!march) { + emitError(ErrMsg); return false; - - // The relocation model is actually a static member of TargetMachine and - // needs to be set before the TargetMachine is instantiated. - Reloc::Model RelocModel = Reloc::Default; - switch (CodeModel) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - RelocModel = Reloc::Static; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - RelocModel = Reloc::PIC_; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - RelocModel = Reloc::DynamicNoPIC; - break; - case LTO_CODEGEN_PIC_MODEL_DEFAULT: - // RelocModel is already the default, so leave it that way. - break; } - // construct LTOModule, hand over ownership of module and target - SubtargetFeatures Features; + // Construct LTOModule, hand over ownership of module and target. Use MAttr as + // the default set of features. + SubtargetFeatures Features(MAttr); Features.getDefaultSubtargetFeatures(Triple); - std::string FeatureStr = Features.getString(); + FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. if (MCpu.empty() && Triple.isOSDarwin()) { if (Triple.getArch() == llvm::Triple::x86_64) MCpu = "core2"; else if (Triple.getArch() == llvm::Triple::x86) MCpu = "yonah"; - else if (Triple.getArch() == llvm::Triple::arm64) + else if (Triple.getArch() == llvm::Triple::aarch64) MCpu = "cyclone"; } - TargetMach = march->createTargetMachine(TripleStr, MCpu, FeatureStr, Options, - RelocModel, CodeModel::Default, - CodeGenOpt::Aggressive); + TargetMach.reset(march->createTargetMachine(TripleStr, MCpu, FeatureStr, + Options, RelocModel, + CodeModel::Default, CGOptLevel)); return true; } void LTOCodeGenerator:: applyRestriction(GlobalValue &GV, - const ArrayRef &Libcalls, + ArrayRef Libcalls, std::vector &MustPreserveList, - SmallPtrSet &AsmUsed, + SmallPtrSetImpl &AsmUsed, Mangler &Mangler) { // There are no restrictions to apply to declarations. if (GV.isDeclaration()) @@ -354,7 +349,7 @@ applyRestriction(GlobalValue &GV, } static void findUsedValues(GlobalVariable *LLVMUsed, - SmallPtrSet &UsedValues) { + SmallPtrSetImpl &UsedValues) { if (!LLVMUsed) return; ConstantArray *Inits = cast(LLVMUsed->getInitializer()); @@ -364,10 +359,13 @@ static void findUsedValues(GlobalVariable *LLVMUsed, UsedValues.insert(GV); } +// Collect names of runtime library functions. User-defined functions with the +// same names are added to llvm.compiler.used to prevent them from being +// deleted by optimizations. static void accumulateAndSortLibcalls(std::vector &Libcalls, const TargetLibraryInfo& TLI, - const TargetLowering *Lowering) -{ + const Module &Mod, + const TargetMachine &TM) { // TargetLibraryInfo has info on C runtime library calls on the current // target. for (unsigned I = 0, E = static_cast(LibFunc::NumLibFuncs); @@ -377,14 +375,21 @@ static void accumulateAndSortLibcalls(std::vector &Libcalls, Libcalls.push_back(TLI.getName(F)); } - // TargetLowering has info on library calls that CodeGen expects to be - // available, both from the C runtime and compiler-rt. - if (Lowering) - for (unsigned I = 0, E = static_cast(RTLIB::UNKNOWN_LIBCALL); - I != E; ++I) - if (const char *Name - = Lowering->getLibcallName(static_cast(I))) - Libcalls.push_back(Name); + SmallPtrSet TLSet; + + for (const Function &F : Mod) { + const TargetLowering *Lowering = + TM.getSubtargetImpl(F)->getTargetLowering(); + + if (Lowering && TLSet.insert(Lowering).second) + // TargetLowering has info on library calls that CodeGen expects to be + // available, both from the C runtime and compiler-rt. + for (unsigned I = 0, E = static_cast(RTLIB::UNKNOWN_LIBCALL); + I != E; ++I) + if (const char *Name = + Lowering->getLibcallName(static_cast(I))) + Libcalls.push_back(Name); + } array_pod_sort(Libcalls.begin(), Libcalls.end()); Libcalls.erase(std::unique(Libcalls.begin(), Libcalls.end()), @@ -392,34 +397,32 @@ static void accumulateAndSortLibcalls(std::vector &Libcalls, } void LTOCodeGenerator::applyScopeRestrictions() { - if (ScopeRestrictionsDone) + if (ScopeRestrictionsDone || !ShouldInternalize) return; - Module *mergedModule = Linker.getModule(); // Start off with a verification pass. - PassManager passes; + legacy::PassManager passes; passes.add(createVerifierPass()); // mark which symbols can not be internalized - Mangler Mangler(TargetMach->getDataLayout()); + Mangler Mangler; std::vector MustPreserveList; SmallPtrSet AsmUsed; std::vector Libcalls; - TargetLibraryInfo TLI(Triple(TargetMach->getTargetTriple())); - accumulateAndSortLibcalls(Libcalls, TLI, TargetMach->getTargetLowering()); - - for (Module::iterator f = mergedModule->begin(), - e = mergedModule->end(); f != e; ++f) - applyRestriction(*f, Libcalls, MustPreserveList, AsmUsed, Mangler); - for (Module::global_iterator v = mergedModule->global_begin(), - e = mergedModule->global_end(); v != e; ++v) - applyRestriction(*v, Libcalls, MustPreserveList, AsmUsed, Mangler); - for (Module::alias_iterator a = mergedModule->alias_begin(), - e = mergedModule->alias_end(); a != e; ++a) - applyRestriction(*a, Libcalls, MustPreserveList, AsmUsed, Mangler); + TargetLibraryInfoImpl TLII(Triple(TargetMach->getTargetTriple())); + TargetLibraryInfo TLI(TLII); + + accumulateAndSortLibcalls(Libcalls, TLI, *MergedModule, *TargetMach); + + for (Function &f : *MergedModule) + applyRestriction(f, Libcalls, MustPreserveList, AsmUsed, Mangler); + for (GlobalVariable &v : MergedModule->globals()) + applyRestriction(v, Libcalls, MustPreserveList, AsmUsed, Mangler); + for (GlobalAlias &a : MergedModule->aliases()) + applyRestriction(a, Libcalls, MustPreserveList, AsmUsed, Mangler); GlobalVariable *LLVMCompilerUsed = - mergedModule->getGlobalVariable("llvm.compiler.used"); + MergedModule->getGlobalVariable("llvm.compiler.used"); findUsedValues(LLVMCompilerUsed, AsmUsed); if (LLVMCompilerUsed) LLVMCompilerUsed->eraseFromParent(); @@ -427,16 +430,14 @@ void LTOCodeGenerator::applyScopeRestrictions() { if (!AsmUsed.empty()) { llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(Context); std::vector asmUsed2; - for (SmallPtrSet::const_iterator i = AsmUsed.begin(), - e = AsmUsed.end(); i !=e; ++i) { - GlobalValue *GV = *i; + for (auto *GV : AsmUsed) { Constant *c = ConstantExpr::getBitCast(GV, i8PTy); asmUsed2.push_back(c); } llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size()); LLVMCompilerUsed = - new llvm::GlobalVariable(*mergedModule, ATy, false, + new llvm::GlobalVariable(*MergedModule, ATy, false, llvm::GlobalValue::AppendingLinkage, llvm::ConstantArray::get(ATy, asmUsed2), "llvm.compiler.used"); @@ -447,95 +448,90 @@ void LTOCodeGenerator::applyScopeRestrictions() { passes.add(createInternalizePass(MustPreserveList)); // apply scope restrictions - passes.run(*mergedModule); + passes.run(*MergedModule); ScopeRestrictionsDone = true; } /// Optimize merged modules using various IPO passes -bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, - bool DisableOpt, - bool DisableInline, - bool DisableGVNLoadPRE, - std::string &errMsg) { - if (!this->determineTarget(errMsg)) +bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline, + bool DisableGVNLoadPRE, + bool DisableVectorization) { + if (!this->determineTarget()) return false; - Module *mergedModule = Linker.getModule(); - // Mark which symbols can not be internalized this->applyScopeRestrictions(); // Instantiate the pass manager to organize the passes. - PassManager passes; - - // Start off with a verification pass. - passes.add(createVerifierPass()); + legacy::PassManager passes; // Add an appropriate DataLayout instance for this module... - mergedModule->setDataLayout(TargetMach->getDataLayout()); - passes.add(new DataLayoutPass(mergedModule)); + MergedModule->setDataLayout(TargetMach->createDataLayout()); - // Add appropriate TargetLibraryInfo for this module. - passes.add(new TargetLibraryInfo(Triple(TargetMach->getTargetTriple()))); + passes.add( + createTargetTransformInfoWrapperPass(TargetMach->getTargetIRAnalysis())); - TargetMach->addAnalysisPasses(passes); + Triple TargetTriple(TargetMach->getTargetTriple()); + PassManagerBuilder PMB; + PMB.DisableGVNLoadPRE = DisableGVNLoadPRE; + PMB.LoopVectorize = !DisableVectorization; + PMB.SLPVectorize = !DisableVectorization; + if (!DisableInline) + PMB.Inliner = createFunctionInliningPass(); + PMB.LibraryInfo = new TargetLibraryInfoImpl(TargetTriple); + PMB.OptLevel = OptLevel; + PMB.VerifyInput = !DisableVerify; + PMB.VerifyOutput = !DisableVerify; - // Enabling internalize here would use its AllButMain variant. It - // keeps only main if it exists and does nothing for libraries. Instead - // we create the pass ourselves with the symbol list provided by the linker. - if (!DisableOpt) - PassManagerBuilder().populateLTOPassManager(passes, - /*Internalize=*/false, - !DisableInline, - DisableGVNLoadPRE); + PMB.populateLTOPassManager(passes); - // Make sure everything is still good. - passes.add(createVerifierPass()); + // Run our queue of passes all at once now, efficiently. + passes.run(*MergedModule); - PassManager codeGenPasses; + return true; +} - codeGenPasses.add(new DataLayoutPass(mergedModule)); +bool LTOCodeGenerator::compileOptimized(ArrayRef Out) { + if (!this->determineTarget()) + return false; - formatted_raw_ostream Out(out); + legacy::PassManager preCodeGenPasses; // If the bitcode files contain ARC code and were compiled with optimization, // the ObjCARCContractPass must be run, so do it unconditionally here. - codeGenPasses.add(createObjCARCContractPass()); - - if (TargetMach->addPassesToEmitFile(codeGenPasses, Out, - TargetMachine::CGFT_ObjectFile)) { - errMsg = "target file type not supported"; - return false; - } - - // Run our queue of passes all at once now, efficiently. - passes.run(*mergedModule); - - // Run the code generator, and write assembly file - codeGenPasses.run(*mergedModule); + preCodeGenPasses.add(createObjCARCContractPass()); + preCodeGenPasses.run(*MergedModule); + + // Do code generation. We need to preserve the module in case the client calls + // writeMergedModules() after compilation, but we only need to allow this at + // parallelism level 1. This is achieved by having splitCodeGen return the + // original module at parallelism level 1 which we then assign back to + // MergedModule. + MergedModule = + splitCodeGen(std::move(MergedModule), Out, MCpu, FeatureStr, Options, + RelocModel, CodeModel::Default, CGOptLevel, FileType); return true; } /// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging /// LTO problems. -void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) { - for (std::pair o = getToken(options); - !o.first.empty(); o = getToken(o.second)) { - // ParseCommandLineOptions() expects argv[0] to be program name. Lazily add - // that. - if (CodegenOptions.empty()) - CodegenOptions.push_back(strdup("libLLVMLTO")); - CodegenOptions.push_back(strdup(o.first.str().c_str())); - } +void LTOCodeGenerator::setCodeGenDebugOptions(const char *Options) { + for (std::pair o = getToken(Options); !o.first.empty(); + o = getToken(o.second)) + CodegenOptions.push_back(o.first); } void LTOCodeGenerator::parseCodeGenDebugOptions() { // if options were requested, set them - if (!CodegenOptions.empty()) - cl::ParseCommandLineOptions(CodegenOptions.size(), - const_cast(&CodegenOptions[0])); + if (!CodegenOptions.empty()) { + // ParseCommandLineOptions() expects argv[0] to be program name. + std::vector CodegenArgv(1, "libLLVMLTO"); + for (std::string &Arg : CodegenOptions) + CodegenArgv.push_back(Arg.c_str()); + cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data()); + } } void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI, @@ -582,5 +578,23 @@ LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler, return Context.setDiagnosticHandler(nullptr, nullptr); // Register the LTOCodeGenerator stub in the LLVMContext to forward the // diagnostic to the external DiagHandler. - Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this); + Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this, + /* RespectFilters */ true); +} + +namespace { +class LTODiagnosticInfo : public DiagnosticInfo { + const Twine &Msg; +public: + LTODiagnosticInfo(const Twine &DiagMsg, DiagnosticSeverity Severity=DS_Error) + : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {} + void print(DiagnosticPrinter &DP) const override { DP << Msg; } +}; +} + +void LTOCodeGenerator::emitError(const std::string &ErrMsg) { + if (DiagHandler) + (*DiagHandler)(LTO_DS_ERROR, ErrMsg.c_str(), DiagContext); + else + Context.diagnose(LTODiagnosticInfo(ErrMsg)); }