1 //===- lib/Linker/LinkModules.cpp - Module Linker Implementation ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the LLVM module linker. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LinkDiagnosticInfo.h" 14 #include "llvm-c/Linker.h" 15 #include "llvm/ADT/SetVector.h" 16 #include "llvm/IR/Comdat.h" 17 #include "llvm/IR/DiagnosticPrinter.h" 18 #include "llvm/IR/GlobalValue.h" 19 #include "llvm/IR/LLVMContext.h" 20 #include "llvm/IR/Module.h" 21 #include "llvm/Linker/Linker.h" 22 #include "llvm/Support/Error.h" 23 using namespace llvm; 24 25 namespace { 26 27 /// This is an implementation class for the LinkModules function, which is the 28 /// entrypoint for this file. 29 class ModuleLinker { 30 IRMover &Mover; 31 std::unique_ptr<Module> SrcM; 32 33 SetVector<GlobalValue *> ValuesToLink; 34 35 /// For symbol clashes, prefer those from Src. 36 unsigned Flags; 37 38 /// List of global value names that should be internalized. 39 StringSet<> Internalize; 40 41 /// Function that will perform the actual internalization. The reason for a 42 /// callback is that the linker cannot call internalizeModule without 43 /// creating a circular dependency between IPO and the linker. 44 std::function<void(Module &, const StringSet<> &)> InternalizeCallback; 45 46 /// Used as the callback for lazy linking. 47 /// The mover has just hit GV and we have to decide if it, and other members 48 /// of the same comdat, should be linked. Every member to be linked is passed 49 /// to Add. 50 void addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add); 51 52 bool shouldOverrideFromSrc() { return Flags & Linker::OverrideFromSrc; } 53 bool shouldLinkOnlyNeeded() { return Flags & Linker::LinkOnlyNeeded; } 54 55 bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest, 56 const GlobalValue &Src); 57 58 /// Should we have mover and linker error diag info? 59 bool emitError(const Twine &Message) { 60 SrcM->getContext().diagnose(LinkDiagnosticInfo(DS_Error, Message)); 61 return true; 62 } 63 64 bool getComdatLeader(Module &M, StringRef ComdatName, 65 const GlobalVariable *&GVar); 66 bool computeResultingSelectionKind(StringRef ComdatName, 67 Comdat::SelectionKind Src, 68 Comdat::SelectionKind Dst, 69 Comdat::SelectionKind &Result, 70 bool &LinkFromSrc); 71 std::map<const Comdat *, std::pair<Comdat::SelectionKind, bool>> 72 ComdatsChosen; 73 bool getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &SK, 74 bool &LinkFromSrc); 75 // Keep track of the lazy linked global members of each comdat in source. 76 DenseMap<const Comdat *, std::vector<GlobalValue *>> LazyComdatMembers; 77 78 /// Given a global in the source module, return the global in the 79 /// destination module that is being linked to, if any. 80 GlobalValue *getLinkedToGlobal(const GlobalValue *SrcGV) { 81 Module &DstM = Mover.getModule(); 82 // If the source has no name it can't link. If it has local linkage, 83 // there is no name match-up going on. 84 if (!SrcGV->hasName() || GlobalValue::isLocalLinkage(SrcGV->getLinkage())) 85 return nullptr; 86 87 // Otherwise see if we have a match in the destination module's symtab. 88 GlobalValue *DGV = DstM.getNamedValue(SrcGV->getName()); 89 if (!DGV) 90 return nullptr; 91 92 // If we found a global with the same name in the dest module, but it has 93 // internal linkage, we are really not doing any linkage here. 94 if (DGV->hasLocalLinkage()) 95 return nullptr; 96 97 // Otherwise, we do in fact link to the destination global. 98 return DGV; 99 } 100 101 /// Drop GV if it is a member of a comdat that we are dropping. 102 /// This can happen with COFF's largest selection kind. 103 void dropReplacedComdat(GlobalValue &GV, 104 const DenseSet<const Comdat *> &ReplacedDstComdats); 105 106 bool linkIfNeeded(GlobalValue &GV); 107 108 public: 109 ModuleLinker(IRMover &Mover, std::unique_ptr<Module> SrcM, unsigned Flags, 110 std::function<void(Module &, const StringSet<> &)> 111 InternalizeCallback = {}) 112 : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags), 113 InternalizeCallback(std::move(InternalizeCallback)) {} 114 115 bool run(); 116 }; 117 } 118 119 static GlobalValue::VisibilityTypes 120 getMinVisibility(GlobalValue::VisibilityTypes A, 121 GlobalValue::VisibilityTypes B) { 122 if (A == GlobalValue::HiddenVisibility || B == GlobalValue::HiddenVisibility) 123 return GlobalValue::HiddenVisibility; 124 if (A == GlobalValue::ProtectedVisibility || 125 B == GlobalValue::ProtectedVisibility) 126 return GlobalValue::ProtectedVisibility; 127 return GlobalValue::DefaultVisibility; 128 } 129 130 bool ModuleLinker::getComdatLeader(Module &M, StringRef ComdatName, 131 const GlobalVariable *&GVar) { 132 const GlobalValue *GVal = M.getNamedValue(ComdatName); 133 if (const auto *GA = dyn_cast_or_null<GlobalAlias>(GVal)) { 134 GVal = GA->getBaseObject(); 135 if (!GVal) 136 // We cannot resolve the size of the aliasee yet. 137 return emitError("Linking COMDATs named '" + ComdatName + 138 "': COMDAT key involves incomputable alias size."); 139 } 140 141 GVar = dyn_cast_or_null<GlobalVariable>(GVal); 142 if (!GVar) 143 return emitError( 144 "Linking COMDATs named '" + ComdatName + 145 "': GlobalVariable required for data dependent selection!"); 146 147 return false; 148 } 149 150 bool ModuleLinker::computeResultingSelectionKind(StringRef ComdatName, 151 Comdat::SelectionKind Src, 152 Comdat::SelectionKind Dst, 153 Comdat::SelectionKind &Result, 154 bool &LinkFromSrc) { 155 Module &DstM = Mover.getModule(); 156 // The ability to mix Comdat::SelectionKind::Any with 157 // Comdat::SelectionKind::Largest is a behavior that comes from COFF. 158 bool DstAnyOrLargest = Dst == Comdat::SelectionKind::Any || 159 Dst == Comdat::SelectionKind::Largest; 160 bool SrcAnyOrLargest = Src == Comdat::SelectionKind::Any || 161 Src == Comdat::SelectionKind::Largest; 162 if (DstAnyOrLargest && SrcAnyOrLargest) { 163 if (Dst == Comdat::SelectionKind::Largest || 164 Src == Comdat::SelectionKind::Largest) 165 Result = Comdat::SelectionKind::Largest; 166 else 167 Result = Comdat::SelectionKind::Any; 168 } else if (Src == Dst) { 169 Result = Dst; 170 } else { 171 return emitError("Linking COMDATs named '" + ComdatName + 172 "': invalid selection kinds!"); 173 } 174 175 switch (Result) { 176 case Comdat::SelectionKind::Any: 177 // Go with Dst. 178 LinkFromSrc = false; 179 break; 180 case Comdat::SelectionKind::NoDeduplicate: { 181 const GlobalVariable *DstGV; 182 const GlobalVariable *SrcGV; 183 if (getComdatLeader(DstM, ComdatName, DstGV) || 184 getComdatLeader(*SrcM, ComdatName, SrcGV)) 185 return true; 186 187 if (SrcGV->isWeakForLinker()) { 188 // Go with Dst. 189 LinkFromSrc = false; 190 } else if (DstGV->isWeakForLinker()) { 191 // Go with Src. 192 LinkFromSrc = true; 193 } else { 194 return emitError("Linking COMDATs named '" + ComdatName + 195 "': nodeduplicate has been violated!"); 196 } 197 break; 198 } 199 case Comdat::SelectionKind::ExactMatch: 200 case Comdat::SelectionKind::Largest: 201 case Comdat::SelectionKind::SameSize: { 202 const GlobalVariable *DstGV; 203 const GlobalVariable *SrcGV; 204 if (getComdatLeader(DstM, ComdatName, DstGV) || 205 getComdatLeader(*SrcM, ComdatName, SrcGV)) 206 return true; 207 208 const DataLayout &DstDL = DstM.getDataLayout(); 209 const DataLayout &SrcDL = SrcM->getDataLayout(); 210 uint64_t DstSize = DstDL.getTypeAllocSize(DstGV->getValueType()); 211 uint64_t SrcSize = SrcDL.getTypeAllocSize(SrcGV->getValueType()); 212 if (Result == Comdat::SelectionKind::ExactMatch) { 213 if (SrcGV->getInitializer() != DstGV->getInitializer()) 214 return emitError("Linking COMDATs named '" + ComdatName + 215 "': ExactMatch violated!"); 216 LinkFromSrc = false; 217 } else if (Result == Comdat::SelectionKind::Largest) { 218 LinkFromSrc = SrcSize > DstSize; 219 } else if (Result == Comdat::SelectionKind::SameSize) { 220 if (SrcSize != DstSize) 221 return emitError("Linking COMDATs named '" + ComdatName + 222 "': SameSize violated!"); 223 LinkFromSrc = false; 224 } else { 225 llvm_unreachable("unknown selection kind"); 226 } 227 break; 228 } 229 } 230 231 return false; 232 } 233 234 bool ModuleLinker::getComdatResult(const Comdat *SrcC, 235 Comdat::SelectionKind &Result, 236 bool &LinkFromSrc) { 237 Module &DstM = Mover.getModule(); 238 Comdat::SelectionKind SSK = SrcC->getSelectionKind(); 239 StringRef ComdatName = SrcC->getName(); 240 Module::ComdatSymTabType &ComdatSymTab = DstM.getComdatSymbolTable(); 241 Module::ComdatSymTabType::iterator DstCI = ComdatSymTab.find(ComdatName); 242 243 if (DstCI == ComdatSymTab.end()) { 244 // Use the comdat if it is only available in one of the modules. 245 LinkFromSrc = true; 246 Result = SSK; 247 return false; 248 } 249 250 const Comdat *DstC = &DstCI->second; 251 Comdat::SelectionKind DSK = DstC->getSelectionKind(); 252 return computeResultingSelectionKind(ComdatName, SSK, DSK, Result, 253 LinkFromSrc); 254 } 255 256 bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc, 257 const GlobalValue &Dest, 258 const GlobalValue &Src) { 259 260 // Should we unconditionally use the Src? 261 if (shouldOverrideFromSrc()) { 262 LinkFromSrc = true; 263 return false; 264 } 265 266 // We always have to add Src if it has appending linkage. 267 if (Src.hasAppendingLinkage() || Dest.hasAppendingLinkage()) { 268 LinkFromSrc = true; 269 return false; 270 } 271 272 bool SrcIsDeclaration = Src.isDeclarationForLinker(); 273 bool DestIsDeclaration = Dest.isDeclarationForLinker(); 274 275 if (SrcIsDeclaration) { 276 // If Src is external or if both Src & Dest are external.. Just link the 277 // external globals, we aren't adding anything. 278 if (Src.hasDLLImportStorageClass()) { 279 // If one of GVs is marked as DLLImport, result should be dllimport'ed. 280 LinkFromSrc = DestIsDeclaration; 281 return false; 282 } 283 // If the Dest is weak, use the source linkage. 284 if (Dest.hasExternalWeakLinkage()) { 285 LinkFromSrc = true; 286 return false; 287 } 288 // Link an available_externally over a declaration. 289 LinkFromSrc = !Src.isDeclaration() && Dest.isDeclaration(); 290 return false; 291 } 292 293 if (DestIsDeclaration) { 294 // If Dest is external but Src is not: 295 LinkFromSrc = true; 296 return false; 297 } 298 299 if (Src.hasCommonLinkage()) { 300 if (Dest.hasLinkOnceLinkage() || Dest.hasWeakLinkage()) { 301 LinkFromSrc = true; 302 return false; 303 } 304 305 if (!Dest.hasCommonLinkage()) { 306 LinkFromSrc = false; 307 return false; 308 } 309 310 const DataLayout &DL = Dest.getParent()->getDataLayout(); 311 uint64_t DestSize = DL.getTypeAllocSize(Dest.getValueType()); 312 uint64_t SrcSize = DL.getTypeAllocSize(Src.getValueType()); 313 LinkFromSrc = SrcSize > DestSize; 314 return false; 315 } 316 317 if (Src.isWeakForLinker()) { 318 assert(!Dest.hasExternalWeakLinkage()); 319 assert(!Dest.hasAvailableExternallyLinkage()); 320 321 if (Dest.hasLinkOnceLinkage() && Src.hasWeakLinkage()) { 322 LinkFromSrc = true; 323 return false; 324 } 325 326 LinkFromSrc = false; 327 return false; 328 } 329 330 if (Dest.isWeakForLinker()) { 331 assert(Src.hasExternalLinkage()); 332 LinkFromSrc = true; 333 return false; 334 } 335 336 assert(!Src.hasExternalWeakLinkage()); 337 assert(!Dest.hasExternalWeakLinkage()); 338 assert(Dest.hasExternalLinkage() && Src.hasExternalLinkage() && 339 "Unexpected linkage type!"); 340 return emitError("Linking globals named '" + Src.getName() + 341 "': symbol multiply defined!"); 342 } 343 344 bool ModuleLinker::linkIfNeeded(GlobalValue &GV) { 345 GlobalValue *DGV = getLinkedToGlobal(&GV); 346 347 if (shouldLinkOnlyNeeded()) { 348 // Always import variables with appending linkage. 349 if (!GV.hasAppendingLinkage()) { 350 // Don't import globals unless they are referenced by the destination 351 // module. 352 if (!DGV) 353 return false; 354 // Don't import globals that are already defined in the destination module 355 if (!DGV->isDeclaration()) 356 return false; 357 } 358 } 359 360 if (DGV && !GV.hasLocalLinkage() && !GV.hasAppendingLinkage()) { 361 auto *DGVar = dyn_cast<GlobalVariable>(DGV); 362 auto *SGVar = dyn_cast<GlobalVariable>(&GV); 363 if (DGVar && SGVar) { 364 if (DGVar->isDeclaration() && SGVar->isDeclaration() && 365 (!DGVar->isConstant() || !SGVar->isConstant())) { 366 DGVar->setConstant(false); 367 SGVar->setConstant(false); 368 } 369 if (DGVar->hasCommonLinkage() && SGVar->hasCommonLinkage()) { 370 MaybeAlign Align( 371 std::max(DGVar->getAlignment(), SGVar->getAlignment())); 372 SGVar->setAlignment(Align); 373 DGVar->setAlignment(Align); 374 } 375 } 376 377 GlobalValue::VisibilityTypes Visibility = 378 getMinVisibility(DGV->getVisibility(), GV.getVisibility()); 379 DGV->setVisibility(Visibility); 380 GV.setVisibility(Visibility); 381 382 GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::getMinUnnamedAddr( 383 DGV->getUnnamedAddr(), GV.getUnnamedAddr()); 384 DGV->setUnnamedAddr(UnnamedAddr); 385 GV.setUnnamedAddr(UnnamedAddr); 386 } 387 388 if (!DGV && !shouldOverrideFromSrc() && 389 (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() || 390 GV.hasAvailableExternallyLinkage())) 391 return false; 392 393 if (GV.isDeclaration()) 394 return false; 395 396 if (const Comdat *SC = GV.getComdat()) { 397 bool LinkFromSrc; 398 Comdat::SelectionKind SK; 399 std::tie(SK, LinkFromSrc) = ComdatsChosen[SC]; 400 if (!LinkFromSrc) 401 return false; 402 } 403 404 bool LinkFromSrc = true; 405 if (DGV && shouldLinkFromSource(LinkFromSrc, *DGV, GV)) 406 return true; 407 if (LinkFromSrc) 408 ValuesToLink.insert(&GV); 409 return false; 410 } 411 412 void ModuleLinker::addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add) { 413 // Add these to the internalize list 414 if (!GV.hasLinkOnceLinkage() && !GV.hasAvailableExternallyLinkage() && 415 !shouldLinkOnlyNeeded()) 416 return; 417 418 if (InternalizeCallback) 419 Internalize.insert(GV.getName()); 420 Add(GV); 421 422 const Comdat *SC = GV.getComdat(); 423 if (!SC) 424 return; 425 for (GlobalValue *GV2 : LazyComdatMembers[SC]) { 426 GlobalValue *DGV = getLinkedToGlobal(GV2); 427 bool LinkFromSrc = true; 428 if (DGV && shouldLinkFromSource(LinkFromSrc, *DGV, *GV2)) 429 return; 430 if (!LinkFromSrc) 431 continue; 432 if (InternalizeCallback) 433 Internalize.insert(GV2->getName()); 434 Add(*GV2); 435 } 436 } 437 438 void ModuleLinker::dropReplacedComdat( 439 GlobalValue &GV, const DenseSet<const Comdat *> &ReplacedDstComdats) { 440 Comdat *C = GV.getComdat(); 441 if (!C) 442 return; 443 if (!ReplacedDstComdats.count(C)) 444 return; 445 if (GV.use_empty()) { 446 GV.eraseFromParent(); 447 return; 448 } 449 450 if (auto *F = dyn_cast<Function>(&GV)) { 451 F->deleteBody(); 452 } else if (auto *Var = dyn_cast<GlobalVariable>(&GV)) { 453 Var->setInitializer(nullptr); 454 } else { 455 auto &Alias = cast<GlobalAlias>(GV); 456 Module &M = *Alias.getParent(); 457 GlobalValue *Declaration; 458 if (auto *FTy = dyn_cast<FunctionType>(Alias.getValueType())) { 459 Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, "", &M); 460 } else { 461 Declaration = 462 new GlobalVariable(M, Alias.getValueType(), /*isConstant*/ false, 463 GlobalValue::ExternalLinkage, 464 /*Initializer*/ nullptr); 465 } 466 Declaration->takeName(&Alias); 467 Alias.replaceAllUsesWith(Declaration); 468 Alias.eraseFromParent(); 469 } 470 } 471 472 bool ModuleLinker::run() { 473 Module &DstM = Mover.getModule(); 474 DenseSet<const Comdat *> ReplacedDstComdats; 475 476 for (const auto &SMEC : SrcM->getComdatSymbolTable()) { 477 const Comdat &C = SMEC.getValue(); 478 if (ComdatsChosen.count(&C)) 479 continue; 480 Comdat::SelectionKind SK; 481 bool LinkFromSrc; 482 if (getComdatResult(&C, SK, LinkFromSrc)) 483 return true; 484 ComdatsChosen[&C] = std::make_pair(SK, LinkFromSrc); 485 486 if (!LinkFromSrc) 487 continue; 488 489 Module::ComdatSymTabType &ComdatSymTab = DstM.getComdatSymbolTable(); 490 Module::ComdatSymTabType::iterator DstCI = ComdatSymTab.find(C.getName()); 491 if (DstCI == ComdatSymTab.end()) 492 continue; 493 494 // The source comdat is replacing the dest one. 495 const Comdat *DstC = &DstCI->second; 496 ReplacedDstComdats.insert(DstC); 497 } 498 499 // Alias have to go first, since we are not able to find their comdats 500 // otherwise. 501 for (auto I = DstM.alias_begin(), E = DstM.alias_end(); I != E;) { 502 GlobalAlias &GV = *I++; 503 dropReplacedComdat(GV, ReplacedDstComdats); 504 } 505 506 for (auto I = DstM.global_begin(), E = DstM.global_end(); I != E;) { 507 GlobalVariable &GV = *I++; 508 dropReplacedComdat(GV, ReplacedDstComdats); 509 } 510 511 for (auto I = DstM.begin(), E = DstM.end(); I != E;) { 512 Function &GV = *I++; 513 dropReplacedComdat(GV, ReplacedDstComdats); 514 } 515 516 for (GlobalVariable &GV : SrcM->globals()) 517 if (GV.hasLinkOnceLinkage()) 518 if (const Comdat *SC = GV.getComdat()) 519 LazyComdatMembers[SC].push_back(&GV); 520 521 for (Function &SF : *SrcM) 522 if (SF.hasLinkOnceLinkage()) 523 if (const Comdat *SC = SF.getComdat()) 524 LazyComdatMembers[SC].push_back(&SF); 525 526 for (GlobalAlias &GA : SrcM->aliases()) 527 if (GA.hasLinkOnceLinkage()) 528 if (const Comdat *SC = GA.getComdat()) 529 LazyComdatMembers[SC].push_back(&GA); 530 531 // Insert all of the globals in src into the DstM module... without linking 532 // initializers (which could refer to functions not yet mapped over). 533 for (GlobalVariable &GV : SrcM->globals()) 534 if (linkIfNeeded(GV)) 535 return true; 536 537 for (Function &SF : *SrcM) 538 if (linkIfNeeded(SF)) 539 return true; 540 541 for (GlobalAlias &GA : SrcM->aliases()) 542 if (linkIfNeeded(GA)) 543 return true; 544 545 for (unsigned I = 0; I < ValuesToLink.size(); ++I) { 546 GlobalValue *GV = ValuesToLink[I]; 547 const Comdat *SC = GV->getComdat(); 548 if (!SC) 549 continue; 550 for (GlobalValue *GV2 : LazyComdatMembers[SC]) { 551 GlobalValue *DGV = getLinkedToGlobal(GV2); 552 bool LinkFromSrc = true; 553 if (DGV && shouldLinkFromSource(LinkFromSrc, *DGV, *GV2)) 554 return true; 555 if (LinkFromSrc) 556 ValuesToLink.insert(GV2); 557 } 558 } 559 560 if (InternalizeCallback) { 561 for (GlobalValue *GV : ValuesToLink) 562 Internalize.insert(GV->getName()); 563 } 564 565 // FIXME: Propagate Errors through to the caller instead of emitting 566 // diagnostics. 567 bool HasErrors = false; 568 if (Error E = Mover.move(std::move(SrcM), ValuesToLink.getArrayRef(), 569 [this](GlobalValue &GV, IRMover::ValueAdder Add) { 570 addLazyFor(GV, Add); 571 }, 572 /* IsPerformingImport */ false)) { 573 handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { 574 DstM.getContext().diagnose(LinkDiagnosticInfo(DS_Error, EIB.message())); 575 HasErrors = true; 576 }); 577 } 578 if (HasErrors) 579 return true; 580 581 if (InternalizeCallback) 582 InternalizeCallback(DstM, Internalize); 583 584 return false; 585 } 586 587 Linker::Linker(Module &M) : Mover(M) {} 588 589 bool Linker::linkInModule( 590 std::unique_ptr<Module> Src, unsigned Flags, 591 std::function<void(Module &, const StringSet<> &)> InternalizeCallback) { 592 ModuleLinker ModLinker(Mover, std::move(Src), Flags, 593 std::move(InternalizeCallback)); 594 return ModLinker.run(); 595 } 596 597 //===----------------------------------------------------------------------===// 598 // LinkModules entrypoint. 599 //===----------------------------------------------------------------------===// 600 601 /// This function links two modules together, with the resulting Dest module 602 /// modified to be the composite of the two input modules. If an error occurs, 603 /// true is returned and ErrorMsg (if not null) is set to indicate the problem. 604 /// Upon failure, the Dest module could be in a modified state, and shouldn't be 605 /// relied on to be consistent. 606 bool Linker::linkModules( 607 Module &Dest, std::unique_ptr<Module> Src, unsigned Flags, 608 std::function<void(Module &, const StringSet<> &)> InternalizeCallback) { 609 Linker L(Dest); 610 return L.linkInModule(std::move(Src), Flags, std::move(InternalizeCallback)); 611 } 612 613 //===----------------------------------------------------------------------===// 614 // C API. 615 //===----------------------------------------------------------------------===// 616 617 LLVMBool LLVMLinkModules2(LLVMModuleRef Dest, LLVMModuleRef Src) { 618 Module *D = unwrap(Dest); 619 std::unique_ptr<Module> M(unwrap(Src)); 620 return Linker::linkModules(*D, std::move(M)); 621 } 622