$30 off During Our Annual Pro Sale. View Details »

Generalized existentialが内部的にすでに存在しているか調べてみた / A...

Generalized existentialが内部的にすでに存在しているか調べてみた / A Dive to Find Inner Generalized Existential Containers

わいわいswiftc #4

Yuta Koshizawa

August 03, 2018
Tweet

More Decks by Yuta Koshizawa

Other Decks in Programming

Transcript

  1. ϓϩτίϧܕม਺ͷαΠζ protocol Animal {} struct Cat: Animal { let a:

    Int8 } struct Dog: Animal { let b: Int32 } let cat: Cat = Cat(a: 2) // 1 όΠτ let dog: Dog = Dog(b: 3) // 4 όΠτ // ԿόΠτʁ ! let animal: Animal = Bool.random() ? cat : dog
  2. ஋ܕͱϓϩτίϧܕͱσΟεύον protocol Animal { func foo() -> Int } struct

    Cat: Animal { func foo() -> Int { return 2 } } struct Dog: Animal { func foo() -> Int { return 3 } } let cat: Cat = Cat() let dog: Dog = Dog() _ = cat.foo() // 2 : ੩తσΟεύον _ = dog.foo() // 3 : ੩తσΟεύον
  3. ஋ܕͱϓϩτίϧܕͱσΟεύον protocol Animal { func foo() -> Int } struct

    Cat: Animal { func foo() -> Int { return 2 } } struct Dog: Animal { func foo() -> Int { return 3 } } let cat: Cat = Cat() let dog: Dog = Dog() let animal: Animal = Bool.random() ? cat : dog _ = animal.foo() // 2 or 3 : ಈతσΟεύον
  4. Existen(al containers 1 struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type;

    WitnessTable *witnessTables[NUM_WITNESS_TABLES]; }; 1 h$ps:/ /github.com/apple/swi6/blob/master/docs/ABI/TypeLayout.rst#existenBal-container-layout
  5. associatedtype Λ࣋ͭϓϩτίϧ protocol Animal { associatedtype Value } struct Cat:

    Animal { typealias Value = Int } let cat: Cat = Cat() let animal: Animal = cat // NG
  6. Generalized existen.als 2 let strings : Any<Sequence where .Iterator.Element ==

    String> = ["a", "b", "c"] 2 h$ps:/ /github.com/apple/swi6/blob/master/docs/GenericsManifesto.md#generalized-existenAals
  7. associatedtype Λ࣋ͭϓϩτίϧ protocol Animal { associatedtype Value } struct Cat:

    Animal { typealias Value = Int } let cat: Cat = Cat() let animal: Any<Animal where .Value == Int> = cat // Generalized existential Ͱ͜Ε͕Ͱ͖ΔΑ͏ʹͳΔ͔΋
  8. Ͱ΋ɺ͜Ε͸Ͱ͖Δ protocol Animal { associatedtype Value } struct Cat: Animal

    { typealias Value = Int } func useAnimal<A: Animal>(_ animal: A) -> Int where A.Value == Int { ... } useAnimal(Cat()) // ✅ OK
  9. A ͕ Cat ʹಛघԽ͞ΕΔͱ͜͏ͳΔ protocol Animal { associatedtype Value }

    struct Cat: Animal { typealias Value = Int } func useAnimal(_ animal: Cat) -> Int { ... } useAnimal(Cat()) // ✅ OK
  10. ಛघԽ͞Εͳ͍ͱͲ͏ͳΔʁ protocol Animal { associatedtype Value } struct Cat: Animal

    { typealias Value = Int } func useAnimal<A: Animal>(_ animal: A) -> Int where A.Value == Int { ... } useAnimal(Cat()) // `Cat` ͸ͲͷΑ͏ʹѻΘΕΔʁ
  11. associatedtype ͕ ͳ͍ ͱ͖ protocol Animal { func foo() ->

    Int } struct Cat: Animal { var value: Int = 42 func foo() -> Int { return value } }
  12. associatedtype ͕ ͳ͍ ͱ͖ func useAnimal(_ animal: Animal) -> Int

    { return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))
  13. associatedtype ͕ ͳ͍ ͱ͖ func useAnimal(_ animal: Animal) -> Int

    { return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))
  14. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 }
  15. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } $S4main9useAnimalySiAA0C0_pF ʹϚϯάϦϯά͞ΕͯΔ
  16. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } ͜Ε͸ main.useAnimal(main.Animal) -> Swift.Int
  17. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } %T4main6AnimalP* ܕͷҾ਺͕Ұͭ
  18. associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x

    i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; };
  19. associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x

    i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; };
  20. Witness tables ͱϙΠϯλܕ • i8* : witness table ͷཁૉ •

    i8** : witness table • i8*** : witness table ͷू·Γ = witnessTables
  21. associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x

    i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; };
  22. associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x

    i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; };
  23. ෳ਺ͷ Witness table Λ࣋ͭ৔߹ protocol P {} protocol Q {}

    struct S : P, Q {} let pq: P & Q = S() ↓ LLVM IR ( P & Q ) %T4main1P_AA1Qp = type { [24 x i8], %swift.type*, i8**, i8** }
  24. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } Ҿ਺ͱͯ͠ Existen)al container Λड͚औ͍ͬͯΔ
  25. associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x

    i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { // 40 όΠτ void *fixedSizeBuffer[3]; // 24 όΠτ Metadata *type; // 8 όΠτ WitnessTable *witnessTable; // 8 όΠτ };
  26. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } Ҿ਺ͱͯ͠ 40 όΠτͷ Existen+al container Λड͚औ͍ͬͯΔ
  27. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } getelementptr ͱ͸ʁ
  28. getelementptr 3 <result> = getelementptr <ty>, <ty>* <ptrval>{, [inrange] <ty>

    <idx>}* <result> = getelementptr inbounds <ty>, <ty>* <ptrval>{, [inrange] <ty> <idx>}* 3 h$p:/ /llvm.org/docs/LangRef.html#getelementptr-instruc=on
  29. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 // getelementptr inbounds <ty>, <ty>* <ptrval>, <ty> <idx>, <ty> <idx> %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } 0 ൪໨ͷ %T4main6AnimalP ͷ 1 ൪໨ͷϝϯόͷϙΠϯλΛऔಘ
  30. associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x

    i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; };
  31. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } type ͷϙΠϯλΛऔಘ
  32. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } type Λϩʔυ
  33. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } 0 ൪໨ͷ %T4main6AnimalP ͷ 2 ൪໨ͷϝϯόͷϙΠϯλΛऔಘ
  34. associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x

    i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; };
  35. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } witnessTable ͷϙΠϯλΛऔಘ
  36. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } witnessTable Λϩʔυ
  37. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } 0 ൪໨ͷ %T4main6AnimalP ͷ 0 ൪໨ͷϝϯόͷϙΠϯλΛऔಘ
  38. associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x

    i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; };
  39. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } fixedSizeBuffer ͷϙΠϯλΛऔಘ
  40. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } fixedSizeBuffer ͷ࣮ମͷϙΠϯλΛऔಘ
  41. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } witnessTable ͔Β 1 ൪໨ͷཁૉͷϙΠϯλΛऔಘ
  42. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } witnessTable ͷ 1 ൪໨ͷཁૉΛϩʔυ
  43. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } foo Λදؔ͢਺ܕϙΠϯλʹΩϟετ
  44. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } foo Λίʔϧ
  45. associatedtype ͕ ͳ͍ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias

    nocapture dereferenceable(40)) #0 { entry: %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1 %2 = load %swift.type*, %swift.type** %1, align 8 %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2 %4 = load i8**, i8*** %3, align 8 %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0 %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1 %7 = getelementptr inbounds i8*, i8** %4, i32 1 %8 = load i8*, i8** %7, align 8, !invariant.load !25 %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)* %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4) ret i64 %10 } foo ͷ໭Γ஋Λ return
  46. associatedtype ͕ ͋Δ ͱ͖ protocol Animal { associatedtype Value func

    foo() -> Value } struct Cat: Animal { var value: Int = 42 func foo() -> Int { return value } }
  47. associatedtype ͕ ͋Δ ͱ͖ func useAnimal<A: Animal>(_ animal: A) ->

    Int where A.Value == Int { return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))
  48. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias

    nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 }
  49. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias

    nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } ࡾͭͷҾ਺: Existen*al container Ͱ͸ͳ͘࠷ॳ͔Β෼ղ͞ΕͯΔ
  50. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias

    nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } ಉ͡Α͏ʹࡾͭΛ༩͑ͯؔ਺Λίʔϧ
  51. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias

    nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } %5 ͸ Witness table ͔ΒऔΓग़͞Εͨ foo Λදؔ͢਺ϙΠϯλ
  52. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias

    nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } %6 ͸͜ͷؔ਺಺Ͱ֬อ͞ΕͨະॳظԽͷ Int → ݁ՌΛ֨ೲ
  53. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias

    nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } %1 ͸ %7 Λհͯ͠ return ͞ΕΔ
  54. associatedtype ͕ ͋Δ ͱ͖ protocol Animal { associatedtype Value func

    foo() -> Value } struct Cat: Animal { var value: Int = 42 func foo() -> Int { return value } }
  55. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias

    nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } ໭Γ஋ͷܕ͕ܾ·ͬͯͳ͍ͷͰ opaque ϙΠϯλΛհͯ݁͠ՌΛ ฦ͢ඞཁ͕͋ͬͨʢͱࢥΘΕΔʣ
  56. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias

    nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } %A.Animal ͸ຊ౰ʹ Witness table ʁ
  57. associatedtype ͕ ͋Δ ͱ͖ func useAnimal<A: Animal>(_ animal: A) ->

    Int where A.Value == Int { return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))
  58. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0

    { entry: %1 = alloca %T4main3CatV, align 8 %2 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0 %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0 store i64 %0, i64* %.value._value, align 8 %3 = bitcast %T4main3CatV* %1 to %swift.opaque* %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"( %swift.opaque* noalias nocapture %3, %swift.type* bitcast ( i64* getelementptr inbounds ( <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf", i32 0, i32 1 ) to %swift.type* ), i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0) ) %5 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %5) ret i64 %4 } useCat ͷ LLVM IR
  59. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0

    { entry: %1 = alloca %T4main3CatV, align 8 %2 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0 %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0 store i64 %0, i64* %.value._value, align 8 %3 = bitcast %T4main3CatV* %1 to %swift.opaque* %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"( %swift.opaque* noalias nocapture %3, %swift.type* bitcast ( i64* getelementptr inbounds ( <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf", i32 0, i32 1 ) to %swift.type* ), i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0) ) %5 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %5) ret i64 %4 } ͜͜Ͱ useAnimal Λίʔϧ
  60. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0

    { entry: %1 = alloca %T4main3CatV, align 8 %2 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0 %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0 store i64 %0, i64* %.value._value, align 8 %3 = bitcast %T4main3CatV* %1 to %swift.opaque* %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"( %swift.opaque* noalias nocapture %3, %swift.type* bitcast ( i64* getelementptr inbounds ( <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf", i32 0, i32 1 ) to %swift.type* ), i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0) ) %5 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %5) ret i64 %4 } ୈ 3 Ҿ਺
  61. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0

    { entry: %1 = alloca %T4main3CatV, align 8 %2 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0 %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0 store i64 %0, i64* %.value._value, align 8 %3 = bitcast %T4main3CatV* %1 to %swift.opaque* %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"( %swift.opaque* noalias nocapture %3, %swift.type* bitcast ( i64* getelementptr inbounds ( <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf", i32 0, i32 1 ) to %swift.type* ), i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0) ) %5 = bitcast %T4main3CatV* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %5) ret i64 %4 } ୈ 3 Ҿ਺ʹ Witness table Λ౉͢
  62. associatedtype ͕ ͋Δ ͱ͖ define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias

    nocapture, %swift.type* %A, i8** %A.Animal) #0 { entry: %1 = alloca %TSi, align 8 %2 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2 %4 = load i8*, i8** %3, align 8, !invariant.load !28 %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)* %6 = bitcast %TSi* %1 to %swift.opaque* call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal) %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0 %7 = load i64, i64* %._value, align 8 %8 = bitcast %TSi* %1 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %8) ret i64 %7 } ࡾͭͷҾ਺͸ Existen)al container ͱ౳Ձ
  63. associatedtype ͕ ͋Δ ͱ͖ func useAnimal<A: Animal>(_ animal: A) ->

    Int where A.Value == Int { return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat()))