Files
swift-mirror/test/IRGen/generic_structs_future.sil
Nate Chandler 4dfaa77935 [IRGen] Pack extra data pattern structs.
Previously, the extra data pattern structs for struct and enums were not
packed.

On 32 bit, this resulted in an extra data pattern struct which was 4
bytes too large whenever there was an odd number of fields in the
struct.  The result was writing past the end of the allocated struct.
That bug only caused occasional crashes because (1) for the most part
there was additional space beyond the end of the allocation intended for
the struct metadata in the bump allocator and (2) while half of the
trailing flags field would be overwritten, because those bits of the
trailing flags being nonzero did not have an observable effect since
those bits of the trailing flags field are not yet used.

Here, the structs are marked packed, resulting in the appropriate size
for the extra data pattern structs on 32 bit platforms.

rdar://problem/68997282
2020-11-19 00:59:53 -08:00

260 lines
12 KiB
Plaintext

// RUN: %empty-directory(%t)
// RUN: %{python} %utils/chex.py < %s > %t/generic_structs_future.sil
// RUN: %target-swift-frontend -disable-type-layout -prespecialize-generic-metadata -target %module-target-future %t/generic_structs_future.sil -emit-ir | %FileCheck %t/generic_structs_future.sil
// REQUIRES: VENDOR=apple || OS=linux-gnu
// REQUIRES: CPU=x86_64
import Builtin
// -- Generic structs with fixed layout should have no completion function
// and emit the field offset vector as part of the pattern.
// CHECK: [[PATTERN:@.*]] = internal constant <{ i32, i32, i32, [4 x i8], i64 }> <{ i32 0, i32 1, i32 8, [4 x i8] zeroinitializer, i64 0 }>, align 8
// CHECK-LABEL: @"$s22generic_structs_future18FixedLayoutGenericVMP" = internal constant <{ {{.*}} }> <{
// -- instantiation function
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**, i8*)* @"$s22generic_structs_future18FixedLayoutGenericVMi"
// -- completion function
// CHECK-SAME: i32 0,
// -- pattern flags
// CHECK-SAME: <i32 0x4000_0003>,
// -- vwtable pointer
// CHECK-SAME: @"$s22generic_structs_future18FixedLayoutGenericVWV"
// -- extra data pattern
// CHECK-SAME: <{ i32, i32, i32, [4 x i8], i64 }>* [[PATTERN]]
// CHECK-SAME: i16 1,
// CHECK-SAME: i16 3 }>
// -- Generic structs with dynamic layout contain the vwtable pattern as part
// of the metadata pattern, and no independent vwtable symbol
// CHECK: @"$s22generic_structs_future13SingleDynamicVWV" = internal constant
// CHECK-SAME: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @"$s22generic_structs_future13SingleDynamicVwCP" to i8*),
// -- ...
// -- placeholder for size, stride, flags
// CHECK-SAME: i64 0,
// CHECK-SAME: i64 0,
// CHECK-SAME: i32 4194304,
// CHECK-SAME: i32 0 }
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
// CHECK: [[SINGLEDYNAMIC_NAME:@.*]] = private constant [14 x i8] c"SingleDynamic\00"
// CHECK: @"$s22generic_structs_future13SingleDynamicVMn" = hidden constant
// -- flags: struct, unique, generic
// CHECK-SAME: <i32 0x0000_00D1>
// -- name
// CHECK-SAME: [14 x i8]* [[SINGLEDYNAMIC_NAME]]
// -- field count
// CHECK-SAME: i32 1,
// -- field offset vector offset
// CHECK-SAME: i32 3,
// -- generic instantiation info
// CHECK-SAME: [{{[0-9]+}} x i8*]* @"$s22generic_structs_future13SingleDynamicVMI"
// CHECK-SAME: @"$s22generic_structs_future13SingleDynamicVMP"
// -- generic params, requirements, key args, extra args
// CHECK-SAME: i16 1, i16 0, i16 1, i16 0
// -- generic parameters
// CHECK-SAME: <i8 0x80>
// CHECK-SAME: }>
// CHECK: @"$s22generic_structs_future13SingleDynamicVMP" = internal constant <{ {{.*}} }> <{
// -- instantiation function
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**, i8*)* @"$s22generic_structs_future13SingleDynamicVMi"
// -- vwtable pointer
// CHECK-SAME: @"$s22generic_structs_future13SingleDynamicVWV"
// -- Nominal type descriptor for generic struct with protocol requirements
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
// CHECK: [[DYNAMICWITHREQUIREMENTS_NAME:@.*]] = private constant [24 x i8] c"DynamicWithRequirements\00"
// CHECK: @"$s22generic_structs_future23DynamicWithRequirementsVMn" = hidden constant <{ {{.*}} i32 }> <{
// -- flags: struct, unique, generic
// CHECK-SAME: <i32 0x0000_00D1>
// -- name
// CHECK-SAME: [24 x i8]* [[DYNAMICWITHREQUIREMENTS_NAME]]
// -- field count
// CHECK-SAME: i32 2,
// -- field offset vector offset
// CHECK-SAME: i32 6,
// -- generic params, requirements, key args, extra args
// CHECK-SAME: i16 2, i16 2, i16 4, i16 0,
// -- generic parameters
// CHECK-SAME: <i8 0x80>, <i8 0x80>,
// -- generic requirement
// -- protocol requirement with key arg
// CHECK-SAME: i32 128
// -- param 0
// CHECK-SAME: i32 0
// -- protocol Req1
// CHECK-SAME: @"$s22generic_structs_future4Req1Mp"
// -- protocol requirement with key arg
// CHECK-SAME: i32 128
// -- param 1
// CHECK-SAME: i32 2
// -- protocol Req2
// CHECK-SAME: @"$s22generic_structs_future4Req2Mp"
// CHECK-SAME: }>
// CHECK: @"$s22generic_structs_future23DynamicWithRequirementsVMP" = internal constant <{ {{.*}} }> <{
// -- Fixed-layout struct metadata contains fixed field offsets
// CHECK: @"$s22generic_structs_future6IntishVMf" = internal constant <{ {{.*}} i32, [4 x i8], i64 }> <{
// CHECK-SAME: i32 0
// CHECK-SAME: }>
// CHECK: @"$s22generic_structs_future7CharethVMf" = internal constant <{ {{.*}} i32, [4 x i8], i64 }> <{
// CHECK-SAME: i32 0
// CHECK-SAME: }>
// CHECK: @"$s22generic_structs_future8StringlyVMf" = internal constant <{ {{.*}} i32, i32, i32, [4 x i8], i64 }> <{
// CHECK-SAME: i32 0, i32 8, i32 16, [4 x i8] zeroinitializer
// CHECK-SAME: }>
struct FixedLayoutGeneric<T> {
var x: Byteful
var y: Byteful
var z: Intish
}
struct SingleDynamic<T> {
var x : T
}
protocol Req1 { associatedtype Assoc1 }
protocol Req2 {}
struct DynamicWithRequirements<T: Req1, U: Req2> {
var x : T
var y : U
}
struct Intish { var value : Builtin.Int64 }
struct Chareth { var value : Builtin.Int21 }
struct Byteful { var value : Builtin.Int8 }
struct Stringly {
var owner : Builtin.NativeObject
var base : Builtin.RawPointer
var size : Builtin.Int64
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i32 } @concrete_instances(i64 %0, i32 %1) {{.*}} {
// CHECK: entry:
// CHECK: %2 = trunc i32 %1 to i21
// CHECK: %3 = zext i21 %2 to i32
// CHECK: %4 = insertvalue { i64, i32 } undef, i64 %0, 0
// CHECK: %5 = insertvalue { i64, i32 } %4, i32 %3, 1
// CHECK: ret { i64, i32 } %5
// CHECK: }
sil @concrete_instances : $(SingleDynamic<Intish>, SingleDynamic<Chareth>) -> (Intish, Chareth) {
entry(%0 : $SingleDynamic<Intish>, %1 : $SingleDynamic<Chareth>):
%a = struct_extract %0 : $SingleDynamic<Intish>, #SingleDynamic.x
%b = struct_extract %1 : $SingleDynamic<Chareth>, #SingleDynamic.x
%c = tuple (%a : $Intish, %b : $Chareth)
return %c : $(Intish, Chareth)
}
struct ComplexDynamic<U, V> {
var a, a2 : Byteful
var b : U
var c : SingleDynamic<V>
var d : Chareth
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @explode_complex_dynamic
sil @explode_complex_dynamic : $<A, B> (@in ComplexDynamic<A, B>, @inout Byteful, @inout A, @inout B, @inout Chareth) -> () {
entry(%0 : $*ComplexDynamic<A, B>, %1 : $*Byteful, %2 : $*A, %3 : $*B, %4 : $*Chareth):
%a = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.a2
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i32*
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i32, i32* [[METADATA]], i64 10
// CHECK: [[FIELD_OFFSET:%.*]] = load i32, i32* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T22generic_structs_future14ComplexDynamicV* %0 to i8*
// CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i32 [[FIELD_OFFSET]]
// CHECK: bitcast i8* [[BYTE_OFFSET]] to %swift.opaque*
%b = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.b
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i32*
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i32, i32* [[METADATA]], i64 11
// CHECK: [[FIELD_OFFSET:%.*]] = load i32, i32* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T22generic_structs_future14ComplexDynamicV* %0 to i8*
// CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i32 [[FIELD_OFFSET]]
// CHECK: bitcast i8* [[BYTE_OFFSET]] to %T22generic_structs_future13SingleDynamicV
%5 = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.c
%c = struct_element_addr %5 : $*SingleDynamic<B>, #SingleDynamic.x
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i32*
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i32, i32* [[METADATA]], i64 12
// CHECK: [[FIELD_OFFSET:%.*]] = load i32, i32* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T22generic_structs_future14ComplexDynamicV* %0 to i8*
// CHECK: [[BYTE_OFFSET:%.*]] = getelementptr inbounds i8, i8* [[BYTES]], i32 [[FIELD_OFFSET]]
// CHECK: bitcast i8* [[BYTE_OFFSET]] to %T22generic_structs_future7CharethV
%d = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.d
copy_addr %a to %1 : $*Byteful
copy_addr %b to %2 : $*A
copy_addr %c to %3 : $*B
copy_addr %d to %4 : $*Chareth
%v = tuple ()
return %v : $()
}
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$s22generic_structs_future13SingleDynamicVMi"(%swift.type_descriptor* %0, i8** %1, i8* %2)
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
// CHECK: %T = load %swift.type*, %swift.type** [[T0]], align 8
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_descriptor* %0, i8** %1, i8* %2, i64 24)
// CHECK-NEXT: ret %swift.type* [[METADATA]]
// CHECK: }
// CHECK-LABEL: define{{( protected)?}} internal swiftcc %swift.metadata_response @"$s22generic_structs_future13SingleDynamicVMr"
// CHECK-SAME: (%swift.type* [[METADATA:%.*]], i8* %0, i8** %1) {{.*}} {
// Lay out fields.
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i32*
// CHECK: [[T1:%.*]] = getelementptr inbounds i32, i32* [[T0]], i64 6
// CHECK: [[T2:%.*]] = getelementptr inbounds i8**, i8*** [[TYPES:%.*]], i32 0
// CHECK: call void @swift_initStructMetadata(%swift.type* [[METADATA]], i64 0, i64 1, i8*** [[TYPES]], i32* [[T1]])
// CHECK: ret %swift.metadata_response
// CHECK: }
// Check that we directly delegate buffer witnesses to a single dynamic field:
// initializeBufferWithCopyOfBuffer
// CHECK-LABEL: define internal %swift.opaque* @"$s22generic_structs_future13SingleDynamicVwCP"([24 x i8]* noalias %dest, [24 x i8]* noalias %src, %swift.type* %"SingleDynamic<T>") {{.*}} {
// CHECK: %T = load %swift.type*,
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8***
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1
// CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]]
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** %T.valueWitnesses,
// CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)*
// CHECK-NEXT: [[T0:%.*]] = call %swift.opaque* [[FN]]([24 x i8]* noalias %dest, [24 x i8]* noalias %src, %swift.type* %T)
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.opaque* [[T0]] to {{.*}}
// CHECK-NEXT: [[T2:%.*]] = bitcast {{.*}} [[T1]] to %swift.opaque*
// CHECK-NEXT: ret %swift.opaque* [[T2]]
protocol HasAssociatedType {
associatedtype Assoc
}
protocol ParentHasAssociatedType : HasAssociatedType {
associatedtype Assoc : HasAssociatedType
}
struct GenericLayoutWithAssocType<T: ParentHasAssociatedType> {
var x: T.Assoc
var y: T.Assoc.Assoc
}
// CHECK-LABEL: define internal %swift.type* @"$s22generic_structs_future26GenericLayoutWithAssocTypeVMi"(
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
// CHECK: %T = load %swift.type*, %swift.type** [[T0]], align 8
// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1
// CHECK: [[T2:%.*]] = bitcast %swift.type** [[T1]] to i8***
// CHECK: %T.ParentHasAssociatedType = load i8**, i8*** [[T2]],
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata
// CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$s22generic_structs_future26GenericLayoutWithAssocTypeVMr"(
// CHECK: [[T0_GEP:%.*]] = getelementptr inbounds i8*, i8** %T.ParentHasAssociatedType, i32 1
// CHECK: [[T0:%.*]] = load i8*, i8** [[T0_GEP]]
// CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to i8**
// CHECK: [[T4:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, i8** %T.HasAssociatedType, %swift.type* %T, %swift.protocol_requirement* @"$s22generic_structs_future17HasAssociatedTypeTL", %swift.protocol_requirement* @"$s5Assoc22generic_structs_future17HasAssociatedTypePTl")
// CHECK: %T.Assoc = extractvalue %swift.metadata_response [[T4]], 0
// CHECK: %T.Assoc.HasAssociatedType = call swiftcc i8** @swift_getAssociatedConformanceWitness(i8** %T.ParentHasAssociatedType, %swift.type* %T, %swift.type* %T.Assoc,
// CHECK: [[T2:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, i8** %T.Assoc.HasAssociatedType, %swift.type* %T.Assoc, %swift.protocol_requirement* @"$s22generic_structs_future17HasAssociatedTypeTL", %swift.protocol_requirement* @"$s5Assoc22generic_structs_future17HasAssociatedTypePTl")
// CHECK: %T.Assoc.Assoc = extractvalue %swift.metadata_response [[T2]], 0