From: Nico Rieck Date: Tue, 14 Jan 2014 15:22:47 +0000 (+0000) Subject: Decouple dllexport/dllimport from linkage X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=38f68c5a2e3993a3ae51421d82e57ccca8f6ec38 Decouple dllexport/dllimport from linkage Representing dllexport/dllimport as distinct linkage types prevents using these attributes on templates and inline functions. Instead of introducing further mixed linkage types to include linkonce and weak ODR, the old import/export linkage types are replaced with a new separate visibility-like specifier: define available_externally dllimport void @f() {} @Var = dllexport global i32 1, align 4 Linkage for dllexported globals and functions is now equal to their linkage without dllexport. Imported globals and functions must be either declarations with external linkage, or definitions with AvailableExternallyLinkage. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199218 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/BitCodeFormat.rst b/docs/BitCodeFormat.rst index 89531dcfea6..9363a62d080 100644 --- a/docs/BitCodeFormat.rst +++ b/docs/BitCodeFormat.rst @@ -658,7 +658,7 @@ for each library name referenced. MODULE_CODE_GLOBALVAR Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``[GLOBALVAR, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, unnamed_addr]`` +``[GLOBALVAR, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, unnamed_addr, dllstorageclass]`` The ``GLOBALVAR`` record (code 7) marks the declaration or definition of a global variable. The operand fields are: @@ -713,12 +713,20 @@ global variable. The operand fields are: * *unnamed_addr*: If present and non-zero, indicates that the variable has ``unnamed_addr`` +.. _dllstorageclass: + +* *dllstorageclass*: If present, an encoding of the DLL storage class of this variable: + + * ``default``: code 0 + * ``dllimport``: code 1 + * ``dllexport``: code 2 + .. _FUNCTION: MODULE_CODE_FUNCTION Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prefix]`` +``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prefix, dllstorageclass]`` The ``FUNCTION`` record (code 8) marks the declaration or definition of a function. The operand fields are: @@ -762,10 +770,12 @@ function. The operand fields are: * *prefix*: If non-zero, the value index of the prefix data for this function, plus 1. +* *dllstorageclass*: An encoding of the `dllstorageclass`_ of this function + MODULE_CODE_ALIAS Record ^^^^^^^^^^^^^^^^^^^^^^^^ -``[ALIAS, alias type, aliasee val#, linkage, visibility]`` +``[ALIAS, alias type, aliasee val#, linkage, visibility, dllstorageclass]`` The ``ALIAS`` record (code 9) marks the definition of an alias. The operand fields are @@ -778,6 +788,8 @@ fields are * *visibility*: If present, an encoding of the `visibility`_ of the alias +* *dllstorageclass*: If present, an encoding of the `dllstorageclass`_ of the alias + MODULE_CODE_PURGEVALS Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/LangRef.rst b/docs/LangRef.rst index ffe3f09d83b..3540bdec8ac 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -274,27 +274,8 @@ linkage: visible, meaning that it participates in linkage and can be used to resolve external symbol references. -The next two types of linkage are targeted for Microsoft Windows -platform only. They are designed to support importing (exporting) -symbols from (to) DLLs (Dynamic Link Libraries). - -``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. Since this linkage exists for defining a dll interface, the - compiler, assembler and linker know it is externally referenced and - must refrain from deleting the symbol. - It is illegal for a function *declaration* to have any linkage type -other than ``external``, ``dllimport`` or ``extern_weak``. +other than ``external`` or ``extern_weak``. .. _callingconv: @@ -416,6 +397,25 @@ styles: .. _namedtypes: +DLL Storage Classes +------------------- + +All Global Variables, Functions and Aliases can have one of the following +DLL storage class: + +``dllimport`` + "``dllimport``" 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``" 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. Since this storage class + exists for defining a dll interface, the compiler, assembler and linker know + it is externally referenced and must refrain from deleting the symbol. + Named Types ----------- @@ -529,6 +529,15 @@ assume that the globals are densely packed in their section and try to iterate over them as an array, alignment padding would break this iteration. +Globals can also have a :ref:`DLL storage class `. + +Syntax:: + + [@ =] [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] + [AddrSpace] [unnamed_addr] [ExternallyInitialized] + + [, section "name"] [, align ] + For example, the following defines a global in a numbered address space with an initializer, section, and alignment: @@ -556,7 +565,8 @@ Functions LLVM function definitions consist of the "``define``" keyword, an optional :ref:`linkage type `, an optional :ref:`visibility -style `, an optional :ref:`calling convention `, +style `, an optional :ref:`DLL storage class `, +an optional :ref:`calling convention `, an optional ``unnamed_addr`` attribute, a return type, an optional :ref:`parameter attribute ` for the return type, a function name, a (possibly empty) argument list (each with optional :ref:`parameter @@ -567,7 +577,8 @@ curly brace, a list of basic blocks, and a closing curly brace. LLVM function declarations consist of the "``declare``" keyword, an optional :ref:`linkage type `, an optional :ref:`visibility -style `, an optional :ref:`calling convention `, +style `, an optional :ref:`DLL storage class `, +an optional :ref:`calling convention `, an optional ``unnamed_addr`` attribute, a return type, an optional :ref:`parameter attribute ` for the return type, a function name, a possibly empty list of arguments, an optional alignment, an optional @@ -603,7 +614,7 @@ be significant and two identical functions can be merged. Syntax:: - define [linkage] [visibility] + define [linkage] [visibility] [DLLStorageClass] [cconv] [ret attrs] @ ([argument list]) [fn Attrs] [section "name"] [align N] @@ -616,12 +627,13 @@ Aliases Aliases act as "second name" for the aliasee value (which can be either function, global variable, another alias or bitcast of global value). -Aliases may have an optional :ref:`linkage type `, and an optional -:ref:`visibility style `. +Aliases may have an optional :ref:`linkage type `, an optional +:ref:`visibility style `, and an optional :ref:`DLL storage class +`. Syntax:: - @ = alias [Linkage] [Visibility] @ + @ = [Visibility] [DLLStorageClass] alias [Linkage] @ The linkage must be one of ``private``, ``linker_private``, ``linker_private_weak``, ``internal``, ``linkonce``, ``weak``, diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 269869ef0da..a84a0313211 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -284,8 +284,8 @@ typedef enum { LLVMInternalLinkage, /**< Rename collisions when linking (static functions) */ LLVMPrivateLinkage, /**< Like Internal, but omit from symbol table */ - LLVMDLLImportLinkage, /**< Function to be imported from DLL */ - LLVMDLLExportLinkage, /**< Function to be accessible from DLL */ + LLVMDLLImportLinkage, /**< Obsolete */ + LLVMDLLExportLinkage, /**< Obsolete */ LLVMExternalWeakLinkage,/**< ExternalWeak linkage description */ LLVMGhostLinkage, /**< Obsolete */ LLVMCommonLinkage, /**< Tentative definitions */ diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 4f20a31a294..5fdf6611e9a 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -42,8 +42,6 @@ public: PrivateLinkage, ///< Like Internal, but omit from symbol table. LinkerPrivateLinkage, ///< Like Private, but linker removes. LinkerPrivateWeakLinkage, ///< Like LinkerPrivate, but weak. - DLLImportLinkage, ///< Function to be imported from DLL - DLLExportLinkage, ///< Function to be accessible from DLL. ExternalWeakLinkage,///< ExternalWeak linkage description. CommonLinkage ///< Tentative definitions. }; @@ -55,11 +53,19 @@ public: ProtectedVisibility ///< The GV is protected }; + /// @brief Storage classes of global values for PE targets. + enum DLLStorageClassTypes { + DefaultStorageClass = 0, + DLLImportStorageClass = 1, ///< Function to be imported from DLL + DLLExportStorageClass = 2 ///< Function to be accessible from DLL. + }; + protected: GlobalValue(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps, LinkageTypes linkage, const Twine &Name) : Constant(ty, vty, Ops, NumOps), Linkage(linkage), - Visibility(DefaultVisibility), Alignment(0), UnnamedAddr(0), Parent(0) { + Visibility(DefaultVisibility), Alignment(0), UnnamedAddr(0), + DllStorageClass(DefaultStorageClass), Parent(0) { setName(Name); } @@ -69,6 +75,7 @@ protected: unsigned Visibility : 2; // The visibility style of this global unsigned Alignment : 16; // Alignment of this symbol, must be power of two unsigned UnnamedAddr : 1; // This value's address is not significant + unsigned DllStorageClass : 2; // DLL storage class Module *Parent; // The containing module. std::string Section; // Section to emit this into, empty mean default public: @@ -91,7 +98,18 @@ public: return Visibility == ProtectedVisibility; } void setVisibility(VisibilityTypes V) { Visibility = V; } - + + DLLStorageClassTypes getDLLStorageClass() const { + return DLLStorageClassTypes(DllStorageClass); + } + bool hasDLLImportStorageClass() const { + return DllStorageClass == DLLImportStorageClass; + } + bool hasDLLExportStorageClass() const { + return DllStorageClass == DLLExportStorageClass; + } + void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; } + bool hasSection() const { return !Section.empty(); } const std::string &getSection() const { return Section; } void setSection(StringRef S) { Section = S; } @@ -146,12 +164,6 @@ public: return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage) || isLinkerPrivateLinkage(Linkage) || isLinkerPrivateWeakLinkage(Linkage); } - static bool isDLLImportLinkage(LinkageTypes Linkage) { - return Linkage == DLLImportLinkage; - } - static bool isDLLExportLinkage(LinkageTypes Linkage) { - return Linkage == DLLExportLinkage; - } static bool isExternalWeakLinkage(LinkageTypes Linkage) { return Linkage == ExternalWeakLinkage; } @@ -209,8 +221,6 @@ public: return isLinkerPrivateWeakLinkage(Linkage); } bool hasLocalLinkage() const { return isLocalLinkage(Linkage); } - bool hasDLLImportLinkage() const { return isDLLImportLinkage(Linkage); } - bool hasDLLExportLinkage() const { return isDLLExportLinkage(Linkage); } bool hasExternalWeakLinkage() const { return isExternalWeakLinkage(Linkage); } bool hasCommonLinkage() const { return isCommonLinkage(Linkage); } diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index a5b2aa586e4..d4d6f7cee14 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -242,8 +242,8 @@ bool LLParser::ParseTopLevelEntities() { // The Global variable production with no name can have many different // optional leading prefixes, the production is: - // GlobalVar ::= OptionalLinkage OptionalVisibility OptionalThreadLocal - // OptionalAddrSpace OptionalUnNammedAddr + // GlobalVar ::= OptionalLinkage OptionalVisibility OptionalDLLStorageClass + // OptionalThreadLocal OptionalAddrSpace OptionalUnNammedAddr // ('constant'|'global') ... case lltok::kw_private: // OptionalLinkage case lltok::kw_linker_private: // OptionalLinkage @@ -254,24 +254,24 @@ bool LLParser::ParseTopLevelEntities() { case lltok::kw_linkonce: // OptionalLinkage case lltok::kw_linkonce_odr: // OptionalLinkage case lltok::kw_appending: // OptionalLinkage - case lltok::kw_dllexport: // OptionalLinkage case lltok::kw_common: // OptionalLinkage - case lltok::kw_dllimport: // OptionalLinkage case lltok::kw_extern_weak: // OptionalLinkage case lltok::kw_external: { // OptionalLinkage - unsigned Linkage, Visibility; + unsigned Linkage, Visibility, DLLStorageClass; if (ParseOptionalLinkage(Linkage) || ParseOptionalVisibility(Visibility) || - ParseGlobal("", SMLoc(), Linkage, true, Visibility)) + ParseOptionalDLLStorageClass(DLLStorageClass) || + ParseGlobal("", SMLoc(), Linkage, true, Visibility, DLLStorageClass)) return true; break; } case lltok::kw_default: // OptionalVisibility case lltok::kw_hidden: // OptionalVisibility case lltok::kw_protected: { // OptionalVisibility - unsigned Visibility; + unsigned Visibility, DLLStorageClass; if (ParseOptionalVisibility(Visibility) || - ParseGlobal("", SMLoc(), 0, false, Visibility)) + ParseOptionalDLLStorageClass(DLLStorageClass) || + ParseGlobal("", SMLoc(), 0, false, Visibility, DLLStorageClass)) return true; break; } @@ -280,7 +280,7 @@ bool LLParser::ParseTopLevelEntities() { case lltok::kw_addrspace: // OptionalAddrSpace case lltok::kw_constant: // GlobalType case lltok::kw_global: // GlobalType - if (ParseGlobal("", SMLoc(), 0, false, 0)) return true; + if (ParseGlobal("", SMLoc(), 0, false, 0, 0)) return true; break; case lltok::kw_attributes: if (ParseUnnamedAttrGrp()) return true; break; @@ -446,9 +446,11 @@ bool LLParser::ParseGlobalType(bool &IsConstant) { /// ParseUnnamedGlobal: /// OptionalVisibility ALIAS ... -/// OptionalLinkage OptionalVisibility ... -> global variable +/// OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// ... -> global variable /// GlobalID '=' OptionalVisibility ALIAS ... -/// GlobalID '=' OptionalLinkage OptionalVisibility ... -> global variable +/// GlobalID '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// ... -> global variable bool LLParser::ParseUnnamedGlobal() { unsigned VarID = NumberedVals.size(); std::string Name; @@ -466,19 +468,22 @@ bool LLParser::ParseUnnamedGlobal() { } bool HasLinkage; - unsigned Linkage, Visibility; + unsigned Linkage, Visibility, DLLStorageClass; if (ParseOptionalLinkage(Linkage, HasLinkage) || - ParseOptionalVisibility(Visibility)) + ParseOptionalVisibility(Visibility) || + ParseOptionalDLLStorageClass(DLLStorageClass)) return true; if (HasLinkage || Lex.getKind() != lltok::kw_alias) - return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility); - return ParseAlias(Name, NameLoc, Visibility); + return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, + DLLStorageClass); + return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass); } /// ParseNamedGlobal: /// GlobalVar '=' OptionalVisibility ALIAS ... -/// GlobalVar '=' OptionalLinkage OptionalVisibility ... -> global variable +/// GlobalVar '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// ... -> global variable bool LLParser::ParseNamedGlobal() { assert(Lex.getKind() == lltok::GlobalVar); LocTy NameLoc = Lex.getLoc(); @@ -486,15 +491,17 @@ bool LLParser::ParseNamedGlobal() { Lex.Lex(); bool HasLinkage; - unsigned Linkage, Visibility; + unsigned Linkage, Visibility, DLLStorageClass; if (ParseToken(lltok::equal, "expected '=' in global variable") || ParseOptionalLinkage(Linkage, HasLinkage) || - ParseOptionalVisibility(Visibility)) + ParseOptionalVisibility(Visibility) || + ParseOptionalDLLStorageClass(DLLStorageClass)) return true; if (HasLinkage || Lex.getKind() != lltok::kw_alias) - return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility); - return ParseAlias(Name, NameLoc, Visibility); + return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, + DLLStorageClass); + return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass); } // MDString: @@ -615,16 +622,17 @@ bool LLParser::ParseStandaloneMetadata() { } /// ParseAlias: -/// ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee +/// ::= GlobalVar '=' OptionalVisibility OptionalDLLStorageClass 'alias' +/// OptionalLinkage Aliasee /// Aliasee /// ::= TypeAndValue /// ::= 'bitcast' '(' TypeAndValue 'to' Type ')' /// ::= 'getelementptr' 'inbounds'? '(' ... ')' /// -/// Everything through visibility has already been parsed. +/// Everything through DLL storage class has already been parsed. /// bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, - unsigned Visibility) { + unsigned Visibility, unsigned DLLStorageClass) { assert(Lex.getKind() == lltok::kw_alias); Lex.Lex(); LocTy LinkageLoc = Lex.getLoc(); @@ -659,6 +667,7 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, (GlobalValue::LinkageTypes)Linkage, Name, Aliasee); GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); // See if this value already exists in the symbol table. If so, it is either // a redefinition or a definition of a forward reference. @@ -691,18 +700,18 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, } /// ParseGlobal -/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalThreadLocal -/// OptionalAddrSpace OptionalUnNammedAddr +/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// OptionalThreadLocal OptionalAddrSpace OptionalUnNammedAddr /// OptionalExternallyInitialized GlobalType Type Const -/// ::= OptionalLinkage OptionalVisibility OptionalThreadLocal -/// OptionalAddrSpace OptionalUnNammedAddr +/// ::= OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// OptionalThreadLocal OptionalAddrSpace OptionalUnNammedAddr /// OptionalExternallyInitialized GlobalType Type Const /// /// Everything through visibility has been parsed already. /// bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, unsigned Linkage, bool HasLinkage, - unsigned Visibility) { + unsigned Visibility, unsigned DLLStorageClass) { unsigned AddrSpace; bool IsConstant, UnnamedAddr, IsExternallyInitialized; GlobalVariable::ThreadLocalMode TLM; @@ -725,8 +734,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, // If the linkage is specified and is external, then no initializer is // present. Constant *Init = 0; - if (!HasLinkage || (Linkage != GlobalValue::DLLImportLinkage && - Linkage != GlobalValue::ExternalWeakLinkage && + if (!HasLinkage || (Linkage != GlobalValue::ExternalWeakLinkage && Linkage != GlobalValue::ExternalLinkage)) { if (ParseGlobalValue(Ty, Init)) return true; @@ -775,6 +783,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, GV->setConstant(IsConstant); GV->setLinkage((GlobalValue::LinkageTypes)Linkage); GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GV->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); GV->setExternallyInitialized(IsExternallyInitialized); GV->setThreadLocalMode(TLM); GV->setUnnamedAddr(UnnamedAddr); @@ -1277,9 +1286,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { /// ::= 'linkonce_odr' /// ::= 'available_externally' /// ::= 'appending' -/// ::= 'dllexport' /// ::= 'common' -/// ::= 'dllimport' /// ::= 'extern_weak' /// ::= 'external' bool LLParser::ParseOptionalLinkage(unsigned &Res, bool &HasLinkage) { @@ -1300,9 +1307,7 @@ bool LLParser::ParseOptionalLinkage(unsigned &Res, bool &HasLinkage) { Res = GlobalValue::AvailableExternallyLinkage; break; case lltok::kw_appending: Res = GlobalValue::AppendingLinkage; break; - case lltok::kw_dllexport: Res = GlobalValue::DLLExportLinkage; break; case lltok::kw_common: Res = GlobalValue::CommonLinkage; break; - case lltok::kw_dllimport: Res = GlobalValue::DLLImportLinkage; break; case lltok::kw_extern_weak: Res = GlobalValue::ExternalWeakLinkage; break; case lltok::kw_external: Res = GlobalValue::ExternalLinkage; break; } @@ -1328,6 +1333,21 @@ bool LLParser::ParseOptionalVisibility(unsigned &Res) { return false; } +/// ParseOptionalDLLStorageClass +/// ::= /*empty*/ +/// ::= 'dllimport' +/// ::= 'dllexport' +/// +bool LLParser::ParseOptionalDLLStorageClass(unsigned &Res) { + switch (Lex.getKind()) { + default: Res = GlobalValue::DefaultStorageClass; return false; + case lltok::kw_dllimport: Res = GlobalValue::DLLImportStorageClass; break; + case lltok::kw_dllexport: Res = GlobalValue::DLLExportStorageClass; break; + } + Lex.Lex(); + return false; +} + /// ParseOptionalCallingConv /// ::= /*empty*/ /// ::= 'ccc' @@ -2934,12 +2954,14 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { unsigned Linkage; unsigned Visibility; + unsigned DLLStorageClass; AttrBuilder RetAttrs; CallingConv::ID CC; Type *RetType = 0; LocTy RetTypeLoc = Lex.getLoc(); if (ParseOptionalLinkage(Linkage) || ParseOptionalVisibility(Visibility) || + ParseOptionalDLLStorageClass(DLLStorageClass) || ParseOptionalCallingConv(CC) || ParseOptionalReturnAttrs(RetAttrs) || ParseType(RetType, RetTypeLoc, true /*void allowed*/)) @@ -2949,7 +2971,6 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { switch ((GlobalValue::LinkageTypes)Linkage) { case GlobalValue::ExternalLinkage: break; // always ok. - case GlobalValue::DLLImportLinkage: case GlobalValue::ExternalWeakLinkage: if (isDefine) return Error(LinkageLoc, "invalid linkage for function definition"); @@ -2963,7 +2984,6 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { case GlobalValue::LinkOnceODRLinkage: case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: - case GlobalValue::DLLExportLinkage: if (!isDefine) return Error(LinkageLoc, "invalid linkage for function declaration"); break; @@ -3110,6 +3130,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { Fn->setLinkage((GlobalValue::LinkageTypes)Linkage); Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility); + Fn->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); Fn->setCallingConv(CC); Fn->setAttributes(PAL); Fn->setUnnamedAddr(UnnamedAddr); diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index ded776c3989..c62979e6f29 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -204,6 +204,7 @@ namespace llvm { bool HasLinkage; return ParseOptionalLinkage(Linkage, HasLinkage); } bool ParseOptionalVisibility(unsigned &Visibility); + bool ParseOptionalDLLStorageClass(unsigned &DLLStorageClass); bool ParseOptionalCallingConv(CallingConv::ID &CC); bool ParseOptionalAlignment(unsigned &Alignment); bool ParseScopeAndOrdering(bool isAtomic, SynchronizationScope &Scope, @@ -234,8 +235,10 @@ namespace llvm { bool ParseUnnamedGlobal(); bool ParseNamedGlobal(); bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage, - bool HasLinkage, unsigned Visibility); - bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility); + bool HasLinkage, unsigned Visibility, + unsigned DLLStorageClass); + bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility, + unsigned DLLStorageClass); bool ParseStandaloneMetadata(); bool ParseNamedMetadata(); bool ParseMDString(MDString *&Result); diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 39a0dfa5006..81ed803ba04 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -80,8 +80,8 @@ static GlobalValue::LinkageTypes GetDecodedLinkage(unsigned Val) { case 2: return GlobalValue::AppendingLinkage; case 3: return GlobalValue::InternalLinkage; case 4: return GlobalValue::LinkOnceAnyLinkage; - case 5: return GlobalValue::DLLImportLinkage; - case 6: return GlobalValue::DLLExportLinkage; + case 5: return GlobalValue::ExternalLinkage; // Obsolete DLLImportLinkage + case 6: return GlobalValue::ExternalLinkage; // Obsolete DLLExportLinkage case 7: return GlobalValue::ExternalWeakLinkage; case 8: return GlobalValue::CommonLinkage; case 9: return GlobalValue::PrivateLinkage; @@ -102,6 +102,16 @@ static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) { } } +static GlobalValue::DLLStorageClassTypes +GetDecodedDLLStorageClass(unsigned Val) { + switch (Val) { + default: // Map unknown values to default. + case 0: return GlobalValue::DefaultStorageClass; + case 1: return GlobalValue::DLLImportStorageClass; + case 2: return GlobalValue::DLLExportStorageClass; + } +} + static GlobalVariable::ThreadLocalMode GetDecodedThreadLocalMode(unsigned Val) { switch (Val) { case 0: return GlobalVariable::NotThreadLocal; @@ -193,6 +203,13 @@ static SynchronizationScope GetDecodedSynchScope(unsigned Val) { } } +static void UpgradeDLLImportExportLinkage(llvm::GlobalValue *GV, unsigned Val) { + switch (Val) { + case 5: GV->setDLLStorageClass(GlobalValue::DLLImportStorageClass); break; + case 6: GV->setDLLStorageClass(GlobalValue::DLLExportStorageClass); break; + } +} + namespace llvm { namespace { /// @brief A class for maintaining the slot number definition @@ -1797,7 +1814,7 @@ error_code BitcodeReader::ParseModule(bool Resume) { } // GLOBALVAR: [pointer type, isconst, initid, // linkage, alignment, section, visibility, threadlocal, - // unnamed_addr] + // unnamed_addr, dllstorageclass] case bitc::MODULE_CODE_GLOBALVAR: { if (Record.size() < 6) return Error(InvalidRecord); @@ -1843,6 +1860,11 @@ error_code BitcodeReader::ParseModule(bool Resume) { NewGV->setVisibility(Visibility); NewGV->setUnnamedAddr(UnnamedAddr); + if (Record.size() > 10) + NewGV->setDLLStorageClass(GetDecodedDLLStorageClass(Record[10])); + else + UpgradeDLLImportExportLinkage(NewGV, Record[3]); + ValueList.push_back(NewGV); // Remember which value to use for the global initializer. @@ -1851,7 +1873,8 @@ error_code BitcodeReader::ParseModule(bool Resume) { break; } // FUNCTION: [type, callingconv, isproto, linkage, paramattr, - // alignment, section, visibility, gc, unnamed_addr] + // alignment, section, visibility, gc, unnamed_addr, + // dllstorageclass] case bitc::MODULE_CODE_FUNCTION: { if (Record.size() < 8) return Error(InvalidRecord); @@ -1891,6 +1914,12 @@ error_code BitcodeReader::ParseModule(bool Resume) { Func->setUnnamedAddr(UnnamedAddr); if (Record.size() > 10 && Record[10] != 0) FunctionPrefixes.push_back(std::make_pair(Func, Record[10]-1)); + + if (Record.size() > 11) + Func->setDLLStorageClass(GetDecodedDLLStorageClass(Record[11])); + else + UpgradeDLLImportExportLinkage(Func, Record[3]); + ValueList.push_back(Func); // If this is a function with a body, remember the prototype we are @@ -1902,7 +1931,7 @@ error_code BitcodeReader::ParseModule(bool Resume) { break; } // ALIAS: [alias type, aliasee val#, linkage] - // ALIAS: [alias type, aliasee val#, linkage, visibility] + // ALIAS: [alias type, aliasee val#, linkage, visibility, dllstorageclass] case bitc::MODULE_CODE_ALIAS: { if (Record.size() < 3) return Error(InvalidRecord); @@ -1917,6 +1946,10 @@ error_code BitcodeReader::ParseModule(bool Resume) { // Old bitcode files didn't have visibility field. if (Record.size() > 3) NewGA->setVisibility(GetDecodedVisibility(Record[3])); + if (Record.size() > 4) + NewGA->setDLLStorageClass(GetDecodedDLLStorageClass(Record[4])); + else + UpgradeDLLImportExportLinkage(NewGA, Record[2]); ValueList.push_back(NewGA); AliasInits.push_back(std::make_pair(NewGA, Record[1])); break; diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index be19b781d4a..1d763d66ddc 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -481,8 +481,6 @@ static unsigned getEncodedLinkage(const GlobalValue *GV) { case GlobalValue::AppendingLinkage: return 2; case GlobalValue::InternalLinkage: return 3; case GlobalValue::LinkOnceAnyLinkage: return 4; - case GlobalValue::DLLImportLinkage: return 5; - case GlobalValue::DLLExportLinkage: return 6; case GlobalValue::ExternalWeakLinkage: return 7; case GlobalValue::CommonLinkage: return 8; case GlobalValue::PrivateLinkage: return 9; @@ -504,6 +502,15 @@ static unsigned getEncodedVisibility(const GlobalValue *GV) { llvm_unreachable("Invalid visibility"); } +static unsigned getEncodedDLLStorageClass(const GlobalValue *GV) { + switch (GV->getDLLStorageClass()) { + case GlobalValue::DefaultStorageClass: return 0; + case GlobalValue::DLLImportStorageClass: return 1; + case GlobalValue::DLLExportStorageClass: return 2; + } + llvm_unreachable("Invalid DLL storage class"); +} + static unsigned getEncodedThreadLocalMode(const GlobalVariable *GV) { switch (GV->getThreadLocalMode()) { case GlobalVariable::NotThreadLocal: return 0; @@ -607,7 +614,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, // GLOBALVAR: [type, isconst, initid, // linkage, alignment, section, visibility, threadlocal, - // unnamed_addr, externally_initialized] + // unnamed_addr, externally_initialized, dllstorageclass] Vals.push_back(VE.getTypeID(GV->getType())); Vals.push_back(GV->isConstant()); Vals.push_back(GV->isDeclaration() ? 0 : @@ -617,11 +624,13 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0); if (GV->isThreadLocal() || GV->getVisibility() != GlobalValue::DefaultVisibility || - GV->hasUnnamedAddr() || GV->isExternallyInitialized()) { + GV->hasUnnamedAddr() || GV->isExternallyInitialized() || + GV->getDLLStorageClass() != GlobalValue::DefaultStorageClass) { Vals.push_back(getEncodedVisibility(GV)); Vals.push_back(getEncodedThreadLocalMode(GV)); Vals.push_back(GV->hasUnnamedAddr()); Vals.push_back(GV->isExternallyInitialized()); + Vals.push_back(getEncodedDLLStorageClass(GV)); } else { AbbrevToUse = SimpleGVarAbbrev; } @@ -646,6 +655,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Vals.push_back(F->hasUnnamedAddr()); Vals.push_back(F->hasPrefixData() ? (VE.getValueID(F->getPrefixData()) + 1) : 0); + Vals.push_back(getEncodedDLLStorageClass(F)); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); @@ -660,6 +670,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Vals.push_back(VE.getValueID(AI->getAliasee())); Vals.push_back(getEncodedLinkage(AI)); Vals.push_back(getEncodedVisibility(AI)); + Vals.push_back(getEncodedDLLStorageClass(AI)); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse); Vals.clear(); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 5a8e8cc2f02..cf950f8cc75 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -257,7 +257,6 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); } return; - case GlobalValue::DLLExportLinkage: case GlobalValue::AppendingLinkage: // FIXME: appending linkage variables should go into a section of // their name or something. For now, just emit them as external. @@ -272,7 +271,6 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { return; case GlobalValue::AvailableExternallyLinkage: llvm_unreachable("Should never emit this"); - case GlobalValue::DLLImportLinkage: case GlobalValue::ExternalWeakLinkage: llvm_unreachable("Don't know how to emit these"); } diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index abc8877ec59..88ec5b3e6a9 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -1211,9 +1211,7 @@ void ExecutionEngine::emitGlobals() { } // If the existing global is strong, never replace it. - if (GVEntry->hasExternalLinkage() || - GVEntry->hasDLLImportLinkage() || - GVEntry->hasDLLExportLinkage()) + if (GVEntry->hasExternalLinkage()) continue; // Otherwise, we know it's linkonce/weak, replace it if this is a strong diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 91684c9c70e..eba05c5f28e 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1367,8 +1367,6 @@ static void PrintLinkage(GlobalValue::LinkageTypes LT, case GlobalValue::WeakODRLinkage: Out << "weak_odr "; break; case GlobalValue::CommonLinkage: Out << "common "; 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::AvailableExternallyLinkage: Out << "available_externally "; @@ -1386,6 +1384,15 @@ static void PrintVisibility(GlobalValue::VisibilityTypes Vis, } } +static void PrintDLLStorageClass(GlobalValue::DLLStorageClassTypes SCT, + formatted_raw_ostream &Out) { + switch (SCT) { + case GlobalValue::DefaultStorageClass: break; + case GlobalValue::DLLImportStorageClass: Out << "dllimport "; break; + case GlobalValue::DLLExportStorageClass: Out << "dllexport "; break; + } +} + static void PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM, formatted_raw_ostream &Out) { switch (TLM) { @@ -1418,6 +1425,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { PrintLinkage(GV->getLinkage(), Out); PrintVisibility(GV->getVisibility(), Out); + PrintDLLStorageClass(GV->getDLLStorageClass(), Out); PrintThreadLocalModel(GV->getThreadLocalMode(), Out); if (unsigned AddressSpace = GV->getType()->getAddressSpace()) @@ -1455,6 +1463,7 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { Out << " = "; } PrintVisibility(GA->getVisibility(), Out); + PrintDLLStorageClass(GA->getDLLStorageClass(), Out); Out << "alias "; @@ -1552,6 +1561,7 @@ void AssemblyWriter::printFunction(const Function *F) { PrintLinkage(F->getLinkage(), Out); PrintVisibility(F->getVisibility(), Out); + PrintDLLStorageClass(F->getDLLStorageClass(), Out); // Print the calling convention. if (F->getCallingConv() != CallingConv::C) { diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index ff4976bcbf9..6e920a2daa4 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -1164,10 +1164,6 @@ LLVMLinkage LLVMGetLinkage(LLVMValueRef Global) { return LLVMLinkerPrivateLinkage; case GlobalValue::LinkerPrivateWeakLinkage: return LLVMLinkerPrivateWeakLinkage; - case GlobalValue::DLLImportLinkage: - return LLVMDLLImportLinkage; - case GlobalValue::DLLExportLinkage: - return LLVMDLLExportLinkage; case GlobalValue::ExternalWeakLinkage: return LLVMExternalWeakLinkage; case GlobalValue::CommonLinkage: @@ -1219,10 +1215,12 @@ void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage) { GV->setLinkage(GlobalValue::LinkerPrivateWeakLinkage); break; case LLVMDLLImportLinkage: - GV->setLinkage(GlobalValue::DLLImportLinkage); + DEBUG(errs() + << "LLVMSetLinkage(): LLVMDLLImportLinkage is no longer supported."); break; case LLVMDLLExportLinkage: - GV->setLinkage(GlobalValue::DLLExportLinkage); + DEBUG(errs() + << "LLVMSetLinkage(): LLVMDLLExportLinkage is no longer supported."); break; case LLVMExternalWeakLinkage: GV->setLinkage(GlobalValue::ExternalWeakLinkage); diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 9e150e85756..d8e5c89598e 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -421,16 +421,12 @@ void Verifier::visitGlobalValue(GlobalValue &GV) { Assert1(!GV.isDeclaration() || GV.isMaterializable() || GV.hasExternalLinkage() || - GV.hasDLLImportLinkage() || GV.hasExternalWeakLinkage() || (isa(GV) && (GV.hasLocalLinkage() || GV.hasWeakLinkage())), - "Global is external, but doesn't have external or dllimport or weak linkage!", + "Global is external, but doesn't have external or weak linkage!", &GV); - Assert1(!GV.hasDLLImportLinkage() || GV.isDeclaration(), - "Global is marked as dllimport, but not external", &GV); - Assert1(!GV.hasAppendingLinkage() || isa(GV), "Only global variables can have appending linkage!", &GV); @@ -456,8 +452,7 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { &GV); } } else { - Assert1(GV.hasExternalLinkage() || GV.hasDLLImportLinkage() || - GV.hasExternalWeakLinkage(), + Assert1(GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(), "invalid linkage type for global declaration", &GV); } @@ -502,6 +497,11 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { } } + Assert1(!GV.hasDLLImportStorageClass() || + (GV.isDeclaration() && GV.hasExternalLinkage()) || + GV.hasAvailableExternallyLinkage(), + "Global is marked as dllimport, but not external", &GV); + if (!GV.hasInitializer()) { visitGlobalValue(GV); return; @@ -1078,8 +1078,7 @@ void Verifier::visitFunction(Function &F) { if (F.isMaterializable()) { // Function has a body somewhere we can't see. } else if (F.isDeclaration()) { - Assert1(F.hasExternalLinkage() || F.hasDLLImportLinkage() || - F.hasExternalWeakLinkage(), + Assert1(F.hasExternalLinkage() || F.hasExternalWeakLinkage(), "invalid linkage type for function declaration", &F); } else { // Verify that this function (which has a body) is not named "llvm.*". It @@ -1105,6 +1104,11 @@ void Verifier::visitFunction(Function &F) { if (F.hasAddressTaken(&U)) Assert1(0, "Invalid user of intrinsic instruction!", U); } + + Assert1(!F.hasDLLImportStorageClass() || + (F.isDeclaration() && F.hasExternalLinkage()) || + F.hasAvailableExternallyLinkage(), + "Function is marked as dllimport, but not external.", &F); } // verifyBasicBlock - Verify that a basic block is well formed... diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 8f2200e4ea2..4d039eb2c6d 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -543,8 +543,8 @@ bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src, if (SrcIsDeclaration) { // If Src is external or if both Src & Dest 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 (Src->hasDLLImportStorageClass()) { + // If one of GVs is marked as DLLImport, result should be dllimport'ed. if (DestIsDeclaration) { LinkFromSrc = true; LT = Src->getLinkage(); @@ -557,7 +557,7 @@ bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src, LinkFromSrc = false; LT = Dest->getLinkage(); } - } else if (DestIsDeclaration && !Dest->hasDLLImportLinkage()) { + } else if (DestIsDeclaration && !Dest->hasDLLImportStorageClass()) { // If Dest is external but Src is not: LinkFromSrc = true; LT = Src->getLinkage(); @@ -584,10 +584,8 @@ bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src, LT = GlobalValue::ExternalLinkage; } } else { - assert((Dest->hasExternalLinkage() || Dest->hasDLLImportLinkage() || - Dest->hasDLLExportLinkage() || Dest->hasExternalWeakLinkage()) && - (Src->hasExternalLinkage() || Src->hasDLLImportLinkage() || - Src->hasDLLExportLinkage() || Src->hasExternalWeakLinkage()) && + assert((Dest->hasExternalLinkage() || Dest->hasExternalWeakLinkage()) && + (Src->hasExternalLinkage() || Src->hasExternalWeakLinkage()) && "Unexpected linkage type!"); return emitError("Linking globals named '" + Src->getName() + "': symbol multiply defined!"); diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 6e2dd0a8e7b..b13709914bf 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -131,6 +131,7 @@ namespace { private: void printLinkageType(GlobalValue::LinkageTypes LT); void printVisibilityType(GlobalValue::VisibilityTypes VisTypes); + void printDLLStorageClassType(GlobalValue::DLLStorageClassTypes DSCType); void printThreadLocalMode(GlobalVariable::ThreadLocalMode TLM); void printCallingConv(CallingConv::ID cc); void printEscapedString(const std::string& str); @@ -300,10 +301,6 @@ void 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::CommonLinkage: @@ -325,6 +322,21 @@ void CppWriter::printVisibilityType(GlobalValue::VisibilityTypes VisType) { } } +void CppWriter::printDLLStorageClassType( + GlobalValue::DLLStorageClassTypes DSCType) { + switch (DSCType) { + case GlobalValue::DefaultStorageClass: + Out << "GlobalValue::DefaultStorageClass"; + break; + case GlobalValue::DLLImportStorageClass: + Out << "GlobalValue::DLLImportStorageClass"; + break; + case GlobalValue::DLLExportStorageClass: + Out << "GlobalValue::DLLExportStorageClass"; + break; + } +} + void CppWriter::printThreadLocalMode(GlobalVariable::ThreadLocalMode TLM) { switch (TLM) { case GlobalVariable::NotThreadLocal: @@ -1028,6 +1040,13 @@ void CppWriter::printVariableHead(const GlobalVariable *GV) { Out << ");"; nl(Out); } + if (GV->getDLLStorageClass() != GlobalValue::DefaultStorageClass) { + printCppName(GV); + Out << "->setDLLStorageClass("; + printDLLStorageClassType(GV->getDLLStorageClass()); + Out << ");"; + nl(Out); + } if (GV->isThreadLocal()) { printCppName(GV); Out << "->setThreadLocalMode("; @@ -1746,6 +1765,13 @@ void CppWriter::printFunctionHead(const Function* F) { Out << ");"; nl(Out); } + if (F->getDLLStorageClass() != GlobalValue::DefaultStorageClass) { + printCppName(F); + Out << "->setDLLStorageClass("; + printDLLStorageClassType(F->getDLLStorageClass()); + Out << ");"; + nl(Out); + } if (F->hasGC()) { printCppName(F); Out << "->setGC(\"" << F->getGC() << "\");"; diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index a2c3f770d31..ad7d3e0fdca 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -649,20 +649,20 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { // Necessary for dllexport support std::vector DLLExportedFns, DLLExportedGlobals; - const TargetLoweringObjectFileCOFF &TLOFCOFF = - static_cast(getObjFileLowering()); - for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) - if (I->hasDLLExportLinkage()) + if (I->hasDLLExportStorageClass()) DLLExportedFns.push_back(getSymbol(I)); for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - if (I->hasDLLExportLinkage()) + if (I->hasDLLExportStorageClass()) DLLExportedGlobals.push_back(getSymbol(I)); // Output linker support code for dllexported globals on windows. if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) { + const TargetLoweringObjectFileCOFF &TLOFCOFF = + static_cast(getObjFileLowering()); + OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection()); SmallString<128> name; for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) { diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index fd10a4a09ea..7b2d1d7776f 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -697,7 +697,7 @@ bool X86FastISel::X86SelectCallAddress(const Value *V, X86AddressMode &AM) { return false; // Can't handle DLLImport. - if (GV->hasDLLImportLinkage()) + if (GV->hasDLLImportStorageClass()) return false; // Can't handle TLS. diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 9fa7f7461fc..677cdbdee8f 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2796,7 +2796,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // We should use extra load for direct calls to dllimported functions in // non-JIT mode. const GlobalValue *GV = G->getGlobal(); - if (!GV->hasDLLImportLinkage()) { + if (!GV->hasDLLImportStorageClass()) { unsigned char OpFlags = 0; bool ExtraLoad = false; unsigned WrapperKind = ISD::DELETED_NODE; diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index b183ed0314f..6f724b42d97 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -55,7 +55,7 @@ unsigned char X86Subtarget:: ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // DLLImport only exists on windows, it is implemented as a load from a // DLLIMPORT stub. - if (GV->hasDLLImportLinkage()) + if (GV->hasDLLImportStorageClass()) return X86II::MO_DLLIMPORT; // Determine whether this is a reference to a definition or a declaration. diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp index ee84aa4a882..778bf9ca39d 100644 --- a/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -135,10 +135,6 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { case GlobalValue::InternalLinkage: case GlobalValue::PrivateLinkage: break; - case GlobalValue::DLLImportLinkage: - llvm_unreachable("DLLImport linkage is not supported by this target!"); - case GlobalValue::DLLExportLinkage: - llvm_unreachable("DLLExport linkage is not supported by this target!"); default: llvm_unreachable("Unknown linkage type!"); } diff --git a/lib/Transforms/IPO/Internalize.cpp b/lib/Transforms/IPO/Internalize.cpp index dae69ce0915..03077141776 100644 --- a/lib/Transforms/IPO/Internalize.cpp +++ b/lib/Transforms/IPO/Internalize.cpp @@ -116,7 +116,7 @@ static bool shouldInternalize(const GlobalValue &GV, return false; // Assume that dllexported symbols are referenced elsewhere - if (GV.hasDLLExportLinkage()) + if (GV.hasDLLExportStorageClass()) return false; // Already has internal linkage diff --git a/test/Bitcode/linkage-types-3.2.ll b/test/Bitcode/linkage-types-3.2.ll index 65c31dd1287..8bacb124eef 100644 --- a/test/Bitcode/linkage-types-3.2.ll +++ b/test/Bitcode/linkage-types-3.2.ll @@ -50,7 +50,7 @@ ; CHECK: @dllexport.var = dllexport global i32 0 @dllimport.var = dllimport global i32 -; CHECK: @dllimport.var = dllimport global i32 +; CHECK: @dllimport.var = external dllimport global i32 define private void @private() ; CHECK: define private void @private diff --git a/test/CodeGen/X86/dll-linkage.ll b/test/CodeGen/X86/dll-linkage.ll deleted file mode 100644 index a0c2a54a99a..00000000000 --- a/test/CodeGen/X86/dll-linkage.ll +++ /dev/null @@ -1,14 +0,0 @@ -; RUN: llc < %s -mtriple=i386-pc-mingw32 | FileCheck %s - -; RUN: llc < %s -mtriple=i386-pc-mingw32 -O0 | FileCheck %s -check-prefix=FAST -; PR6275 - -declare dllimport void @foo() - -define void @bar() nounwind { -; CHECK: calll *__imp__foo -; FAST: movl __imp__foo, [[R:%[a-z]{3}]] -; FAST: calll *[[R]] - call void @foo() - ret void -} diff --git a/test/CodeGen/X86/dllexport-x86_64.ll b/test/CodeGen/X86/dllexport-x86_64.ll new file mode 100644 index 00000000000..6bf73aa5366 --- /dev/null +++ b/test/CodeGen/X86/dllexport-x86_64.ll @@ -0,0 +1,79 @@ +; RUN: llc -mtriple x86_64-pc-win32 < %s | FileCheck -check-prefix=CHECK -check-prefix=WIN32 %s +; RUN: llc -mtriple x86_64-pc-mingw32 < %s | FileCheck -check-prefix=CHECK -check-prefix=MINGW %s + +; CHECK: .text + +define void @notExported() { + ret void +} + +; CHECK: .globl f1 +define dllexport void @f1() { + ret void +} + +; CHECK: .globl f2 +define dllexport void @f2() unnamed_addr { + ret void +} + +; CHECK: .section .text,"xr",discard,lnk1 +; CHECK: .globl lnk1 +define linkonce_odr dllexport void @lnk1() { + ret void +} + +; CHECK: .section .text,"xr",discard,lnk2 +; CHECK: .globl lnk2 +define linkonce_odr dllexport void @lnk2() alwaysinline { + ret void +} + +; CHECK: .section .text,"xr",discard,weak1 +; CHECK: .globl weak1 +define weak_odr dllexport void @weak1() { + ret void +} + + +; CHECK: .data +; CHECK: .globl Var1 +@Var1 = dllexport global i32 1, align 4 + +; CHECK: .rdata,"r" +; CHECK: .globl Var2 +@Var2 = dllexport unnamed_addr constant i32 1 + +; CHECK: .comm Var3 +@Var3 = common dllexport global i32 0, align 4 + +; CHECK: .section .data,"w",discard,WeakVar1 +; CHECK: .globl WeakVar1 +@WeakVar1 = weak_odr dllexport global i32 1, align 4 + +; CHECK: .section .rdata,"r",discard,WeakVar2 +; CHECK: .globl WeakVar2 +@WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1 + + +; CHECK: .section .drectve +; WIN32: /EXPORT:Var1,DATA +; WIN32: /EXPORT:Var2,DATA +; WIN32: /EXPORT:Var3,DATA +; WIN32: /EXPORT:WeakVar1,DATA +; WIN32: /EXPORT:WeakVar2,DATA +; WIN32: /EXPORT:f1 +; WIN32: /EXPORT:f2 +; WIN32: /EXPORT:lnk1 +; WIN32: /EXPORT:lnk2 +; WIN32: /EXPORT:weak1 +; MINGW: -export:Var1,data +; MINGW: -export:Var2,data +; MINGW: -export:Var3,data +; MINGW: -export:WeakVar1,data +; MINGW: -export:WeakVar2,data +; MINGW: -export:f1 +; MINGW: -export:f2 +; MINGW: -export:lnk1 +; MINGW: -export:lnk2 +; MINGW: -export:weak1 diff --git a/test/CodeGen/X86/dllexport.ll b/test/CodeGen/X86/dllexport.ll index bf57e78f35d..1d992125976 100644 --- a/test/CodeGen/X86/dllexport.ll +++ b/test/CodeGen/X86/dllexport.ll @@ -1,12 +1,100 @@ -; RUN: llc < %s | FileCheck %s -; PR2936 +; RUN: llc -mtriple i386-pc-win32 < %s | FileCheck -check-prefix=CHECK -check-prefix=WIN32 %s +; RUN: llc -mtriple i386-pc-mingw32 < %s | FileCheck -check-prefix=CHECK -check-prefix=MINGW %s -target triple = "i386-pc-mingw32" +; CHECK: .text -define dllexport x86_fastcallcc i32 @foo() nounwind { -entry: +define void @notExported() { + ret void +} + +; CHECK: .globl _f1 +define dllexport void @f1() { + ret void +} + +; CHECK: .globl _f2 +define dllexport void @f2() unnamed_addr { + ret void +} + +; CHECK: .globl _stdfun@0 +define dllexport x86_stdcallcc void @stdfun() nounwind { + ret void +} + +; CHECK: .globl @fastfun@0 +define dllexport x86_fastcallcc i32 @fastfun() nounwind { ret i32 0 } +; CHECK: .globl _thisfun +define dllexport x86_thiscallcc void @thisfun() nounwind { + ret void +} + +; CHECK: .section .text,"xr",discard,_lnk1 +; CHECK: .globl _lnk1 +define linkonce_odr dllexport void @lnk1() { + ret void +} + +; CHECK: .section .text,"xr",discard,_lnk2 +; CHECK: .globl _lnk2 +define linkonce_odr dllexport void @lnk2() alwaysinline { + ret void +} + +; CHECK: .section .text,"xr",discard,_weak1 +; CHECK: .globl _weak1 +define weak_odr dllexport void @weak1() { + ret void +} + + +; CHECK: .data +; CHECK: .globl _Var1 +@Var1 = dllexport global i32 1, align 4 + +; CHECK: .rdata,"r" +; CHECK: .globl _Var2 +@Var2 = dllexport unnamed_addr constant i32 1 + +; CHECK: .comm _Var3 +@Var3 = common dllexport global i32 0, align 4 + +; CHECK: .section .data,"w",discard,_WeakVar1 +; CHECK: .globl _WeakVar1 +@WeakVar1 = weak_odr dllexport global i32 1, align 4 + +; CHECK: .section .rdata,"r",discard,_WeakVar2 +; CHECK: .globl _WeakVar2 +@WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1 + + ; CHECK: .section .drectve -; CHECK: -export:@foo@0 +; WIN32: /EXPORT:_Var1,DATA +; WIN32: /EXPORT:_Var2,DATA +; WIN32: /EXPORT:_Var3,DATA +; WIN32: /EXPORT:_WeakVar1,DATA +; WIN32: /EXPORT:_WeakVar2,DATA +; WIN32: /EXPORT:_f1 +; WIN32: /EXPORT:_f2 +; WIN32: /EXPORT:_stdfun@0 +; WIN32: /EXPORT:@fastfun@0 +; WIN32: /EXPORT:_thisfun +; WIN32: /EXPORT:_lnk1 +; WIN32: /EXPORT:_lnk2 +; WIN32: /EXPORT:_weak1 +; MINGW: -export:_Var1,data +; MINGW: -export:_Var2,data +; MINGW: -export:_Var3,data +; MINGW: -export:_WeakVar1,data +; MINGW: -export:_WeakVar2,data +; MINGW: -export:_f1 +; MINGW: -export:_f2 +; MINGW: -export:_stdfun@0 +; MINGW: -export:@fastfun@0 +; MINGW: -export:_thisfun +; MINGW: -export:_lnk1 +; MINGW: -export:_lnk2 +; MINGW: -export:_weak1 diff --git a/test/CodeGen/X86/dllimport-x86_64.ll b/test/CodeGen/X86/dllimport-x86_64.ll new file mode 100644 index 00000000000..666409fd4c0 --- /dev/null +++ b/test/CodeGen/X86/dllimport-x86_64.ll @@ -0,0 +1,48 @@ +; RUN: llc -mtriple x86_64-pc-win32 < %s | FileCheck %s +; RUN: llc -mtriple x86_64-pc-mingw32 < %s | FileCheck %s +; +; RUN: llc -mtriple x86_64-pc-mingw32 -O0 < %s | FileCheck %s -check-prefix=FAST +; PR6275 +; +; RUN: opt -mtriple x86_64-pc-win32 -std-compile-opts -S < %s | FileCheck %s -check-prefix=OPT + +@Var1 = external dllimport global i32 +@Var2 = available_externally dllimport unnamed_addr constant i32 1 + +declare dllimport void @fun() + +define available_externally dllimport void @inline1() { + ret void +} + +define available_externally dllimport void @inline2() { + ret void +} + +declare void @dummy(...) + +define void @use() nounwind { +; CHECK: callq *__imp_fun(%rip) +; FAST: movq __imp_fun(%rip), [[R:%[a-z]{3}]] +; FAST-NEXT: callq *[[R]] + call void @fun() + +; CHECK: callq *__imp_inline1(%rip) +; CHECK: callq *__imp_inline2(%rip) + call void @inline1() + call void @inline2() + +; available_externally uses go away +; OPT-NOT: call void @inline1() +; OPT-NOT: call void @inline2() +; OPT-NOT: load i32* @Var2 +; OPT: call void (...)* @dummy(i32 %1, i32 1) + +; CHECK-DAG: movq __imp_Var1(%rip), [[R1:%[a-z]{3}]] +; CHECK-DAG: movq __imp_Var2(%rip), [[R2:%[a-z]{3}]] + %1 = load i32* @Var1 + %2 = load i32* @Var2 + call void(...)* @dummy(i32 %1, i32 %2) + + ret void +} diff --git a/test/CodeGen/X86/dllimport.ll b/test/CodeGen/X86/dllimport.ll new file mode 100644 index 00000000000..695bfce821b --- /dev/null +++ b/test/CodeGen/X86/dllimport.ll @@ -0,0 +1,59 @@ +; RUN: llc -mtriple i386-pc-win32 < %s | FileCheck %s +; RUN: llc -mtriple i386-pc-mingw32 < %s | FileCheck %s +; +; RUN: llc -mtriple i386-pc-mingw32 -O0 < %s | FileCheck %s -check-prefix=FAST +; PR6275 +; +; RUN: opt -mtriple i386-pc-win32 -std-compile-opts -S < %s | FileCheck %s -check-prefix=OPT + +@Var1 = external dllimport global i32 +@Var2 = available_externally dllimport unnamed_addr constant i32 1 + +declare dllimport void @fun() + +define available_externally dllimport void @inline1() { + ret void +} + +define available_externally dllimport void @inline2() alwaysinline { + ret void +} + +declare dllimport x86_stdcallcc void @stdfun() nounwind +declare dllimport x86_fastcallcc void @fastfun() nounwind +declare dllimport x86_thiscallcc void @thisfun() nounwind + +declare void @dummy(...) + +define void @use() nounwind { +; CHECK: calll *__imp__fun +; FAST: movl __imp__fun, [[R:%[a-z]{3}]] +; FAST-NEXT: calll *[[R]] + call void @fun() + +; CHECK: calll *__imp__inline1 +; CHECK: calll *__imp__inline2 + call void @inline1() + call void @inline2() + +; CHECK: calll *__imp__stdfun@0 +; CHECK: calll *__imp_@fastfun@0 +; CHECK: calll *__imp__thisfun + call void @stdfun() + call void @fastfun() + call void @thisfun() + +; available_externally uses go away +; OPT-NOT: call void @inline1() +; OPT-NOT: call void @inline2() +; OPT-NOT: load i32* @Var2 +; OPT: call void (...)* @dummy(i32 %1, i32 1) + +; CHECK-DAG: movl __imp__Var1, [[R1:%[a-z]{3}]] +; CHECK-DAG: movl __imp__Var2, [[R2:%[a-z]{3}]] + %1 = load i32* @Var1 + %2 = load i32* @Var2 + call void(...)* @dummy(i32 %1, i32 %2) + + ret void +}