GlobalIFunc: Make allowed constant expressions stricter
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Thu, 24 Nov 2022 02:23:47 +0000 (21:23 -0500)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Fri, 2 Dec 2022 20:20:57 +0000 (15:20 -0500)
This was allowing getelementptr with offsets, which doesn't make
sense. My initial attempt to use stripPointerCasts broke a few tests
involving aliases; add a new targeted verifier test for aliases.

This also provides the fix from D138537 for free, and also adds
support for addrspacecast (D138538) for free. Merge the tests in from
those.

I'm not really sure why findBaseObject exists; it seems redundant with
stripPointerCasts* (I'm also not really sure why getelementptrs are
allowed off of functions).

llvm/lib/IR/Globals.cpp
llvm/test/Assembler/ifunc-stripPointerCastsAndAliases.ll [new file with mode: 0644]
llvm/test/Verifier/ifunc-opaque.ll [new file with mode: 0644]

index 7880369..41b090a 100644 (file)
@@ -584,9 +584,7 @@ void GlobalIFunc::eraseFromParent() {
 }
 
 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(
diff --git a/llvm/test/Assembler/ifunc-stripPointerCastsAndAliases.ll b/llvm/test/Assembler/ifunc-stripPointerCastsAndAliases.ll
new file mode 100644 (file)
index 0000000..ae1b446
--- /dev/null
@@ -0,0 +1,23 @@
+; 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
+}
diff --git a/llvm/test/Verifier/ifunc-opaque.ll b/llvm/test/Verifier/ifunc-opaque.ll
new file mode 100644 (file)
index 0000000..349207b
--- /dev/null
@@ -0,0 +1,17 @@
+; 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)