Files
swift-mirror/test/IRGen/objc_block_storage.sil
Anthony Latsis 55e5618eab [test] Match nocapture to succeed both on main and rebranch
Both the syntax and relative order of the LLVM `nocapture` parameter
attribute changed upstream in 29441e4f5fa5f5c7709f7cf180815ba97f611297.
To reduce conflicts with rebranch, adjust FileCheck patterns to expect
both syntaxes and orders anywhere the presence of the attribute is not
critical to the test. These changes are temporary and will be cleaned
up once rebranch is merged into main.
2025-05-08 23:52:43 +01:00

171 lines
10 KiB
Plaintext

// RUN: %empty-directory(%t)
// RUN: %build-irgen-test-overlays
// RUN: %target-swift-frontend -Xllvm -sil-disable-pass=simplification -gnone -enable-objc-interop -sdk %S/Inputs -I %t %s -emit-ir | %FileCheck %s
// REQUIRES: CPU=x86_64
// REQUIRES: objc_interop
sil_stage canonical
import Builtin
import Swift
import gizmo
// CHECK: [[BLOCK_ISA:@_NSConcreteStackBlock]] = external global {{(dllimport )?}}%objc_class
// CHECK: [[VOID_BLOCK_SIGNATURE:@.*]] = private unnamed_addr constant {{.*}} c"v8@?0\00"
// CHECK: [[TRIVIAL_BLOCK_DESCRIPTOR:@.*]] = internal constant { i64, i64, ptr } {
// CHECK-SAME: i64 0,
// CHECK-SAME: i64 40,
// CHECK-SAME: ptr [[VOID_BLOCK_SIGNATURE]]
// CHECK-SAME: }
// CHECK: [[BLOCK_PARAM_BLOCK_SIGNATURE:@.*]] = private unnamed_addr constant {{.*}} c"v16@?0@?<q@?q>8\00"
// CHECK: [[BLOCK_PARAM_BLOCK_DESCRIPTOR:@.*]] = internal constant { {{.*}} } {
// CHECK: i64 0,
// CHECK: i64 40,
// CHECK: ptr [[BLOCK_PARAM_BLOCK_SIGNATURE]]
// CHECK: }
// CHECK: [[NONTRIVIAL_BLOCK_DESCRIPTOR:@.*]] = internal constant { {{.*}} } {
// CHECK: i64 0,
// CHECK: i64 40,
// CHECK: ptr [[NONTRIVIAL_BLOCK_COPY:@[A-Za-z0-9_]+]],
// CHECK: ptr [[NONTRIVIAL_BLOCK_DISPOSE:@[A-Za-z0-9_]+]],
// CHECK: ptr [[VOID_BLOCK_SIGNATURE]]
// CHECK: }
// CHECK: [[NSRECT_BLOCK_SIGNATURE:@.*]] = private unnamed_addr constant {{.*}} c"{NSRect={NSPoint=dd}{NSSize=dd}}8@?0\00"
// CHECK: [[STRET_BLOCK_DESCRIPTOR:@.*]] = internal constant { {{.*}} } {
// CHECK: i64 0,
// CHECK: i64 40,
// CHECK: ptr [[NSRECT_BLOCK_SIGNATURE]]
// CHECK: }
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @project_block_storage(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
// CHECK-NEXT: entry:
// CHECK-NEXT: %1 = getelementptr inbounds{{.*}} { %objc_block, ptr }, ptr %0, i32 0, i32 1
// CHECK-NEXT: %2 = load ptr, ptr %1, align 8
// CHECK-NEXT: ret ptr %2
// CHECK-NEXT: }
sil @project_block_storage : $@convention(thin) (@inout_aliasable @block_storage Builtin.RawPointer) -> Builtin.RawPointer {
entry(%0 : $*@block_storage Builtin.RawPointer):
%c = project_block_storage %0 : $*@block_storage Builtin.RawPointer
%p = load %c : $*Builtin.RawPointer
return %p : $Builtin.RawPointer
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc fp128 @overaligned_project_block_storage(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
// CHECK-NEXT: entry:
// CHECK-NEXT: %1 = getelementptr inbounds{{.*}} { %objc_block, fp128 }, ptr %0, i32 0, i32 1
// CHECK-NEXT: %2 = load fp128, ptr %1, align 16
// CHECK-NEXT: ret fp128 %2
// CHECK-NEXT: }
sil @overaligned_project_block_storage : $@convention(thin) (@inout_aliasable @block_storage Builtin.FPIEEE128) -> Builtin.FPIEEE128 {
entry(%0 : $*@block_storage Builtin.FPIEEE128):
%c = project_block_storage %0 : $*@block_storage Builtin.FPIEEE128
%p = load %c : $*Builtin.FPIEEE128
return %p : $Builtin.FPIEEE128
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @init_block_header_trivial(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
// CHECK: [[HEADER:%.*]] = getelementptr inbounds{{.*}} { %objc_block, ptr }, ptr %0, i32 0, i32 0
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 0
// CHECK: store ptr [[BLOCK_ISA]], ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 1
// -- 0x4000_0000 -- HAS_SIGNATURE
// CHECK: store i32 1073741824, ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 2
// CHECK: store i32 0, ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 3
// CHECK: store ptr @invoke_trivial, ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 4
// CHECK: store ptr [[TRIVIAL_BLOCK_DESCRIPTOR]], ptr [[T0]]
// CHECK: ret ptr %0
sil @init_block_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{{( dllexport)?}}{{( protected)?}} void @invoke_trivial(ptr %0) {{.*}} {
// CHECK: %1 = getelementptr inbounds{{.*}} { %objc_block, ptr }, ptr %0, i32 0, i32 1
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_block_header_trivial_block_param : $@convention(thin) (@inout_aliasable @block_storage Builtin.RawPointer) -> @convention(block) (@convention(block) (Int) -> Int) -> () {
entry(%0 : $*@block_storage Builtin.RawPointer):
%i = function_ref @invoke_trivial_block_param : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer, @convention(block) (Int) -> Int) -> ()
%b = init_block_storage_header %0 : $*@block_storage Builtin.RawPointer, invoke %i : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer, @convention(block) (Int) -> Int) -> (), type $@convention(block) (@convention(block) (Int) -> Int) -> ()
return %b : $@convention(block) (@convention(block) (Int) -> Int) -> ()
}
sil @invoke_trivial_block_param : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer, @convention(block) (Int) -> Int) -> ()
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} i64 @invoke_trivial_with_arg(ptr %0, i64 %1) {{.*}} {
// CHECK: ret i64 %1
sil @invoke_trivial_with_arg : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer, Int) -> Int {
entry(%0 : $*@block_storage Builtin.RawPointer, %1 : $Int):
return %1 : $Int
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @init_block_header_nontrivial(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
// CHECK: [[HEADER:%.*]] = getelementptr inbounds
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 0
// CHECK: store ptr [[BLOCK_ISA]], ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 1
// -- 0x4200_0000 -- HAS_SIGNATURE, HAS_COPY_DISPOSE
// CHECK: store i32 1107296256, ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 2
// CHECK: store i32 0, ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 3
// CHECK: store ptr @invoke_nontrivial, ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 4
// CHECK: store ptr [[NONTRIVIAL_BLOCK_DESCRIPTOR]], ptr [[T0]]
sil @init_block_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: define internal void [[NONTRIVIAL_BLOCK_COPY]]
// CHECK-NEXT: entry:
// CHECK-NEXT: %2 = getelementptr inbounds{{.*}} { %objc_block, ptr }, ptr %0, i32 0, i32 1
// CHECK-NEXT: %3 = getelementptr inbounds{{.*}} { %objc_block, ptr }, ptr %1, i32 0, i32 1
// CHECK-NEXT: %4 = load ptr, ptr %3, align 8
// CHECK-NEXT: call ptr @swift_retain(ptr returned %4) {{#[0-9]+}}
// CHECK-NEXT: store ptr %4, ptr %2, align 8
// CHECK-NEXT: ret void
// CHECK: define internal void [[NONTRIVIAL_BLOCK_DISPOSE]]
// CHECK-NEXT: entry:
// CHECK-NEXT: %1 = getelementptr inbounds{{.*}} { %objc_block, ptr }, ptr %0, i32 0, i32 1
// CHECK-NEXT: %toDestroy = load ptr, ptr %1, align 8
// CHECK-NEXT: call void @swift_release(ptr %toDestroy) {{#[0-9]+}}
// CHECK-NEXT: ret void
sil public_external @invoke_nontrivial : $@convention(c) (@inout_aliasable @block_storage Builtin.NativeObject) -> ()
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @init_block_header_stret(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
// CHECK: [[HEADER:%.*]] = getelementptr inbounds
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 0
// CHECK: store ptr [[BLOCK_ISA]], ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 1
// -- 0x6000_0000 -- HAS_STRET, HAS_SIGNATURE
// CHECK: store i32 1610612736, ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 2
// CHECK: store i32 0, ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 3
// CHECK: store ptr @invoke_stret, ptr [[T0]]
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %objc_block, ptr [[HEADER]], i32 0, i32 4
// CHECK: store ptr [[STRET_BLOCK_DESCRIPTOR]], ptr [[T0]]
sil @init_block_header_stret : $@convention(thin) (@inout_aliasable @block_storage Builtin.RawPointer) -> @convention(block) () -> NSRect {
entry(%0 : $*@block_storage Builtin.RawPointer):
%i = function_ref @invoke_stret : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer) -> NSRect
%b = init_block_storage_header %0 : $*@block_storage Builtin.RawPointer, invoke %i : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer) -> NSRect, type $@convention(block) () -> NSRect
return %b : $@convention(block) () -> NSRect
}
sil public_external @invoke_stret : $@convention(c) (@inout_aliasable @block_storage Builtin.RawPointer) -> NSRect