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

ジェネリック型のメタタイプ

3781f49ea2c76d6ecf0c6cda46096d49?s=47 omochimetaru
September 12, 2018

 ジェネリック型のメタタイプ

3781f49ea2c76d6ecf0c6cda46096d49?s=128

omochimetaru

September 12, 2018
Tweet

Transcript

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

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

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

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

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

    Vector Field Offset Vector 5
  6. ϝλλΠϓͷྫ struct Stone { var a: Int = 0 var

    b: Bool = false var c: String = "" } 6
  7. @"$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
  8. @"$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
  9. @"$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
  10. @"$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
  11. @"$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
  12. class Cat { var a: Int = 0 var b:

    Bool = false var c: String = "" } 12
  13. @"$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
  14. @"$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
  15. @"$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
  16. @"$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
  17. @"$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
  18. @"$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
  19. @"$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
  20. Nominal Type Descriptor Metadata Accessor Generic Metadata Pattern Field Offset

    Vector Offset VTable Offset 20
  21. δΣωϦοΫΫϥε class RefBox<T> { var value: T init(value: T) {

    self.value = value } } 21
  22. ϨΠΞ΢τ class RefBox<Int> { var value: Int } class RefBox<String>

    { var value: String } 22
  23. RefBox<T>ͷϝλλΠϓ [-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
  24. 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
  25. 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
  26. 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
  27. 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
  28. 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
  29. 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
  30. 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
  31. ϝλλΠϓͱNTD ϝλλΠϓ͸ίϯΫϦʔτͳܕ͝ͱʹଘࡏ for Stone, Cat, RefBox<Int>, RefBox<String>, ... NTD͸ͦͷఆٛ͝ͱʹଘࡏ for

    Stone, Cat, RefBox, ... ↓ δΣωϦοΫͳ৔߹, NTDͷ৘ใ͔ΒϝλλΠϓ Λ࣮ߦ࣌ʹੜ੒ 31
  32. Metadata Accessor define hidden swiftcc %swift.metadata_response @"$S1g6RefBoxCMa"(i64, %swift.type*) %0: ϦΫΤετ

    %1: ύϥϝʔλܕͷϝλλΠϓ ϝλλΠϓΛฦ͢ ಺෦Ͱ swift_getGenericMetadata ΛݺͿ 32
  33. swift_getGenericMetadata MetadataResponse swift_getGenericMetadata( MetadataRequest request, const void * const *arguments,

    const TypeContextDescriptor *description); request: ϦΫΤετ arguments: ύϥϝʔλܕͷϝλλΠϓͷ഑ྻ description: Nominal Type Descriptor ϝλλΠϓΛฦ͢ 33
  34. Generic Metadata Pattern ੜ੒ʹඞཁͳ৘ใΛ࣋ͬͨΦϒδΣΫτɻ NTD͔ΒऔΓग़ͤΔɻ 34

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

    define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox<T>", i8*, i8**) 35
  36. Generic Metadata Instantiation Function define internal %swift.type* @"$S1g6RefBoxCMi"(%swift.type_descriptor*, i8**, i8*)

    %0: NTD %1: ύϥϝʔλܕͷϝλλΠϓͷ഑ྻ %2: Generic Metadata Pattern ߏங్தͷϝλλΠϓΛฦ͢ ಺෦Ͱ swift_allocateGenericClassMetadata ΛݺͿ 36
  37. swift_allocateGenericClassMetadata ClassMetadata * swift_allocateGenericClassMetadata( const ClassDescriptor *description, const void *arguments,

    const GenericClassMetadataPattern *pattern); description: NTD arguments: ύϥϝʔλܕͷϝλλΠϓͷ഑ྻ pattern: Generic Metadata Pattern ߏங్தͷϝλλΠϓΛฦ͢ 37
  38. Generic Metadata Completion Function define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox<T>",

    i8*, i8**) %0: ߏஙதͷϝλλΠϓ %1: ύϥϝʔλܕͷϝλλΠϓͷ഑ྻ %2: Generic Metadata Pattern ϝλλΠϓΛฦ͢ ಺෦Ͱ swift_initClassMetadata ΛݺͿ 38
  39. 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
  40. TypeLayout struct TypeLayout { ValueWitnessTypes::size size; ValueWitnessTypes::flags flags; ValueWitnessTypes::stride stride;

    } VWTͷ [8], [9], [10] ͷ෦෼ɻ 40
  41. define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox<T>", i8*, i8**) #0 {

    entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox<T>" 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<T>" 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<T>", %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
  42. define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox<T>", i8*, i8**) #0 {

    entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox<T>" 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<T>" 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<T>", %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
  43. define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox<T>", i8*, i8**) #0 {

    entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox<T>" 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<T>" 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<T>", %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
  44. define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox<T>", i8*, i8**) #0 {

    entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox<T>" 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<T>" 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<T>", %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
  45. define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox<T>", i8*, i8**) #0 {

    entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox<T>" 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<T>" 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<T>", %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
  46. define internal swiftcc %swift.metadata_response @"$S1g6RefBoxCMr"(%swift.type* %"RefBox<T>", i8*, i8**) #0 {

    entry: %classFields = alloca [1 x i8**], align 8 %T1 = alloca %swift.type*, align 8 %2 = bitcast %swift.type* %"RefBox<T>" 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<T>" 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<T>", %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
  47. δΣωϦοΫ஋ܕͷ৔߹ struct ValueBox<T> { var value: T } ࢖͏ϥϯλΠϜؔ਺͕มΘΔ swift_allocateGenericValueMetadata

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

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

  50. ίϯύΠϧ͞ΕͨίʔυͰͷΩϟογ ϡ RefBox<Int> ʹಛघԽ͞ΕͨΞΫηα define linkonce_odr hidden swiftcc %swift.metadata_response @"$S1a6RefBoxCySiGMa"(i64)

    Ωϟογϡม਺ @"$S1a6RefBoxCySiGML" lazy cache variable for type metadata for a.RefBox<Swift.Int> 50
  51. swift_getGenericMetadata ಺෦ͰͷΩϟογϡ ίϯύΠϧ͞ΕͨίʔυଆͰ16ϫʔυͷϝϞϦΛ ༻ҙ͢Δɻ ϥϯλΠϜ͕ͦ͜Λ࢖༻͢Δɻ @"$S1a6RefBoxCMI" = internal global [16

    x i8*] zeroinitializer, align 8 51
  52. উखʹ࢖͏ͨΊͷϋʔυΩϟετ 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<LazyGenericMetadataCache*>( generics.getInstantiationCache()->PrivateData); return lazyCache->get(); } 52
  53. ·ͱΊ • δΣωϦοΫܕͷϨΠΞ΢τ͸ίϯΫϦʔτͳ ܕ͝ͱʹ࡞ΒΕΔ • δΣωϦοΫܕͷϝλλΠϓ͸ Metadata Accessor ʹΑΓ lazy

    ʹੜ੒͞ΕΔ • ੜ੒ʹ͓͍ͯ͸ɺ Nominal Type Descriptor, Metadata Pattern, ϥϯλΠϜؔ਺͕࢖ΘΕΔ 53