From 72ac148d4964fbff950fe11a0eeeda73973b849b Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 16 Oct 2003 18:29:00 +0000 Subject: [PATCH] Add support for 'weak' linkage. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9171 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AsmParser/llvmAsmParser.y | 2 +- lib/Linker/LinkModules.cpp | 37 +++++++++++++++++++++++++++----- lib/Target/CBackend/CBackend.cpp | 4 ++++ lib/Target/CBackend/Writer.cpp | 4 ++++ lib/Target/X86/Printer.cpp | 4 +++- lib/Target/X86/X86AsmPrinter.cpp | 4 +++- lib/Transforms/Utils/Linker.cpp | 37 +++++++++++++++++++++++++++----- lib/VMCore/AsmWriter.cpp | 10 +++++---- lib/VMCore/Linker.cpp | 37 +++++++++++++++++++++++++++----- 9 files changed, 117 insertions(+), 22 deletions(-) diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 3347e8833a4..725f2547573 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -763,7 +763,7 @@ OptAssign : Name '=' { OptLinkage : INTERNAL { $$ = GlobalValue::InternalLinkage; } | LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | - WEAK { $$ = GlobalValue::LinkOnceLinkage; /* FIXME */ } | + WEAK { $$ = GlobalValue::WeakLinkage; } | APPENDING { $$ = GlobalValue::AppendingLinkage; } | /*empty*/ { $$ = GlobalValue::ExternalLinkage; }; diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index aa9a8fcafd4..a71572bd331 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -433,6 +433,24 @@ static bool LinkGlobals(Module *Dest, const Module *Src, } 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()) { + // 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!"); + // Otherwise, just perform the link. + ValueMap.insert(std::make_pair(SGV, DGV)); + } else if (DGV->hasWeakLinkage()) { + // 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->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!"); @@ -505,7 +523,7 @@ static bool LinkGlobalInits(Module *Dest, const Module *Src, 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()) { @@ -574,6 +592,16 @@ static bool LinkFunctionProtos(Module *Dest, const Module *Src, ValueMap.insert(std::make_pair(SF, DF)); DF->setLinkage(SF->getLinkage()); + } else if (SF->hasWeakLinkage()) { + // At this point we know that DF has LinkOnce, Weak, or External linkage. + ValueMap.insert(std::make_pair(SF, DF)); + + } else if (DF->hasWeakLinkage()) { + // 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!"); @@ -667,10 +695,9 @@ 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!"; - return true; + if (SF->hasWeakLinkage()) continue; + return Error(Err, "Function '" + SF->getName() + + "' body multiply defined!"); } if (LinkFunctionBody(DF, SF, ValueMap, Err)) return true; diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index af33e4b85fb..a34f3f77125 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -684,6 +684,8 @@ void CWriter::printModule(Module *M) { printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); if (I->hasLinkOnceLinkage()) Out << " __attribute__((common))"; + else if (I->hasWeakLinkage()) + Out << " __attribute__((weak))"; if (!I->getInitializer()->isNullValue()) { Out << " = " ; writeOperand(I->getInitializer()); @@ -893,6 +895,8 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { FunctionInnards << ")"; // Print out the return type and the entire signature for that matter printType(Out, F->getReturnType(), FunctionInnards.str()); + + if (F->hasWeakLinkage()) Out << " __attribute((weak))"; } void CWriter::printFunction(Function *F) { diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp index af33e4b85fb..a34f3f77125 100644 --- a/lib/Target/CBackend/Writer.cpp +++ b/lib/Target/CBackend/Writer.cpp @@ -684,6 +684,8 @@ void CWriter::printModule(Module *M) { printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); if (I->hasLinkOnceLinkage()) Out << " __attribute__((common))"; + else if (I->hasWeakLinkage()) + Out << " __attribute__((weak))"; if (!I->getInitializer()->isNullValue()) { Out << " = " ; writeOperand(I->getInitializer()); @@ -893,6 +895,8 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { FunctionInnards << ")"; // Print out the return type and the entire signature for that matter printType(Out, F->getReturnType(), FunctionInnards.str()); + + if (F->hasWeakLinkage()) Out << " __attribute((weak))"; } void CWriter::printFunction(Function *F) { diff --git a/lib/Target/X86/Printer.cpp b/lib/Target/X86/Printer.cpp index fbc6b6e1aff..f8c006cfd1c 100644 --- a/lib/Target/X86/Printer.cpp +++ b/lib/Target/X86/Printer.cpp @@ -948,7 +948,8 @@ bool Printer::doFinalization(Module &M) { unsigned Align = TD.getTypeAlignment(C->getType()); if (C->isNullValue() && - (I->hasLinkOnceLinkage() || I->hasInternalLinkage())) { + (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || + I->hasWeakLinkage() /* FIXME: Verify correct */)) { SwitchSection(O, CurSection, ".data"); if (I->hasInternalLinkage()) O << "\t.local " << name << "\n"; @@ -961,6 +962,7 @@ bool Printer::doFinalization(Module &M) { } else { switch (I->getLinkage()) { case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. // Nonnull linkonce -> weak O << "\t.weak " << name << "\n"; SwitchSection(O, CurSection, ""); diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index fbc6b6e1aff..f8c006cfd1c 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -948,7 +948,8 @@ bool Printer::doFinalization(Module &M) { unsigned Align = TD.getTypeAlignment(C->getType()); if (C->isNullValue() && - (I->hasLinkOnceLinkage() || I->hasInternalLinkage())) { + (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || + I->hasWeakLinkage() /* FIXME: Verify correct */)) { SwitchSection(O, CurSection, ".data"); if (I->hasInternalLinkage()) O << "\t.local " << name << "\n"; @@ -961,6 +962,7 @@ bool Printer::doFinalization(Module &M) { } else { switch (I->getLinkage()) { case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. // Nonnull linkonce -> weak O << "\t.weak " << name << "\n"; SwitchSection(O, CurSection, ""); diff --git a/lib/Transforms/Utils/Linker.cpp b/lib/Transforms/Utils/Linker.cpp index aa9a8fcafd4..a71572bd331 100644 --- a/lib/Transforms/Utils/Linker.cpp +++ b/lib/Transforms/Utils/Linker.cpp @@ -433,6 +433,24 @@ static bool LinkGlobals(Module *Dest, const Module *Src, } 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()) { + // 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!"); + // Otherwise, just perform the link. + ValueMap.insert(std::make_pair(SGV, DGV)); + } else if (DGV->hasWeakLinkage()) { + // 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->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!"); @@ -505,7 +523,7 @@ static bool LinkGlobalInits(Module *Dest, const Module *Src, 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()) { @@ -574,6 +592,16 @@ static bool LinkFunctionProtos(Module *Dest, const Module *Src, ValueMap.insert(std::make_pair(SF, DF)); DF->setLinkage(SF->getLinkage()); + } else if (SF->hasWeakLinkage()) { + // At this point we know that DF has LinkOnce, Weak, or External linkage. + ValueMap.insert(std::make_pair(SF, DF)); + + } else if (DF->hasWeakLinkage()) { + // 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!"); @@ -667,10 +695,9 @@ 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!"; - return true; + if (SF->hasWeakLinkage()) continue; + return Error(Err, "Function '" + SF->getName() + + "' body multiply defined!"); } if (LinkFunctionBody(DF, SF, ValueMap, Err)) return true; diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index ea8f43c9852..9437b59c53a 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -584,8 +584,9 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { Out << "external "; else switch (GV->getLinkage()) { - case GlobalValue::InternalLinkage: Out << "internal "; break; - case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::InternalLinkage: Out << "internal "; break; + case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::WeakLinkage: Out << "weak "; break; case GlobalValue::AppendingLinkage: Out << "appending "; break; case GlobalValue::ExternalLinkage: break; } @@ -652,8 +653,9 @@ void AssemblyWriter::printFunction(const Function *F) { Out << "declare "; else switch (F->getLinkage()) { - case GlobalValue::InternalLinkage: Out << "internal "; break; - case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::InternalLinkage: Out << "internal "; break; + case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::WeakLinkage: Out << "weak "; break; case GlobalValue::AppendingLinkage: Out << "appending "; break; case GlobalValue::ExternalLinkage: break; } diff --git a/lib/VMCore/Linker.cpp b/lib/VMCore/Linker.cpp index aa9a8fcafd4..a71572bd331 100644 --- a/lib/VMCore/Linker.cpp +++ b/lib/VMCore/Linker.cpp @@ -433,6 +433,24 @@ static bool LinkGlobals(Module *Dest, const Module *Src, } 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()) { + // 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!"); + // Otherwise, just perform the link. + ValueMap.insert(std::make_pair(SGV, DGV)); + } else if (DGV->hasWeakLinkage()) { + // 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->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!"); @@ -505,7 +523,7 @@ static bool LinkGlobalInits(Module *Dest, const Module *Src, 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()) { @@ -574,6 +592,16 @@ static bool LinkFunctionProtos(Module *Dest, const Module *Src, ValueMap.insert(std::make_pair(SF, DF)); DF->setLinkage(SF->getLinkage()); + } else if (SF->hasWeakLinkage()) { + // At this point we know that DF has LinkOnce, Weak, or External linkage. + ValueMap.insert(std::make_pair(SF, DF)); + + } else if (DF->hasWeakLinkage()) { + // 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!"); @@ -667,10 +695,9 @@ 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!"; - return true; + if (SF->hasWeakLinkage()) continue; + return Error(Err, "Function '" + SF->getName() + + "' body multiply defined!"); } if (LinkFunctionBody(DF, SF, ValueMap, Err)) return true; -- 2.34.1