Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
SwiftのGenericsとProtocolの実装
omochimetaru
November 17, 2018
Programming
3
260
SwiftのGenericsとProtocolの実装
ソース
https://gist.github.com/omochi/58f374f2809fb1c9122d2b0b69948256
omochimetaru
November 17, 2018
Tweet
Share
More Decks by omochimetaru
See All by omochimetaru
Swift6のprotocol
omochi
3
330
SwiftSyntaxをうまく使おう
omochi
2
75
今から使えるSwiftとC++の新しいinterop手法
omochi
0
140
CSFixとラベルマッチ
omochi
0
150
Swiftのmodifyアクセサとコルーチン
omochi
0
380
Swiftのオーバーロード選択のスコア規則12種類
omochi
2
120
SILを読もう
omochi
2
480
型推論ハンズオン
omochi
4
2.3k
Swiftの型推論アルゴリズム(1)
omochi
4
2.4k
Other Decks in Programming
See All in Programming
Reactive Java Microservices on Kubernetes with Spring and JHipster
deepu105
1
170
Value and Record Types
hschwentner
0
550
競プロのすすめ
uya116
0
660
RFC 9111: HTTP Caching
jxck
0
160
パターンマッチングを学んで新しいJavaの世界へ!Java 18までの目玉機能をおさらいしよう / Java 18 pattern matching
ihcomega56
3
400
Vite でお手軽 Vue.js の環境構築
azuki
2
180
実践エクストリームプログラミング / Extreme Programming in Practice
enk
1
520
ISUCON12 事前講習
rosylilly
3
4.6k
エンジニアによる事業指標計測のススメ
doyaaaaaken
1
190
GoogleI/O2022 LT報告会資料
shinsukefujita1126
0
330
Client-Side Field-Level Encryption for Apache Kafka Connect @ VoxxedDays Luxembourg 2022
hpgrahsl
0
110
How we run a Realtime Puzzle Fighting Game on AWS Serverless
falken
0
250
Featured
See All Featured
The Brand Is Dead. Long Live the Brand.
mthomps
46
2.7k
Ruby is Unlike a Banana
tanoku
91
9.2k
The World Runs on Bad Software
bkeepers
PRO
57
5.3k
The Art of Programming - Codeland 2020
erikaheidi
32
11k
4 Signs Your Business is Dying
shpigford
169
20k
Put a Button on it: Removing Barriers to Going Fast.
kastner
56
2.3k
Docker and Python
trallard
27
1.6k
Reflections from 52 weeks, 52 projects
jeffersonlam
337
17k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
655
120k
Art Directing for the Web. Five minutes with CSS Template Areas
malarkey
196
9.4k
Intergalactic Javascript Robots from Outer Space
tanoku
261
25k
Stop Working from a Prison Cell
hatefulcrawdad
261
17k
Transcript
SwiftͷGenerics ͱProtocolͷ࣮ omochimetaru ݴޠॲཧܥษڧձ Vol.1 1
ࣗݾհ • omochimetaru • Qoncept, Inc. • iOS, Mac, Web
Frontend, Unity, Android • Swift, C++, TypeScript, Kotlin • Twitter, GitHub, Qiita, Qrunch • ήʔϜ, SwiftίϯύΠϥ 2
• Θ͍Θ͍swiftc https://iosdiscord.connpass.com • iOSDC (2018/09/02) SwiftͷδΣωϦΫεͲ͏ͬͯಈ͍͍ͯΔͷ ͔ίϯύΠϥͷιʔε͔Β୳Δ • Discord
swift-developers-japan 3
Swift • Apple͕։ൃ • Φʔϓϯιʔε • ωΠςΟϒίϯύΠϧݴޠ • ܕ •
Generics • ϓϩτίϧࢦ 4
Φʔϓϯιʔε https://github.com/apple/swift https://forums.swift.org 5
ωΠςΟϒίϯύΠϧ Swift → SIL → LLVM IR → ࣮ߦϑΝΠϧ 6
ࢀরܕ class Cat { var name: String = "ͨ·" }
let a = Cat() let b = a b.name = "Έ͚" print(a.name) // Έ͚ TraceGCແ͠ɻࢀরΧϯλΛ͏ɻ 7
ܕ let a = [10, 20, 30] var b =
a b[0] = 999 print(a) // [10, 20, 30] print(b) // [999, 20, 30] 8
struct Stone { var weight: Int = 5 } let
size = MemoryLayout<Stone>.size print(size) // 8 9
struct BigStone { var weight: Int = 5 var blob1:
Int = 999 var blob2: Int = 999 var blob3: Int = 999 } let size = MemoryLayout<BigStone>.size print(size) // 32 10
Generics // Array<Element> let a: [Int] = [10, 20, 30]
let b: [String] = a.map { String($0) } print(b) // ["10", "20", "30"] 11
func wrapArray<X>(_ x: X) -> Array<X> { return [x] }
let a = wrapArray(Stone()) print(a[0].weight) // 5 12
Genericsͷ࣮ 13
ಛ • ܕͱࢀরܕʹରԠ ܕҟͳΔαΠζΛͪɺ ࣗʹϝλใΛ࣋ͨͳ͍ 14
func takeX1<X>(_ x: X) { } func main() { takeX1(4)
} 15
$ swiftc -emit-ir a.swift 16
define hidden swiftcc void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture, %swift.type* %X)
#0 { entry: %X1 = alloca %swift.type*, align 8 store %swift.type* %X, %swift.type** %X1, align 8 ret void } define hidden swiftcc void @"$s1a4mainyyF"() #0 { entry: %0 = alloca %TSi, align 8 %1 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %1) %._value = getelementptr inbounds %TSi, %TSi* %0, i32 0, i32 0 store i64 4, i64* %._value, align 8 %2 = bitcast %TSi* %0 to %swift.opaque* call swiftcc void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture %2, %swift.type* @"$sSiN") %3 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %3) ret void } 17
Signature func takeX1<X>(_ x: X) void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture,
%swift.type* %X) <X> → opaque pointer + metatype 18
Metatype let t1: Int.Type = Int.self let t2 = type(of:
3) print(t1 == t2) // true // static member access print(Int.bitWidth) // 64 print(t1.bitWidth) // 64 19
ୈ1Ҿͷߏங define hidden swiftcc void @"$s1a4mainyyF"() #0 { entry: %0
= alloca %TSi, align 8 %1 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %1) %._value = getelementptr inbounds %TSi, %TSi* %0, i32 0, i32 0 store i64 4, i64* %._value, align 8 %2 = bitcast %TSi* %0 to %swift.opaque* call swiftcc void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture %2, %swift.type* @"$sSiN") %3 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %3) ret void } 20
ୈ2Ҿͷߏங define hidden swiftcc void @"$s1a4mainyyF"() #0 { entry: %0
= alloca %TSi, align 8 %1 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %1) %._value = getelementptr inbounds %TSi, %TSi* %0, i32 0, i32 0 store i64 4, i64* %._value, align 8 %2 = bitcast %TSi* %0 to %swift.opaque* call swiftcc void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture %2, %swift.type* @"$sSiN") %3 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %3) ret void } 21
IntͷMetatype֎෦ఆٛ͞ΕΔɻ @"$sSiN" = external global %swift.type, align 8 22
libSwiftCore.dylib ඪ४ϥΠϒϥϦ(Swift) + ϥϯλΠϜϥΠϒϥϦ(C++) • IntSwiftͰ࣮ • Int෦ͷBuildin.Int64C++Ͱ࣮ 23
stdlib/public/core/IntegerTypes.swift.gyb public struct Int { public var _value: Builtin.Int64 }
gybςϯϓϨʔτݴޠ 24
include/swift/Runtime/Metadata.h using FullOpaqueMetadata = FullMetadata<OpaqueMetadata>; #define BUILTIN_TYPE(Symbol, Name) \ SWIFT_RUNTIME_EXPORT
\ const FullOpaqueMetadata METADATA_SYM(Symbol); #include "swift/Runtime/BuiltinTypes.def" 25
swift/Runtime/BuiltinTypes.def BUILTIN_TYPE(Bi64_, "Builtin.Int64") ల։ޙ SWIFT_RUNTIME_EXPORT const FullOpaqueMetadata $SBi64_N; 26
ܕ͕ෆ໌ͳͷૢ࡞ func takeX2<X>(_ x: X) { let a = x
} • มaͷετϨʔδ֬อ • x͔Βaʹͷίϐʔ • aͷഁغ, ετϨʔδղ์ 27
Value Witness Table Metatype͔ΒऔΓग़ͤΔؔςʔϒϧ ίϐʔഁغͳͲɺ(Value)ʹର͢ΔҰൠతͳૢ ࡞Λ͢Δ͕ؔೖ͍ͬͯΔ ΠϯλʔϑΣʔεOpaqueͳදݱʹͳ͍ͬͯΔ ೖ͍ͬͯΔؔݸผͷܕΛظ͍ͯ͠ΔͨΊɺ OpaqueͳͱɺͦͷਅͷܕͷMetatypeΛϖΞͰ औΓճ͢
28
Valueͷҙຯ ܕ(struct)ͷ߹ɺͦͷϝϞϦ্ͷදݱͷ͜ͱɻ ࢀরܕ(class)ͷ߹ɺͦͷΞυϨεΛ֨ೲ͢Δ8ό ΠτͷϙΠϯλͷ͜ͱɻ https://github.com/apple/swift/blob/master/ docs/OwnershipManifesto.md 29
ίϐʔ/ഁغͷॲཧ༰ ܕͷ߹ɺͦΕͷͭ stored property ͯ͢ Λ࠶ؼతʹίϐʔ/ഁغɻ ࢀরܕͷͷ߹ɺͦͷࢀরઌͷΦϒδΣΫτʹ ͋ΔࢀরΧϯλͷ૿ݮૢ࡞ɻ 30
VWTͷݻ༗ɺڞ༗ ܕͷMetatypeݻ༗ͷVWTΛ࣋ͭɻ ࢀরܕͷMetatypeڞ௨ͷVWTΛ࣋ͭɻ 31
Value Witness Table ͷৄࡉ 32
include/swift/ABI/Metadata.h template <typename Runtime> struct TargetValueWitnessTable; using ValueWitnessTable = TargetValueWitnessTable<InProcess>;
template <typename Runtime> struct TargetValueWitnessTable { #define WANT_ONLY_REQUIRED_VALUE_WITNESSES #define VALUE_WITNESS(LOWER_ID, UPPER_ID) \ typename TargetValueWitnessTypes<Runtime>::LOWER_ID LOWER_ID; #include "swift/ABI/ValueWitness.def" } 33
template <typename Runtime> struct TargetValueWitnessTable { typename TargetValueWitnessTypes<Runtime>::initializeBufferWithCopyOfBuffer initializeBufferWithCopyOfBuffer; typename
TargetValueWitnessTypes<Runtime>::destroy destroy; typename TargetValueWitnessTypes<Runtime>::initializeWithCopy initializeWithCopy; typename TargetValueWitnessTypes<Runtime>::assignWithCopy assignWithCopy; typename TargetValueWitnessTypes<Runtime>::initializeWithTake initializeWithTake; typename TargetValueWitnessTypes<Runtime>::assignWithTake assignWithTake; typename TargetValueWitnessTypes<Runtime>::getEnumTagSinglePayload getEnumTagSinglePayload; typename TargetValueWitnessTypes<Runtime>::storeEnumTagSinglePayload storeEnumTagSinglePayload; typename TargetValueWitnessTypes<Runtime>::size size; typename TargetValueWitnessTypes<Runtime>::flags flags; typename TargetValueWitnessTypes<Runtime>::stride stride; } 34
ݟ͘͢লུ struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake;
getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 35
ίϐʔ4छྨ struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake;
getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 36
ഁغ struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake;
getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 37
ϝϞϦ֬อ༻ͷใ struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake;
getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 38
࠶ܝ func takeX2<X>(_ x: X) { let a = x
} 39
define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type* %X)
#0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 40
VWTͷऔΓग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*
%X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 41
VWT͔ΒsizeͷऔΓग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*
%X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 42
[8] = size struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy;
initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 43
ετϨʔδͷ֬อ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*
%X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 44
VWT͔ΒinitializeWithCopyͷऔΓग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*
%X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 45
[2] = initializeWithCopy struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy;
initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 46
initializeWithCopyͷݺͼग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*
%X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 47
VWT͔ΒdestroyͷऔΓग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*
%X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 48
[1] = destroy struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy;
initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 49
destroyͷݺͼग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*
%X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 50
ετϨʔδallocaͰ֬อ͞Ε͍ͯͨͷͰɺ ղ์༻ͷ໋ྩಛʹͳ͠ 51
VWTૢ࡞ॲཧͷ ίϯύΠϥͷ࣮ 52
࠶ܝ Swift → SIL → LLVM IR → ࣮ߦϑΝΠϧ LLVM
IRͷੜSIL͔Βͷมͱ࣮ͯ͠͞Εͯ ͍Δɻ 53
$ swiftc -emit-sil b.swift 54
// takeX2<A>(_:) sil hidden @$s1b6takeX2yyxlF : $@convention(thin) <X> (@in_guaranteed X)
-> () { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "x", argno 1 // id: %1 %2 = alloc_stack $X, let, name "a" // users: %5, %4, %3 copy_addr %0 to [initialization] %2 : $*X // id: %3 destroy_addr %2 : $*X // id: %4 dealloc_stack %2 : $*X // id: %5 %6 = tuple () // user: %7 return %6 : $() // id: %7 } // end sil function '$s1b6takeX2yyxlF' 55
copy_addr Λݟ͍ͯ͘ // takeX2<A>(_:) sil hidden @$s1b6takeX2yyxlF : $@convention(thin) <X>
(@in_guaranteed X) -> () { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "x", argno 1 // id: %1 %2 = alloc_stack $X, let, name "a" // users: %5, %4, %3 copy_addr %0 to [initialization] %2 : $*X // id: %3 destroy_addr %2 : $*X // id: %4 dealloc_stack %2 : $*X // id: %5 %6 = tuple () // user: %7 return %6 : $() // id: %7 } // end sil function '$s1b6takeX2yyxlF' 56
ରԠ͢ΔLLVM-IR %6 = bitcast i8* %a to %swift.opaque* store i8*
%a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 57
SILؔ͝ͱʹLLVM IR͕ੜ͞ΕΔ swift/lib/IRGen/IRGenSIL.cpp void IRGenModule::emitSILFunction(SILFunction *f) 58
SILؔʹ͓͍ͯɺBasicBlock͝ͱʹLLVM IR͕ੜ ͞ΕΔ swift/lib/IRGen/IRGenSIL.cpp void IRGenSILFunction::visitSILBasicBlock(SILBasicBlock *BB) 59
SIL BasicBlockʹ͓͍ͯɺInstruction͝ͱʹLLVM IR͕ੜ͞ΕΔ ໋ྩछྨʹର͢ΔVisitorύλʔϯͰॻ͔Ε͍ͯΔ include/swift/SIL/SILVisitor.h 60
template <typename ImplClass, typename RetTy = void, typename... ArgTys> class
SILInstructionVisitor { public: RetTy visit(SILInstruction *inst, ArgTys... args) { asImpl().beforeVisit(inst, args...); switch (inst->getKind()) { #define INST(CLASS, PARENT) \ case SILInstructionKind::CLASS: \ return asImpl().visit##CLASS(static_cast<CLASS*>(inst), \ std::forward<ArgTys>(args)...); #include "swift/SIL/SILNodes.def" } llvm_unreachable("Not reachable, all cases handled"); } } 61
copy_addr໋ྩͷॲཧதͳͷͰvisitCopyAddrInst ͕ݺΕΔ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) { SILType addrTy = i->getSrc()->getType();
const TypeInfo &addrTI = getTypeInfo(addrTy); Address src = getLoweredAddress(i->getSrc()); // See whether we have a deferred fixed-size buffer initialization. auto &loweredDest = getLoweredValue(i->getDest()); assert(!loweredDest.isUnallocatedAddressInBuffer()); Address dest = loweredDest.getAnyAddress(); if (i->isInitializationOfDest()) { if (i->isTakeOfSrc()) { addrTI.initializeWithTake(*this, dest, src, addrTy, false); } else { addrTI.initializeWithCopy(*this, dest, src, addrTy, false); } } else { if (i->isTakeOfSrc()) { addrTI.assignWithTake(*this, dest, src, addrTy, false); } else { addrTI.assignWithCopy(*this, dest, src, addrTy, false); } } } 62
ίϐʔݩͷίϯύΠϧ࣌ܕใ(TypeInfo)ΛऔΓग़ ͢ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) { SILType addrTy = i->getSrc()->getType();
const TypeInfo &addrTI = getTypeInfo(addrTy); Address src = getLoweredAddress(i->getSrc()); // See whether we have a deferred fixed-size buffer initialization. auto &loweredDest = getLoweredValue(i->getDest()); assert(!loweredDest.isUnallocatedAddressInBuffer()); Address dest = loweredDest.getAnyAddress(); if (i->isInitializationOfDest()) { if (i->isTakeOfSrc()) { addrTI.initializeWithTake(*this, dest, src, addrTy, false); } else { addrTI.initializeWithCopy(*this, dest, src, addrTy, false); } } else { if (i->isTakeOfSrc()) { addrTI.assignWithTake(*this, dest, src, addrTy, false); } else { addrTI.assignWithCopy(*this, dest, src, addrTy, false); } } } 63
ܕใͷϝιουʹసૹ͢Δ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) { SILType addrTy = i->getSrc()->getType(); const
TypeInfo &addrTI = getTypeInfo(addrTy); Address src = getLoweredAddress(i->getSrc()); // See whether we have a deferred fixed-size buffer initialization. auto &loweredDest = getLoweredValue(i->getDest()); assert(!loweredDest.isUnallocatedAddressInBuffer()); Address dest = loweredDest.getAnyAddress(); if (i->isInitializationOfDest()) { if (i->isTakeOfSrc()) { addrTI.initializeWithTake(*this, dest, src, addrTy, false); } else { addrTI.initializeWithCopy(*this, dest, src, addrTy, false); } } else { if (i->isTakeOfSrc()) { addrTI.assignWithTake(*this, dest, src, addrTy, false); } else { addrTI.assignWithCopy(*this, dest, src, addrTy, false); } } } 64
ܕ͕<X>ͳͷͰaddrTI OpaqueArchetypeTypeInfo lib/IRGen/GenArcheType.cpp class OpaqueArchetypeTypeInfo : public ResilientTypeInfo<OpaqueArchetypeTypeInfo> { };
65
ΫϥεͷResilientTypeInfoͷ࣮͕ݺΕΔ lib/IRGen/ResilientTypeInfo.h template <class Impl> class ResilientTypeInfo : public WitnessSizedTypeInfo<Impl>
{ void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T, bool isOutlined) const override { emitInitializeWithCopyCall(IGF, T, dest, src); } }; 66
lib/IRGen/GenOpaque.cpp void irgen::emitInitializeWithCopyCall(IRGenFunction &IGF, SILType T, Address dest, Address src)
{ llvm::Value *metadata; auto fn = IGF.emitValueWitnessFunctionRef(T, metadata, ValueWitness::InitializeWithCopy); auto destPtr = emitCastToOpaquePtr(IGF, dest); auto srcPtr = emitCastToOpaquePtr(IGF, src); IGF.Builder.CreateCall(fn, {destPtr, srcPtr, metadata}); } 67
void irgen::emitInitializeWithCopyCall(IRGenFunction &IGF, SILType T, Address dest, Address src) {
llvm::Value *metadata; auto fn = IGF.emitValueWitnessFunctionRef(T, metadata, ValueWitness::InitializeWithCopy); auto destPtr = emitCastToOpaquePtr(IGF, dest); auto srcPtr = emitCastToOpaquePtr(IGF, src); IGF.Builder.CreateCall(fn, {destPtr, srcPtr, metadata}); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 68
void irgen::emitInitializeWithCopyCall(IRGenFunction &IGF, SILType T, Address dest, Address src) {
llvm::Value *metadata; auto fn = IGF.emitValueWitnessFunctionRef(T, metadata, ValueWitness::InitializeWithCopy); auto destPtr = emitCastToOpaquePtr(IGF, dest); auto srcPtr = emitCastToOpaquePtr(IGF, src); IGF.Builder.CreateCall(fn, {destPtr, srcPtr, metadata}); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 69
void irgen::emitInitializeWithCopyCall(IRGenFunction &IGF, SILType T, Address dest, Address src) {
llvm::Value *metadata; auto fn = IGF.emitValueWitnessFunctionRef(T, metadata, ValueWitness::InitializeWithCopy); auto destPtr = emitCastToOpaquePtr(IGF, dest); auto srcPtr = emitCastToOpaquePtr(IGF, src); IGF.Builder.CreateCall(fn, {destPtr, srcPtr, metadata}); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 70
lib/IRGen/GenOpaque.cpp // index = ValueWitness::InitializeWithCopy FunctionPointer IRGenFunction::emitValueWitnessFunctionRef(SILType type, llvm::Value *&metadataSlot,
ValueWitness index) { assert(isValueWitnessFunction(index)); auto key = LocalTypeDataKind::forValueWitness(index); if (auto witness = tryGetLocalTypeDataForLayout(type, key)) { metadataSlot = emitTypeMetadataRefForLayout(type); auto signature = IGM.getValueWitnessSignature(index); return FunctionPointer(witness, signature); } auto vwtable = emitValueWitnessTableRef(type, &metadataSlot); auto witness = emitLoadOfValueWitnessFunction(*this, vwtable, index); setScopedLocalTypeDataForLayout(type, key, witness.getPointer()); return witness; } 71
// index = ValueWitness::InitializeWithCopy FunctionPointer IRGenFunction::emitValueWitnessFunctionRef(SILType type, llvm::Value *&metadataSlot, ValueWitness
index) { assert(isValueWitnessFunction(index)); auto key = LocalTypeDataKind::forValueWitness(index); if (auto witness = tryGetLocalTypeDataForLayout(type, key)) { metadataSlot = emitTypeMetadataRefForLayout(type); auto signature = IGM.getValueWitnessSignature(index); return FunctionPointer(witness, signature); } auto vwtable = emitValueWitnessTableRef(type, &metadataSlot); auto witness = emitLoadOfValueWitnessFunction(*this, vwtable, index); setScopedLocalTypeDataForLayout(type, key, witness.getPointer()); return witness; } 72
// index = ValueWitness::InitializeWithCopy static FunctionPointer emitLoadOfValueWitnessFunction(IRGenFunction &IGF, llvm::Value *table,
ValueWitness index) { assert(isValueWitnessFunction(index)); llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, table, index); auto label = getValueWitnessLabel(index); auto signature = IGF.IGM.getValueWitnessSignature(index); auto type = signature.getType()->getPointerTo(); witness = IGF.Builder.CreateBitCast(witness, type, label); return FunctionPointer(witness, signature); } 73
// index = ValueWitness::InitializeWithCopy static FunctionPointer emitLoadOfValueWitnessFunction(IRGenFunction &IGF, llvm::Value *table,
ValueWitness index) { assert(isValueWitnessFunction(index)); llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, table, index); auto label = getValueWitnessLabel(index); auto signature = IGF.IGM.getValueWitnessSignature(index); auto type = signature.getType()->getPointerTo(); witness = IGF.Builder.CreateBitCast(witness, type, label); return FunctionPointer(witness, signature); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 74
// index = ValueWitness::InitializeWithCopy static FunctionPointer emitLoadOfValueWitnessFunction(IRGenFunction &IGF, llvm::Value *table,
ValueWitness index) { assert(isValueWitnessFunction(index)); llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, table, index); auto label = getValueWitnessLabel(index); auto signature = IGF.IGM.getValueWitnessSignature(index); auto type = signature.getType()->getPointerTo(); witness = IGF.Builder.CreateBitCast(witness, type, label); return FunctionPointer(witness, signature); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 75
// index = ValueWitness::InitializeWithCopy llvm::Value *irgen::emitInvariantLoadOfOpaqueWitness(IRGenFunction &IGF, llvm::Value *table, WitnessIndex
index) { assert(table->getType() == IGF.IGM.WitnessTablePtrTy); // GEP to the appropriate index, avoiding spurious IR in the trivial case. llvm::Value *slot = table; if (index.getValue() != 0) slot = IGF.Builder.CreateConstInBoundsGEP1_32( /*Ty=*/nullptr, table, index.getValue()); auto witness = IGF.Builder.CreateLoad(Address(slot, IGF.IGM.getPointerAlignment())); IGF.setInvariantLoad(witness); return witness; } 76
// index = ValueWitness::InitializeWithCopy llvm::Value *irgen::emitInvariantLoadOfOpaqueWitness(IRGenFunction &IGF, llvm::Value *table, WitnessIndex
index) { assert(table->getType() == IGF.IGM.WitnessTablePtrTy); // GEP to the appropriate index, avoiding spurious IR in the trivial case. llvm::Value *slot = table; if (index.getValue() != 0) slot = IGF.Builder.CreateConstInBoundsGEP1_32( /*Ty=*/nullptr, table, index.getValue()); auto witness = IGF.Builder.CreateLoad(Address(slot, IGF.IGM.getPointerAlignment())); IGF.setInvariantLoad(witness); return witness; } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 77
// index = ValueWitness::InitializeWithCopy llvm::Value *irgen::emitInvariantLoadOfOpaqueWitness(IRGenFunction &IGF, llvm::Value *table, WitnessIndex
index) { assert(table->getType() == IGF.IGM.WitnessTablePtrTy); // GEP to the appropriate index, avoiding spurious IR in the trivial case. llvm::Value *slot = table; if (index.getValue() != 0) slot = IGF.Builder.CreateConstInBoundsGEP1_32( /*Ty=*/nullptr, table, index.getValue()); auto witness = IGF.Builder.CreateLoad(Address(slot, IGF.IGM.getPointerAlignment())); IGF.setInvariantLoad(witness); return witness; } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 78
Protocol 79
ϝιουͷఆٛ protocol Animal { func speak() -> String } class
Cat : Animal { func speak() -> String { return "ʹΌʔ" } } class Dog : Animal { func speak() -> String { return "ΘΜ" } } 80
staticϝιουͷఆٛ protocol Animal { static func label() -> String }
class Cat : Animal { static func label() -> String { return "ೣ" } } class Dog : Animal { static func label() -> String { return "ݘ" } } 81
associated type protocol Animal { associatedtype Food func eat(food: Food)
} struct CatFood {} class Cat : Animal { typealias Food = CatFood func eat(food: CatFood) { } } struct DogFood {} class Dog : Animal { typealias Food = DogFood func eat(food: DogFood) { } } 82
Selfܕ protocol Animal { func spawn() -> Self } final
class Cat : Animal { func spawn() -> Cat { return Cat() } } final class Dog : Animal { func spawn() -> Dog { return Dog() } } 83
GenericsͱΈ߹ΘͤΔ protocol Animal { func speak() -> String } class
Cat : Animal { func speak() -> String { return "ʹΌʔ" } } func invokeSpeak<X: Animal>(animal: X) -> String { return animal.speak() } print(invokeSpeak(animal: Cat())) // ʹΌʔ 84
ܕΫϥε෩ protocol Addable { static var zero: Self { get
} static func +(a: Self, b: Self) -> Self } extension Int : Addable { static var zero: Int { return 0 } } extension Sequence where Element : Addable { func sum() -> Element { return reduce(Element.zero) { $0 + $1 } } } let a = [1, 2, 3] // Array (struct) Sequence (protocol) print(a.sum()) // 6 85
Protocolͷ࣮ 86
ಛ • ܕͱࢀরܕʹରԠ • طଘͷܕʹޙՄೳ • staticϝϯό 87
protocol Animal { func speak() -> Int } class Cat
: Animal { func speak() -> Int { return 28 } } struct Stone : Animal { func speak() -> Int { return 14 } } 88
SILͰݟΔͱɺCatͱStoneͦΕͧΕʹɺ Animalͷwitness table͕͋Δ sil_witness_table hidden Cat: Animal module c {
method #Animal.speak!1: <Self where Self : Animal> (Self) -> () -> Int : @$s1c3CatCAA6AnimalA2aDP5speakSiyFTW // protocol witness for Animal.speak() in conformance Cat } sil_witness_table hidden Stone: Animal module c { method #Animal.speak!1: <Self where Self : Animal> (Self) -> () -> Int : @$s1c5StoneVAA6AnimalA2aDP5speakSiyFTW // protocol witness for Animal.speak() in conformance Stone } 89
Protocol Witness Table Protocolʹ४ڌ͢ΔͨΊͷؔςʔϒϧ ͦͷProtocolͰنఆ͞ΕΔૢ࡞Λ͢Δ͕ؔೖͬ ͍ͯΔ ΠϯλʔϑΣʔεOpaqueͳදݱʹͳ͍ͬͯΔ ೖ͍ͬͯΔؔݸผͷܕΛظ͍ͯ͠ΔͨΊɺ OpaqueͳͱɺͦͷਅͷܕͷPWTΛϖΞͰऔΓ ճ͢
90
γϯϓϧͳྫ func invokeSpeak<X: Animal>(animal: X) -> Int { return animal.speak()
} 91
SILͰݟΔ // invokeSpeak<A>(animal:) sil hidden @$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF : $@convention(thin) <X where
X : Animal> (@in_guaranteed X) -> Int { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "animal", argno 1 // id: %1 %2 = witness_method $X, #Animal.speak!1 : <Self where Self : Animal> (Self) -> () -> Int : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %3 %3 = apply %2<X>(%0) : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %4 return %3 : $Int // id: %4 } // end sil function '$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF' 92
witnessϝιουͷऔΓग़͠ // invokeSpeak<A>(animal:) sil hidden @$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF : $@convention(thin) <X where
X : Animal> (@in_guaranteed X) -> Int { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "animal", argno 1 // id: %1 %2 = witness_method $X, #Animal.speak!1 : <Self where Self : Animal> (Self) -> () -> Int : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %3 %3 = apply %2<X>(%0) : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %4 return %3 : $Int // id: %4 } // end sil function '$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF' 93
ؔͷݺͼग़͠ // invokeSpeak<A>(animal:) sil hidden @$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF : $@convention(thin) <X where
X : Animal> (@in_guaranteed X) -> Int { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "animal", argno 1 // id: %1 %2 = witness_method $X, #Animal.speak!1 : <Self where Self : Animal> (Self) -> () -> Int : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %3 %3 = apply %2<X>(%0) : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %4 return %3 : $Int // id: %4 } // end sil function '$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF' 94
LLVM-IRͰͷPWT @"$s1c3CatCAA6AnimalAAWP" = hidden constant [2 x i8*] [ i8*
bitcast (%swift.protocol_conformance_descriptor* @"$s1c3CatCAA6AnimalAAMc" to i8*), i8* bitcast (i64 (%T1c3CatC**, %swift.type*, i8**)* @"$s1c3CatCAA6AnimalA2aDP5speakSiyFTW" to i8*) ], align 8 @"$s1c5StoneVAA6AnimalAAWP" = hidden constant [2 x i8*] [ i8* bitcast (%swift.protocol_conformance_descriptor* @"$s1c5StoneVAA6AnimalAAMc" to i8*), i8* bitcast (i64 (%T1c5StoneV*, %swift.type*, i8**)* @"$s1c5StoneVAA6AnimalA2aDP5speakSiyFTW" to i8*) ], align 8 95
LLVM-IRͰͷར༻ଆ define hidden swiftcc i64 @"$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF"( %swift.opaque* noalias nocapture, %swift.type*
%X, i8** %X.Animal) #0 { entry: %X1 = alloca %swift.type*, align 8 store %swift.type* %X, %swift.type** %X1, align 8 %1 = getelementptr inbounds i8*, i8** %X.Animal, i32 1 %2 = load i8*, i8** %1, align 8, !invariant.load !29 %3 = bitcast i8* %2 to i64 (%swift.opaque*, %swift.type*, i8**)* %4 = call swiftcc i64 %3(%swift.opaque* noalias nocapture swiftself %0, %swift.type* %X, i8** %X.Animal) ret i64 %4 } 96
Signature func invokeSpeak<X: Animal>(animal: X) -> Int define hidden swiftcc
i64 @"$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF"( %swift.opaque* noalias nocapture, %swift.type* %X, i8** %X.Animal) <X: Animal> → opaque pointer + meta type + witness table 97
witnessϝιουͷऔΓग़͠ define hidden swiftcc i64 @"$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF"( %swift.opaque* noalias nocapture, %swift.type*
%X, i8** %X.Animal) #0 { entry: %X1 = alloca %swift.type*, align 8 store %swift.type* %X, %swift.type** %X1, align 8 %1 = getelementptr inbounds i8*, i8** %X.Animal, i32 1 %2 = load i8*, i8** %1, align 8, !invariant.load !29 %3 = bitcast i8* %2 to i64 (%swift.opaque*, %swift.type*, i8**)* %4 = call swiftcc i64 %3(%swift.opaque* noalias nocapture swiftself %0, %swift.type* %X, i8** %X.Animal) ret i64 %4 } 98
@"$s1c3CatCAA6AnimalAAWP" = hidden constant [2 x i8*] [ i8* bitcast
(%swift.protocol_conformance_descriptor* @"$s1c3CatCAA6AnimalAAMc" to i8*), i8* bitcast (i64 (%T1c3CatC**, %swift.type*, i8**)* @"$s1c3CatCAA6AnimalA2aDP5speakSiyFTW" to i8*) ], align 8 @"$s1c5StoneVAA6AnimalAAWP" = hidden constant [2 x i8*] [ i8* bitcast (%swift.protocol_conformance_descriptor* @"$s1c5StoneVAA6AnimalAAMc" to i8*), i8* bitcast (i64 (%T1c5StoneV*, %swift.type*, i8**)* @"$s1c5StoneVAA6AnimalA2aDP5speakSiyFTW" to i8*) ], align 8 99
witnessϝιουͷݺͼग़͠ define hidden swiftcc i64 @"$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF"( %swift.opaque* noalias nocapture, %swift.type*
%X, i8** %X.Animal) #0 { entry: %X1 = alloca %swift.type*, align 8 store %swift.type* %X, %swift.type** %X1, align 8 %1 = getelementptr inbounds i8*, i8** %X.Animal, i32 1 %2 = load i8*, i8** %1, align 8, !invariant.load !29 %3 = bitcast i8* %2 to i64 (%swift.opaque*, %swift.type*, i8**)* %4 = call swiftcc i64 %3(%swift.opaque* noalias nocapture swiftself %0, %swift.type* %X, i8** %X.Animal) ret i64 %4 } 100
ܕΫϥε෩ͷྫ protocol Addable { static var zero: Self { get
} static func +(a: Self, b: Self) -> Self } extension Int : Addable { static var zero: Int { return 0 } } extension Sequence where Element : Addable { func sum() -> Element { return reduce(Element.zero) { $0 + $1 } } } let a = [1, 2, 3] // Array (struct) Sequence (protocol) print(a.sum()) // 6 101
IntͷAddable @"$sSi1d7AddableAAWP" = hidden constant [3 x i8*] [ i8*
bitcast (%swift.protocol_conformance_descriptor* @"$sSi1d7AddableAAMc" to i8*), i8* bitcast ( void (%TSi*, %swift.type*, %swift.type*, i8**)* @"$sSi1d7AddableA2aBP4zeroxvgZTW" to i8*), i8* bitcast ( void (%TSi*, %TSi*, %TSi*, %swift.type*, %swift.type*, i8**)* @"$sSi1d7AddableA2aBP1poiyxx_xtFZTW" to i8*) ], align 8 102
sumϝιου define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,
%swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* call swiftcc void @"$sSTsE6reduceyqd__qd___qd__qd___7ElementQztKXEtKlF"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %8, i8* bitcast ( void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.refcounted*)* @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA" to i8*), %swift.opaque* %21, %swift.type* %Self, %swift.type* %Self.Element, i8** %Self.Sequence, %swift.opaque* noalias nocapture swiftself %1, %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) %22 = load %swift.error*, %swift.error** %swifterror, align 8 %23 = icmp ne %swift.error* %22, null br i1 %23, label %28, label %24 ; <label>:24: ; preds = %entry call void @swift_release(%swift.refcounted* %12) #5 call void @swift_release(%swift.refcounted* %12) #5 %25 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 1 %26 = load i8*, i8** %25, align 8, !invariant.load !23 %destroy = bitcast i8* %26 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %8, %swift.type* %Self.Element) #5 %27 = bitcast %swift.opaque* %8 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %27) ret void ; <label>:28: ; preds = %entry %29 = phi %swift.error* [ %22, %entry ] store %swift.error* null, %swift.error** %swifterror, align 8 call void @swift_release(%swift.refcounted* %12) #5 unreachable } 103
େ·͔ͳྲྀΕ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,
%swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: ; Element.zeroͷ༻ҙ ; Ϋϩʔδϟڥͷ༻ҙ ; Sequence.reduceͷݺͼग़͠ ; ྫ֎ϋϯυϦϯά ; <label>:24: ; ਖ਼ৗܥ, ΫϦϯφοϓ ; <label>:28: ; ҟৗܥ } 104
Signature define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( ; ฦΓ %swift.opaque* noalias
nocapture sret, ; Array metatype %swift.type* %Self, ; Sequence PWT of Array i8** %Self.Sequence, ; Addable PWT of Int i8** %Self.Element.Addable, ; self (Array) %swift.opaque* noalias nocapture swiftself) 105
Element.zeroͷ༻ҙ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,
%swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 106
Array<Int>.Type͔ΒInt.TypeͷऔΓग़͠ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,
%swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 107
IntͷVWTͷऔΓग़͠ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,
%swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 108
VWT͔ΒsizeͷऔΓग़͠ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,
%swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 109
zeroͷྖҬ֬อ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,
%swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 110
PWT͔Βstatic funcͷऔΓग़͠ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture
sret, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 111
zeroͷݺͼग़͠ͱ֨ೲ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,
%swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 112
Ϋϩʔδϟڥͷ༻ҙ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds
( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 113
3ϫʔυͷstorageΛ࣋ͭΦϒδΣΫτͷੜ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds
( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 114
[0]ʹArray.TypeΛ֨ೲ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds
( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 115
[1]ʹArrayͷSequence PWTΛ֨ೲ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr
inbounds ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 116
[2]ʹIntͷAddable PWTΛ֨ೲ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr
inbounds ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 117
Sequence.reduceͷݺͼग़͠ call swiftcc void @"$sSTsE6reduceyqd__qd___qd__qd___7ElementQztKXEtKlF"( %swift.opaque* noalias nocapture sret %0,
%swift.opaque* noalias nocapture %8, i8* bitcast ( void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.refcounted*)* @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA" to i8*), %swift.opaque* %21, %swift.type* %Self, %swift.type* %Self.Element, i8** %Self.Sequence, %swift.opaque* noalias nocapture swiftself %1, %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) 118
call swiftcc void @"$sSTsE6reduceyqd__qd___qd__qd___7ElementQztKXEtKlF"( ; ฦΓ %swift.opaque* noalias nocapture sret
%0, ; ࡞ͬͨzero %swift.opaque* noalias nocapture %8, ; ΫϩʔδϟͷؔϙΠϯλ i8* bitcast ( void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.refcounted*)* @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA" to i8*), ; ࡞ͬͨΫϩʔδϟڥ %swift.opaque* %21, ; Array.Type %swift.type* %Self, ; Int.Type %swift.type* %Self.Element, ; ArrayͷSequence PWT i8** %Self.Sequence, ; self (Array) %swift.opaque* noalias nocapture swiftself %1, ; ྫ֎ %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) 119
ͯ͠ΔΫϩʔδϟ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture sret,
%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 120
Signature define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( ; ฦΓ %swift.opaque* noalias
nocapture sret, ; Ҿ1 %swift.opaque* noalias nocapture, ; Ҿ2 %swift.opaque* noalias nocapture, ; Ϋϩʔδϟڥ %swift.refcounted* swiftself) 121
ڥ͔ΒArray.TypeͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture sret,
%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 122
ڥ͔ΒArrayͷSequence PWTͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture
sret, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 123
ڥ͔ΒIntͷAddable PWTͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture
sret, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 124
Ϋϩʔδϟຊମͷݺͼग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture sret,
%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 125
Ϋϩʔδϟຊମ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret,
%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %3 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %3, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %4 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 2 %5 = load i8*, i8** %4, align 8, !invariant.load !23 %6 = bitcast i8* %5 to void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %6( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) ret void } 126
Array.Type͔ΒInt.TypeͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret,
%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %3 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %3, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %4 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 2 %5 = load i8*, i8** %4, align 8, !invariant.load !23 %6 = bitcast i8* %5 to void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %6( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) ret void } 127
PWT͔Β+ͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret,
%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %3 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %3, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %4 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 2 %5 = load i8*, i8** %4, align 8, !invariant.load !23 %6 = bitcast i8* %5 to void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %6( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) ret void } 128
+ͷݺͼग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret,
%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %3 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %3, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %4 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 2 %5 = load i8*, i8** %4, align 8, !invariant.load !23 %6 = bitcast i8* %5 to void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %6( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) ret void } 129
·ͱΊ GenericMetatypeͱVWTͰಈ͘ ProtocolPWTͰಈ͘ 130
͓ΘΓ ڵຯΛ࣋ͬͨਓͥͻ DiscordΘ͍Θ͍swiftc 131