X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FLTO%2FLTOCodeGenerator.cpp;h=6baaaa4b1395009db44bd1f333ebb404d25c7d06;hp=231e4838470afeb282e9527002f7e8db2886c01f;hb=18f59c52f2641562978412e7c336f9ca9fe991c9;hpb=431bdfc4c118cd8bc39b0052abe6ceb0ea40de66 diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 231e4838470..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,7 +46,6 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" @@ -63,29 +64,15 @@ const char* LTOCodeGenerator::getVersionString() { #endif } -LTOCodeGenerator::LTOCodeGenerator() - : Context(getGlobalContext()), IRLinker(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() {} - IRLinker.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() { @@ -96,17 +83,17 @@ 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); @@ -115,22 +102,39 @@ void LTOCodeGenerator::initializeLTOPasses() { initializeCFGSimplifyPassPass(R); } -bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { - bool ret = IRLinker.linkInModule(&mod->getModule(), &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 = options; +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; @@ -142,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(IRLinker.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; } @@ -186,26 +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; + + const char *Extension = + (FileType == TargetMachine::CGFT_AssemblyFile ? "s" : "o"); + std::error_code EC = - sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename); + 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(); @@ -220,80 +230,76 @@ 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 ErrorOr> BufferOrErr = MemoryBuffer::getFile(name, -1, false); if (std::error_code EC = BufferOrErr.getError()) { - errMsg = EC.message(); + emitError(EC.message()); sys::fs::remove(NativeObjectPath); return nullptr; } - NativeObjectFile = BufferOrErr.get().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 = IRLinker.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. 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) @@ -304,15 +310,15 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) { 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, SmallPtrSetImpl &AsmUsed, Mangler &Mangler) { @@ -353,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); @@ -366,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()), @@ -381,36 +397,32 @@ static void accumulateAndSortLibcalls(std::vector &Libcalls, } void LTOCodeGenerator::applyScopeRestrictions() { - if (ScopeRestrictionsDone) + if (ScopeRestrictionsDone || !ShouldInternalize) return; - Module *mergedModule = IRLinker.getModule(); // Start off with a verification pass. - PassManager passes; + legacy::PassManager passes; passes.add(createVerifierPass()); - passes.add(createDebugInfoVerifierPass()); // mark which symbols can not be internalized - Mangler Mangler(TargetMach->getSubtargetImpl()->getDataLayout()); + Mangler Mangler; std::vector MustPreserveList; SmallPtrSet AsmUsed; std::vector Libcalls; - TargetLibraryInfo TLI(Triple(TargetMach->getTargetTriple())); - accumulateAndSortLibcalls( - Libcalls, TLI, TargetMach->getSubtargetImpl()->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(); @@ -425,7 +437,7 @@ void LTOCodeGenerator::applyScopeRestrictions() { 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"); @@ -436,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 = IRLinker.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()); - passes.add(createDebugInfoVerifierPass()); + legacy::PassManager passes; // Add an appropriate DataLayout instance for this module... - mergedModule->setDataLayout(TargetMach->getSubtargetImpl()->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, !DisableInline, - DisableGVNLoadPRE); + PMB.populateLTOPassManager(passes); - // Make sure everything is still good. - passes.add(createVerifierPass()); - passes.add(createDebugInfoVerifierPass()); + // 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, @@ -571,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)); }