unsigned Mode; // Mode to treat source module.
- struct LazyLinkEntry {
- Function *Fn;
- llvm::SmallPtrSet<User*, 4> Uses;
- };
-
// Set of items not to link in from source.
SmallPtrSet<const Value*, 16> DoNotLinkFromSource;
// Vector of functions to lazily link in.
- std::vector<LazyLinkEntry> LazilyLinkFunctions;
+ std::vector<Function*> LazilyLinkFunctions;
public:
std::string ErrorMsg;
}
}
- // If the function is to be lazily linked, don't create it just yet.
- // Instead, remember its current set of uses to diff against later.
- if (!DGV && (SF->hasLocalLinkage() || SF->hasLinkOnceLinkage() ||
- SF->hasAvailableExternallyLinkage())) {
- LazyLinkEntry LLE;
- LLE.Fn = SF;
- LLE.Uses.insert(SF->use_begin(), SF->use_end());
- LazilyLinkFunctions.push_back(LLE);
- DoNotLinkFromSource.insert(SF);
- return false;
- }
-
// If there is no linkage to be performed or we are linking from the source,
// bring SF over.
Function *NewDF = Function::Create(TypeMap.get(SF->getFunctionType()),
// 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;
do {
LinkedInAnyFunctions = false;
- for(std::vector<LazyLinkEntry>::iterator I = LazilyLinkFunctions.begin(),
- E = LazilyLinkFunctions.end(); I != E; ++I) {
- Function *SF = I->Fn;
- if (!SF)
+ for(std::vector<Function*>::iterator I = LazilyLinkFunctions.begin(),
+ E = LazilyLinkFunctions.end(); I != E; ++I) {
+ if (!*I)
continue;
- // If the number of uses of this function is the same as it was at the
- // start of the link, it is not used in this link.
- if (SF->getNumUses() != I->Uses.size()) {
- Function *DF = Function::Create(TypeMap.get(SF->getFunctionType()),
- SF->getLinkage(), SF->getName(), DstM);
- copyGVAttributes(DF, SF);
-
- // Now, copy over any uses of SF that were from DstM to DF.
- for (Function::use_iterator UI = SF->use_begin(), UE = SF->use_end();
- UI != UE;) {
- if (I->Uses.count(*UI) == 0) {
- Use &U = UI.getUse();
- // Increment UI before performing the set to ensure the iterator
- // remains valid.
- ++UI;
- U.set(DF);
- } else {
- ++UI;
- }
- }
-
+ Function *SF = *I;
+ Function *DF = cast<Function>(ValueMap[SF]);
+
+ if (!DF->use_empty()) {
+
// Materialize if necessary.
if (SF->isDeclaration()) {
if (!SF->isMaterializable())
SF->Dematerialize();
// "Remove" from vector by setting the element to 0.
- I->Fn = 0;
+ *I = 0;
// Set flag to indicate we may have more functions to lazily link in
// since we linked in a function.
}
} 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();