Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

ࣗݾ঺հ • omochimetaru • Qoncept, Inc. • iOS, Mac, Web Frontend, Unity, Android • Swift, C++, TypeScript, Kotlin • Twitter, GitHub, Qiita, Qrunch • ήʔϜ, SwiftίϯύΠϥ 2

Slide 3

Slide 3 text

• Θ͍Θ͍swiftc https://iosdiscord.connpass.com • iOSDC (2018/09/02) SwiftͷδΣωϦΫε͸Ͳ͏΍ͬͯಈ͍͍ͯΔͷ ͔ίϯύΠϥͷιʔε͔Β୳Δ • Discord swift-developers-japan 3

Slide 4

Slide 4 text

Swift • Apple͕։ൃ • Φʔϓϯιʔε • ωΠςΟϒίϯύΠϧݴޠ • ஋ܕ • Generics • ϓϩτίϧࢦ޲ 4

Slide 5

Slide 5 text

Φʔϓϯιʔε https://github.com/apple/swift https://forums.swift.org 5

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

ࢀরܕ class Cat { var name: String = "ͨ·" } let a = Cat() let b = a b.name = "Έ͚" print(a.name) // Έ͚ TraceGC͸ແ͠ɻࢀরΧ΢ϯλΛ࢖͏ɻ 7

Slide 8

Slide 8 text

஋ܕ let a = [10, 20, 30] var b = a b[0] = 999 print(a) // [10, 20, 30] print(b) // [999, 20, 30] 8

Slide 9

Slide 9 text

struct Stone { var weight: Int = 5 } let size = MemoryLayout.size print(size) // 8 9

Slide 10

Slide 10 text

struct BigStone { var weight: Int = 5 var blob1: Int = 999 var blob2: Int = 999 var blob3: Int = 999 } let size = MemoryLayout.size print(size) // 32 10

Slide 11

Slide 11 text

Generics // Array let a: [Int] = [10, 20, 30] let b: [String] = a.map { String($0) } print(b) // ["10", "20", "30"] 11

Slide 12

Slide 12 text

func wrapArray(_ x: X) -> Array { return [x] } let a = wrapArray(Stone()) print(a[0].weight) // 5 12

Slide 13

Slide 13 text

Genericsͷ࣮૷ 13

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

$ swiftc -emit-ir a.swift 16

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Signature func takeX1(_ x: X) void @"$s1a6takeX1yyxlF"( %swift.opaque* noalias nocapture, %swift.type* %X) → opaque pointer + metatype 18

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

ୈ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

Slide 21

Slide 21 text

ୈ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

Slide 22

Slide 22 text

IntͷMetatype͸֎෦ఆٛ͞ΕΔɻ @"$sSiN" = external global %swift.type, align 8 22

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

stdlib/public/core/IntegerTypes.swift.gyb public struct Int { public var _value: Builtin.Int64 } gyb͸ςϯϓϨʔτݴޠ 24

Slide 25

Slide 25 text

include/swift/Runtime/Metadata.h using FullOpaqueMetadata = FullMetadata; #define BUILTIN_TYPE(Symbol, Name) \ SWIFT_RUNTIME_EXPORT \ const FullOpaqueMetadata METADATA_SYM(Symbol); #include "swift/Runtime/BuiltinTypes.def" 25

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

ܕ͕ෆ໌ͳ஋ͷૢ࡞ func takeX2(_ x: X) { let a = x } • ม਺aͷετϨʔδ֬อ • x͔Βaʹ஋ͷίϐʔ • aͷഁغ, ετϨʔδղ์ 27

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

Value Witness Table ͷৄࡉ 32

Slide 33

Slide 33 text

include/swift/ABI/Metadata.h template struct TargetValueWitnessTable; using ValueWitnessTable = TargetValueWitnessTable; template struct TargetValueWitnessTable { #define WANT_ONLY_REQUIRED_VALUE_WITNESSES #define VALUE_WITNESS(LOWER_ID, UPPER_ID) \ typename TargetValueWitnessTypes::LOWER_ID LOWER_ID; #include "swift/ABI/ValueWitness.def" } 33

Slide 34

Slide 34 text

template struct TargetValueWitnessTable { typename TargetValueWitnessTypes::initializeBufferWithCopyOfBuffer initializeBufferWithCopyOfBuffer; typename TargetValueWitnessTypes::destroy destroy; typename TargetValueWitnessTypes::initializeWithCopy initializeWithCopy; typename TargetValueWitnessTypes::assignWithCopy assignWithCopy; typename TargetValueWitnessTypes::initializeWithTake initializeWithTake; typename TargetValueWitnessTypes::assignWithTake assignWithTake; typename TargetValueWitnessTypes::getEnumTagSinglePayload getEnumTagSinglePayload; typename TargetValueWitnessTypes::storeEnumTagSinglePayload storeEnumTagSinglePayload; typename TargetValueWitnessTypes::size size; typename TargetValueWitnessTypes::flags flags; typename TargetValueWitnessTypes::stride stride; } 34

Slide 35

Slide 35 text

ݟ΍͘͢লུ struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 35

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

࠶ܝ func takeX2(_ x: X) { let a = x } 39

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

[8] = size struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 43

Slide 44

Slide 44 text

ετϨʔδͷ֬อ 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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

[2] = initializeWithCopy struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 46

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

[1] = destroy struct TargetValueWitnessTable { initializeBufferWithCopyOfBuffer; destroy; initializeWithCopy; assignWithCopy; initializeWithTake; assignWithTake; getEnumTagSinglePayload; storeEnumTagSinglePayload; size; flags; stride; } 49

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

ετϨʔδ͸allocaͰ֬อ͞Ε͍ͯͨͷͰɺ ղ์༻ͷ໋ྩ͸ಛʹͳ͠ 51

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

࠶ܝ Swift → SIL → LLVM IR → ࣮ߦϑΝΠϧ LLVM IRͷੜ੒͸SIL͔Βͷม׵ͱ࣮ͯ͠૷͞Εͯ ͍Δɻ 53

Slide 54

Slide 54 text

$ swiftc -emit-sil b.swift 54

Slide 57

Slide 57 text

ରԠ͢Δ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

Slide 58

Slide 58 text

SILؔ਺͝ͱʹLLVM IR͕ੜ੒͞ΕΔ swift/lib/IRGen/IRGenSIL.cpp void IRGenModule::emitSILFunction(SILFunction *f) 58

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

template 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(inst), \ std::forward(args)...); #include "swift/SIL/SILNodes.def" } llvm_unreachable("Not reachable, all cases handled"); } } 61

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

ίϐʔݩͷίϯύΠϧ࣌ܕ৘ใ(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

Slide 64

Slide 64 text

ܕ৘ใͷϝιουʹసૹ͢Δ 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

Slide 65

Slide 65 text

ܕ͕ͳͷͰaddrTI͸ OpaqueArchetypeTypeInfo lib/IRGen/GenArcheType.cpp class OpaqueArchetypeTypeInfo : public ResilientTypeInfo { }; 65

Slide 66

Slide 66 text

਌ΫϥεͷResilientTypeInfoͷ࣮૷͕ݺ͹ΕΔ lib/IRGen/ResilientTypeInfo.h template class ResilientTypeInfo : public WitnessSizedTypeInfo { void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T, bool isOutlined) const override { emitInitializeWithCopyCall(IGF, T, dest, src); } }; 66

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

// 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

Slide 73

Slide 73 text

// 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

Slide 74

Slide 74 text

// 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

Slide 75

Slide 75 text

// 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

Slide 76

Slide 76 text

// 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

Slide 77

Slide 77 text

// 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

Slide 78

Slide 78 text

// 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

Slide 79

Slide 79 text

Protocol 79

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

staticϝιουͷఆٛ protocol Animal { static func label() -> String } class Cat : Animal { static func label() -> String { return "ೣ" } } class Dog : Animal { static func label() -> String { return "ݘ" } } 81

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

Genericsͱ૊Έ߹ΘͤΔ protocol Animal { func speak() -> String } class Cat : Animal { func speak() -> String { return "ʹΌʔ" } } func invokeSpeak(animal: X) -> String { return animal.speak() } print(invokeSpeak(animal: Cat())) // ʹΌʔ 84

Slide 85

Slide 85 text

ܕΫϥε෩ 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

Slide 86

Slide 86 text

Protocolͷ࣮૷ 86

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

protocol Animal { func speak() -> Int } class Cat : Animal { func speak() -> Int { return 28 } } struct Stone : Animal { func speak() -> Int { return 14 } } 88

Slide 89

Slide 89 text

SILͰݟΔͱɺCatͱStoneͦΕͧΕʹɺ Animalͷwitness table͕͋Δ sil_witness_table hidden Cat: Animal module c { method #Animal.speak!1: (Self) -> () -> Int : @$s1c3CatCAA6AnimalA2aDP5speakSiyFTW // protocol witness for Animal.speak() in conformance Cat } sil_witness_table hidden Stone: Animal module c { method #Animal.speak!1: (Self) -> () -> Int : @$s1c5StoneVAA6AnimalA2aDP5speakSiyFTW // protocol witness for Animal.speak() in conformance Stone } 89

Slide 90

Slide 90 text

Protocol Witness Table Protocolʹ४ڌ͢ΔͨΊͷؔ਺ςʔϒϧ ͦͷProtocolͰنఆ͞ΕΔૢ࡞Λ͢Δؔ਺͕ೖͬ ͍ͯΔ ΠϯλʔϑΣʔε͸Opaqueͳදݱʹͳ͍ͬͯΔ ೖ͍ͬͯΔؔ਺͸ݸผͷܕΛظ଴͍ͯ͠ΔͨΊɺ Opaqueͳ஋ͱɺͦͷਅͷܕͷPWTΛϖΞͰऔΓ ճ͢ 90

Slide 91

Slide 91 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

Signature func invokeSpeak(animal: X) -> Int define hidden swiftcc i64 @"$s1c11invokeSpeak6animalSix_tAA6AnimalRzlF"( %swift.opaque* noalias nocapture, %swift.type* %X, i8** %X.Animal) → opaque pointer + meta type + witness table 97

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

@"$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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

ܕΫϥε෩ͷྫ 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

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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 ; :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 ; :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

Slide 104

Slide 104 text

େ·͔ͳྲྀΕ 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ͷݺͼग़͠ ; ྫ֎ϋϯυϦϯά ; :24: ; ਖ਼ৗܥ, ΫϦϯφοϓ ; :28: ; ҟৗܥ } 104

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

Array.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

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

Ϋϩʔδϟ؀ڥͷ༻ҙ %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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

[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

Slide 116

Slide 116 text

[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

Slide 117

Slide 117 text

[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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

౉ͯ͠ΔΫϩʔδϟ 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

Slide 121

Slide 121 text

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

Slide 122

Slide 122 text

؀ڥ͔Β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

Slide 123

Slide 123 text

؀ڥ͔Β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

Slide 124

Slide 124 text

؀ڥ͔Β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

Slide 125

Slide 125 text

Ϋϩʔδϟຊମͷݺͼग़͠ 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

Slide 126

Slide 126 text

Ϋϩʔδϟຊମ 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

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

+ͷݺͼग़͠ 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

Slide 130

Slide 130 text

·ͱΊ Generic͸MetatypeͱVWTͰಈ͘ Protocol͸PWTͰಈ͘ 130

Slide 131

Slide 131 text

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