diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLToken.h | 1 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/ValueEnumerator.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 9 | ||||
-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 |
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 { |