// RUN: %empty-directory(%t) // RUN: %target-build-swift %S/Inputs/struct_with_fields.swift -parse-as-library -wmo -enable-library-evolution -module-name=Test -emit-module -emit-module-path=%t/Test.swiftmodule -c -o %t/test.o // RUN: %target-build-swift -O %s -module-name=test -Xfrontend -sil-verify-all -I%t -emit-sil | %FileCheck %s // RUN: %target-build-swift -Onone %s -I%t %t/test.o -o %t/Onone.out // RUN: %target-build-swift -O %s -I%t %t/test.o -o %t/O.out // RUN: %target-run %t/Onone.out > %t/Onone.txt // RUN: %target-run %t/O.out > %t/O.txt // RUN: diff %t/Onone.txt %t/O.txt // REQUIRES: executable_test,swift_stdlib_no_asserts,optimized_stdlib import Test final class C { var x: Int var z: T let immutable: String private(set) var secretlyMutable: String init(x: Int, z: T) { self.x = x self.z = z self.immutable = "somestring" self.secretlyMutable = immutable } } struct Point { var x: Double var y: Double } struct S { var x: Int var y: Int? var z: T var p: Point var op: Point? var c: C } struct NonOffsetableProperties { // observers var x: Int { didSet {} } // reabstracted var y: () -> () // computed var z: Int { return 0 } } struct TupleProperties { // unlabeled var a: (Int, String) // labeled let b: (x: String, y: Int) // reference writable let c: (m: C, n: C) } typealias Tuple = (S, C) typealias TupleOfFunctions = (a: @convention(c) () -> (), b: @convention(c) () -> ()) func getIdentityKeyPathOfType(_: T.Type) -> KeyPath { return \.self } @inline(never) func printOffset(_ o: Int?) { print(o as Any) } // CHECK-LABEL: sil {{.*}} @$s4test0A13StructOffsetsyyF // CHECK-NOT: _storedInlineOffset // CHECK-NOT: class_method // CHECK: } // end sil function '$s4test0A13StructOffsetsyyF' @inline(never) func testStructOffsets() { let SLayout = MemoryLayout>.self printOffset(SLayout.offset(of: \S.x)) printOffset(SLayout.offset(of: \S.y)) printOffset(SLayout.offset(of: \S.z)) printOffset(SLayout.offset(of: \S.p)) printOffset(SLayout.offset(of: \S.p.x)) printOffset(SLayout.offset(of: \S.p.y)) printOffset(SLayout.offset(of: \S.c)) } // CHECK-LABEL: sil {{.*}} @$s4test0A20GenericStructOffsetsyyxmlF // CHECK-NOT: _storedInlineOffset // CHECK-NOT: class_method // CHECK: } // end sil function '$s4test0A20GenericStructOffsetsyyxmlF' @inline(never) @_semantics("optimize.sil.specialize.generic.never") func testGenericStructOffsets(_ t: T.Type) { let SLayout = MemoryLayout>.self printOffset(SLayout.offset(of: \S.x)) printOffset(SLayout.offset(of: \S.y)) printOffset(SLayout.offset(of: \S.z)) printOffset(SLayout.offset(of: \S.p)) printOffset(SLayout.offset(of: \S.p.x)) printOffset(SLayout.offset(of: \S.p.y)) printOffset(SLayout.offset(of: \S.c)) } // CHECK-LABEL: sil {{.*}} @$s4test0A10NonOffsetsyyF // CHECK-NOT: _storedInlineOffset // CHECK-NOT: class_method // CHECK: } // end sil function '$s4test0A10NonOffsetsyyF' @inline(never) func testNonOffsets() { let NOPLayout = MemoryLayout.self printOffset(NOPLayout.offset(of: \NonOffsetableProperties.x)) printOffset(NOPLayout.offset(of: \NonOffsetableProperties.y)) printOffset(NOPLayout.offset(of: \NonOffsetableProperties.z)) printOffset(MemoryLayout>.offset(of: \C.x)) let SLayout = MemoryLayout>.self printOffset(SLayout.offset(of: \S.c.x)) printOffset(SLayout.offset(of: \S.op!.x)) printOffset(SLayout.offset(of: \S.op?.x)) } // CHECK-LABEL: sil {{.*}} @$s4test0A11SelfOffsetsyyF // CHECK-NOT: _storedInlineOffset // CHECK-NOT: class_method // CHECK: } // end sil function '$s4test0A11SelfOffsetsyyF' @inline(never) func testSelfOffsets() { let SLayout = MemoryLayout>.self printOffset(SLayout.offset(of: \.self)) printOffset(SLayout.offset(of: getIdentityKeyPathOfType(S.self))) } // CHECK-LABEL: sil {{.*}} @$s4test0A12TupleOffsetsyyF // CHECK-NOT: _storedInlineOffset // CHECK-NOT: class_method // CHECK: } // end sil function '$s4test0A12TupleOffsetsyyF' @inline(never) func testTupleOffsets() { let TPLayout = MemoryLayout.self printOffset(TPLayout.offset(of: \TupleProperties.self)) printOffset(TPLayout.offset(of: \TupleProperties.a)) printOffset(TPLayout.offset(of: \TupleProperties.a.0)) printOffset(TPLayout.offset(of: \TupleProperties.a.1)) printOffset(TPLayout.offset(of: \TupleProperties.b)) printOffset(TPLayout.offset(of: \TupleProperties.b.x)) printOffset(TPLayout.offset(of: \TupleProperties.b.y)) printOffset(TPLayout.offset(of: \TupleProperties.c)) printOffset(TPLayout.offset(of: \TupleProperties.c.m)) printOffset(TPLayout.offset(of: \TupleProperties.c.n)) let TLayout = MemoryLayout>.self printOffset(TLayout.offset(of: \Tuple.self)) printOffset(TLayout.offset(of: \Tuple.0)) printOffset(TLayout.offset(of: \Tuple.0.x)) printOffset(TLayout.offset(of: \Tuple.1)) } // CHECK-LABEL: sil {{.*}} @$s4test0A16TupleOfFunctionsyyF // CHECK-NOT: _storedInlineOffset // CHECK-NOT: class_method // CHECK: } // end sil function '$s4test0A16TupleOfFunctionsyyF' @inline(never) func testTupleOfFunctions() { printOffset(MemoryLayout.offset(of: \.b)) } // CHECK-LABEL: sil {{.*}} @$s4test0A19GenericTupleOffsetsyyxmlF // CHECK-NOT: _storedInlineOffset // CHECK-NOT: class_method // CHECK: } // end sil function '$s4test0A19GenericTupleOffsetsyyxmlF' @inline(never) @_semantics("optimize.sil.specialize.generic.never") func testGenericTupleOffsets(_ t: T.Type) { let TLayout = MemoryLayout>.self printOffset(TLayout.offset(of: \Tuple.self)) printOffset(TLayout.offset(of: \Tuple.0)) printOffset(TLayout.offset(of: \Tuple.0.x)) printOffset(TLayout.offset(of: \Tuple.1)) } // CHECK-LABEL: sil {{.*}} @$s4test0A16ResilientOffsetsyyF // CHECK: class_method {{.*}}_storedInlineOffset // CHECK: } // end sil function '$s4test0A16ResilientOffsetsyyF' @inline(never) func testResilientOffsets() { let TLayout = MemoryLayout.self printOffset(TLayout.offset(of: \TestStruct.x)) } @inline(never) func testit() { print("### testStructOffsets") testStructOffsets() print("### testGenericStructOffsets") testGenericStructOffsets(Int.self) print("### testNonOffsets") testNonOffsets() print("### testSelfOffsets") testSelfOffsets() print("### testTupleOffsets") testTupleOffsets() print("### testGenericTupleOffsets") testGenericTupleOffsets(Int.self) print("### testResilientOffsets") testResilientOffsets() print("### testTupleOfFunctions") testTupleOfFunctions() } testit()