Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
Swiftの関数型の実行時表現
omochimetaru
December 17, 2018
Programming
7
200
Swiftの関数型の実行時表現
ソース
https://gist.github.com/omochi/3a6c7790a7a53c0f844c7aea01709044
omochimetaru
December 17, 2018
Tweet
Share
More Decks by omochimetaru
See All by omochimetaru
omochi
0
71
omochi
0
260
omochi
2
96
omochi
2
400
omochi
4
2k
omochi
4
2.1k
omochi
5
860
omochi
1
160
omochi
1
150
Other Decks in Programming
See All in Programming
matyo91
1
150
daipresents
0
330
kaz29
2
130
kodetr
0
150
bamboooo
1
130
yusuke57
0
120
shiba6v
0
200
mathetake
7
2.2k
kilometer
2
260
devinjeon
2
870
kubode
2
190
joytomo
1
540
Featured
See All Featured
robhawkes
53
2.9k
qrush
285
19k
maltzj
502
36k
roundedbygravity
84
7.9k
lara
590
61k
destraynor
221
47k
chriscoyier
498
130k
yeseniaperezcruz
302
31k
caitiem20
311
17k
denniskardys
220
120k
thoeni
4
660
addyosmani
495
110k
Transcript
Swiftͷؔܕͷ ࣮ߦ࣌දݱ Θ͍Θ͍swiftc omochimetaru 1
3छྨͷදݱ • thin: ͨͩͷؔϙΠϯλ • thick: ؔϙΠϯλ + ίϯςΩετϙΠϯλ •
block: Objective-CͷϒϩοΫɻObjectiveCʹ ͓͚ΔΦϒδΣΫτϙΠϯλ 2
thinؔ ੜίʔυ func main1() { let a = { (x:
Int) -> Int in return x * 2 } } 3
ੜίʔυ define hidden swiftcc void @"$s1d5main1yyF"() #0 { entry: %a.debug
= alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %1) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64)* @"$s1d5main1yyFS2icfU_" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* null, %swift.refcounted** %a.debug.data, align 8 ret void } 4
Ϋϩʔδϟຊମؔͷऔಘ define hidden swiftcc void @"$s1d5main1yyF"() #0 { entry: %a.debug
= alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %1) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64)* @"$s1d5main1yyFS2icfU_" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* null, %swift.refcounted** %a.debug.data, align 8 ret void } 5
Ϋϩʔδϟຊମؔ define internal swiftcc i64 @"$s1d5main1yyFS2icfU_"(i64) #0 { entry: %x.debug
= alloca i64, align 8 %1 = bitcast i64* %x.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store i64 %0, i64* %x.debug, align 8 %2 = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %0, i64 2) %3 = extractvalue { i64, i1 } %2, 0 %4 = extractvalue { i64, i1 } %2, 1 br i1 %4, label %6, label %5 ; <label>:5: ; preds = %entry ret i64 %3 ; <label>:6: ; preds = %entry call void @llvm.trap() unreachable } 6
ͦͷ··ͷγάωνϟ define internal swiftcc i64 @"$s1d5main1yyFS2icfU_"(i64) SwiftͰॻ͘ͳΒ (Int) -> Int
7
thickؔ thickؔΩϟϓνϟ͕͋Δͱੜ͞ΕΔɻ Ωϟϓνϟͨ͠ϝϞϦۭؒΛؔͱҰॹʹऔΓճ ͢ɻ 8
ੜίʔυ func main2() { var t = 3 let a
= { (x: Int) -> Int in t += x return t } } 9
ੜίʔυ define hidden swiftcc void @"$s1d5main2yyF"() #0 { entry: %t
= alloca %TSi, align 8 %0 = bitcast %TSi* %t to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %a.debug = alloca %swift.function, align 8 %1 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 16, i1 false) %2 = bitcast %TSi* %t to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %t._value = getelementptr inbounds %TSi, %TSi* %t, i32 0, i32 0 store i64 3, i64* %t._value, align 8 %3 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 24, i64 7) #3 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, %TSi* }>* %5 = getelementptr inbounds <{ %swift.refcounted, %TSi* }>, <{ %swift.refcounted, %TSi* }>* %4, i32 0, i32 1 store %TSi* %t, %TSi** %5, align 8 %6 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %6) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main2yyFS2icfU_Tf0ns_nTA" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* %3, %swift.refcounted** %a.debug.data, align 8 call void @swift_release(%swift.refcounted* %3) #3 %7 = bitcast %TSi* %t to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %7) ret void } 10
Ϋϩʔδϟຊମؔͷऔಘ define hidden swiftcc void @"$s1d5main2yyF"() #0 { entry: %t
= alloca %TSi, align 8 %0 = bitcast %TSi* %t to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false) %a.debug = alloca %swift.function, align 8 %1 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 16, i1 false) %2 = bitcast %TSi* %t to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) %t._value = getelementptr inbounds %TSi, %TSi* %t, i32 0, i32 0 store i64 3, i64* %t._value, align 8 %3 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 24, i64 7) #3 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, %TSi* }>* %5 = getelementptr inbounds <{ %swift.refcounted, %TSi* }>, <{ %swift.refcounted, %TSi* }>* %4, i32 0, i32 1 store %TSi* %t, %TSi** %5, align 8 %6 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %6) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main2yyFS2icfU_Tf0ns_nTA" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* %3, %swift.refcounted** %a.debug.data, align 8 call void @swift_release(%swift.refcounted* %3) #3 %7 = bitcast %TSi* %t to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %7) ret void } 11
Ϋϩʔδϟຊମؔ define internal swiftcc i64 @"$s1d5main2yyFS2icfU_Tf0ns_nTA"(i64, %swift.refcounted* swiftself) #0 {
entry: %2 = bitcast %swift.refcounted* %1 to <{ %swift.refcounted, %TSi* }>* %3 = getelementptr inbounds <{ %swift.refcounted, %TSi* }>, <{ %swift.refcounted, %TSi* }>* %2, i32 0, i32 1 %4 = load %TSi*, %TSi** %3, align 8 %5 = tail call swiftcc i64 @"$s1d5main2yyFS2icfU_Tf0ns_n"(i64 %0, %TSi* nocapture dereferenceable(8) %4) ret i64 %5 } 12
γάωνϟʹίϯςΩετϙΠϯλΛؚΉ define internal swiftcc i64 @"$s1d5main2yyFS2icfU_Tf0ns_nTA"( i64, %swift.refcounted* swiftself) SwiftͰॻ͘ͳΒ
(Int, Context) -> Int 13
ݺͼग़͠ίʔυ func invoke(_ f: (Int) -> Int) { f(33) }
14
ݺͼग़͠ίʔυ define hidden swiftcc void @"$s1d6invokeyyS2iXEF"(i8*, %swift.opaque*) #0 { entry:
%f.debug = alloca %swift.noescape.function, align 8 %2 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 16, i1 false) %3 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %3) %f.debug.fn = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 0 store i8* %0, i8** %f.debug.fn, align 8 %f.debug.data = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 1 store %swift.opaque* %1, %swift.opaque** %f.debug.data, align 8 %4 = bitcast i8* %0 to i64 (i64, %swift.refcounted*)* %5 = bitcast %swift.opaque* %1 to %swift.refcounted* %6 = call swiftcc i64 %4(i64 33, %swift.refcounted* swiftself %5) ret void } 15
ؔϙΠϯλͱίϯςΩετϙΠϯλ define hidden swiftcc void @"$s1d6invokeyyS2iXEF"(i8*, %swift.opaque*) #0 { entry:
%f.debug = alloca %swift.noescape.function, align 8 %2 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 16, i1 false) %3 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %3) %f.debug.fn = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 0 store i8* %0, i8** %f.debug.fn, align 8 %f.debug.data = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 1 store %swift.opaque* %1, %swift.opaque** %f.debug.data, align 8 %4 = bitcast i8* %0 to i64 (i64, %swift.refcounted*)* %5 = bitcast %swift.opaque* %1 to %swift.refcounted* %6 = call swiftcc i64 %4(i64 33, %swift.refcounted* swiftself %5) ret void } 16
ؔϙΠϯλͷऔΓग़͠ define hidden swiftcc void @"$s1d6invokeyyS2iXEF"(i8*, %swift.opaque*) #0 { entry:
%f.debug = alloca %swift.noescape.function, align 8 %2 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 16, i1 false) %3 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %3) %f.debug.fn = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 0 store i8* %0, i8** %f.debug.fn, align 8 %f.debug.data = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 1 store %swift.opaque* %1, %swift.opaque** %f.debug.data, align 8 %4 = bitcast i8* %0 to i64 (i64, %swift.refcounted*)* %5 = bitcast %swift.opaque* %1 to %swift.refcounted* %6 = call swiftcc i64 %4(i64 33, %swift.refcounted* swiftself %5) ret void } 17
ίϯςΩετϙΠϯλͷऔΓग़͠ define hidden swiftcc void @"$s1d6invokeyyS2iXEF"(i8*, %swift.opaque*) #0 { entry:
%f.debug = alloca %swift.noescape.function, align 8 %2 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 16, i1 false) %3 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %3) %f.debug.fn = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 0 store i8* %0, i8** %f.debug.fn, align 8 %f.debug.data = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 1 store %swift.opaque* %1, %swift.opaque** %f.debug.data, align 8 %4 = bitcast i8* %0 to i64 (i64, %swift.refcounted*)* %5 = bitcast %swift.opaque* %1 to %swift.refcounted* %6 = call swiftcc i64 %4(i64 33, %swift.refcounted* swiftself %5) ret void } 18
ίϯςΩετϙΠϯλΛͯ͠ݺͼग़͠ define hidden swiftcc void @"$s1d6invokeyyS2iXEF"(i8*, %swift.opaque*) #0 { entry:
%f.debug = alloca %swift.noescape.function, align 8 %2 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 16, i1 false) %3 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %3) %f.debug.fn = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 0 store i8* %0, i8** %f.debug.fn, align 8 %f.debug.data = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 1 store %swift.opaque* %1, %swift.opaque** %f.debug.data, align 8 %4 = bitcast i8* %0 to i64 (i64, %swift.refcounted*)* %5 = bitcast %swift.opaque* %1 to %swift.refcounted* %6 = call swiftcc i64 %4(i64 33, %swift.refcounted* swiftself %5) ret void } 19
ड͚͠ίʔυ func main3() { var t = 3 let a
= { (x: Int) -> Int in t += x return t } invoke(a) } 20
ड͚͠ίʔυ define hidden swiftcc void @"$s1d5main3yyF"() #0 { entry: %a.debug
= alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.3, i32 0, i32 2), i64 24, i64 7) #2 %2 = bitcast %swift.refcounted* %1 to <{ %swift.refcounted, [8 x i8] }>* %3 = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, <{ %swift.refcounted, [8 x i8] }>* %2, i32 0, i32 1 %4 = bitcast [8 x i8]* %3 to %TSi* call void asm sideeffect "", "r"(%TSi* %4) %._value = getelementptr inbounds %TSi, %TSi* %4, i32 0, i32 0 store i64 3, i64* %._value, align 8 %5 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %6 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %6) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* %1, %swift.refcounted** %a.debug.data, align 8 %7 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %8 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %9 = bitcast %swift.refcounted* %1 to %swift.opaque* call swiftcc void @"$s1d6invokeyyS2iXEF"(i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), %swift.opaque* %9) call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 ret void } 21
ΩϟϓνϟΦϒδΣΫτͷϝϞϦ֬อ define hidden swiftcc void @"$s1d5main3yyF"() #0 { entry: %a.debug
= alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.3, i32 0, i32 2), i64 24, i64 7) #2 %2 = bitcast %swift.refcounted* %1 to <{ %swift.refcounted, [8 x i8] }>* %3 = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, <{ %swift.refcounted, [8 x i8] }>* %2, i32 0, i32 1 %4 = bitcast [8 x i8]* %3 to %TSi* call void asm sideeffect "", "r"(%TSi* %4) %._value = getelementptr inbounds %TSi, %TSi* %4, i32 0, i32 0 store i64 3, i64* %._value, align 8 %5 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %6 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %6) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* %1, %swift.refcounted** %a.debug.data, align 8 %7 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %8 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %9 = bitcast %swift.refcounted* %1 to %swift.opaque* call swiftcc void @"$s1d6invokeyyS2iXEF"(i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), %swift.opaque* %9) call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 ret void } 22
Ωϟϓνϟม༻ͷϝϞϦࢀর define hidden swiftcc void @"$s1d5main3yyF"() #0 { entry: %a.debug
= alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.3, i32 0, i32 2), i64 24, i64 7) #2 %2 = bitcast %swift.refcounted* %1 to <{ %swift.refcounted, [8 x i8] }>* %3 = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, <{ %swift.refcounted, [8 x i8] }>* %2, i32 0, i32 1 %4 = bitcast [8 x i8]* %3 to %TSi* call void asm sideeffect "", "r"(%TSi* %4) %._value = getelementptr inbounds %TSi, %TSi* %4, i32 0, i32 0 store i64 3, i64* %._value, align 8 %5 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %6 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %6) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* %1, %swift.refcounted** %a.debug.data, align 8 %7 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %8 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %9 = bitcast %swift.refcounted* %1 to %swift.opaque* call swiftcc void @"$s1d6invokeyyS2iXEF"(i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), %swift.opaque* %9) call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 ret void } 23
t = 3 define hidden swiftcc void @"$s1d5main3yyF"() #0 {
entry: %a.debug = alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.3, i32 0, i32 2), i64 24, i64 7) #2 %2 = bitcast %swift.refcounted* %1 to <{ %swift.refcounted, [8 x i8] }>* %3 = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, <{ %swift.refcounted, [8 x i8] }>* %2, i32 0, i32 1 %4 = bitcast [8 x i8]* %3 to %TSi* call void asm sideeffect "", "r"(%TSi* %4) %._value = getelementptr inbounds %TSi, %TSi* %4, i32 0, i32 0 store i64 3, i64* %._value, align 8 %5 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %6 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %6) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* %1, %swift.refcounted** %a.debug.data, align 8 %7 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %8 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %9 = bitcast %swift.refcounted* %1 to %swift.opaque* call swiftcc void @"$s1d6invokeyyS2iXEF"(i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), %swift.opaque* %9) call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 ret void } 24
ؔຊମͱҰॹʹ͢ define hidden swiftcc void @"$s1d5main3yyF"() #0 { entry: %a.debug
= alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.3, i32 0, i32 2), i64 24, i64 7) #2 %2 = bitcast %swift.refcounted* %1 to <{ %swift.refcounted, [8 x i8] }>* %3 = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, <{ %swift.refcounted, [8 x i8] }>* %2, i32 0, i32 1 %4 = bitcast [8 x i8]* %3 to %TSi* call void asm sideeffect "", "r"(%TSi* %4) %._value = getelementptr inbounds %TSi, %TSi* %4, i32 0, i32 0 store i64 3, i64* %._value, align 8 %5 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %6 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %6) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* %1, %swift.refcounted** %a.debug.data, align 8 %7 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %8 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #2 %9 = bitcast %swift.refcounted* %1 to %swift.opaque* call swiftcc void @"$s1d6invokeyyS2iXEF"(i8* bitcast (i64 (i64, %swift.refcounted*)* @"$s1d5main3yyFS2icfU_TA" to i8*), %swift.opaque* %9) call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 call void @swift_release(%swift.refcounted* %1) #2 ret void } 25
thinͱthickͷޓੑ thinؔthickؔͱͯ͠ѻ͑Δ 26
ड͚͠ίʔυ func main4() { let a = { (x: Int)
-> Int in return x * 2 } invoke(a) } 27
ड͚͠ίʔυ define hidden swiftcc void @"$s1d5main4yyF"() #0 { entry: %a.debug
= alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %1) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64)* @"$s1d5main4yyFS2icfU_" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* null, %swift.refcounted** %a.debug.data, align 8 call swiftcc void @"$s1d6invokeyyS2iXEF"( i8* bitcast (i64 (i64)* @"$s1d5main4yyFS2icfU_" to i8*), %swift.opaque* null) ret void } 28
thinؔϙΠϯλ͕ͦͷ··͞Ε͍ͯΔ ίϯςΩετϙΠϯλnull define hidden swiftcc void @"$s1d5main4yyF"() #0 { entry:
%a.debug = alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %1) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64)* @"$s1d5main4yyFS2icfU_" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* null, %swift.refcounted** %a.debug.data, align 8 call swiftcc void @"$s1d6invokeyyS2iXEF"( i8* bitcast (i64 (i64)* @"$s1d5main4yyFS2icfU_" to i8*), %swift.opaque* null) ret void } 29
Ҿʹड͚ΒΕͳ͍ͣͷɺ ίϯςΩετϙΠϯλ͕͞ΕΔʂ ; invokeʹؔΛ͢ͱ͜Ζ call swiftcc void @"$s1d6invokeyyS2iXEF"( i8* bitcast
(i64 (i64)* @"$s1d5main4yyFS2icfU_" to i8*), %swift.opaque* null) ; invoke͕ؔΛݺͼग़͢ͱ͜Ζ %6 = call swiftcc i64 %4( i64 33, %swift.refcounted* swiftself %5) 30
swiftcc Swift༻ͷݺͼग़͠ن(Calling Convention) swiftself: ίϯςΩετϙΠϯλଐੑ %6 = call swiftcc i64
%4(i64 33, %swift.refcounted* swiftself %5) 31
swiftselfࢦఆ͞ΕͨҾઐ༻ͷϨδελͰ ͞ΕΔɻͭ·Γɺଞͷ௨ৗͷҾ͜ͷϨδελ ʹׂΓͯΒΕͳ͍ɻΑͬͯɺίϯςΩετϙ Πϯλ͕ෆཁͳؔͰ͜ͷϨδελΛಡ·ͳ͍ ͱ͍͏͚ͩͰޓੑ͕ಘΒΕΔɻ https://github.com/apple/swift/blob/master/ docs/CallingConvention.rst 32
ϝιουͱswiftself ϝιουʹselfΛҾ͖͢ͱ͖ʹswiftself͕ ΘΕΔ 33
ϝιουੜίʔυ class Cat { var age: Int = 3 func
sleep(year: Int) -> Int { age += year return age } } define hidden swiftcc i64 @"$s1d3CatC5sleep4yearS2i_tF"( i64, %T1d3CatC* swiftself) { ... } 34
throwsͳؔ ੜίʔυ extension Int : Error {} func main5() {
let a = { (x: Int) -> Int in throw x } } 35
ੜ͞ΕͨΫϩʔδϟ define internal swiftcc i64 @"$s1d5main5yyFS2iKcfU_"(i64, %swift.refcounted* swiftself, %swift.error** noalias
nocapture swifterror dereferenceable(8)) #0 { entry: %x.debug = alloca i64, align 8 %3 = bitcast i64* %x.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %3, i8 0, i64 8, i1 false) store i64 %0, i64* %x.debug, align 8 %4 = call i8** @"$sS2is5Error1dWl"() #5 %5 = call swiftcc { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* @"$sSiN", i8** %4, %swift.opaque* null, i1 false) %6 = extractvalue { %swift.error*, %swift.opaque* } %5, 0 %7 = extractvalue { %swift.error*, %swift.opaque* } %5, 1 %8 = bitcast %swift.opaque* %7 to %TSi* %._value = getelementptr inbounds %TSi, %TSi* %8, i32 0, i32 0 store i64 %0, i64* %._value, align 8 store %swift.error* %6, %swift.error** %2, align 8 call swiftcc void @swift_willThrow(i8* swiftself undef, %swift.error** noalias nocapture readonly swifterror dereferenceable(8) %2) #2 store %swift.error* null, %swift.error** %2, align 8 store %swift.error* %6, %swift.error** %2, align 8 ret i64 undef } 36
γάωνϟ define internal swiftcc i64 @"$s1d5main5yyFS2iKcfU_"(i64, %swift.refcounted* swiftself, %swift.error** noalias
nocapture swifterror dereferenceable(8)) SwiftͰॻ͘ͳΒ (Int, Context, inout Error) -> Int 37
throwsͳؔ%swift.errorͷμϒϧϙΠϯλ ΛҾʹड͚ɺͦ͜ͷॻ͖ࠐΈͱͯ͠ΤϥʔΛ ૹग़͢Δɻ͜ͷҾswifterrorଐੑΛ༩͑Β ΕΔɻswifterrorͷҾ͕͋Δؔɺ swiftselfͷҾඞਢͱ͞Ε͍ͯΔɻͦͷͨ Ίɺ͜ͷΫϩʔδϟΩϟϓνϟΛ͍ͯ͠ͳ͍͕ swiftselfΛҾʹ͍࣋ͬͯΔɻ 38
ݺͼग़͠ଆ func invokeThrowing(_ f: (Int) throws -> Int) { try!
f(44) } 39
ݺͼग़͠ଆ define hidden swiftcc void @"$s1d14invokeThrowingyyS2iKXEF"(i8*, %swift.opaque*) #0 { entry:
%f.debug = alloca %swift.noescape.function, align 8 %2 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 16, i1 false) %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 %3 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %3) %f.debug.fn = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 0 store i8* %0, i8** %f.debug.fn, align 8 %f.debug.data = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 1 store %swift.opaque* %1, %swift.opaque** %f.debug.data, align 8 %4 = bitcast i8* %0 to i64 (i64, %swift.refcounted*, %swift.error**)* %5 = bitcast %swift.opaque* %1 to %swift.refcounted* %6 = call swiftcc i64 %4(i64 44, %swift.refcounted* swiftself %5, %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) %7 = load %swift.error*, %swift.error** %swifterror, align 8 %8 = icmp ne %swift.error* %7, null br i1 %8, label %11, label %9 ; <label>:9: ; preds = %entry %10 = phi i64 [ %6, %entry ] ret void ; <label>:11: ; preds = %entry %12 = phi %swift.error* [ %7, %entry ] store %swift.error* null, %swift.error** %swifterror, align 8 call swiftcc void @swift_unexpectedError(%swift.error* %12, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @0, i64 0, i64 0), i64 7, i1 true, i64 52) unreachable } 40
ΤϥʔΛड͚ΔϝϞϦͷ༻ҙ define hidden swiftcc void @"$s1d14invokeThrowingyyS2iKXEF"(i8*, %swift.opaque*) #0 { entry:
%f.debug = alloca %swift.noescape.function, align 8 %2 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 16, i1 false) %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 %3 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %3) %f.debug.fn = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 0 store i8* %0, i8** %f.debug.fn, align 8 %f.debug.data = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 1 store %swift.opaque* %1, %swift.opaque** %f.debug.data, align 8 %4 = bitcast i8* %0 to i64 (i64, %swift.refcounted*, %swift.error**)* %5 = bitcast %swift.opaque* %1 to %swift.refcounted* %6 = call swiftcc i64 %4(i64 44, %swift.refcounted* swiftself %5, %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) %7 = load %swift.error*, %swift.error** %swifterror, align 8 %8 = icmp ne %swift.error* %7, null br i1 %8, label %11, label %9 ; <label>:9: ; preds = %entry %10 = phi i64 [ %6, %entry ] ret void ; <label>:11: ; preds = %entry %12 = phi %swift.error* [ %7, %entry ] store %swift.error* null, %swift.error** %swifterror, align 8 call swiftcc void @swift_unexpectedError(%swift.error* %12, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @0, i64 0, i64 0), i64 7, i1 true, i64 52) unreachable } 41
ͯ͠ݺͼग़͠ define hidden swiftcc void @"$s1d14invokeThrowingyyS2iKXEF"(i8*, %swift.opaque*) #0 { entry:
%f.debug = alloca %swift.noescape.function, align 8 %2 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 16, i1 false) %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 %3 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %3) %f.debug.fn = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 0 store i8* %0, i8** %f.debug.fn, align 8 %f.debug.data = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 1 store %swift.opaque* %1, %swift.opaque** %f.debug.data, align 8 %4 = bitcast i8* %0 to i64 (i64, %swift.refcounted*, %swift.error**)* %5 = bitcast %swift.opaque* %1 to %swift.refcounted* %6 = call swiftcc i64 %4(i64 44, %swift.refcounted* swiftself %5, %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) %7 = load %swift.error*, %swift.error** %swifterror, align 8 %8 = icmp ne %swift.error* %7, null br i1 %8, label %11, label %9 ; <label>:9: ; preds = %entry %10 = phi i64 [ %6, %entry ] ret void ; <label>:11: ; preds = %entry %12 = phi %swift.error* [ %7, %entry ] store %swift.error* null, %swift.error** %swifterror, align 8 call swiftcc void @swift_unexpectedError(%swift.error* %12, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @0, i64 0, i64 0), i64 7, i1 true, i64 52) unreachable } 42
ࢀরઌ͕null͔Ͳ͏͔ௐͯذ define hidden swiftcc void @"$s1d14invokeThrowingyyS2iKXEF"(i8*, %swift.opaque*) #0 { entry:
%f.debug = alloca %swift.noescape.function, align 8 %2 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 16, i1 false) %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 %3 = bitcast %swift.noescape.function* %f.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %3) %f.debug.fn = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 0 store i8* %0, i8** %f.debug.fn, align 8 %f.debug.data = getelementptr inbounds %swift.noescape.function, %swift.noescape.function* %f.debug, i32 0, i32 1 store %swift.opaque* %1, %swift.opaque** %f.debug.data, align 8 %4 = bitcast i8* %0 to i64 (i64, %swift.refcounted*, %swift.error**)* %5 = bitcast %swift.opaque* %1 to %swift.refcounted* %6 = call swiftcc i64 %4(i64 44, %swift.refcounted* swiftself %5, %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) %7 = load %swift.error*, %swift.error** %swifterror, align 8 %8 = icmp ne %swift.error* %7, null br i1 %8, label %11, label %9 ; <label>:9: ; preds = %entry %10 = phi i64 [ %6, %entry ] ret void ; <label>:11: ; preds = %entry %12 = phi %swift.error* [ %7, %entry ] store %swift.error* null, %swift.error** %swifterror, align 8 call swiftcc void @swift_unexpectedError(%swift.error* %12, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @0, i64 0, i64 0), i64 7, i1 true, i64 52) unreachable } 43
nothrowͱthrowsͷޓੑ nothrowͳؔͦͷ··throwsͳؔͱͯ͠ ͑Δ 44
͢ίʔυ func main6() { let a = { (x: Int)
-> Int in return x * 2 } invokeThrowing(a) } 45
͢ίʔυ define hidden swiftcc void @"$s1d5main6yyF"() #0 { entry: %a.debug
= alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %1) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64)* @"$s1d5main6yyFS2icfU_" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* null, %swift.refcounted** %a.debug.data, align 8 call swiftcc void @"$s1d14invokeThrowingyyS2iKXEF"( i8* bitcast (i64 (i64)* @"$s1d5main6yyFS2icfU_" to i8*), %swift.opaque* null) ret void } 46
ΫϩʔδϟຊମΛͦͷ··͢ define hidden swiftcc void @"$s1d5main6yyF"() #0 { entry: %a.debug
= alloca %swift.function, align 8 %0 = bitcast %swift.function* %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 16, i1 false) %1 = bitcast %swift.function* %a.debug to i8* call void @llvm.lifetime.start.p0i8(i64 16, i8* %1) %a.debug.fn = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 0 store i8* bitcast (i64 (i64)* @"$s1d5main6yyFS2icfU_" to i8*), i8** %a.debug.fn, align 8 %a.debug.data = getelementptr inbounds %swift.function, %swift.function* %a.debug, i32 0, i32 1 store %swift.refcounted* null, %swift.refcounted** %a.debug.data, align 8 call swiftcc void @"$s1d14invokeThrowingyyS2iKXEF"( i8* bitcast (i64 (i64)* @"$s1d5main6yyFS2icfU_" to i8*), %swift.opaque* null) ret void } 47
Ҿʹड͚ΒΕͳ͍ͣͷɺ ΤϥʔμϒϧϙΠϯλ͕͞ΕΔʂ ; invokeThrowingʹؔΛ͢ͱ͜Ζ call swiftcc void @"$s1d14invokeThrowingyyS2iKXEF"( i8* bitcast
(i64 (i64)* @"$s1d5main6yyFS2icfU_" to i8*), %swift.opaque* null) ; invokeThrowing͕ؔΛݺͼग़͢ͱ͜Ζ %6 = call swiftcc i64 %4( i64 44, %swift.refcounted* swiftself %5, %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) 48
swifterror swiftccͰΤϥʔΛड͚औΔͨΊͷμϒϧϙΠ ϯλҾʹswifterrorΛࢦఆ͢Δɻ͜Ε swiftselfಉ༷ʹઐ༻ͷϨδελΛ༻͢Δɻͦ ͷͨΊɺΤϥʔΛฦ͞ͳ͍ؔʹ͓͍ͯ୯ʹ͜ ΕΛແࢹ͢Δ͜ͱͰޓੑ͕ಘΒΕΔɻ 49
·ͱΊ Ωϟϓνϟ͕͋ΔͱthickؔʹͳΔ thinؔswiftselfʹΑΓthickؔͱޓੑ͕ ͋Δ throwsͳؔΤϥʔͷμϒϧϙΠϯλΛҾʹ ड͚Δ nothrowͳؔswifterrorʹΑΓthrowsͳؔ ͱޓੑ͕͋Δ 50