Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -887,6 +887,10 @@ // Check that the immediate resolver operand (prior to any bitcasts) has the // correct type. const Type *ResolverTy = GI.getResolver()->getType(); + + Check(isa(Resolver->getFunctionType()->getReturnType()), + "IFunc resolver must return a pointer", &GI); + const Type *ResolverFuncTy = GlobalIFunc::getResolverFunctionType(GI.getValueType()); Check(ResolverTy == ResolverFuncTy->getPointerTo(GI.getAddressSpace()), Index: llvm/test/Assembler/opaque-ptr-struct-types.ll =================================================================== --- llvm/test/Assembler/opaque-ptr-struct-types.ll +++ llvm/test/Assembler/opaque-ptr-struct-types.ll @@ -20,7 +20,7 @@ @g = external global %T1 -@g.ifunc = ifunc %T8 (), ptr @f +@g.ifunc = ifunc %T8 (), ptr @f.resolver define %T2 @f(ptr %p) { alloca %T3 @@ -30,4 +30,12 @@ unreachable } +define %T2* @f.resolver(ptr %p) { + alloca %T3 + getelementptr %T4, ptr %p, i64 1 + call void @f(ptr sret(%T5) %p) + store ptr getelementptr (%T6, ptr @g, i64 1), ptr %p + unreachable +} + declare void @f2(ptr sret(%T7)) Index: llvm/test/Other/force-opaque-ptrs.ll =================================================================== --- llvm/test/Other/force-opaque-ptrs.ll +++ llvm/test/Other/force-opaque-ptrs.ll @@ -20,8 +20,15 @@ ; CHECK: @ga2 = alias i19, ptr @g2 @ga2 = alias i19, i19* bitcast (i18* @g2 to i19*) -; CHECK: @gi = ifunc i20 (), ptr @f -@gi = ifunc i20 (), i20 ()* ()* bitcast (void (i32*)* @f to i20 ()* ()*) +; CHECK: @gi = ifunc i20 (), ptr @resolver +@gi = ifunc i20 (), i20 ()* ()* bitcast (i32* ()* @resolver to i20 ()* ()*) + + +define i32* @resolver() { + %load = load i32, i32* @g.fwd + %ptr = inttoptr i32 %load to i32* + ret i32* %ptr +} define void @f(i32* %p) { ; CHECK-LABEL: define {{[^@]+}}@f Index: llvm/test/Verifier/ifunc.ll =================================================================== --- llvm/test/Verifier/ifunc.ll +++ llvm/test/Verifier/ifunc.ll @@ -27,3 +27,11 @@ @inval_resolver_type = ifunc i32 (), void ()* ()* @resolver ; CHECK: IFunc resolver has incorrect type ; CHECK-NEXT: @inval_resolver_type + +@ifunc_nonpointer_return_type = ifunc i32 (), i32 ()* @resolver_returns_nonpointer +; CHECK: IFunc resolver must return a pointer +; CHECK-NEXT: i32 ()* @ifunc_nonpointer_return_type + +define i32 @resolver_returns_nonpointer() { + ret i32 0 +}