Decouple dllexport/dllimport from linkage
authorNico Rieck <nico.rieck@gmail.com>
Tue, 14 Jan 2014 15:22:47 +0000 (15:22 +0000)
committerNico Rieck <nico.rieck@gmail.com>
Tue, 14 Jan 2014 15:22:47 +0000 (15:22 +0000)
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

27 files changed:
docs/BitCodeFormat.rst
docs/LangRef.rst
include/llvm-c/Core.h
include/llvm/IR/GlobalValue.h
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/ExecutionEngine/ExecutionEngine.cpp
lib/IR/AsmWriter.cpp
lib/IR/Core.cpp
lib/IR/Verifier.cpp
lib/Linker/LinkModules.cpp
lib/Target/CppBackend/CPPBackend.cpp
lib/Target/X86/X86AsmPrinter.cpp
lib/Target/X86/X86FastISel.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86Subtarget.cpp
lib/Target/XCore/XCoreAsmPrinter.cpp
lib/Transforms/IPO/Internalize.cpp
test/Bitcode/linkage-types-3.2.ll
test/CodeGen/X86/dll-linkage.ll [deleted file]
test/CodeGen/X86/dllexport-x86_64.ll [new file with mode: 0644]
test/CodeGen/X86/dllexport.ll
test/CodeGen/X86/dllimport-x86_64.ll [new file with mode: 0644]
test/CodeGen/X86/dllimport.ll [new file with mode: 0644]

index 89531dcfea69a39ff1315c6e3003cae501d71439..9363a62d0806b2730395bdf3e2f5bf73031c97ca 100644 (file)
@@ -658,7 +658,7 @@ for each library name referenced.
 MODULE_CODE_GLOBALVAR Record
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 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:
 
 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``
 
 * *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:
 
 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:
 
 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.
 
 * *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
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 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
 
 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
 
 
 * *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
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 MODULE_CODE_PURGEVALS Record
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
index ffe3f09d83b46fa494da69726b90eb19cdc4c390..3540bdec8acef3b54790081a1113fb588d8b6213 100644 (file)
@@ -274,27 +274,8 @@ linkage:
     visible, meaning that it participates in linkage and can be used to
     resolve external symbol references.
 
     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
 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:
 
 
 .. _callingconv:
 
@@ -416,6 +397,25 @@ styles:
 
 .. _namedtypes:
 
 
 .. _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
 -----------
 
 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.
 
 iterate over them as an array, alignment padding would break this
 iteration.
 
+Globals can also have a :ref:`DLL storage class <dllstorageclass>`.
+
+Syntax::
+
+    [@<GlobalVarName> =] [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal]
+                         [AddrSpace] [unnamed_addr] [ExternallyInitialized]
+                         <global | constant> <Type>
+                         [, section "name"] [, align <Alignment>]
+
 For example, the following defines a global in a numbered address space
 with an initializer, section, and alignment:
 
 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 <linkage>`, an optional :ref:`visibility
 
 LLVM function definitions consist of the "``define``" keyword, an
 optional :ref:`linkage type <linkage>`, an optional :ref:`visibility
-style <visibility>`, an optional :ref:`calling convention <callingconv>`,
+style <visibility>`, an optional :ref:`DLL storage class <dllstorageclass>`,
+an optional :ref:`calling convention <callingconv>`,
 an optional ``unnamed_addr`` attribute, a return type, an optional
 :ref:`parameter attribute <paramattrs>` for the return type, a function
 name, a (possibly empty) argument list (each with optional :ref:`parameter
 an optional ``unnamed_addr`` attribute, a return type, an optional
 :ref:`parameter attribute <paramattrs>` 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 <linkage>`, an optional :ref:`visibility
 
 LLVM function declarations consist of the "``declare``" keyword, an
 optional :ref:`linkage type <linkage>`, an optional :ref:`visibility
-style <visibility>`, an optional :ref:`calling convention <callingconv>`,
+style <visibility>`, an optional :ref:`DLL storage class <dllstorageclass>`,
+an optional :ref:`calling convention <callingconv>`,
 an optional ``unnamed_addr`` attribute, a return type, an optional
 :ref:`parameter attribute <paramattrs>` for the return type, a function
 name, a possibly empty list of arguments, an optional alignment, an optional
 an optional ``unnamed_addr`` attribute, a return type, an optional
 :ref:`parameter attribute <paramattrs>` 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::
 
 
 Syntax::
 
-    define [linkage] [visibility]
+    define [linkage] [visibility] [DLLStorageClass]
            [cconv] [ret attrs]
            <ResultType> @<FunctionName> ([argument list])
            [fn Attrs] [section "name"] [align N]
            [cconv] [ret attrs]
            <ResultType> @<FunctionName> ([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 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 <linkage>`, and an optional
-:ref:`visibility style <visibility>`.
+Aliases may have an optional :ref:`linkage type <linkage>`, an optional
+:ref:`visibility style <visibility>`, and an optional :ref:`DLL storage class
+<dllstorageclass>`.
 
 Syntax::
 
 
 Syntax::
 
-    @<Name> = alias [Linkage] [Visibility] <AliaseeTy> @<Aliasee>
+    @<Name> = [Visibility] [DLLStorageClass] alias [Linkage] <AliaseeTy> @<Aliasee>
 
 The linkage must be one of ``private``, ``linker_private``,
 ``linker_private_weak``, ``internal``, ``linkonce``, ``weak``,
 
 The linkage must be one of ``private``, ``linker_private``,
 ``linker_private_weak``, ``internal``, ``linkonce``, ``weak``,
index 269869ef0da755fd7c311707ca28cca8feeab44e..a84a0313211315d094a9d0a81836b65a353d74fc 100644 (file)
@@ -284,8 +284,8 @@ typedef enum {
   LLVMInternalLinkage,    /**< Rename collisions when linking (static
                                functions) */
   LLVMPrivateLinkage,     /**< Like Internal, but omit from symbol table */
   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 */
   LLVMExternalWeakLinkage,/**< ExternalWeak linkage description */
   LLVMGhostLinkage,       /**< Obsolete */
   LLVMCommonLinkage,      /**< Tentative definitions */
index 4f20a31a294b577da063e78f7e0745d12424016f..5fdf6611e9a23601ef7a0b13e14f6a6480040aa7 100644 (file)
@@ -42,8 +42,6 @@ public:
     PrivateLinkage,     ///< Like Internal, but omit from symbol table.
     LinkerPrivateLinkage, ///< Like Private, but linker removes.
     LinkerPrivateWeakLinkage, ///< Like LinkerPrivate, but weak.
     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.
   };
     ExternalWeakLinkage,///< ExternalWeak linkage description.
     CommonLinkage       ///< Tentative definitions.
   };
@@ -55,11 +53,19 @@ public:
     ProtectedVisibility     ///< The GV is protected
   };
 
     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),
 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);
   }
 
     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 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:
   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; }
     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; }
   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);
   }
     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;
   }
   static bool isExternalWeakLinkage(LinkageTypes Linkage) {
     return Linkage == ExternalWeakLinkage;
   }
@@ -209,8 +221,6 @@ public:
     return isLinkerPrivateWeakLinkage(Linkage);
   }
   bool hasLocalLinkage() const { return isLocalLinkage(Linkage); }
     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); }
 
   bool hasExternalWeakLinkage() const { return isExternalWeakLinkage(Linkage); }
   bool hasCommonLinkage() const { return isCommonLinkage(Linkage); }
 
index a5b2aa586e46ce08e839d5b402dda40982182e29..d4d6f7cee14ec0498df47104d13abec461ba60ca 100644 (file)
@@ -242,8 +242,8 @@ bool LLParser::ParseTopLevelEntities() {
 
     // The Global variable production with no name can have many different
     // optional leading prefixes, the production is:
 
     // 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
     //               ('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_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_common:              // OptionalLinkage
-    case lltok::kw_dllimport:           // OptionalLinkage
     case lltok::kw_extern_weak:         // OptionalLinkage
     case lltok::kw_external: {          // OptionalLinkage
     case lltok::kw_extern_weak:         // OptionalLinkage
     case lltok::kw_external: {          // OptionalLinkage
-      unsigned Linkage, Visibility;
+      unsigned Linkage, Visibility, DLLStorageClass;
       if (ParseOptionalLinkage(Linkage) ||
           ParseOptionalVisibility(Visibility) ||
       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
         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) ||
       if (ParseOptionalVisibility(Visibility) ||
-          ParseGlobal("", SMLoc(), 0, false, Visibility))
+          ParseOptionalDLLStorageClass(DLLStorageClass) ||
+          ParseGlobal("", SMLoc(), 0, false, Visibility, DLLStorageClass))
         return true;
       break;
     }
         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
     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;
       break;
 
     case lltok::kw_attributes: if (ParseUnnamedAttrGrp()) return true; break;
@@ -446,9 +446,11 @@ bool LLParser::ParseGlobalType(bool &IsConstant) {
 
 /// ParseUnnamedGlobal:
 ///   OptionalVisibility ALIAS ...
 
 /// ParseUnnamedGlobal:
 ///   OptionalVisibility ALIAS ...
-///   OptionalLinkage OptionalVisibility ...   -> global variable
+///   OptionalLinkage OptionalVisibility OptionalDLLStorageClass
+///                                                     ...   -> global variable
 ///   GlobalID '=' OptionalVisibility ALIAS ...
 ///   GlobalID '=' OptionalVisibility ALIAS ...
-///   GlobalID '=' OptionalLinkage OptionalVisibility ...   -> global variable
+///   GlobalID '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass
+///                                                     ...   -> global variable
 bool LLParser::ParseUnnamedGlobal() {
   unsigned VarID = NumberedVals.size();
   std::string Name;
 bool LLParser::ParseUnnamedGlobal() {
   unsigned VarID = NumberedVals.size();
   std::string Name;
@@ -466,19 +468,22 @@ bool LLParser::ParseUnnamedGlobal() {
   }
 
   bool HasLinkage;
   }
 
   bool HasLinkage;
-  unsigned Linkage, Visibility;
+  unsigned Linkage, Visibility, DLLStorageClass;
   if (ParseOptionalLinkage(Linkage, HasLinkage) ||
   if (ParseOptionalLinkage(Linkage, HasLinkage) ||
-      ParseOptionalVisibility(Visibility))
+      ParseOptionalVisibility(Visibility) ||
+      ParseOptionalDLLStorageClass(DLLStorageClass))
     return true;
 
   if (HasLinkage || Lex.getKind() != lltok::kw_alias)
     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 ...
 }
 
 /// 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();
 bool LLParser::ParseNamedGlobal() {
   assert(Lex.getKind() == lltok::GlobalVar);
   LocTy NameLoc = Lex.getLoc();
@@ -486,15 +491,17 @@ bool LLParser::ParseNamedGlobal() {
   Lex.Lex();
 
   bool HasLinkage;
   Lex.Lex();
 
   bool HasLinkage;
-  unsigned Linkage, Visibility;
+  unsigned Linkage, Visibility, DLLStorageClass;
   if (ParseToken(lltok::equal, "expected '=' in global variable") ||
       ParseOptionalLinkage(Linkage, HasLinkage) ||
   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 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:
 }
 
 // MDString:
@@ -615,16 +622,17 @@ bool LLParser::ParseStandaloneMetadata() {
 }
 
 /// ParseAlias:
 }
 
 /// ParseAlias:
-///   ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee
+///   ::= GlobalVar '=' OptionalVisibility OptionalDLLStorageClass 'alias'
+///                     OptionalLinkage Aliasee
 /// Aliasee
 ///   ::= TypeAndValue
 ///   ::= 'bitcast' '(' TypeAndValue 'to' Type ')'
 ///   ::= 'getelementptr' 'inbounds'? '(' ... ')'
 ///
 /// 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,
 ///
 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();
   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);
                                     (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.
 
   // 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
 }
 
 /// ParseGlobal
-///   ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalThreadLocal
-///       OptionalAddrSpace OptionalUnNammedAddr
+///   ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass
+///       OptionalThreadLocal OptionalAddrSpace OptionalUnNammedAddr
 ///       OptionalExternallyInitialized GlobalType Type Const
 ///       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,
 ///       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;
   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 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;
                       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->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);
   GV->setExternallyInitialized(IsExternallyInitialized);
   GV->setThreadLocalMode(TLM);
   GV->setUnnamedAddr(UnnamedAddr);
@@ -1277,9 +1286,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) {
 ///   ::= 'linkonce_odr'
 ///   ::= 'available_externally'
 ///   ::= 'appending'
 ///   ::= 'linkonce_odr'
 ///   ::= 'available_externally'
 ///   ::= 'appending'
-///   ::= 'dllexport'
 ///   ::= 'common'
 ///   ::= 'common'
-///   ::= 'dllimport'
 ///   ::= 'extern_weak'
 ///   ::= 'external'
 bool LLParser::ParseOptionalLinkage(unsigned &Res, bool &HasLinkage) {
 ///   ::= '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;
     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_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;
   }
   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;
 }
 
   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'
 /// ParseOptionalCallingConv
 ///   ::= /*empty*/
 ///   ::= 'ccc'
@@ -2934,12 +2954,14 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
   unsigned Linkage;
 
   unsigned Visibility;
   unsigned Linkage;
 
   unsigned Visibility;
+  unsigned DLLStorageClass;
   AttrBuilder RetAttrs;
   CallingConv::ID CC;
   Type *RetType = 0;
   LocTy RetTypeLoc = Lex.getLoc();
   if (ParseOptionalLinkage(Linkage) ||
       ParseOptionalVisibility(Visibility) ||
   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*/))
       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.
   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");
   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::LinkOnceODRLinkage:
   case GlobalValue::WeakAnyLinkage:
   case GlobalValue::WeakODRLinkage:
-  case GlobalValue::DLLExportLinkage:
     if (!isDefine)
       return Error(LinkageLoc, "invalid linkage for function declaration");
     break;
     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->setLinkage((GlobalValue::LinkageTypes)Linkage);
   Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility);
+  Fn->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass);
   Fn->setCallingConv(CC);
   Fn->setAttributes(PAL);
   Fn->setUnnamedAddr(UnnamedAddr);
   Fn->setCallingConv(CC);
   Fn->setAttributes(PAL);
   Fn->setUnnamedAddr(UnnamedAddr);
index ded776c3989c7ee852eb4a5ce9dc5889661c72fa..c62979e6f29e22c5a8ab74b517918861601b0458 100644 (file)
@@ -204,6 +204,7 @@ namespace llvm {
       bool HasLinkage; return ParseOptionalLinkage(Linkage, HasLinkage);
     }
     bool ParseOptionalVisibility(unsigned &Visibility);
       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,
     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 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);
     bool ParseStandaloneMetadata();
     bool ParseNamedMetadata();
     bool ParseMDString(MDString *&Result);
index 39a0dfa50063b7c2b6830aa5492bfbeffb5dcaa9..81ed803ba04985ad32dc65547438d120fe8e8a62 100644 (file)
@@ -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 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;
   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;
 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
 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,
     }
     // 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);
     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);
 
       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.
       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,
       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);
     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));
       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
       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]
       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);
     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]));
       // 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;
       ValueList.push_back(NewGA);
       AliasInits.push_back(std::make_pair(NewGA, Record[1]));
       break;
index be19b781d4aacb8a989fb319df95e878484839d8..1d763d66ddc474f88f2b7c7d187d412bb3c97c0c 100644 (file)
@@ -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::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;
   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");
 }
 
   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;
 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,
 
     // 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 :
     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 ||
     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(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;
     }
     } 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(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);
 
     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(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();
     unsigned AbbrevToUse = 0;
     Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);
     Vals.clear();
index 5a8e8cc2f02ff4fb8e3297b5aded4379958d873c..cf950f8cc75efc6f0b5c259d5288eae34f24a2dc 100644 (file)
@@ -257,7 +257,6 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
       OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
     }
     return;
       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.
   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");
     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");
   }
   case GlobalValue::ExternalWeakLinkage:
     llvm_unreachable("Don't know how to emit these");
   }
index abc8877ec590f64faace0674f3e906aa52451e54..88ec5b3e6a999079ffc5314e632d200bf72670c0 100644 (file)
@@ -1211,9 +1211,7 @@ void ExecutionEngine::emitGlobals() {
         }
 
         // If the existing global is strong, never replace it.
         }
 
         // 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
           continue;
 
         // Otherwise, we know it's linkonce/weak, replace it if this is a strong
index 91684c9c70ef34409587bd6a7ef77d178f71bafd..eba05c5f28e1f1d5bd207b54c831e48e3b4f3dfd 100644 (file)
@@ -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::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 ";
   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) {
 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);
 
   PrintLinkage(GV->getLinkage(), Out);
   PrintVisibility(GV->getVisibility(), Out);
+  PrintDLLStorageClass(GV->getDLLStorageClass(), Out);
   PrintThreadLocalModel(GV->getThreadLocalMode(), Out);
 
   if (unsigned AddressSpace = GV->getType()->getAddressSpace())
   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);
     Out << " = ";
   }
   PrintVisibility(GA->getVisibility(), Out);
+  PrintDLLStorageClass(GA->getDLLStorageClass(), Out);
 
   Out << "alias ";
 
 
   Out << "alias ";
 
@@ -1552,6 +1561,7 @@ void AssemblyWriter::printFunction(const Function *F) {
 
   PrintLinkage(F->getLinkage(), Out);
   PrintVisibility(F->getVisibility(), Out);
 
   PrintLinkage(F->getLinkage(), Out);
   PrintVisibility(F->getVisibility(), Out);
+  PrintDLLStorageClass(F->getDLLStorageClass(), Out);
 
   // Print the calling convention.
   if (F->getCallingConv() != CallingConv::C) {
 
   // Print the calling convention.
   if (F->getCallingConv() != CallingConv::C) {
index ff4976bcbf9815a4e23667cbbd781e19716d858e..6e920a2daa4b8a93ace7306c1706e43d837c8ab5 100644 (file)
@@ -1164,10 +1164,6 @@ LLVMLinkage LLVMGetLinkage(LLVMValueRef Global) {
     return LLVMLinkerPrivateLinkage;
   case GlobalValue::LinkerPrivateWeakLinkage:
     return LLVMLinkerPrivateWeakLinkage;
     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:
   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::LinkerPrivateWeakLinkage);
     break;
   case LLVMDLLImportLinkage:
-    GV->setLinkage(GlobalValue::DLLImportLinkage);
+    DEBUG(errs()
+          << "LLVMSetLinkage(): LLVMDLLImportLinkage is no longer supported.");
     break;
   case LLVMDLLExportLinkage:
     break;
   case LLVMDLLExportLinkage:
-    GV->setLinkage(GlobalValue::DLLExportLinkage);
+    DEBUG(errs()
+          << "LLVMSetLinkage(): LLVMDLLExportLinkage is no longer supported.");
     break;
   case LLVMExternalWeakLinkage:
     GV->setLinkage(GlobalValue::ExternalWeakLinkage);
     break;
   case LLVMExternalWeakLinkage:
     GV->setLinkage(GlobalValue::ExternalWeakLinkage);
index 9e150e857561d2d4c09069954e76e2846ea9d848..d8e5c89598e298e83c9f481e43527ae49bb69dfd 100644 (file)
@@ -421,16 +421,12 @@ void Verifier::visitGlobalValue(GlobalValue &GV) {
   Assert1(!GV.isDeclaration() ||
           GV.isMaterializable() ||
           GV.hasExternalLinkage() ||
   Assert1(!GV.isDeclaration() ||
           GV.isMaterializable() ||
           GV.hasExternalLinkage() ||
-          GV.hasDLLImportLinkage() ||
           GV.hasExternalWeakLinkage() ||
           (isa<GlobalAlias>(GV) &&
            (GV.hasLocalLinkage() || GV.hasWeakLinkage())),
           GV.hasExternalWeakLinkage() ||
           (isa<GlobalAlias>(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);
 
           &GV);
 
-  Assert1(!GV.hasDLLImportLinkage() || GV.isDeclaration(),
-          "Global is marked as dllimport, but not external", &GV);
-
   Assert1(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),
           "Only global variables can have appending linkage!", &GV);
 
   Assert1(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),
           "Only global variables can have appending linkage!", &GV);
 
@@ -456,8 +452,7 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
               &GV);
     }
   } else {
               &GV);
     }
   } else {
-    Assert1(GV.hasExternalLinkage() || GV.hasDLLImportLinkage() ||
-            GV.hasExternalWeakLinkage(),
+    Assert1(GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(),
             "invalid linkage type for global declaration", &GV);
   }
 
             "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;
   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()) {
   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
             "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);
   }
     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...
 }
 
 // verifyBasicBlock - Verify that a basic block is well formed...
index 8f2200e4ea2e88572de5d64bc96f883e0cb3eb71..4d039eb2c6dabc3b901e50be0e1dd0359e306bb8 100644 (file)
@@ -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 (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();
       if (DestIsDeclaration) {
         LinkFromSrc = true;
         LT = Src->getLinkage();
@@ -557,7 +557,7 @@ bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
       LinkFromSrc = false;
       LT = Dest->getLinkage();
     }
       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();
     // 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 {
       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!");
            "Unexpected linkage type!");
     return emitError("Linking globals named '" + Src->getName() +
                  "': symbol multiply defined!");
index 6e2dd0a8e7b2d33c4fa3baf29d60335f3b6a72eb..b13709914bf6f0e011421067536ddc8aa7840264 100644 (file)
@@ -131,6 +131,7 @@ namespace {
   private:
     void printLinkageType(GlobalValue::LinkageTypes LT);
     void printVisibilityType(GlobalValue::VisibilityTypes VisTypes);
   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);
     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;
     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:
   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:
 void CppWriter::printThreadLocalMode(GlobalVariable::ThreadLocalMode TLM) {
   switch (TLM) {
     case GlobalVariable::NotThreadLocal:
@@ -1028,6 +1040,13 @@ void CppWriter::printVariableHead(const GlobalVariable *GV) {
     Out << ");";
     nl(Out);
   }
     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(";
   if (GV->isThreadLocal()) {
     printCppName(GV);
     Out << "->setThreadLocalMode(";
@@ -1746,6 +1765,13 @@ void CppWriter::printFunctionHead(const Function* F) {
     Out << ");";
     nl(Out);
   }
     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() << "\");";
   if (F->hasGC()) {
     printCppName(F);
     Out << "->setGC(\"" << F->getGC() << "\");";
index a2c3f770d310dda179568c60c3ebe1d513841833..ad7d3e0fdcae0ad3914dbc2e4c7e7bbb00656312 100644 (file)
@@ -649,20 +649,20 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
     // Necessary for dllexport support
     std::vector<const MCSymbol*> DLLExportedFns, DLLExportedGlobals;
 
     // Necessary for dllexport support
     std::vector<const MCSymbol*> DLLExportedFns, DLLExportedGlobals;
 
-    const TargetLoweringObjectFileCOFF &TLOFCOFF =
-      static_cast<const TargetLoweringObjectFileCOFF&>(getObjFileLowering());
-
     for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
     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)
         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()) {
         DLLExportedGlobals.push_back(getSymbol(I));
 
     // Output linker support code for dllexported globals on windows.
     if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) {
+      const TargetLoweringObjectFileCOFF &TLOFCOFF =
+        static_cast<const TargetLoweringObjectFileCOFF&>(getObjFileLowering());
+
       OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection());
       SmallString<128> name;
       for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) {
       OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection());
       SmallString<128> name;
       for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) {
index fd10a4a09eab0a29d8bcbe69920877ada36aeb49..7b2d1d7776fbd5022d08d85763d0cc97033aac46 100644 (file)
@@ -697,7 +697,7 @@ bool X86FastISel::X86SelectCallAddress(const Value *V, X86AddressMode &AM) {
       return false;
 
     // Can't handle DLLImport.
       return false;
 
     // Can't handle DLLImport.
-    if (GV->hasDLLImportLinkage())
+    if (GV->hasDLLImportStorageClass())
       return false;
 
     // Can't handle TLS.
       return false;
 
     // Can't handle TLS.
index 9fa7f7461fc4f9882d595f813d0d0b9b98adbe6d..677cdbdee8f1164a1c690c3dc5198ad11bb0a628 100644 (file)
@@ -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();
     // 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;
       unsigned char OpFlags = 0;
       bool ExtraLoad = false;
       unsigned WrapperKind = ISD::DELETED_NODE;
index b183ed0314f28bb55c5cf8bc0e15c7efa0ffafab..6f724b42d977483c9ff2420dc4837c1a84adcd85 100644 (file)
@@ -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.
 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.
     return X86II::MO_DLLIMPORT;
 
   // Determine whether this is a reference to a definition or a declaration.
index ee84aa4a88292f8a79fe97e399e4676774c2afe4..778bf9ca39dc3225a57def38dd601b3f3dae21a3 100644 (file)
@@ -135,10 +135,6 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
   case GlobalValue::InternalLinkage:
   case GlobalValue::PrivateLinkage:
     break;
   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!");
   }
   default:
     llvm_unreachable("Unknown linkage type!");
   }
index dae69ce09156d101f27edec25dad50c6958e6f75..0307714177664a9dbc88f64ce8c651e675844b68 100644 (file)
@@ -116,7 +116,7 @@ static bool shouldInternalize(const GlobalValue &GV,
     return false;
 
   // Assume that dllexported symbols are referenced elsewhere
     return false;
 
   // Assume that dllexported symbols are referenced elsewhere
-  if (GV.hasDLLExportLinkage())
+  if (GV.hasDLLExportStorageClass())
     return false;
 
   // Already has internal linkage
     return false;
 
   // Already has internal linkage
index 65c31dd12877fce9e2c2328aabf0b330f729a39e..8bacb124eef4aba7646c4df261353d86627ec144 100644 (file)
@@ -50,7 +50,7 @@
 ; CHECK: @dllexport.var = dllexport global i32 0
 
 @dllimport.var = dllimport global i32
 ; 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
 
 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 (file)
index a0c2a54..0000000
+++ /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 (file)
index 0000000..6bf73aa
--- /dev/null
@@ -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
index bf57e78f35d4b493e6ad4263c80464e502c982ef..1d9921259767130a4cdf3ac854ae3316609fb104 100644 (file)
-; 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
 }
 
        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: .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 (file)
index 0000000..666409f
--- /dev/null
@@ -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 (file)
index 0000000..695bfce
--- /dev/null
@@ -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
+}