[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
llvm-svn: 265667
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 0e74fe3..b8ebe8f 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -3658,6 +3658,8 @@
}
// 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 @@
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()) {
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index cbaaea8..23cd088 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -809,6 +809,18 @@
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(),
diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
index 91b523f..ff87052 100644
--- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -86,6 +86,9 @@
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 @@
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 @@
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 @@
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 @@
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())