// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK // REQUIRES: CPU=arm64e // REQUIRES: OS=ios import Builtin // CHECK: @"$s4test1ACfD.ptrauth" = private constant { ptr, i32, i64, i64 } { ptr @"$s4test1ACfD", i32 0, i64 ptrtoint ({{.*}} @"$s4test1ACMf", i32 0, i32 1) to i64), i64 48063 }, section "llvm.ptrauth", align 8 // CHECK: @A_foo.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @A_foo, i32 0, i64 ptrtoint ({{.*}} getelementptr inbounds ({{.*}} @"$s4test1ACMf", i32 0, i32 {{.*}}) to i64), i64 23008 }, section "llvm.ptrauth", align 8 // CHECK: @"$s4test1BCfD.ptrauth" = private constant { ptr, i32, i64, i64 } { ptr @"$s4test1BCfD", i32 0, i64 ptrtoint ({{.*}} @"$s4test1BCMf", i32 0, i32 1) to i64), i64 48063 }, section "llvm.ptrauth", align 8 // CHECK: @B_foo.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @B_foo, i32 0, i64 ptrtoint ({{.*}} getelementptr inbounds ({{.*}} @"$s4test1BCMf", i32 0, i32 {{.*}}) to i64), i64 23008 }, section "llvm.ptrauth", align 8 // CHECK: @"$s4test1GCMn" = // -1212481520 == 0xb7bb0010. 0xb7bb == 47035. // CHECK-SAME: i32 -1212481520, {{.*}} @G_bar open class A { deinit {} open func foo() } open class B : A { deinit {} override open func foo() } open class G { open func bar() } sil @A_foo : $@convention(method) (@guaranteed A) -> () sil @B_foo : $@convention(method) (@guaranteed B) -> () sil @G_bar : $@convention(method) (@guaranteed G) -> () sil @$s4test1ACfD : $@convention(method) (@owned A) -> () sil @$s4test1BCfD : $@convention(method) (@owned B) -> () sil_vtable A { #A.deinit!deallocator: (A) -> () -> () : @$s4test1ACfD #A.foo: (A) -> () -> () : @A_foo } sil_vtable B { #B.deinit!deallocator: (B) -> () -> () : @$s4test1BCfD #A.foo: (A) -> () -> () : @B_foo [override] } sil_vtable G { #G.bar: @G_bar } sil @test_call_a : $@convention(thin) (@guaranteed A) -> () { bb0(%0 : $A): %1 = class_method %0 : $A, #A.foo : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () %2 = apply %1(%0) : $@convention(method) (@guaranteed A) -> () return %2 : $() } // CHECK-LABEL: define swiftcc void @test_call_a(ptr %0) // CHECK: [[META:%.*]] = load ptr, ptr %0, align // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds ptr, ptr [[META]], i64 {{.*}} // CHECK-NEXT: [[FN:%.*]] = load ptr, ptr [[SLOT]] // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[SLOT]] to i64 // Discriminator value is arbitrary, but must be the same as the next test. // CHECK-NEXT: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 23008) // CHECK-NEXT: call swiftcc void [[FN]](ptr swiftself %0) [ "ptrauth"(i32 0, i64 [[DISCRIMINATOR]]) ] // CHECK-NEXT: ret void sil @test_call_b : $@convention(thin) (@guaranteed B) -> () { bb0(%0 : $B): %1 = class_method %0 : $B, #B.foo : (B) -> () -> (), $@convention(method) (@guaranteed B) -> () %2 = apply %1(%0) : $@convention(method) (@guaranteed B) -> () return %2 : $() } // CHECK-LABEL: define swiftcc void @test_call_b(ptr %0) // CHECK: [[META:%.*]] = load ptr, ptr %0, align // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds ptr, ptr [[META]], i64 {{.*}} // CHECK-NEXT: [[FN:%.*]] = load ptr, ptr [[SLOT]] // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[SLOT]] to i64 // Discriminator value is arbitrary, but must be the same as the previous test. // CHECK-NEXT: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 23008) // CHECK-NEXT: call swiftcc void [[FN]](ptr swiftself %0) [ "ptrauth"(i32 0, i64 [[DISCRIMINATOR]]) ] // CHECK-NEXT: ret void sil @test_call_g : $@convention(thin) (@guaranteed G) -> () { bb0(%0 : $G): %1 = class_method %0 : $G, #G.bar : (G) -> () -> (), $@convention(method) (@guaranteed G) -> () %2 = apply %1(%0) : $@convention(method) (@guaranteed G) -> () return %2 : $() } // CHECK-LABEL: define swiftcc void @test_call_g(ptr %0) // CHECK: load // CHECK: [[META:%.*]] = load ptr, ptr %0, align // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds ptr, ptr [[META]], i64 {{.*}} // CHECK-NEXT: [[FN:%.*]] = load ptr, ptr [[SLOT]] // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[SLOT]] to i64 // Discriminator value is arbitrary, but must be the same as the previous test. // CHECK-NEXT: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 47035) // CHECK-NEXT: call swiftcc void [[FN]](ptr swiftself %0) [ "ptrauth"(i32 0, i64 [[DISCRIMINATOR]]) ] // CHECK-NEXT: ret void