From f883e75497b610de81b3a6af106c976bb3c2bbb1 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 23 Nov 2022 21:23:47 -0500 Subject: [PATCH] GlobalIFunc: Make allowed constant expressions stricter 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 | 4 +--- .../Assembler/ifunc-stripPointerCastsAndAliases.ll | 23 ++++++++++++++++++++++ llvm/test/Verifier/ifunc-opaque.ll | 17 ++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 llvm/test/Assembler/ifunc-stripPointerCastsAndAliases.ll create mode 100644 llvm/test/Verifier/ifunc-opaque.ll diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index 7880369..41b090a 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -584,9 +584,7 @@ void GlobalIFunc::eraseFromParent() { } const Function *GlobalIFunc::getResolverFunction() const { - DenseSet Aliases; - return dyn_cast( - findBaseObject(getResolver(), Aliases, [](const GlobalValue &) {})); + return dyn_cast(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 index 0000000..ae1b446 --- /dev/null +++ b/llvm/test/Assembler/ifunc-stripPointerCastsAndAliases.ll @@ -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 index 0000000..349207b --- /dev/null +++ b/llvm/test/Verifier/ifunc-opaque.ll @@ -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) -- 2.7.4