//===- Linker.cpp - Module Linker Implementation --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
//
// This file implements the LLVM module linker.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/Linker.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
-#include "llvm/DerivedTypes.h"
#include "llvm/iOther.h"
-#include "llvm/Constants.h"
+#include "llvm/Assembly/Writer.h"
+
+namespace llvm {
// Error - Simple wrapper function to conditionally assign to E and return true.
// This just makes error return conditions a little bit simpler...
return true;
}
-// ResolveTypes - Attempt to link the two specified types together. Return true
-// if there is an error and they cannot yet be linked.
+//
+// Function: ResolveTypes()
+//
+// Description:
+// Attempt to link the two specified types together.
+//
+// Inputs:
+// DestTy - The type to which we wish to resolve.
+// SrcTy - The original type which we want to resolve.
+// Name - The name of the type.
+//
+// Outputs:
+// DestST - The symbol table in which the new type should be placed.
+//
+// Return value:
+// true - There is an error and the types cannot yet be linked.
+// false - No errors.
//
static bool ResolveTypes(const Type *DestTy, const Type *SrcTy,
SymbolTable *DestST, const std::string &Name) {
}
// If we STILL cannot resolve the types, then there is something wrong.
- // Report the error.
+ // Report the warning and delete one of the names.
if (DelayedTypesToResolve.size() == OldSize) {
- // Build up an error message of all of the mismatched types.
- std::string ErrorMessage;
- for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) {
- const std::string &Name = DelayedTypesToResolve[i];
- const Type *T1 = cast<Type>(VM.find(Name)->second);
- const Type *T2 = cast<Type>(DestST->lookup(Type::TypeTy, Name));
- ErrorMessage += " Type named '" + Name +
- "' conflicts.\n Src='" + T1->getDescription() +
- "'.\n Dest='" + T2->getDescription() + "'\n";
- }
- return Error(Err, "Type conflict between types in modules:\n" +
- ErrorMessage);
+ const std::string &Name = DelayedTypesToResolve.back();
+
+ const Type *T1 = cast<Type>(VM.find(Name)->second);
+ const Type *T2 = cast<Type>(DestST->lookup(Type::TypeTy, Name));
+ std::cerr << "WARNING: Type conflict between types named '" << Name
+ << "'.\n Src='";
+ WriteTypeSymbolic(std::cerr, T1, Src);
+ std::cerr << "'.\n Dest='";
+ WriteTypeSymbolic(std::cerr, T2, Dest);
+ std::cerr << "'\n";
+
+ // Remove the symbol name from the destination.
+ DelayedTypesToResolve.pop_back();
}
}
}
assert(CE->getOpcode() == Instruction::Cast);
Value *V = RemapOperand(CE->getOperand(0), LocalMap, GlobalMap);
Result = ConstantExpr::getCast(cast<Constant>(V), CE->getType());
+ } else if (CE->getOpcode() == Instruction::Shl ||
+ CE->getOpcode() == Instruction::Shr) { // Shift
+ Value *V1 = RemapOperand(CE->getOperand(0), LocalMap, GlobalMap);
+ Value *V2 = RemapOperand(CE->getOperand(1), LocalMap, GlobalMap);
+ Result = ConstantExpr::getShift(CE->getOpcode(), cast<Constant>(V1),
+ cast<Constant>(V2));
} else if (CE->getNumOperands() == 2) {
// Binary operator...
Value *V1 = RemapOperand(CE->getOperand(0), LocalMap, GlobalMap);
Value *V2 = RemapOperand(CE->getOperand(1), LocalMap, GlobalMap);
Result = ConstantExpr::get(CE->getOpcode(), cast<Constant>(V1),
- cast<Constant>(V2));
+ cast<Constant>(V2));
} else {
assert(0 && "Unknown constant expr type!");
}
for (SymbolTable::iterator I = ST->begin(), E = ST->end(); I != E; ++I)
if (I->first != Type::TypeTy) {
SymbolTable::VarMap &VM = I->second;
+
// Does this type plane contain an entry with the specified name?
SymbolTable::type_iterator TI = VM.find(Name);
if (TI != VM.end()) {
+ //
+ // Ensure that this type if placed correctly into the symbol table.
+ //
+ assert(TI->second->getType() == I->first && "Type conflict!");
+
+ //
+ // Save a reference to the new type. Resolving the type can modify the
+ // symbol table, invalidating the TI variable.
+ //
+ Value *ValPtr = TI->second;
+
+ //
// Determine whether we can fold the two types together, resolving them.
// If so, we can use this value.
+ //
if (!RecursiveResolveTypes(Ty, I->first, ST, ""))
- return cast<GlobalValue>(TI->second);
+ return cast<GlobalValue>(ValPtr);
}
}
return 0; // Otherwise, nothing could be found.
} else if (DGV->isExternal()) { // If DGV is external but SGV is not...
ValueMap.insert(std::make_pair(SGV, DGV));
DGV->setLinkage(SGV->getLinkage()); // Inherit linkage!
+ } else if (SGV->hasWeakLinkage() || SGV->hasLinkOnceLinkage()) {
+ // At this point we know that DGV has LinkOnce, Appending, Weak, or
+ // External linkage. If DGV is Appending, this is an error.
+ if (DGV->hasAppendingLinkage())
+ return Error(Err, "Linking globals named '" + SGV->getName() +
+ " ' with 'weak' and 'appending' linkage is not allowed!");
+
+ if (SGV->isConstant() != DGV->isConstant())
+ return Error(Err, "Global Variable Collision on '" +
+ SGV->getType()->getDescription() + " %" + SGV->getName() +
+ "' - Global variables differ in const'ness");
+
+ // Otherwise, just perform the link.
+ ValueMap.insert(std::make_pair(SGV, DGV));
+
+ // Linkonce+Weak = Weak
+ if (DGV->hasLinkOnceLinkage() && SGV->hasWeakLinkage())
+ DGV->setLinkage(SGV->getLinkage());
+
+ } else if (DGV->hasWeakLinkage() || DGV->hasLinkOnceLinkage()) {
+ // At this point we know that SGV has LinkOnce, Appending, or External
+ // linkage. If SGV is Appending, this is an error.
+ if (SGV->hasAppendingLinkage())
+ return Error(Err, "Linking globals named '" + SGV->getName() +
+ " ' with 'weak' and 'appending' linkage is not allowed!");
+
+ if (SGV->isConstant() != DGV->isConstant())
+ return Error(Err, "Global Variable Collision on '" +
+ SGV->getType()->getDescription() + " %" + SGV->getName() +
+ "' - Global variables differ in const'ness");
+
+ if (!SGV->hasLinkOnceLinkage())
+ DGV->setLinkage(SGV->getLinkage()); // Inherit linkage!
+ ValueMap.insert(std::make_pair(SGV, DGV));
+
} else if (SGV->getLinkage() != DGV->getLinkage()) {
return Error(Err, "Global variables named '" + SGV->getName() +
"' have different linkage specifiers!");
} else if (SGV->hasExternalLinkage()) {
// Allow linking two exactly identical external global variables...
- if (SGV->isConstant() != DGV->isConstant() ||
- SGV->getInitializer() != DGV->getInitializer())
+ if (SGV->isConstant() != DGV->isConstant())
return Error(Err, "Global Variable Collision on '" +
SGV->getType()->getDescription() + " %" + SGV->getName() +
"' - Global variables differ in const'ness");
- ValueMap.insert(std::make_pair(SGV, DGV));
- } else if (SGV->hasLinkOnceLinkage()) {
- // If the global variable has a name, and that name is already in use in
- // the Dest module, make sure that the name is a compatible global
- // variable...
- //
- // Check to see if the two GV's have the same Const'ness...
- if (SGV->isConstant() != DGV->isConstant())
+
+ if (SGV->getInitializer() != DGV->getInitializer())
return Error(Err, "Global Variable Collision on '" +
SGV->getType()->getDescription() + " %" + SGV->getName() +
- "' - Global variables differ in const'ness");
+ "' - External linkage globals have different initializers");
- // Okay, everything is cool, remember the mapping...
ValueMap.insert(std::make_pair(SGV, DGV));
} else if (SGV->hasAppendingLinkage()) {
// No linking is performed yet. Just insert a new copy of the global, and
return Error(Err, "Global Variable Collision on '" +
SGV->getType()->getDescription() +"':%"+SGV->getName()+
" - Global variables have different initializers");
- } else if (DGV->hasLinkOnceLinkage()) {
+ } else if (DGV->hasLinkOnceLinkage() || DGV->hasWeakLinkage()) {
// Nothing is required, mapped values will take the new global
// automatically.
} else if (DGV->hasAppendingLinkage()) {
ValueMap.insert(std::make_pair(SF, DF));
DF->setLinkage(SF->getLinkage());
+ } else if (SF->hasWeakLinkage() || SF->hasLinkOnceLinkage()) {
+ // At this point we know that DF has LinkOnce, Weak, or External linkage.
+ ValueMap.insert(std::make_pair(SF, DF));
+
+ // Linkonce+Weak = Weak
+ if (DF->hasLinkOnceLinkage() && SF->hasWeakLinkage())
+ DF->setLinkage(SF->getLinkage());
+
+ } else if (DF->hasWeakLinkage() || DF->hasLinkOnceLinkage()) {
+ // At this point we know that SF has LinkOnce or External linkage.
+ ValueMap.insert(std::make_pair(SF, DF));
+ if (!SF->hasLinkOnceLinkage()) // Don't inherit linkonce linkage
+ DF->setLinkage(SF->getLinkage());
+
} else if (SF->getLinkage() != DF->getLinkage()) {
return Error(Err, "Functions named '" + SF->getName() +
"' have different linkage specifiers!");
return Error(Err, "Function '" +
SF->getFunctionType()->getDescription() + "':\"" +
SF->getName() + "\" - Function is already defined!");
- } else if (SF->hasLinkOnceLinkage()) {
- // Completely ignore the source function.
- ValueMap.insert(std::make_pair(SF, DF));
} else {
assert(0 && "Unknown linkage configuration found!");
}
Function *DF = cast<Function>(ValueMap[SF]); // Destination function
// DF not external SF external?
- if (!DF->isExternal()) {
- if (DF->hasLinkOnceLinkage()) continue; // No relinkage for link-once!
- if (Err)
- *Err = "Function '" + (SF->hasName() ? SF->getName() :std::string(""))
- + "' body multiply defined!";
- return true;
+ if (DF->isExternal()) {
+ // Only provide the function body if there isn't one already.
+ if (LinkFunctionBody(DF, SF, ValueMap, Err))
+ return true;
}
-
- if (LinkFunctionBody(DF, SF, ValueMap, Err)) return true;
}
}
return false;
return false;
}
+} // End llvm namespace