diff options
-rw-r--r-- | lib/Linker/LinkModules.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index bcc6782..ab099bb 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -341,6 +341,9 @@ namespace { // Set of items not to link in from source. SmallPtrSet<const Value*, 16> DoNotLinkFromSource; + // Vector of functions to lazily link in. + std::vector<Function*> LazilyLinkFunctions; + public: std::string ErrorMsg; @@ -708,6 +711,13 @@ bool ModuleLinker::linkFunctionProto(Function *SF) { // Any uses of DF need to change to NewDF, with cast. DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDF, DGV->getType())); DGV->eraseFromParent(); + } else { + // Internal, LO_ODR, or LO linkage - stick in set to ignore and lazily link. + if (SF->hasLocalLinkage() || SF->hasLinkOnceLinkage() || + SF->hasAvailableExternallyLinkage()) { + DoNotLinkFromSource.insert(SF); + LazilyLinkFunctions.push_back(SF); + } } ValueMap[SF] = NewDF; @@ -974,6 +984,54 @@ bool ModuleLinker::run() { // are properly remapped. linkNamedMDNodes(); + // Process vector of lazily linked in functions. + bool LinkedInAnyFunctions; + do { + LinkedInAnyFunctions = false; + + for(std::vector<Function*>::iterator I = LazilyLinkFunctions.begin(), + E = LazilyLinkFunctions.end(); I != E; ++I) { + if (!*I) + continue; + + Function *SF = *I; + Function *DF = cast<Function>(ValueMap[SF]); + + if (!DF->use_empty()) { + + // Materialize if necessary. + if (SF->isDeclaration()) { + if (!SF->isMaterializable()) + continue; + if (SF->Materialize(&ErrorMsg)) + return true; + } + + // Link in function body. + linkFunctionBody(DF, SF); + + // "Remove" from vector by setting the element to 0. + *I = 0; + + // Set flag to indicate we may have more functions to lazily link in + // since we linked in a function. + LinkedInAnyFunctions = true; + } + } + } while (LinkedInAnyFunctions); + + // Remove any prototypes of functions that were not actually linked in. + for(std::vector<Function*>::iterator I = LazilyLinkFunctions.begin(), + E = LazilyLinkFunctions.end(); I != E; ++I) { + if (!*I) + continue; + + Function *SF = *I; + Function *DF = cast<Function>(ValueMap[SF]); + if (DF->use_empty()) + DF->eraseFromParent(); + } + // Now that all of the types from the source are used, resolve any structs // copied over to the dest that didn't exist there. TypeMap.linkDefinedTypeBodies(); |