return getIndirectSymbol();
}
+ const GlobalObject *getBaseObject() const;
+ GlobalObject *getBaseObject() {
+ return const_cast<GlobalObject *>(
+ static_cast<const GlobalAlias *>(this)->getBaseObject());
+ }
+
static bool isValidLinkage(LinkageTypes L) {
return isExternalLinkage(L) || isLocalLinkage(L) ||
isWeakLinkage(L) || isLinkOnceLinkage(L);
void setResolver(Constant *Resolver) {
setIndirectSymbol(Resolver);
}
- const Constant *getResolver() const {
- return getIndirectSymbol();
- }
- Constant *getResolver() {
- return getIndirectSymbol();
+ const Constant *getResolver() const { return getIndirectSymbol(); }
+ Constant *getResolver() { return getIndirectSymbol(); }
+
+ // Return the resolver function after peeling off potential ConstantExpr
+ // indirection.
+ const Function *getResolverFunction() const;
+ Function *getResolverFunction() {
+ return const_cast<Function *>(
+ static_cast<const GlobalIFunc *>(this)->getResolverFunction());
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
const GlobalObject *GlobalValue::getBaseObject() const {
if (auto *GO = dyn_cast<GlobalObject>(this))
return GO;
- if (auto *GA = dyn_cast<GlobalIndirectSymbol>(this))
+ if (auto *GA = dyn_cast<GlobalAlias>(this))
return GA->getBaseObject();
return nullptr;
}
return nullptr;
}
-const GlobalObject *GlobalIndirectSymbol::getBaseObject() const {
- DenseSet<const GlobalAlias *> Aliases;
- return findBaseObject(getOperand(0), Aliases);
-}
-
//===----------------------------------------------------------------------===//
// GlobalAlias Implementation
//===----------------------------------------------------------------------===//
setIndirectSymbol(Aliasee);
}
+const GlobalObject *GlobalAlias::getBaseObject() const {
+ DenseSet<const GlobalAlias *> Aliases;
+ return findBaseObject(getOperand(0), Aliases);
+}
+
//===----------------------------------------------------------------------===//
// GlobalIFunc Implementation
//===----------------------------------------------------------------------===//
void GlobalIFunc::eraseFromParent() {
getParent()->getIFuncList().erase(getIterator());
}
+
+const Function *GlobalIFunc::getResolverFunction() const {
+ DenseSet<const GlobalAlias *> Aliases;
+ return cast<Function>(findBaseObject(getIndirectSymbol(), Aliases));
+}
}
const GlobalObject *Base = GV->getBaseObject();
- if (!Base)
- return make_error<StringError>("Unable to determine comdat of alias!",
- inconvertibleErrorCode());
+ if (!Base) {
+ if (isa<GlobalIFunc>(GV))
+ Base = cast<GlobalIFunc>(GV)->getResolverFunction();
+ if (!Base)
+ return make_error<StringError>("Unable to determine comdat of alias!",
+ inconvertibleErrorCode());
+ }
if (const Comdat *C = Base->getComdat()) {
Expected<int> ComdatIndexOrErr = getComdatIndex(C, GV->getParent());
if (!ComdatIndexOrErr)
if (GVar->isConstant())
Res |= BasicSymbolRef::SF_Const;
}
- if (dyn_cast_or_null<Function>(GV->getBaseObject()))
+ if (isa_and_nonnull<Function>(GV->getBaseObject()) || isa<GlobalIFunc>(GV))
Res |= BasicSymbolRef::SF_Executable;
if (isa<GlobalAlias>(GV))
Res |= BasicSymbolRef::SF_Indirect;
// For aliases we should not separate them from their aliasees regardless
// of linkage.
- if (auto *GIS = dyn_cast<GlobalIndirectSymbol>(&GV)) {
+ if (auto *GIS = dyn_cast<GlobalAlias>(&GV)) {
if (const GlobalObject *Base = GIS->getBaseObject())
GVtoClusterMap.unionSets(&GV, Base);
+ } else if (auto *GIS = dyn_cast<GlobalIFunc>(&GV)) {
+ GVtoClusterMap.unionSets(&GV, GIS->getResolverFunction());
}
if (const Function *F = dyn_cast<Function>(&GV)) {
// Returns whether GV should be in partition (0-based) I of N.
static bool isInPartition(const GlobalValue *GV, unsigned I, unsigned N) {
- if (auto *GIS = dyn_cast<GlobalIndirectSymbol>(GV))
+ if (auto *GIS = dyn_cast<GlobalAlias>(GV)) {
if (const GlobalObject *Base = GIS->getBaseObject())
GV = Base;
+ } else if (auto *GIS = dyn_cast<GlobalIFunc>(GV)) {
+ GV = GIS->getResolverFunction();
+ }
StringRef Name;
if (const Comdat *C = GV->getComdat())
; RUN: opt -module-summary -o %t.bc %s
-; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,pl -o %t2
+; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,pl -r %t.bc,strlen,pl -o %t2
; RUN: llvm-nm %t2.1 | FileCheck %s
; CHECK: i foo
-; CHECK: t foo_ifunc
+; CHECK: t foo_resolver
+; CHECK: i strlen
+; CHECK: t strlen_resolver
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
-@foo = ifunc i32 (i32), i64 ()* @foo_ifunc
+@foo = ifunc i32 (i32), i64 ()* @foo_resolver
+@strlen = ifunc i64 (i8*), bitcast (i64 (i8*)* ()* @strlen_resolver to i64 (i8*)*)
-define internal i64 @foo_ifunc() {
+define internal i64 @foo_resolver() {
entry:
ret i64 0
}
+
+define internal i64 (i8*)* @strlen_resolver() {
+entry:
+ ret i64 (i8*)* null
+}