SILを読もう

3781f49ea2c76d6ecf0c6cda46096d49?s=47 omochimetaru
November 16, 2019

 SILを読もう

3781f49ea2c76d6ecf0c6cda46096d49?s=128

omochimetaru

November 16, 2019
Tweet

Transcript

  1. SILΛಡ΋͏ @omochimetaru SwiftcKaigi #1 1

  2. ࣗݾ঺հ • omochimetaru • ΞΠίϯˠ • Θ͍Θ͍swiftcͰ͠͹͠͹ ొஃ 2

  3. SIL1 • Swift intermediate language • SILίʔυʹ͸SwiftίʔυΑΓ΋۩ମతͳڍಈ ͕ॻ͔Ε͍ͯΔ 1 https://github.com/apple/swift/blob/master/docs/SIL.rst

    3
  4. ۩ମతͳڍಈͷྫ • ҉໧ͷܕม׵ • ࢀরΧ΢ϯτͷ૿ݮ • ϝιουͷݺͼग़͠ 4

  5. ҉໧ͷܕม׵ 5

  6. func intToIntOptional(x: Int) -> Int? { return x } •

    Swiftతʹ͸ͦͷ··return͍ͯ͠Δ͕ɺCPUʹ ͱͬͯ͸Int͔ΒInt?΁ͷม׵Λ͍ͯ͠Δɻ 6
  7. • swiftcίϚϯυͰSILΛग़ྗ͢Δ $ swiftc -emit-sil -parse-as-library code01.swift 7

  8. sil_stage canonical import Builtin import Swift import SwiftShims func intToIntOptional(x:

    Int) -> Int? // intToIntOptional(x:) sil hidden @$s6code0116intToIntOptional1xSiSgSi_tF : $@convention(thin) (Int) -> Optional<Int> { // %0 // users: %2, %1 bb0(%0 : $Int): debug_value %0 : $Int, let, name "x", argno 1 // id: %1 %2 = enum $Optional<Int>, #Optional.some!enumelt.1, %0 : $Int // user: %3 return %2 : $Optional<Int> // id: %3 } // end sil function '$s6code0116intToIntOptional1xSiSgSi_tF' 8
  9. Mangling2 // module: code01 func intToIntOptional(x: Int) -> Int? ↓

    $s6code0116intToIntOptional1xSiSgSi_tF 2 https://github.com/apple/swift/blob/master/docs/ABI/Mangling.rst 9
  10. • Ϟδϡʔϧ໊΍ܕ໊ΛࠞͥࠐΜͩ(mangle)໊લ Λ࡞Δ • swift demangleίϚϯυͰల։Ͱ͖Δ $ swift demangle '$s6code0116intToIntOptional1xSiSgSi_tF'

    $s6code0116intToIntOptional1xSiSgSi_tF ---> code01.intToIntOptional(x: Swift.Int) -> Swift.Int? 10
  11. Demangling $s6code0116intToIntOptional1xSiSgSi_tF $s: Swift5 6: 6จࣈͷ୯ޠ code01 16: 16จࣈͷ୯ޠ intToIntOptional

    1: 1จࣈͷ୯ޠ x Si: Int Sg: Optional Si: Int _: Ϧετͷ۠੾Γ t: λϓϧ F: ؔ਺ 11
  12. // intToIntOptional(x:) sil hidden @$s6code0116intToIntOptional1xSiSgSi_tF : $@convention(thin) (Int) -> Optional<Int>

    { // %0 // users: %2, %1 bb0(%0 : $Int): debug_value %0 : $Int, let, name "x", argno 1 // id: %1 %2 = enum $Optional<Int>, #Optional.some!enumelt.1, %0 : $Int // user: %3 return %2 : $Optional<Int> // id: %3 } // end sil function '$s6code0116intToIntOptional1xSiSgSi_tF' 12
  13. // intToIntOptional(x:) sil hidden @$s6code0116intToIntOptional1xSiSgSi_tF : $@convention(thin) (Int) -> Optional<Int>

    { // %0 // users: %2, %1 bb0(%0 : $Int): debug_value %0 : $Int, let, name "x", argno 1 // id: %1 %2 = enum $Optional<Int>, #Optional.some!enumelt.1, %0 : $Int // user: %3 return %2 : $Optional<Int> // id: %3 } // end sil function '$s6code0116intToIntOptional1xSiSgSi_tF' 13
  14. %2 = enum $Optional<Int>, #Optional.some!enumelt.1, %0 : $Int // user:

    %3 %2 =: ݁ՌΛ%2ʹ୅ೖ enum: enumͷ஋Λߏங $Optional<Int>: ܕ͸Optional<Int> $Optional.some!enumelt.1: case͸some %0: associated value͸%0 : $Int: $0ͷܕ͸Int //: ίϝϯτ user: %3: ݁Ռ͸໋ྩ%3Ͱ࢖͏ 14
  15. ࢀরΧ΢ϯτͷ૿ݮ 15

  16. ࢀরΧ΢ϯτ • Swift͸ΫϥεΠϯελϯεͷϝϞϦ؅ཧʹࢀর Χ΢ϯτΛ࢖͏ 16

  17. • ॳظ஋1 • 0ʹͳͬͨΒղ์ • ม਺୅ೖ: ݹ͍Πϯελϯε͸release(-1) • ม਺ഁغ: ॴ࣋͢ΔΠϯελϯεΛrelease

    • ؔ਺ݺͼग़͠: ࣮Ҿ਺Λretain(+1), ݺͼग़͠ޙ ʹrelease 17
  18. class Cat {} func useCat(_ cat: Cat) { } func

    changeCat(_ cat: Cat) -> Cat { return Cat() } func main() { var cat = Cat() useCat(cat) cat = changeCat(cat) } 18
  19. func main() { // ॳظԽ var cat = Cat() //

    ݺͼग़͠લʹҾ਺ͷretain useCat(cat) // ݺͼग़͠ޙʹҾ਺ͷrelease // ݺͼग़͠લʹҾ਺ͷretain cat = changeCat(cat) // ݺͼग़͠ޙʹҾ਺ͷrelease // ݹ͍஋Λrelease // ม਺ͷ஋Λrelease } 19
  20. // main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' 20
  21. // main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • ม਺catΛੜ੒(%0) 21
  22. // main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • ม਺cat(%0)Λղ์ 22
  23. // main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • Cat.initͷݺͼग़͠(%3)ɺม਺cat(%0)ʹอଘ 23
  24. // main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • useCatͷݺͼग़͠Ͱ%3Λ౉͢ 24
  25. // main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • useCatͷݺͼग़͠લޙͰ%3Λretain, release 25
  26. // main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • changeCatͷݺͼग़͠(%15)ɺҾ਺ʹ%3 26
  27. // main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • changeCatͷݺͼग़͠લޙͰ%3Λretain, release 27
  28. // main() sil hidden @$s6code024mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = alloc_stack $Cat, var, name "cat" // users: %4, %22, %21, %5, %11, %17 %1 = metatype $@thick Cat.Type // user: %3 // function_ref Cat.__allocating_init() %2 = function_ref @$s6code023CatCACycfC : $@convention(method) (@thick Cat.Type) -> @owned Cat // user: %3 %3 = apply %2(%1) : $@convention(method) (@thick Cat.Type) -> @owned Cat // users: %19, %12, %15, %16, %6, %9, %10, %4 store %3 to %0 : $*Cat // id: %4 %5 = begin_access [read] [static] %0 : $*Cat // user: %7 strong_retain %3 : $Cat // id: %6 end_access %5 : $*Cat // id: %7 // function_ref useCat(_:) %8 = function_ref @$s6code026useCatyyAA0C0CF : $@convention(thin) (@guaranteed Cat) -> () // user: %9 %9 = apply %8(%3) : $@convention(thin) (@guaranteed Cat) -> () strong_release %3 : $Cat // id: %10 %11 = begin_access [read] [static] %0 : $*Cat // user: %13 strong_retain %3 : $Cat // id: %12 end_access %11 : $*Cat // id: %13 // function_ref changeCat(_:) %14 = function_ref @$s6code029changeCatyAA0C0CADF : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %15 %15 = apply %14(%3) : $@convention(thin) (@guaranteed Cat) -> @owned Cat // user: %18 strong_release %3 : $Cat // id: %16 %17 = begin_access [modify] [static] %0 : $*Cat // users: %18, %20 store %15 to %17 : $*Cat // id: %18 strong_release %3 : $Cat // id: %19 end_access %17 : $*Cat // id: %20 destroy_addr %0 : $*Cat // id: %21 dealloc_stack %0 : $*Cat // id: %22 %23 = tuple () // user: %24 return %23 : $() // id: %24 } // end sil function '$s6code024mainyyF' • changeCatͷ݁Ռ(%15)Λม਺cat(%17=%0)ʹ୅ೖɺ ݹ͍஋(%3)Λrelease 28
  29. ϝιουݺͼग़͠ 29

  30. ϓϩτίϧͷσϑΥϧτ࣮૷ͱΫϥε ܧঝͷؔ܎͸΍΍͍͜͠ • Swift Forum: Default Protocol Implementation Inheritance Behaviour

    - The current situation and what/if anything should be done about it 3 2019/08/20 3 https://forums.swift.org/t/default-protocol-implementation-inheritance-behaviour-the-current- situation-and-what-if-anything-should-be-done-about-it/28049 30
  31. 31

  32. • ఆظతʹ۷Γฦ͞ΕΔ࿩୊ • ͜ͷ౤ߘͰ΋Πγϡʔνέοτ4 2015/12/7 ΁ ͷݴٴ͋Γ 4 https://bugs.swift.org/browse/SR-103 32

  33. 33

  34. protocol P { func f() } extension P { func

    f() { print("P.f") } } class A: P { func f() { print("A.f") } } class B: A { override func f() { print("B.f") } } class C: P { } class D: C { func f() { print("D.f") } } func main() { A().f() // A.f B().f() // B.f (B() as A).f() // B.f C().f() // P.f D().f() // D.f (D() as C).f() // P.f } main() 34
  35. • B͸AΛܧঝ͍ͯ͠Δͷ͔ͩΒɺBͷfΛͦͷ· ·ݺΜͰ΋ɺAʹΞοϓΩϟετ͔ͯ͠ΒݺΜ Ͱ΋ಉ͡ ! • D͸CΛܧঝ͍ͯ͠ΔͷʹɺDͷfΛͦͷ··ݺ ͿͷͱɺCʹΞοϓΩϟετ͔ͯ͠ΒݺͿͷͰ ݁Ռ͕ҧ͏ "

    35
  36. ܗࣜతͳճ౴ • A.fͱB.f͸Ϋϥεϝιουݺͼग़͠ͳͷͰɺ ΦʔόʔϥΠυ͞Ε࣮ͨ૷͕ݺ͹ΕΔ • C.f͸witnessϝιουݺͼग़͠ɺD.f͸Ϋϥεϝ ιουݺͼग़͠ͳͷͰɺΦʔόʔϥΠυؔ܎͸ ͳ͍ 36

  37. Swiftͷ2ͭͷϝιουݺͼग़͠ • Ϋϥεϝιουݺͼग़͠: ͋ΔΫϥεʹରԠ͢ Δvtable͔ΒϝιουΛҾ͘ • witnessϝιουݺͼग़͠: ͋Δϓϩτίϧʹର Ԡ͢Δwitness table͔ΒϝιουΛҾ͘

    37
  38. ࣮૷͞Εͨؔ਺6ͭ // P.f() sil hidden @$s6code031PPAAE1fyyF : $@convention(method) <Self where

    Self : P> (@in_guaranteed Self) -> () { ... } // A.f() sil hidden @$s6code031AC1fyyF : $@convention(method) (@guaranteed A) -> () { ... } // protocol witness for P.f() in conformance A sil private [transparent] [thunk] @$s6code031ACAA1PA2aDP1fyyFTW : $@convention(witness_method: P) (@in_guaranteed A) -> () { ... } // B.f() sil hidden @$s6code031BC1fyyF : $@convention(method) (@guaranteed B) -> () { ... } // protocol witness for P.f() in conformance C sil private [transparent] [thunk] @$s6code031CCAA1PA2aDP1fyyFTW : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : C> (@in_guaranteed τ_0_0) -> () { ... } // D.f() sil hidden @$s6code031DC1fyyF : $@convention(method) (@guaranteed D) -> () { ... } 38
  39. ੜ੒͞Εͨςʔϒϧ6ͭ sil_vtable A { #A.f!1: (A) -> () -> ()

    : @$s6code031AC1fyyF // A.f() #A.init!allocator.1: (A.Type) -> () -> A : @$s6code031ACACycfC // A.__allocating_init() #A.deinit!deallocator.1: @$s6code031ACfD // A.__deallocating_deinit } sil_vtable B { #A.f!1: (A) -> () -> () : @$s6code031BC1fyyF [override] // B.f() #A.init!allocator.1: (A.Type) -> () -> A : @$s6code031BCACycfC [override] // B.__allocating_init() #B.deinit!deallocator.1: @$s6code031BCfD // B.__deallocating_deinit } sil_vtable C { #C.init!allocator.1: (C.Type) -> () -> C : @$s6code031CCACycfC // C.__allocating_init() #C.deinit!deallocator.1: @$s6code031CCfD // C.__deallocating_deinit } sil_vtable D { #C.init!allocator.1: (C.Type) -> () -> C : @$s6code031DCACycfC [override] // D.__allocating_init() #D.f!1: (D) -> () -> () : @$s6code031DC1fyyF // D.f() #D.deinit!deallocator.1: @$s6code031DCfD // D.__deallocating_deinit } sil_witness_table hidden A: P module code03 { method #P.f!1: <Self where Self : P> (Self) -> () -> () : @$s6code031ACAA1PA2aDP1fyyFTW // protocol witness for P.f() in conformance A } sil_witness_table hidden C: P module code03 { method #P.f!1: <Self where Self : P> (Self) -> () -> () : @$s6code031CCAA1PA2aDP1fyyFTW // protocol witness for P.f() in conformance C } 39
  40. // main() sil hidden @$s6code034mainyyF : $@convention(thin) () -> ()

    { bb0: %0 = metatype $@thick A.Type // user: %2 // function_ref A.__allocating_init() %1 = function_ref @$s6code031ACACycfC : $@convention(method) (@thick A.Type) -> @owned A // user: %2 %2 = apply %1(%0) : $@convention(method) (@thick A.Type) -> @owned A // users: %5, %4, %3 %3 = class_method %2 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %4 %4 = apply %3(%2) : $@convention(method) (@guaranteed A) -> () strong_release %2 : $A // id: %5 %6 = metatype $@thick B.Type // user: %8 // function_ref B.__allocating_init() %7 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %8 %8 = apply %7(%6) : $@convention(method) (@thick B.Type) -> @owned B // users: %11, %10, %9 %9 = class_method %8 : $B, #B.f!1 : (B) -> () -> (), $@convention(method) (@guaranteed B) -> () // user: %10 %10 = apply %9(%8) : $@convention(method) (@guaranteed B) -> () strong_release %8 : $B // id: %11 %12 = metatype $@thick B.Type // user: %14 // function_ref B.__allocating_init() %13 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %14 %14 = apply %13(%12) : $@convention(method) (@thick B.Type) -> @owned B // user: %15 %15 = upcast %14 : $B to $A // users: %18, %17, %16 %16 = class_method %15 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %17 %17 = apply %16(%15) : $@convention(method) (@guaranteed A) -> () strong_release %15 : $A // id: %18 %19 = metatype $@thick C.Type // user: %21 // function_ref C.__allocating_init() %20 = function_ref @$s6code031CCACycfC : $@convention(method) (@thick C.Type) -> @owned C // user: %21 %21 = apply %20(%19) : $@convention(method) (@thick C.Type) -> @owned C // user: %23 %22 = alloc_stack $C // users: %23, %27, %26, %25 store %21 to %22 : $*C // id: %23 // function_ref P.f() %24 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %25 %25 = apply %24<C>(%22) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %22 : $*C // id: %26 dealloc_stack %22 : $*C // id: %27 %28 = metatype $@thick D.Type // user: %30 // function_ref D.__allocating_init() %29 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %30 %30 = apply %29(%28) : $@convention(method) (@thick D.Type) -> @owned D // users: %33, %32, %31 %31 = class_method %30 : $D, #D.f!1 : (D) -> () -> (), $@convention(method) (@guaranteed D) -> () // user: %32 %32 = apply %31(%30) : $@convention(method) (@guaranteed D) -> () strong_release %30 : $D // id: %33 %34 = metatype $@thick D.Type // user: %36 // function_ref D.__allocating_init() %35 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %36 %36 = apply %35(%34) : $@convention(method) (@thick D.Type) -> @owned D // user: %37 %37 = upcast %36 : $D to $C // user: %39 %38 = alloc_stack $C // users: %39, %43, %42, %41 store %37 to %38 : $*C // id: %39 // function_ref P.f() %40 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %41 %41 = apply %40<(C)>(%38) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %38 : $*C // id: %42 dealloc_stack %38 : $*C // id: %43 %44 = tuple () // user: %45 return %44 : $() // id: %45 } // end sil function '$s6code034mainyyF' 40
  41. ؔ਺ͷ಺༁ • P.f(): $s6code031PPAAE1fyyF • A.f(): $s6code031AC1fyyF • protocol witness

    for P.f() in conformance A: $s6code031ACAA1PA2aDP1fyyFTW • B.f(): $s6code031BC1fyyF • protocol witness for P.f() in conformance C: $s6code031CCAA1PA2aDP1fyyFTW • D.f(): $s6code031DC1fyyF 41
  42. • A.fʹؔͯ͠͸Ϋϥεϝιουͱɺwitnessϝ ιουͷ2͕ͭੜ੒͞Ε͍ͯΔ class A: P { func f() {

    print("A.f") } } 42
  43. • C.fʹؔͯ͠͸witnessϝιου͚͕ͩੜ੒͞Ε ͍ͯͯɺΫϥεϝιου͸ͳ͍ class C: P { } 43

  44. A.fͷwitnessϝιουͷ࣮૷ // protocol witness for P.f() in conformance A sil

    private [transparent] [thunk] @$s6code031ACAA1PA2aDP1fyyFTW : $@convention(witness_method: P) (@in_guaranteed A) -> () { // %0 // user: %1 bb0(%0 : $*A): %1 = load %0 : $*A // users: %2, %3 %2 = class_method %1 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %3 %3 = apply %2(%1) : $@convention(method) (@guaranteed A) -> () %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function '$s6code031ACAA1PA2aDP1fyyFTW' 44
  45. // protocol witness for P.f() in conformance A sil private

    [transparent] [thunk] @$s6code031ACAA1PA2aDP1fyyFTW : $@convention(witness_method: P) (@in_guaranteed A) -> () { // %0 // user: %1 bb0(%0 : $*A): %1 = load %0 : $*A // users: %2, %3 %2 = class_method %1 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %3 %3 = apply %2(%1) : $@convention(method) (@guaranteed A) -> () %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function '$s6code031ACAA1PA2aDP1fyyFTW' • class_method໋ྩͰvtable͔Βؔ਺ΛऔΓग़ ͠ɺݺͼग़͢ɻ 45
  46. C.fͷwitnessϝιουͷ࣮૷ // protocol witness for P.f() in conformance C sil

    private [transparent] [thunk] @$s6code031CCAA1PA2aDP1fyyFTW : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : C> (@in_guaranteed τ_0_0) -> () { // %0 // user: %2 bb0(%0 : $*τ_0_0): // function_ref P.f() %1 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %2 %2 = apply %1<τ_0_0>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () %3 = tuple () // user: %4 return %3 : $() // id: %4 } // end sil function '$s6code031CCAA1PA2aDP1fyyFTW' 46
  47. // protocol witness for P.f() in conformance C sil private

    [transparent] [thunk] @$s6code031CCAA1PA2aDP1fyyFTW : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : C> (@in_guaranteed τ_0_0) -> () { // %0 // user: %2 bb0(%0 : $*τ_0_0): // function_ref P.f() %1 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %2 %2 = apply %1<τ_0_0>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () %3 = tuple () // user: %4 return %3 : $() // id: %4 } // end sil function '$s6code031CCAA1PA2aDP1fyyFTW' • P.fͷσϑΥϧτ࣮૷Λݺͼग़͢ɻvtable͸ࢀর ͠ͳ͍ɻ 47
  48. AͱBͷvtable sil_vtable A { #A.f!1: (A) -> () -> ()

    : @$s6code031AC1fyyF // A.f() #A.init!allocator.1: (A.Type) -> () -> A : @$s6code031ACACycfC // A.__allocating_init() #A.deinit!deallocator.1: @$s6code031ACfD // A.__deallocating_deinit } sil_vtable B { #A.f!1: (A) -> () -> () : @$s6code031BC1fyyF [override] // B.f() #A.init!allocator.1: (A.Type) -> () -> A : @$s6code031BCACycfC [override] // B.__allocating_init() #B.deinit!deallocator.1: @$s6code031BCfD // B.__deallocating_deinit } • BͷςʔϒϧͷA.fͷཝ͕B.f() ($s6code031BC1fyyF)ͰΦʔόϥΠυ͞Ε͍ͯ Δ 48
  49. CͱDͷvtable sil_vtable C { #C.init!allocator.1: (C.Type) -> () -> C

    : @$s6code031CCACycfC // C.__allocating_init() #C.deinit!deallocator.1: @$s6code031CCfD // C.__deallocating_deinit } sil_vtable D { #C.init!allocator.1: (C.Type) -> () -> C : @$s6code031DCACycfC [override] // D.__allocating_init() #D.f!1: (D) -> () -> () : @$s6code031DC1fyyF // D.f() #D.deinit!deallocator.1: @$s6code031DCfD // D.__deallocating_deinit } • CͷςʔϒϧʹC.fͷཝ͕ͳ͍ɻDͷςʔϒϧͰ ৽نͷD.fͱͯ͠ొ࿥͞Ε͍ͯΔɻ 49
  50. AͱCͷwitness table sil_witness_table hidden A: P module code03 { method

    #P.f!1: <Self where Self : P> (Self) -> () -> () : @$s6code031ACAA1PA2aDP1fyyFTW // protocol witness for P.f() in conformance A } sil_witness_table hidden C: P module code03 { method #P.f!1: <Self where Self : P> (Self) -> () -> () : @$s6code031CCAA1PA2aDP1fyyFTW // protocol witness for P.f() in conformance C } • AͱCͷwitnessϝιου͕ͦΕͧΕొ࿥͞Εͯ ͍Δɻ • BͱDͷwitness table͸ͳ͍ɻ 50
  51. A().f()ͷݺͼग़͠ %0 = metatype $@thick A.Type // user: %2 //

    function_ref A.__allocating_init() %1 = function_ref @$s6code031ACACycfC : $@convention(method) (@thick A.Type) -> @owned A // user: %2 %2 = apply %1(%0) : $@convention(method) (@thick A.Type) -> @owned A // users: %5, %4, %3 %3 = class_method %2 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %4 %4 = apply %3(%2) : $@convention(method) (@guaranteed A) -> () strong_release %2 : $A // id: %5 51
  52. %0 = metatype $@thick A.Type // user: %2 // function_ref

    A.__allocating_init() %1 = function_ref @$s6code031ACACycfC : $@convention(method) (@thick A.Type) -> @owned A // user: %2 %2 = apply %1(%0) : $@convention(method) (@thick A.Type) -> @owned A // users: %5, %4, %3 %3 = class_method %2 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %4 %4 = apply %3(%2) : $@convention(method) (@guaranteed A) -> () strong_release %2 : $A // id: %5 • class_method໋ྩͰA.fͷΤϯτϦΛऔΓग़ ͯ͠ݺͼग़͠ 52
  53. B().f()ͷݺͼग़͠ %6 = metatype $@thick B.Type // user: %8 //

    function_ref B.__allocating_init() %7 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %8 %8 = apply %7(%6) : $@convention(method) (@thick B.Type) -> @owned B // users: %11, %10, %9 %9 = class_method %8 : $B, #B.f!1 : (B) -> () -> (), $@convention(method) (@guaranteed B) -> () // user: %10 %10 = apply %9(%8) : $@convention(method) (@guaranteed B) -> () strong_release %8 : $B // id: %11 53
  54. %6 = metatype $@thick B.Type // user: %8 // function_ref

    B.__allocating_init() %7 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %8 %8 = apply %7(%6) : $@convention(method) (@thick B.Type) -> @owned B // users: %11, %10, %9 %9 = class_method %8 : $B, #B.f!1 : (B) -> () -> (), $@convention(method) (@guaranteed B) -> () // user: %10 %10 = apply %9(%8) : $@convention(method) (@guaranteed B) -> () strong_release %8 : $B // id: %11 • class_method໋ྩͰB.fͷΤϯτϦΛऔΓग़ ͯ͠ݺͼग़͠ • A.fͰ͸ͳ͍ͷͰಛʹΦʔόϥΠυ͸ແؔ܎ 54
  55. (B() as A).f()ͷݺͼग़͠ %12 = metatype $@thick B.Type // user:

    %14 // function_ref B.__allocating_init() %13 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %14 %14 = apply %13(%12) : $@convention(method) (@thick B.Type) -> @owned B // user: %15 %15 = upcast %14 : $B to $A // users: %18, %17, %16 %16 = class_method %15 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %17 %17 = apply %16(%15) : $@convention(method) (@guaranteed A) -> () strong_release %15 : $A // id: %18 55
  56. %12 = metatype $@thick B.Type // user: %14 // function_ref

    B.__allocating_init() %13 = function_ref @$s6code031BCACycfC : $@convention(method) (@thick B.Type) -> @owned B // user: %14 %14 = apply %13(%12) : $@convention(method) (@thick B.Type) -> @owned B // user: %15 %15 = upcast %14 : $B to $A // users: %18, %17, %16 %16 = class_method %15 : $A, #A.f!1 : (A) -> () -> (), $@convention(method) (@guaranteed A) -> () // user: %17 %17 = apply %16(%15) : $@convention(method) (@guaranteed A) -> () strong_release %15 : $A // id: %18 • Bͷ஋ΛAʹupcast໋ྩͰΞοϓΩϟετͨ͠ ޙɺclass_method໋ྩͰA.fͷΤϯτϦΛऔ Γग़ͯ͠ݺͼग़͠ • ςʔϒϧͷͦͷཝʹొ࿥͞Ε͍ͯΔB.f͕ݺ͹ ΕΔ 56
  57. C().f()ͷݺͼग़͠ %19 = metatype $@thick C.Type // user: %21 //

    function_ref C.__allocating_init() %20 = function_ref @$s6code031CCACycfC : $@convention(method) (@thick C.Type) -> @owned C // user: %21 %21 = apply %20(%19) : $@convention(method) (@thick C.Type) -> @owned C // user: %23 %22 = alloc_stack $C // users: %23, %27, %26, %25 store %21 to %22 : $*C // id: %23 // function_ref P.f() %24 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %25 %25 = apply %24<C>(%22) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %22 : $*C // id: %26 dealloc_stack %22 : $*C // id: %27 57
  58. %19 = metatype $@thick C.Type // user: %21 // function_ref

    C.__allocating_init() %20 = function_ref @$s6code031CCACycfC : $@convention(method) (@thick C.Type) -> @owned C // user: %21 %21 = apply %20(%19) : $@convention(method) (@thick C.Type) -> @owned C // user: %23 %22 = alloc_stack $C // users: %23, %27, %26, %25 store %21 to %22 : $*C // id: %23 // function_ref P.f() %24 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %25 %25 = apply %24<C>(%22) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %22 : $*C // id: %26 dealloc_stack %22 : $*C // id: %27 • P.fͷσϑΥϧτ࣮૷Λ௚઀ݺͼग़͠ • witnessςʔϒϧ͸ࢀর͠ͳ͍ 58
  59. D().f()ͷݺͼग़͠ %28 = metatype $@thick D.Type // user: %30 //

    function_ref D.__allocating_init() %29 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %30 %30 = apply %29(%28) : $@convention(method) (@thick D.Type) -> @owned D // users: %33, %32, %31 %31 = class_method %30 : $D, #D.f!1 : (D) -> () -> (), $@convention(method) (@guaranteed D) -> () // user: %32 %32 = apply %31(%30) : $@convention(method) (@guaranteed D) -> () strong_release %30 : $D // id: %33 59
  60. %28 = metatype $@thick D.Type // user: %30 // function_ref

    D.__allocating_init() %29 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %30 %30 = apply %29(%28) : $@convention(method) (@thick D.Type) -> @owned D // users: %33, %32, %31 %31 = class_method %30 : $D, #D.f!1 : (D) -> () -> (), $@convention(method) (@guaranteed D) -> () // user: %32 %32 = apply %31(%30) : $@convention(method) (@guaranteed D) -> () strong_release %30 : $D // id: %33 • class_method໋ྩͰD.fΛݺͼग़͠ • C.fͰ͸ແ͍ͷͰΦʔόʔϥΠυ͸ແؔ܎(ͦ΋ ͦ΋͞Ε͍ͯͳ͍) 60
  61. (D() as C).f()ͷݺͼग़͠ %34 = metatype $@thick D.Type // user:

    %36 // function_ref D.__allocating_init() %35 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %36 %36 = apply %35(%34) : $@convention(method) (@thick D.Type) -> @owned D // user: %37 %37 = upcast %36 : $D to $C // user: %39 %38 = alloc_stack $C // users: %39, %43, %42, %41 store %37 to %38 : $*C // id: %39 // function_ref P.f() %40 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %41 %41 = apply %40<(C)>(%38) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %38 : $*C // id: %42 dealloc_stack %38 : $*C // id: %43 61
  62. %34 = metatype $@thick D.Type // user: %36 // function_ref

    D.__allocating_init() %35 = function_ref @$s6code031DCACycfC : $@convention(method) (@thick D.Type) -> @owned D // user: %36 %36 = apply %35(%34) : $@convention(method) (@thick D.Type) -> @owned D // user: %37 %37 = upcast %36 : $D to $C // user: %39 %38 = alloc_stack $C // users: %39, %43, %42, %41 store %37 to %38 : $*C // id: %39 // function_ref P.f() %40 = function_ref @$s6code031PPAAE1fyyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %41 %41 = apply %40<(C)>(%38) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () destroy_addr %38 : $*C // id: %42 dealloc_stack %38 : $*C // id: %43 • upcast໋ྩͰDΛCʹΞοϓΩϟετͨ͠ޙɺ P.fͷσϑΥϧτ࣮૷Λ௚઀ݺͼग़͠ 62
  63. witnessςʔϒϧͷࢀর func invokeP<X: P>(_ x: X) { x.f() } 63

  64. // invokeP<A>(_:) sil hidden @$s6code037invokePyyxAA1PRzlF : $@convention(thin) <X where X

    : P> (@in_guaranteed X) -> () { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "x", argno 1 // id: %1 %2 = witness_method $X, #P.f!1 : <Self where Self : P> (Self) -> () -> () : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %3 %3 = apply %2<X>(%0) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function '$s6code037invokePyyxAA1PRzlF' 64
  65. // invokeP<A>(_:) sil hidden @$s6code037invokePyyxAA1PRzlF : $@convention(thin) <X where X

    : P> (@in_guaranteed X) -> () { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "x", argno 1 // id: %1 %2 = witness_method $X, #P.f!1 : <Self where Self : P> (Self) -> () -> () : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () // user: %3 %3 = apply %2<X>(%0) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> () %4 = tuple () // user: %5 return %4 : $() // id: %5 } // end sil function '$s6code037invokePyyxAA1PRzlF' • witness_method໋ྩʹΑΔwitnessςʔϒϧ͔ Βͷؔ਺औΓग़͠ͱݺͼग़͠ • ςʔϒϧࢀরΛΠϯελϯε͔ΒͰ͸ͳ͘ϝλ λΠϓʹରͯ͠ߦ͏ 65