From: Rafael Espindola Date: Sat, 25 Oct 2014 04:06:10 +0000 (+0000) Subject: Update the error handling of lib/Linker. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=72478e59c7dfb01870a8f6b5ae6c7e1fb18719c3;p=oota-llvm.git Update the error handling of lib/Linker. Instead of passing a std::string&, use the new diagnostic infrastructure. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220608 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index ac21eb5024b..b592f890b22 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -47,6 +47,7 @@ enum DiagnosticSeverity { enum DiagnosticKind { DK_InlineAsm, DK_StackSize, + DK_Linker, DK_DebugMetadataVersion, DK_SampleProfile, DK_OptimizationRemark, diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 5bd28950d6c..274c45b9269 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -64,7 +64,7 @@ struct LTOCodeGenerator { ~LTOCodeGenerator(); // Merge given module, return true on success. - bool addModule(struct LTOModule*, std::string &errMsg); + bool addModule(struct LTOModule *); void setTargetOptions(TargetOptions options); void setDebugInfo(lto_debug_model); diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index 6254bbb6d6d..18fa412d24a 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -11,14 +11,10 @@ #define LLVM_LINKER_LINKER_H #include "llvm/ADT/SmallPtrSet.h" -#include namespace llvm { -class Comdat; -class GlobalValue; class Module; -class StringRef; class StructType; /// This class provides the core functionality of linking in LLVM. It keeps a @@ -32,7 +28,7 @@ class Linker { PreserveSource = 1 // Preserve the source module. }; - Linker(Module *M, bool SuppressWarnings=false); + Linker(Module *M); ~Linker(); Module *getModule() const { return Composite; } @@ -43,19 +39,16 @@ class Linker { /// If \p ErrorMsg is not null, information about any error is written /// to it. /// Returns true on error. - bool linkInModule(Module *Src, unsigned Mode, std::string *ErrorMsg); - bool linkInModule(Module *Src, std::string *ErrorMsg) { - return linkInModule(Src, Linker::DestroySource, ErrorMsg); + bool linkInModule(Module *Src, unsigned Mode); + bool linkInModule(Module *Src) { + return linkInModule(Src, Linker::DestroySource); } - static bool LinkModules(Module *Dest, Module *Src, unsigned Mode, - std::string *ErrorMsg); + static bool LinkModules(Module *Dest, Module *Src, unsigned Mode); private: Module *Composite; SmallPtrSet IdentifiedStructTypes; - - bool SuppressWarnings; }; } // End llvm namespace diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 3d7c5cead17..bb85cfde501 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -113,8 +113,8 @@ 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) { + bool ret = IRLinker.linkInModule(&mod->getModule()); const std::vector &undefs = mod->getAsmUndefinedRefs(); for (int i = 0, e = undefs.size(); i != e; ++i) diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index c0601430fea..c9563e6c272 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -17,6 +17,9 @@ #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/TypeFinder.h" #include "llvm/Support/CommandLine.h" @@ -376,6 +379,20 @@ namespace { Value *materializeValueFor(Value *V) override; }; + namespace { + class LinkDiagnosticInfo : public DiagnosticInfo { + const Twine &Msg; + + public: + LinkDiagnosticInfo(DiagnosticSeverity Severity, const Twine &Msg); + void print(DiagnosticPrinter &DP) const override; + }; + LinkDiagnosticInfo::LinkDiagnosticInfo(DiagnosticSeverity Severity, + const Twine &Msg) + : DiagnosticInfo(DK_Linker, Severity), Msg(Msg) {} + void LinkDiagnosticInfo::print(DiagnosticPrinter &DP) const { DP << Msg; } + } + /// ModuleLinker - This is an implementation class for the LinkModules /// function, which is the entrypoint for this file. class ModuleLinker { @@ -406,29 +423,27 @@ namespace { // Vector of functions to lazily link in. std::vector LazilyLinkFunctions; - bool SuppressWarnings; - public: - std::string ErrorMsg; - - ModuleLinker(Module *dstM, TypeSet &Set, Module *srcM, unsigned mode, - bool SuppressWarnings=false) + ModuleLinker(Module *dstM, TypeSet &Set, Module *srcM, unsigned mode) : DstM(dstM), SrcM(srcM), TypeMap(Set), - ValMaterializer(TypeMap, DstM, LazilyLinkFunctions), Mode(mode), - SuppressWarnings(SuppressWarnings) {} + ValMaterializer(TypeMap, DstM, LazilyLinkFunctions), Mode(mode) {} bool run(); private: - bool shouldLinkFromSource(const GlobalValue &Dest, const GlobalValue &Src); + bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest, + const GlobalValue &Src); - /// emitError - Helper method for setting a message and returning an error - /// code. + /// Helper method for setting a message and returning an error code. bool emitError(const Twine &Message) { - ErrorMsg = Message.str(); + DstM->getContext().diagnose(LinkDiagnosticInfo(DS_Error, Message)); return true; } + void emitWarning(const Twine &Message) { + DstM->getContext().diagnose(LinkDiagnosticInfo(DS_Warning, Message)); + } + bool getComdatLeader(Module *M, StringRef ComdatName, const GlobalVariable *&GVar); bool computeResultingSelectionKind(StringRef ComdatName, @@ -672,7 +687,8 @@ bool ModuleLinker::getComdatResult(const Comdat *SrcC, LinkFromSrc); } -bool ModuleLinker::shouldLinkFromSource(const GlobalValue &Dest, +bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc, + const GlobalValue &Dest, const GlobalValue &Src) { bool SrcIsDeclaration = Src.isDeclarationForLinker(); bool DestIsDeclaration = Dest.isDeclarationForLinker(); @@ -683,42 +699,56 @@ bool ModuleLinker::shouldLinkFromSource(const GlobalValue &Dest, if (SrcIsDeclaration) { // If Src is external or if both Src & Dest are external.. Just link the // external globals, we aren't adding anything. - if (Src.hasDLLImportStorageClass()) + if (Src.hasDLLImportStorageClass()) { // If one of GVs is marked as DLLImport, result should be dllimport'ed. - return DestIsDeclaration; + LinkFromSrc = DestIsDeclaration; + return false; + } // If the Dest is weak, use the source linkage. - return Dest.hasExternalWeakLinkage(); + LinkFromSrc = Dest.hasExternalWeakLinkage(); + return false; } - if (DestIsDeclaration) + if (DestIsDeclaration) { // If Dest is external but Src is not: - return true; + LinkFromSrc = true; + return false; + } if (Src.hasCommonLinkage()) { - if (Dest.hasLinkOnceLinkage() || Dest.hasWeakLinkage()) - return true; + if (Dest.hasLinkOnceLinkage() || Dest.hasWeakLinkage()) { + LinkFromSrc = true; + return false; + } - if (!Dest.hasCommonLinkage()) + if (!Dest.hasCommonLinkage()) { + LinkFromSrc = false; return false; + } uint64_t DestSize = DL.getTypeAllocSize(Dest.getType()->getElementType()); uint64_t SrcSize = DL.getTypeAllocSize(Src.getType()->getElementType()); - return SrcSize > DestSize; + LinkFromSrc = SrcSize > DestSize; + return false; } if (Src.isWeakForLinker()) { assert(!Dest.hasExternalWeakLinkage()); assert(!Dest.hasAvailableExternallyLinkage()); - if (Dest.hasLinkOnceLinkage() && Src.hasWeakLinkage()) - return true; + if (Dest.hasLinkOnceLinkage() && Src.hasWeakLinkage()) { + LinkFromSrc = true; + return false; + } + LinkFromSrc = false; return false; } if (Dest.isWeakForLinker()) { assert(Src.hasExternalLinkage()); - return true; + LinkFromSrc = true; + return false; } assert(!Src.hasExternalWeakLinkage()); @@ -742,9 +772,7 @@ bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src, assert(!Src->hasLocalLinkage() && "If Src has internal linkage, Dest shouldn't be set!"); - assert(ErrorMsg.empty()); - LinkFromSrc = shouldLinkFromSource(*Dest, *Src); - if (!ErrorMsg.empty()) + if (shouldLinkFromSource(LinkFromSrc, *Dest, *Src)) return true; if (LinkFromSrc) @@ -1470,10 +1498,8 @@ bool ModuleLinker::linkModuleFlagsMetadata() { case Module::Warning: { // Emit a warning if the values differ. if (SrcOp->getOperand(2) != DstOp->getOperand(2)) { - if (!SuppressWarnings) { - errs() << "WARNING: linking module flags '" << ID->getString() - << "': IDs have conflicting values"; - } + emitWarning("linking module flags '" + ID->getString() + + "': IDs have conflicting values"); } continue; } @@ -1540,23 +1566,19 @@ bool ModuleLinker::run() { if (SrcM->getDataLayout() && DstM->getDataLayout() && *SrcM->getDataLayout() != *DstM->getDataLayout()) { - if (!SuppressWarnings) { - errs() << "WARNING: Linking two modules of different data layouts: '" - << SrcM->getModuleIdentifier() << "' is '" - << SrcM->getDataLayoutStr() << "' whereas '" - << DstM->getModuleIdentifier() << "' is '" - << DstM->getDataLayoutStr() << "'\n"; - } + emitWarning("Linking two modules of different data layouts: '" + + SrcM->getModuleIdentifier() + "' is '" + + SrcM->getDataLayoutStr() + "' whereas '" + + DstM->getModuleIdentifier() + "' is '" + + DstM->getDataLayoutStr() + "'\n"); } if (!SrcM->getTargetTriple().empty() && DstM->getTargetTriple() != SrcM->getTargetTriple()) { - if (!SuppressWarnings) { - errs() << "WARNING: Linking two modules of different target triples: " - << SrcM->getModuleIdentifier() << "' is '" - << SrcM->getTargetTriple() << "' whereas '" - << DstM->getModuleIdentifier() << "' is '" - << DstM->getTargetTriple() << "'\n"; - } + emitWarning("Linking two modules of different target triples: " + + SrcM->getModuleIdentifier() + "' is '" + + SrcM->getTargetTriple() + "' whereas '" + + DstM->getModuleIdentifier() + "' is '" + + DstM->getTargetTriple() + "'\n"); } // Append the module inline asm string. @@ -1626,10 +1648,8 @@ bool ModuleLinker::run() { // Materialize if needed. if (SF->isMaterializable()) { - if (std::error_code EC = SF->materialize()) { - ErrorMsg = EC.message(); - return true; - } + if (std::error_code EC = SF->materialize()) + return emitError(EC.message()); } // Skip if no body (function is external). @@ -1679,10 +1699,8 @@ bool ModuleLinker::run() { // Materialize if needed. if (SF->isMaterializable()) { - if (std::error_code EC = SF->materialize()) { - ErrorMsg = EC.message(); - return true; - } + if (std::error_code EC = SF->materialize()) + return emitError(EC.message()); } // Skip if no body (function is external). @@ -1711,8 +1729,7 @@ bool ModuleLinker::run() { return false; } -Linker::Linker(Module *M, bool SuppressWarnings) - : Composite(M), SuppressWarnings(SuppressWarnings) { +Linker::Linker(Module *M) : Composite(M) { TypeFinder StructTypes; StructTypes.run(*M, true); IdentifiedStructTypes.insert(StructTypes.begin(), StructTypes.end()); @@ -1726,15 +1743,9 @@ void Linker::deleteModule() { Composite = nullptr; } -bool Linker::linkInModule(Module *Src, unsigned Mode, std::string *ErrorMsg) { - ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, Mode, - SuppressWarnings); - if (TheLinker.run()) { - if (ErrorMsg) - *ErrorMsg = TheLinker.ErrorMsg; - return true; - } - return false; +bool Linker::linkInModule(Module *Src, unsigned Mode) { + ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, Mode); + return TheLinker.run(); } //===----------------------------------------------------------------------===// @@ -1746,10 +1757,9 @@ bool Linker::linkInModule(Module *Src, unsigned Mode, std::string *ErrorMsg) { /// error occurs, true is returned and ErrorMsg (if not null) is set to indicate /// the problem. Upon failure, the Dest module could be in a modified state, /// and shouldn't be relied on to be consistent. -bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode, - std::string *ErrorMsg) { +bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode) { Linker L(Dest); - return L.linkInModule(Src, Mode, ErrorMsg); + return L.linkInModule(Src, Mode); } //===----------------------------------------------------------------------===// @@ -1758,10 +1768,6 @@ bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode, LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, LLVMLinkerMode Mode, char **OutMessages) { - std::string Messages; - LLVMBool Result = Linker::LinkModules(unwrap(Dest), unwrap(Src), - Mode, OutMessages? &Messages : nullptr); - if (OutMessages) - *OutMessages = strdup(Messages.c_str()); + LLVMBool Result = Linker::LinkModules(unwrap(Dest), unwrap(Src), Mode); return Result; } diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp index a87610422c2..b54ea2387b3 100644 --- a/tools/bugpoint/BugDriver.cpp +++ b/tools/bugpoint/BugDriver.cpp @@ -126,13 +126,8 @@ bool BugDriver::addSources(const std::vector &Filenames) { if (!M.get()) return true; outs() << "Linking in input file: '" << Filenames[i] << "'\n"; - std::string ErrorMessage; - if (Linker::LinkModules(Program, M.get(), Linker::DestroySource, - &ErrorMessage)) { - errs() << ToolName << ": error linking in '" << Filenames[i] << "': " - << ErrorMessage << '\n'; + if (Linker::LinkModules(Program, M.get(), Linker::DestroySource)) return true; - } } outs() << "*** All input ok\n"; diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 01624208612..ce16d4d18af 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -218,16 +218,12 @@ static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2, bool DeleteInputs, std::string &Error, bool &Broken) { // Link the two portions of the program back to together. - std::string ErrorMsg; if (!DeleteInputs) { M1 = CloneModule(M1); M2 = CloneModule(M2); } - if (Linker::LinkModules(M1, M2, Linker::DestroySource, &ErrorMsg)) { - errs() << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; + if (Linker::LinkModules(M1, M2, Linker::DestroySource)) exit(1); - } delete M2; // We are done with this module. // Execute the program. @@ -396,13 +392,9 @@ static bool ExtractLoops(BugDriver &BD, F->getFunctionType())); } - std::string ErrorMsg; - if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, - Linker::DestroySource, &ErrorMsg)){ - errs() << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; + if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, + Linker::DestroySource)) exit(1); - } MiscompiledFunctions.clear(); for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) { @@ -430,13 +422,10 @@ static bool ExtractLoops(BugDriver &BD, // extraction both didn't break the program, and didn't mask the problem. // Replace the current program with the loop extracted version, and try to // extract another loop. - std::string ErrorMsg; - if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, - Linker::DestroySource, &ErrorMsg)){ - errs() << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; + if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, + Linker::DestroySource)) exit(1); - } + delete ToOptimizeLoopExtracted; // All of the Function*'s in the MiscompiledFunctions list are in the old @@ -612,13 +601,8 @@ static bool ExtractBlocks(BugDriver &BD, MisCompFunctions.push_back(std::make_pair(I->getName(), I->getFunctionType())); - std::string ErrorMsg; - if (Linker::LinkModules(ProgClone, Extracted.get(), Linker::DestroySource, - &ErrorMsg)) { - errs() << BD.getToolName() << ": Error linking modules together:" - << ErrorMsg << '\n'; + if (Linker::LinkModules(ProgClone, Extracted.get(), Linker::DestroySource)) exit(1); - } // Set the new program and delete the old one. BD.setNewProgram(ProgClone); diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 2d50f49ffd7..cc0e9f35661 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -777,9 +777,8 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) { M->setTargetTriple(DefaultTriple); } - std::string ErrMsg; - if (L.linkInModule(M.get(), &ErrMsg)) - message(LDPL_FATAL, "Failed to link module: %s", ErrMsg.c_str()); + if (L.linkInModule(M.get())) + message(LDPL_FATAL, "Failed to link module"); } for (const auto &Name : Internalize) { diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index 7c2894baa1b..c4a4e49ba74 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -14,6 +14,8 @@ #include "llvm/Linker/Linker.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" @@ -69,6 +71,25 @@ loadFile(const char *argv0, const std::string &FN, LLVMContext &Context) { return Result; } +static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) { + unsigned Severity = DI.getSeverity(); + switch (Severity) { + case DS_Error: + errs() << "ERROR: "; + case DS_Warning: + if (SuppressWarnings) + return; + errs() << "WARNING: "; + break; + case DS_Remark: + case DS_Note: + llvm_unreachable("Only expecting warnings and errors"); + } + + DiagnosticPrinterRawOStream DP(errs()); + DI.print(DP); +} + int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); @@ -79,9 +100,9 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); auto Composite = make_unique("llvm-link", Context); - Linker L(Composite.get(), SuppressWarnings); + Linker L(Composite.get()); - std::string ErrorMessage; + Context.setDiagnosticHandler(diagnosticHandler); for (unsigned i = 0; i < InputFilenames.size(); ++i) { std::unique_ptr M = loadFile(argv[0], InputFilenames[i], Context); if (!M.get()) { @@ -91,11 +112,8 @@ int main(int argc, char **argv) { if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n"; - if (L.linkInModule(M.get(), &ErrorMessage)) { - errs() << argv[0] << ": link error in '" << InputFilenames[i] - << "': " << ErrorMessage << "\n"; + if (L.linkInModule(M.get())) return 1; - } } if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite; diff --git a/tools/llvm-lto/llvm-lto.cpp b/tools/llvm-lto/llvm-lto.cpp index 2bfd9594555..0910df14203 100644 --- a/tools/llvm-lto/llvm-lto.cpp +++ b/tools/llvm-lto/llvm-lto.cpp @@ -143,12 +143,8 @@ int main(int argc, char **argv) { return 1; } - - if (!CodeGen.addModule(Module.get(), error)) { - errs() << argv[0] << ": error adding file '" << InputFilenames[i] - << "': " << error << "\n"; + if (!CodeGen.addModule(Module.get())) return 1; - } unsigned NumSyms = Module->getSymbolCount(); for (unsigned I = 0; I < NumSyms; ++I) { diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index 5732996a160..3389425915d 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -205,7 +205,7 @@ lto_code_gen_t lto_codegen_create(void) { void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); } bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) { - return !unwrap(cg)->addModule(unwrap(mod), sLastErrorString); + return !unwrap(cg)->addModule(unwrap(mod)); } bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) { diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp index 4ccced195d2..540849ec6a8 100644 --- a/unittests/Linker/LinkModulesTest.cpp +++ b/unittests/Linker/LinkModulesTest.cpp @@ -88,7 +88,7 @@ TEST_F(LinkModuleTest, BlockAddress) { Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx))); Module *LinkedModule = new Module("MyModuleLinked", Ctx); - Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, nullptr); + Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource); // Delete the original module. M.reset(); @@ -143,11 +143,11 @@ TEST_F(LinkModuleTest, EmptyModule) { GV->setInitializer(ConstantStruct::get(STy, F)); Module *EmptyM = new Module("EmptyModule1", Ctx); - Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource, nullptr); + Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource); delete EmptyM; EmptyM = new Module("EmptyModule2", Ctx); - Linker::LinkModules(InternalM, EmptyM, Linker::PreserveSource, nullptr); + Linker::LinkModules(InternalM, EmptyM, Linker::PreserveSource); delete EmptyM; delete InternalM;