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/AsmParser/LLParser.cpp | |
parent | 79cb643b201bfa1acba9a1afef7395f3be3f60e6 (diff) | |
download | llvm-a1feff7024b552b579f302fea0030aaaa14624b3.zip llvm-a1feff7024b552b579f302fea0030aaaa14624b3.tar.gz llvm-a1feff7024b552b579f302fea0030aaaa14624b3.tar.bz2 |
[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/AsmParser/LLParser.cpp')
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index bf1d2f00..db87fa7 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 |