Share
Embed
Generalized existentialが内部的にすでに存在しているか調べてみた / A Dive to Find Inner Generalized Existential Containers
わいわいswiftc #4
Yuta Koshizawa
August 03, 2018
Transcript
94 slides
-
͜ͷίʔυͷ S ͕ಛघԽ͞Εͳ͍߹ɺ sequence ͷ࣮ߦ࣌ͷ෦తදݱͲ͏ͳͬͯΔʁ func sum<S: Sequence>(of sequence: S)
-> Int where S.Element == Int { return sequence.reduce(0, +) } -
associatedtype Λ࣋ͨͳ͍ϓϩτίϧ protocol Animal {} struct Cat: Animal {} let
cat: Cat = Cat() let animal: Animal = cat // OK -
ϓϩτίϧܕมͷαΠζ 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 -
ܕͱϓϩτίϧܕͱσΟεύον 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 : ੩తσΟεύον -
ܕͱϓϩτίϧܕͱσΟεύον 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 : ಈతσΟεύον -
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 -
ෳͷ Witness table Λ࣋ͭ߹ protocol P {} protocol Q {}
struct S : P, Q {} let pq: P & Q = S() -
associatedtype Λ࣋ͭϓϩτίϧ protocol Animal { associatedtype Value } struct Cat:
Animal { typealias Value = Int } let cat: Cat = Cat() let animal: Animal = cat // NG -
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 -
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 Ͱ͜Ε͕Ͱ͖ΔΑ͏ʹͳΔ͔ -
Ͱɺ͜ΕͰ͖Δ protocol Animal { associatedtype Value } struct Cat: Animal
{ typealias Value = Int } func useAnimal<A: Animal>(_ animal: A) -> Int where A.Value == Int { ... } useAnimal(Cat()) // ✅ OK -
A ͕ Cat ʹಛघԽ͞ΕΔͱ͜͏ͳΔ protocol Animal { associatedtype Value }
struct Cat: Animal { typealias Value = Int } func useAnimal(_ animal: Cat) -> Int { ... } useAnimal(Cat()) // ✅ OK -
ಛघԽ͞Εͳ͍ͱͲ͏ͳΔʁ protocol Animal { associatedtype Value } struct Cat: Animal
{ typealias Value = Int } func useAnimal<A: Animal>(_ animal: A) -> Int where A.Value == Int { ... } useAnimal(Cat()) // `Cat` ͲͷΑ͏ʹѻΘΕΔʁ -
associatedtype ͕ ͳ͍ ͱ͖ protocol Animal { func foo() ->
Int } struct Cat: Animal { var value: Int = 42 func foo() -> Int { return value } } -
associatedtype ͕ ͳ͍ ͱ͖ func useAnimal(_ animal: Animal) -> Int
{ return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat())) -
associatedtype ͕ ͳ͍ ͱ͖ func useAnimal(_ animal: Animal) -> Int
{ return animal.foo() } func useCat(_ cat: Cat) -> Int { return useAnimal(cat) } print(useCat(Cat())) -
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 } -
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 ʹϚϯάϦϯά͞ΕͯΔ -
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 -
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* ܕͷҾ͕Ұͭ -
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } -
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; }; -
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; }; -
Witness tables ͱϙΠϯλܕ • i8* : witness table ͷཁૉ •
i8** : witness table • i8*** : witness table ͷू·Γ = witnessTables -
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; }; -
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; }; -
ෳͷ 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** } -
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 Λड͚औ͍ͬͯΔ -
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { // 40 όΠτ void *fixedSizeBuffer[3]; // 24 όΠτ Metadata *type; // 8 όΠτ WitnessTable *witnessTable; // 8 όΠτ }; -
Existen(al container ͷαΠζ protocol P {} protocol Q {} print(MemoryLayout<P>.size)
// 40 print(MemoryLayout<P & Q>.size) // 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 } Ҿͱͯ͠ 40 όΠτͷ Existen+al container Λड͚औ͍ͬͯΔ -
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 ͱʁ -
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 -
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 ൪ͷϝϯόͷϙΠϯλΛऔಘ -
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; }; -
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 ͷϙΠϯλΛऔಘ -
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 Λϩʔυ -
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 ൪ͷϝϯόͷϙΠϯλΛऔಘ -
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; }; -
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 ͷϙΠϯλΛऔಘ -
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 Λϩʔυ -
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 ൪ͷϝϯόͷϙΠϯλΛऔಘ -
associatedtype ͕ ͳ͍ ͱ͖ %T4main6AnimalP = type { [24 x
i8], %swift.type*, i8** } ↕ ରԠ͍ͯ͠Δ struct OpaqueExistentialContainer { void *fixedSizeBuffer[3]; Metadata *type; WitnessTable *witnessTable; }; -
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 ͷϙΠϯλΛऔಘ -
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 ͷ࣮ମͷϙΠϯλΛऔಘ -
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 ൪ͷཁૉͷϙΠϯλΛऔಘ -
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 ൪ͷཁૉΛϩʔυ -
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 Λදؔ͢ܕϙΠϯλʹΩϟετ -
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 Λίʔϧ -
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 -
associatedtype ͕ ͋Δ ͱ͖ protocol Animal { associatedtype Value func
foo() -> Value } struct Cat: Animal { var value: Int = 42 func foo() -> Int { return value } } -
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())) -
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 } -
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 Ͱͳ͘࠷ॳ͔Βղ͞ΕͯΔ -
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 } ಉ͡Α͏ʹࡾͭΛ༩͑ͯؔΛίʔϧ -
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 Λදؔ͢ϙΠϯλ -
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 → ݁ՌΛ֨ೲ -
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 ͞ΕΔ -
associatedtype ͕ ͋Δ ͱ͖ protocol Animal { associatedtype Value func
foo() -> Value } struct Cat: Animal { var value: Int = 42 func foo() -> Int { return value } } -
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 ϙΠϯλΛհͯ݁͠ՌΛ ฦ͢ඞཁ͕͋ͬͨʢͱࢥΘΕΔʣ -
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 ʁ -
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())) -
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 -
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 Λίʔϧ -
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 Ҿ -
S4main3CatVAA6AnimalAAWP ΛσϚϯάϦϯά $ swift demangle S4main3CatVAA6AnimalAAWP $S4main3CatVAA6AnimalAAWP ---> protocol witness
table for main.Cat : main.Animal in main -
S4main3CatVAA6AnimalAAWP ΛσϚϯάϦϯά $ swift demangle S4main3CatVAA6AnimalAAWP $S4main3CatVAA6AnimalAAWP ---> protocol witness
table for main.Cat : main.Animal in main ^^^^^^^^^^^^^^^^^^^^^^^^^^ -
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 Λ͢ -
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 ͱՁ -
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()))