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

SILを読もう

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for omochimetaru omochimetaru
November 16, 2019

 SILを読もう

Avatar for omochimetaru

omochimetaru

November 16, 2019
Tweet

More Decks by omochimetaru

Other Decks in Programming

Transcript

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

    Swiftతʹ͸ͦͷ··return͍ͯ͠Δ͕ɺCPUʹ ͱͬͯ͸Int͔ΒInt?΁ͷม׵Λ͍ͯ͠Δɻ 6
  2. 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
  3. Mangling2 // module: code01 func intToIntOptional(x: Int) -> Int? ↓

    $s6code0116intToIntOptional1xSiSgSi_tF 2 https://github.com/apple/swift/blob/master/docs/ABI/Mangling.rst 9
  4. Demangling $s6code0116intToIntOptional1xSiSgSi_tF $s: Swift5 6: 6จࣈͷ୯ޠ code01 16: 16จࣈͷ୯ޠ intToIntOptional

    1: 1จࣈͷ୯ޠ x Si: Int Sg: Optional Si: Int _: Ϧετͷ۠੾Γ t: λϓϧ F: ؔ਺ 11
  5. // 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
  6. // 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
  7. %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
  8. class Cat {} func useCat(_ cat: Cat) { } func

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

    ݺͼग़͠લʹҾ਺ͷretain useCat(cat) // ݺͼग़͠ޙʹҾ਺ͷrelease // ݺͼग़͠લʹҾ਺ͷretain cat = changeCat(cat) // ݺͼग़͠ޙʹҾ਺ͷrelease // ݹ͍஋Λrelease // ม਺ͷ஋Λrelease } 19
  10. // 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
  11. // 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
  12. // 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
  13. // 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
  14. // 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
  15. // 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
  16. // 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
  17. // 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
  18. // 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
  19. ϓϩτίϧͷσϑΥϧτ࣮૷ͱΫϥε ܧঝͷؔ܎͸΍΍͍͜͠ • 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
  20. 31

  21. 33

  22. 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
  23. ࣮૷͞Εͨؔ਺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
  24. ੜ੒͞Εͨςʔϒϧ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
  25. // 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
  26. ؔ਺ͷ಺༁ • 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
  27. 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
  28. // 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
  29. 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
  30. // 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
  31. 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
  32. 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
  33. 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
  34. 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
  35. %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
  36. 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
  37. %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
  38. (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
  39. %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
  40. 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
  41. %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
  42. 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
  43. %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
  44. (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
  45. %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
  46. // 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
  47. // 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