mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-25 14:32:53 +00:00
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:
parent
d05a6582da
commit
38f68c5a2e
@ -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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -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``,
|
||||
|
@ -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 */
|
||||
|
@ -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); }
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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...
|
||||
|
@ -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!");
|
||||
|
@ -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() << "\");";
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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!");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
79
test/CodeGen/X86/dllexport-x86_64.ll
Normal file
79
test/CodeGen/X86/dllexport-x86_64.ll
Normal 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
|
@ -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
|
||||
|
48
test/CodeGen/X86/dllimport-x86_64.ll
Normal file
48
test/CodeGen/X86/dllimport-x86_64.ll
Normal 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
|
||||
}
|
59
test/CodeGen/X86/dllimport.ll
Normal file
59
test/CodeGen/X86/dllimport.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user