Yuta Koshizawa
August 03, 2018
230

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

わいわいswiftc #4

August 03, 2018

## Transcript

1. Generalized existen.al͕಺෦తʹ͢
Ͱʹଘࡏ͍ͯ͠Δ͔ௐ΂ͯΈͨ
Yuta Koshizawa @koher

2. ① ٙ໰ʹࢥͬͨ͜ͱ

3. ͜ͷίʔυͷ S ͕ಛघԽ͞Εͳ͍৔߹ɺ
sequence ͷ࣮ߦ࣌ͷ಺෦తදݱ͸Ͳ͏ͳͬͯΔʁ
func sum(of sequence: S) -> Int
where S.Element == Int {
return sequence.reduce(0, +)
}

4. ΋ͬͱஸೡʹ

5. associatedtype Λ࣋ͨͳ͍ϓϩτίϧ
protocol Animal {}
struct Cat: Animal {}
let cat: Cat = Cat()
let animal: Animal = cat // OK

6. ϓϩτίϧܕม਺ͷαΠζ
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

7. ஋ܕͱϓϩτίϧܕͱσΟεύον
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 : ੩తσΟεύον

8. ஋ܕͱϓϩτίϧܕͱσΟεύον
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 : ಈతσΟεύον

9. Existen(al containers 1
struct OpaqueExistentialContainer {
void *fixedSizeBuffer[3];
WitnessTable *witnessTables[NUM_WITNESS_TABLES];
};
1 h\$ps:/
/github.com/apple/swi6/blob/master/docs/ABI/TypeLayout.rst#existenBal-container-layout

10. ෳ਺ͷ Witness table Λ࣋ͭ৔߹
protocol P {}
protocol Q {}
struct S : P, Q {}
let pq: P & Q = S()

11. !
Existen(al container ͷ͓͔͛Ͱ
ந৅తͳϓϩτίϧܕͱͯ͠ѻ͑Δ

12. associatedtype Λ࣋ͭϓϩτίϧ
protocol Animal { associatedtype Value }
struct Cat: Animal { typealias Value = Int }
let cat: Cat = Cat()
let animal: Animal = cat // NG

13. Generalized existen.als 2
let strings
: Any
= ["a", "b", "c"]
2 h\$ps:/
/github.com/apple/swi6/blob/master/docs/GenericsManifesto.md#generalized-existenAals

14. associatedtype Λ࣋ͭϓϩτίϧ
protocol Animal { associatedtype Value }
struct Cat: Animal { typealias Value = Int }
let cat: Cat = Cat()
let animal: Any = cat
// Generalized existential Ͱ͜Ε͕Ͱ͖ΔΑ͏ʹͳΔ͔΋

15. !
Generalized existen.al ͕ͳ͍ͷͰ
associatedype ͕͋Δͱ
ϓϩίτϧܕͱͯ͠ѻ͑ͳ͍

16. Ͱ΋ɺ͜Ε͸Ͱ͖Δ
protocol Animal { associatedtype Value }
struct Cat: Animal { typealias Value = Int }
func useAnimal(_ animal: A) -> Int
where A.Value == Int { ... }
useAnimal(Cat()) //

OK

17. A ͕ Cat ʹಛघԽ͞ΕΔͱ͜͏ͳΔ
protocol Animal { associatedtype Value }
struct Cat: Animal { typealias Value = Int }
func useAnimal(_ animal: Cat) -> Int { ... }
useAnimal(Cat()) //

OK

18. ಛघԽ͞Εͳ͍ͱͲ͏ͳΔʁ
protocol Animal { associatedtype Value }
struct Cat: Animal { typealias Value = Int }
func useAnimal(_ animal: A) -> Int
where A.Value == Int { ... }
useAnimal(Cat()) // `Cat` ͸ͲͷΑ͏ʹѻΘΕΔʁ

19. !
΋͔ͯ͠͠಺෦తʹ͸
Existen(al ʹͳ͍ͬͯΔͷͰ͸ʁ

20. ② LLVM IR Ͱ಺෦తදݱΛௐࠪ

21. associatedtype ͕ ͳ͍ ͱ͖

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

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

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

25. swiftc -emit-ir foo.swift

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
}

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
}
\$S4main9useAnimalySiAA0C0_pF ʹϚϯάϦϯά͞ΕͯΔ

28. swift demangle S4main9useAnimalySiAA0C0_pF

29. σϚϯάϦϯάͷ݁Ռ
\$ swift demangle S4main9useAnimalySiAA0C0_pF
\$S4main9useAnimalySiAA0C0_pF ---> main.useAnimal(main.Animal) -> Swift.Int

30. 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

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
}
%T4main6AnimalP* ܕͷҾ਺͕Ұͭ

32. associatedtype ͕ ͳ͍ ͱ͖
%T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }

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

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

35. Witness tables ͱϙΠϯλܕ
• i8* : witness table ͷཁૉ
• i8** : witness table
• i8*** : witness table ͷू·Γ = witnessTables

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

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

38. ෳ਺ͷ 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** }

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
}
Ҿ਺ͱͯ͠ Existen)al container Λड͚औ͍ͬͯΔ

40. associatedtype ͕ ͳ͍ ͱ͖
%T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }
↕ ରԠ͍ͯ͠Δ
struct OpaqueExistentialContainer { // 40 όΠτ
void *fixedSizeBuffer[3]; // 24 όΠτ
Metadata *type; // 8 όΠτ
WitnessTable *witnessTable; // 8 όΠτ
};

41. Existen(al container ͷαΠζ
protocol P {}
protocol Q {}
print(MemoryLayout.size) // 40
print(MemoryLayout.size) // 48

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
}
Ҿ਺ͱͯ͠ 40 όΠτͷ Existen+al container Λड͚औ͍ͬͯΔ

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
}
getelementptr ͱ͸ʁ

44. getelementptr 3
= getelementptr , * {, [inrange] }*
= getelementptr inbounds , * {, [inrange] }*
3 h\$p:/
/llvm.org/docs/LangRef.html#getelementptr-instruc=on

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
// getelementptr inbounds , * , ,
%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 ൪໨ͷϝϯόͷϙΠϯλΛऔಘ

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

47. 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 ͷϙΠϯλΛऔಘ

48. 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 Λϩʔυ

49. 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 ൪໨ͷϝϯόͷϙΠϯλΛऔಘ

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

51. 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 ͷϙΠϯλΛऔಘ

52. 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 Λϩʔυ

53. 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 ൪໨ͷϝϯόͷϙΠϯλΛऔಘ

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

55. 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 ͷϙΠϯλΛऔಘ

56. 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 ͷ࣮ମͷϙΠϯλΛऔಘ

57. 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 ൪໨ͷཁૉͷϙΠϯλΛऔಘ

58. 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 ൪໨ͷཁૉΛϩʔυ

59. 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 Λදؔ͢਺ܕϙΠϯλʹΩϟετ

60. 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 Λίʔϧ

61. 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

62. associatedtype ͕ ͋Δ ͱ͖

63. associatedtype ͕ ͋Δ ͱ͖
protocol Animal {
associatedtype Value
func foo() -> Value
}
struct Cat: Animal {
var value: Int = 42
func foo() -> Int { return value }
}

64. associatedtype ͕ ͋Δ ͱ͖
func useAnimal(_ animal: A) -> Int
where A.Value == Int {
return animal.foo()
}
func useCat(_ cat: Cat) -> Int {
return useAnimal(cat)
}
print(useCat(Cat()))

65. 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
}

66. 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 Ͱ͸ͳ͘࠷ॳ͔Β෼ղ͞ΕͯΔ

67. 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
}
ಉ͡Α͏ʹࡾͭΛ༩͑ͯؔ਺Λίʔϧ

68. 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 Λදؔ͢਺ϙΠϯλ

69. 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 → ݁ՌΛ֨ೲ

70. 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 ͞ΕΔ

71. associatedtype ͕ ͋Δ ͱ͖
protocol Animal {
associatedtype Value
func foo() -> Value
}
struct Cat: Animal {
var value: Int = 42
func foo() -> Int { return value }
}

72. 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 ϙΠϯλΛհͯ݁͠ՌΛ
ฦ͢ඞཁ͕͋ͬͨʢͱࢥΘΕΔʣ

73. 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 ʁ

74. associatedtype ͕ ͋Δ ͱ͖
func useAnimal(_ animal: A) -> Int
where A.Value == Int {
return animal.foo()
}
func useCat(_ cat: Cat) -> Int {
return useAnimal(cat)
}
print(useCat(Cat()))

75. 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

76. 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 Λίʔϧ

77. 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 Ҿ਺

78. S4main3CatVAA6AnimalAAWP ΛσϚϯάϦϯά
\$ swift demangle S4main3CatVAA6AnimalAAWP
\$S4main3CatVAA6AnimalAAWP ---> protocol witness table for main.Cat : main.Animal in main

79. S4main3CatVAA6AnimalAAWP ΛσϚϯάϦϯά
\$ swift demangle S4main3CatVAA6AnimalAAWP
\$S4main3CatVAA6AnimalAAWP ---> protocol witness table for main.Cat : main.Animal in main
^^^^^^^^^^^^^^^^^^^^^^^^^^

80. 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 Λ౉͢

81. 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 ͱ౳Ձ

82. !
Existen(al container Ͱ
౉͞ͳ͍ͷ͸ͳͥʁ

83. associatedtype ͕ ͋Δ ͱ͖
func useAnimal(_ animal: A) -> Int
where A.Value == Int {
return animal.foo()
}
func useCat(_ cat: Cat) -> Int {
return useAnimal(cat)
}
print(useCat(Cat()))

84. A ܕ͸ useCat ͷத͚ͩͷܕ

85. !
useCat ͷϩʔΧϧείʔϓͰ
औΓѻ͑Ε͹ྑ͍

86. !
Existen(al container Ͱ
औΓճ͢ඞཁ͸ͳ͍

87. !
Existen(al container Ͱ
แΜͩΓ෼ղͨ͠Γ͢Δͱ
Φʔόʔϔου͕ൃੜ

88. !
ͦΕͳΒ Existen)al ʹͤͣ
࠷ॳ͔Β͹Β͹Βʹѻ͓͏
ʢͱ͍͏͜ͱͰ͸ʁʣ

89. ʲ౰ॳͷٙ໰ʳ
΋͔ͯ͠͠಺෦తʹ͸
Existen(al ʹͳ͍ͬͯΔͷͰ͸ʁ

90. !
Generalized existen.al ͸
಺෦తʹ΋ଘࡏ͠ͳ͔ͬͨ

91. !
Ͱ΋ useCat(_:) ͸
Existen(al ͱࣅͨ࢓૊ΈͰಈ͍ͯͨ

92. ΄΅ಉ͜͡ͱ͕͔֬ΊΒΕͯͨ 4
4 h\$ps:/
/qiita.com/omochimetaru/items/b41e7699ea25a324aefa

93. ͓͠·͍