Index: llvm/lib/IR/Globals.cpp =================================================================== --- llvm/lib/IR/Globals.cpp +++ llvm/lib/IR/Globals.cpp @@ -541,5 +541,5 @@ const Function *GlobalIFunc::getResolverFunction() const { DenseSet Aliases; - return cast(findBaseObject(getResolver(), Aliases)); + return dyn_cast(findBaseObject(getResolver(), Aliases)); } Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -415,6 +415,9 @@ for (const GlobalAlias &GA : M.aliases()) visitGlobalAlias(GA); + for (const GlobalIFunc &GI : M.ifuncs()) + visitGlobalIFunc(GI); + for (const NamedMDNode &NMD : M.named_metadata()) visitNamedMDNode(NMD); @@ -440,6 +443,7 @@ void visitGlobalValue(const GlobalValue &GV); void visitGlobalVariable(const GlobalVariable &GV); void visitGlobalAlias(const GlobalAlias &GA); + void visitGlobalIFunc(const GlobalIFunc &GI); void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); void visitAliaseeSubExpr(SmallPtrSetImpl &Visited, const GlobalAlias &A, const Constant &C); @@ -821,6 +825,15 @@ visitGlobalValue(GA); } +void Verifier::visitGlobalIFunc(const GlobalIFunc &GI) { + const Function *Resolver = GI.getResolverFunction(); + Assert(Resolver, "IFunc must have a Function resolver", &GI); + Assert(!Resolver->isDeclarationForLinker(), + "IFunc resolver must be a definition", &GI); + Assert(GI.getType() == Resolver->getFunctionType()->getReturnType(), + "IFunc resolver return type must match IFunc type", &GI); +} + void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { // There used to be various other llvm.dbg.* nodes, but we don't support // upgrading them and we want to reserve the namespace for future uses. Index: llvm/test/Assembler/ifunc-asm.ll =================================================================== --- llvm/test/Assembler/ifunc-asm.ll +++ llvm/test/Assembler/ifunc-asm.ll @@ -2,11 +2,11 @@ target triple = "x86_64-unknown-linux-gnu" -@foo = ifunc i32 (i32), i64 ()* @foo_ifunc -; CHECK: @foo = ifunc i32 (i32), i64 ()* @foo_ifunc +@foo = ifunc i32 (i32), i32 (i32)* ()* @foo_ifunc +; CHECK: @foo = ifunc i32 (i32), i32 (i32)* ()* @foo_ifunc -define internal i64 @foo_ifunc() { +define internal i32 (i32)* @foo_ifunc() { entry: - ret i64 0 + ret i32 (i32)* null } -; CHECK: define internal i64 @foo_ifunc() +; CHECK: define internal i32 (i32)* @foo_ifunc() Index: llvm/test/Assembler/ifunc-dsolocal.ll =================================================================== --- llvm/test/Assembler/ifunc-dsolocal.ll +++ llvm/test/Assembler/ifunc-dsolocal.ll @@ -1,9 +1,9 @@ ; RUN: llvm-as < %s | llvm-dis | FileCheck %s -@foo = dso_local ifunc i32 (i32), i64 ()* @foo_ifunc -; CHECK: @foo = dso_local ifunc i32 (i32), i64 ()* @foo_ifunc +@foo = dso_local ifunc i32 (i32), i32 (i32)* ()* @foo_ifunc +; CHECK: @foo = dso_local ifunc i32 (i32), i32 (i32)* ()* @foo_ifunc -define internal i64 @foo_ifunc() { +define internal i32 (i32)* @foo_ifunc() { entry: - ret i64 0 + ret i32 (i32)* null } Index: llvm/test/Assembler/ifunc-use-list-order.ll =================================================================== --- llvm/test/Assembler/ifunc-use-list-order.ll +++ llvm/test/Assembler/ifunc-use-list-order.ll @@ -6,11 +6,11 @@ ; Alias for ifunc. @alias_foo = alias void (), void ()* @foo_ifunc -@foo_ifunc = ifunc void (), i8* ()* @foo_resolver +@foo_ifunc = ifunc void (), void ()* ()* @foo_resolver -define i8* @foo_resolver() { +define void ()* @foo_resolver() { entry: - ret i8* null + ret void ()* null } ; Function referencing ifunc. @@ -26,12 +26,11 @@ ; Alias for function. @alias_bar = alias void (), void ()* @bar -@bar_ifunc = ifunc void (), i8* ()* @bar2_ifunc -@bar2_ifunc = ifunc i8* (), i8* ()* @bar_resolver +@bar_ifunc = ifunc void (), void ()* ()* @bar_resolver -define i8* @bar_resolver() { +define void ()* @bar_resolver() { entry: - ret i8* null + ret void ()* null } ; Function referencing bar. Index: llvm/test/Bindings/llvm-c/echo.ll =================================================================== --- llvm/test/Bindings/llvm-c/echo.ll +++ llvm/test/Bindings/llvm-c/echo.ll @@ -29,11 +29,11 @@ @aliased4 = weak alias i32, i32* @var @aliased5 = weak_odr alias i32, i32* @var -@ifunc = ifunc i32 (i32), i64 ()* @ifunc_resolver +@ifunc = ifunc i32 (i32), i32 (i32)* ()* @ifunc_resolver -define i64 @ifunc_resolver() { +define i32 (i32)* @ifunc_resolver() { entry: - ret i64 0 + ret i32 (i32)* null } define { i64, %S* } @unpackrepack(%S %s) { Index: llvm/test/Bitcode/compatibility-6.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-6.0.ll +++ llvm/test/Bitcode/compatibility-6.0.ll @@ -254,24 +254,24 @@ ; * @ ; IFunc -- Linkage -@ifunc.external = external ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.external = ifunc void (), i8* ()* @ifunc_resolver -@ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver -@ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver +@ifunc.external = external ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.external = ifunc void (), void ()* ()* @ifunc_resolver +@ifunc.private = private ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.private = private ifunc void (), void ()* ()* @ifunc_resolver +@ifunc.internal = internal ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.internal = internal ifunc void (), void ()* ()* @ifunc_resolver ; IFunc -- Visibility -@ifunc.default = default ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.default = ifunc void (), i8* ()* @ifunc_resolver -@ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver -@ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver - -define i8* @ifunc_resolver() { +@ifunc.default = default ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.default = ifunc void (), void ()* ()* @ifunc_resolver +@ifunc.hidden = hidden ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.hidden = hidden ifunc void (), void ()* ()* @ifunc_resolver +@ifunc.protected = protected ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.protected = protected ifunc void (), void ()* ()* @ifunc_resolver + +define void ()* @ifunc_resolver() { entry: - ret i8* null + ret void ()* null } ;; Functions Index: llvm/test/Bitcode/compatibility.ll =================================================================== --- llvm/test/Bitcode/compatibility.ll +++ llvm/test/Bitcode/compatibility.ll @@ -264,28 +264,28 @@ ; * @ ; IFunc -- Linkage -@ifunc.external = external ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.external = ifunc void (), i8* ()* @ifunc_resolver -@ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver -@ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver +@ifunc.external = external ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.external = ifunc void (), void ()* ()* @ifunc_resolver +@ifunc.private = private ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.private = private ifunc void (), void ()* ()* @ifunc_resolver +@ifunc.internal = internal ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.internal = internal ifunc void (), void ()* ()* @ifunc_resolver ; IFunc -- Visibility -@ifunc.default = default ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.default = ifunc void (), i8* ()* @ifunc_resolver -@ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver -@ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver -; CHECK: @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver +@ifunc.default = default ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.default = ifunc void (), void ()* ()* @ifunc_resolver +@ifunc.hidden = hidden ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.hidden = hidden ifunc void (), void ()* ()* @ifunc_resolver +@ifunc.protected = protected ifunc void (), void ()* ()* @ifunc_resolver +; CHECK: @ifunc.protected = protected ifunc void (), void ()* ()* @ifunc_resolver ; IFunc -- partition -; CHECK: @ifunc.partition = ifunc void (), i8* ()* @ifunc_resolver, partition "part" -@ifunc.partition = ifunc void (), i8* ()* @ifunc_resolver, partition "part" +; CHECK: @ifunc.partition = ifunc void (), void ()* ()* @ifunc_resolver, partition "part" +@ifunc.partition = ifunc void (), void ()* ()* @ifunc_resolver, partition "part" -define i8* @ifunc_resolver() { +define void ()* @ifunc_resolver() { entry: - ret i8* null + ret void ()* null } ;; Functions Index: llvm/test/Bitcode/dso_local_equivalent.ll =================================================================== --- llvm/test/Bitcode/dso_local_equivalent.ll +++ llvm/test/Bitcode/dso_local_equivalent.ll @@ -65,12 +65,12 @@ ret void } -@ifunc_func = ifunc void (), i64 ()* @resolver -@dso_local_ifunc_func = dso_local ifunc void (), i64 ()* @resolver +@ifunc_func = ifunc void (), void ()* ()* @resolver +@dso_local_ifunc_func = dso_local ifunc void (), void ()* ()* @resolver -define internal i64 @resolver() { +define internal void ()* @resolver() { entry: - ret i64 0 + ret void ()* null } define void @call_ifunc_func() { Index: llvm/test/Bitcode/dso_location.ll =================================================================== --- llvm/test/Bitcode/dso_location.ll +++ llvm/test/Bitcode/dso_location.ll @@ -27,8 +27,8 @@ @preemptable_alias = dso_preemptable alias i32, i32* @hidden_local_global ; CHECK-DAG: @preemptable_alias = alias i32, i32* @hidden_local_global -@preemptable_ifunc = dso_preemptable ifunc void (), i8* ()* @ifunc_resolver -; CHECK-DAG: @preemptable_ifunc = ifunc void (), i8* ()* @ifunc_resolver +@preemptable_ifunc = dso_preemptable ifunc void (), void ()* ()* @ifunc_resolver +; CHECK-DAG: @preemptable_ifunc = ifunc void (), void ()* ()* @ifunc_resolver declare dso_local default void @default_local() ; CHECK: declare dso_local void @default_local() @@ -41,7 +41,7 @@ ret void } -define i8* @ifunc_resolver() { +define void ()* @ifunc_resolver() { entry: - ret i8* null + ret void ()* null } Index: llvm/test/CodeGen/X86/addrsig.ll =================================================================== --- llvm/test/CodeGen/X86/addrsig.ll +++ llvm/test/CodeGen/X86/addrsig.ll @@ -6,9 +6,9 @@ ; CHECK: .addrsig ; CHECK: .addrsig_sym f1 -define void @f1() { - %f1 = bitcast void()* @f1 to i8* - %f2 = bitcast void()* @f2 to i8* +define void()* @f1() { + %f1 = bitcast void()* ()* @f1 to i8* + %f2 = bitcast void()* ()* @f2 to i8* %f3 = bitcast void()* @f3 to i8* %g1 = bitcast i32* @g1 to i8* %g2 = bitcast i32* @g2 to i8* @@ -34,7 +34,7 @@ declare void @metadata_f2() ; CHECK-NOT: .addrsig_sym f2 -define internal void @f2() local_unnamed_addr { +define internal void()* @f2() local_unnamed_addr { unreachable } @@ -63,9 +63,9 @@ @a2 = internal local_unnamed_addr alias i32, i32* @g2 ; CHECK: .addrsig_sym i1 -@i1 = ifunc void(), void()* @f1 +@i1 = ifunc void(), void()* ()* @f1 ; CHECK-NOT: .addrsig_sym i2 -@i2 = internal local_unnamed_addr ifunc void(), void()* @f2 +@i2 = internal local_unnamed_addr ifunc void(), void()* ()* @f2 declare void @llvm.dbg.value(metadata, metadata, metadata) Index: llvm/test/CodeGen/X86/dso_local_equivalent.ll =================================================================== --- llvm/test/CodeGen/X86/dso_local_equivalent.ll +++ llvm/test/CodeGen/X86/dso_local_equivalent.ll @@ -74,12 +74,12 @@ ret void } -@ifunc_func = ifunc void (), i64 ()* @resolver -@dso_local_ifunc_func = dso_local ifunc void (), i64 ()* @resolver +@ifunc_func = ifunc void (), void ()* ()* @resolver +@dso_local_ifunc_func = dso_local ifunc void (), void ()* ()* @resolver -define internal i64 @resolver() { +define internal void ()* @resolver() { entry: - ret i64 0 + ret void ()* null } ; If an ifunc is not dso_local already, then we should still emit a stub for it Index: llvm/test/CodeGen/X86/ifunc-asm.ll =================================================================== --- llvm/test/CodeGen/X86/ifunc-asm.ll +++ llvm/test/CodeGen/X86/ifunc-asm.ll @@ -2,13 +2,13 @@ target triple = "x86_64-unknown-linux-gnu" -define internal i64 @foo_ifunc() { +define internal i32 (i32)* @foo_ifunc() { entry: - ret i64 0 + ret i32 (i32)* null } ; CHECK: .type foo_ifunc,@function ; CHECK-NEXT: foo_ifunc: -@foo = ifunc i32 (i32), i64 ()* @foo_ifunc +@foo = ifunc i32 (i32), i32 (i32)* ()* @foo_ifunc ; CHECK: .type foo,@gnu_indirect_function ; CHECK-NEXT: .set foo, foo_ifunc Index: llvm/test/CodeGen/X86/partition.ll =================================================================== --- llvm/test/CodeGen/X86/partition.ll +++ llvm/test/CodeGen/X86/partition.ll @@ -17,7 +17,7 @@ ; CHECK-NEXT: .zero 1 ; CHECK-NEXT: .quad i1 -define void @f1() partition "part1" { +define void ()* @f1() partition "part1" { unreachable } @@ -30,4 +30,4 @@ @g1 = global i32 0, partition "part4" @a1 = alias i32, i32* @g1, partition "part5" -@i1 = ifunc void(), void()* @f1, partition "part6" +@i1 = ifunc void(), void()* ()* @f1, partition "part6" Index: llvm/test/LTO/Resolution/X86/Inputs/ifunc2.ll =================================================================== --- llvm/test/LTO/Resolution/X86/Inputs/ifunc2.ll +++ llvm/test/LTO/Resolution/X86/Inputs/ifunc2.ll @@ -1,6 +1,6 @@ target datalayout = "e-p:64:64" target triple = "x86_64-unknown-linux-gnu" -define i32 @foo_resolver() { - ret i32 2 +define i32 ()* @foo_resolver() { + ret i32 ()* inttoptr (i32 2 to i32 ()*) } Index: llvm/test/LTO/Resolution/X86/ifunc.ll =================================================================== --- llvm/test/LTO/Resolution/X86/ifunc.ll +++ llvm/test/LTO/Resolution/X86/ifunc.ll @@ -9,12 +9,12 @@ 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_resolver +@foo = ifunc i32 (i32), i32 (i32)* ()* @foo_resolver @strlen = ifunc i64 (i8*), bitcast (i64 (i8*)* ()* @strlen_resolver to i64 (i8*)*) -define internal i64 @foo_resolver() { +define internal i32 (i32)* @foo_resolver() { entry: - ret i64 0 + ret i32 (i32)* null } define internal i64 (i8*)* @strlen_resolver() { Index: llvm/test/LTO/Resolution/X86/ifunc2.ll =================================================================== --- llvm/test/LTO/Resolution/X86/ifunc2.ll +++ llvm/test/LTO/Resolution/X86/ifunc2.ll @@ -6,14 +6,14 @@ target datalayout = "e-p:64:64" target triple = "x86_64-unknown-linux-gnu" -; CHECK: @foo = ifunc i32 (), i32 ()* @foo_resolver.2 -@foo = ifunc i32 (), i32 ()* @foo_resolver +; CHECK: @foo = ifunc i32 (), i32 ()* ()* @foo_resolver.2 +@foo = ifunc i32 (), i32 ()* ()* @foo_resolver -; CHECK: define internal i32 @foo_resolver.2() { -; CHECK-NEXT: ret i32 1 -define weak i32 @foo_resolver() { - ret i32 1 +; CHECK: define internal i32 ()* @foo_resolver.2() { +; CHECK-NEXT: ret i32 ()* inttoptr (i32 1 to i32 ()*) +define weak i32 ()* @foo_resolver() { + ret i32 ()* inttoptr (i32 1 to i32 ()*) } -; CHECK: define i32 @foo_resolver() { -; CHECK-NEXT: ret i32 2 +; CHECK: define i32 ()* @foo_resolver() { +; CHECK-NEXT: ret i32 ()* inttoptr (i32 2 to i32 ()*) Index: llvm/test/Object/X86/nm-ir.ll =================================================================== --- llvm/test/Object/X86/nm-ir.ll +++ llvm/test/Object/X86/nm-ir.ll @@ -32,12 +32,12 @@ @a1 = alias i32, i32* @g1 @a2 = internal alias i32, i32* @g1 -define void @f1() { +define void ()* @f1() { call void @f5() - ret void + ret void ()* null } -@ifunc_f1 = ifunc void (), void ()* @f1 +@ifunc_f1 = ifunc void (), void ()* ()* @f1 define internal void @f2() { ret void Index: llvm/test/ThinLTO/X86/empty-module.ll =================================================================== --- llvm/test/ThinLTO/X86/empty-module.ll +++ llvm/test/ThinLTO/X86/empty-module.ll @@ -10,9 +10,9 @@ 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), i32 (i32)* ()* @foo_ifunc -define internal i64 @foo_ifunc() { +define internal i32 (i32)* @foo_ifunc() { entry: - ret i64 0 + ret i32 (i32)* null } Index: llvm/test/Transforms/GlobalDCE/global-ifunc.ll =================================================================== --- llvm/test/Transforms/GlobalDCE/global-ifunc.ll +++ llvm/test/Transforms/GlobalDCE/global-ifunc.ll @@ -2,12 +2,12 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -@if = ifunc void (), void ()* @fn +@if = ifunc void (), void ()* ()* @fn -define internal void @fn() { +define internal void ()* @fn() { entry: - ret void + ret void ()* null } -; CHECK-DAG: @if = ifunc void (), void ()* @fn -; CHECK-DAG: define internal void @fn( +; CHECK-DAG: @if = ifunc void (), void ()* ()* @fn +; CHECK-DAG: define internal void ()* @fn(