Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swiftの関数型の実行時表現

3781f49ea2c76d6ecf0c6cda46096d49?s=47 omochimetaru
December 17, 2018

 Swiftの関数型の実行時表現

3781f49ea2c76d6ecf0c6cda46096d49?s=128

omochimetaru

December 17, 2018
Tweet

Transcript

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

  2. 3छྨͷදݱ • thin: ͨͩͷؔ਺ϙΠϯλ • thick: ؔ਺ϙΠϯλ + ίϯςΩετϙΠϯλ •

    block: Objective-CͷϒϩοΫɻObjectiveCʹ ͓͚ΔΦϒδΣΫτϙΠϯλ 2
  3. thinؔ਺ ੜ੒ίʔυ func main1() { let a = { (x:

    Int) -> Int in return x * 2 } } 3
  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 } 4
  5. Ϋϩʔδϟຊମؔ਺ͷऔಘ 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
  6. Ϋϩʔδϟຊମؔ਺ 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
  7. ͦͷ··ͷγάωνϟ define internal swiftcc i64 @"$s1d5main1yyFS2icfU_"(i64) SwiftͰॻ͘ͳΒ (Int) -> Int

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

  9. ੜ੒ίʔυ func main2() { var t = 3 let a

    = { (x: Int) -> Int in t += x return t } } 9
  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 } 10
  11. Ϋϩʔδϟຊମؔ਺ͷऔಘ 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
  12. Ϋϩʔδϟຊମؔ਺ 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
  13. γάωνϟʹίϯςΩετϙΠϯλΛؚΉ define internal swiftcc i64 @"$s1d5main2yyFS2icfU_Tf0ns_nTA"( i64, %swift.refcounted* swiftself) SwiftͰॻ͘ͳΒ

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

    14
  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 } 15
  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 } 16
  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 } 17
  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 } 18
  19. ίϯςΩετϙΠϯλΛ౉ͯ͠ݺͼग़͠ 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
  20. ड͚౉͠ίʔυ func main3() { var t = 3 let a

    = { (x: Int) -> Int in t += x return t } invoke(a) } 20
  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 } 21
  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 } 22
  23. Ωϟϓνϟม਺༻ͷϝϞϦࢀর 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
  24. 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
  25. ؔ਺ຊମͱҰॹʹ౉͢ 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
  26. thinͱthickͷޓ׵ੑ thinؔ਺͸thickؔ਺ͱͯ͠ѻ͑Δ 26

  27. ड͚౉͠ίʔυ func main4() { let a = { (x: Int)

    -> Int in return x * 2 } invoke(a) } 27
  28. ड͚౉͠ίʔυ 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
  29. 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
  30. Ҿ਺ʹड͚ΒΕͳ͍͸ͣͷɺ ίϯςΩετϙΠϯλ͕౉͞ΕΔʂ ; 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
  31. swiftcc Swift༻ͷݺͼग़͠ن໿(Calling Convention) swiftself: ίϯςΩετϙΠϯλଐੑ %6 = call swiftcc i64

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

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

  34. ϝιουੜ੒ίʔυ 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
  35. throwsͳؔ਺ ੜ੒ίʔυ extension Int : Error {} func main5() {

    let a = { (x: Int) -> Int in throw x } } 35
  36. ੜ੒͞ΕͨΫϩʔδϟ 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
  37. γάωνϟ define internal swiftcc i64 @"$s1d5main5yyFS2iKcfU_"(i64, %swift.refcounted* swiftself, %swift.error** noalias

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

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

    f(44) } 39
  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 } 40
  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 } 41
  42. ౉ͯ͠ݺͼग़͠ 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
  43. ࢀরઌ͕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
  44. nothrowͱthrowsͷޓ׵ੑ nothrowͳؔ਺͸ͦͷ··throwsͳؔ਺ͱͯ͠࢖ ͑Δ 44

  45. ౉͢ίʔυ func main6() { let a = { (x: Int)

    -> Int in return x * 2 } invokeThrowing(a) } 45
  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 } 46
  47. ΫϩʔδϟຊମΛͦͷ··౉͢ 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
  48. Ҿ਺ʹड͚ΒΕͳ͍͸ͣͷɺ ΤϥʔμϒϧϙΠϯλ͕౉͞ΕΔʂ ; 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
  49. swifterror swiftccͰ͸ΤϥʔΛड͚औΔͨΊͷμϒϧϙΠ ϯλҾ਺ʹswifterrorΛࢦఆ͢Δɻ͜Ε͸ swiftselfಉ༷ʹઐ༻ͷϨδελΛ࢖༻͢Δɻͦ ͷͨΊɺΤϥʔΛฦ͞ͳ͍ؔ਺ʹ͓͍ͯ͸୯ʹ͜ ΕΛແࢹ͢Δ͜ͱͰޓ׵ੑ͕ಘΒΕΔɻ 49

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