Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Generalized existentialが内部的にすでに存在しているか調べてみた / A Dive to Find Inner Generalized Existential Containers
Search
Yuta Koshizawa
August 03, 2018
Programming
2
240
Generalized existentialが内部的にすでに存在しているか調べてみた / A Dive to Find Inner Generalized Existential Containers
わいわいswiftc #4
Yuta Koshizawa
August 03, 2018
Tweet
Share
More Decks by Yuta Koshizawa
See All by Yuta Koshizawa
Swift Concurrency時代のiOSアプリの作り方
koher
15
6.9k
Swift Zoomin' #8
koher
2
510
async/awaitやactorでiOSアプリ開発がどう変わるか Before & Afterの具体例で学ぶ
koher
9
6.2k
Swift Language Updates - Learn Languages 2021
koher
8
1.5k
先取り! Swift 6 の async/await
koher
15
3.7k
SwiftUIで勘違いした話
koher
1
2.6k
iOSエンジニアのための、SwiftからPythonのライブラリを使って機械学習する方法 / Machine Learning using Python from Swift for iOS Engineer
koher
5
13k
RPGで学ぶSwiftの値型 / Learning Value Types in Swift with RPG
koher
1
620
具体例とクイズで学ぶ、Swiftの4種類のエラーの使い分け
koher
3
6.3k
Other Decks in Programming
See All in Programming
両面どころかインフラもTSでできるよ ~ 全方位TypeScriptによるプロダクト開発 ~
myfinder
9
3.2k
はてなにおける CSS Modules、及び CSS Modules に足りないもの / CSS Modules in Hatena, and CSS Modules missing parts
mizdra
3
220
Java 22 Overview
kishida
1
170
スキーマ駆動開発による品質とスピードの両立 - 私達は何故、スキーマを書くのか
kentaroutakeda
0
120
[技育CAMPアカデミア]アイディアを形に!【超入門】スマホアプリ開発〜リリースまでの流れをご紹介
teamlab
PRO
0
350
Semantic search with Django and pgvector
pauloxnet
0
240
Front-end application development, Symfony-style(s)
dunglas
2
1.9k
Prepare for Jakarta EE 11 - Performance and Developer Productivity
ivargrimstad
0
440
From Spring Boot 2 to Spring Boot 3 with Java 21 and Jakarta EE
ivargrimstad
0
1.1k
Changed Rules: Architectures with Lightweight Stores
manfredsteyer
PRO
0
230
ADRを一年運用してみた/adr_after_a_year
hanhan1978
7
2.2k
#phpcon_odawara オープン・クローズドなテストフィクスチャを求めて / open closed test fixtures
77web
3
220
Featured
See All Featured
The Invisible Side of Design
smashingmag
294
49k
Building Flexible Design Systems
yeseniaperezcruz
318
37k
Making the Leap to Tech Lead
cromwellryan
123
8.5k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
6
990
Teambox: Starting and Learning
jrom
128
8.4k
Building Better People: How to give real-time feedback that sticks.
wjessup
354
18k
Documentation Writing (for coders)
carmenintech
59
3.9k
Creatively Recalculating Your Daily Design Routine
revolveconf
209
11k
Design by the Numbers
sachag
274
18k
BBQ
matthewcrist
80
8.7k
Web Components: a chance to create the future
zenorocha
305
41k
The Cost Of JavaScript in 2023
addyosmani
14
3.8k
Transcript
Generalized existen.al͕෦తʹ͢ Ͱʹଘࡏ͍ͯ͠Δ͔ௐͯΈͨ Yuta Koshizawa @koher
① ٙʹࢥͬͨ͜ͱ
͜ͷίʔυͷ 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()
! Existen(al container ͷ͓͔͛Ͱ நతͳϓϩτίϧܕͱͯ͠ѻ͑Δ
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 Ͱ͜Ε͕Ͱ͖ΔΑ͏ʹͳΔ͔
! Generalized existen.al ͕ͳ͍ͷͰ associatedype ͕͋Δͱ ϓϩίτϧܕͱͯ͠ѻ͑ͳ͍
Ͱɺ͜ΕͰ͖Δ 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` ͲͷΑ͏ʹѻΘΕΔʁ
! ͔ͯ͠͠෦తʹ Existen(al ʹͳ͍ͬͯΔͷͰʁ
② LLVM IR Ͱ෦తදݱΛௐࠪ
associatedtype ͕ ͳ͍ ͱ͖
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()))
swiftc -emit-ir foo.swift
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 ʹϚϯάϦϯά͞ΕͯΔ
swift demangle S4main9useAnimalySiAA0C0_pF
σϚϯάϦϯάͷ݁Ռ $ swift demangle S4main9useAnimalySiAA0C0_pF $S4main9useAnimalySiAA0C0_pF ---> 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 } ͜Ε 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 ͕ ͋Δ ͱ͖
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 ͱՁ
! 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()))
A ܕ useCat ͷத͚ͩͷܕ
! useCat ͷϩʔΧϧείʔϓͰ औΓѻ͑Εྑ͍
! Existen(al container Ͱ औΓճ͢ඞཁͳ͍
! Existen(al container Ͱ แΜͩΓղͨ͠Γ͢Δͱ Φʔόʔϔου͕ൃੜ
! ͦΕͳΒ Existen)al ʹͤͣ ࠷ॳ͔ΒΒΒʹѻ͓͏ ʢͱ͍͏͜ͱͰʁʣ
ʲॳͷٙʳ ͔ͯ͠͠෦తʹ Existen(al ʹͳ͍ͬͯΔͷͰʁ
! Generalized existen.al ෦తʹଘࡏ͠ͳ͔ͬͨ
! Ͱ useCat<A:Animal>(_:) Existen(al ͱࣅͨΈͰಈ͍ͯͨ
None
΄΅ಉ͜͡ͱ͕͔֬ΊΒΕͯͨ 4 4 h$ps:/ /qiita.com/omochimetaru/items/b41e7699ea25a324aefa
͓͠·͍