[llvm] r265667 - [GCC] Attribute ifunc support in llvm
Dmitry Polukhin via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 7 05:32:20 PDT 2016
Author: dpolukhin
Date: Thu Apr 7 07:32:19 2016
New Revision: 265667
URL: http://llvm.org/viewvc/llvm-project?rev=265667&view=rev
Log:
[GCC] Attribute ifunc support in llvm
This patch add support for GCC attribute((ifunc("resolver"))) for
targets that use ELF as object file format. In general ifunc is a
special kind of function alias with type @gnu_indirect_function. Patch
for Clang http://reviews.llvm.org/D15524
Differential Revision: http://reviews.llvm.org/D15525
Added:
llvm/trunk/include/llvm/IR/GlobalIFunc.h (with props)
llvm/trunk/test/Assembler/ifunc-asm.ll
llvm/trunk/test/Assembler/ifunc-use-list-order.ll
Modified:
llvm/trunk/docs/LangRef.rst
llvm/trunk/include/llvm-c/Core.h
llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h
llvm/trunk/include/llvm/IR/GlobalValue.h
llvm/trunk/include/llvm/IR/Module.h
llvm/trunk/include/llvm/IR/SymbolTableListTraits.h
llvm/trunk/include/llvm/IR/Value.def
llvm/trunk/include/llvm/IR/Value.h
llvm/trunk/include/llvm/IR/ValueSymbolTable.h
llvm/trunk/lib/AsmParser/LLLexer.cpp
llvm/trunk/lib/AsmParser/LLParser.cpp
llvm/trunk/lib/AsmParser/LLToken.h
llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/trunk/lib/IR/AsmWriter.cpp
llvm/trunk/lib/IR/Globals.cpp
llvm/trunk/lib/IR/Module.cpp
llvm/trunk/test/Bitcode/compatibility.ll
Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Thu Apr 7 07:32:19 2016
@@ -764,6 +764,25 @@ some can only be checked when producing
* No global value in the expression can be a declaration, since that
would require a relocation, which is not possible.
+.. _langref_ifunc:
+
+IFuncs
+-------
+
+IFuncs, like as aliases, don't create any new data or func. They are just a new
+symbol that dynamic linker resolves at runtime by calling a resolver function.
+
+IFuncs have a name and a resolver that is a function called by dynamic linker
+that returns address of another function associated with the name.
+
+IFunc may have an optional :ref:`linkage type <linkage>` and an optional
+:ref:`visibility style <visibility>`.
+
+Syntax::
+
+ @<Name> = [Linkage] [Visibility] ifunc <IFuncTy>, <ResolverTy>* @<Resolver>
+
+
.. _langref_comdats:
Comdats
Modified: llvm/trunk/include/llvm-c/Core.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Core.h?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/include/llvm-c/Core.h (original)
+++ llvm/trunk/include/llvm-c/Core.h Thu Apr 7 07:32:19 2016
@@ -256,6 +256,7 @@ typedef enum {
LLVMFunctionValueKind,
LLVMGlobalAliasValueKind,
+ LLVMGlobalIFuncValueKind,
LLVMGlobalVariableValueKind,
LLVMBlockAddressValueKind,
LLVMConstantExprValueKind,
Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Thu Apr 7 07:32:19 2016
@@ -110,6 +110,9 @@ enum ModuleCodes {
// HASH: [5*i32]
MODULE_CODE_HASH = 17,
+
+ // IFUNC: [ifunc value type, addrspace, resolver val#, linkage, visibility]
+ MODULE_CODE_IFUNC = 18,
};
/// PARAMATTR blocks have code for defining a parameter attribute set.
Added: llvm/trunk/include/llvm/IR/GlobalIFunc.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalIFunc.h?rev=265667&view=auto
==============================================================================
--- llvm/trunk/include/llvm/IR/GlobalIFunc.h (added)
+++ llvm/trunk/include/llvm/IR/GlobalIFunc.h Thu Apr 7 07:32:19 2016
@@ -0,0 +1,76 @@
+//===-------- llvm/GlobalIFunc.h - GlobalIFunc class ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \brief
+/// This file contains the declaration of the GlobalIFunc class, which
+/// represents a single indirect function in the IR. Indirect function uses
+/// ELF symbol type extension to mark that the address of a declaration should
+/// be resolved at runtime by calling a resolver function.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_GLOBALIFUNC_H
+#define LLVM_IR_GLOBALIFUNC_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/IR/GlobalIndirectSymbol.h"
+
+namespace llvm {
+
+class Module;
+
+// Traits class for using GlobalIFunc in symbol table in Module.
+template <typename ValueSubClass> class SymbolTableListTraits;
+
+class GlobalIFunc final : public GlobalIndirectSymbol,
+ public ilist_node<GlobalIFunc> {
+ friend class SymbolTableListTraits<GlobalIFunc>;
+ void operator=(const GlobalIFunc &) = delete;
+ GlobalIFunc(const GlobalIFunc &) = delete;
+
+ void setParent(Module *parent);
+
+ GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage,
+ const Twine &Name, Constant *Resolver, Module *Parent);
+
+public:
+ /// If a parent module is specified, the ifunc is automatically inserted into
+ /// the end of the specified module's ifunc list.
+ static GlobalIFunc *create(Type *Ty, unsigned AddressSpace,
+ LinkageTypes Linkage, const Twine &Name,
+ Constant *Resolver, Module *Parent);
+
+ /// This method unlinks 'this' from the containing module, but does not
+ /// delete it.
+ void removeFromParent() final;
+
+ /// This method unlinks 'this' from the containing module and deletes it.
+ void eraseFromParent() final;
+
+ /// These methods retrieve and set ifunc resolver function.
+ void setResolver(Constant *Resolver) {
+ setIndirectSymbol(Resolver);
+ }
+ const Constant *getResolver() const {
+ return getIndirectSymbol();
+ }
+ Constant *getResolver() {
+ return getIndirectSymbol();
+ }
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const Value *V) {
+ return V->getValueID() == Value::GlobalIFuncVal;
+ }
+};
+
+} // End llvm namespace
+
+#endif
Propchange: llvm/trunk/include/llvm/IR/GlobalIFunc.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: llvm/trunk/include/llvm/IR/GlobalIFunc.h
------------------------------------------------------------------------------
svn:keywords = "Author Date Id Rev URL"
Propchange: llvm/trunk/include/llvm/IR/GlobalIFunc.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h (original)
+++ llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h Thu Apr 7 07:32:19 2016
@@ -51,7 +51,8 @@ public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *V) {
- return V->getValueID() == Value::GlobalAliasVal;
+ return V->getValueID() == Value::GlobalAliasVal ||
+ V->getValueID() == Value::GlobalIFuncVal;
}
};
Modified: llvm/trunk/include/llvm/IR/GlobalValue.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalValue.h?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/GlobalValue.h (original)
+++ llvm/trunk/include/llvm/IR/GlobalValue.h Thu Apr 7 07:32:19 2016
@@ -388,7 +388,8 @@ public:
static bool classof(const Value *V) {
return V->getValueID() == Value::FunctionVal ||
V->getValueID() == Value::GlobalVariableVal ||
- V->getValueID() == Value::GlobalAliasVal;
+ V->getValueID() == Value::GlobalAliasVal ||
+ V->getValueID() == Value::GlobalIFuncVal;
}
};
Modified: llvm/trunk/include/llvm/IR/Module.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Module.h?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Module.h (original)
+++ llvm/trunk/include/llvm/IR/Module.h Thu Apr 7 07:32:19 2016
@@ -21,6 +21,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalIFunc.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/CBindingWrapping.h"
@@ -75,6 +76,8 @@ public:
typedef SymbolTableList<Function> FunctionListType;
/// The type for the list of aliases.
typedef SymbolTableList<GlobalAlias> AliasListType;
+ /// The type for the list of ifuncs.
+ typedef SymbolTableList<GlobalIFunc> IFuncListType;
/// The type for the list of named metadata.
typedef ilist<NamedMDNode> NamedMDListType;
/// The type of the comdat "symbol" table.
@@ -100,6 +103,11 @@ public:
/// The Global Alias constant iterator
typedef AliasListType::const_iterator const_alias_iterator;
+ /// The Global IFunc iterators.
+ typedef IFuncListType::iterator ifunc_iterator;
+ /// The Global IFunc constant iterator
+ typedef IFuncListType::const_iterator const_ifunc_iterator;
+
/// The named metadata iterators.
typedef NamedMDListType::iterator named_metadata_iterator;
/// The named metadata constant iterators.
@@ -163,6 +171,7 @@ private:
GlobalListType GlobalList; ///< The Global Variables in the module
FunctionListType FunctionList; ///< The Functions in the module
AliasListType AliasList; ///< The Aliases in the module
+ IFuncListType IFuncList; ///< The IFuncs in the module
NamedMDListType NamedMDList; ///< The named metadata in the module
std::string GlobalScopeAsm; ///< Inline Asm at global scope.
ValueSymbolTable *ValSymTab; ///< Symbol table for values
@@ -384,6 +393,15 @@ public:
GlobalAlias *getNamedAlias(StringRef Name) const;
/// @}
+/// @name Global IFunc Accessors
+/// @{
+
+ /// Return the global ifunc in the module with the specified name, of
+ /// arbitrary type. This method returns null if a global with the specified
+ /// name is not found.
+ GlobalIFunc *getNamedIFunc(StringRef Name) const;
+
+/// @}
/// @name Named Metadata Accessors
/// @{
@@ -486,6 +504,13 @@ public:
static AliasListType Module::*getSublistAccess(GlobalAlias*) {
return &Module::AliasList;
}
+ /// Get the Module's list of ifuncs (constant).
+ const IFuncListType &getIFuncList() const { return IFuncList; }
+ /// Get the Module's list of ifuncs.
+ IFuncListType &getIFuncList() { return IFuncList; }
+ static IFuncListType Module::*getSublistAccess(GlobalIFunc*) {
+ return &Module::IFuncList;
+ }
/// Get the Module's list of named metadata (constant).
const NamedMDListType &getNamedMDList() const { return NamedMDList; }
/// Get the Module's list of named metadata.
@@ -560,6 +585,24 @@ public:
}
/// @}
+/// @name IFunc Iteration
+/// @{
+
+ ifunc_iterator ifunc_begin() { return IFuncList.begin(); }
+ const_ifunc_iterator ifunc_begin() const { return IFuncList.begin(); }
+ ifunc_iterator ifunc_end () { return IFuncList.end(); }
+ const_ifunc_iterator ifunc_end () const { return IFuncList.end(); }
+ size_t ifunc_size () const { return IFuncList.size(); }
+ bool ifunc_empty() const { return IFuncList.empty(); }
+
+ iterator_range<ifunc_iterator> ifuncs() {
+ return make_range(ifunc_begin(), ifunc_end());
+ }
+ iterator_range<const_ifunc_iterator> ifuncs() const {
+ return make_range(ifunc_begin(), ifunc_end());
+ }
+
+/// @}
/// @name Named Metadata Iteration
/// @{
Modified: llvm/trunk/include/llvm/IR/SymbolTableListTraits.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/SymbolTableListTraits.h?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/SymbolTableListTraits.h (original)
+++ llvm/trunk/include/llvm/IR/SymbolTableListTraits.h Thu Apr 7 07:32:19 2016
@@ -49,6 +49,7 @@ class Function;
class Instruction;
class GlobalVariable;
class GlobalAlias;
+class GlobalIFunc;
class Module;
#define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT) \
template <> struct SymbolTableListParentType<NODE> { typedef PARENT type; };
@@ -58,6 +59,7 @@ DEFINE_SYMBOL_TABLE_PARENT_TYPE(Argument
DEFINE_SYMBOL_TABLE_PARENT_TYPE(Function, Module)
DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalVariable, Module)
DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalAlias, Module)
+DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalIFunc, Module)
#undef DEFINE_SYMBOL_TABLE_PARENT_TYPE
template <typename NodeTy> class SymbolTableList;
Modified: llvm/trunk/include/llvm/IR/Value.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Value.def?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Value.def (original)
+++ llvm/trunk/include/llvm/IR/Value.def Thu Apr 7 07:32:19 2016
@@ -60,6 +60,7 @@ HANDLE_VALUE(MemoryPhi)
HANDLE_GLOBAL_VALUE(Function)
HANDLE_GLOBAL_VALUE(GlobalAlias)
+HANDLE_GLOBAL_VALUE(GlobalIFunc)
HANDLE_GLOBAL_VALUE(GlobalVariable)
HANDLE_CONSTANT(BlockAddress)
HANDLE_CONSTANT(ConstantExpr)
Modified: llvm/trunk/include/llvm/IR/Value.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Value.h?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Value.h (original)
+++ llvm/trunk/include/llvm/IR/Value.h Thu Apr 7 07:32:19 2016
@@ -32,6 +32,7 @@ class ConstantAggregate;
class DataLayout;
class Function;
class GlobalAlias;
+class GlobalIFunc;
class GlobalIndirectSymbol;
class GlobalObject;
class GlobalValue;
@@ -751,9 +752,15 @@ template <> struct isa_impl<GlobalAlias,
}
};
+template <> struct isa_impl<GlobalIFunc, Value> {
+ static inline bool doit(const Value &Val) {
+ return Val.getValueID() == Value::GlobalIFuncVal;
+ }
+};
+
template <> struct isa_impl<GlobalIndirectSymbol, Value> {
static inline bool doit(const Value &Val) {
- return isa<GlobalAlias>(Val);
+ return isa<GlobalAlias>(Val) || isa<GlobalIFunc>(Val);
}
};
Modified: llvm/trunk/include/llvm/IR/ValueSymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ValueSymbolTable.h?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ValueSymbolTable.h (original)
+++ llvm/trunk/include/llvm/IR/ValueSymbolTable.h Thu Apr 7 07:32:19 2016
@@ -39,6 +39,7 @@ class ValueSymbolTable {
friend class SymbolTableListTraits<Function>;
friend class SymbolTableListTraits<GlobalVariable>;
friend class SymbolTableListTraits<GlobalAlias>;
+ friend class SymbolTableListTraits<GlobalIFunc>;
/// @name Types
/// @{
public:
Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Thu Apr 7 07:32:19 2016
@@ -560,6 +560,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(addrspace);
KEYWORD(section);
KEYWORD(alias);
+ KEYWORD(ifunc);
KEYWORD(module);
KEYWORD(asm);
KEYWORD(sideeffect);
Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Thu Apr 7 07:32:19 2016
@@ -467,10 +467,10 @@ bool LLParser::ParseGlobalType(bool &IsC
}
/// ParseUnnamedGlobal:
-/// OptionalVisibility ALIAS ...
+/// OptionalVisibility (ALIAS | IFUNC) ...
/// OptionalLinkage OptionalVisibility OptionalDLLStorageClass
/// ... -> global variable
-/// GlobalID '=' OptionalVisibility ALIAS ...
+/// GlobalID '=' OptionalVisibility (ALIAS | IFUNC) ...
/// GlobalID '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass
/// ... -> global variable
bool LLParser::ParseUnnamedGlobal() {
@@ -500,7 +500,7 @@ bool LLParser::ParseUnnamedGlobal() {
parseOptionalUnnamedAddr(UnnamedAddr))
return true;
- if (Lex.getKind() != lltok::kw_alias)
+ if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc)
return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility,
DLLStorageClass, TLM, UnnamedAddr);
@@ -509,7 +509,7 @@ bool LLParser::ParseUnnamedGlobal() {
}
/// ParseNamedGlobal:
-/// GlobalVar '=' OptionalVisibility ALIAS ...
+/// GlobalVar '=' OptionalVisibility (ALIAS | IFUNC) ...
/// GlobalVar '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass
/// ... -> global variable
bool LLParser::ParseNamedGlobal() {
@@ -530,7 +530,7 @@ bool LLParser::ParseNamedGlobal() {
parseOptionalUnnamedAddr(UnnamedAddr))
return true;
- if (Lex.getKind() != lltok::kw_alias)
+ if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc)
return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility,
DLLStorageClass, TLM, UnnamedAddr);
@@ -695,7 +695,7 @@ static bool isValidVisibilityForLinkage(
/// parseIndirectSymbol:
/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility
/// OptionalDLLStorageClass OptionalThreadLocal
-/// OptionalUnnamedAddr 'alias' IndirectSymbol
+/// OptionalUnnamedAddr 'alias|ifunc' IndirectSymbol
///
/// IndirectSymbol
/// ::= TypeAndValue
@@ -710,8 +710,10 @@ bool LLParser::parseIndirectSymbol(const
bool IsAlias;
if (Lex.getKind() == lltok::kw_alias)
IsAlias = true;
+ else if (Lex.getKind() == lltok::kw_ifunc)
+ IsAlias = false;
else
- llvm_unreachable("Not an alias!");
+ llvm_unreachable("Not an alias or ifunc!");
Lex.Lex();
GlobalValue::LinkageTypes Linkage = (GlobalValue::LinkageTypes) L;
@@ -726,7 +728,7 @@ bool LLParser::parseIndirectSymbol(const
Type *Ty;
LocTy ExplicitTypeLoc = Lex.getLoc();
if (ParseType(Ty) ||
- ParseToken(lltok::comma, "expected comma after alias's type"))
+ ParseToken(lltok::comma, "expected comma after alias or ifunc's type"))
return true;
Constant *Aliasee;
@@ -750,7 +752,7 @@ bool LLParser::parseIndirectSymbol(const
Type *AliaseeType = Aliasee->getType();
auto *PTy = dyn_cast<PointerType>(AliaseeType);
if (!PTy)
- return Error(AliaseeLoc, "An alias must have pointer type");
+ return Error(AliaseeLoc, "An alias or ifunc must have pointer type");
unsigned AddrSpace = PTy->getAddressSpace();
if (IsAlias && Ty != PTy->getElementType())
@@ -788,7 +790,9 @@ bool LLParser::parseIndirectSymbol(const
(GlobalValue::LinkageTypes)Linkage, Name,
Aliasee, /*Parent*/ nullptr));
else
- llvm_unreachable("Not an alias!");
+ GA.reset(GlobalIFunc::create(Ty, AddrSpace,
+ (GlobalValue::LinkageTypes)Linkage, Name,
+ Aliasee, /*Parent*/ nullptr));
GA->setThreadLocalMode(TLM);
GA->setVisibility((GlobalValue::VisibilityTypes)Visibility);
GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass);
@@ -814,7 +818,7 @@ bool LLParser::parseIndirectSymbol(const
if (IsAlias)
M->getAliasList().push_back(cast<GlobalAlias>(GA.get()));
else
- llvm_unreachable("Not an alias!");
+ M->getIFuncList().push_back(cast<GlobalIFunc>(GA.get()));
assert(GA->getName() == Name && "Should not be a name conflict!");
// The module owns this now
Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Thu Apr 7 07:32:19 2016
@@ -80,6 +80,7 @@ namespace lltok {
kw_addrspace,
kw_section,
kw_alias,
+ kw_ifunc,
kw_module,
kw_asm,
kw_sideeffect,
Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Thu Apr 7 07:32:19 2016
@@ -3658,6 +3658,8 @@ std::error_code BitcodeReader::parseModu
}
// ALIAS: [alias type, addrspace, aliasee val#, linkage]
// ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility, dllstorageclass]
+ // IFUNC: [alias type, addrspace, aliasee val#, linkage, visibility, dllstorageclass]
+ case bitc::MODULE_CODE_IFUNC:
case bitc::MODULE_CODE_ALIAS:
case bitc::MODULE_CODE_ALIAS_OLD: {
bool NewRecord = BitCode != bitc::MODULE_CODE_ALIAS_OLD;
@@ -3684,10 +3686,11 @@ std::error_code BitcodeReader::parseModu
GlobalIndirectSymbol *NewGA;
if (BitCode == bitc::MODULE_CODE_ALIAS ||
BitCode == bitc::MODULE_CODE_ALIAS_OLD)
- NewGA = GlobalAlias::create(
- Ty, AddrSpace, getDecodedLinkage(Linkage), "", TheModule);
+ NewGA = GlobalAlias::create(Ty, AddrSpace, getDecodedLinkage(Linkage),
+ "", TheModule);
else
- llvm_unreachable("Not an alias!");
+ NewGA = GlobalIFunc::create(Ty, AddrSpace, getDecodedLinkage(Linkage),
+ "", nullptr, TheModule);
// Old bitcode files didn't have visibility field.
// Local linkage must have default visibility.
if (OpNum != Record.size()) {
Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Thu Apr 7 07:32:19 2016
@@ -809,6 +809,18 @@ static uint64_t WriteModuleInfo(const Mo
Vals.clear();
}
+ // Emit the ifunc information.
+ for (const GlobalIFunc &I : M->ifuncs()) {
+ // IFUNC: [ifunc type, address space, resolver val#, linkage, visibility]
+ Vals.push_back(VE.getTypeID(I.getValueType()));
+ Vals.push_back(I.getType()->getAddressSpace());
+ Vals.push_back(VE.getValueID(I.getResolver()));
+ Vals.push_back(getEncodedLinkage(I));
+ Vals.push_back(getEncodedVisibility(I));
+ Stream.EmitRecord(bitc::MODULE_CODE_IFUNC, Vals);
+ Vals.clear();
+ }
+
// Emit the module's source file name.
{
StringEncoding Bits = getStringEncoding(M->getSourceFileName().data(),
Modified: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp Thu Apr 7 07:32:19 2016
@@ -86,6 +86,9 @@ static OrderMap orderModule(const Module
for (const GlobalAlias &A : M.aliases())
if (!isa<GlobalValue>(A.getAliasee()))
orderValue(A.getAliasee(), OM);
+ for (const GlobalIFunc &I : M.ifuncs())
+ if (!isa<GlobalValue>(I.getResolver()))
+ orderValue(I.getResolver(), OM);
for (const Function &F : M) {
for (const Use &U : F.operands())
if (!isa<GlobalValue>(U.get()))
@@ -105,6 +108,8 @@ static OrderMap orderModule(const Module
orderValue(&F, OM);
for (const GlobalAlias &A : M.aliases())
orderValue(&A, OM);
+ for (const GlobalIFunc &I : M.ifuncs())
+ orderValue(&I, OM);
for (const GlobalVariable &G : M.globals())
orderValue(&G, OM);
OM.LastGlobalValueID = OM.size();
@@ -261,11 +266,15 @@ static UseListOrderStack predictUseListO
predictValueUseListOrder(&F, nullptr, OM, Stack);
for (const GlobalAlias &A : M.aliases())
predictValueUseListOrder(&A, nullptr, OM, Stack);
+ for (const GlobalIFunc &I : M.ifuncs())
+ predictValueUseListOrder(&I, nullptr, OM, Stack);
for (const GlobalVariable &G : M.globals())
if (G.hasInitializer())
predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack);
for (const GlobalAlias &A : M.aliases())
predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack);
+ for (const GlobalIFunc &I : M.ifuncs())
+ predictValueUseListOrder(I.getResolver(), nullptr, OM, Stack);
for (const Function &F : M) {
for (const Use &U : F.operands())
predictValueUseListOrder(U.get(), nullptr, OM, Stack);
@@ -298,6 +307,10 @@ ValueEnumerator::ValueEnumerator(const M
for (const GlobalAlias &GA : M.aliases())
EnumerateValue(&GA);
+ // Enumerate the ifuncs.
+ for (const GlobalIFunc &GIF : M.ifuncs())
+ EnumerateValue(&GIF);
+
// Remember what is the cutoff between globalvalue's and other constants.
unsigned FirstConstant = Values.size();
@@ -310,6 +323,10 @@ ValueEnumerator::ValueEnumerator(const M
for (const GlobalAlias &GA : M.aliases())
EnumerateValue(GA.getAliasee());
+ // Enumerate the ifunc resolvers.
+ for (const GlobalIFunc &GIF : M.ifuncs())
+ EnumerateValue(GIF.getResolver());
+
// Enumerate any optional Function data.
for (const Function &F : M)
for (const Use &U : F.operands())
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Thu Apr 7 07:32:19 2016
@@ -1069,12 +1069,15 @@ void AsmPrinter::emitGlobalIndirectSymbo
else if (GIS.hasWeakLinkage() || GIS.hasLinkOnceLinkage())
OutStreamer->EmitSymbolAttribute(Name, MCSA_WeakReference);
else
- assert(GIS.hasLocalLinkage() && "Invalid alias linkage");
+ assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage");
// Set the symbol type to function if the alias has a function type.
// This affects codegen when the aliasee is not a function.
- if (GIS.getType()->getPointerElementType()->isFunctionTy())
+ if (GIS.getType()->getPointerElementType()->isFunctionTy()) {
OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeFunction);
+ if (isa<GlobalIFunc>(GIS))
+ OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeIndFunction);
+ }
EmitVisibility(Name, GIS.getVisibility());
@@ -1209,6 +1212,8 @@ bool AsmPrinter::doFinalization(Module &
emitGlobalIndirectSymbol(M, *AncestorAlias);
AliasStack.clear();
}
+ for (const auto &IFunc : M.ifuncs())
+ emitGlobalIndirectSymbol(M, IFunc);
GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
assert(MI && "AsmPrinter didn't require GCModuleInfo?");
Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Thu Apr 7 07:32:19 2016
@@ -102,6 +102,11 @@ static OrderMap orderModule(const Module
orderValue(A.getAliasee(), OM);
orderValue(&A, OM);
}
+ for (const GlobalIFunc &I : M->ifuncs()) {
+ if (!isa<GlobalValue>(I.getResolver()))
+ orderValue(I.getResolver(), OM);
+ orderValue(&I, OM);
+ }
for (const Function &F : *M) {
for (const Use &U : F.operands())
if (!isa<GlobalValue>(U.get()))
@@ -249,11 +254,15 @@ static UseListOrderStack predictUseListO
predictValueUseListOrder(&F, nullptr, OM, Stack);
for (const GlobalAlias &A : M->aliases())
predictValueUseListOrder(&A, nullptr, OM, Stack);
+ for (const GlobalIFunc &I : M->ifuncs())
+ predictValueUseListOrder(&I, nullptr, OM, Stack);
for (const GlobalVariable &G : M->globals())
if (G.hasInitializer())
predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack);
for (const GlobalAlias &A : M->aliases())
predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack);
+ for (const GlobalIFunc &I : M->ifuncs())
+ predictValueUseListOrder(I.getResolver(), nullptr, OM, Stack);
for (const Function &F : *M)
for (const Use &U : F.operands())
predictValueUseListOrder(U.get(), nullptr, OM, Stack);
@@ -729,6 +738,9 @@ static SlotTracker *createSlotTracker(co
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
return new SlotTracker(GA->getParent());
+ if (const GlobalIFunc *GIF = dyn_cast<GlobalIFunc>(V))
+ return new SlotTracker(GIF->getParent());
+
if (const Function *Func = dyn_cast<Function>(V))
return new SlotTracker(Func);
@@ -782,6 +794,11 @@ void SlotTracker::processModule() {
CreateModuleSlot(&A);
}
+ for (const GlobalIFunc &I : TheModule->ifuncs()) {
+ if (!I.hasName())
+ CreateModuleSlot(&I);
+ }
+
// Add metadata used by named metadata.
for (const NamedMDNode &NMD : TheModule->named_metadata()) {
for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
@@ -945,10 +962,11 @@ void SlotTracker::CreateModuleSlot(const
ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" <<
DestSlot << " [");
- // G = Global, F = Function, A = Alias, o = other
+ // G = Global, F = Function, A = Alias, I = IFunc, o = other
ST_DEBUG((isa<GlobalVariable>(V) ? 'G' :
(isa<Function>(V) ? 'F' :
- (isa<GlobalAlias>(V) ? 'A' : 'o'))) << "]\n");
+ (isa<GlobalAlias>(V) ? 'A' :
+ (isa<GlobalIFunc>(V) ? 'I' : 'o')))) << "]\n");
}
/// CreateSlot - Create a new slot for the specified value if it has no name.
@@ -2253,6 +2271,11 @@ void AssemblyWriter::printModule(const M
for (const GlobalAlias &GA : M->aliases())
printIndirectSymbol(&GA);
+ // Output all ifuncs.
+ if (!M->ifunc_empty()) Out << "\n";
+ for (const GlobalIFunc &GI : M->ifuncs())
+ printIndirectSymbol(&GI);
+
// Output global use-lists.
printUseLists(nullptr);
@@ -2448,8 +2471,10 @@ void AssemblyWriter::printIndirectSymbol
if (isa<GlobalAlias>(GIS))
Out << "alias ";
+ else if (isa<GlobalIFunc>(GIS))
+ Out << "ifunc ";
else
- llvm_unreachable("Not an alias!");
+ llvm_unreachable("Not an alias or ifunc!");
TypePrinter.print(GIS->getValueType(), Out);
Modified: llvm/trunk/lib/IR/Globals.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Globals.cpp?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Globals.cpp (original)
+++ llvm/trunk/lib/IR/Globals.cpp Thu Apr 7 07:32:19 2016
@@ -145,6 +145,9 @@ Comdat *GlobalValue::getComdat() {
return const_cast<GlobalObject *>(GO)->getComdat();
return nullptr;
}
+ // ifunc and its resolver are separate things so don't use resolver comdat.
+ if (isa<GlobalIFunc>(this))
+ return nullptr;
return cast<GlobalObject>(this)->getComdat();
}
@@ -364,3 +367,34 @@ void GlobalAlias::setAliasee(Constant *A
"Alias and aliasee types should match!");
setIndirectSymbol(Aliasee);
}
+
+//===----------------------------------------------------------------------===//
+// GlobalIFunc Implementation
+//===----------------------------------------------------------------------===//
+
+GlobalIFunc::GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Link,
+ const Twine &Name, Constant *Resolver,
+ Module *ParentModule)
+ : GlobalIndirectSymbol(Ty, Value::GlobalIFuncVal, AddressSpace, Link, Name,
+ Resolver) {
+ if (ParentModule)
+ ParentModule->getIFuncList().push_back(this);
+}
+
+GlobalIFunc *GlobalIFunc::create(Type *Ty, unsigned AddressSpace,
+ LinkageTypes Link, const Twine &Name,
+ Constant *Resolver, Module *ParentModule) {
+ return new GlobalIFunc(Ty, AddressSpace, Link, Name, Resolver, ParentModule);
+}
+
+void GlobalIFunc::setParent(Module *parent) {
+ Parent = parent;
+}
+
+void GlobalIFunc::removeFromParent() {
+ getParent()->getIFuncList().remove(getIterator());
+}
+
+void GlobalIFunc::eraseFromParent() {
+ getParent()->getIFuncList().erase(getIterator());
+}
Modified: llvm/trunk/lib/IR/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Module.cpp?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Module.cpp (original)
+++ llvm/trunk/lib/IR/Module.cpp Thu Apr 7 07:32:19 2016
@@ -41,6 +41,7 @@ using namespace llvm;
template class llvm::SymbolTableListTraits<Function>;
template class llvm::SymbolTableListTraits<GlobalVariable>;
template class llvm::SymbolTableListTraits<GlobalAlias>;
+template class llvm::SymbolTableListTraits<GlobalIFunc>;
//===----------------------------------------------------------------------===//
// Primitive Module methods.
@@ -59,6 +60,7 @@ Module::~Module() {
GlobalList.clear();
FunctionList.clear();
AliasList.clear();
+ IFuncList.clear();
NamedMDList.clear();
delete ValSymTab;
delete static_cast<StringMap<NamedMDNode *> *>(NamedMDSymTab);
@@ -250,6 +252,10 @@ GlobalAlias *Module::getNamedAlias(Strin
return dyn_cast_or_null<GlobalAlias>(getNamedValue(Name));
}
+GlobalIFunc *Module::getNamedIFunc(StringRef Name) const {
+ return dyn_cast_or_null<GlobalIFunc>(getNamedValue(Name));
+}
+
/// getNamedMetadata - Return the first NamedMDNode in the module with the
/// specified name. This method returns null if a NamedMDNode with the
/// specified name is not found.
@@ -438,6 +444,9 @@ void Module::dropAllReferences() {
for (GlobalAlias &GA : aliases())
GA.dropAllReferences();
+
+ for (GlobalIFunc &GIF : ifuncs())
+ GIF.dropAllReferences();
}
unsigned Module::getDwarfVersion() const {
Added: llvm/trunk/test/Assembler/ifunc-asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/ifunc-asm.ll?rev=265667&view=auto
==============================================================================
--- llvm/trunk/test/Assembler/ifunc-asm.ll (added)
+++ llvm/trunk/test/Assembler/ifunc-asm.ll Thu Apr 7 07:32:19 2016
@@ -0,0 +1,14 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s --check-prefix=CHECK-LLVM
+; RUN: llvm-as < %s -o - | llc -filetype=asm | FileCheck %s --check-prefix=CHECK-ASM
+
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = ifunc i32 (i32), i64 ()* @foo_ifunc
+; CHECK-LLVM: @foo = ifunc i32 (i32), i64 ()* @foo_ifunc
+; CHECK-ASM: .type foo, at gnu_indirect_function
+
+define internal i64 @foo_ifunc() {
+entry:
+ ret i64 0
+}
+; CHECK-LLVM: define internal i64 @foo_ifunc()
Added: llvm/trunk/test/Assembler/ifunc-use-list-order.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/ifunc-use-list-order.ll?rev=265667&view=auto
==============================================================================
--- llvm/trunk/test/Assembler/ifunc-use-list-order.ll (added)
+++ llvm/trunk/test/Assembler/ifunc-use-list-order.ll Thu Apr 7 07:32:19 2016
@@ -0,0 +1,42 @@
+; RUN: verify-uselistorder < %s
+
+; Global referencing ifunc.
+ at ptr_foo = global void ()* @foo_ifunc
+
+; Alias for ifunc.
+ at alias_foo = alias void (), void ()* @foo_ifunc
+
+ at foo_ifunc = ifunc void (), i8* ()* @foo_resolver
+
+define i8* @foo_resolver() {
+entry:
+ ret i8* null
+}
+
+; Function referencing ifunc.
+define void @bar() {
+entry:
+ call void @foo_ifunc()
+ ret void
+}
+
+; Global referencing function.
+ at ptr_bar = global void ()* @bar
+
+; Alias for function.
+ at alias_bar = alias void (), void ()* @bar
+
+ at bar_ifunc = ifunc void (), i8* ()* @bar2_ifunc
+ at bar2_ifunc = ifunc i8* (), i8* ()* @bar_resolver
+
+define i8* @bar_resolver() {
+entry:
+ ret i8* null
+}
+
+; Function referencing bar.
+define void @bar2() {
+entry:
+ call void @bar()
+ ret void
+}
Modified: llvm/trunk/test/Bitcode/compatibility.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility.ll?rev=265667&r1=265666&r2=265667&view=diff
==============================================================================
--- llvm/trunk/test/Bitcode/compatibility.ll (original)
+++ llvm/trunk/test/Bitcode/compatibility.ll Thu Apr 7 07:32:19 2016
@@ -249,6 +249,31 @@ declare void @g.f1()
@a.unnamed_addr = unnamed_addr alias i32, i32* @g.unnamed_addr
; CHECK: @a.unnamed_addr = unnamed_addr alias i32, i32* @g.unnamed_addr
+;; IFunc
+; Format @<Name> = [Linkage] [Visibility] ifunc <IFuncTy>,
+; <ResolverTy>* @<Resolver>
+
+; IFunc -- Linkage
+ at ifunc.external = external ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.external = ifunc void (), i8* ()* @ifunc_resolver
+ at ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
+ at ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
+
+; IFunc -- Visibility
+ at ifunc.default = default ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.default = ifunc void (), i8* ()* @ifunc_resolver
+ at ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
+ at ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
+
+define i8* @ifunc_resolver() {
+entry:
+ ret i8* null
+}
+
;; Functions
; Format: define [linkage] [visibility] [DLLStorageClass]
; [cconv] [ret attrs]
More information about the llvm-commits
mailing list