mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
258 lines
11 KiB
Plaintext
258 lines
11 KiB
Plaintext
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -stack-promotion-limit 48 -Onone -emit-ir %s | %FileCheck %s
|
|
//
|
|
// REQUIRES: CPU=x86_64
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
// sizeof(TestClass) = 16 bytes header + 1 byte = 17 bytes
|
|
class TestClass {
|
|
@sil_stored var a : Int8
|
|
init()
|
|
}
|
|
|
|
sil_vtable TestClass {}
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @alloc_on_stack
|
|
// CHECK: %reference.raw = alloca i8, i32 28, align 8
|
|
// CHECK-NEXT: [[M:%[0-9]+]] = call %swift.type* @_T0{{[a-zA-Z0-9_]+}}Ma()
|
|
// CHECK-NEXT: [[O:%[0-9]+]] = bitcast i8* %reference.raw to %swift.refcounted*
|
|
// CHECK-NEXT: %reference.new = call %swift.refcounted* @swift_initStackObject(%swift.type* [[M]], %swift.refcounted* [[O]])
|
|
// CHECK-NEXT: [[R:%[0-9]+]] = bitcast %swift.refcounted* %reference.new to %[[C:.*TestClass.*]]*
|
|
// CHECK-NEXT: [[O2:%[0-9]+]] = bitcast %[[C]]* [[R]] to i8*
|
|
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[O2]])
|
|
// 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_ref [stack] %o1 : $TestClass
|
|
%r = tuple()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} {{.*}}* @alloc_on_heap
|
|
// CHECK: [[M:%[0-9]+]] = call %swift.type* @_T0{{[a-zA-Z0-9_]+}}Ma()
|
|
// CHECK-NEXT: [[O:%[0-9]+]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* [[M]], i64 28, i64 7)
|
|
// CHECK-NEXT: [[O2:%[0-9]+]] = bitcast %swift.refcounted* [[O]] to %[[C:.*TestClass.*]]*
|
|
// CHECK-NEXT: ret %[[C]]* [[O2]]
|
|
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{{( protected)?}} {{.*}}* @alloc_3_on_heap
|
|
// CHECK: [[M:%[0-9]+]] = call %swift.type* @_T0{{[a-zA-Z0-9_]+}}CMa()
|
|
// CHECK-NEXT: [[O:%[0-9]+]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* [[M]], i64 40, i64 7)
|
|
// CHECK-NEXT: [[O2:%[0-9]+]] = bitcast %swift.refcounted* [[O]] to %[[C:.*TestClass.*]]*
|
|
// CHECK-NEXT: ret %[[C]]* [[O2]]
|
|
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{{( protected)?}} {{.*}}* @alloc_non_const_count
|
|
// CHECK: [[M:%[0-9]+]] = call %swift.type* @_T0{{[a-zA-Z0-9_]+}}Ma()
|
|
// 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 %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* [[M]], i64 [[A]], i64 7)
|
|
// CHECK-NEXT: [[O2:%[0-9]+]] = bitcast %swift.refcounted* [[O]] to %[[C:.*TestClass.*]]*
|
|
// CHECK-NEXT: ret %[[C]]* [[O2]]
|
|
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{{( protected)?}} {{.*}}* @alloc_2_non_const_count
|
|
// CHECK: [[M:%[0-9]+]] = call %swift.type* @_T0{{[a-zA-Z0-9_]+}}Ma()
|
|
// 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 %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* [[M]], i64 [[S6]], i64 7)
|
|
// CHECK-NEXT: [[O2:%[0-9]+]] = bitcast %swift.refcounted* [[O]] to %[[C:.*TestClass.*]]*
|
|
// CHECK-NEXT: ret %[[C]]* [[O2]]
|
|
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{{( protected)?}} {{.*}}* @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: call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* %{{[0-9]+}}, i64 [[S5]], i64 7)
|
|
// CHECK: ret
|
|
sil @alloc_generic : $@convention(thin) <T> (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{{( protected)?}} {{.*}}* @alloc_dynamic
|
|
// CHECK: [[BYTE_PTR:%[0-9]+]] = bitcast %swift.type* %0 to i8*
|
|
// CHECK-NEXT: [[SIZE_ADDR:%[0-9]+]] = getelementptr inbounds i8, i8* [[BYTE_PTR]], i32 48
|
|
// CHECK-NEXT: [[INT_PTR:%[0-9]+]] = bitcast i8* [[SIZE_ADDR]] to i32*
|
|
// CHECK-NEXT: [[SIZE:%[0-9]+]] = load i32, i32* [[INT_PTR]]
|
|
// CHECK-NEXT: [[SIZE64:%[0-9]+]] = zext i32 [[SIZE]] to i64
|
|
// CHECK: [[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: [[O:%[0-9]+]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* %0, i64 [[TOTAL_SIZE]], i64 {{.*}})
|
|
// CHECK-NEXT: [[O2:%[0-9]+]] = bitcast %swift.refcounted* [[O]] to %{{.*TestClassC}}*
|
|
// CHECK-NEXT: ret %{{.*TestClassC}}* [[O2]]
|
|
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{{( protected)?}} swiftcc i8* @project_tail_byte
|
|
// CHECK: getelementptr inbounds i8, i8* %{{[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{{( protected)?}} swiftcc void @project_tail_int
|
|
// CHECK: [[S:%[0-9]+]] = getelementptr inbounds i8, i8* %{{[0-9]+}}, i64 20
|
|
// CHECK: bitcast i8* [[S]] to %Ts5Int32V*
|
|
// 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{{( protected)?}} swiftcc i8* @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: [[S4:%[0-9]+]] = bitcast %{{.*}}* %0 to i8*
|
|
// CHECK-NEXT: [[S5:%[0-9]+]] = getelementptr inbounds i8, i8* [[S4]], i64 [[S3]]
|
|
// CHECK-NEXT: %tailaddr = bitcast i8* [[S5]] to %swift.opaque*
|
|
// CHECK: ret
|
|
sil @project_tail_generic : $@convention(thin) <T> (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<T> {
|
|
var t: T
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc i8* @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: [[S4:%[0-9]+]] = bitcast %{{.*}}* %0 to i8*
|
|
// CHECK-NEXT: [[S5:%[0-9]+]] = getelementptr inbounds i8, i8* [[S4]], i64 [[S3]]
|
|
// CHECK-NEXT: %tailaddr = bitcast i8* [[S5]] to %{{.*}}Str
|
|
// CHECK: ret
|
|
sil @project_tail_generic_struct : $@convention(thin) <T> (TestClass, @thick T.Type) -> Builtin.RawPointer {
|
|
bb0(%0 : $TestClass, %1 : $@thick T.Type):
|
|
%a = ref_tail_addr %0 : $TestClass, $Str<T>
|
|
%p = address_to_pointer %a : $*Str<T> to $Builtin.RawPointer
|
|
return %p : $Builtin.RawPointer
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @project_tail_index_byte_to_int
|
|
// CHECK: [[S1:%[0-9]+]] = bitcast i8* %0 to %Ts4Int8V*
|
|
// CHECK-NEXT: [[S2:%[0-9]+]] = getelementptr inbounds %Ts4Int8V, %Ts4Int8V* [[S1]], i64 2
|
|
// CHECK-NEXT: [[S3:%[0-9]+]] = ptrtoint %Ts4Int8V* [[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 %Ts4Int8V*
|
|
// CHECK-NEXT: [[S7:%[0-9]+]] = bitcast %Ts4Int8V* [[S6]] to %Ts5Int32V*
|
|
// 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{{( protected)?}} swiftcc i8* @project_tail_index_generic_struct
|
|
// CHECK: call %swift.type* @{{.*Str.*}}(%swift.type* %T)
|
|
// CHECK: load
|
|
// CHECK: and
|
|
// CHECK: xor
|
|
// CHECK: and
|
|
// CHECK: ret
|
|
sil @project_tail_index_generic_struct : $@convention(thin) <T> (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<T>
|
|
%p = address_to_pointer %a2 : $*Str<T> to $Builtin.RawPointer
|
|
return %p : $Builtin.RawPointer
|
|
}
|
|
|
|
// sizeof(EmptyClass) = 16 bytes
|
|
class EmptyClass {
|
|
}
|
|
|
|
sil_vtable EmptyClass {}
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc i8 @test_align_1_int8
|
|
// CHECK: load i8, i8* %{{.*}}, 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{{( protected)?}} swiftcc i8 @test_align_2_int8
|
|
// CHECK: load i8, i8* %{{.*}}, 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{{( protected)?}} swiftcc i32 @test_align_int32
|
|
// CHECK: load i32, i32* %{{.*}}, 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
|
|
}
|
|
|