Files
swift-mirror/test/IRGen/struct_resilience.swift
Joe Groff 8cb1175e49 IRGen: Emit public definitions with protected visibility on ELF.
This prevents the linker from trying to emit relative relocations to locally-defined public symbols into dynamic libraries, which gives ld.so heartache.
2016-02-08 13:09:27 -08:00

185 lines
9.3 KiB
Swift

// RUN: %target-swift-frontend -I %S/../Inputs -enable-source-import -emit-ir -enable-resilience %s | FileCheck %s
// RUN: %target-swift-frontend -I %S/../Inputs -enable-source-import -emit-ir -enable-resilience -O %s
import resilient_struct
import resilient_enum
// CHECK: %Si = type <{ [[INT:i32|i64]] }>
// CHECK-LABEL: @_TMPV17struct_resilience26StructWithResilientStorage = {{(protected )?}}global
// Resilient structs from outside our resilience domain are manipulated via
// value witnesses
// CHECK-LABEL: define{{( protected)?}} void @_TF17struct_resilience26functionWithResilientTypesFTV16resilient_struct4Size1fFS1_S1__S1_(%swift.opaque* noalias nocapture sret, %swift.opaque* noalias nocapture, i8*, %swift.refcounted*)
public func functionWithResilientTypes(s: Size, f: Size -> Size) -> Size {
// CHECK: [[RESULT:%.*]] = alloca [[BUFFER_TYPE:\[.* x i8\]]]
// CHECK: [[METADATA:%.*]] = call %swift.type* @_TMaV16resilient_struct4Size()
// CHECK: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT]] -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[WITNESS_PTR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 5
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_PTR]]
// CHECK: [[initializeBufferWithCopy:%.*]] = bitcast i8* [[WITNESS]]
// CHECK: [[BUFFER:%.*]] = call %swift.opaque* [[initializeBufferWithCopy]]([[BUFFER_TYPE]]* [[RESULT]], %swift.opaque* %1, %swift.type* [[METADATA]])
// CHECK: [[FN:%.*]] = bitcast i8* %2 to void (%swift.opaque*, %swift.opaque*, %swift.refcounted*)*
// CHECK: call void [[FN]](%swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture [[BUFFER]], %swift.refcounted* %3)
// CHECK: [[WITNESS_PTR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 3
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_PTR]]
// CHECK: [[deallocateBuffer:%.*]] = bitcast i8* [[WITNESS]]
// CHECK: call void [[deallocateBuffer]]([[BUFFER_TYPE]]* [[RESULT]], %swift.type* [[METADATA]])
// CHECK: [[WITNESS_PTR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 4
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_PTR]]
// CHECK: [[destroy:%.*]] = bitcast i8* [[WITNESS]] to void (%swift.opaque*, %swift.type*)*
// CHECK: call void [[destroy]](%swift.opaque* %1, %swift.type* [[METADATA]])
// CHECK: ret void
return f(s)
}
// CHECK-LABEL: declare %swift.type* @_TMaV16resilient_struct4Size()
// Rectangle has fixed layout inside its resilience domain, and dynamic
// layout on the outside.
//
// Make sure we use a type metadata accessor function, and load indirect
// field offsets from it.
// CHECK-LABEL: define{{( protected)?}} void @_TF17struct_resilience26functionWithResilientTypesFV16resilient_struct9RectangleT_(%V16resilient_struct9Rectangle* noalias nocapture)
public func functionWithResilientTypes(r: Rectangle) {
// CHECK: [[METADATA:%.*]] = call %swift.type* @_TMaV16resilient_struct9Rectangle()
// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], i32 3
// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %V16resilient_struct9Rectangle* %0 to i8*
// CHECK-NEXT: [[FIELD_ADDR:%.*]] = getelementptr inbounds i8, i8* [[STRUCT_ADDR]], [[INT]] [[FIELD_OFFSET]]
// CHECK-NEXT: [[FIELD_PTR:%.*]] = bitcast i8* [[FIELD_ADDR]] to %Si*
// CHECK-NEXT: [[FIELD_PAYLOAD_PTR:%.*]] = getelementptr inbounds %Si, %Si* [[FIELD_PTR]], i32 0, i32 0
// CHECK-NEXT: [[FIELD_PAYLOAD:%.*]] = load [[INT]], [[INT]]* [[FIELD_PAYLOAD_PTR]]
_ = r.color
// CHECK: ret void
}
// Resilient structs from inside our resilience domain are manipulated
// directly.
public struct MySize {
public let w: Int
public let h: Int
}
// CHECK-LABEL: define{{( protected)?}} void @_TF17struct_resilience28functionWithMyResilientTypesFTVS_6MySize1fFS0_S0__S0_(%V17struct_resilience6MySize* {{.*}}, %V17struct_resilience6MySize* {{.*}}, i8*, %swift.refcounted*)
public func functionWithMyResilientTypes(s: MySize, f: MySize -> MySize) -> MySize {
// CHECK: [[TEMP:%.*]] = alloca %V17struct_resilience6MySize
// CHECK: bitcast
// CHECK: llvm.lifetime.start
// CHECK: [[COPY:%.*]] = bitcast %V17struct_resilience6MySize* %4 to i8*
// CHECK: [[ARG:%.*]] = bitcast %V17struct_resilience6MySize* %1 to i8*
// CHECK: call void @llvm.memcpy{{.*}}(i8* [[COPY]], i8* [[ARG]], {{i32 8|i64 16}}, i32 {{.*}}, i1 false)
// CHECK: [[FN:%.*]] = bitcast i8* %2
// CHECK: call void [[FN]](%V17struct_resilience6MySize* {{.*}} %0, {{.*}} [[TEMP]], %swift.refcounted* %3)
// CHECK: ret void
return f(s)
}
// Structs with resilient storage from a different resilience domain require
// runtime metadata instantiation, just like generics.
public struct StructWithResilientStorage {
public let s: Size
public let ss: (Size, Size)
public let n: Int
public let i: ResilientInt
}
// Make sure we call a function to access metadata of structs with
// resilient layout, and go through the field offset vector in the
// metadata when accessing stored properties.
// CHECK-LABEL: define{{( protected)?}} {{i32|i64}} @_TFV17struct_resilience26StructWithResilientStorageg1nSi(%V17struct_resilience26StructWithResilientStorage* {{.*}})
// CHECK: [[METADATA:%.*]] = call %swift.type* @_TMaV17struct_resilience26StructWithResilientStorage()
// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], i32 3
// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %V17struct_resilience26StructWithResilientStorage* %0 to i8*
// CHECK-NEXT: [[FIELD_ADDR:%.*]] = getelementptr inbounds i8, i8* [[STRUCT_ADDR]], [[INT]] [[FIELD_OFFSET]]
// CHECK-NEXT: [[FIELD_PTR:%.*]] = bitcast i8* [[FIELD_ADDR]] to %Si*
// CHECK-NEXT: [[FIELD_PAYLOAD_PTR:%.*]] = getelementptr inbounds %Si, %Si* [[FIELD_PTR]], i32 0, i32 0
// CHECK-NEXT: [[FIELD_PAYLOAD:%.*]] = load [[INT]], [[INT]]* [[FIELD_PAYLOAD_PTR]]
// CHECK-NEXT: ret [[INT]] [[FIELD_PAYLOAD]]
// Indirect enums with resilient payloads are still fixed-size.
public struct StructWithIndirectResilientEnum {
public let s: FunnyShape
public let n: Int
}
// CHECK-LABEL: define{{( protected)?}} {{i32|i64}} @_TFV17struct_resilience31StructWithIndirectResilientEnumg1nSi(%V17struct_resilience31StructWithIndirectResilientEnum* {{.*}})
// CHECK: [[FIELD_PTR:%.*]] = getelementptr inbounds %V17struct_resilience31StructWithIndirectResilientEnum, %V17struct_resilience31StructWithIndirectResilientEnum* %0, i32 0, i32 1
// CHECK-NEXT: [[FIELD_PAYLOAD_PTR:%.*]] = getelementptr inbounds %Si, %Si* [[FIELD_PTR]], i32 0, i32 0
// CHECK-NEXT: [[FIELD_PAYLOAD:%.*]] = load [[INT]], [[INT]]* [[FIELD_PAYLOAD_PTR]]
// CHECK-NEXT: ret [[INT]] [[FIELD_PAYLOAD]]
// Public metadata accessor for our resilient struct
// CHECK-LABEL: define{{( protected)?}} %swift.type* @_TMaV17struct_resilience6MySize()
// CHECK: ret %swift.type* bitcast ([[INT]]* getelementptr inbounds {{.*}} @_TMfV17struct_resilience6MySize, i32 0, i32 1) to %swift.type*)
// FIXME: this should modify the template in-place instead of copying it
// CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_StructWithResilientStorage(%swift.type_pattern*, i8**)
// CHECK: [[FIELDS:%.*]] = alloca [4 x i8**]
// CHECK: [[RESULT:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1)
// CHECK: [[RESULT_ADDR:%.*]] = bitcast %swift.type* [[RESULT]] to i8**
// CHECK: [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[RESULT_ADDR]], i32 8
// CHECK: [[VWT_ADDR:%.*]] = bitcast i8** [[VWT]] to i8*
// CHECK: [[RESULT_ADDR2:%.*]] = bitcast %swift.type* %2 to [[INT]]*
// CHECK: [[FIELD_OFFSETS_ADDR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[RESULT_ADDR:%.*]], i32 3
// CHECK: [[FIELDS_ADDR:%.*]] = getelementptr inbounds [4 x i8**], [4 x i8**]* [[FIELDS]], i32 0, i32 0
// public let s: Size
// CHECK: [[FIELD_1:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 0
// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_1]]
// public let ss: (Size, Size)
// CHECK: [[FIELD_2:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 1
// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_2]]
// Fixed-layout aggregate -- we can reference a static value witness table
// public let n: Int
// CHECK: [[FIELD_3:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 2
// CHECK: store i8** getelementptr inbounds (i8*, i8** @_TWVBi{{32|64}}_, i32 {{.*}}), i8*** [[FIELD_3]]
// Resilient aggregate with one field -- make sure we don't look inside it
// public let i: ResilientInt
// CHECK: [[FIELD_4:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 3
// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_4]]
// CHECK: call void @swift_initStructMetadata_UniversalStrategy([[INT]] 4, i8*** [[FIELDS_ADDR]], [[INT]]* [[FIELD_OFFSETS_ADDR]], i8** [[VWT]])
// CHECK: ret %swift.type* [[RESULT]]