| // 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* @"$S{{[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* @"$S{{[a-zA-Z0-9_]+}}Ma"() |
| // CHECK-NEXT: [[O:%[0-9]+]] = call noalias %swift.refcounted* @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* @"$S{{[a-zA-Z0-9_]+}}CMa"() |
| // CHECK-NEXT: [[O:%[0-9]+]] = call noalias %swift.refcounted* @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* @"$S{{[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_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* @"$S{{[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_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_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_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 |
| } |
| |