summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/AsmParser/LLLexer.cpp1
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp26
-rw-r--r--llvm/lib/AsmParser/LLToken.h1
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp9
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp12
-rw-r--r--llvm/lib/Bitcode/Writer/ValueEnumerator.cpp17
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp9
-rw-r--r--llvm/lib/IR/AsmWriter.cpp31
-rw-r--r--llvm/lib/IR/Globals.cpp34
-rw-r--r--llvm/lib/IR/Module.cpp9
10 files changed, 130 insertions, 19 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 58558b99dfa..be7ab960db3 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -560,6 +560,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(addrspace);
KEYWORD(section);
KEYWORD(alias);
+ KEYWORD(ifunc);
KEYWORD(module);
KEYWORD(asm);
KEYWORD(sideeffect);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index bf1d2f005ee..db87fa75a58 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -467,10 +467,10 @@ bool LLParser::ParseGlobalType(bool &IsConstant) {
}
/// 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(unsigned V, unsigned L) {
/// parseIndirectSymbol:
/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility
/// OptionalDLLStorageClass OptionalThreadLocal
-/// OptionalUnnamedAddr 'alias' IndirectSymbol
+/// OptionalUnnamedAddr 'alias|ifunc' IndirectSymbol
///
/// IndirectSymbol
/// ::= TypeAndValue
@@ -710,8 +710,10 @@ bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc,
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 std::string &Name, LocTy NameLoc,
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 std::string &Name, LocTy NameLoc,
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 std::string &Name, LocTy NameLoc,
(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 std::string &Name, LocTy NameLoc,
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
diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h
index c6258046cf0..20e563b0e96 100644
--- a/llvm/lib/AsmParser/LLToken.h
+++ b/llvm/lib/AsmParser/LLToken.h
@@ -80,6 +80,7 @@ namespace lltok {
kw_addrspace,
kw_section,
kw_alias,
+ kw_ifunc,
kw_module,
kw_asm,
kw_sideeffect,
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 0e74fe38d63..b8ebe8f517b 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -3658,6 +3658,8 @@ std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,
}
// 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::parseModule(uint64_t ResumeBit,
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 cbaaea8bbc6..23cd0888726 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -809,6 +809,18 @@ static uint64_t WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
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 91b523f05bc..ff87052c4ef 100644
--- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -86,6 +86,9 @@ static OrderMap orderModule(const Module &M) {
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 &M) {
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 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);
@@ -298,6 +307,10 @@ ValueEnumerator::ValueEnumerator(const Module &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 Module &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())
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 216cab7b30e..32efab094e0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1069,12 +1069,15 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M,
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 &M) {
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?");
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 {
OpenPOWER on IntegriCloud