Hello, Everyone. Please find patches for LLVM & llvm-gcc4 which enables external weak linkage. This is just first "draft".
Know issues: 1. There is some "FIXME" in the llvm-backend.cpp connected with external weak linkage. It seems to be somehow "old". Don't know, what should be done with it. 2. FIXME's in backend code: Darwin & Mingw32 codegens should be implemented 3. Linker & ExecutionEngine wasn't touched. TBD later. 4. Fixed somehow ELFWriter.cpp. It should be finished. The same applies to MachOWriter.cpp. Unfortunately, I don't know this code well to finish it. -- With best regards, Anton Korobeynikov. Faculty of Mathematics & Mechanics, Saint Petersburg State University.
diff -r 86069e5e6d4a lib/AsmParser/llvmAsmParser.y --- a/lib/AsmParser/llvmAsmParser.y Sat Nov 25 08:38:44 2006 +0000 +++ b/lib/AsmParser/llvmAsmParser.y Sat Nov 25 23:54:26 2006 +0300 @@ -2159,7 +2159,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 -r 86069e5e6d4a lib/CodeGen/ELFWriter.cpp --- a/lib/CodeGen/ELFWriter.cpp Sat Nov 25 08:38:44 2006 +0000 +++ b/lib/CodeGen/ELFWriter.cpp Sun Nov 26 00:27:24 2006 +0300 @@ -134,6 +134,7 @@ bool ELFCodeEmitter::finishFunction(Mach break; case GlobalValue::LinkOnceLinkage: case GlobalValue::WeakLinkage: + case GlobalValue::ExternalWeakLinkage: FnSym.SetBind(ELFWriter::ELFSym::STB_WEAK); break; case GlobalValue::InternalLinkage: diff -r 86069e5e6d4a lib/Target/CBackend/Writer.cpp --- a/lib/Target/CBackend/Writer.cpp Sat Nov 25 08:38:44 2006 +0000 +++ b/lib/Target/CBackend/Writer.cpp Sun Nov 26 00:19:50 2006 +0300 @@ -1031,8 +1031,6 @@ static void generateCompilerSpecificCode << "#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" @@ -1041,7 +1039,6 @@ static void generateCompilerSpecificCode << "#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" @@ -1231,7 +1228,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"; + } } } @@ -1244,9 +1245,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)) @@ -1279,6 +1284,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 -r 86069e5e6d4a lib/Target/X86/X86ATTAsmPrinter.cpp --- a/lib/Target/X86/X86ATTAsmPrinter.cpp Sat Nov 25 08:38:44 2006 +0000 +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp Sun Nov 26 03:36:43 2006 +0300 @@ -255,6 +255,10 @@ void X86ATTAsmPrinter::printOperand(cons } O << Name; } + + if (GV->hasExternalWeakLinkage()) { + ExtWeakSymbols.insert(Name); + } int Offset = MO.getOffset(); if (Offset > 0) diff -r 86069e5e6d4a lib/Target/X86/X86AsmPrinter.cpp --- a/lib/Target/X86/X86AsmPrinter.cpp Sat Nov 25 08:38:44 2006 +0000 +++ b/lib/Target/X86/X86AsmPrinter.cpp Sun Nov 26 03:32:49 2006 +0300 @@ -128,10 +128,11 @@ bool X86SharedAsmPrinter::doFinalization // 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,15 @@ bool X86SharedAsmPrinter::doFinalization O << "\t\t" << TAI->getCommentString() << " " << I->getName() << "\n"; } else { switch (I->getLinkage()) { + case GlobalValue::ExternalWeakLinkage: + if (Subtarget->isTargetDarwin()) { + assert(0 && "FIXME"); + } else if (Subtarget->isTargetCygwin()) { + assert(0 && "FIXME"); + } else { + O << "\t.weak " << name << "\n"; + break; + } case GlobalValue::LinkOnceLinkage: case GlobalValue::WeakLinkage: if (Subtarget->isTargetDarwin()) { @@ -270,6 +280,22 @@ bool X86SharedAsmPrinter::doFinalization i != e; ++i) { O << "\t.ascii \" -export:" << *i << "\"\n"; } + if (ExtWeakSymbols.begin() != ExtWeakSymbols.end()) + SwitchToDataSection(""); + + for (std::set<std::string>::iterator i = ExtWeakSymbols.begin(), + e = ExtWeakSymbols.end(); + i != e; ++i) { + + if (Subtarget->isTargetDarwin()) { + assert(0 && "FIXME"); + } else if (Subtarget->isTargetCygwin()) { + assert(0 && "FIXME"); + } else { + O << "\t.weak " << *i << "\n"; + } + } + if (Subtarget->isTargetDarwin()) { SwitchToDataSection(""); diff -r 86069e5e6d4a lib/Target/X86/X86AsmPrinter.h --- a/lib/Target/X86/X86AsmPrinter.h Sat Nov 25 08:38:44 2006 +0000 +++ b/lib/Target/X86/X86AsmPrinter.h Sun Nov 26 03:16:12 2006 +0300 @@ -84,6 +84,9 @@ struct VISIBILITY_HIDDEN X86SharedAsmPri // Necessary for dllexport support std::set<std::string> DLLExportedFns, DLLExportedGVs; + + // Necessary for external weak linkage support + std::set<std::string> ExtWeakSymbols; inline static bool isScale(const MachineOperand &MO) { return MO.isImmediate() && diff -r 86069e5e6d4a lib/VMCore/ConstantFolding.cpp --- a/lib/VMCore/ConstantFolding.cpp Sat Nov 25 08:38:44 2006 +0000 +++ b/lib/VMCore/ConstantFolding.cpp Sun Nov 26 00:49:21 2006 +0300 @@ -810,12 +810,10 @@ Constant *llvm::ConstantFoldCastInstruct const Type *DestTy) { if (V->getType() == DestTy) return (Constant*)V; - // Cast of a global address to boolean is always true. - if (isa<GlobalValue>(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. + // Cast of a global address to boolean is always true, when symbol doesn't + // have external weak linkage. + if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) { + if (DestTy == Type::BoolTy && !GV->hasExternalWeakLinkage()) return ConstantBool::getTrue(); } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { if (CE->getOpcode() == Instruction::Cast) {
diff -r da2c731b5893 gcc/crtstuff.c --- a/gcc/crtstuff.c Tue Nov 21 18:34:05 2006 +0000 +++ b/gcc/crtstuff.c Sun Nov 26 03:58:43 2006 +0300 @@ -65,13 +65,6 @@ 02111-1307, USA. */ #include "coretypes.h" #include "tm.h" #include "unwind-dw2-fde.h" - -/* APPLE LOCAL begin LLVM */ -#ifdef __llvm__ - /* FIXME: Remove when external weak linkage will be alive. */ - #undef JCR_SECTION_NAME -#endif -/* APPLE LOCAL end LLVM */ #ifndef FORCE_CODE_SECTION_ALIGN # define FORCE_CODE_SECTION_ALIGN diff -r da2c731b5893 gcc/llvm-backend.cpp --- a/gcc/llvm-backend.cpp Tue Nov 21 18:34:05 2006 +0000 +++ b/gcc/llvm-backend.cpp Sun Nov 26 02:32:04 2006 +0300 @@ -673,6 +675,11 @@ void make_decl_llvm(tree decl) { FnEntry = new Function(Ty, Function::ExternalLinkage, Name, TheModule); FnEntry->setCallingConv(CC); + // Check for external weak linkage + if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) { + FnEntry->setLinkage(Function::ExternalWeakLinkage); + } + #ifdef TARGET_ADJUST_LLVM_LINKAGE TARGET_ADJUST_LLVM_LINKAGE(FnEntry,decl); #endif /* TARGET_ADJUST_LLVM_LINKAGE */ @@ -692,6 +699,11 @@ void make_decl_llvm(tree decl) { if (Name[0] == 0) { // Global has no name. GV = new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage, 0, Name, TheModule); + + // Check for external weak linkage + if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) { + GV->setLinkage(GlobalValue::ExternalWeakLinkage); + } #ifdef TARGET_ADJUST_LLVM_LINKAGE TARGET_ADJUST_LLVM_LINKAGE(GV,decl); @@ -704,6 +716,11 @@ void make_decl_llvm(tree decl) { if (GVE == 0) { GVE = GV = new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage,0, Name, TheModule); + + // Check for external weak linkage + if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) { + GV->setLinkage(GlobalValue::ExternalWeakLinkage); + } #ifdef TARGET_ADJUST_LLVM_LINKAGE TARGET_ADJUST_LLVM_LINKAGE(GV,decl); @@ -752,17 +769,21 @@ const char *llvm_get_decl_name(void *LLV } // llvm_mark_decl_weak - Used by varasm.c, called when a decl is found to be -// weak, but it already had an llvm object created for it. This marks the LLVM +// weak, but it already had an llvm object created for it. This marks the LLVM // object weak as well. void llvm_mark_decl_weak(tree decl) { assert(DECL_LLVM_SET_P(decl) && DECL_WEAK(decl) && isa<GlobalValue>(DECL_LLVM(decl)) && "Decl isn't marked weak!"); GlobalValue *GV = cast<GlobalValue>(DECL_LLVM(decl)); - if (!GV->isExternal() && // FIXME: Support external weak globals! - // Do not mark something that is already known to be linkonce or internal. - GV->getLinkage() == GlobalValue::ExternalLinkage) - GV->setLinkage(GlobalValue::WeakLinkage); + // Do not mark something that is already known to be linkonce or internal. + if (GV->getLinkage() == GlobalValue::ExternalLinkage) { + if (GV->isExternal()) { + GV->setLinkage(GlobalValue::ExternalWeakLinkage); + } else { + GV->setLinkage(GlobalValue::WeakLinkage); + } + } } // llvm_emit_ctor_dtor - Called to emit static ctors/dtors to LLVM code. fndecl
_______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits