$30 off During Our Annual Pro Sale. View Details »

SILを読もう

omochimetaru
November 16, 2019

 SILを読もう

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