From b74ed07bfd3af42331b1964c24c39912610a08f4 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Thu, 14 Sep 2006 18:23:27 +0000 Subject: [PATCH] Adding dllimport, dllexport and external weak linkage types. DLL* linkages got full (I hope) codegeneration support in C & both x86 assembler backends. External weak linkage added for future use, we don't provide any codegeneration, etc. support for it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30374 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/BytecodeFormat.html | 21 +++++--- docs/LangRef.html | 29 +++++++++++ include/llvm/GlobalValue.h | 28 ++++++----- lib/AsmParser/Lexer.l | 3 ++ lib/AsmParser/Lexer.l.cvs | 3 ++ lib/AsmParser/llvmAsmParser.y | 65 +++++++++++++++++++------ lib/AsmParser/llvmAsmParser.y.cvs | 65 +++++++++++++++++++------ lib/Bytecode/Reader/Reader.cpp | 14 ++++++ lib/Bytecode/Writer/Writer.cpp | 35 +++++++++---- lib/ExecutionEngine/ExecutionEngine.cpp | 4 +- lib/ExecutionEngine/JIT/JITEmitter.cpp | 4 +- lib/Linker/LinkArchives.cpp | 10 +++- lib/Linker/LinkModules.cpp | 42 +++++++++++----- lib/Target/Alpha/AlphaAsmPrinter.cpp | 8 +++ lib/Target/CBackend/CBackend.cpp | 13 ++++- lib/Target/CBackend/Writer.cpp | 13 ++++- lib/Target/IA64/IA64AsmPrinter.cpp | 8 +++ lib/Target/Sparc/SparcAsmPrinter.cpp | 8 +++ lib/Target/X86/X86ATTAsmPrinter.cpp | 28 +++++++++-- lib/Target/X86/X86AsmPrinter.cpp | 24 +++++++++ lib/Target/X86/X86AsmPrinter.h | 3 ++ lib/Target/X86/X86ISelLowering.cpp | 16 ++++++ lib/Target/X86/X86IntelAsmPrinter.cpp | 59 ++++++++++++++++++++-- lib/Target/X86/X86Subtarget.h | 2 + lib/Transforms/IPO/GlobalOpt.cpp | 4 +- lib/Transforms/IPO/SimplifyLibCalls.cpp | 6 ++- lib/VMCore/AsmWriter.cpp | 36 +++++++++----- lib/VMCore/Mangler.cpp | 11 +++-- lib/VMCore/Verifier.cpp | 12 ++++- tools/llvm2cpp/CppWriter.cpp | 6 +++ 30 files changed, 477 insertions(+), 103 deletions(-) diff --git a/docs/BytecodeFormat.html b/docs/BytecodeFormat.html index 51177492a9e..2b856a71631 100644 --- a/docs/BytecodeFormat.html +++ b/docs/BytecodeFormat.html @@ -1025,7 +1025,8 @@ follows. bit(2-4) Linkage type: 0=External, 1=Weak, -2=Appending, 3=Internal, 4=LinkOnce + 2=Appending, 3=Internal, 4=LinkOnce, 5=DllImport, + 6=DllExport, 7=ExternWeak bit(5-31) @@ -1136,13 +1137,16 @@ href="#uint32_vbr">uint32_vbr that describes the function.

bit(4) If this bit is set to 1, the indicated function is external, and there is no Function Definiton - Block in the bytecode file for the function. + Block in the bytecode file for the function. If the function is + external and has dllimport or extern_weak linkage additional + field in the extension word is used to indicate the actual linkage + type. bit(5-30) Type slot number of type for the function. - + bit(31) Indicates whether an extension word follows. @@ -1171,7 +1175,12 @@ follows with the following fields:

If this bit is set, a SectionID follows this vbr. - bit(11-31) + bit(11-12) + Linkage type for external functions. 0 - External + linkage, 1 - DLLImport linkage, 2 - External weak linkage. + + + bit(13-31) Currently unassigned. @@ -1410,8 +1419,8 @@ size
uint32_vbr - The linkage type of the function: 0=External, -1=Weak, 2=Appending, 3=Internal, 4=LinkOnce1 + The linkage type of the function: 0=External, 1=Weak, +2=Appending, 3=Internal, 4=LinkOnce, 5=DllImport, 6=DllExport1 block diff --git a/docs/LangRef.html b/docs/LangRef.html index 232b4683323..5ae8472ffdd 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -439,6 +439,35 @@ All Global Variables and Functions have one of the following types of linkage: visible, meaning that it participates in linkage and can be used to resolve external symbol references. + +
extern_weak:
+ +
"extern_weak" TBD +
+ +

+ The next two types of linkage are targeted for Microsoft Windows platform + only. They are designed to support importing (exporting) symbols from (to) + DLLs. +

+ +
dllimport:
+ +
"dllimport" linkage causes the compiler to reference a function + or variable via a global pointer to a pointer that is set up by the DLL + exporting the symbol. On Microsoft Windows targets, the pointer name is + formed by combining _imp__ and the function or variable name. +
+ +
dllexport:
+ +
"dllexport" linkage causes the compiler to provide a global + pointer to a pointer in a DLL, so that it can be referenced with the + dllimport attribute. On Microsoft Windows targets, the pointer + name is formed by combining _imp__ and the function or variable + name. +
+

For example, since the ".LC0" diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h index ca189b2cbe1..6aa830e6283 100644 --- a/include/llvm/GlobalValue.h +++ b/include/llvm/GlobalValue.h @@ -28,12 +28,15 @@ class GlobalValue : public Constant { GlobalValue(const GlobalValue &); // do not implement public: enum LinkageTypes { - ExternalLinkage, /// Externally visible function - LinkOnceLinkage, /// Keep one copy of named function when linking (inline) - WeakLinkage, /// Keep one copy of named function when linking (weak) - AppendingLinkage, /// Special purpose, only applies to global arrays - InternalLinkage, /// Rename collisions when linking (static functions) - GhostLinkage /// Stand-in functions for streaming fns from BC files + ExternalLinkage, /// Externally visible function + LinkOnceLinkage, /// Keep one copy of named function when linking (inline) + WeakLinkage, /// Keep one copy of named function when linking (weak) + AppendingLinkage, /// Special purpose, only applies to global arrays + InternalLinkage, /// Rename collisions when linking (static functions) + DLLImportLinkage, /// Function to be imported from DLL + DLLExportLinkage, /// Function to be accessible from DLL + ExternalWeakLinkage, /// TBD: ExternalWeak linkage description + GhostLinkage /// Stand-in functions for streaming fns from BC files }; protected: GlobalValue(const Type *Ty, ValueTy vty, Use *Ops, unsigned NumOps, @@ -72,11 +75,14 @@ public: return reinterpret_cast(User::getType()); } - bool hasExternalLinkage() const { return Linkage == ExternalLinkage; } - bool hasLinkOnceLinkage() const { return Linkage == LinkOnceLinkage; } - bool hasWeakLinkage() const { return Linkage == WeakLinkage; } - bool hasAppendingLinkage() const { return Linkage == AppendingLinkage; } - bool hasInternalLinkage() const { return Linkage == InternalLinkage; } + bool hasExternalLinkage() const { return Linkage == ExternalLinkage; } + bool hasLinkOnceLinkage() const { return Linkage == LinkOnceLinkage; } + bool hasWeakLinkage() const { return Linkage == WeakLinkage; } + bool hasAppendingLinkage() const { return Linkage == AppendingLinkage; } + bool hasInternalLinkage() const { return Linkage == InternalLinkage; } + bool hasDLLImportLinkage() const { return Linkage == DLLImportLinkage; } + bool hasDLLExportLinkage() const { return Linkage == DLLExportLinkage; } + bool hasExternalWeakLinkage() const { return Linkage == ExternalWeakLinkage; } void setLinkage(LinkageTypes LT) { Linkage = LT; } LinkageTypes getLinkage() const { return Linkage; } diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l index fd752459f0b..7c27f137bcb 100644 --- a/lib/AsmParser/Lexer.l +++ b/lib/AsmParser/Lexer.l @@ -191,6 +191,9 @@ internal { return INTERNAL; } linkonce { return LINKONCE; } weak { return WEAK; } appending { return APPENDING; } +dllimport { return DLLIMPORT; } +dllexport { return DLLEXPORT; } +extern_weak { return EXTERN_WEAK; } uninitialized { return EXTERNAL; } /* Deprecated, turn into external */ external { return EXTERNAL; } implementation { return IMPLEMENTATION; } diff --git a/lib/AsmParser/Lexer.l.cvs b/lib/AsmParser/Lexer.l.cvs index fd752459f0b..7c27f137bcb 100644 --- a/lib/AsmParser/Lexer.l.cvs +++ b/lib/AsmParser/Lexer.l.cvs @@ -191,6 +191,9 @@ internal { return INTERNAL; } linkonce { return LINKONCE; } weak { return WEAK; } appending { return APPENDING; } +dllimport { return DLLIMPORT; } +dllexport { return DLLEXPORT; } +extern_weak { return EXTERN_WEAK; } uninitialized { return EXTERNAL; } /* Deprecated, turn into external */ external { return EXTERNAL; } implementation { return IMPLEMENTATION; } diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 7d6a9f7af36..af3a39d3d90 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -150,9 +150,10 @@ static struct PerModuleInfo { static struct PerFunctionInfo { Function *CurrentFunction; // Pointer to current function being created - std::map Values; // Keep track of #'d definitions + std::map Values; // Keep track of #'d definitions std::map LateResolveValues; - bool isDeclare; // Is this function a forward declararation? + bool isDeclare; // Is this function a forward declararation? + GlobalValue::LinkageTypes Linkage; // Linkage for forward declaration. /// BBForwardRefs - When we see forward references to basic blocks, keep /// track of them here. @@ -163,6 +164,7 @@ static struct PerFunctionInfo { inline PerFunctionInfo() { CurrentFunction = 0; isDeclare = false; + Linkage = GlobalValue::ExternalLinkage; } inline void FunctionStart(Function *M) { @@ -184,6 +186,7 @@ static struct PerFunctionInfo { Values.clear(); // Clear out function local definitions CurrentFunction = 0; isDeclare = false; + Linkage = GlobalValue::ExternalLinkage; } } CurFun; // Info for the current function... @@ -998,7 +1001,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token IMPLEMENTATION ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK %token DECLARE GLOBAL CONSTANT SECTION VOLATILE -%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING +%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING +%token DLLIMPORT DLLEXPORT EXTERN_WEAK %token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG ALIGN %token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT %token CC_TOK CCC_TOK CSRETCC_TOK FASTCC_TOK COLDCC_TOK @@ -1070,11 +1074,14 @@ OptAssign : Name '=' { CHECK_FOR_ERROR }; -OptLinkage : INTERNAL { $$ = GlobalValue::InternalLinkage; } | - LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | - WEAK { $$ = GlobalValue::WeakLinkage; } | - APPENDING { $$ = GlobalValue::AppendingLinkage; } | - /*empty*/ { $$ = GlobalValue::ExternalLinkage; }; +OptLinkage : INTERNAL { $$ = GlobalValue::InternalLinkage; } | + LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | + WEAK { $$ = GlobalValue::WeakLinkage; } | + APPENDING { $$ = GlobalValue::AppendingLinkage; } | + DLLIMPORT { $$ = GlobalValue::DLLImportLinkage; } | + DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; } | + EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; } | + /*empty*/ { $$ = GlobalValue::ExternalLinkage; }; OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | CCC_TOK { $$ = CallingConv::C; } | @@ -1728,8 +1735,24 @@ ConstPool : ConstPool OptAssign TYPE TypesV { CHECK_FOR_ERROR } | ConstPool OptAssign EXTERNAL GlobalType Types { - CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage, - $4, *$5, 0); + CurGV = ParseGlobalVariable($2, + GlobalValue::ExternalLinkage, $4, *$5, 0); + delete $5; + } GlobalVarAttributes { + CurGV = 0; + CHECK_FOR_ERROR + } + | ConstPool OptAssign DLLIMPORT GlobalType Types { + CurGV = ParseGlobalVariable($2, + GlobalValue::DLLImportLinkage, $4, *$5, 0); + delete $5; + } GlobalVarAttributes { + CurGV = 0; + CHECK_FOR_ERROR + } + | ConstPool OptAssign EXTERN_WEAK GlobalType Types { + CurGV = ParseGlobalVariable($2, + GlobalValue::ExternalWeakLinkage, $4, *$5, 0); delete $5; } GlobalVarAttributes { CurGV = 0; @@ -1895,9 +1918,17 @@ FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' AI != AE; ++AI) AI->setName(""); + if (CurFun.isDeclare) { + Fn->setLinkage(CurFun.Linkage); + } } else { // Not already defined? Fn = new Function(FT, GlobalValue::ExternalLinkage, FunctionName, CurModule.CurrentModule); + + if (CurFun.isDeclare) { + Fn->setLinkage(CurFun.Linkage); + } + InsertValue(Fn, CurModule.Values); } @@ -1948,11 +1979,15 @@ Function : BasicBlockList END { CHECK_FOR_ERROR }; -FunctionProto : DECLARE { CurFun.isDeclare = true; } FunctionHeaderH { - $$ = CurFun.CurrentFunction; - CurFun.FunctionDone(); - CHECK_FOR_ERROR -}; +FnDeclareLinkage: /*default*/ | + DLLIMPORT { CurFun.Linkage = GlobalValue::DLLImportLinkage } | + EXTERN_WEAK { CurFun.Linkage = GlobalValue::DLLImportLinkage }; + +FunctionProto : DECLARE { CurFun.isDeclare = true; } FnDeclareLinkage FunctionHeaderH { + $$ = CurFun.CurrentFunction; + CurFun.FunctionDone(); + CHECK_FOR_ERROR + }; //===----------------------------------------------------------------------===// // Rules to match Basic Blocks diff --git a/lib/AsmParser/llvmAsmParser.y.cvs b/lib/AsmParser/llvmAsmParser.y.cvs index 7d6a9f7af36..af3a39d3d90 100644 --- a/lib/AsmParser/llvmAsmParser.y.cvs +++ b/lib/AsmParser/llvmAsmParser.y.cvs @@ -150,9 +150,10 @@ static struct PerModuleInfo { static struct PerFunctionInfo { Function *CurrentFunction; // Pointer to current function being created - std::map Values; // Keep track of #'d definitions + std::map Values; // Keep track of #'d definitions std::map LateResolveValues; - bool isDeclare; // Is this function a forward declararation? + bool isDeclare; // Is this function a forward declararation? + GlobalValue::LinkageTypes Linkage; // Linkage for forward declaration. /// BBForwardRefs - When we see forward references to basic blocks, keep /// track of them here. @@ -163,6 +164,7 @@ static struct PerFunctionInfo { inline PerFunctionInfo() { CurrentFunction = 0; isDeclare = false; + Linkage = GlobalValue::ExternalLinkage; } inline void FunctionStart(Function *M) { @@ -184,6 +186,7 @@ static struct PerFunctionInfo { Values.clear(); // Clear out function local definitions CurrentFunction = 0; isDeclare = false; + Linkage = GlobalValue::ExternalLinkage; } } CurFun; // Info for the current function... @@ -998,7 +1001,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token IMPLEMENTATION ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK %token DECLARE GLOBAL CONSTANT SECTION VOLATILE -%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING +%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING +%token DLLIMPORT DLLEXPORT EXTERN_WEAK %token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG ALIGN %token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT %token CC_TOK CCC_TOK CSRETCC_TOK FASTCC_TOK COLDCC_TOK @@ -1070,11 +1074,14 @@ OptAssign : Name '=' { CHECK_FOR_ERROR }; -OptLinkage : INTERNAL { $$ = GlobalValue::InternalLinkage; } | - LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | - WEAK { $$ = GlobalValue::WeakLinkage; } | - APPENDING { $$ = GlobalValue::AppendingLinkage; } | - /*empty*/ { $$ = GlobalValue::ExternalLinkage; }; +OptLinkage : INTERNAL { $$ = GlobalValue::InternalLinkage; } | + LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | + WEAK { $$ = GlobalValue::WeakLinkage; } | + APPENDING { $$ = GlobalValue::AppendingLinkage; } | + DLLIMPORT { $$ = GlobalValue::DLLImportLinkage; } | + DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; } | + EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; } | + /*empty*/ { $$ = GlobalValue::ExternalLinkage; }; OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | CCC_TOK { $$ = CallingConv::C; } | @@ -1728,8 +1735,24 @@ ConstPool : ConstPool OptAssign TYPE TypesV { CHECK_FOR_ERROR } | ConstPool OptAssign EXTERNAL GlobalType Types { - CurGV = ParseGlobalVariable($2, GlobalValue::ExternalLinkage, - $4, *$5, 0); + CurGV = ParseGlobalVariable($2, + GlobalValue::ExternalLinkage, $4, *$5, 0); + delete $5; + } GlobalVarAttributes { + CurGV = 0; + CHECK_FOR_ERROR + } + | ConstPool OptAssign DLLIMPORT GlobalType Types { + CurGV = ParseGlobalVariable($2, + GlobalValue::DLLImportLinkage, $4, *$5, 0); + delete $5; + } GlobalVarAttributes { + CurGV = 0; + CHECK_FOR_ERROR + } + | ConstPool OptAssign EXTERN_WEAK GlobalType Types { + CurGV = ParseGlobalVariable($2, + GlobalValue::ExternalWeakLinkage, $4, *$5, 0); delete $5; } GlobalVarAttributes { CurGV = 0; @@ -1895,9 +1918,17 @@ FunctionHeaderH : OptCallingConv TypesV Name '(' ArgList ')' AI != AE; ++AI) AI->setName(""); + if (CurFun.isDeclare) { + Fn->setLinkage(CurFun.Linkage); + } } else { // Not already defined? Fn = new Function(FT, GlobalValue::ExternalLinkage, FunctionName, CurModule.CurrentModule); + + if (CurFun.isDeclare) { + Fn->setLinkage(CurFun.Linkage); + } + InsertValue(Fn, CurModule.Values); } @@ -1948,11 +1979,15 @@ Function : BasicBlockList END { CHECK_FOR_ERROR }; -FunctionProto : DECLARE { CurFun.isDeclare = true; } FunctionHeaderH { - $$ = CurFun.CurrentFunction; - CurFun.FunctionDone(); - CHECK_FOR_ERROR -}; +FnDeclareLinkage: /*default*/ | + DLLIMPORT { CurFun.Linkage = GlobalValue::DLLImportLinkage } | + EXTERN_WEAK { CurFun.Linkage = GlobalValue::DLLImportLinkage }; + +FunctionProto : DECLARE { CurFun.isDeclare = true; } FnDeclareLinkage FunctionHeaderH { + $$ = CurFun.CurrentFunction; + CurFun.FunctionDone(); + CHECK_FOR_ERROR + }; //===----------------------------------------------------------------------===// // Rules to match Basic Blocks diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index 60c8e4f9db8..ac6418d7a7d 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -1791,6 +1791,9 @@ void BytecodeReader::ParseFunctionBody(Function* F) { case 2: Linkage = GlobalValue::AppendingLinkage; break; case 3: Linkage = GlobalValue::InternalLinkage; break; case 4: Linkage = GlobalValue::LinkOnceLinkage; break; + case 5: Linkage = GlobalValue::DLLImportLinkage; break; + case 6: Linkage = GlobalValue::DLLExportLinkage; break; + case 7: Linkage = GlobalValue::ExternalWeakLinkage; break; default: error("Invalid linkage type for Function."); Linkage = GlobalValue::InternalLinkage; @@ -2047,6 +2050,9 @@ void BytecodeReader::ParseModuleGlobalInfo() { case 2: Linkage = GlobalValue::AppendingLinkage; break; case 3: Linkage = GlobalValue::InternalLinkage; break; case 4: Linkage = GlobalValue::LinkOnceLinkage; break; + case 5: Linkage = GlobalValue::DLLImportLinkage; break; + case 6: Linkage = GlobalValue::DLLExportLinkage; break; + case 7: Linkage = GlobalValue::ExternalWeakLinkage; break; default: error("Unknown linkage type: " + utostr(LinkageID)); Linkage = GlobalValue::InternalLinkage; @@ -2129,6 +2135,14 @@ void BytecodeReader::ParseModuleGlobalInfo() { if (ExtWord & (1 << 10)) // Has a section ID. SectionID[Func] = read_vbr_uint(); + + // Parse external declaration linkage + switch ((ExtWord >> 11) & 3) { + case 0: break; + case 1: Func->setLinkage(Function::DLLImportLinkage); break; + case 2: Func->setLinkage(Function::ExternalWeakLinkage); break; + default: assert(0 && "Unsupported external linkage"); + } } Func->setCallingConv(CC-1); diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp index 2fb05f147a6..48cccda8f40 100644 --- a/lib/Bytecode/Writer/Writer.cpp +++ b/lib/Bytecode/Writer/Writer.cpp @@ -938,11 +938,14 @@ void BytecodeWriter::outputConstants(bool isFunction) { static unsigned getEncodedLinkage(const GlobalValue *GV) { switch (GV->getLinkage()) { default: assert(0 && "Invalid linkage!"); - case GlobalValue::ExternalLinkage: return 0; - case GlobalValue::WeakLinkage: return 1; - case GlobalValue::AppendingLinkage: return 2; - case GlobalValue::InternalLinkage: return 3; - case GlobalValue::LinkOnceLinkage: return 4; + case GlobalValue::ExternalLinkage: return 0; + case GlobalValue::WeakLinkage: return 1; + case GlobalValue::AppendingLinkage: return 2; + case GlobalValue::InternalLinkage: return 3; + case GlobalValue::LinkOnceLinkage: return 4; + case GlobalValue::DLLImportLinkage: return 5; + case GlobalValue::DLLExportLinkage: return 6; + case GlobalValue::ExternalWeakLinkage: return 7; } } @@ -973,7 +976,7 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) { unsigned oSlot = ((unsigned)Slot << 5) | (getEncodedLinkage(I) << 2) | (I->hasInitializer() << 1) | (unsigned)I->isConstant(); output_vbr(oSlot); - } else { + } else { unsigned oSlot = ((unsigned)Slot << 5) | (3 << 2) | (0 << 1) | (unsigned)I->isConstant(); output_vbr(oSlot); @@ -1018,16 +1021,30 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) { if (I->isExternal()) // If external, we don't have an FunctionInfo block. ID |= 1 << 4; - if (I->getAlignment() || I->hasSection() || (CC & ~15) != 0) + if (I->getAlignment() || I->hasSection() || (CC & ~15) != 0 || + (I->isExternal() && I->hasDLLImportLinkage()) || + (I->isExternal() && I->hasExternalWeakLinkage()) + ) ID |= 1 << 31; // Do we need an extension word? output_vbr(ID); if (ID & (1 << 31)) { // Extension byte: bits 0-4 = alignment, bits 5-9 = top nibble of calling - // convention, bit 10 = hasSectionID. + // convention, bit 10 = hasSectionID., bits 11-12 = external linkage type + unsigned extLinkage = 0; + + if (I->isExternal()) { + if (I->hasDLLImportLinkage()) { + extLinkage = 1; + } else if (I->hasExternalWeakLinkage()) { + extLinkage = 2; + } + } + ID = (Log2_32(I->getAlignment())+1) | ((CC >> 4) << 5) | - (I->hasSection() << 10); + (I->hasSection() << 10) | + ((extLinkage & 3) << 11); output_vbr(ID); // Give section names unique ID's. diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 9ad6b57ecd7..067f24de8b4 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -657,7 +657,9 @@ void ExecutionEngine::emitGlobals() { } // If the existing global is strong, never replace it. - if (GVEntry->hasExternalLinkage()) + if (GVEntry->hasExternalLinkage() || + GVEntry->hasDLLImportLinkage() || + GVEntry->hasDLLExportLinkage()) continue; // Otherwise, we know it's linkonce/weak, replace it if this is a strong diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index 6e60caf332e..264caae2c9b 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -542,7 +542,7 @@ void *JITResolver::getFunctionStub(Function *F) { // Call the lazy resolver function unless we already KNOW it is an external // function, in which case we just skip the lazy resolution step. void *Actual = (void*)(intptr_t)LazyResolverFn; - if (F->isExternal() && F->hasExternalLinkage()) + if (F->isExternal()) Actual = TheJIT->getPointerToFunction(F); // Otherwise, codegen a new stub. For now, the stub will call the lazy @@ -738,7 +738,7 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, void *ResultPtr = TheJIT->getPointerToGlobalIfAvailable(F); if (ResultPtr) return ResultPtr; - if (F->hasExternalLinkage() && F->isExternal()) { + if (F->isExternal()) { // If this is an external function pointer, we can force the JIT to // 'compile' it, which really just adds it to the map. if (DoesntNeedStub) diff --git a/lib/Linker/LinkArchives.cpp b/lib/Linker/LinkArchives.cpp index e115b93ad28..15d261e25bd 100644 --- a/lib/Linker/LinkArchives.cpp +++ b/lib/Linker/LinkArchives.cpp @@ -65,16 +65,22 @@ GetAllUndefinedSymbols(Module *M, std::set &UndefinedSymbols) { if (I->hasName()) { if (I->isExternal()) UndefinedSymbols.insert(I->getName()); - else if (!I->hasInternalLinkage()) + else if (!I->hasInternalLinkage()) { + assert(!I->hasDLLImportLinkage() + && "Found dllimported non-external symbol!"); DefinedSymbols.insert(I->getName()); + } } for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasName()) { if (I->isExternal()) UndefinedSymbols.insert(I->getName()); - else if (!I->hasInternalLinkage()) + else if (!I->hasInternalLinkage()) { + assert(!I->hasDLLImportLinkage() + && "Found dllimported non-external symbol!"); DefinedSymbols.insert(I->getName()); + } } // Prune out any defined symbols from the undefined symbols set... diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 3c87177df3d..90b45028bc1 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -359,9 +359,16 @@ static bool GetLinkageResult(GlobalValue *Dest, GlobalValue *Src, } else if (Src->isExternal()) { // If Src is external or if both Src & Drc are external.. Just link the // external globals, we aren't adding anything. - LinkFromSrc = false; - LT = Dest->getLinkage(); - } else if (Dest->isExternal()) { + if (Src->hasDLLImportLinkage()) { + if (Dest->isExternal()) { + LinkFromSrc = true; + LT = Src->getLinkage(); + } + } else { + LinkFromSrc = false; + LT = Dest->getLinkage(); + } + } else if (Dest->isExternal() && !Dest->hasDLLImportLinkage()) { // If Dest is external but Src is not: LinkFromSrc = true; LT = Src->getLinkage(); @@ -372,7 +379,7 @@ 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 or Weak linkage. + // At this point we know that Dest has LinkOnce, External, Weak, DLL* linkage. if (Dest->hasLinkOnceLinkage() && Src->hasWeakLinkage()) { LinkFromSrc = true; LT = Src->getLinkage(); @@ -381,11 +388,16 @@ 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 linkage. + // At this point we know that Src has External or DLL* linkage. LinkFromSrc = true; LT = GlobalValue::ExternalLinkage; } else { - assert(Dest->hasExternalLinkage() && Src->hasExternalLinkage() && + assert((Dest->hasExternalLinkage() || + Dest->hasDLLImportLinkage() || + Dest->hasDLLExportLinkage()) && + (Src->hasExternalLinkage() || + Src->hasDLLImportLinkage() || + Src->hasDLLExportLinkage()) && "Unexpected linkage type!"); return Error(Err, "Linking globals named '" + Src->getName() + "': symbol multiply defined!"); @@ -425,7 +437,8 @@ static bool LinkGlobals(Module *Dest, Module *Src, if (DGV && DGV->hasInternalLinkage()) DGV = 0; - assert(SGV->hasInitializer() || SGV->hasExternalLinkage() && + assert(SGV->hasInitializer() || + SGV->hasExternalLinkage() || SGV->hasDLLImportLinkage() && "Global must either be external or have an initializer!"); GlobalValue::LinkageTypes NewLinkage; @@ -565,7 +578,7 @@ static bool LinkGlobalInits(Module *Dest, const Module *Src, // static bool LinkFunctionProtos(Module *Dest, const Module *Src, std::map &ValueMap, - std::map &GlobalsByName, + std::map &GlobalsByName, std::string *Err) { SymbolTable *ST = (SymbolTable*)&Dest->getSymbolTable(); @@ -604,12 +617,19 @@ static bool LinkFunctionProtos(Module *Dest, const Module *Src, } else if (SF->isExternal()) { // If SF is external or if both SF & DF are external.. Just link the // external functions, we aren't adding anything. - ValueMap.insert(std::make_pair(SF, DF)); - } else if (DF->isExternal()) { // If DF is external but SF is not... + if (SF->hasDLLImportLinkage()) { + if (DF->isExternal()) { + ValueMap.insert(std::make_pair(SF, DF)); + DF->setLinkage(SF->getLinkage()); + } + } else { + ValueMap.insert(std::make_pair(SF, DF)); + } + } else if (DF->isExternal() && !DF->hasDLLImportLinkage()) { + // If DF is external but SF is not... // Link the external functions, update linkage qualifiers 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)); diff --git a/lib/Target/Alpha/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AlphaAsmPrinter.cpp index 2ce4865404b..52e2bb6d349 100644 --- a/lib/Target/Alpha/AlphaAsmPrinter.cpp +++ b/lib/Target/Alpha/AlphaAsmPrinter.cpp @@ -258,6 +258,14 @@ bool AlphaAsmPrinter::doFinalization(Module &M) { case GlobalValue::GhostLinkage: std::cerr << "GhostLinkage cannot appear in AlphaAsmPrinter!\n"; abort(); + case GlobalValue::DLLImportLinkage: + std::cerr << "DLLImport linkage is not supported by this target!\n"; + abort(); + case GlobalValue::DLLExportLinkage: + std::cerr << "DLLExport linkage is not supported by this target!\n"; + abort(); + default: + assert(0 && "Unknown linkage type!"); } EmitAlignment(Align); diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 330a7bc53f8..2aa36270bf2 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -1054,7 +1054,11 @@ bool CWriter::doInitialization(Module &M) { Out << "extern "; printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); Out << ";\n"; - } + } else if (I->hasDLLImportLinkage()) { + Out << "__declspec(dllimport) "; + printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); + Out << ";\n"; + } } } @@ -1118,6 +1122,11 @@ bool CWriter::doInitialization(Module &M) { if (I->hasInternalLinkage()) Out << "static "; + else if (I->hasDLLImportLinkage()) + Out << "__declspec(dllimport) "; + else if (I->hasDLLExportLinkage()) + Out << "__declspec(dllexport) "; + printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); if (I->hasLinkOnceLinkage()) Out << " __attribute__((common))"; @@ -1267,6 +1276,8 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { bool isCStructReturn = F->getCallingConv() == CallingConv::CSRet; if (F->hasInternalLinkage()) Out << "static "; + if (F->hasDLLImportLinkage()) Out << "__declspec(dllimport) "; + if (F->hasDLLExportLinkage()) Out << "__declspec(dllexport) "; // Loop over the arguments, printing them... const FunctionType *FT = cast(F->getFunctionType()); diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp index 330a7bc53f8..2aa36270bf2 100644 --- a/lib/Target/CBackend/Writer.cpp +++ b/lib/Target/CBackend/Writer.cpp @@ -1054,7 +1054,11 @@ bool CWriter::doInitialization(Module &M) { Out << "extern "; printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); Out << ";\n"; - } + } else if (I->hasDLLImportLinkage()) { + Out << "__declspec(dllimport) "; + printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); + Out << ";\n"; + } } } @@ -1118,6 +1122,11 @@ bool CWriter::doInitialization(Module &M) { if (I->hasInternalLinkage()) Out << "static "; + else if (I->hasDLLImportLinkage()) + Out << "__declspec(dllimport) "; + else if (I->hasDLLExportLinkage()) + Out << "__declspec(dllexport) "; + printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); if (I->hasLinkOnceLinkage()) Out << " __attribute__((common))"; @@ -1267,6 +1276,8 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { bool isCStructReturn = F->getCallingConv() == CallingConv::CSRet; if (F->hasInternalLinkage()) Out << "static "; + if (F->hasDLLImportLinkage()) Out << "__declspec(dllimport) "; + if (F->hasDLLExportLinkage()) Out << "__declspec(dllexport) "; // Loop over the arguments, printing them... const FunctionType *FT = cast(F->getFunctionType()); diff --git a/lib/Target/IA64/IA64AsmPrinter.cpp b/lib/Target/IA64/IA64AsmPrinter.cpp index 4a16777f9bb..5fcc86f50e7 100644 --- a/lib/Target/IA64/IA64AsmPrinter.cpp +++ b/lib/Target/IA64/IA64AsmPrinter.cpp @@ -306,6 +306,14 @@ bool IA64AsmPrinter::doFinalization(Module &M) { case GlobalValue::GhostLinkage: std::cerr << "GhostLinkage cannot appear in IA64AsmPrinter!\n"; abort(); + case GlobalValue::DLLImportLinkage: + std::cerr << "DLLImport linkage is not supported by this target!\n"; + abort(); + case GlobalValue::DLLExportLinkage: + std::cerr << "DLLExport linkage is not supported by this target!\n"; + abort(); + default: + assert(0 && "Unknown linkage type!"); } EmitAlignment(Align); diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp index 1e6efcbeaf2..f8efc9ee545 100644 --- a/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -271,6 +271,14 @@ bool SparcAsmPrinter::doFinalization(Module &M) { case GlobalValue::GhostLinkage: std::cerr << "Should not have any unmaterialized functions!\n"; abort(); + case GlobalValue::DLLImportLinkage: + std::cerr << "DLLImport linkage is not supported by this target!\n"; + abort(); + case GlobalValue::DLLExportLinkage: + std::cerr << "DLLExport linkage is not supported by this target!\n"; + abort(); + default: + assert(0 && "Unknown linkage type!"); } O << "\t.align " << Align << "\n"; diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp index b17cde18de2..1ce24fda0cf 100755 --- a/lib/Target/X86/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp @@ -48,10 +48,13 @@ bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { SwitchToTextSection(TAI->getTextSection(), F); EmitAlignment(4, F); // FIXME: This should be parameterized somewhere. break; + case Function::DLLExportLinkage: + DLLExportedFns.insert(Mang->makeNameProper(F->getName(), "")); + //FALLS THROUGH case Function::ExternalLinkage: SwitchToTextSection(TAI->getTextSection(), F); EmitAlignment(4, F); // FIXME: This should be parameterized somewhere. - O << "\t.globl\t" << CurrentFnName << "\n"; + O << "\t.globl\t" << CurrentFnName << "\n"; break; case Function::WeakLinkage: case Function::LinkOnceLinkage: @@ -179,8 +182,9 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, bool isMemOp = Modifier && !strcmp(Modifier, "mem"); if (!isMemOp && !isCallOp) O << '$'; - GlobalValue *GV = MO.getGlobal(); + GlobalValue *GV = MO.getGlobal(); std::string Name = Mang->getValueName(GV); + bool isExt = (GV->isExternal() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()); if (X86PICStyle == PICStyle::Stub && @@ -196,13 +200,27 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, GVStubs.insert(Name); O << "L" << Name << "$non_lazy_ptr"; } - } else + } else { + if (GV->hasDLLImportLinkage()) { + // FIXME: This should be fixed with full support of stdcall & fastcall + // CC's + O << "__imp_"; + } O << Name; + } + if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_) O << "-\"L" << getFunctionNumber() << "$pb\""; - } else + } else { + if (GV->hasDLLImportLinkage()) { + // FIXME: This should be fixed with full support of stdcall & fastcall + // CC's + O << "__imp_"; + } O << Name; - + + } + int Offset = MO.getOffset(); if (Offset > 0) O << "+" << Offset; diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index b634d13ea4a..08dc7b26502 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -112,6 +112,9 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { case GlobalValue::AppendingLinkage: // FIXME: appending linkage variables should go into a section of // their name or something. For now, just emit them as external. + case GlobalValue::DLLExportLinkage: + DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),"")); + // FALL THROUGH case GlobalValue::ExternalLinkage: // If external or appending, declare as a global symbol O << "\t.globl " << name << "\n"; @@ -134,6 +137,27 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { } } + // Output linker support code for dllexported globals + if (DLLExportedGVs.begin() != DLLExportedGVs.end()) { + SwitchToDataSection(".section .drectve", 0); + } + + for (std::set::iterator i = DLLExportedGVs.begin(), + e = DLLExportedGVs.end(); + i != e; ++i) { + O << "\t.ascii \" -export:" << *i << ",data\"\n"; + } + + if (DLLExportedFns.begin() != DLLExportedFns.end()) { + SwitchToDataSection(".section .drectve", 0); + } + + for (std::set::iterator i = DLLExportedFns.begin(), + e = DLLExportedFns.end(); + i != e; ++i) { + O << "\t.ascii \" -export:" << *i << "\"\n"; + } + if (Subtarget->isTargetDarwin()) { SwitchToDataSection("", 0); diff --git a/lib/Target/X86/X86AsmPrinter.h b/lib/Target/X86/X86AsmPrinter.h index 6db9e45dc3b..ae03ca5382d 100755 --- a/lib/Target/X86/X86AsmPrinter.h +++ b/lib/Target/X86/X86AsmPrinter.h @@ -63,6 +63,9 @@ struct VISIBILITY_HIDDEN X86SharedAsmPrinter : public AsmPrinter { // Necessary for Darwin to print out the apprioriate types of linker stubs std::set FnStubs, GVStubs, LinkOnceStubs; + // Necessary for dllexport support + std::set DLLExportedFns, DLLExportedGVs; + inline static bool isScale(const MachineOperand &MO) { return MO.isImmediate() && (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 || diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index dfd7aa59044..166345c2b21 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1964,6 +1964,15 @@ static bool DarwinGVRequiresExtraLoad(GlobalValue *GV) { (GV->isExternal() && !GV->hasNotBeenReadFromBytecode())); } +/// WinndowsGVRequiresExtraLoad - true if accessing the GV requires an extra +/// load. For Windows, dllimported variables (not functions!) are indirect, +/// loading the value at address GV rather then the value of GV itself. This +/// means that the GlobalAddress must be in the base or index register of the +/// address, not the GV offset field. +static bool WindowsGVRequiresExtraLoad(GlobalValue *GV) { + return (isa((Value*)GV) && GV->hasDLLImportLinkage()); +} + /// isUndefOrInRange - Op is either an undef node or a ConstantSDNode. Return /// true if Op is undef or if its value falls within the specified range (L, H]. static bool isUndefOrInRange(SDOperand Op, unsigned Low, unsigned Hi) { @@ -3376,7 +3385,14 @@ X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) { DarwinGVRequiresExtraLoad(GV)) Result = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), Result, DAG.getSrcValue(NULL)); + } else if (Subtarget->isTargetCygwin() || Subtarget->isTargetWindows()) { + // FIXME: What's about PIC? + if (WindowsGVRequiresExtraLoad(GV)) { + Result = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), + Result, DAG.getSrcValue(NULL)); + } } + return Result; } diff --git a/lib/Target/X86/X86IntelAsmPrinter.cpp b/lib/Target/X86/X86IntelAsmPrinter.cpp index 24dbb15941d..44a218ca1eb 100755 --- a/lib/Target/X86/X86IntelAsmPrinter.cpp +++ b/lib/Target/X86/X86IntelAsmPrinter.cpp @@ -35,10 +35,23 @@ bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) { EmitConstantPool(MF.getConstantPool()); // Print out labels for the function. - SwitchToTextSection("_text", MF.getFunction()); - EmitAlignment(4); - if (MF.getFunction()->getLinkage() == GlobalValue::ExternalLinkage) + const Function* F = MF.getFunction(); + switch (F->getLinkage()) { + default: assert(0 && "Unsupported linkage type!"); + case Function::InternalLinkage: + SwitchToTextSection("_text", F); + EmitAlignment(4); + break; + case Function::DLLExportLinkage: + DLLExportedFns.insert(CurrentFnName); + //FALLS THROUGH + case Function::ExternalLinkage: O << "\tpublic " << CurrentFnName << "\n"; + SwitchToTextSection("_text", F); + EmitAlignment(4); + break; + } + O << CurrentFnName << "\tproc near\n"; // Print out code for the function. @@ -118,8 +131,15 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO, case MachineOperand::MO_GlobalAddress: { bool isCallOp = Modifier && !strcmp(Modifier, "call"); bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + GlobalValue *GV = MO.getGlobal(); + if (!isMemOp && !isCallOp) O << "OFFSET "; - O << Mang->getValueName(MO.getGlobal()); + if (GV->hasDLLImportLinkage()) { + // FIXME: This should be fixed with full support of stdcall & fastcall + // CC's + O << "__imp_"; + } + O << Mang->getValueName(GV); int Offset = MO.getOffset(); if (Offset > 0) O << " + " << Offset; @@ -350,6 +370,9 @@ bool X86IntelAsmPrinter::doFinalization(Module &M) { // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256 // are also available. break; + case GlobalValue::DLLExportLinkage: + DLLExportedGVs.insert(name); + // FALL THROUGH case GlobalValue::ExternalLinkage: O << "\tpublic " << name << "\n"; // FALL THROUGH @@ -371,6 +394,34 @@ bool X86IntelAsmPrinter::doFinalization(Module &M) { if (bCustomSegment) O << name << "?\tends\n"; } + + // Output linker support code for dllexported globals + if ((DLLExportedGVs.begin() != DLLExportedGVs.end()) || + (DLLExportedFns.begin() != DLLExportedFns.end())) { + SwitchToDataSection("", 0); + O << "; WARNING: The following code is valid only with MASM v8.x and (possible) higher\n" + << "; This version of MASM is usually shipped with Microsoft Visual Studio 2005\n" + << "; or (possible) further versions. Unfortunately, there is no way to support\n" + << "; dllexported symbols in the earlier versions of MASM in fully automatic way\n\n"; + O << "_drectve\t segment info alias('.drectve')\n"; + } + + for (std::set::iterator i = DLLExportedGVs.begin(), + e = DLLExportedGVs.end(); + i != e; ++i) { + O << "\t db ' /EXPORT:" << *i << ",data'\n"; + } + + for (std::set::iterator i = DLLExportedFns.begin(), + e = DLLExportedFns.end(); + i != e; ++i) { + O << "\t db ' /EXPORT:" << *i << "'\n"; + } + + if ((DLLExportedGVs.begin() != DLLExportedGVs.end()) || + (DLLExportedFns.begin() != DLLExportedFns.end())) { + O << "_drectve\t ends\n"; + } // Bypass X86SharedAsmPrinter::doFinalization(). AsmPrinter::doFinalization(M); diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index 224ebcd3081..6e0d1dbae6e 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -99,6 +99,8 @@ public: bool isTargetDarwin() const { return TargetType == isDarwin; } bool isTargetELF() const { return TargetType == isELF; } + bool isTargetWindows() const { return TargetType == isWindows; } + bool isTargetCygwin() const { return TargetType == isCygwin; } }; } // End llvm namespace diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 8324b432e89..609bd94aa1a 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -1245,7 +1245,7 @@ static Constant *getVal(std::map &ComputedValues, static bool isSimpleEnoughPointerToCommit(Constant *C) { if (GlobalVariable *GV = dyn_cast(C)) { if (!GV->hasExternalLinkage() && !GV->hasInternalLinkage()) - return false; // do not allow weak/linkonce linkage. + return false; // do not allow weak/linkonce/dllimport/dllexport linkage. return !GV->isExternal(); // reject external globals. } if (ConstantExpr *CE = dyn_cast(C)) @@ -1254,7 +1254,7 @@ static bool isSimpleEnoughPointerToCommit(Constant *C) { isa(CE->getOperand(0))) { GlobalVariable *GV = cast(CE->getOperand(0)); if (!GV->hasExternalLinkage() && !GV->hasInternalLinkage()) - return false; // do not allow weak/linkonce linkage. + return false; // do not allow weak/linkonce/dllimport/dllexport linkage. return GV->hasInitializer() && ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE); } diff --git a/lib/Transforms/IPO/SimplifyLibCalls.cpp b/lib/Transforms/IPO/SimplifyLibCalls.cpp index 79cdf28e0a4..9f9c52788bc 100644 --- a/lib/Transforms/IPO/SimplifyLibCalls.cpp +++ b/lib/Transforms/IPO/SimplifyLibCalls.cpp @@ -178,8 +178,10 @@ public: // All the "well-known" functions are external and have external linkage // because they live in a runtime library somewhere and were (probably) // not compiled by LLVM. So, we only act on external functions that - // have external linkage and non-empty uses. - if (!FI->isExternal() || !FI->hasExternalLinkage() || FI->use_empty()) + // have external or dllimport linkage and non-empty uses. + if (!FI->isExternal() || + !(FI->hasExternalLinkage() || FI->hasDLLImportLinkage()) || + FI->use_empty()) continue; // Get the optimization class that pertains to this function diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index f3bcfb53ba5..b6f5fb37a3e 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -845,14 +845,21 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->hasName()) Out << getLLVMName(GV->getName()) << " = "; if (!GV->hasInitializer()) - Out << "external "; + switch (GV->getLinkage()) { + case GlobalValue::DLLImportLinkage: Out << "dllimport "; break; + case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break; + default: Out << "external "; break; + } else switch (GV->getLinkage()) { - 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; + 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::DLLImportLinkage: Out << "dllimport "; break; + case GlobalValue::DLLExportLinkage: Out << "dllexport "; break; + case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break; + case GlobalValue::ExternalLinkage: break; case GlobalValue::GhostLinkage: std::cerr << "GhostLinkage not allowed in AsmWriter!\n"; abort(); @@ -937,13 +944,20 @@ void AssemblyWriter::printFunction(const Function *F) { if (AnnotationWriter) AnnotationWriter->emitFunctionAnnot(F, Out); if (F->isExternal()) - Out << "declare "; + switch (F->getLinkage()) { + case GlobalValue::DLLImportLinkage: Out << "declare dllimport "; break; + case GlobalValue::ExternalWeakLinkage: Out << "declare extern_weak "; break; + default: Out << "declare "; + } else switch (F->getLinkage()) { - 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::InternalLinkage: Out << "internal "; break; + case GlobalValue::LinkOnceLinkage: Out << "linkonce "; break; + case GlobalValue::WeakLinkage: Out << "weak "; break; + case GlobalValue::AppendingLinkage: Out << "appending "; break; + case GlobalValue::DLLImportLinkage: Out << "dllimport "; break; + case GlobalValue::DLLExportLinkage: Out << "dllexport "; break; + case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break; case GlobalValue::ExternalLinkage: break; case GlobalValue::GhostLinkage: std::cerr << "GhostLinkage not allowed in AsmWriter!\n"; diff --git a/lib/VMCore/Mangler.cpp b/lib/VMCore/Mangler.cpp index 8715498b9cd..b3211a31530 100644 --- a/lib/VMCore/Mangler.cpp +++ b/lib/VMCore/Mangler.cpp @@ -162,11 +162,16 @@ void Mangler::InsertName(GlobalValue *GV, ExistingValue = GV; } else { // If GV is external but the existing one is static, mangle the existing one - if (GV->hasExternalLinkage() && !ExistingValue->hasExternalLinkage()) { + if ((GV->hasExternalLinkage() || GV->hasDLLImportLinkage()) && + !(ExistingValue->hasExternalLinkage() || ExistingValue->hasDLLImportLinkage())) { MangledGlobals.insert(ExistingValue); ExistingValue = GV; - } else if (GV->hasExternalLinkage() && ExistingValue->hasExternalLinkage()&& - GV->isExternal() && ExistingValue->isExternal()) { + } else if ((GV->hasExternalLinkage() || + GV->hasDLLImportLinkage()) && + (ExistingValue->hasExternalLinkage() || + ExistingValue->hasDLLImportLinkage()) && + GV->isExternal() && + ExistingValue->isExternal()) { // If the two globals both have external inkage, and are both external, // don't mangle either of them, we just have some silly type mismatch. } else { diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 606a43f0751..cbef68b7dc3 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -257,8 +257,16 @@ namespace { // Anonymous namespace for class void Verifier::visitGlobalValue(GlobalValue &GV) { - Assert1(!GV.isExternal() || GV.hasExternalLinkage(), - "Global is external, but doesn't have external linkage!", &GV); + Assert1(!GV.isExternal() || + GV.hasExternalLinkage() || + GV.hasDLLImportLinkage() || + GV.hasExternalWeakLinkage(), + "Global is external, but doesn't have external or dllimport or weak linkage!", + &GV); + + Assert1(!GV.hasDLLImportLinkage() || GV.isExternal(), + "Global is marked as dllimport, but not external", &GV); + Assert1(!GV.hasAppendingLinkage() || isa(GV), "Only global variables can have appending linkage!", &GV); diff --git a/tools/llvm2cpp/CppWriter.cpp b/tools/llvm2cpp/CppWriter.cpp index 0438a7e5d69..66ed5b257c7 100644 --- a/tools/llvm2cpp/CppWriter.cpp +++ b/tools/llvm2cpp/CppWriter.cpp @@ -284,6 +284,12 @@ CppWriter::printLinkageType(GlobalValue::LinkageTypes LT) { Out << "GlobalValue::AppendingLinkage"; break; case GlobalValue::ExternalLinkage: Out << "GlobalValue::ExternalLinkage"; break; + case GlobalValue::DLLImportLinkage: + Out << "GlobalValue::DllImportLinkage"; break; + case GlobalValue::DLLExportLinkage: + Out << "GlobalValue::DllExportLinkage"; break; + case GlobalValue::ExternalWeakLinkage: + Out << "GlobalValue::ExternalWeakLinkage"; break; case GlobalValue::GhostLinkage: Out << "GlobalValue::GhostLinkage"; break; } -- 2.34.1