diff options
author | Dmitry Polukhin <dmitry.polukhin@gmail.com> | 2016-04-07 12:32:19 +0000 |
---|---|---|
committer | Dmitry Polukhin <dmitry.polukhin@gmail.com> | 2016-04-07 12:32:19 +0000 |
commit | a1feff7024b552b579f302fea0030aaaa14624b3 (patch) | |
tree | bc5cbda70333854512705e91da81598e4368a052 /llvm/lib/IR | |
parent | 79cb643b201bfa1acba9a1afef7395f3be3f60e6 (diff) | |
download | bcm5719-llvm-a1feff7024b552b579f302fea0030aaaa14624b3.tar.gz bcm5719-llvm-a1feff7024b552b579f302fea0030aaaa14624b3.zip |
[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
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/IR/Globals.cpp | 34 | ||||
-rw-r--r-- | llvm/lib/IR/Module.cpp | 9 |
3 files changed, 71 insertions, 3 deletions
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 0dd49a43022..2e04677043c 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -102,6 +102,11 @@ static OrderMap orderModule(const Module *M) { 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 predictUseListOrder(const Module *M) { 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(const Value *V) { 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 GlobalValue *V) { 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 Module *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(const GlobalIndirectSymbol *GIS) { 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); diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index a0d59fddfc4..a9702b7af81 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -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 *Aliasee) { "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()); +} diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index a0bda0035f7..0a2dcc1dcf6 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -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(StringRef Name) const { 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 { |