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

Generalized existentialが内部的にすでに存在しているか調べてみた / A Dive to Find Inner Generalized Existential Containers

Generalized existentialが内部的にすでに存在しているか調べてみた / A Dive to Find Inner Generalized Existential Containers

わいわいswiftc #4

Yuta Koshizawa

August 03, 2018
Tweet

More Decks by Yuta Koshizawa

Other Decks in Programming

Transcript

  1. Generalized existen.al͕಺෦తʹ͢
    Ͱʹଘࡏ͍ͯ͠Δ͔ௐ΂ͯΈͨ
    Yuta Koshizawa @koher

    View full-size slide

  2. ① ٙ໰ʹࢥͬͨ͜ͱ

    View full-size slide

  3. ͜ͷίʔυͷ S ͕ಛघԽ͞Εͳ͍৔߹ɺ
    sequence ͷ࣮ߦ࣌ͷ಺෦తදݱ͸Ͳ͏ͳͬͯΔʁ
    func sum(of sequence: S) -> Int
    where S.Element == Int {
    return sequence.reduce(0, +)
    }

    View full-size slide

  4. ΋ͬͱஸೡʹ

    View full-size slide

  5. associatedtype Λ࣋ͨͳ͍ϓϩτίϧ
    protocol Animal {}
    struct Cat: Animal {}
    let cat: Cat = Cat()
    let animal: Animal = cat // OK

    View full-size slide

  6. ϓϩτίϧܕม਺ͷαΠζ
    protocol Animal {}
    struct Cat: Animal { let a: Int8 }
    struct Dog: Animal { let b: Int32 }
    let cat: Cat = Cat(a: 2) // 1 όΠτ
    let dog: Dog = Dog(b: 3) // 4 όΠτ
    // ԿόΠτʁ
    !
    let animal: Animal = Bool.random() ? cat : dog

    View full-size slide

  7. ஋ܕͱϓϩτίϧܕͱσΟεύον
    protocol Animal { func foo() -> Int }
    struct Cat: Animal { func foo() -> Int { return 2 } }
    struct Dog: Animal { func foo() -> Int { return 3 } }
    let cat: Cat = Cat()
    let dog: Dog = Dog()
    _ = cat.foo() // 2 : ੩తσΟεύον
    _ = dog.foo() // 3 : ੩తσΟεύον

    View full-size slide

  8. ஋ܕͱϓϩτίϧܕͱσΟεύον
    protocol Animal { func foo() -> Int }
    struct Cat: Animal { func foo() -> Int { return 2 } }
    struct Dog: Animal { func foo() -> Int { return 3 } }
    let cat: Cat = Cat()
    let dog: Dog = Dog()
    let animal: Animal = Bool.random() ? cat : dog
    _ = animal.foo() // 2 or 3 : ಈతσΟεύον

    View full-size slide

  9. Existen(al containers 1
    struct OpaqueExistentialContainer {
    void *fixedSizeBuffer[3];
    Metadata *type;
    WitnessTable *witnessTables[NUM_WITNESS_TABLES];
    };
    1 h$ps:/
    /github.com/apple/swi6/blob/master/docs/ABI/TypeLayout.rst#existenBal-container-layout

    View full-size slide

  10. ෳ਺ͷ Witness table Λ࣋ͭ৔߹
    protocol P {}
    protocol Q {}
    struct S : P, Q {}
    let pq: P & Q = S()

    View full-size slide

  11. !
    Existen(al container ͷ͓͔͛Ͱ
    ந৅తͳϓϩτίϧܕͱͯ͠ѻ͑Δ

    View full-size slide

  12. associatedtype Λ࣋ͭϓϩτίϧ
    protocol Animal { associatedtype Value }
    struct Cat: Animal { typealias Value = Int }
    let cat: Cat = Cat()
    let animal: Animal = cat // NG

    View full-size slide

  13. Generalized existen.als 2
    let strings
    : Any
    = ["a", "b", "c"]
    2 h$ps:/
    /github.com/apple/swi6/blob/master/docs/GenericsManifesto.md#generalized-existenAals

    View full-size slide

  14. associatedtype Λ࣋ͭϓϩτίϧ
    protocol Animal { associatedtype Value }
    struct Cat: Animal { typealias Value = Int }
    let cat: Cat = Cat()
    let animal: Any = cat
    // Generalized existential Ͱ͜Ε͕Ͱ͖ΔΑ͏ʹͳΔ͔΋

    View full-size slide

  15. !
    Generalized existen.al ͕ͳ͍ͷͰ
    associatedype ͕͋Δͱ
    ϓϩίτϧܕͱͯ͠ѻ͑ͳ͍

    View full-size slide

  16. Ͱ΋ɺ͜Ε͸Ͱ͖Δ
    protocol Animal { associatedtype Value }
    struct Cat: Animal { typealias Value = Int }
    func useAnimal(_ animal: A) -> Int
    where A.Value == Int { ... }
    useAnimal(Cat()) //

    OK

    View full-size slide

  17. A ͕ Cat ʹಛघԽ͞ΕΔͱ͜͏ͳΔ
    protocol Animal { associatedtype Value }
    struct Cat: Animal { typealias Value = Int }
    func useAnimal(_ animal: Cat) -> Int { ... }
    useAnimal(Cat()) //

    OK

    View full-size slide

  18. ಛघԽ͞Εͳ͍ͱͲ͏ͳΔʁ
    protocol Animal { associatedtype Value }
    struct Cat: Animal { typealias Value = Int }
    func useAnimal(_ animal: A) -> Int
    where A.Value == Int { ... }
    useAnimal(Cat()) // `Cat` ͸ͲͷΑ͏ʹѻΘΕΔʁ

    View full-size slide

  19. !
    ΋͔ͯ͠͠಺෦తʹ͸
    Existen(al ʹͳ͍ͬͯΔͷͰ͸ʁ

    View full-size slide

  20. ② LLVM IR Ͱ಺෦తදݱΛௐࠪ

    View full-size slide

  21. associatedtype ͕ ͳ͍ ͱ͖

    View full-size slide

  22. associatedtype ͕ ͳ͍ ͱ͖
    protocol Animal {
    func foo() -> Int
    }
    struct Cat: Animal {
    var value: Int = 42
    func foo() -> Int { return value }
    }

    View full-size slide

  23. associatedtype ͕ ͳ͍ ͱ͖
    func useAnimal(_ animal: Animal) -> Int {
    return animal.foo()
    }
    func useCat(_ cat: Cat) -> Int {
    return useAnimal(cat)
    }
    print(useCat(Cat()))

    View full-size slide

  24. associatedtype ͕ ͳ͍ ͱ͖
    func useAnimal(_ animal: Animal) -> Int {
    return animal.foo()
    }
    func useCat(_ cat: Cat) -> Int {
    return useAnimal(cat)
    }
    print(useCat(Cat()))

    View full-size slide

  25. swiftc -emit-ir foo.swift

    View full-size slide

  26. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }

    View full-size slide

  27. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    $S4main9useAnimalySiAA0C0_pF ʹϚϯάϦϯά͞ΕͯΔ

    View full-size slide

  28. swift demangle S4main9useAnimalySiAA0C0_pF

    View full-size slide

  29. σϚϯάϦϯάͷ݁Ռ
    $ swift demangle S4main9useAnimalySiAA0C0_pF
    $S4main9useAnimalySiAA0C0_pF ---> main.useAnimal(main.Animal) -> Swift.Int

    View full-size slide

  30. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    ͜Ε͸ main.useAnimal(main.Animal) -> Swift.Int

    View full-size slide

  31. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    %T4main6AnimalP* ܕͷҾ਺͕Ұͭ

    View full-size slide

  32. associatedtype ͕ ͳ͍ ͱ͖
    %T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }

    View full-size slide

  33. associatedtype ͕ ͳ͍ ͱ͖
    %T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }
    ↕ ରԠ͍ͯ͠Δ
    struct OpaqueExistentialContainer {
    void *fixedSizeBuffer[3];
    Metadata *type;
    WitnessTable *witnessTables[NUM_WITNESS_TABLES];
    };

    View full-size slide

  34. associatedtype ͕ ͳ͍ ͱ͖
    %T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }
    ↕ ରԠ͍ͯ͠Δ
    struct OpaqueExistentialContainer {
    void *fixedSizeBuffer[3];
    Metadata *type;
    WitnessTable *witnessTables[NUM_WITNESS_TABLES];
    };

    View full-size slide

  35. Witness tables ͱϙΠϯλܕ
    • i8* : witness table ͷཁૉ
    • i8** : witness table
    • i8*** : witness table ͷू·Γ = witnessTables

    View full-size slide

  36. associatedtype ͕ ͳ͍ ͱ͖
    %T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }
    ↕ ରԠ͍ͯ͠Δ
    struct OpaqueExistentialContainer {
    void *fixedSizeBuffer[3];
    Metadata *type;
    WitnessTable *witnessTables[NUM_WITNESS_TABLES];
    };

    View full-size slide

  37. associatedtype ͕ ͳ͍ ͱ͖
    %T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }
    ↕ ରԠ͍ͯ͠Δ
    struct OpaqueExistentialContainer {
    void *fixedSizeBuffer[3];
    Metadata *type;
    WitnessTable *witnessTable;
    };

    View full-size slide

  38. ෳ਺ͷ Witness table Λ࣋ͭ৔߹
    protocol P {}
    protocol Q {}
    struct S : P, Q {}
    let pq: P & Q = S()
    ↓ LLVM IR ( P & Q )
    %T4main1P_AA1Qp = type { [24 x i8], %swift.type*, i8**, i8** }

    View full-size slide

  39. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    Ҿ਺ͱͯ͠ Existen)al container Λड͚औ͍ͬͯΔ

    View full-size slide

  40. associatedtype ͕ ͳ͍ ͱ͖
    %T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }
    ↕ ରԠ͍ͯ͠Δ
    struct OpaqueExistentialContainer { // 40 όΠτ
    void *fixedSizeBuffer[3]; // 24 όΠτ
    Metadata *type; // 8 όΠτ
    WitnessTable *witnessTable; // 8 όΠτ
    };

    View full-size slide

  41. Existen(al container ͷαΠζ
    protocol P {}
    protocol Q {}
    print(MemoryLayout.size) // 40
    print(MemoryLayout.size) // 48

    View full-size slide

  42. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    Ҿ਺ͱͯ͠ 40 όΠτͷ Existen+al container Λड͚औ͍ͬͯΔ

    View full-size slide

  43. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    getelementptr ͱ͸ʁ

    View full-size slide

  44. getelementptr 3
    = getelementptr , * {, [inrange] }*
    = getelementptr inbounds , * {, [inrange] }*
    3 h$p:/
    /llvm.org/docs/LangRef.html#getelementptr-instruc=on

    View full-size slide

  45. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    // getelementptr inbounds , * , ,
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    0 ൪໨ͷ %T4main6AnimalP ͷ 1 ൪໨ͷϝϯόͷϙΠϯλΛऔಘ

    View full-size slide

  46. associatedtype ͕ ͳ͍ ͱ͖
    %T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }
    ↕ ରԠ͍ͯ͠Δ
    struct OpaqueExistentialContainer {
    void *fixedSizeBuffer[3];
    Metadata *type;
    WitnessTable *witnessTable;
    };

    View full-size slide

  47. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    type ͷϙΠϯλΛऔಘ

    View full-size slide

  48. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    type Λϩʔυ

    View full-size slide

  49. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    0 ൪໨ͷ %T4main6AnimalP ͷ 2 ൪໨ͷϝϯόͷϙΠϯλΛऔಘ

    View full-size slide

  50. associatedtype ͕ ͳ͍ ͱ͖
    %T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }
    ↕ ରԠ͍ͯ͠Δ
    struct OpaqueExistentialContainer {
    void *fixedSizeBuffer[3];
    Metadata *type;
    WitnessTable *witnessTable;
    };

    View full-size slide

  51. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    witnessTable ͷϙΠϯλΛऔಘ

    View full-size slide

  52. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    witnessTable Λϩʔυ

    View full-size slide

  53. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    0 ൪໨ͷ %T4main6AnimalP ͷ 0 ൪໨ͷϝϯόͷϙΠϯλΛऔಘ

    View full-size slide

  54. associatedtype ͕ ͳ͍ ͱ͖
    %T4main6AnimalP = type { [24 x i8], %swift.type*, i8** }
    ↕ ରԠ͍ͯ͠Δ
    struct OpaqueExistentialContainer {
    void *fixedSizeBuffer[3];
    Metadata *type;
    WitnessTable *witnessTable;
    };

    View full-size slide

  55. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    fixedSizeBuffer ͷϙΠϯλΛऔಘ

    View full-size slide

  56. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    fixedSizeBuffer ͷ࣮ମͷϙΠϯλΛऔಘ

    View full-size slide

  57. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    witnessTable ͔Β 1 ൪໨ͷཁૉͷϙΠϯλΛऔಘ

    View full-size slide

  58. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    witnessTable ͷ 1 ൪໨ͷཁૉΛϩʔυ

    View full-size slide

  59. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    foo Λදؔ͢਺ܕϙΠϯλʹΩϟετ

    View full-size slide

  60. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    foo Λίʔϧ

    View full-size slide

  61. associatedtype ͕ ͳ͍ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySiAA0C0_pF"(%T4main6AnimalP* noalias nocapture dereferenceable(40)) #0 {
    entry:
    %1 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 1
    %2 = load %swift.type*, %swift.type** %1, align 8
    %3 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 2
    %4 = load i8**, i8*** %3, align 8
    %5 = getelementptr inbounds %T4main6AnimalP, %T4main6AnimalP* %0, i32 0, i32 0
    %6 = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([24 x i8]* %5, %swift.type* %2) #1
    %7 = getelementptr inbounds i8*, i8** %4, i32 1
    %8 = load i8*, i8** %7, align 8, !invariant.load !25
    %9 = bitcast i8* %8 to i64 (%swift.opaque*, %swift.type*, i8**)*
    %10 = call swiftcc i64 %9(%swift.opaque* noalias nocapture swiftself %6, %swift.type* %2, i8** %4)
    ret i64 %10
    }
    foo ͷ໭Γ஋Λ return

    View full-size slide

  62. associatedtype ͕ ͋Δ ͱ͖

    View full-size slide

  63. associatedtype ͕ ͋Δ ͱ͖
    protocol Animal {
    associatedtype Value
    func foo() -> Value
    }
    struct Cat: Animal {
    var value: Int = 42
    func foo() -> Int { return value }
    }

    View full-size slide

  64. associatedtype ͕ ͋Δ ͱ͖
    func useAnimal(_ animal: A) -> Int
    where A.Value == Int {
    return animal.foo()
    }
    func useCat(_ cat: Cat) -> Int {
    return useAnimal(cat)
    }
    print(useCat(Cat()))

    View full-size slide

  65. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.Animal) #0 {
    entry:
    %1 = alloca %TSi, align 8
    %2 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2
    %4 = load i8*, i8** %3, align 8, !invariant.load !28
    %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
    %6 = bitcast %TSi* %1 to %swift.opaque*
    call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal)
    %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0
    %7 = load i64, i64* %._value, align 8
    %8 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
    ret i64 %7
    }

    View full-size slide

  66. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.Animal) #0 {
    entry:
    %1 = alloca %TSi, align 8
    %2 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2
    %4 = load i8*, i8** %3, align 8, !invariant.load !28
    %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
    %6 = bitcast %TSi* %1 to %swift.opaque*
    call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal)
    %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0
    %7 = load i64, i64* %._value, align 8
    %8 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
    ret i64 %7
    }
    ࡾͭͷҾ਺: Existen*al container Ͱ͸ͳ͘࠷ॳ͔Β෼ղ͞ΕͯΔ

    View full-size slide

  67. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.Animal) #0 {
    entry:
    %1 = alloca %TSi, align 8
    %2 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2
    %4 = load i8*, i8** %3, align 8, !invariant.load !28
    %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
    %6 = bitcast %TSi* %1 to %swift.opaque*
    call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal)
    %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0
    %7 = load i64, i64* %._value, align 8
    %8 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
    ret i64 %7
    }
    ಉ͡Α͏ʹࡾͭΛ༩͑ͯؔ਺Λίʔϧ

    View full-size slide

  68. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.Animal) #0 {
    entry:
    %1 = alloca %TSi, align 8
    %2 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2
    %4 = load i8*, i8** %3, align 8, !invariant.load !28
    %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
    %6 = bitcast %TSi* %1 to %swift.opaque*
    call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal)
    %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0
    %7 = load i64, i64* %._value, align 8
    %8 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
    ret i64 %7
    }
    %5 ͸ Witness table ͔ΒऔΓग़͞Εͨ foo Λදؔ͢਺ϙΠϯλ

    View full-size slide

  69. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.Animal) #0 {
    entry:
    %1 = alloca %TSi, align 8
    %2 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2
    %4 = load i8*, i8** %3, align 8, !invariant.load !28
    %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
    %6 = bitcast %TSi* %1 to %swift.opaque*
    call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal)
    %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0
    %7 = load i64, i64* %._value, align 8
    %8 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
    ret i64 %7
    }
    %6 ͸͜ͷؔ਺಺Ͱ֬อ͞ΕͨະॳظԽͷ Int → ݁ՌΛ֨ೲ

    View full-size slide

  70. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.Animal) #0 {
    entry:
    %1 = alloca %TSi, align 8
    %2 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2
    %4 = load i8*, i8** %3, align 8, !invariant.load !28
    %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
    %6 = bitcast %TSi* %1 to %swift.opaque*
    call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal)
    %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0
    %7 = load i64, i64* %._value, align 8
    %8 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
    ret i64 %7
    }
    %1 ͸ %7 Λհͯ͠ return ͞ΕΔ

    View full-size slide

  71. associatedtype ͕ ͋Δ ͱ͖
    protocol Animal {
    associatedtype Value
    func foo() -> Value
    }
    struct Cat: Animal {
    var value: Int = 42
    func foo() -> Int { return value }
    }

    View full-size slide

  72. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.Animal) #0 {
    entry:
    %1 = alloca %TSi, align 8
    %2 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2
    %4 = load i8*, i8** %3, align 8, !invariant.load !28
    %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
    %6 = bitcast %TSi* %1 to %swift.opaque*
    call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal)
    %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0
    %7 = load i64, i64* %._value, align 8
    %8 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
    ret i64 %7
    }
    ໭Γ஋ͷܕ͕ܾ·ͬͯͳ͍ͷͰ opaque ϙΠϯλΛհͯ݁͠ՌΛ
    ฦ͢ඞཁ͕͋ͬͨʢͱࢥΘΕΔʣ

    View full-size slide

  73. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.Animal) #0 {
    entry:
    %1 = alloca %TSi, align 8
    %2 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2
    %4 = load i8*, i8** %3, align 8, !invariant.load !28
    %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
    %6 = bitcast %TSi* %1 to %swift.opaque*
    call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal)
    %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0
    %7 = load i64, i64* %._value, align 8
    %8 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
    ret i64 %7
    }
    %A.Animal ͸ຊ౰ʹ Witness table ʁ

    View full-size slide

  74. associatedtype ͕ ͋Δ ͱ͖
    func useAnimal(_ animal: A) -> Int
    where A.Value == Int {
    return animal.foo()
    }
    func useCat(_ cat: Cat) -> Int {
    return useAnimal(cat)
    }
    print(useCat(Cat()))

    View full-size slide

  75. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0 {
    entry:
    %1 = alloca %T4main3CatV, align 8
    %2 = bitcast %T4main3CatV* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0
    %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0
    store i64 %0, i64* %.value._value, align 8
    %3 = bitcast %T4main3CatV* %1 to %swift.opaque*
    %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(
    %swift.opaque* noalias nocapture %3,
    %swift.type* bitcast (
    i64* getelementptr inbounds (
    <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>,
    <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf",
    i32 0, i32 1
    ) to %swift.type*
    ),
    i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0)
    )
    %5 = bitcast %T4main3CatV* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %5)
    ret i64 %4
    }
    useCat ͷ LLVM IR

    View full-size slide

  76. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0 {
    entry:
    %1 = alloca %T4main3CatV, align 8
    %2 = bitcast %T4main3CatV* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0
    %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0
    store i64 %0, i64* %.value._value, align 8
    %3 = bitcast %T4main3CatV* %1 to %swift.opaque*
    %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(
    %swift.opaque* noalias nocapture %3,
    %swift.type* bitcast (
    i64* getelementptr inbounds (
    <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>,
    <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf",
    i32 0, i32 1
    ) to %swift.type*
    ),
    i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0)
    )
    %5 = bitcast %T4main3CatV* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %5)
    ret i64 %4
    }
    ͜͜Ͱ useAnimal Λίʔϧ

    View full-size slide

  77. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0 {
    entry:
    %1 = alloca %T4main3CatV, align 8
    %2 = bitcast %T4main3CatV* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0
    %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0
    store i64 %0, i64* %.value._value, align 8
    %3 = bitcast %T4main3CatV* %1 to %swift.opaque*
    %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(
    %swift.opaque* noalias nocapture %3,
    %swift.type* bitcast (
    i64* getelementptr inbounds (
    <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>,
    <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf",
    i32 0, i32 1
    ) to %swift.type*
    ),
    i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0)
    )
    %5 = bitcast %T4main3CatV* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %5)
    ret i64 %4
    }
    ୈ 3 Ҿ਺

    View full-size slide

  78. S4main3CatVAA6AnimalAAWP ΛσϚϯάϦϯά
    $ swift demangle S4main3CatVAA6AnimalAAWP
    $S4main3CatVAA6AnimalAAWP ---> protocol witness table for main.Cat : main.Animal in main

    View full-size slide

  79. S4main3CatVAA6AnimalAAWP ΛσϚϯάϦϯά
    $ swift demangle S4main3CatVAA6AnimalAAWP
    $S4main3CatVAA6AnimalAAWP ---> protocol witness table for main.Cat : main.Animal in main
    ^^^^^^^^^^^^^^^^^^^^^^^^^^

    View full-size slide

  80. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main6useCatySiAA0C0VF"(i64) #0 {
    entry:
    %1 = alloca %T4main3CatV, align 8
    %2 = bitcast %T4main3CatV* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %.value = getelementptr inbounds %T4main3CatV, %T4main3CatV* %1, i32 0, i32 0
    %.value._value = getelementptr inbounds %TSi, %TSi* %.value, i32 0, i32 0
    store i64 %0, i64* %.value._value, align 8
    %3 = bitcast %T4main3CatV* %1 to %swift.opaque*
    %4 = call swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(
    %swift.opaque* noalias nocapture %3,
    %swift.type* bitcast (
    i64* getelementptr inbounds (
    <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>,
    <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32 }>*, i32, [4 x i8] }>* @"$S4main3CatVMf",
    i32 0, i32 1
    ) to %swift.type*
    ),
    i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @"$S4main3CatVAA6AnimalAAWP", i32 0, i32 0)
    )
    %5 = bitcast %T4main3CatV* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %5)
    ret i64 %4
    }
    ୈ 3 Ҿ਺ʹ Witness table Λ౉͢

    View full-size slide

  81. associatedtype ͕ ͋Δ ͱ͖
    define hidden swiftcc i64 @"$S4main9useAnimalySixAA0C0RzSi5ValueRtzlF"(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.Animal) #0 {
    entry:
    %1 = alloca %TSi, align 8
    %2 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.start.p0i8(i64 8, i8* %2)
    %3 = getelementptr inbounds i8*, i8** %A.Animal, i32 2
    %4 = load i8*, i8** %3, align 8, !invariant.load !28
    %5 = bitcast i8* %4 to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
    %6 = bitcast %TSi* %1 to %swift.opaque*
    call swiftcc void %5(%swift.opaque* noalias nocapture sret %6, %swift.opaque* noalias nocapture swiftself %0, %swift.type* %A, i8** %A.Animal)
    %._value = getelementptr inbounds %TSi, %TSi* %1, i32 0, i32 0
    %7 = load i64, i64* %._value, align 8
    %8 = bitcast %TSi* %1 to i8*
    call void @llvm.lifetime.end.p0i8(i64 8, i8* %8)
    ret i64 %7
    }
    ࡾͭͷҾ਺͸ Existen)al container ͱ౳Ձ

    View full-size slide

  82. !
    Existen(al container Ͱ
    ౉͞ͳ͍ͷ͸ͳͥʁ

    View full-size slide

  83. associatedtype ͕ ͋Δ ͱ͖
    func useAnimal(_ animal: A) -> Int
    where A.Value == Int {
    return animal.foo()
    }
    func useCat(_ cat: Cat) -> Int {
    return useAnimal(cat)
    }
    print(useCat(Cat()))

    View full-size slide

  84. A ܕ͸ useCat ͷத͚ͩͷܕ

    View full-size slide

  85. !
    useCat ͷϩʔΧϧείʔϓͰ
    औΓѻ͑Ε͹ྑ͍

    View full-size slide

  86. !
    Existen(al container Ͱ
    औΓճ͢ඞཁ͸ͳ͍

    View full-size slide

  87. !
    Existen(al container Ͱ
    แΜͩΓ෼ղͨ͠Γ͢Δͱ
    Φʔόʔϔου͕ൃੜ

    View full-size slide

  88. !
    ͦΕͳΒ Existen)al ʹͤͣ
    ࠷ॳ͔Β͹Β͹Βʹѻ͓͏
    ʢͱ͍͏͜ͱͰ͸ʁʣ

    View full-size slide

  89. ʲ౰ॳͷٙ໰ʳ
    ΋͔ͯ͠͠಺෦తʹ͸
    Existen(al ʹͳ͍ͬͯΔͷͰ͸ʁ

    View full-size slide

  90. !
    Generalized existen.al ͸
    ಺෦తʹ΋ଘࡏ͠ͳ͔ͬͨ

    View full-size slide

  91. !
    Ͱ΋ useCat(_:) ͸
    Existen(al ͱࣅͨ࢓૊ΈͰಈ͍ͯͨ

    View full-size slide

  92. ΄΅ಉ͜͡ͱ͕͔֬ΊΒΕͯͨ 4
    4 h$ps:/
    /qiita.com/omochimetaru/items/b41e7699ea25a324aefa

    View full-size slide