}
const Function *GlobalIFunc::getResolverFunction() const {
- DenseSet<const GlobalAlias *> Aliases;
- return dyn_cast<Function>(
- findBaseObject(getResolver(), Aliases, [](const GlobalValue &) {}));
+ return dyn_cast<Function>(getResolver()->stripPointerCastsAndAliases());
}
void GlobalIFunc::applyAlongResolverPath(
--- /dev/null
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+
+; Check constantexprs which ifunc looks through to find the resolver
+; function.
+
+@ifunc_addrspacecast_as1_to_as0 = ifunc void (), ptr addrspacecast (ptr addrspace(1) @resolver_as1 to ptr)
+
+; CHECK: @alias_resolver = internal alias i32 (i32), ptr @resolver
+@alias_resolver = internal alias i32 (i32), ptr @resolver
+
+; CHECK: @ifunc_resolver_is_alias = internal ifunc i32 (i32), ptr @alias_resolver
+@ifunc_resolver_is_alias = internal ifunc i32 (i32), ptr @alias_resolver
+
+
+; CHECK: define ptr @resolver_as1() addrspace(1) {
+define ptr @resolver_as1() addrspace(1) {
+ ret ptr null
+}
+
+; CHECK: define internal ptr @resolver() {
+define internal ptr @resolver() {
+ ret ptr null
+}
--- /dev/null
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+define ptr @resolver() {
+ ret ptr null
+}
+
+; CHECK: IFunc must have a Function resolver
+; CHECK-NEXT: ptr @ifunc_getelementptr
+@ifunc_getelementptr = ifunc void (), ptr getelementptr (i8, ptr @resolver, i32 4)
+
+
+; Make sure nothing asserts on an unhandled constantexpr for the
+; resolver.
+
+; CHECK: IFunc must have a Function resolver
+; CHECK-NEXT: ptr @ifunc_shl
+@ifunc_shl = ifunc void (), ptr inttoptr (i64 shl (i64 ptrtoint (ptr @resolver to i64), i64 4) to ptr)