diff options
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 25 | ||||
-rw-r--r-- | lib/VMCore/Function.cpp | 8 | ||||
-rw-r--r-- | lib/VMCore/Linker.cpp | 125 | ||||
-rw-r--r-- | lib/VMCore/Module.cpp | 7 |
4 files changed, 101 insertions, 64 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 958980bad6..c55a87515c 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -535,8 +535,15 @@ void AssemblyWriter::printModule(const Module *M) { void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->hasName()) Out << "%" << GV->getName() << " = "; - if (GV->hasInternalLinkage()) Out << "internal "; - if (!GV->hasInitializer()) Out << "external "; + if (!GV->hasInitializer()) + Out << "external "; + else + switch (GV->getLinkage()) { + case GlobalValue::InternalLinkage: Out << "internal "; break; + case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::AppendingLinkage: Out << "appending "; break; + case GlobalValue::ExternalLinkage: break; + } Out << (GV->isConstant() ? "constant " : "global "); printType(GV->getType()->getElementType()); @@ -594,8 +601,18 @@ void AssemblyWriter::printConstant(const Constant *CPV) { // void AssemblyWriter::printFunction(const Function *F) { // Print out the return type and name... - Out << "\n" << (F->isExternal() ? "declare " : "") - << (F->hasInternalLinkage() ? "internal " : ""); + Out << "\n"; + + if (F->isExternal()) + Out << "declare "; + else + switch (F->getLinkage()) { + case GlobalValue::InternalLinkage: Out << "internal "; break; + case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::AppendingLinkage: Out << "appending "; break; + case GlobalValue::ExternalLinkage: break; + } + printType(F->getReturnType()) << " %" << F->getName() << "("; Table.incorporateFunction(F); diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 70569c0f67..3324565654 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -77,9 +77,9 @@ void Argument::setParent(Function *parent) { // Function Implementation //===----------------------------------------------------------------------===// -Function::Function(const FunctionType *Ty, bool isInternal, +Function::Function(const FunctionType *Ty, LinkageTypes Linkage, const std::string &name, Module *ParentModule) - : GlobalValue(PointerType::get(Ty), Value::FunctionVal, isInternal, name) { + : GlobalValue(PointerType::get(Ty), Value::FunctionVal, Linkage, name) { BasicBlocks.setItemParent(this); BasicBlocks.setParent(this); ArgumentList.setItemParent(this); @@ -154,10 +154,10 @@ void Function::dropAllReferences() { // GlobalVariable Implementation //===----------------------------------------------------------------------===// -GlobalVariable::GlobalVariable(const Type *Ty, bool constant, bool isIntern, +GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link, Constant *Initializer, const std::string &Name, Module *ParentModule) - : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal, isIntern, Name), + : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal, Link, Name), isConstantGlobal(constant) { if (Initializer) Operands.push_back(Use((Value*)Initializer, this)); diff --git a/lib/VMCore/Linker.cpp b/lib/VMCore/Linker.cpp index 60c6e03ae1..b5207a8542 100644 --- a/lib/VMCore/Linker.cpp +++ b/lib/VMCore/Linker.cpp @@ -189,42 +189,48 @@ static bool LinkGlobals(Module *Dest, const Module *Src, // for (Module::const_giterator I = Src->gbegin(), E = Src->gend(); I != E; ++I){ const GlobalVariable *SGV = I; - Value *V; - - // 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... - // - if (SGV->hasExternalLinkage() && SGV->hasName() && - (V = ST->lookup(SGV->getType(), SGV->getName())) && - cast<GlobalVariable>(V)->hasExternalLinkage()) { - // The same named thing is a global variable, because the only two things + GlobalVariable *DGV = 0; + if (SGV->hasName()) { + // A same named thing is a global variable, because the only two things // that may be in a module level symbol table are Global Vars and // Functions, and they both have distinct, nonoverlapping, possible types. // - GlobalVariable *DGV = cast<GlobalVariable>(V); + DGV = cast_or_null<GlobalVariable>(ST->lookup(SGV->getType(), + SGV->getName())); + } - // Check to see if the two GV's have the same Const'ness... - if (SGV->isConstant() != DGV->isConstant()) - return Error(Err, "Global Variable Collision on '" + - SGV->getType()->getDescription() + "':%" + SGV->getName() + - " - Global variables differ in const'ness"); + assert(SGV->hasInitializer() || SGV->hasExternalLinkage() && + "Global must either be external or have an initializer!"); - // Okay, everything is cool, remember the mapping... - ValueMap.insert(std::make_pair(SGV, DGV)); - } else { + if (!DGV || DGV->hasInternalLinkage() || SGV->hasInternalLinkage()) { // No linking to be performed, simply create an identical version of the // symbol over in the dest module... the initializer will be filled in // later by LinkGlobalInits... // - GlobalVariable *DGV = - new GlobalVariable(SGV->getType()->getElementType(), SGV->isConstant(), - SGV->hasInternalLinkage(), 0, SGV->getName()); - - // Add the new global to the dest module - Dest->getGlobalList().push_back(DGV); + DGV = new GlobalVariable(SGV->getType()->getElementType(), + SGV->isConstant(), SGV->getLinkage(), /*init*/0, + SGV->getName(), Dest); // Make sure to remember this mapping... 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() || SGV->hasLinkOnceLinkage() || + SGV->hasAppendingLinkage()) { + // 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()) + return Error(Err, "Global Variable Collision on '" + + SGV->getType()->getDescription() + "':%" + SGV->getName() + + " - Global variables differ in const'ness"); + // Okay, everything is cool, remember the mapping... + ValueMap.insert(std::make_pair(SGV, DGV)); + } else { + assert(0 && "Unknown linkage!"); } } return false; @@ -245,19 +251,28 @@ static bool LinkGlobalInits(Module *Dest, const Module *Src, if (SGV->hasInitializer()) { // Only process initialized GV's // Figure out what the initializer looks like in the dest module... - Constant *DInit = + Constant *SInit = cast<Constant>(RemapOperand(SGV->getInitializer(), ValueMap, 0)); GlobalVariable *DGV = cast<GlobalVariable>(ValueMap[SGV]); - if (DGV->hasInitializer() && SGV->hasExternalLinkage() && - DGV->hasExternalLinkage()) { - if (DGV->getInitializer() != DInit) - return Error(Err, "Global Variable Collision on '" + - SGV->getType()->getDescription() + "':%" +SGV->getName()+ - " - Global variables have different initializers"); + if (DGV->hasInitializer()) { + assert(SGV->getLinkage() == DGV->getLinkage()); + if (SGV->hasExternalLinkage()) { + if (DGV->getInitializer() != SInit) + return Error(Err, "Global Variable Collision on '" + + SGV->getType()->getDescription() +"':%"+SGV->getName()+ + " - Global variables have different initializers"); + } else if (DGV->hasLinkOnceLinkage()) { + // Nothing is required, mapped values will take the new global + // automatically. + } else if (DGV->hasAppendingLinkage()) { + assert(0 && "Appending linkage unimplemented!"); + } else { + assert(0 && "Unknown linkage!"); + } } else { // Copy the initializer over now... - DGV->setInitializer(DInit); + DGV->setInitializer(SInit); } } } @@ -278,39 +293,42 @@ static bool LinkFunctionProtos(Module *Dest, const Module *Src, // for (Module::const_iterator I = Src->begin(), E = Src->end(); I != E; ++I) { const Function *SF = I; // SrcFunction - Value *V; - - // If the function has a name, and that name is already in use in the Dest - // module, make sure that the name is a compatible function... - // - if (SF->hasExternalLinkage() && SF->hasName() && - (V = ST->lookup(SF->getType(), SF->getName())) && - cast<Function>(V)->hasExternalLinkage()) { + Function *DF = 0; + if (SF->hasName()) // The same named thing is a Function, because the only two things // that may be in a module level symbol table are Global Vars and // Functions, and they both have distinct, nonoverlapping, possible types. // - Function *DF = cast<Function>(V); // DestFunction + DF = cast_or_null<Function>(ST->lookup(SF->getType(), SF->getName())); + if (!DF || SF->hasInternalLinkage() || DF->hasInternalLinkage()) { + // Function does not already exist, simply insert an external function + // signature identical to SF into the dest module... + Function *DF = new Function(SF->getFunctionType(), SF->getLinkage(), + SF->getName(), Dest); + + // ... and remember this mapping... + ValueMap.insert(std::make_pair(SF, DF)); + } else if (SF->getLinkage() != DF->getLinkage()) { + return Error(Err, "Functions named '" + SF->getName() + + "' have different linkage specifiers!"); + } else if (SF->getLinkage() == GlobalValue::AppendingLinkage) { + return Error(Err, "Functions named '" + SF->getName() + + "' have appending linkage!"); + } else if (SF->getLinkage() == GlobalValue::ExternalLinkage) { + // If the function has a name, and that name is already in use in the Dest + // module, make sure that the name is a compatible function... + // // Check to make sure the function is not defined in both modules... if (!SF->isExternal() && !DF->isExternal()) return Error(Err, "Function '" + SF->getFunctionType()->getDescription() + "':\"" + SF->getName() + "\" - Function is already defined!"); - + // Otherwise, just remember this mapping... ValueMap.insert(std::make_pair(SF, DF)); - } else { - // Function does not already exist, simply insert an external function - // signature identical to SF into the dest module... - Function *DF = new Function(SF->getFunctionType(), - SF->hasInternalLinkage(), - SF->getName()); - - // Add the function signature to the dest module... - Dest->getFunctionList().push_back(DF); - - // ... and remember this mapping... + } else if (SF->getLinkage() == GlobalValue::LinkOnceLinkage) { + // Completely ignore the source function. ValueMap.insert(std::make_pair(SF, DF)); } } @@ -391,6 +409,7 @@ static bool LinkFunctionBodies(Module *Dest, const Module *Src, // 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!"; diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp index f54a6f390b..e0a6fb271c 100644 --- a/lib/VMCore/Module.cpp +++ b/lib/VMCore/Module.cpp @@ -17,13 +17,14 @@ Function *ilist_traits<Function>::createNode() { FunctionType *FTy = FunctionType::get(Type::VoidTy, std::vector<const Type*>(), false); - Function *Ret = new Function(FTy, false); + Function *Ret = new Function(FTy, GlobalValue::ExternalLinkage); // This should not be garbage monitored. LeakDetector::removeGarbageObject(Ret); return Ret; } GlobalVariable *ilist_traits<GlobalVariable>::createNode() { - GlobalVariable *Ret = new GlobalVariable(Type::IntTy, false, false); + GlobalVariable *Ret = new GlobalVariable(Type::IntTy, false, + GlobalValue::ExternalLinkage); // This should not be garbage monitored. LeakDetector::removeGarbageObject(Ret); return Ret; @@ -87,7 +88,7 @@ Function *Module::getOrInsertFunction(const std::string &Name, if (Value *V = SymTab.lookup(PointerType::get(Ty), Name)) { return cast<Function>(V); // Yup, got it } else { // Nope, add one - Function *New = new Function(Ty, false, Name); + Function *New = new Function(Ty, GlobalVariable::ExternalLinkage, Name); FunctionList.push_back(New); return New; // Return the new prototype... } |