blob: fa2ce0b38aeef7c45f1d34baba63d71fde6a8178 [file] [log] [blame]
// 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: [[VOID_BLOCK_SIGNATURE:@.*]] = private unnamed_addr constant {{.*}} c"v8@?0\00"
// CHECK: [[TRIVIAL_BLOCK_DESCRIPTOR:@.*]] = internal constant { {{.*}} } { i64 0, i64 40, i8* getelementptr inbounds ({{.*}} [[VOID_BLOCK_SIGNATURE]], i64 0, i64 0) }
// CHECK: @block_copy_helper.ptrauth = private constant { i8*, i32, i64, i64 } { i8* bitcast ({{.*}}* @block_copy_helper to i8*), i32 0, i64 ptrtoint ({{.*}} getelementptr inbounds ({{.*}} [[NONTRIVIAL_BLOCK_DESCRIPTOR:@.*]], i32 0, i32 2) to i64), i64 0 }, section "llvm.ptrauth"
// CHECK: @block_destroy_helper.ptrauth = private constant { i8*, i32, i64, i64 } { i8* bitcast ({{.*}}* @block_destroy_helper to i8*), i32 0, i64 ptrtoint ({{.*}} getelementptr inbounds ({{.*}} [[NONTRIVIAL_BLOCK_DESCRIPTOR:@.*]], i32 0, i32 3) to i64), i64 0 }, section "llvm.ptrauth"
// CHECK: [[NONTRIVIAL_BLOCK_DESCRIPTOR]] = internal constant { {{.*}} } { i64 0, i64 40, void ({ %objc_block, %swift.refcounted* }*, {{.*}} bitcast ({{.*}} @block_copy_helper.ptrauth to {{.*}}), {{.*}} bitcast ({{.*}} @block_destroy_helper.ptrauth to {{.*}}), i8* getelementptr inbounds ({{.*}} [[VOID_BLOCK_SIGNATURE]], i64 0, i64 0) }
sil @init_header_trivial : $@convention(thin) (@inout_aliasable @block_storage Builtin.RawPointer) -> @convention(block) () -> () {
entry(%0 : $*@block_storage Builtin.RawPointer):
%i = function_ref @invoke_trivial : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer) -> ()
%b = init_block_storage_header %0 : $*@block_storage Builtin.RawPointer, invoke %i : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer) -> (), type $@convention(block) () -> ()
return %b : $@convention(block) () -> ()
}
// CHECK-LABEL: define swiftcc %objc_block* @init_header_trivial({ %objc_block, i8* }*
// CHECK: [[HEADER:%.*]] = getelementptr inbounds { %objc_block, i8* }, { %objc_block, i8* }* %0, i32 0, i32 0
// CHECK: [[SLOT:%.*]] = getelementptr inbounds %objc_block, %objc_block* [[HEADER]], i32 0, i32 3
// CHECK: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64
// CHECK: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.sign.i64(i64 ptrtoint (void (void (...)*)* @invoke_trivial to i64), i32 0, i64 [[T0]])
// CHECK: [[T0:%.*]] = inttoptr i64 [[SIGNED]] to i8*
// CHECK: store i8* [[T0]], i8** [[SLOT]],
// CHECK: [[SLOT:%.*]] = getelementptr inbounds %objc_block, %objc_block* [[HEADER]], i32 0, i32 4
// CHECK: store i8* bitcast ({{.*}} [[TRIVIAL_BLOCK_DESCRIPTOR]] to i8*), i8** [[SLOT]]
sil @invoke_trivial : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer) -> () {
entry(%0 : $*@block_storage Builtin.RawPointer):
%c = project_block_storage %0 : $*@block_storage Builtin.RawPointer
return undef : $()
}
sil @init_header_nontrivial : $@convention(thin) (@inout_aliasable @block_storage Builtin.NativeObject) -> @convention(block) () -> () {
entry(%0 : $*@block_storage Builtin.NativeObject):
%i = function_ref @invoke_nontrivial : $@convention(c) (@inout_aliasable @block_storage Builtin.NativeObject) -> ()
%b = init_block_storage_header %0 : $*@block_storage Builtin.NativeObject, invoke %i : $@convention(c) (@inout_aliasable @block_storage Builtin.NativeObject) -> (), type $@convention(block) () -> ()
return %b : $@convention(block) () -> ()
}
// CHECK-LABEL: define swiftcc %objc_block* @init_header_nontrivial({ %objc_block, %swift.refcounted* }*
// CHECK: [[HEADER:%.*]] = getelementptr inbounds { %objc_block, %swift.refcounted* }, { %objc_block, %swift.refcounted* }* %0, i32 0, i32 0
// CHECK: [[SLOT:%.*]] = getelementptr inbounds %objc_block, %objc_block* [[HEADER]], i32 0, i32 3
// CHECK: [[T0:%.*]] = ptrtoint i8** [[SLOT]] to i64
// CHECK: [[SIGNED:%.*]] = call i64 @llvm.ptrauth.sign.i64(i64 ptrtoint (void (void (...)*)* @invoke_nontrivial to i64), i32 0, i64 [[T0]])
// CHECK: [[T0:%.*]] = inttoptr i64 [[SIGNED]] to i8*
// CHECK: store i8* [[T0]], i8** [[SLOT]],
// CHECK: [[SLOT:%.*]] = getelementptr inbounds %objc_block, %objc_block* [[HEADER]], i32 0, i32 4
// CHECK: store i8* bitcast ({{.*}} [[NONTRIVIAL_BLOCK_DESCRIPTOR]] to i8*), i8** [[SLOT]]
sil @invoke_nontrivial : $@convention(c) (@inout_aliasable @block_storage Builtin.NativeObject) -> () {
entry(%0 : $*@block_storage Builtin.NativeObject):
%c = project_block_storage %0 : $*@block_storage Builtin.NativeObject
return undef : $()
}
sil @invoke_block : $@convention(thin) (@convention(block) () -> ()) -> () {
entry(%0 : $@convention(block) () -> ()):
apply %0() : $@convention(block) () -> ()
return undef : $()
}
// CHECK-LABEL: define swiftcc void @invoke_block(%objc_block* %0)
// CHECK: [[SLOT:%.*]] = getelementptr inbounds %objc_block, %objc_block* %0, i32 0, i32 3
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[SLOT]], align
// CHECK-NEXT: [[INVOKE:%.*]] = bitcast i8* [[T0]] to void (%objc_block*)*
// CHECK-NEXT: [[DISC:%.*]] = ptrtoint i8** [[SLOT]] to i64
// CHECK-NEXT: call void [[INVOKE]](%objc_block* %0) [ "ptrauth"(i32 0, i64 [[DISC]]) ]