Slide 1

Slide 1 text

δΣωϦοΫܕͷ ϝλλΠϓ Θ͍Θ͍swiftc #5 @omochimetaru 1

Slide 2

Slide 2 text

iOSDCͰԼهͷ࿩Λ͠·ͨ͠ SwiftͷδΣωϦΫε͸Ͳ͏΍ͬͯಈ͍͍ͯΔͷ͔ ίϯύΠϥͷιʔε͔Β୳Δ https://speakerdeck.com/omochi/ swiftfalsezienerikusuhadouyatutedong- iteirufalsekakonpairafalsesosukaratan-ru 2

Slide 3

Slide 3 text

ൃද಺༰Λ௒࣭͑ͨ໰ δΣωϦοΫܕͷϑΟʔϧυϨΠΞ΢τ͸ʁ δΣωϦοΫܕͷϑΟʔϧυΞΫηε͸ʁ δΣωϦοΫܕͷVWT͸Ͳ͏༻ҙ͢Δʁ Protocol WTͱͷؔ܎͸ʁ Associated type΁ͷδΣωϦοΫͳΞΫηε͸ʁ 3

Slide 4

Slide 4 text

ࠓ೔ͷ࿩ δΣωϦοΫܕͷϝλλΠϓ Protocol ͸·ͨࠓ౓ 4

Slide 5

Slide 5 text

ϝλλΠϓ ܕͷ৘ใ Value Witness Table Nominal Type Descriptor Generic Argument Vector Field Offset Vector 5

Slide 6

Slide 6 text

ϝλλΠϓͷྫ struct Stone { var a: Int = 0 var b: Bool = false var c: String = "" } 6

Slide 7

Slide 7 text

@"$S1g5StoneVMf" = <{ i8** getelementptr inbounds ( @"$S1g5StoneVWV", i32 0, i32 0), i64 0x200, <{ ... }>* @"$S1g5StoneVMn", i32 0, i32 8, i32 16, [4 x i8] zeroinitializer }>, align 8 7

Slide 8

Slide 8 text

@"$S1g5StoneVMf" = <{ i8** getelementptr inbounds ( @"$S1g5StoneVWV", i32 0, i32 0), i64 0x200, <{ ... }>* @"$S1g5StoneVMn", i32 0, i32 8, i32 16, [4 x i8] zeroinitializer }>, align 8 8

Slide 9

Slide 9 text

@"$S1g5StoneVMf" = <{ i8** getelementptr inbounds ( @"$S1g5StoneVWV", i32 0, i32 0), i64 0x200, <{ ... }>* @"$S1g5StoneVMn", i32 0, i32 8, i32 16, [4 x i8] zeroinitializer }>, align 8 9

Slide 10

Slide 10 text

@"$S1g5StoneVMf" = <{ i8** getelementptr inbounds ( @"$S1g5StoneVWV", i32 0, i32 0), i64 0x200, <{ ... }>* @"$S1g5StoneVMn", i32 0, i32 8, i32 16, [4 x i8] zeroinitializer }>, align 8 10

Slide 11

Slide 11 text

@"$S1g5StoneVMf" = <{ i8** getelementptr inbounds ( @"$S1g5StoneVWV", i32 0, i32 0), i64 0x200, <{ ... }>* @"$S1g5StoneVMn", i32 0, i32 8, i32 16, [4 x i8] zeroinitializer }>, align 8 11

Slide 12

Slide 12 text

class Cat { var a: Int = 0 var b: Bool = false var c: String = "" } 12

Slide 13

Slide 13 text

@"$S1g3CatCMf" = <{ void (%T1g3CatC*)* @"$S1g3CatCfD", i8** @"$SBoWV", i64 ptrtoint (%objc_class* @"$S1g3CatCMm" to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ ... }* @_DATA__TtC1g3Cat to i64), i64 1), i32 3, i32 0, i32 48, i16 7, i16 0, i32 200, i32 16, <{ ... }>* @"$S1g3CatCMn", i8* null, i64 (%T1g3CatC*)* @"$S1g3CatC1aSivg", void (i64, %T1g3CatC*)* @"$S1g3CatC1aSivs", { i8*, %TSi* } (i8*, %T1g3CatC*)* @"$S1g3CatC1aSivM", i1 (%T1g3CatC*)* @"$S1g3CatC1bSbvg", void (i1, %T1g3CatC*)* @"$S1g3CatC1bSbvs", { i8*, %TSb* } (i8*, %T1g3CatC*)* @"$S1g3CatC1bSbvM", { %swift.bridge*, i64 } (%T1g3CatC*)* @"$S1g3CatC1cSSvg", void (%swift.bridge*, i64, %T1g3CatC*)* @"$S1g3CatC1cSSvs", { i8*, %TSS* } (i8*, %T1g3CatC*)* @"$S1g3CatC1cSSvM", %T1g3CatC* (%T1g3CatC*)* @"$S1g3CatCACycfc", i64 16, i64 24, i64 32 }>, align 8 13

Slide 14

Slide 14 text

@"$S1g3CatCMf" = <{ void (%T1g3CatC*)* @"$S1g3CatCfD", i8** @"$SBoWV", i64 ptrtoint (%objc_class* @"$S1g3CatCMm" to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ ... }* @_DATA__TtC1g3Cat to i64), i64 1), i32 3, i32 0, i32 48, i16 7, i16 0, i32 200, i32 16, <{ ... }>* @"$S1g3CatCMn", i8* null, i64 (%T1g3CatC*)* @"$S1g3CatC1aSivg", void (i64, %T1g3CatC*)* @"$S1g3CatC1aSivs", { i8*, %TSi* } (i8*, %T1g3CatC*)* @"$S1g3CatC1aSivM", i1 (%T1g3CatC*)* @"$S1g3CatC1bSbvg", void (i1, %T1g3CatC*)* @"$S1g3CatC1bSbvs", { i8*, %TSb* } (i8*, %T1g3CatC*)* @"$S1g3CatC1bSbvM", { %swift.bridge*, i64 } (%T1g3CatC*)* @"$S1g3CatC1cSSvg", void (%swift.bridge*, i64, %T1g3CatC*)* @"$S1g3CatC1cSSvs", { i8*, %TSS* } (i8*, %T1g3CatC*)* @"$S1g3CatC1cSSvM", %T1g3CatC* (%T1g3CatC*)* @"$S1g3CatCACycfc", i64 16, i64 24, i64 32 }>, align 8 14

Slide 15

Slide 15 text

@"$S1g3CatCMf" = <{ void (%T1g3CatC*)* @"$S1g3CatCfD", i8** @"$SBoWV", i64 ptrtoint (%objc_class* @"$S1g3CatCMm" to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ ... }* @_DATA__TtC1g3Cat to i64), i64 1), i32 3, i32 0, i32 48, i16 7, i16 0, i32 200, i32 16, <{ ... }>* @"$S1g3CatCMn", i8* null, i64 (%T1g3CatC*)* @"$S1g3CatC1aSivg", void (i64, %T1g3CatC*)* @"$S1g3CatC1aSivs", { i8*, %TSi* } (i8*, %T1g3CatC*)* @"$S1g3CatC1aSivM", i1 (%T1g3CatC*)* @"$S1g3CatC1bSbvg", void (i1, %T1g3CatC*)* @"$S1g3CatC1bSbvs", { i8*, %TSb* } (i8*, %T1g3CatC*)* @"$S1g3CatC1bSbvM", { %swift.bridge*, i64 } (%T1g3CatC*)* @"$S1g3CatC1cSSvg", void (%swift.bridge*, i64, %T1g3CatC*)* @"$S1g3CatC1cSSvs", { i8*, %TSS* } (i8*, %T1g3CatC*)* @"$S1g3CatC1cSSvM", %T1g3CatC* (%T1g3CatC*)* @"$S1g3CatCACycfc", i64 16, i64 24, i64 32 }>, align 8 15

Slide 16

Slide 16 text

@"$S1g3CatCMf" = <{ void (%T1g3CatC*)* @"$S1g3CatCfD", i8** @"$SBoWV", i64 ptrtoint (%objc_class* @"$S1g3CatCMm" to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ ... }* @_DATA__TtC1g3Cat to i64), i64 1), i32 3, i32 0, i32 48, i16 7, i16 0, i32 200, i32 16, <{ ... }>* @"$S1g3CatCMn", i8* null, i64 (%T1g3CatC*)* @"$S1g3CatC1aSivg", void (i64, %T1g3CatC*)* @"$S1g3CatC1aSivs", { i8*, %TSi* } (i8*, %T1g3CatC*)* @"$S1g3CatC1aSivM", i1 (%T1g3CatC*)* @"$S1g3CatC1bSbvg", void (i1, %T1g3CatC*)* @"$S1g3CatC1bSbvs", { i8*, %TSb* } (i8*, %T1g3CatC*)* @"$S1g3CatC1bSbvM", { %swift.bridge*, i64 } (%T1g3CatC*)* @"$S1g3CatC1cSSvg", void (%swift.bridge*, i64, %T1g3CatC*)* @"$S1g3CatC1cSSvs", { i8*, %TSS* } (i8*, %T1g3CatC*)* @"$S1g3CatC1cSSvM", %T1g3CatC* (%T1g3CatC*)* @"$S1g3CatCACycfc", i64 16, i64 24, i64 32 }>, align 8 16

Slide 17

Slide 17 text

@"$S1g3CatCMf" = <{ void (%T1g3CatC*)* @"$S1g3CatCfD", i8** @"$SBoWV", i64 ptrtoint (%objc_class* @"$S1g3CatCMm" to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ ... }* @_DATA__TtC1g3Cat to i64), i64 1), i32 3, i32 0, i32 48, i16 7, i16 0, i32 200, i32 16, <{ ... }>* @"$S1g3CatCMn", i8* null, i64 (%T1g3CatC*)* @"$S1g3CatC1aSivg", void (i64, %T1g3CatC*)* @"$S1g3CatC1aSivs", { i8*, %TSi* } (i8*, %T1g3CatC*)* @"$S1g3CatC1aSivM", i1 (%T1g3CatC*)* @"$S1g3CatC1bSbvg", void (i1, %T1g3CatC*)* @"$S1g3CatC1bSbvs", { i8*, %TSb* } (i8*, %T1g3CatC*)* @"$S1g3CatC1bSbvM", { %swift.bridge*, i64 } (%T1g3CatC*)* @"$S1g3CatC1cSSvg", void (%swift.bridge*, i64, %T1g3CatC*)* @"$S1g3CatC1cSSvs", { i8*, %TSS* } (i8*, %T1g3CatC*)* @"$S1g3CatC1cSSvM", %T1g3CatC* (%T1g3CatC*)* @"$S1g3CatCACycfc", i64 16, i64 24, i64 32 }>, align 8 17

Slide 18

Slide 18 text

@"$S1g3CatCMf" = <{ void (%T1g3CatC*)* @"$S1g3CatCfD", i8** @"$SBoWV", i64 ptrtoint (%objc_class* @"$S1g3CatCMm" to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ ... }* @_DATA__TtC1g3Cat to i64), i64 1), i32 3, i32 0, i32 48, i16 7, i16 0, i32 200, i32 16, <{ ... }>* @"$S1g3CatCMn", i8* null, i64 (%T1g3CatC*)* @"$S1g3CatC1aSivg", void (i64, %T1g3CatC*)* @"$S1g3CatC1aSivs", { i8*, %TSi* } (i8*, %T1g3CatC*)* @"$S1g3CatC1aSivM", i1 (%T1g3CatC*)* @"$S1g3CatC1bSbvg", void (i1, %T1g3CatC*)* @"$S1g3CatC1bSbvs", { i8*, %TSb* } (i8*, %T1g3CatC*)* @"$S1g3CatC1bSbvM", { %swift.bridge*, i64 } (%T1g3CatC*)* @"$S1g3CatC1cSSvg", void (%swift.bridge*, i64, %T1g3CatC*)* @"$S1g3CatC1cSSvs", { i8*, %TSS* } (i8*, %T1g3CatC*)* @"$S1g3CatC1cSSvM", %T1g3CatC* (%T1g3CatC*)* @"$S1g3CatCACycfc", i64 16, i64 24, i64 32 }>, align 8 18

Slide 19

Slide 19 text

@"$S1g3CatCMf" = <{ void (%T1g3CatC*)* @"$S1g3CatCfD", i8** @"$SBoWV", i64 ptrtoint (%objc_class* @"$S1g3CatCMm" to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 add (i64 ptrtoint ({ ... }* @_DATA__TtC1g3Cat to i64), i64 1), i32 3, i32 0, i32 48, i16 7, i16 0, i32 200, i32 16, <{ ... }>* @"$S1g3CatCMn", i8* null, i64 (%T1g3CatC*)* @"$S1g3CatC1aSivg", void (i64, %T1g3CatC*)* @"$S1g3CatC1aSivs", { i8*, %TSi* } (i8*, %T1g3CatC*)* @"$S1g3CatC1aSivM", i1 (%T1g3CatC*)* @"$S1g3CatC1bSbvg", void (i1, %T1g3CatC*)* @"$S1g3CatC1bSbvs", { i8*, %TSb* } (i8*, %T1g3CatC*)* @"$S1g3CatC1bSbvM", { %swift.bridge*, i64 } (%T1g3CatC*)* @"$S1g3CatC1cSSvg", void (%swift.bridge*, i64, %T1g3CatC*)* @"$S1g3CatC1cSSvs", { i8*, %TSS* } (i8*, %T1g3CatC*)* @"$S1g3CatC1cSSvM", %T1g3CatC* (%T1g3CatC*)* @"$S1g3CatCACycfc", i64 16, i64 24, i64 32 }>, align 8 19

Slide 20

Slide 20 text

Nominal Type Descriptor Metadata Accessor Generic Metadata Pattern Field Offset Vector Offset VTable Offset 20

Slide 21

Slide 21 text

δΣωϦοΫΫϥε class RefBox { var value: T init(value: T) { self.value = value } } 21

Slide 22

Slide 22 text

ϨΠΞ΢τ class RefBox { var value: Int } class RefBox { var value: String } 22

Slide 23

Slide 23 text

RefBoxͷϝλλΠϓ [-2] destroy [-1] VWT (SBoWV) [ 0] isa pointer: %objc_class* [ 1] super: %objc_class* [ 2] %swift.opaque* [ 3] %swift.opaque* [ 4] i64 [ 5] i32, i32 [ 6] i32, i16, i16 [ 7] i32, i32 [ 8] Nominal Type Descriptor [ 9] i8* [10] T: %swift.type* -- Generic Argument Vector [11] value.getter -- VTable [12] value.setter [13] value.modify [14] init(value: T) [15] i32 16 -- Field Offset Vector 23

Slide 24

Slide 24 text

define hidden swiftcc void @"$S1g6RefBoxC5valuexvg"(%swift.opaque* noalias nocapture sret, %T1g6RefBoxC* swiftself) #0 { entry: %access-scratch = alloca [24 x i8], align 8 %2 = bitcast %T1g6RefBoxC* %1 to %swift.type** %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1g6RefBoxC, %T1g6RefBoxC* %1, i32 0, i32 0, i32 0 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = bitcast %swift.type* %5 to i64* %7 = getelementptr inbounds i64, i64* %6, i64 15 %8 = load i64, i64* %7, align 8, !invariant.load !33 %9 = bitcast %T1g6RefBoxC* %1 to i8* %10 = getelementptr inbounds i8, i8* %9, i64 %8 %.value = bitcast i8* %10 to %swift.opaque* %11 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.start.p0i8(i64 -1, i8* %11) %12 = bitcast %swift.opaque* %.value to i8* call void @swift_beginAccess(i8* %12, [24 x i8]* %access-scratch, i64 32, i8* null) #2 %13 = bitcast %swift.type* %3 to %swift.type** %14 = getelementptr inbounds %swift.type*, %swift.type** %13, i64 10 %T = load %swift.type*, %swift.type** %14, align 8, !invariant.load !33 %15 = bitcast %swift.type* %T to i8*** %16 = getelementptr inbounds i8**, i8*** %15, i64 -1 %T.valueWitnesses = load i8**, i8*** %16, align 8, !invariant.load !33, !dereferenceable !34 %17 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 2 %18 = load i8*, i8** %17, align 8, !invariant.load !33 %initializeWithCopy = bitcast i8* %18 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %19 = call %swift.opaque* %initializeWithCopy(%swift.opaque* noalias %0, %swift.opaque* noalias %.value, %swift.type* %T) #2 call void @swift_endAccess([24 x i8]* %access-scratch) #2 %20 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 24

Slide 25

Slide 25 text

define hidden swiftcc void @"$S1g6RefBoxC5valuexvg"(%swift.opaque* noalias nocapture sret, %T1g6RefBoxC* swiftself) #0 { entry: %access-scratch = alloca [24 x i8], align 8 %2 = bitcast %T1g6RefBoxC* %1 to %swift.type** %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1g6RefBoxC, %T1g6RefBoxC* %1, i32 0, i32 0, i32 0 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = bitcast %swift.type* %5 to i64* %7 = getelementptr inbounds i64, i64* %6, i64 15 %8 = load i64, i64* %7, align 8, !invariant.load !33 %9 = bitcast %T1g6RefBoxC* %1 to i8* %10 = getelementptr inbounds i8, i8* %9, i64 %8 %.value = bitcast i8* %10 to %swift.opaque* %11 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.start.p0i8(i64 -1, i8* %11) %12 = bitcast %swift.opaque* %.value to i8* call void @swift_beginAccess(i8* %12, [24 x i8]* %access-scratch, i64 32, i8* null) #2 %13 = bitcast %swift.type* %3 to %swift.type** %14 = getelementptr inbounds %swift.type*, %swift.type** %13, i64 10 %T = load %swift.type*, %swift.type** %14, align 8, !invariant.load !33 %15 = bitcast %swift.type* %T to i8*** %16 = getelementptr inbounds i8**, i8*** %15, i64 -1 %T.valueWitnesses = load i8**, i8*** %16, align 8, !invariant.load !33, !dereferenceable !34 %17 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 2 %18 = load i8*, i8** %17, align 8, !invariant.load !33 %initializeWithCopy = bitcast i8* %18 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %19 = call %swift.opaque* %initializeWithCopy(%swift.opaque* noalias %0, %swift.opaque* noalias %.value, %swift.type* %T) #2 call void @swift_endAccess([24 x i8]* %access-scratch) #2 %20 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 25

Slide 26

Slide 26 text

define hidden swiftcc void @"$S1g6RefBoxC5valuexvg"(%swift.opaque* noalias nocapture sret, %T1g6RefBoxC* swiftself) #0 { entry: %access-scratch = alloca [24 x i8], align 8 %2 = bitcast %T1g6RefBoxC* %1 to %swift.type** %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1g6RefBoxC, %T1g6RefBoxC* %1, i32 0, i32 0, i32 0 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = bitcast %swift.type* %5 to i64* %7 = getelementptr inbounds i64, i64* %6, i64 15 %8 = load i64, i64* %7, align 8, !invariant.load !33 %9 = bitcast %T1g6RefBoxC* %1 to i8* %10 = getelementptr inbounds i8, i8* %9, i64 %8 %.value = bitcast i8* %10 to %swift.opaque* %11 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.start.p0i8(i64 -1, i8* %11) %12 = bitcast %swift.opaque* %.value to i8* call void @swift_beginAccess(i8* %12, [24 x i8]* %access-scratch, i64 32, i8* null) #2 %13 = bitcast %swift.type* %3 to %swift.type** %14 = getelementptr inbounds %swift.type*, %swift.type** %13, i64 10 %T = load %swift.type*, %swift.type** %14, align 8, !invariant.load !33 %15 = bitcast %swift.type* %T to i8*** %16 = getelementptr inbounds i8**, i8*** %15, i64 -1 %T.valueWitnesses = load i8**, i8*** %16, align 8, !invariant.load !33, !dereferenceable !34 %17 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 2 %18 = load i8*, i8** %17, align 8, !invariant.load !33 %initializeWithCopy = bitcast i8* %18 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %19 = call %swift.opaque* %initializeWithCopy(%swift.opaque* noalias %0, %swift.opaque* noalias %.value, %swift.type* %T) #2 call void @swift_endAccess([24 x i8]* %access-scratch) #2 %20 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 26

Slide 27

Slide 27 text

define hidden swiftcc void @"$S1g6RefBoxC5valuexvg"(%swift.opaque* noalias nocapture sret, %T1g6RefBoxC* swiftself) #0 { entry: %access-scratch = alloca [24 x i8], align 8 %2 = bitcast %T1g6RefBoxC* %1 to %swift.type** %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1g6RefBoxC, %T1g6RefBoxC* %1, i32 0, i32 0, i32 0 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = bitcast %swift.type* %5 to i64* %7 = getelementptr inbounds i64, i64* %6, i64 15 %8 = load i64, i64* %7, align 8, !invariant.load !33 %9 = bitcast %T1g6RefBoxC* %1 to i8* %10 = getelementptr inbounds i8, i8* %9, i64 %8 %.value = bitcast i8* %10 to %swift.opaque* %11 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.start.p0i8(i64 -1, i8* %11) %12 = bitcast %swift.opaque* %.value to i8* call void @swift_beginAccess(i8* %12, [24 x i8]* %access-scratch, i64 32, i8* null) #2 %13 = bitcast %swift.type* %3 to %swift.type** %14 = getelementptr inbounds %swift.type*, %swift.type** %13, i64 10 %T = load %swift.type*, %swift.type** %14, align 8, !invariant.load !33 %15 = bitcast %swift.type* %T to i8*** %16 = getelementptr inbounds i8**, i8*** %15, i64 -1 %T.valueWitnesses = load i8**, i8*** %16, align 8, !invariant.load !33, !dereferenceable !34 %17 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 2 %18 = load i8*, i8** %17, align 8, !invariant.load !33 %initializeWithCopy = bitcast i8* %18 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %19 = call %swift.opaque* %initializeWithCopy(%swift.opaque* noalias %0, %swift.opaque* noalias %.value, %swift.type* %T) #2 call void @swift_endAccess([24 x i8]* %access-scratch) #2 %20 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 27

Slide 28

Slide 28 text

define hidden swiftcc void @"$S1g6RefBoxC5valuexvg"(%swift.opaque* noalias nocapture sret, %T1g6RefBoxC* swiftself) #0 { entry: %access-scratch = alloca [24 x i8], align 8 %2 = bitcast %T1g6RefBoxC* %1 to %swift.type** %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1g6RefBoxC, %T1g6RefBoxC* %1, i32 0, i32 0, i32 0 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = bitcast %swift.type* %5 to i64* %7 = getelementptr inbounds i64, i64* %6, i64 15 %8 = load i64, i64* %7, align 8, !invariant.load !33 %9 = bitcast %T1g6RefBoxC* %1 to i8* %10 = getelementptr inbounds i8, i8* %9, i64 %8 %.value = bitcast i8* %10 to %swift.opaque* %11 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.start.p0i8(i64 -1, i8* %11) %12 = bitcast %swift.opaque* %.value to i8* call void @swift_beginAccess(i8* %12, [24 x i8]* %access-scratch, i64 32, i8* null) #2 %13 = bitcast %swift.type* %3 to %swift.type** %14 = getelementptr inbounds %swift.type*, %swift.type** %13, i64 10 %T = load %swift.type*, %swift.type** %14, align 8, !invariant.load !33 %15 = bitcast %swift.type* %T to i8*** %16 = getelementptr inbounds i8**, i8*** %15, i64 -1 %T.valueWitnesses = load i8**, i8*** %16, align 8, !invariant.load !33, !dereferenceable !34 %17 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 2 %18 = load i8*, i8** %17, align 8, !invariant.load !33 %initializeWithCopy = bitcast i8* %18 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %19 = call %swift.opaque* %initializeWithCopy(%swift.opaque* noalias %0, %swift.opaque* noalias %.value, %swift.type* %T) #2 call void @swift_endAccess([24 x i8]* %access-scratch) #2 %20 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 28

Slide 29

Slide 29 text

define hidden swiftcc void @"$S1g6RefBoxC5valuexvg"(%swift.opaque* noalias nocapture sret, %T1g6RefBoxC* swiftself) #0 { entry: %access-scratch = alloca [24 x i8], align 8 %2 = bitcast %T1g6RefBoxC* %1 to %swift.type** %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1g6RefBoxC, %T1g6RefBoxC* %1, i32 0, i32 0, i32 0 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = bitcast %swift.type* %5 to i64* %7 = getelementptr inbounds i64, i64* %6, i64 15 %8 = load i64, i64* %7, align 8, !invariant.load !33 %9 = bitcast %T1g6RefBoxC* %1 to i8* %10 = getelementptr inbounds i8, i8* %9, i64 %8 %.value = bitcast i8* %10 to %swift.opaque* %11 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.start.p0i8(i64 -1, i8* %11) %12 = bitcast %swift.opaque* %.value to i8* call void @swift_beginAccess(i8* %12, [24 x i8]* %access-scratch, i64 32, i8* null) #2 %13 = bitcast %swift.type* %3 to %swift.type** %14 = getelementptr inbounds %swift.type*, %swift.type** %13, i64 10 %T = load %swift.type*, %swift.type** %14, align 8, !invariant.load !33 %15 = bitcast %swift.type* %T to i8*** %16 = getelementptr inbounds i8**, i8*** %15, i64 -1 %T.valueWitnesses = load i8**, i8*** %16, align 8, !invariant.load !33, !dereferenceable !34 %17 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 2 %18 = load i8*, i8** %17, align 8, !invariant.load !33 %initializeWithCopy = bitcast i8* %18 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %19 = call %swift.opaque* %initializeWithCopy(%swift.opaque* noalias %0, %swift.opaque* noalias %.value, %swift.type* %T) #2 call void @swift_endAccess([24 x i8]* %access-scratch) #2 %20 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 29

Slide 30

Slide 30 text

define hidden swiftcc void @"$S1g6RefBoxC5valuexvg"(%swift.opaque* noalias nocapture sret, %T1g6RefBoxC* swiftself) #0 { entry: %access-scratch = alloca [24 x i8], align 8 %2 = bitcast %T1g6RefBoxC* %1 to %swift.type** %3 = load %swift.type*, %swift.type** %2, align 8 %4 = getelementptr inbounds %T1g6RefBoxC, %T1g6RefBoxC* %1, i32 0, i32 0, i32 0 %5 = load %swift.type*, %swift.type** %4, align 8 %6 = bitcast %swift.type* %5 to i64* %7 = getelementptr inbounds i64, i64* %6, i64 15 %8 = load i64, i64* %7, align 8, !invariant.load !33 %9 = bitcast %T1g6RefBoxC* %1 to i8* %10 = getelementptr inbounds i8, i8* %9, i64 %8 %.value = bitcast i8* %10 to %swift.opaque* %11 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.start.p0i8(i64 -1, i8* %11) %12 = bitcast %swift.opaque* %.value to i8* call void @swift_beginAccess(i8* %12, [24 x i8]* %access-scratch, i64 32, i8* null) #2 %13 = bitcast %swift.type* %3 to %swift.type** %14 = getelementptr inbounds %swift.type*, %swift.type** %13, i64 10 %T = load %swift.type*, %swift.type** %14, align 8, !invariant.load !33 %15 = bitcast %swift.type* %T to i8*** %16 = getelementptr inbounds i8**, i8*** %15, i64 -1 %T.valueWitnesses = load i8**, i8*** %16, align 8, !invariant.load !33, !dereferenceable !34 %17 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 2 %18 = load i8*, i8** %17, align 8, !invariant.load !33 %initializeWithCopy = bitcast i8* %18 to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* %19 = call %swift.opaque* %initializeWithCopy(%swift.opaque* noalias %0, %swift.opaque* noalias %.value, %swift.type* %T) #2 call void @swift_endAccess([24 x i8]* %access-scratch) #2 %20 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.end.p0i8(i64 -1, i8* %20) ret void } 30

Slide 31

Slide 31 text

ϝλλΠϓͱNTD ϝλλΠϓ͸ίϯΫϦʔτͳܕ͝ͱʹଘࡏ for Stone, Cat, RefBox, RefBox, ... NTD͸ͦͷఆٛ͝ͱʹଘࡏ for Stone, Cat, RefBox, ... ↓ δΣωϦοΫͳ৔߹, NTDͷ৘ใ͔ΒϝλλΠϓ Λ࣮ߦ࣌ʹੜ੒ 31

Slide 32

Slide 32 text

Metadata Accessor define hidden swiftcc %swift.metadata_response @"$S1g6RefBoxCMa"(i64, %swift.type*) %0: ϦΫΤετ %1: ύϥϝʔλܕͷϝλλΠϓ ϝλλΠϓΛฦ͢ ಺෦Ͱ swift_getGenericMetadata ΛݺͿ 32

Slide 33

Slide 33 text

swift_getGenericMetadata MetadataResponse swift_getGenericMetadata( MetadataRequest request, const void * const *arguments, const TypeContextDescriptor *description); request: ϦΫΤετ arguments: ύϥϝʔλܕͷϝλλΠϓͷ഑ྻ description: Nominal Type Descriptor ϝλλΠϓΛฦ͢ 33

Slide 34

Slide 34 text

Generic Metadata Pattern ੜ੒ʹඞཁͳ৘ใΛ࣋ͬͨΦϒδΣΫτɻ NTD͔ΒऔΓग़ͤΔɻ 34

Slide 35

Slide 35 text

ܕύϥϝʔλͷ॥؀ʹରԠ͢ΔͨΊɺ ੜ੒͸2ϑΣʔζʹΘ͔Ε͍ͯΔɻ InstantiationFunction define internal %swift.type* @"$S1g6RefBoxCMi"(%swift.type_descriptor*, i8**, i8*) CompletionFunction define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox", i8*, i8**) 35

Slide 36

Slide 36 text

Generic Metadata Instantiation Function define internal %swift.type* @"$S1g6RefBoxCMi"(%swift.type_descriptor*, i8**, i8*) %0: NTD %1: ύϥϝʔλܕͷϝλλΠϓͷ഑ྻ %2: Generic Metadata Pattern ߏங్தͷϝλλΠϓΛฦ͢ ಺෦Ͱ swift_allocateGenericClassMetadata ΛݺͿ 36

Slide 37

Slide 37 text

swift_allocateGenericClassMetadata ClassMetadata * swift_allocateGenericClassMetadata( const ClassDescriptor *description, const void *arguments, const GenericClassMetadataPattern *pattern); description: NTD arguments: ύϥϝʔλܕͷϝλλΠϓͷ഑ྻ pattern: Generic Metadata Pattern ߏங్தͷϝλλΠϓΛฦ͢ 37

Slide 38

Slide 38 text

Generic Metadata Completion Function define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox", i8*, i8**) %0: ߏஙதͷϝλλΠϓ %1: ύϥϝʔλܕͷϝλλΠϓͷ഑ྻ %2: Generic Metadata Pattern ϝλλΠϓΛฦ͢ ಺෦Ͱ swift_initClassMetadata ΛݺͿ 38

Slide 39

Slide 39 text

swift_initClassMetadata void swift_initClassMetadata(ClassMetadata *self, ClassMetadata *super, ClassLayoutFlags flags, size_t numFields, const TypeLayout * const *fieldTypes, size_t *fieldOffsets); fieldTypes: ϑΟʔϧυͷܕͷ৘ใ fieldOffsets: Field Offset Vector 39

Slide 40

Slide 40 text

TypeLayout struct TypeLayout { ValueWitnessTypes::size size; ValueWitnessTypes::flags flags; ValueWitnessTypes::stride stride; } VWTͷ [8], [9], [10] ͷ෦෼ɻ 40

Slide 41

Slide 41 text

define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox", i8*, i8**) #0 { entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox" to i64* %3 = getelementptr inbounds i64, i64* %2, i64 15 %4 = bitcast [1 x i8**]* %classFields to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %4) %5 = getelementptr inbounds [1 x i8**], [1 x i8**]* %classFields, i32 0, i32 0 %6 = bitcast %swift.type* %"RefBox" to %swift.type** %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i64 10 %T = load %swift.type*, %swift.type** %7, align 8, !invariant.load !33 %8 = call swiftcc %swift.metadata_response @swift_checkMetadataState(i64 319, %swift.type* %T) %9 = extractvalue %swift.metadata_response %8, 0 %10 = extractvalue %swift.metadata_response %8, 1 %11 = icmp ule i64 %10, 63 br i1 %11, label %dependency-satisfied, label %metadata-dependencies.cont dependency-satisfied: ; preds = %entry store %swift.type* %9, %swift.type** %T1, align 8 %12 = bitcast %swift.type* %9 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses = load i8**, i8*** %13, align 8, !invariant.load !33, !dereferenceable !34 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 8 %15 = getelementptr inbounds i8**, i8*** %5, i32 0 store i8** %14, i8*** %15, align 8 call void @swift_initClassMetadata(%swift.type* %"RefBox", %swift.type* null, i64 0, i64 1, i8*** %5, i64* %3) %16 = bitcast i8*** %5 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) br label %metadata-dependencies.cont metadata-dependencies.cont: ; preds = %dependency-satisfied, %entry %17 = phi %swift.type* [ %9, %entry ], [ null, %dependency-satisfied ] %18 = phi i64 [ 63, %entry ], [ 0, %dependency-satisfied ] %19 = insertvalue %swift.metadata_response undef, %swift.type* %17, 0 %20 = insertvalue %swift.metadata_response %19, i64 %18, 1 ret %swift.metadata_response %20 } 41

Slide 42

Slide 42 text

define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox", i8*, i8**) #0 { entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox" to i64* %3 = getelementptr inbounds i64, i64* %2, i64 15 %4 = bitcast [1 x i8**]* %classFields to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %4) %5 = getelementptr inbounds [1 x i8**], [1 x i8**]* %classFields, i32 0, i32 0 %6 = bitcast %swift.type* %"RefBox" to %swift.type** %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i64 10 %T = load %swift.type*, %swift.type** %7, align 8, !invariant.load !33 %8 = call swiftcc %swift.metadata_response @swift_checkMetadataState(i64 319, %swift.type* %T) %9 = extractvalue %swift.metadata_response %8, 0 %10 = extractvalue %swift.metadata_response %8, 1 %11 = icmp ule i64 %10, 63 br i1 %11, label %dependency-satisfied, label %metadata-dependencies.cont dependency-satisfied: ; preds = %entry store %swift.type* %9, %swift.type** %T1, align 8 %12 = bitcast %swift.type* %9 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses = load i8**, i8*** %13, align 8, !invariant.load !33, !dereferenceable !34 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 8 %15 = getelementptr inbounds i8**, i8*** %5, i32 0 store i8** %14, i8*** %15, align 8 call void @swift_initClassMetadata(%swift.type* %"RefBox", %swift.type* null, i64 0, i64 1, i8*** %5, i64* %3) %16 = bitcast i8*** %5 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) br label %metadata-dependencies.cont metadata-dependencies.cont: ; preds = %dependency-satisfied, %entry %17 = phi %swift.type* [ %9, %entry ], [ null, %dependency-satisfied ] %18 = phi i64 [ 63, %entry ], [ 0, %dependency-satisfied ] %19 = insertvalue %swift.metadata_response undef, %swift.type* %17, 0 %20 = insertvalue %swift.metadata_response %19, i64 %18, 1 ret %swift.metadata_response %20 } 42

Slide 43

Slide 43 text

define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox", i8*, i8**) #0 { entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox" to i64* %3 = getelementptr inbounds i64, i64* %2, i64 15 %4 = bitcast [1 x i8**]* %classFields to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %4) %5 = getelementptr inbounds [1 x i8**], [1 x i8**]* %classFields, i32 0, i32 0 %6 = bitcast %swift.type* %"RefBox" to %swift.type** %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i64 10 %T = load %swift.type*, %swift.type** %7, align 8, !invariant.load !33 %8 = call swiftcc %swift.metadata_response @swift_checkMetadataState(i64 319, %swift.type* %T) %9 = extractvalue %swift.metadata_response %8, 0 %10 = extractvalue %swift.metadata_response %8, 1 %11 = icmp ule i64 %10, 63 br i1 %11, label %dependency-satisfied, label %metadata-dependencies.cont dependency-satisfied: ; preds = %entry store %swift.type* %9, %swift.type** %T1, align 8 %12 = bitcast %swift.type* %9 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses = load i8**, i8*** %13, align 8, !invariant.load !33, !dereferenceable !34 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 8 %15 = getelementptr inbounds i8**, i8*** %5, i32 0 store i8** %14, i8*** %15, align 8 call void @swift_initClassMetadata(%swift.type* %"RefBox", %swift.type* null, i64 0, i64 1, i8*** %5, i64* %3) %16 = bitcast i8*** %5 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) br label %metadata-dependencies.cont metadata-dependencies.cont: ; preds = %dependency-satisfied, %entry %17 = phi %swift.type* [ %9, %entry ], [ null, %dependency-satisfied ] %18 = phi i64 [ 63, %entry ], [ 0, %dependency-satisfied ] %19 = insertvalue %swift.metadata_response undef, %swift.type* %17, 0 %20 = insertvalue %swift.metadata_response %19, i64 %18, 1 ret %swift.metadata_response %20 } 43

Slide 44

Slide 44 text

define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox", i8*, i8**) #0 { entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox" to i64* %3 = getelementptr inbounds i64, i64* %2, i64 15 %4 = bitcast [1 x i8**]* %classFields to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %4) %5 = getelementptr inbounds [1 x i8**], [1 x i8**]* %classFields, i32 0, i32 0 %6 = bitcast %swift.type* %"RefBox" to %swift.type** %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i64 10 %T = load %swift.type*, %swift.type** %7, align 8, !invariant.load !33 %8 = call swiftcc %swift.metadata_response @swift_checkMetadataState(i64 319, %swift.type* %T) %9 = extractvalue %swift.metadata_response %8, 0 %10 = extractvalue %swift.metadata_response %8, 1 %11 = icmp ule i64 %10, 63 br i1 %11, label %dependency-satisfied, label %metadata-dependencies.cont dependency-satisfied: ; preds = %entry store %swift.type* %9, %swift.type** %T1, align 8 %12 = bitcast %swift.type* %9 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses = load i8**, i8*** %13, align 8, !invariant.load !33, !dereferenceable !34 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 8 %15 = getelementptr inbounds i8**, i8*** %5, i32 0 store i8** %14, i8*** %15, align 8 call void @swift_initClassMetadata(%swift.type* %"RefBox", %swift.type* null, i64 0, i64 1, i8*** %5, i64* %3) %16 = bitcast i8*** %5 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) br label %metadata-dependencies.cont metadata-dependencies.cont: ; preds = %dependency-satisfied, %entry %17 = phi %swift.type* [ %9, %entry ], [ null, %dependency-satisfied ] %18 = phi i64 [ 63, %entry ], [ 0, %dependency-satisfied ] %19 = insertvalue %swift.metadata_response undef, %swift.type* %17, 0 %20 = insertvalue %swift.metadata_response %19, i64 %18, 1 ret %swift.metadata_response %20 } 44

Slide 45

Slide 45 text

define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox", i8*, i8**) #0 { entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox" to i64* %3 = getelementptr inbounds i64, i64* %2, i64 15 %4 = bitcast [1 x i8**]* %classFields to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %4) %5 = getelementptr inbounds [1 x i8**], [1 x i8**]* %classFields, i32 0, i32 0 %6 = bitcast %swift.type* %"RefBox" to %swift.type** %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i64 10 %T = load %swift.type*, %swift.type** %7, align 8, !invariant.load !33 %8 = call swiftcc %swift.metadata_response @swift_checkMetadataState(i64 319, %swift.type* %T) %9 = extractvalue %swift.metadata_response %8, 0 %10 = extractvalue %swift.metadata_response %8, 1 %11 = icmp ule i64 %10, 63 br i1 %11, label %dependency-satisfied, label %metadata-dependencies.cont dependency-satisfied: ; preds = %entry store %swift.type* %9, %swift.type** %T1, align 8 %12 = bitcast %swift.type* %9 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses = load i8**, i8*** %13, align 8, !invariant.load !33, !dereferenceable !34 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 8 %15 = getelementptr inbounds i8**, i8*** %5, i32 0 store i8** %14, i8*** %15, align 8 call void @swift_initClassMetadata(%swift.type* %"RefBox", %swift.type* null, i64 0, i64 1, i8*** %5, i64* %3) %16 = bitcast i8*** %5 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) br label %metadata-dependencies.cont metadata-dependencies.cont: ; preds = %dependency-satisfied, %entry %17 = phi %swift.type* [ %9, %entry ], [ null, %dependency-satisfied ] %18 = phi i64 [ 63, %entry ], [ 0, %dependency-satisfied ] %19 = insertvalue %swift.metadata_response undef, %swift.type* %17, 0 %20 = insertvalue %swift.metadata_response %19, i64 %18, 1 ret %swift.metadata_response %20 } 45

Slide 46

Slide 46 text

define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox", i8*, i8**) #0 { entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox" to i64* %3 = getelementptr inbounds i64, i64* %2, i64 15 %4 = bitcast [1 x i8**]* %classFields to i8* call void @llvm.lifetime.start.p0i8(i64 8, i8* %4) %5 = getelementptr inbounds [1 x i8**], [1 x i8**]* %classFields, i32 0, i32 0 %6 = bitcast %swift.type* %"RefBox" to %swift.type** %7 = getelementptr inbounds %swift.type*, %swift.type** %6, i64 10 %T = load %swift.type*, %swift.type** %7, align 8, !invariant.load !33 %8 = call swiftcc %swift.metadata_response @swift_checkMetadataState(i64 319, %swift.type* %T) %9 = extractvalue %swift.metadata_response %8, 0 %10 = extractvalue %swift.metadata_response %8, 1 %11 = icmp ule i64 %10, 63 br i1 %11, label %dependency-satisfied, label %metadata-dependencies.cont dependency-satisfied: ; preds = %entry store %swift.type* %9, %swift.type** %T1, align 8 %12 = bitcast %swift.type* %9 to i8*** %13 = getelementptr inbounds i8**, i8*** %12, i64 -1 %.valueWitnesses = load i8**, i8*** %13, align 8, !invariant.load !33, !dereferenceable !34 %14 = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 8 %15 = getelementptr inbounds i8**, i8*** %5, i32 0 store i8** %14, i8*** %15, align 8 call void @swift_initClassMetadata(%swift.type* %"RefBox", %swift.type* null, i64 0, i64 1, i8*** %5, i64* %3) %16 = bitcast i8*** %5 to i8* call void @llvm.lifetime.end.p0i8(i64 8, i8* %16) br label %metadata-dependencies.cont metadata-dependencies.cont: ; preds = %dependency-satisfied, %entry %17 = phi %swift.type* [ %9, %entry ], [ null, %dependency-satisfied ] %18 = phi i64 [ 63, %entry ], [ 0, %dependency-satisfied ] %19 = insertvalue %swift.metadata_response undef, %swift.type* %17, 0 %20 = insertvalue %swift.metadata_response %19, i64 %18, 1 ret %swift.metadata_response %20 } 46

Slide 47

Slide 47 text

δΣωϦοΫ஋ܕͷ৔߹ struct ValueBox { var value: T } ࢖͏ϥϯλΠϜؔ਺͕มΘΔ swift_allocateGenericValueMetadata swift_initStructMetadata 47

Slide 48

Slide 48 text

δΣωϦοΫ஋ܕͷVWT VWT͸ύϥϝʔλܕ͕ҟͳΔϝλλΠϓؒͰڞ ௨ɻ ValueBox ͷϝλλΠϓ͔Β T ͷVWTΛऔΓ ग़͢൚༻ͳ࣮૷ɻ 48

Slide 49

Slide 49 text

ϝλλΠϓͷΩϟογϡ • ίϯύΠϧ͞ΕͨίʔυͰͷΩϟογϡ • swift_getGenericMetadata ಺෦ͰͷΩϟο γϡ 49

Slide 50

Slide 50 text

ίϯύΠϧ͞ΕͨίʔυͰͷΩϟογ ϡ RefBox ʹಛघԽ͞ΕͨΞΫηα define linkonce_odr hidden swiftcc %swift.metadata_response @"$S1a6RefBoxCySiGMa"(i64) Ωϟογϡม਺ @"$S1a6RefBoxCySiGML" lazy cache variable for type metadata for a.RefBox 50

Slide 51

Slide 51 text

swift_getGenericMetadata ಺෦ͰͷΩϟογϡ ίϯύΠϧ͞ΕͨίʔυଆͰ16ϫʔυͷϝϞϦΛ ༻ҙ͢Δɻ ϥϯλΠϜ͕ͦ͜Λ࢖༻͢Δɻ @"$S1a6RefBoxCMI" = internal global [16 x i8*] zeroinitializer, align 8 51

Slide 52

Slide 52 text

উखʹ࢖͏ͨΊͷϋʔυΩϟετ static GenericMetadataCache &getCache( const TypeGenericContextDescriptorHeader &generics) { // Keep this assert even if you change the representation above. static_assert(sizeof(LazyGenericMetadataCache) <= sizeof(GenericMetadataInstantiationCache::PrivateData), "metadata cache is larger than the allowed space"); auto lazyCache = reinterpret_cast( generics.getInstantiationCache()->PrivateData); return lazyCache->get(); } 52

Slide 53

Slide 53 text

·ͱΊ • δΣωϦοΫܕͷϨΠΞ΢τ͸ίϯΫϦʔτͳ ܕ͝ͱʹ࡞ΒΕΔ • δΣωϦοΫܕͷϝλλΠϓ͸ Metadata Accessor ʹΑΓ lazy ʹੜ੒͞ΕΔ • ੜ੒ʹ͓͍ͯ͸ɺ Nominal Type Descriptor, Metadata Pattern, ϥϯλΠϜؔ਺͕࢖ΘΕΔ 53