ibookstein updated this revision to Diff 381773.
ibookstein added a comment.

Change BitcodeReader to transparently fix up the type rather than returning an 
error because older formats use wrong type.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D112349/new/

https://reviews.llvm.org/D112349

Files:
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGen/ifunc.c
  clang/test/CodeGen/semantic-interposition.c
  llvm/include/llvm/IR/GlobalIFunc.h
  llvm/lib/Bitcode/Reader/BitcodeReader.cpp
  llvm/lib/IR/Globals.cpp
  llvm/lib/IR/Verifier.cpp
  llvm/test/Assembler/ifunc-asm.ll
  llvm/test/Assembler/ifunc-dsolocal.ll
  llvm/test/Assembler/ifunc-use-list-order.ll
  llvm/test/Bindings/llvm-c/echo.ll
  llvm/test/Bitcode/compatibility-3.9.ll
  llvm/test/Bitcode/compatibility-4.0.ll
  llvm/test/Bitcode/compatibility-5.0.ll
  llvm/test/Bitcode/compatibility-6.0.ll
  llvm/test/Bitcode/compatibility.ll
  llvm/test/Bitcode/dso_local_equivalent.ll
  llvm/test/Bitcode/dso_location.ll
  llvm/test/CodeGen/PowerPC/ifunc.ll
  llvm/test/CodeGen/X86/addrsig.ll
  llvm/test/CodeGen/X86/dso_local_equivalent.ll
  llvm/test/CodeGen/X86/ifunc-asm.ll
  llvm/test/CodeGen/X86/partition.ll
  llvm/test/LTO/Resolution/X86/Inputs/ifunc2.ll
  llvm/test/LTO/Resolution/X86/ifunc.ll
  llvm/test/LTO/Resolution/X86/ifunc2.ll
  llvm/test/Linker/ifunc.ll
  llvm/test/Object/X86/nm-ir.ll
  llvm/test/ThinLTO/X86/empty-module.ll
  llvm/test/Transforms/GlobalDCE/global-ifunc.ll

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(
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/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/Linker/ifunc.ll
===================================================================
--- llvm/test/Linker/ifunc.ll
+++ llvm/test/Linker/ifunc.ll
@@ -3,18 +3,18 @@
 
 ;; Check that ifuncs are linked in properly.
 
-; CHECK-DAG: @foo = ifunc void (), bitcast (void ()* ()* @foo_resolve to void ()*)
+; CHECK-DAG: @foo = ifunc void (), void ()* ()* @foo_resolve
 ; CHECK-DAG: define internal void ()* @foo_resolve() {
 
-; CHECK-DAG: @bar = ifunc void (), bitcast (void ()* ()* @bar_resolve to void ()*)
+; CHECK-DAG: @bar = ifunc void (), void ()* ()* @bar_resolve
 ; CHECK-DAG: define internal void ()* @bar_resolve() {
 
 ;--- a.ll
 declare void @bar()
 
 ;--- b.ll
-@foo = ifunc void (), bitcast (void ()* ()* @foo_resolve to void ()*)
-@bar = ifunc void (), bitcast (void ()* ()* @bar_resolve to void ()*)
+@foo = ifunc void (), void ()* ()* @foo_resolve
+@bar = ifunc void (), void ()* ()* @bar_resolve
 
 define internal void ()* @foo_resolve() {
   ret void ()* null
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/LTO/Resolution/X86/ifunc.ll
===================================================================
--- llvm/test/LTO/Resolution/X86/ifunc.ll
+++ llvm/test/LTO/Resolution/X86/ifunc.ll
@@ -1,23 +1,15 @@
 ; RUN: opt -module-summary -o %t.bc %s
-; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,pl -r %t.bc,strlen,pl -o %t2
+; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,pl -o %t2
 ; RUN: llvm-nm %t2.1 | FileCheck %s
 ; CHECK: i foo
 ; CHECK: t foo_resolver
-; CHECK: i strlen
-; CHECK: t strlen_resolver
 
 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
-@strlen = ifunc i64 (i8*), bitcast (i64 (i8*)* ()* @strlen_resolver to i64 (i8*)*)
+@foo = ifunc i32 (i32), i32 (i32)* ()* @foo_resolver
 
-define internal i64 @foo_resolver() {
+define internal i32 (i32)* @foo_resolver() {
 entry:
-  ret i64 0
-}
-
-define internal i64 (i8*)* @strlen_resolver() {
-entry:
-  ret i64 (i8*)* null
+  ret i32 (i32)* null
 }
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/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/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/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/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/PowerPC/ifunc.ll
===================================================================
--- llvm/test/CodeGen/PowerPC/ifunc.ll
+++ llvm/test/CodeGen/PowerPC/ifunc.ll
@@ -7,10 +7,10 @@
 ; RUN: llc %s -o - -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr10 \
 ; RUN:   -verify-machineinstrs | FileCheck --check-prefix=LEP10 %s
 
-@ifunc1 = dso_local ifunc void(), i8*()* @resolver
-@ifunc2 = ifunc void(), i8*()* @resolver
+@ifunc1 = dso_local ifunc void(), void()* ()* @resolver
+@ifunc2 = ifunc void(), void()* ()* @resolver
 
-define i8* @resolver() { ret i8* null }
+define void()* @resolver() { ret void()* null }
 
 define void @foo() #0 {
   ; REL-LABEL:    foo
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/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/compatibility.ll
===================================================================
--- llvm/test/Bitcode/compatibility.ll
+++ llvm/test/Bitcode/compatibility.ll
@@ -264,28 +264,28 @@
 ;                  <ResolverTy>* @<Resolver>
 
 ; 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/compatibility-6.0.ll
===================================================================
--- llvm/test/Bitcode/compatibility-6.0.ll
+++ llvm/test/Bitcode/compatibility-6.0.ll
@@ -255,19 +255,19 @@
 
 ; IFunc -- Linkage
 @ifunc.external = external ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.external = ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.external = ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.private = private ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.internal = internal ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 
 ; IFunc -- Visibility
 @ifunc.default = default ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.default = ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.default = ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.hidden = hidden ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.protected = protected ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 
 define i8* @ifunc_resolver() {
 entry:
Index: llvm/test/Bitcode/compatibility-5.0.ll
===================================================================
--- llvm/test/Bitcode/compatibility-5.0.ll
+++ llvm/test/Bitcode/compatibility-5.0.ll
@@ -256,19 +256,19 @@
 
 ; IFunc -- Linkage
 @ifunc.external = external ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.external = ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.external = ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.private = private ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.internal = internal ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 
 ; IFunc -- Visibility
 @ifunc.default = default ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.default = ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.default = ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.hidden = hidden ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.protected = protected ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 
 define i8* @ifunc_resolver() {
 entry:
Index: llvm/test/Bitcode/compatibility-4.0.ll
===================================================================
--- llvm/test/Bitcode/compatibility-4.0.ll
+++ llvm/test/Bitcode/compatibility-4.0.ll
@@ -256,19 +256,19 @@
 
 ; IFunc -- Linkage
 @ifunc.external = external ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.external = ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.external = ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.private = private ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.internal = internal ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 
 ; IFunc -- Visibility
 @ifunc.default = default ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.default = ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.default = ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.hidden = hidden ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.protected = protected ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 
 define i8* @ifunc_resolver() {
 entry:
Index: llvm/test/Bitcode/compatibility-3.9.ll
===================================================================
--- llvm/test/Bitcode/compatibility-3.9.ll
+++ llvm/test/Bitcode/compatibility-3.9.ll
@@ -256,19 +256,19 @@
 
 ; IFunc -- Linkage
 @ifunc.external = external ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.external = ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.external = ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.private = private ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.private = private ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.internal = internal ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.internal = internal ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 
 ; IFunc -- Visibility
 @ifunc.default = default ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.default = ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.default = ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.hidden = hidden ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.hidden = hidden ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
-; CHECK: @ifunc.protected = protected ifunc void (), i8* ()* @ifunc_resolver
+; CHECK: @ifunc.protected = protected ifunc void (), bitcast (i8* ()* @ifunc_resolver to void ()* ()*)
 
 define i8* @ifunc_resolver() {
 entry:
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/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/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-asm.ll
===================================================================
--- llvm/test/Assembler/ifunc-asm.ll
+++ llvm/test/Assembler/ifunc-asm.ll
@@ -2,11 +2,20 @@
 
 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() {
+@strlen = ifunc i64 (i8*), bitcast (i64 (i32*)* ()* @mistyped_strlen_resolver to i64 (i8*)* ()*)
+; CHECK: strlen = ifunc i64 (i8*), bitcast (i64 (i32*)* ()* @mistyped_strlen_resolver to i64 (i8*)* ()*)
+
+define internal i32 (i32)* @foo_ifunc() {
+entry:
+  ret i32 (i32)* null
+}
+; CHECK: define internal i32 (i32)* @foo_ifunc()
+
+define internal i64 (i32*)* @mistyped_strlen_resolver() {
 entry:
-  ret i64 0
+  ret i64 (i32*)* null
 }
-; CHECK: define internal i64 @foo_ifunc()
+; CHECK: define internal i64 (i32*)* @mistyped_strlen_resolver()
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<const GlobalAlias *> &Visited,
                            const GlobalAlias &A, const Constant &C);
@@ -821,6 +825,23 @@
   visitGlobalValue(GA);
 }
 
+void Verifier::visitGlobalIFunc(const GlobalIFunc &GI) {
+  // Pierce through ConstantExprs and GlobalAliases and check that the resolver
+  // is a Function definition
+  const Function *Resolver = GI.getResolverFunction();
+  Assert(Resolver, "IFunc must have a Function resolver", &GI);
+  Assert(!Resolver->isDeclarationForLinker(),
+         "IFunc resolver must be a definition", &GI);
+
+  // Check that the immediate resolver operand (prior to any bitcasts) has the
+  // correct type
+  const Type *ResolverTy = GI.getResolver()->getType();
+  const Type *ResolverFuncTy =
+      GlobalIFunc::getResolverFunctionType(GI.getValueType());
+  Assert(ResolverTy == ResolverFuncTy->getPointerTo(),
+         "IFunc resolver has incorrect 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/lib/IR/Globals.cpp
===================================================================
--- llvm/lib/IR/Globals.cpp
+++ llvm/lib/IR/Globals.cpp
@@ -541,5 +541,5 @@
 
 const Function *GlobalIFunc::getResolverFunction() const {
   DenseSet<const GlobalAlias *> Aliases;
-  return cast<Function>(findBaseObject(getResolver(), Aliases));
+  return dyn_cast<Function>(findBaseObject(getResolver(), Aliases));
 }
Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp
===================================================================
--- llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2281,7 +2281,11 @@
           return error("Alias and aliasee types don't match");
         GA->setAliasee(C);
       } else if (auto *GI = dyn_cast<GlobalIFunc>(GV)) {
-        GI->setResolver(C);
+        Type *ResolverFTy =
+            GlobalIFunc::getResolverFunctionType(GI->getValueType());
+        // Transparently fix up the type for compatiblity with older bitcode
+        GI->setResolver(
+            ConstantExpr::getBitCast(C, ResolverFTy->getPointerTo()));
       } else {
         return error("Expected an alias or an ifunc");
       }
Index: llvm/include/llvm/IR/GlobalIFunc.h
===================================================================
--- llvm/include/llvm/IR/GlobalIFunc.h
+++ llvm/include/llvm/IR/GlobalIFunc.h
@@ -80,6 +80,10 @@
         static_cast<const GlobalIFunc *>(this)->getResolverFunction());
   }
 
+  static FunctionType *getResolverFunctionType(Type *IFuncValTy) {
+    return FunctionType::get(IFuncValTy->getPointerTo(), false);
+  }
+
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const Value *V) {
     return V->getValueID() == Value::GlobalIFuncVal;
Index: clang/test/CodeGen/semantic-interposition.c
===================================================================
--- clang/test/CodeGen/semantic-interposition.c
+++ clang/test/CodeGen/semantic-interposition.c
@@ -10,13 +10,13 @@
 
 // CHECK: @var = global i32 0, align 4
 // CHECK: @ext_var = external global i32, align 4
-// CHECK: @ifunc = ifunc i32 (), bitcast (i8* ()* @ifunc_resolver to i32 ()*)
+// CHECK: @ifunc = ifunc i32 (), bitcast (i8* ()* @ifunc_resolver to i32 ()* ()*)
 // CHECK: define dso_local i32 @func()
 // CHECK: declare i32 @ext()
 
 // PREEMPT: @var = global i32 0, align 4
 // PREEMPT: @ext_var = external global i32, align 4
-// PREEMPT: @ifunc = ifunc i32 (), bitcast (i8* ()* @ifunc_resolver to i32 ()*)
+// PREEMPT: @ifunc = ifunc i32 (), bitcast (i8* ()* @ifunc_resolver to i32 ()* ()*)
 // PREEMPT: define i32 @func()
 // PREEMPT: declare i32 @ext()
 
Index: clang/test/CodeGen/ifunc.c
===================================================================
--- clang/test/CodeGen/ifunc.c
+++ clang/test/CodeGen/ifunc.c
@@ -34,8 +34,8 @@
 void* goo_ifunc(void) {
   return 0;
 }
-// CHECK: @foo = ifunc i32 (i32), bitcast (i32 (i32)* ()* @foo_ifunc to i32 (i32)*)
-// CHECK: @goo = ifunc void (), bitcast (i8* ()* @goo_ifunc to void ()*)
+// CHECK: @foo = ifunc i32 (i32), i32 (i32)* ()* @foo_ifunc
+// CHECK: @goo = ifunc void (), bitcast (i8* ()* @goo_ifunc to void ()* ()*)
 
 // CHECK: call i32 @foo(i32
 // CHECK: call void @goo()
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -5013,8 +5013,9 @@
   Aliases.push_back(GD);
 
   llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
+  llvm::Type *ResolverTy = llvm::GlobalIFunc::getResolverFunctionType(DeclTy);
   llvm::Constant *Resolver =
-      GetOrCreateLLVMFunction(IFA->getResolver(), DeclTy, GD,
+      GetOrCreateLLVMFunction(IFA->getResolver(), ResolverTy, GD,
                               /*ForVTable=*/false);
   llvm::GlobalIFunc *GIF =
       llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to