Slide 1

Slide 1 text

Swiftͷؔ਺ܕͷ ࣮ߦ࣌දݱ Θ͍Θ͍swiftc omochimetaru 1

Slide 2

Slide 2 text

3छྨͷදݱ • thin: ͨͩͷؔ਺ϙΠϯλ • thick: ؔ਺ϙΠϯλ + ίϯςΩετϙΠϯλ • block: Objective-CͷϒϩοΫɻObjectiveCʹ ͓͚ΔΦϒδΣΫτϙΠϯλ 2

Slide 3

Slide 3 text

thinؔ਺ ੜ੒ίʔυ func main1() { let a = { (x: Int) -> Int in return x * 2 } } 3

Slide 4

Slide 4 text

ੜ੒ίʔυ 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

Slide 5

Slide 5 text

Ϋϩʔδϟຊମؔ਺ͷऔಘ 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

Slide 6

Slide 6 text

Ϋϩʔδϟຊମؔ਺ 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 ; :5: ; preds = %entry ret i64 %3 ; :6: ; preds = %entry call void @llvm.trap() unreachable } 6

Slide 7

Slide 7 text

ͦͷ··ͷγάωνϟ define internal swiftcc i64 @"$s1d5main1yyFS2icfU_"(i64) SwiftͰॻ͘ͳΒ (Int) -> Int 7

Slide 8

Slide 8 text

thickؔ਺ thickؔ਺͸Ωϟϓνϟ͕͋Δͱੜ੒͞ΕΔɻ Ωϟϓνϟͨ͠ϝϞϦۭؒΛؔ਺ͱҰॹʹऔΓճ ͢ɻ 8

Slide 9

Slide 9 text

ੜ੒ίʔυ func main2() { var t = 3 let a = { (x: Int) -> Int in t += x return t } } 9

Slide 10

Slide 10 text

ੜ੒ίʔυ 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

Slide 11

Slide 11 text

Ϋϩʔδϟຊମؔ਺ͷऔಘ 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

Slide 12

Slide 12 text

Ϋϩʔδϟຊମؔ਺ 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

Slide 13

Slide 13 text

γάωνϟʹίϯςΩετϙΠϯλΛؚΉ define internal swiftcc i64 @"$s1d5main2yyFS2icfU_Tf0ns_nTA"( i64, %swift.refcounted* swiftself) SwiftͰॻ͘ͳΒ (Int, Context) -> Int 13

Slide 14

Slide 14 text

ݺͼग़͠ίʔυ func invoke(_ f: (Int) -> Int) { f(33) } 14

Slide 15

Slide 15 text

ݺͼग़͠ίʔυ 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

Slide 16

Slide 16 text

ؔ਺ϙΠϯλͱίϯςΩετϙΠϯλ 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

Slide 17

Slide 17 text

ؔ਺ϙΠϯλͷऔΓग़͠ 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

Slide 18

Slide 18 text

ίϯςΩετϙΠϯλͷऔΓग़͠ 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

Slide 19

Slide 19 text

ίϯςΩετϙΠϯλΛ౉ͯ͠ݺͼग़͠ 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

Slide 20

Slide 20 text

ड͚౉͠ίʔυ func main3() { var t = 3 let a = { (x: Int) -> Int in t += x return t } invoke(a) } 20

Slide 21

Slide 21 text

ड͚౉͠ίʔυ 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

Slide 22

Slide 22 text

ΩϟϓνϟΦϒδΣΫτͷϝϞϦ֬อ 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

Slide 23

Slide 23 text

Ωϟϓνϟม਺༻ͷϝϞϦࢀর 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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

ؔ਺ຊମͱҰॹʹ౉͢ 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

Slide 26

Slide 26 text

thinͱthickͷޓ׵ੑ thinؔ਺͸thickؔ਺ͱͯ͠ѻ͑Δ 26

Slide 27

Slide 27 text

ड͚౉͠ίʔυ func main4() { let a = { (x: Int) -> Int in return x * 2 } invoke(a) } 27

Slide 28

Slide 28 text

ड͚౉͠ίʔυ 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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

Ҿ਺ʹड͚ΒΕͳ͍͸ͣͷɺ ίϯςΩετϙΠϯλ͕౉͞ΕΔʂ ; 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

Slide 31

Slide 31 text

swiftcc Swift༻ͷݺͼग़͠ن໿(Calling Convention) swiftself: ίϯςΩετϙΠϯλଐੑ %6 = call swiftcc i64 %4(i64 33, %swift.refcounted* swiftself %5) 31

Slide 32

Slide 32 text

swiftselfࢦఆ͞ΕͨҾ਺͸ઐ༻ͷϨδελͰ౉ ͞ΕΔɻͭ·Γɺଞͷ௨ৗͷҾ਺͸͜ͷϨδελ ʹ͸ׂΓ౰ͯΒΕͳ͍ɻΑͬͯɺίϯςΩετϙ Πϯλ͕ෆཁͳؔ਺Ͱ͸͜ͷϨδελΛಡ·ͳ͍ ͱ͍͏͚ͩͰޓ׵ੑ͕ಘΒΕΔɻ https://github.com/apple/swift/blob/master/ docs/CallingConvention.rst 32

Slide 33

Slide 33 text

ϝιουͱswiftself ϝιουʹselfΛҾ͖౉͢ͱ͖ʹ΋swiftself͕ ࢖ΘΕΔ 33

Slide 34

Slide 34 text

ϝιουੜ੒ίʔυ 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

Slide 35

Slide 35 text

throwsͳؔ਺ ੜ੒ίʔυ extension Int : Error {} func main5() { let a = { (x: Int) -> Int in throw x } } 35

Slide 36

Slide 36 text

ੜ੒͞ΕͨΫϩʔδϟ 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

Slide 37

Slide 37 text

γάωνϟ define internal swiftcc i64 @"$s1d5main5yyFS2iKcfU_"(i64, %swift.refcounted* swiftself, %swift.error** noalias nocapture swifterror dereferenceable(8)) SwiftͰॻ͘ͳΒ (Int, Context, inout Error) -> Int 37

Slide 38

Slide 38 text

throwsͳؔ਺͸%swift.errorͷμϒϧϙΠϯλ ΛҾ਺ʹड͚ɺͦ͜΁ͷॻ͖ࠐΈͱͯ͠ΤϥʔΛ ૹग़͢Δɻ͜ͷҾ਺͸swifterrorଐੑΛ༩͑Β ΕΔɻswifterrorͷҾ਺͕͋Δؔ਺͸ɺ swiftselfͷҾ਺΋ඞਢͱ͞Ε͍ͯΔɻͦͷͨ Ίɺ͜ͷΫϩʔδϟ͸ΩϟϓνϟΛ͍ͯ͠ͳ͍͕ swiftselfΛҾ਺ʹ͍࣋ͬͯΔɻ 38

Slide 39

Slide 39 text

ݺͼग़͠ଆ func invokeThrowing(_ f: (Int) throws -> Int) { try! f(44) } 39

Slide 40

Slide 40 text

ݺͼग़͠ଆ 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 ; :9: ; preds = %entry %10 = phi i64 [ %6, %entry ] ret void ; :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

Slide 41

Slide 41 text

ΤϥʔΛड͚ΔϝϞϦͷ༻ҙ 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 ; :9: ; preds = %entry %10 = phi i64 [ %6, %entry ] ret void ; :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

Slide 42

Slide 42 text

౉ͯ͠ݺͼग़͠ 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 ; :9: ; preds = %entry %10 = phi i64 [ %6, %entry ] ret void ; :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

Slide 43

Slide 43 text

ࢀরઌ͕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 ; :9: ; preds = %entry %10 = phi i64 [ %6, %entry ] ret void ; :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

Slide 44

Slide 44 text

nothrowͱthrowsͷޓ׵ੑ nothrowͳؔ਺͸ͦͷ··throwsͳؔ਺ͱͯ͠࢖ ͑Δ 44

Slide 45

Slide 45 text

౉͢ίʔυ func main6() { let a = { (x: Int) -> Int in return x * 2 } invokeThrowing(a) } 45

Slide 46

Slide 46 text

౉͢ίʔυ 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

Slide 47

Slide 47 text

ΫϩʔδϟຊମΛͦͷ··౉͢ 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

Slide 48

Slide 48 text

Ҿ਺ʹड͚ΒΕͳ͍͸ͣͷɺ ΤϥʔμϒϧϙΠϯλ͕౉͞ΕΔʂ ; 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

Slide 49

Slide 49 text

swifterror swiftccͰ͸ΤϥʔΛड͚औΔͨΊͷμϒϧϙΠ ϯλҾ਺ʹswifterrorΛࢦఆ͢Δɻ͜Ε͸ swiftselfಉ༷ʹઐ༻ͷϨδελΛ࢖༻͢Δɻͦ ͷͨΊɺΤϥʔΛฦ͞ͳ͍ؔ਺ʹ͓͍ͯ͸୯ʹ͜ ΕΛແࢹ͢Δ͜ͱͰޓ׵ੑ͕ಘΒΕΔɻ 49

Slide 50

Slide 50 text

·ͱΊ Ωϟϓνϟ͕͋Δͱthickؔ਺ʹͳΔ thinؔ਺͸swiftselfʹΑΓthickؔ਺ͱޓ׵ੑ͕ ͋Δ throwsͳؔ਺͸ΤϥʔͷμϒϧϙΠϯλΛҾ਺ʹ ड͚Δ nothrowͳؔ਺͸swifterrorʹΑΓthrowsͳؔ਺ ͱޓ׵ੑ͕͋Δ 50