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

SwiftのGenericsとProtocolの実装

3781f49ea2c76d6ecf0c6cda46096d49?s=47 omochimetaru
November 17, 2018

 SwiftのGenericsとProtocolの実装

3781f49ea2c76d6ecf0c6cda46096d49?s=128

omochimetaru

November 17, 2018
Tweet

More Decks by omochimetaru

Other Decks in Programming

Transcript

  1. SwiftͷGenerics ͱProtocolͷ࣮૷ omochimetaru ݴޠॲཧܥษڧձ Vol.1 1

  2. ࣗݾ঺հ • omochimetaru • Qoncept, Inc. • iOS, Mac, Web

    Frontend, Unity, Android • Swift, C++, TypeScript, Kotlin • Twitter, GitHub, Qiita, Qrunch • ήʔϜ, SwiftίϯύΠϥ 2
  3. • Θ͍Θ͍swiftc https://iosdiscord.connpass.com • iOSDC (2018/09/02) SwiftͷδΣωϦΫε͸Ͳ͏΍ͬͯಈ͍͍ͯΔͷ ͔ίϯύΠϥͷιʔε͔Β୳Δ • Discord

    swift-developers-japan 3
  4. Swift • Apple͕։ൃ • Φʔϓϯιʔε • ωΠςΟϒίϯύΠϧݴޠ • ஋ܕ •

    Generics • ϓϩτίϧࢦ޲ 4
  5. Φʔϓϯιʔε https://github.com/apple/swift https://forums.swift.org 5

  6. ωΠςΟϒίϯύΠϧ Swift → SIL → LLVM IR → ࣮ߦϑΝΠϧ 6

  7. ࢀরܕ class Cat { var name: String = "ͨ·" }

    let a = Cat() let b = a b.name = "Έ͚" print(a.name) // Έ͚ TraceGC͸ແ͠ɻࢀরΧ΢ϯλΛ࢖͏ɻ 7
  8. ஋ܕ let a = [10, 20, 30] var b =

    a b[0] = 999 print(a) // [10, 20, 30] print(b) // [999, 20, 30] 8
  9. struct Stone { var weight: Int = 5 } let

    size = MemoryLayout<Stone>.size print(size) // 8 9
  10. struct BigStone { var weight: Int = 5 var blob1:

    Int = 999 var blob2: Int = 999 var blob3: Int = 999 } let size = MemoryLayout<BigStone>.size print(size) // 32 10
  11. Generics // Array<Element> let a: [Int] = [10, 20, 30]

    let b: [String] = a.map { String($0) } print(b) // ["10", "20", "30"] 11
  12. func wrapArray<X>(_ x: X) -> Array<X> { return [x] }

    let a = wrapArray(Stone()) print(a[0].weight) // 5 12
  13. Genericsͷ࣮૷ 13

  14. ಛ௃ • ஋ܕͱࢀরܕʹରԠ ஋ܕ͸ҟͳΔαΠζΛ΋ͪɺ ࣗ਎ʹϝλ৘ใΛ࣋ͨͳ͍ 14

  15. func takeX1<X>(_ x: X) { } func main() { takeX1(4)

    } 15
  16. $ swiftc -emit-ir a.swift 16

  17. define hidden swiftcc void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture, %swift.type* %X)

    #0 { entry: %X1 = alloca %swift.type*, align 8 store %swift.type* %X, %swift.type** %X1, align 8 ret void } define hidden swiftcc void @"$s1a4mainyyF"() #0 { entry: %0 = alloca %TSi, align 8 %1 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %1) %._value = getelementptr inbounds %TSi, %TSi* %0, i32 0, i32 0 store i64 4, i64* %._value, align 8 %2 = bitcast %TSi* %0 to %swift.opaque* call swiftcc void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture %2, %swift.type* @"$sSiN") %3 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %3) ret void } 17
  18. Signature func takeX1<X>(_ x: X) void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture,

    %swift.type* %X) <X> → opaque pointer + metatype 18
  19. Metatype let t1: Int.Type = Int.self let t2 = type(of:

    3) print(t1 == t2) // true // static member access print(Int.bitWidth) // 64 print(t1.bitWidth) // 64 19
  20. ୈ1Ҿ਺ͷߏங define hidden swiftcc void @"$s1a4mainyyF"() #0 { entry: %0

    = alloca %TSi, align 8 %1 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %1) %._value = getelementptr inbounds %TSi, %TSi* %0, i32 0, i32 0 store i64 4, i64* %._value, align 8 %2 = bitcast %TSi* %0 to %swift.opaque* call swiftcc void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture %2, %swift.type* @"$sSiN") %3 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %3) ret void } 20
  21. ୈ2Ҿ਺ͷߏங define hidden swiftcc void @"$s1a4mainyyF"() #0 { entry: %0

    = alloca %TSi, align 8 %1 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %1) %._value = getelementptr inbounds %TSi, %TSi* %0, i32 0, i32 0 store i64 4, i64* %._value, align 8 %2 = bitcast %TSi* %0 to %swift.opaque* call swiftcc void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture %2, %swift.type* @"$sSiN") %3 = bitcast %TSi* %0 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %3) ret void } 21
  22. IntͷMetatype͸֎෦ఆٛ͞ΕΔɻ @"$sSiN" = external global %swift.type, align 8 22

  23. libSwiftCore.dylib ඪ४ϥΠϒϥϦ(Swift) + ϥϯλΠϜϥΠϒϥϦ(C++) • Int͸SwiftͰ࣮૷ • Int಺෦ͷBuildin.Int64͸C++Ͱ࣮૷ 23

  24. stdlib/public/core/IntegerTypes.swift.gyb public struct Int { public var _value: Builtin.Int64 }

    gyb͸ςϯϓϨʔτݴޠ 24
  25. include/swift/Runtime/Metadata.h using FullOpaqueMetadata = FullMetadata<OpaqueMetadata>; #define BUILTIN_TYPE(Symbol, Name) \ SWIFT_RUNTIME_EXPORT

    \ const FullOpaqueMetadata METADATA_SYM(Symbol); #include "swift/Runtime/BuiltinTypes.def" 25
  26. swift/Runtime/BuiltinTypes.def BUILTIN_TYPE(Bi64_, "Builtin.Int64") ల։ޙ SWIFT_RUNTIME_EXPORT const FullOpaqueMetadata $SBi64_N; 26

  27. ܕ͕ෆ໌ͳ஋ͷૢ࡞ func takeX2<X>(_ x: X) { let a = x

    } • ม਺aͷετϨʔδ֬อ • x͔Βaʹ஋ͷίϐʔ • aͷഁغ, ετϨʔδղ์ 27
  28. Value Witness Table Metatype͔ΒऔΓग़ͤΔؔ਺ςʔϒϧ ίϐʔ΍ഁغͳͲɺ஋(Value)ʹର͢ΔҰൠతͳૢ ࡞Λ͢Δؔ਺͕ೖ͍ͬͯΔ ΠϯλʔϑΣʔε͸Opaqueͳදݱʹͳ͍ͬͯΔ ೖ͍ͬͯΔؔ਺͸ݸผͷܕΛظ଴͍ͯ͠ΔͨΊɺ Opaqueͳ஋ͱɺͦͷਅͷܕͷMetatypeΛϖΞͰ औΓճ͢

    28
  29. Valueͷҙຯ ஋ܕ(struct)ͷ৔߹ɺͦͷϝϞϦ্ͷදݱͷ͜ͱɻ ࢀরܕ(class)ͷ৔߹ɺͦͷΞυϨεΛ֨ೲ͢Δ8ό ΠτͷϙΠϯλͷ͜ͱɻ https://github.com/apple/swift/blob/master/ docs/OwnershipManifesto.md 29

  30. ίϐʔ/ഁغͷॲཧ಺༰ ஋ܕͷ৔߹ɺͦΕͷ΋ͭ stored property ͢΂ͯ Λ࠶ؼతʹίϐʔ/ഁغɻ ࢀরܕͷ஋ͷ৔߹ɺͦͷࢀরઌͷΦϒδΣΫτʹ ͋ΔࢀরΧ΢ϯλͷ૿ݮૢ࡞ɻ 30

  31. VWTͷݻ༗ɺڞ༗ ஋ܕͷMetatype͸ݻ༗ͷVWTΛ࣋ͭɻ ࢀরܕͷMetatype͸ڞ௨ͷVWTΛ࣋ͭɻ 31

  32. Value Witness Table ͷৄࡉ 32

  33. include/swift/ABI/Metadata.h template <typename Runtime> struct TargetValueWitnessTable; using ValueWitnessTable = TargetValueWitnessTable<InProcess>;

    template <typename Runtime> struct TargetValueWitnessTable { #define WANT_ONLY_REQUIRED_VALUE_WITNESSES #define VALUE_WITNESS(LOWER_ID, UPPER_ID) \ typename TargetValueWitnessTypes<Runtime>::LOWER_ID LOWER_ID; #include "swift/ABI/ValueWitness.def" } 33
  34. template <typename Runtime> struct TargetValueWitnessTable { typename TargetValueWitnessTypes<Runtime>::initializeBufferWithCopyOfBuffer initializeBufferWithCopyOfBuffer; typename

    TargetValueWitnessTypes<Runtime>::destroy destroy; typename TargetValueWitnessTypes<Runtime>::initializeWithCopy initializeWithCopy; typename TargetValueWitnessTypes<Runtime>::assignWithCopy assignWithCopy; typename TargetValueWitnessTypes<Runtime>::initializeWithTake initializeWithTake; typename TargetValueWitnessTypes<Runtime>::assignWithTake assignWithTake; typename TargetValueWitnessTypes<Runtime>::getEnumTagSinglePayload getEnumTagSinglePayload; typename TargetValueWitnessTypes<Runtime>::storeEnumTagSinglePayload storeEnumTagSinglePayload; typename TargetValueWitnessTypes<Runtime>::size size; typename TargetValueWitnessTypes<Runtime>::flags flags; typename TargetValueWitnessTypes<Runtime>::stride stride; } 34
  35. ݟ΍͘͢লུ struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake;

    getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 35
  36. ίϐʔ4छྨ struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake;

    getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 36
  37. ഁغ struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake;

    getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 37
  38. ϝϞϦ֬อ༻ͷ৘ใ struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake;

    getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 38
  39. ࠶ܝ func takeX2<X>(_ x: X) { let a = x

    } 39
  40. define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type* %X)

    #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 40
  41. VWTͷऔΓग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 41
  42. VWT͔ΒsizeͷऔΓग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 42
  43. [8] = size struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy;

    initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 43
  44. ετϨʔδͷ֬อ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 44
  45. VWT͔ΒinitializeWithCopyͷऔΓग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 45
  46. [2] = initializeWithCopy struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy;

    initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 46
  47. initializeWithCopyͷݺͼग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 47
  48. VWT͔ΒdestroyͷऔΓग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 48
  49. [1] = destroy struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy;

    initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 49
  50. destroyͷݺͼग़͠ define hidden swiftcc void @"$s1b6takeX2yyxlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X) #0 { entry: %X1 = alloca %swift.type*, align 8 %a.debug = alloca i8*, align 8 %1 = bitcast i8** %a.debug to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %1, i8 0, i64 8, i1 false) store %swift.type* %X, %swift.type** %X1, align 8 %2 = bitcast %swift.type* %X to i8*** %3 = getelementptr inbounds i8**, i8*** %2, i64 -1 %X.valueWitnesses = load i8**, i8*** %3, align 8, !invariant.load !13, !dereferenceable !14 %4 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 8 %5 = load i8*, i8** %4, align 8, !invariant.load !13 %size = ptrtoint i8* %5 to i64 %a = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 %10 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 1 %11 = load i8*, i8** %10, align 8, !invariant.load !13 %destroy = bitcast i8* %11 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %6, %swift.type* %X) #3 %12 = bitcast %swift.opaque* %6 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %12) ret void } 50
  51. ετϨʔδ͸allocaͰ֬อ͞Ε͍ͯͨͷͰɺ ղ์༻ͷ໋ྩ͸ಛʹͳ͠ 51

  52. VWTૢ࡞ॲཧͷ ίϯύΠϥͷ࣮૷ 52

  53. ࠶ܝ Swift → SIL → LLVM IR → ࣮ߦϑΝΠϧ LLVM

    IRͷੜ੒͸SIL͔Βͷม׵ͱ࣮ͯ͠૷͞Εͯ ͍Δɻ 53
  54. $ swiftc -emit-sil b.swift 54

  55. // takeX2<A>(_:) sil hidden @$s1b6takeX2yyxlF : $@convention(thin) <X> (@in_guaranteed X)

    -> () { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "x", argno 1 // id: %1 %2 = alloc_stack $X, let, name "a" // users: %5, %4, %3 copy_addr %0 to [initialization] %2 : $*X // id: %3 destroy_addr %2 : $*X // id: %4 dealloc_stack %2 : $*X // id: %5 %6 = tuple () // user: %7 return %6 : $() // id: %7 } // end sil function '$s1b6takeX2yyxlF' 55
  56. copy_addr Λݟ͍ͯ͘ // takeX2<A>(_:) sil hidden @$s1b6takeX2yyxlF : $@convention(thin) <X>

    (@in_guaranteed X) -> () { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "x", argno 1 // id: %1 %2 = alloc_stack $X, let, name "a" // users: %5, %4, %3 copy_addr %0 to [initialization] %2 : $*X // id: %3 destroy_addr %2 : $*X // id: %4 dealloc_stack %2 : $*X // id: %5 %6 = tuple () // user: %7 return %6 : $() // id: %7 } // end sil function '$s1b6takeX2yyxlF' 56
  57. ରԠ͢ΔLLVM-IR %6 = bitcast i8* %a to %swift.opaque* store i8*

    %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 57
  58. SILؔ਺͝ͱʹLLVM IR͕ੜ੒͞ΕΔ swift/lib/IRGen/IRGenSIL.cpp void IRGenModule::emitSILFunction(SILFunction *f) 58

  59. SILؔ਺ʹ͓͍ͯɺBasicBlock͝ͱʹLLVM IR͕ੜ ੒͞ΕΔ swift/lib/IRGen/IRGenSIL.cpp void IRGenSILFunction::visitSILBasicBlock(SILBasicBlock *BB) 59

  60. SIL BasicBlockʹ͓͍ͯɺInstruction͝ͱʹLLVM IR͕ੜ੒͞ΕΔ ໋ྩछྨʹର͢ΔVisitorύλʔϯͰॻ͔Ε͍ͯΔ include/swift/SIL/SILVisitor.h 60

  61. template <typename ImplClass, typename RetTy = void, typename... ArgTys> class

    SILInstructionVisitor { public: RetTy visit(SILInstruction *inst, ArgTys... args) { asImpl().beforeVisit(inst, args...); switch (inst->getKind()) { #define INST(CLASS, PARENT) \ case SILInstructionKind::CLASS: \ return asImpl().visit##CLASS(static_cast<CLASS*>(inst), \ std::forward<ArgTys>(args)...); #include "swift/SIL/SILNodes.def" } llvm_unreachable("Not reachable, all cases handled"); } } 61
  62. copy_addr໋ྩͷॲཧதͳͷͰvisitCopyAddrInst ͕ݺ͹ΕΔ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) { SILType addrTy = i->getSrc()->getType();

    const TypeInfo &addrTI = getTypeInfo(addrTy); Address src = getLoweredAddress(i->getSrc()); // See whether we have a deferred fixed-size buffer initialization. auto &loweredDest = getLoweredValue(i->getDest()); assert(!loweredDest.isUnallocatedAddressInBuffer()); Address dest = loweredDest.getAnyAddress(); if (i->isInitializationOfDest()) { if (i->isTakeOfSrc()) { addrTI.initializeWithTake(*this, dest, src, addrTy, false); } else { addrTI.initializeWithCopy(*this, dest, src, addrTy, false); } } else { if (i->isTakeOfSrc()) { addrTI.assignWithTake(*this, dest, src, addrTy, false); } else { addrTI.assignWithCopy(*this, dest, src, addrTy, false); } } } 62
  63. ίϐʔݩͷίϯύΠϧ࣌ܕ৘ใ(TypeInfo)ΛऔΓग़ ͢ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) { SILType addrTy = i->getSrc()->getType();

    const TypeInfo &addrTI = getTypeInfo(addrTy); Address src = getLoweredAddress(i->getSrc()); // See whether we have a deferred fixed-size buffer initialization. auto &loweredDest = getLoweredValue(i->getDest()); assert(!loweredDest.isUnallocatedAddressInBuffer()); Address dest = loweredDest.getAnyAddress(); if (i->isInitializationOfDest()) { if (i->isTakeOfSrc()) { addrTI.initializeWithTake(*this, dest, src, addrTy, false); } else { addrTI.initializeWithCopy(*this, dest, src, addrTy, false); } } else { if (i->isTakeOfSrc()) { addrTI.assignWithTake(*this, dest, src, addrTy, false); } else { addrTI.assignWithCopy(*this, dest, src, addrTy, false); } } } 63
  64. ܕ৘ใͷϝιουʹసૹ͢Δ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) { SILType addrTy = i->getSrc()->getType(); const

    TypeInfo &addrTI = getTypeInfo(addrTy); Address src = getLoweredAddress(i->getSrc()); // See whether we have a deferred fixed-size buffer initialization. auto &loweredDest = getLoweredValue(i->getDest()); assert(!loweredDest.isUnallocatedAddressInBuffer()); Address dest = loweredDest.getAnyAddress(); if (i->isInitializationOfDest()) { if (i->isTakeOfSrc()) { addrTI.initializeWithTake(*this, dest, src, addrTy, false); } else { addrTI.initializeWithCopy(*this, dest, src, addrTy, false); } } else { if (i->isTakeOfSrc()) { addrTI.assignWithTake(*this, dest, src, addrTy, false); } else { addrTI.assignWithCopy(*this, dest, src, addrTy, false); } } } 64
  65. ܕ͕<X>ͳͷͰaddrTI͸ OpaqueArchetypeTypeInfo lib/IRGen/GenArcheType.cpp class OpaqueArchetypeTypeInfo : public ResilientTypeInfo<OpaqueArchetypeTypeInfo> { };

    65
  66. ਌ΫϥεͷResilientTypeInfoͷ࣮૷͕ݺ͹ΕΔ lib/IRGen/ResilientTypeInfo.h template <class Impl> class ResilientTypeInfo : public WitnessSizedTypeInfo<Impl>

    { void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T, bool isOutlined) const override { emitInitializeWithCopyCall(IGF, T, dest, src); } }; 66
  67. lib/IRGen/GenOpaque.cpp void irgen::emitInitializeWithCopyCall(IRGenFunction &IGF, SILType T, Address dest, Address src)

    { llvm::Value *metadata; auto fn = IGF.emitValueWitnessFunctionRef(T, metadata, ValueWitness::InitializeWithCopy); auto destPtr = emitCastToOpaquePtr(IGF, dest); auto srcPtr = emitCastToOpaquePtr(IGF, src); IGF.Builder.CreateCall(fn, {destPtr, srcPtr, metadata}); } 67
  68. void irgen::emitInitializeWithCopyCall(IRGenFunction &IGF, SILType T, Address dest, Address src) {

    llvm::Value *metadata; auto fn = IGF.emitValueWitnessFunctionRef(T, metadata, ValueWitness::InitializeWithCopy); auto destPtr = emitCastToOpaquePtr(IGF, dest); auto srcPtr = emitCastToOpaquePtr(IGF, src); IGF.Builder.CreateCall(fn, {destPtr, srcPtr, metadata}); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 68
  69. void irgen::emitInitializeWithCopyCall(IRGenFunction &IGF, SILType T, Address dest, Address src) {

    llvm::Value *metadata; auto fn = IGF.emitValueWitnessFunctionRef(T, metadata, ValueWitness::InitializeWithCopy); auto destPtr = emitCastToOpaquePtr(IGF, dest); auto srcPtr = emitCastToOpaquePtr(IGF, src); IGF.Builder.CreateCall(fn, {destPtr, srcPtr, metadata}); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 69
  70. void irgen::emitInitializeWithCopyCall(IRGenFunction &IGF, SILType T, Address dest, Address src) {

    llvm::Value *metadata; auto fn = IGF.emitValueWitnessFunctionRef(T, metadata, ValueWitness::InitializeWithCopy); auto destPtr = emitCastToOpaquePtr(IGF, dest); auto srcPtr = emitCastToOpaquePtr(IGF, src); IGF.Builder.CreateCall(fn, {destPtr, srcPtr, metadata}); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 70
  71. lib/IRGen/GenOpaque.cpp // index = ValueWitness::InitializeWithCopy FunctionPointer IRGenFunction::emitValueWitnessFunctionRef(SILType type, llvm::Value *&metadataSlot,

    ValueWitness index) { assert(isValueWitnessFunction(index)); auto key = LocalTypeDataKind::forValueWitness(index); if (auto witness = tryGetLocalTypeDataForLayout(type, key)) { metadataSlot = emitTypeMetadataRefForLayout(type); auto signature = IGM.getValueWitnessSignature(index); return FunctionPointer(witness, signature); } auto vwtable = emitValueWitnessTableRef(type, &metadataSlot); auto witness = emitLoadOfValueWitnessFunction(*this, vwtable, index); setScopedLocalTypeDataForLayout(type, key, witness.getPointer()); return witness; } 71
  72. // index = ValueWitness::InitializeWithCopy FunctionPointer IRGenFunction::emitValueWitnessFunctionRef(SILType type, llvm::Value *&metadataSlot, ValueWitness

    index) { assert(isValueWitnessFunction(index)); auto key = LocalTypeDataKind::forValueWitness(index); if (auto witness = tryGetLocalTypeDataForLayout(type, key)) { metadataSlot = emitTypeMetadataRefForLayout(type); auto signature = IGM.getValueWitnessSignature(index); return FunctionPointer(witness, signature); } auto vwtable = emitValueWitnessTableRef(type, &metadataSlot); auto witness = emitLoadOfValueWitnessFunction(*this, vwtable, index); setScopedLocalTypeDataForLayout(type, key, witness.getPointer()); return witness; } 72
  73. // index = ValueWitness::InitializeWithCopy static FunctionPointer emitLoadOfValueWitnessFunction(IRGenFunction &IGF, llvm::Value *table,

    ValueWitness index) { assert(isValueWitnessFunction(index)); llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, table, index); auto label = getValueWitnessLabel(index); auto signature = IGF.IGM.getValueWitnessSignature(index); auto type = signature.getType()->getPointerTo(); witness = IGF.Builder.CreateBitCast(witness, type, label); return FunctionPointer(witness, signature); } 73
  74. // index = ValueWitness::InitializeWithCopy static FunctionPointer emitLoadOfValueWitnessFunction(IRGenFunction &IGF, llvm::Value *table,

    ValueWitness index) { assert(isValueWitnessFunction(index)); llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, table, index); auto label = getValueWitnessLabel(index); auto signature = IGF.IGM.getValueWitnessSignature(index); auto type = signature.getType()->getPointerTo(); witness = IGF.Builder.CreateBitCast(witness, type, label); return FunctionPointer(witness, signature); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 74
  75. // index = ValueWitness::InitializeWithCopy static FunctionPointer emitLoadOfValueWitnessFunction(IRGenFunction &IGF, llvm::Value *table,

    ValueWitness index) { assert(isValueWitnessFunction(index)); llvm::Value *witness = emitInvariantLoadOfOpaqueWitness(IGF, table, index); auto label = getValueWitnessLabel(index); auto signature = IGF.IGM.getValueWitnessSignature(index); auto type = signature.getType()->getPointerTo(); witness = IGF.Builder.CreateBitCast(witness, type, label); return FunctionPointer(witness, signature); } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 75
  76. // index = ValueWitness::InitializeWithCopy llvm::Value *irgen::emitInvariantLoadOfOpaqueWitness(IRGenFunction &IGF, llvm::Value *table, WitnessIndex

    index) { assert(table->getType() == IGF.IGM.WitnessTablePtrTy); // GEP to the appropriate index, avoiding spurious IR in the trivial case. llvm::Value *slot = table; if (index.getValue() != 0) slot = IGF.Builder.CreateConstInBoundsGEP1_32( /*Ty=*/nullptr, table, index.getValue()); auto witness = IGF.Builder.CreateLoad(Address(slot, IGF.IGM.getPointerAlignment())); IGF.setInvariantLoad(witness); return witness; } 76
  77. // index = ValueWitness::InitializeWithCopy llvm::Value *irgen::emitInvariantLoadOfOpaqueWitness(IRGenFunction &IGF, llvm::Value *table, WitnessIndex

    index) { assert(table->getType() == IGF.IGM.WitnessTablePtrTy); // GEP to the appropriate index, avoiding spurious IR in the trivial case. llvm::Value *slot = table; if (index.getValue() != 0) slot = IGF.Builder.CreateConstInBoundsGEP1_32( /*Ty=*/nullptr, table, index.getValue()); auto witness = IGF.Builder.CreateLoad(Address(slot, IGF.IGM.getPointerAlignment())); IGF.setInvariantLoad(witness); return witness; } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 77
  78. // index = ValueWitness::InitializeWithCopy llvm::Value *irgen::emitInvariantLoadOfOpaqueWitness(IRGenFunction &IGF, llvm::Value *table, WitnessIndex

    index) { assert(table->getType() == IGF.IGM.WitnessTablePtrTy); // GEP to the appropriate index, avoiding spurious IR in the trivial case. llvm::Value *slot = table; if (index.getValue() != 0) slot = IGF.Builder.CreateConstInBoundsGEP1_32( /*Ty=*/nullptr, table, index.getValue()); auto witness = IGF.Builder.CreateLoad(Address(slot, IGF.IGM.getPointerAlignment())); IGF.setInvariantLoad(witness); return witness; } %6 = bitcast i8* %a to %swift.opaque* store i8* %a, i8** %a.debug, align 8 %7 = getelementptr inbounds i8*, i8** %X.valueWitnesses, i32 2 %8 = load i8*, i8** %7, align 8, !invariant.load !13 %initializeWithCopy = bitcast i8* %8 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %9 = call %swift.opaque* %initializeWithCopy( %swift.opaque* noalias %6, %swift.opaque* noalias %0, %swift.type* %X) #3 78
  79. Protocol 79

  80. ϝιουͷఆٛ protocol Animal { func speak() -> String } class

    Cat : Animal { func speak() -> String { return "ʹΌʔ" } } class Dog : Animal { func speak() -> String { return "ΘΜ" } } 80
  81. staticϝιουͷఆٛ protocol Animal { static func label() -> String }

    class Cat : Animal { static func label() -> String { return "ೣ" } } class Dog : Animal { static func label() -> String { return "ݘ" } } 81
  82. associated type protocol Animal { associatedtype Food func eat(food: Food)

    } struct CatFood {} class Cat : Animal { typealias Food = CatFood func eat(food: CatFood) { } } struct DogFood {} class Dog : Animal { typealias Food = DogFood func eat(food: DogFood) { } } 82
  83. Selfܕ protocol Animal { func spawn() -> Self } final

    class Cat : Animal { func spawn() -> Cat { return Cat() } } final class Dog : Animal { func spawn() -> Dog { return Dog() } } 83
  84. Genericsͱ૊Έ߹ΘͤΔ protocol Animal { func speak() -> String } class

    Cat : Animal { func speak() -> String { return "ʹΌʔ" } } func invokeSpeak<X: Animal>(animal: X) -> String { return animal.speak() } print(invokeSpeak(animal: Cat())) // ʹΌʔ 84
  85. ܕΫϥε෩ protocol Addable { static var zero: Self { get

    } static func +(a: Self, b: Self) -> Self } extension Int : Addable { static var zero: Int { return 0 } } extension Sequence where Element : Addable { func sum() -> Element { return reduce(Element.zero) { $0 + $1 } } } let a = [1, 2, 3] // Array (struct) ͸ Sequence (protocol) print(a.sum()) // 6 85
  86. Protocolͷ࣮૷ 86

  87. ಛ௃ • ஋ܕͱࢀরܕʹରԠ • طଘͷܕʹޙ෇Մೳ • staticϝϯό 87

  88. protocol Animal { func speak() -> Int } class Cat

    : Animal { func speak() -> Int { return 28 } } struct Stone : Animal { func speak() -> Int { return 14 } } 88
  89. SILͰݟΔͱɺCatͱStoneͦΕͧΕʹɺ Animalͷwitness table͕͋Δ sil_witness_table hidden Cat: Animal module c {

    method #Animal.speak!1: <Self where Self : Animal> (Self) -> () -> Int : @$s1c3CatCAA6AnimalA2aDP5speakSiyFTW // protocol witness for Animal.speak() in conformance Cat } sil_witness_table hidden Stone: Animal module c { method #Animal.speak!1: <Self where Self : Animal> (Self) -> () -> Int : @$s1c5StoneVAA6AnimalA2aDP5speakSiyFTW // protocol witness for Animal.speak() in conformance Stone } 89
  90. Protocol Witness Table Protocolʹ४ڌ͢ΔͨΊͷؔ਺ςʔϒϧ ͦͷProtocolͰنఆ͞ΕΔૢ࡞Λ͢Δؔ਺͕ೖͬ ͍ͯΔ ΠϯλʔϑΣʔε͸Opaqueͳදݱʹͳ͍ͬͯΔ ೖ͍ͬͯΔؔ਺͸ݸผͷܕΛظ଴͍ͯ͠ΔͨΊɺ Opaqueͳ஋ͱɺͦͷਅͷܕͷPWTΛϖΞͰऔΓ ճ͢

    90
  91. γϯϓϧͳྫ func invokeSpeak<X: Animal>(animal: X) -> Int { return animal.speak()

    } 91
  92. SILͰݟΔ // invokeSpeak<A>(animal:) sil hidden @$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF : $@convention(thin) <X where

    X : Animal> (@in_guaranteed X) -> Int { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "animal", argno 1 // id: %1 %2 = witness_method $X, #Animal.speak!1 : <Self where Self : Animal> (Self) -> () -> Int : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %3 %3 = apply %2<X>(%0) : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %4 return %3 : $Int // id: %4 } // end sil function '$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF' 92
  93. witnessϝιουͷऔΓग़͠ // invokeSpeak<A>(animal:) sil hidden @$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF : $@convention(thin) <X where

    X : Animal> (@in_guaranteed X) -> Int { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "animal", argno 1 // id: %1 %2 = witness_method $X, #Animal.speak!1 : <Self where Self : Animal> (Self) -> () -> Int : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %3 %3 = apply %2<X>(%0) : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %4 return %3 : $Int // id: %4 } // end sil function '$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF' 93
  94. ؔ਺ͷݺͼग़͠ // invokeSpeak<A>(animal:) sil hidden @$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF : $@convention(thin) <X where

    X : Animal> (@in_guaranteed X) -> Int { // %0 // users: %3, %1 bb0(%0 : $*X): debug_value_addr %0 : $*X, let, name "animal", argno 1 // id: %1 %2 = witness_method $X, #Animal.speak!1 : <Self where Self : Animal> (Self) -> () -> Int : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %3 %3 = apply %2<X>(%0) : $@convention(witness_method: Animal) <τ_0_0 where τ_0_0 : Animal> (@in_guaranteed τ_0_0) -> Int // user: %4 return %3 : $Int // id: %4 } // end sil function '$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF' 94
  95. LLVM-IRͰͷPWT @"$s1c3CatCAA6AnimalAAWP" = hidden constant [2 x i8*] [ i8*

    bitcast (%swift.protocol_conformance_descriptor* @"$s1c3CatCAA6AnimalAAMc" to i8*), i8* bitcast (i64 (%T1c3CatC**, %swift.type*, i8**)* @"$s1c3CatCAA6AnimalA2aDP5speakSiyFTW" to i8*) ], align 8 @"$s1c5StoneVAA6AnimalAAWP" = hidden constant [2 x i8*] [ i8* bitcast (%swift.protocol_conformance_descriptor* @"$s1c5StoneVAA6AnimalAAMc" to i8*), i8* bitcast (i64 (%T1c5StoneV*, %swift.type*, i8**)* @"$s1c5StoneVAA6AnimalA2aDP5speakSiyFTW" to i8*) ], align 8 95
  96. LLVM-IRͰͷར༻ଆ define hidden swiftcc i64 @"$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X, i8** %X.Animal) #0 { entry: %X1 = alloca %swift.type*, align 8 store %swift.type* %X, %swift.type** %X1, align 8 %1 = getelementptr inbounds i8*, i8** %X.Animal, i32 1 %2 = load i8*, i8** %1, align 8, !invariant.load !29 %3 = bitcast i8* %2 to i64 (%swift.opaque*, %swift.type*, i8**)* %4 = call swiftcc i64 %3(%swift.opaque* noalias nocapture swiftself %0, %swift.type* %X, i8** %X.Animal) ret i64 %4 } 96
  97. Signature func invokeSpeak<X: Animal>(animal: X) -> Int define hidden swiftcc

    i64 @"$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF"( %swift.opaque* noalias nocapture, %swift.type* %X, i8** %X.Animal) <X: Animal> → opaque pointer + meta type + witness table 97
  98. witnessϝιουͷऔΓग़͠ define hidden swiftcc i64 @"$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X, i8** %X.Animal) #0 { entry: %X1 = alloca %swift.type*, align 8 store %swift.type* %X, %swift.type** %X1, align 8 %1 = getelementptr inbounds i8*, i8** %X.Animal, i32 1 %2 = load i8*, i8** %1, align 8, !invariant.load !29 %3 = bitcast i8* %2 to i64 (%swift.opaque*, %swift.type*, i8**)* %4 = call swiftcc i64 %3(%swift.opaque* noalias nocapture swiftself %0, %swift.type* %X, i8** %X.Animal) ret i64 %4 } 98
  99. @"$s1c3CatCAA6AnimalAAWP" = hidden constant [2 x i8*] [ i8* bitcast

    (%swift.protocol_conformance_descriptor* @"$s1c3CatCAA6AnimalAAMc" to i8*), i8* bitcast (i64 (%T1c3CatC**, %swift.type*, i8**)* @"$s1c3CatCAA6AnimalA2aDP5speakSiyFTW" to i8*) ], align 8 @"$s1c5StoneVAA6AnimalAAWP" = hidden constant [2 x i8*] [ i8* bitcast (%swift.protocol_conformance_descriptor* @"$s1c5StoneVAA6AnimalAAMc" to i8*), i8* bitcast (i64 (%T1c5StoneV*, %swift.type*, i8**)* @"$s1c5StoneVAA6AnimalA2aDP5speakSiyFTW" to i8*) ], align 8 99
  100. witnessϝιουͷݺͼग़͠ define hidden swiftcc i64 @"$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF"( %swift.opaque* noalias nocapture, %swift.type*

    %X, i8** %X.Animal) #0 { entry: %X1 = alloca %swift.type*, align 8 store %swift.type* %X, %swift.type** %X1, align 8 %1 = getelementptr inbounds i8*, i8** %X.Animal, i32 1 %2 = load i8*, i8** %1, align 8, !invariant.load !29 %3 = bitcast i8* %2 to i64 (%swift.opaque*, %swift.type*, i8**)* %4 = call swiftcc i64 %3(%swift.opaque* noalias nocapture swiftself %0, %swift.type* %X, i8** %X.Animal) ret i64 %4 } 100
  101. ܕΫϥε෩ͷྫ protocol Addable { static var zero: Self { get

    } static func +(a: Self, b: Self) -> Self } extension Int : Addable { static var zero: Int { return 0 } } extension Sequence where Element : Addable { func sum() -> Element { return reduce(Element.zero) { $0 + $1 } } } let a = [1, 2, 3] // Array (struct) ͸ Sequence (protocol) print(a.sum()) // 6 101
  102. IntͷAddable @"$sSi1d7AddableAAWP" = hidden constant [3 x i8*] [ i8*

    bitcast (%swift.protocol_conformance_descriptor* @"$sSi1d7AddableAAMc" to i8*), i8* bitcast ( void (%TSi*, %swift.type*, %swift.type*, i8**)* @"$sSi1d7AddableA2aBP4zeroxvgZTW" to i8*), i8* bitcast ( void (%TSi*, %TSi*, %TSi*, %swift.type*, %swift.type*, i8**)* @"$sSi1d7AddableA2aBP1poiyxx_xtFZTW" to i8*) ], align 8 102
  103. sumϝιου define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,

    %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* call swiftcc void @"$sSTsE6reduceyqd__qd___qd__qd___7ElementQztKXEtKlF"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %8, i8* bitcast ( void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.refcounted*)* @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA" to i8*), %swift.opaque* %21, %swift.type* %Self, %swift.type* %Self.Element, i8** %Self.Sequence, %swift.opaque* noalias nocapture swiftself %1, %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) %22 = load %swift.error*, %swift.error** %swifterror, align 8 %23 = icmp ne %swift.error* %22, null br i1 %23, label %28, label %24 ; <label>:24: ; preds = %entry call void @swift_release(%swift.refcounted* %12) #5 call void @swift_release(%swift.refcounted* %12) #5 %25 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 1 %26 = load i8*, i8** %25, align 8, !invariant.load !23 %destroy = bitcast i8* %26 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* noalias %8, %swift.type* %Self.Element) #5 %27 = bitcast %swift.opaque* %8 to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %27) ret void ; <label>:28: ; preds = %entry %29 = phi %swift.error* [ %22, %entry ] store %swift.error* null, %swift.error** %swifterror, align 8 call void @swift_release(%swift.refcounted* %12) #5 unreachable } 103
  104. େ·͔ͳྲྀΕ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,

    %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: ; Element.zeroͷ༻ҙ ; Ϋϩʔδϟ؀ڥͷ༻ҙ ; Sequence.reduceͷݺͼग़͠ ; ྫ֎ϋϯυϦϯά ; <label>:24: ; ਖ਼ৗܥ, ΫϦϯφοϓ ; <label>:28: ; ҟৗܥ } 104
  105. Signature define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( ; ฦΓ஋ %swift.opaque* noalias

    nocapture sret, ; Array metatype %swift.type* %Self, ; Sequence PWT of Array i8** %Self.Sequence, ; Addable PWT of Int i8** %Self.Element.Addable, ; self (Array) %swift.opaque* noalias nocapture swiftself) 105
  106. Element.zeroͷ༻ҙ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,

    %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 106
  107. Array<Int>.Type͔ΒInt.TypeͷऔΓग़͠ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,

    %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 107
  108. IntͷVWTͷऔΓग़͠ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,

    %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 108
  109. VWT͔ΒsizeͷऔΓग़͠ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,

    %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 109
  110. zeroͷྖҬ֬อ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,

    %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 110
  111. PWT͔Βstatic funcͷऔΓग़͠ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture

    sret, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 111
  112. zeroͷݺͼग़͠ͱ֨ೲ define hidden swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyF"( %swift.opaque* noalias nocapture sret,

    %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable, %swift.opaque* noalias nocapture swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 %swifterror = alloca swifterror %swift.error*, align 8 store %swift.error* null, %swift.error** %swifterror, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %2 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %2, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %3 = bitcast %swift.type* %Self.Element to i8*** %4 = getelementptr inbounds i8**, i8*** %3, i64 -1 %Self.Element.valueWitnesses = load i8**, i8*** %4, align 8, !invariant.load !23, !dereferenceable !24 %5 = getelementptr inbounds i8*, i8** %Self.Element.valueWitnesses, i32 8 %6 = load i8*, i8** %5, align 8, !invariant.load !23 %size = ptrtoint i8* %6 to i64 %7 = alloca i8, i64 %size, align 16 call void @llvm.lifetime.start.p0i8(i64 -1, i8* %7) %8 = bitcast i8* %7 to %swift.opaque* %9 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 1 %10 = load i8*, i8** %9, align 8, !invariant.load !23 %11 = bitcast i8* %10 to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %11( %swift.opaque* noalias nocapture sret %8, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) 112
  113. Ϋϩʔδϟ؀ڥͷ༻ҙ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds

    ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 113
  114. 3ϫʔυͷstorageΛ࣋ͭΦϒδΣΫτͷੜ੒ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds

    ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 114
  115. [0]ʹArray.TypeΛ֨ೲ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr inbounds

    ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 115
  116. [1]ʹArrayͷSequence PWTΛ֨ೲ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr

    inbounds ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 116
  117. [2]ʹIntͷAddable PWTΛ֨ೲ %12 = call noalias %swift.refcounted* @swift_allocObject( %swift.type* getelementptr

    inbounds ( %swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 40, i64 7) #5 %13 = bitcast %swift.refcounted* %12 to <{ %swift.refcounted, [24 x i8] }>* %14 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %13, i32 0, i32 1 %15 = bitcast [24 x i8]* %14 to %swift.type** store %swift.type* %Self, %swift.type** %15, align 8 %16 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 1 %17 = bitcast %swift.type** %16 to i8*** store i8** %Self.Sequence, i8*** %17, align 8 %18 = getelementptr inbounds %swift.type*, %swift.type** %15, i32 2 %19 = bitcast %swift.type** %18 to i8*** store i8** %Self.Element.Addable, i8*** %19, align 8 %20 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %12) #5 %21 = bitcast %swift.refcounted* %12 to %swift.opaque* 117
  118. Sequence.reduceͷݺͼग़͠ call swiftcc void @"$sSTsE6reduceyqd__qd___qd__qd___7ElementQztKXEtKlF"( %swift.opaque* noalias nocapture sret %0,

    %swift.opaque* noalias nocapture %8, i8* bitcast ( void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.refcounted*)* @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA" to i8*), %swift.opaque* %21, %swift.type* %Self, %swift.type* %Self.Element, i8** %Self.Sequence, %swift.opaque* noalias nocapture swiftself %1, %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) 118
  119. call swiftcc void @"$sSTsE6reduceyqd__qd___qd__qd___7ElementQztKXEtKlF"( ; ฦΓ஋ %swift.opaque* noalias nocapture sret

    %0, ; ࡞ͬͨzero %swift.opaque* noalias nocapture %8, ; Ϋϩʔδϟͷؔ਺ϙΠϯλ i8* bitcast ( void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.refcounted*)* @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA" to i8*), ; ࡞ͬͨΫϩʔδϟ؀ڥ %swift.opaque* %21, ; Array.Type %swift.type* %Self, ; Int.Type %swift.type* %Self.Element, ; ArrayͷSequence PWT i8** %Self.Sequence, ; self (Array) %swift.opaque* noalias nocapture swiftself %1, ; ྫ֎ %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) 119
  120. ౉ͯ͠ΔΫϩʔδϟ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture sret,

    %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 120
  121. Signature define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( ; ฦΓ஋ %swift.opaque* noalias

    nocapture sret, ; Ҿ਺1 %swift.opaque* noalias nocapture, ; Ҿ਺2 %swift.opaque* noalias nocapture, ; Ϋϩʔδϟ؀ڥ %swift.refcounted* swiftself) 121
  122. ؀ڥ͔ΒArray.TypeͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture sret,

    %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 122
  123. ؀ڥ͔ΒArrayͷSequence PWTͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture

    sret, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 123
  124. ؀ڥ͔ΒIntͷAddable PWTͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture

    sret, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 124
  125. Ϋϩʔδϟຊମͷݺͼग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_TA"( %swift.opaque* noalias nocapture sret,

    %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself) #0 { entry: %Self1 = alloca %swift.type*, align 8 %4 = bitcast %swift.refcounted* %3 to <{ %swift.refcounted, [24 x i8] }>* %5 = getelementptr inbounds <{ %swift.refcounted, [24 x i8] }>, <{ %swift.refcounted, [24 x i8] }>* %4, i32 0, i32 1 %6 = bitcast [24 x i8]* %5 to %swift.type** %Self = load %swift.type*, %swift.type** %6, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 1 %8 = bitcast %swift.type** %7 to i8*** %Self.Sequence = load i8**, i8*** %8, align 8 %9 = getelementptr inbounds %swift.type*, %swift.type** %6, i32 2 %10 = bitcast %swift.type** %9 to i8*** %Self.Element.Addable = load i8**, i8*** %10, align 8 tail call swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) ret void } 125
  126. Ϋϩʔδϟຊମ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret,

    %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %3 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %3, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %4 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 2 %5 = load i8*, i8** %4, align 8, !invariant.load !23 %6 = bitcast i8* %5 to void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %6( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) ret void } 126
  127. Array.Type͔ΒInt.TypeͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret,

    %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %3 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %3, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %4 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 2 %5 = load i8*, i8** %4, align 8, !invariant.load !23 %6 = bitcast i8* %5 to void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %6( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) ret void } 127
  128. PWT͔Β+ͷऔΓग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret,

    %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %3 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %3, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %4 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 2 %5 = load i8*, i8** %4, align 8, !invariant.load !23 %6 = bitcast i8* %5 to void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %6( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) ret void } 128
  129. +ͷݺͼग़͠ define internal swiftcc void @"$sST1dAA7Addable7ElementRpzrlE3sumADyFA2D_ADtXEfU_"( %swift.opaque* noalias nocapture sret,

    %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %Self, i8** %Self.Sequence, i8** %Self.Element.Addable) #0 { entry: %Self1 = alloca %swift.type*, align 8 %Self.Element2 = alloca %swift.type*, align 8 store %swift.type* %Self, %swift.type** %Self1, align 8 %3 = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness( i64 0, i8** %Self.Sequence, %swift.type* %Self, %swift.protocol_requirement* @"$sSTTL", %swift.protocol_requirement* @"$s7ElementSTTl") #6 %Self.Element = extractvalue %swift.metadata_response %3, 0 store %swift.type* %Self.Element, %swift.type** %Self.Element2, align 8 %4 = getelementptr inbounds i8*, i8** %Self.Element.Addable, i32 2 %5 = load i8*, i8** %4, align 8, !invariant.load !23 %6 = bitcast i8* %5 to void (%swift.opaque*, %swift.opaque*, %swift.opaque*, %swift.type*, %swift.type*, i8**)* call swiftcc void %6( %swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.opaque* noalias nocapture %2, %swift.type* swiftself %Self.Element, %swift.type* %Self.Element, i8** %Self.Element.Addable) ret void } 129
  130. ·ͱΊ Generic͸MetatypeͱVWTͰಈ͘ Protocol͸PWTͰಈ͘ 130

  131. ͓ΘΓ ڵຯΛ࣋ͬͨਓ͸ͥͻ Discord΍Θ͍Θ͍swiftc΁ 131