// RUN: %target-swift-frontend -enable-objc-interop -stack-promotion-limit 48 -Onone -emit-ir %s | %FileCheck --check-prefixes=CHECK,CHECK-objc %s -DINT=i%target-ptrsize // RUN: %target-swift-frontend -disable-objc-interop -stack-promotion-limit 48 -Onone -emit-ir %s | %FileCheck --check-prefixes=CHECK,CHECK-native %s -DINT=i%target-ptrsize // // REQUIRES: CPU=x86_64 sil_stage canonical import Builtin import Swift // sizeof(TestClass) = 16 bytes header + 1 byte = 17 bytes class TestClass { @_hasStorage var a : Int8 init() } sil_vtable TestClass {} // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @alloc_on_stack // CHECK: %reference.raw = alloca i8, i32 28, align 8 // CHECK-NEXT: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s{{[a-zA-Z0-9_]+}}Ma"([[INT]] 0) // CHECK-NEXT: [[M:%[0-9]+]] = extractvalue %swift.metadata_response [[TMP]], 0 // CHECK-NEXT: %reference.new = call ptr @swift_initStackObject(ptr [[M]], ptr %reference.raw) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr %reference.new) // CHECK-NEXT: ret void sil @alloc_on_stack : $@convention(thin) () -> () { bb0: %c = integer_literal $Builtin.Word, 2 // size = 17 + 3(padding) + 2 * 4 = 28 %o1 = alloc_ref [stack] [tail_elems $Int32 * %c : $Builtin.Word] $TestClass dealloc_stack_ref %o1 : $TestClass %r = tuple() return %r : $() } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @alloc_on_heap // CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s{{[a-zA-Z0-9_]+}}Ma"([[INT]] 0) // CHECK: [[M:%[0-9]+]] = extractvalue %swift.metadata_response [[TMP]], 0 // CHECK-NEXT: [[O:%[0-9]+]] = call noalias ptr @swift_allocObject(ptr [[M]], i64 28, i64 7) // CHECK-NEXT: ret ptr [[O]] sil @alloc_on_heap : $@convention(thin) () -> @owned TestClass { bb0: %c = integer_literal $Builtin.Word, 2 // size = 17 + 3(padding) + 2 * 4 = 28 %o1 = alloc_ref [tail_elems $Int32 * %c : $Builtin.Word] $TestClass return %o1 : $TestClass } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @alloc_3_on_heap // CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s{{[a-zA-Z0-9_]+}}CMa"([[INT]] 0) // CHECK: [[M:%[0-9]+]] = extractvalue %swift.metadata_response [[TMP]], 0 // CHECK-NEXT: [[O:%[0-9]+]] = call noalias ptr @swift_allocObject(ptr [[M]], i64 40, i64 7) // CHECK-NEXT: ret ptr [[O]] sil @alloc_3_on_heap : $@convention(thin) () -> @owned TestClass { bb0: %c1 = integer_literal $Builtin.Word, 2 // size = 17 + 2 = 19 %c2 = integer_literal $Builtin.Word, 5 // size = 19 + 1(padding) + 5 * 2 = 30 %c3 = integer_literal $Builtin.Word, 1 // size = 30 + 2(padding) + 8 = 40 %o1 = alloc_ref [tail_elems $Int8 * %c1 : $Builtin.Word] [tail_elems $Int16 * %c2 : $Builtin.Word] [tail_elems $Int64 * %c3 : $Builtin.Word] $TestClass return %o1 : $TestClass } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @alloc_non_const_count // CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s{{[a-zA-Z0-9_]+}}Ma"([[INT]] 0) // CHECK: [[M:%[0-9]+]] = extractvalue %swift.metadata_response [[TMP]], 0 // CHECK-NEXT: [[S:%[0-9]+]] = mul i64 4, %0 // CHECK-NEXT: [[A:%[0-9]+]] = add i64 20, [[S]] // CHECK-NEXT: [[O:%[0-9]+]] = call noalias ptr @swift_allocObject(ptr [[M]], i64 [[A]], i64 7) // CHECK-NEXT: ret ptr [[O]] sil @alloc_non_const_count : $@convention(thin) (Builtin.Word) -> @owned TestClass { bb0(%c : $Builtin.Word): %o1 = alloc_ref [tail_elems $Int32 * %c : $Builtin.Word] $TestClass return %o1 : $TestClass } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @alloc_2_non_const_count // CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s{{[a-zA-Z0-9_]+}}Ma"([[INT]] 0) // CHECK: [[M:%[0-9]+]] = extractvalue %swift.metadata_response [[TMP]], 0 // CHECK-NEXT: [[S1:%[0-9]+]] = mul i64 1, %0 // CHECK-NEXT: [[S2:%[0-9]+]] = add i64 17, [[S1]] // CHECK-NEXT: [[S3:%[0-9]+]] = add i64 [[S2]], 3 // CHECK-NEXT: [[S4:%[0-9]+]] = and i64 [[S3]], -4 // CHECK-NEXT: [[S5:%[0-9]+]] = mul i64 4, %1 // CHECK-NEXT: [[S6:%[0-9]+]] = add i64 [[S4]], [[S5]] // CHECK-NEXT: [[O:%[0-9]+]] = call noalias ptr @swift_allocObject(ptr [[M]], i64 [[S6]], i64 7) // CHECK-NEXT: ret ptr [[O]] sil @alloc_2_non_const_count : $@convention(thin) (Builtin.Word, Builtin.Word) -> @owned TestClass { bb0(%c1 : $Builtin.Word, %c2 : $Builtin.Word): %o1 = alloc_ref [tail_elems $Int8 * %c1 : $Builtin.Word] [tail_elems $Int32 * %c2 : $Builtin.Word] $TestClass return %o1 : $TestClass } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @alloc_generic // CHECK: [[S1:%[0-9]+]] = add i64 17, %flags.alignmentMask // CHECK-NEXT: [[S2:%[0-9]+]] = xor i64 %flags.alignmentMask, -1 // CHECK-NEXT: [[S3:%[0-9]+]] = and i64 [[S1]], [[S2]] // CHECK-NEXT: [[S4:%[0-9]+]] = mul i64 %stride, %0 // CHECK-NEXT: [[S5:%[0-9]+]] = add i64 [[S3]], [[S4]] // CHECK-NEXT: [[A:%[0-9]+]] = or i64 7, %flags.alignmentMask // CHECK: call noalias ptr @swift_allocObject(ptr %{{[0-9]+}}, i64 [[S5]], i64 [[A]]) // CHECK: ret sil @alloc_generic : $@convention(thin) (Builtin.Word, @thick T.Type) -> @owned TestClass { bb0(%0 : $Builtin.Word, %1 : $@thick T.Type): %4 = metatype $@thick TestClass.Type %5 = alloc_ref [tail_elems $T * %0 : $Builtin.Word] $TestClass return %5 : $TestClass } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @alloc_dynamic // CHECK-objc: [[SIZE_ADDR:%[0-9]+]] = getelementptr inbounds i8, ptr %0, i32 48 // CHECK-native: [[SIZE_ADDR:%[0-9]+]] = getelementptr inbounds i8, ptr %0, i32 24 // CHECK-NEXT: [[SIZE:%[0-9]+]] = load i32, ptr [[SIZE_ADDR]] // CHECK-NEXT: [[SIZE64:%[0-9]+]] = zext i32 [[SIZE]] to i64 // CHECK-objc-NEXT: [[ALIGN_ADDR:%[0-9]+]] = getelementptr inbounds i8, ptr %0, i32 52 // CHECK-native-NEXT: [[ALIGN_ADDR:%[0-9]+]] = getelementptr inbounds i8, ptr %0, i32 28 // CHECK-NEXT: [[ALIGN:%[0-9]+]] = load i16, ptr [[ALIGN_ADDR]] // CHECK-NEXT: [[ALIGN64:%[0-9]+]] = zext i16 [[ALIGN]] to i64 // CHECK-NEXT: [[ALIGN_TMP:%[0-9]+]] = add i64 [[SIZE64]], 3 // CHECK-NEXT: [[ALIGNED:%[0-9]+]] = and i64 [[ALIGN_TMP]], -4 // CHECK-NEXT: [[TOTAL_SIZE:%[0-9]+]] = add i64 [[ALIGNED]], 12 // CHECK-NEXT: [[TOTAL_ALIGN:%[0-9]+]] = or i64 [[ALIGN64]], 3 // CHECK-NEXT: [[O:%[0-9]+]] = call noalias ptr @swift_allocObject(ptr %0, i64 [[TOTAL_SIZE]], i64 [[TOTAL_ALIGN]]) // CHECK-NEXT: ret ptr [[O]] sil @alloc_dynamic : $@convention(thin) (@thick TestClass.Type) -> @owned TestClass { bb0(%0 : $@thick TestClass.Type): %c = integer_literal $Builtin.Word, 3 %o = alloc_ref_dynamic [tail_elems $Int32 * %c : $Builtin.Word] %0 : $@thick TestClass.Type, $TestClass return %o : $TestClass } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @project_tail_byte // CHECK: getelementptr inbounds i8, ptr %{{[0-9]+}}, i64 17 // CHECK: ret sil @project_tail_byte : $@convention(thin) (TestClass) -> Builtin.RawPointer { bb0(%0 : $TestClass): %a = ref_tail_addr %0 : $TestClass, $Int8 %p = address_to_pointer %a : $*Int8 to $Builtin.RawPointer return %p : $Builtin.RawPointer } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @project_tail_int // CHECK: [[S:%[0-9]+]] = getelementptr inbounds i8, ptr %{{[0-9]+}}, i64 20 // CHECK: ret sil @project_tail_int : $@convention(thin) (TestClass, Int32) -> () { bb0(%0 : $TestClass, %1 : $Int32): %a = ref_tail_addr %0 : $TestClass, $Int32 store %1 to %a : $*Int32 %r = tuple () return %r : $() } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @project_tail_generic // CHECK: [[S1:%[0-9]+]] = add i64 17, %flags.alignmentMask // CHECK-NEXT: [[S2:%[0-9]+]] = xor i64 %flags.alignmentMask, -1 // CHECK-NEXT: [[S3:%[0-9]+]] = and i64 [[S1]], [[S2]] // CHECK-NEXT: [[S5:%[0-9]+]] = getelementptr inbounds i8, ptr %0, i64 [[S3]] // CHECK: ret sil @project_tail_generic : $@convention(thin) (TestClass, @thick T.Type) -> Builtin.RawPointer { bb0(%0 : $TestClass, %1 : $@thick T.Type): %a = ref_tail_addr %0 : $TestClass, $T %p = address_to_pointer %a : $*T to $Builtin.RawPointer return %p : $Builtin.RawPointer } struct Str { var t: T } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @project_tail_generic_struct // CHECK: [[S1:%[0-9]+]] = add i64 17, %flags.alignmentMask // CHECK-NEXT: [[S2:%[0-9]+]] = xor i64 %flags.alignmentMask, -1 // CHECK-NEXT: [[S3:%[0-9]+]] = and i64 [[S1]], [[S2]] // CHECK-NEXT: [[S5:%[0-9]+]] = getelementptr inbounds i8, ptr %0, i64 [[S3]] // CHECK: ret sil @project_tail_generic_struct : $@convention(thin) (TestClass, @thick T.Type) -> Builtin.RawPointer { bb0(%0 : $TestClass, %1 : $@thick T.Type): %a = ref_tail_addr %0 : $TestClass, $Str %p = address_to_pointer %a : $*Str to $Builtin.RawPointer return %p : $Builtin.RawPointer } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @project_tail_index_byte_to_int // CHECK: [[S2:%[0-9]+]] = getelementptr inbounds %Ts4Int8V, ptr %0, i64 2 // CHECK-NEXT: [[S3:%[0-9]+]] = ptrtoint ptr [[S2]] to i64 // CHECK-NEXT: [[S4:%[0-9]+]] = add nuw i64 [[S3]], 3 // CHECK-NEXT: [[S5:%[0-9]+]] = and i64 [[S4]], -4 // CHECK-NEXT: [[S6:%[0-9]+]] = inttoptr i64 [[S5]] to ptr // CHECK: ret sil @project_tail_index_byte_to_int : $@convention(thin) (Builtin.RawPointer, Int32) -> () { bb0(%0 : $Builtin.RawPointer, %1 : $Int32): %a1 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Int8 %c = integer_literal $Builtin.Word, 2 %a2 = tail_addr %a1 : $*Int8, %c : $Builtin.Word, $Int32 store %1 to %a2 : $*Int32 %r = tuple () return %r : $() } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @project_tail_index_generic_struct // CHECK: call swiftcc %swift.metadata_response @{{.*Str.*}}([[INT]] 0, ptr %T) // CHECK: load // CHECK: and // CHECK: xor // CHECK: and // CHECK: ret sil @project_tail_index_generic_struct : $@convention(thin) (Builtin.RawPointer, @thick T.Type) -> Builtin.RawPointer { bb0(%0 : $Builtin.RawPointer, %1 : $@thick T.Type): %a1 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Int8 %c = integer_literal $Builtin.Word, 2 %a2 = tail_addr %a1 : $*Int8, %c : $Builtin.Word, $Str %p = address_to_pointer %a2 : $*Str to $Builtin.RawPointer return %p : $Builtin.RawPointer } // sizeof(EmptyClass) = 16 bytes class EmptyClass { } sil_vtable EmptyClass {} // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc i8 @test_align_1_int8 // CHECK: load i8, ptr %{{.*}}, align 1 // CHECK: ret sil @test_align_1_int8 : $@convention(thin) (EmptyClass) -> Int8 { bb0(%0 : $EmptyClass): %a = ref_tail_addr %0 : $EmptyClass, $Int8 %w = integer_literal $Builtin.Word, 1 %i = index_addr %a : $*Int8, %w : $Builtin.Word %l = load %i : $*Int8 return %l : $Int8 } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc i8 @test_align_2_int8 // CHECK: load i8, ptr %{{.*}}, align 2 // CHECK: ret sil @test_align_2_int8 : $@convention(thin) (EmptyClass) -> Int8 { bb0(%0 : $EmptyClass): %a = ref_tail_addr %0 : $EmptyClass, $Int8 %w = integer_literal $Builtin.Word, 2 %i = index_addr %a : $*Int8, %w : $Builtin.Word %l = load %i : $*Int8 return %l : $Int8 } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc i32 @test_align_int32 // CHECK: load i32, ptr %{{.*}}, align 4 // CHECK: ret sil @test_align_int32 : $@convention(thin) (EmptyClass, Builtin.Word) -> Int32 { bb0(%0 : $EmptyClass, %1 : $Builtin.Word): %a = ref_tail_addr %0 : $EmptyClass, $Int32 %i = index_addr %a : $*Int32, %1 : $Builtin.Word %l = load %i : $*Int32 return %l : $Int32 }