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
This commit is contained in:
Nico Rieck 2014-01-14 15:22:47 +00:00
parent d05a6582da
commit 38f68c5a2e
27 changed files with 547 additions and 157 deletions

View File

@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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 <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:
@ -556,7 +565,8 @@ Functions
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
@ -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
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
@ -603,7 +614,7 @@ be significant and two identical functions can be merged.
Syntax::
define [linkage] [visibility]
define [linkage] [visibility] [DLLStorageClass]
[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 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::
@<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``,

View File

@ -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 */

View 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.
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); }

View 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:
// 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);

View File

@ -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);

View 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 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;

View 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::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();

View File

@ -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");
}

View File

@ -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

View 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::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) {

View File

@ -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);

View File

@ -421,16 +421,12 @@ void Verifier::visitGlobalValue(GlobalValue &GV) {
Assert1(!GV.isDeclaration() ||
GV.isMaterializable() ||
GV.hasExternalLinkage() ||
GV.hasDLLImportLinkage() ||
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);
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);
@ -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...

View 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 (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!");

View File

@ -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() << "\");";

View File

@ -649,20 +649,20 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
// 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)
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<const TargetLoweringObjectFileCOFF&>(getObjFileLowering());
OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection());
SmallString<128> name;
for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) {

View File

@ -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.

View 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();
if (!GV->hasDLLImportLinkage()) {
if (!GV->hasDLLImportStorageClass()) {
unsigned char OpFlags = 0;
bool ExtraLoad = false;
unsigned WrapperKind = ISD::DELETED_NODE;

View 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.
if (GV->hasDLLImportLinkage())
if (GV->hasDLLImportStorageClass())
return X86II::MO_DLLIMPORT;
// Determine whether this is a reference to a definition or a declaration.

View File

@ -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!");
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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
}