From 78ee7b78c3c47b71c4b7a1475438d6574216a64b Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Fri, 1 Dec 2006 00:25:12 +0000 Subject: [PATCH] Introducing external weak linkage. Darwin codegen should be added later. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32052 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AsmParser/llvmAsmParser.y | 2 +- lib/ExecutionEngine/ExecutionEngine.cpp | 2 +- lib/Linker/LinkModules.cpp | 36 ++++++++++++++++--------- lib/Target/CBackend/CBackend.cpp | 15 ++++++++--- lib/Target/CBackend/Writer.cpp | 15 ++++++++--- lib/Target/X86/X86ATTAsmPrinter.cpp | 4 +++ lib/Target/X86/X86AsmPrinter.cpp | 35 +++++++++++++++++++++--- lib/Target/X86/X86AsmPrinter.h | 3 +++ lib/VMCore/ConstantFold.cpp | 7 ++--- 9 files changed, 89 insertions(+), 30 deletions(-) diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index a6f6c2e19b1..1d1558eb6be 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -2201,7 +2201,7 @@ Function : BasicBlockList END { FnDeclareLinkage: /*default*/ | DLLIMPORT { CurFun.Linkage = GlobalValue::DLLImportLinkage; } | - EXTERN_WEAK { CurFun.Linkage = GlobalValue::DLLImportLinkage; }; + EXTERN_WEAK { CurFun.Linkage = GlobalValue::ExternalWeakLinkage; }; FunctionProto : DECLARE { CurFun.isDeclare = true; } FnDeclareLinkage FunctionHeaderH { $$ = CurFun.CurrentFunction; diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 683b4c75176..8447acf0e53 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -681,7 +681,7 @@ void ExecutionEngine::emitGlobals() { // Otherwise, we know it's linkonce/weak, replace it if this is a strong // symbol. - if (GV->hasExternalLinkage()) + if (GV->hasExternalLinkage() || GVEntry->hasExternalWeakLinkage()) GVEntry = GV; } } diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 46f74359874..b09fd656f2e 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -360,6 +360,7 @@ static bool GetLinkageResult(GlobalValue *Dest, GlobalValue *Src, // If Src is external or if both Src & Drc are external.. Just link the // external globals, we aren't adding anything. if (Src->hasDLLImportLinkage()) { + // If one of GVs has DLLImport linkage, result should be dllimport'ed. if (Dest->isExternal()) { LinkFromSrc = true; LT = Src->getLinkage(); @@ -379,8 +380,9 @@ static bool GetLinkageResult(GlobalValue *Dest, GlobalValue *Src, LinkFromSrc = true; // Special cased. LT = Src->getLinkage(); } else if (Src->hasWeakLinkage() || Src->hasLinkOnceLinkage()) { - // At this point we know that Dest has LinkOnce, External, Weak, DLL* linkage. - if (Dest->hasLinkOnceLinkage() && Src->hasWeakLinkage()) { + // At this point we know that Dest has LinkOnce, External*, Weak, DLL* linkage. + if ((Dest->hasLinkOnceLinkage() && Src->hasWeakLinkage()) || + Dest->hasExternalWeakLinkage()) { LinkFromSrc = true; LT = Src->getLinkage(); } else { @@ -388,16 +390,23 @@ static bool GetLinkageResult(GlobalValue *Dest, GlobalValue *Src, LT = Dest->getLinkage(); } } else if (Dest->hasWeakLinkage() || Dest->hasLinkOnceLinkage()) { - // At this point we know that Src has External or DLL* linkage. - LinkFromSrc = true; - LT = GlobalValue::ExternalLinkage; + // At this point we know that Src has External* or DLL* linkage. + if (Src->hasExternalWeakLinkage()) { + LinkFromSrc = false; + LT = Dest->getLinkage(); + } else { + LinkFromSrc = true; + LT = GlobalValue::ExternalLinkage; + } } else { assert((Dest->hasExternalLinkage() || Dest->hasDLLImportLinkage() || - Dest->hasDLLExportLinkage()) && + Dest->hasDLLExportLinkage() || + Dest->hasExternalWeakLinkage()) && (Src->hasExternalLinkage() || Src->hasDLLImportLinkage() || - Src->hasDLLExportLinkage()) && + Src->hasDLLExportLinkage() || + Src->hasExternalWeakLinkage()) && "Unexpected linkage type!"); return Error(Err, "Linking globals named '" + Src->getName() + "': symbol multiply defined!"); @@ -631,19 +640,22 @@ static bool LinkFunctionProtos(Module *Dest, const Module *Src, 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. + // 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()) + // *+External Weak = * + if ((DF->hasLinkOnceLinkage() && SF->hasWeakLinkage()) || + DF->hasExternalWeakLinkage()) DF->setLinkage(SF->getLinkage()); + } else if (DF->hasWeakLinkage() || DF->hasLinkOnceLinkage()) { - // At this point we know that SF has LinkOnce or External linkage. + // 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 + if (!SF->hasLinkOnceLinkage() && !SF->hasExternalWeakLinkage()) + // Don't inherit linkonce & external weak linkage DF->setLinkage(SF->getLinkage()); - } else if (SF->getLinkage() != DF->getLinkage()) { return Error(Err, "Functions named '" + SF->getName() + "' have different linkage specifiers!"); diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index fa869db6aa3..6d83aeb85db 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -1157,8 +1157,6 @@ static void generateCompilerSpecificCode(std::ostream& Out) { << "#define __attribute__(X)\n" << "#endif\n\n"; -#if 0 - // At some point, we should support "external weak" vs. "weak" linkages. // On Mac OS X, "external weak" is spelled "__attribute__((weak_import))". Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n" << "#define __EXTERNAL_WEAK__ __attribute__((weak_import))\n" @@ -1167,7 +1165,6 @@ static void generateCompilerSpecificCode(std::ostream& Out) { << "#else\n" << "#define __EXTERNAL_WEAK__\n" << "#endif\n\n"; -#endif // For now, turn off the weak linkage attribute on Mac OS X. (See above.) Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n" @@ -1357,7 +1354,11 @@ bool CWriter::doInitialization(Module &M) { Out << "__declspec(dllimport) "; printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); Out << ";\n"; - } + } else if (I->hasExternalWeakLinkage()) { + Out << "extern "; + printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); + Out << " __EXTERNAL_WEAK__ ;\n"; + } } } @@ -1370,9 +1371,13 @@ bool CWriter::doInitialization(Module &M) { // Don't print declarations for intrinsic functions. if (!I->getIntrinsicID() && I->getName() != "setjmp" && I->getName() != "longjmp" && I->getName() != "_setjmp") { + if (I->hasExternalWeakLinkage()) + Out << "extern "; printFunctionSignature(I, true); if (I->hasWeakLinkage() || I->hasLinkOnceLinkage()) Out << " __ATTRIBUTE_WEAK__"; + if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; if (StaticCtors.count(I)) Out << " __ATTRIBUTE_CTOR__"; if (StaticDtors.count(I)) @@ -1405,6 +1410,8 @@ bool CWriter::doInitialization(Module &M) { Out << " __attribute__((common))"; else if (I->hasWeakLinkage()) Out << " __ATTRIBUTE_WEAK__"; + else if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; Out << ";\n"; } } diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp index fa869db6aa3..6d83aeb85db 100644 --- a/lib/Target/CBackend/Writer.cpp +++ b/lib/Target/CBackend/Writer.cpp @@ -1157,8 +1157,6 @@ static void generateCompilerSpecificCode(std::ostream& Out) { << "#define __attribute__(X)\n" << "#endif\n\n"; -#if 0 - // At some point, we should support "external weak" vs. "weak" linkages. // On Mac OS X, "external weak" is spelled "__attribute__((weak_import))". Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n" << "#define __EXTERNAL_WEAK__ __attribute__((weak_import))\n" @@ -1167,7 +1165,6 @@ static void generateCompilerSpecificCode(std::ostream& Out) { << "#else\n" << "#define __EXTERNAL_WEAK__\n" << "#endif\n\n"; -#endif // For now, turn off the weak linkage attribute on Mac OS X. (See above.) Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n" @@ -1357,7 +1354,11 @@ bool CWriter::doInitialization(Module &M) { Out << "__declspec(dllimport) "; printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); Out << ";\n"; - } + } else if (I->hasExternalWeakLinkage()) { + Out << "extern "; + printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); + Out << " __EXTERNAL_WEAK__ ;\n"; + } } } @@ -1370,9 +1371,13 @@ bool CWriter::doInitialization(Module &M) { // Don't print declarations for intrinsic functions. if (!I->getIntrinsicID() && I->getName() != "setjmp" && I->getName() != "longjmp" && I->getName() != "_setjmp") { + if (I->hasExternalWeakLinkage()) + Out << "extern "; printFunctionSignature(I, true); if (I->hasWeakLinkage() || I->hasLinkOnceLinkage()) Out << " __ATTRIBUTE_WEAK__"; + if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; if (StaticCtors.count(I)) Out << " __ATTRIBUTE_CTOR__"; if (StaticDtors.count(I)) @@ -1405,6 +1410,8 @@ bool CWriter::doInitialization(Module &M) { Out << " __attribute__((common))"; else if (I->hasWeakLinkage()) Out << " __ATTRIBUTE_WEAK__"; + else if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; Out << ";\n"; } } diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp index 7784f621ae8..88d0c7c16fe 100755 --- a/lib/Target/X86/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp @@ -255,6 +255,10 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, } O << Name; } + + if (GV->hasExternalWeakLinkage()) { + ExtWeakSymbols.insert(Name); + } int Offset = MO.getOffset(); if (Offset > 0) diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index 2c53b72bd2a..cb792ad1ce0 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -128,11 +128,12 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { // from how MASM does things. When making changes here don't forget to look // at X86IntelAsmPrinter::doFinalization(). const TargetData *TD = TM.getTargetData(); - + // Print out module-level global variables here. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { - if (!I->hasInitializer()) continue; // External global require no code + if (!I->hasInitializer() && !I->hasExternalWeakLinkage()) + continue; // External global require no code // Check to see if this is a special global used by LLVM, if so, emit it. if (EmitSpecialLLVMGlobal(I)) @@ -176,6 +177,17 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { O << "\t\t" << TAI->getCommentString() << " " << I->getName() << "\n"; } else { switch (I->getLinkage()) { + case GlobalValue::ExternalWeakLinkage: + if (Subtarget->isTargetDarwin()) { + assert(0 && "External weak linkage for Darwin not implemented yet"); + } else if (Subtarget->isTargetCygwin()) { + // There is no external weak linkage on Mingw32 platform. + // Defaulting just to external + O << "\t.globl " << name << "\n"; + } else { + O << "\t.weak " << name << "\n"; + break; + } case GlobalValue::LinkOnceLinkage: case GlobalValue::WeakLinkage: if (Subtarget->isTargetDarwin()) { @@ -270,7 +282,24 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { i != e; ++i) { O << "\t.ascii \" -export:" << *i << "\"\n"; } - + + if (Subtarget->isTargetDarwin()) { + if (ExtWeakSymbols.begin() != ExtWeakSymbols.end()) + assert(0 && "External weak linkage for Darwin not implemented yet"); + } else if (Subtarget->isTargetCygwin()) { + // There is no external weak linkage on Mingw32 platform. + // Defaulting to external + } else { + if (ExtWeakSymbols.begin() != ExtWeakSymbols.end()) + SwitchToDataSection(""); + + for (std::set::iterator i = ExtWeakSymbols.begin(), + e = ExtWeakSymbols.end(); + i != e; ++i) { + O << "\t.weak " << *i << "\n"; + } + } + if (Subtarget->isTargetDarwin()) { SwitchToDataSection(""); diff --git a/lib/Target/X86/X86AsmPrinter.h b/lib/Target/X86/X86AsmPrinter.h index 3503e37c0bc..8dad733bb28 100755 --- a/lib/Target/X86/X86AsmPrinter.h +++ b/lib/Target/X86/X86AsmPrinter.h @@ -84,6 +84,9 @@ struct VISIBILITY_HIDDEN X86SharedAsmPrinter : public AsmPrinter { // Necessary for dllexport support std::set DLLExportedFns, DLLExportedGVs; + + // Necessary for external weak linkage support + std::set ExtWeakSymbols; inline static bool isScale(const MachineOperand &MO) { return MO.isImmediate() && diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 9974071385b..fd6ad108a9c 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -894,11 +894,8 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, const Constant *V, case Instruction::PtrToInt: // Cast of a global address to boolean is always true. - if (isa(V)) { - if (DestTy == Type::BoolTy) - // FIXME: When we support 'external weak' references, we have to - // prevent this transformation from happening. This code will need - // to be updated to ignore external weak symbols when we support it. + if (const GlobalValue *GV = dyn_cast(V)) { + if (DestTy == Type::BoolTy && !GV->hasExternalWeakLinkage()) return ConstantBool::getTrue(); } break;