Slide 1

Slide 1 text

IRGen͔Βݟͨ Type Metadata Θ͍Θ͍swiftc #3, 2018/06/22 omochimetaru @ 1

Slide 2

Slide 2 text

Type Metadata ܕʹ͍ͭͯͷ৘ใΛอ࣋ͨ͠Swift Runtime಺෦ͷσʔλɻ ϓϩύςΟ΍਌ΫϥεͳͲͷ৘ใΛอ࣋͢Δɻ ϦϑϨΫγϣϯ(Mirror API)ͷ಺෦Ͱ࢖༻͞ΕΔɻ 2

Slide 3

Slide 3 text

Metatype Swiftݴޠʹ͓͚ΔܕΛද͢ΦϒδΣΫτɻ // ܕͷܕͷม਺ʹܕͷΦϒδΣΫτΛ୅ೖ let stoneType: Stone.Type = Stone.self // ܕͷܕͷαϒλΠϐϯά let anyType: Any.Type = stoneType // ಈతʹܕͷΦϒδΣΫτΛऔಘ let dynamicType = type(of: Stone()) 3

Slide 4

Slide 4 text

Metatype -> Type Metadata Any.Type͸Type Metadata΁ͷϙΠϯλɻ struct Stone {} var type: Any.Type = Stone.self var typePtr: UnsafePointer = unsafeBitCast(type, to: UnsafePointer.self) var kind: Int = typePtr.pointee print(kind) // 1 structͷ৔߹͸ઌ಄ʹkind=1͕ೖͬͯΔɻ 4

Slide 5

Slide 5 text

Type Metadataͷ࢓༷ TypeMetadata.rst https://github.com/apple/swift/blob/master/docs/ABI/ TypeMetadata.rst Kind: Struct=1, Enum=2, Optional=3, Function=10, Protocol=12... 5

Slide 6

Slide 6 text

structͷType Metadata [-1]: Value Witness Table [ 0]: Kind = 1 [ 1]: Nominal Type Descriptor [..]: (Generic Argument Vector)* [..]: (Field Offset)* 6

Slide 7

Slide 7 text

Value Witness Table ܕ͕ෆ໌ͳ஋ʹରͯ͠ϙϦϞʔϑΟζϜΛ࣮ݱɻ ʮίϐʔ͢Δؔ਺ʯͳͲɻ Nominal Type Descriptor ϓϩύςΟͷ৘ใͳͲΛఏڙɻ 7

Slide 8

Slide 8 text

offset=0ʹkind͕͋Δཧ༝ ObjectiveCͰ͸ܕ΋ΦϒδΣΫτɻ struct objc_class { struct objc_class *isa; struct objc_class *super_class; const char *name; ... }; ϙΠϯλ͸੔਺ͰݟΔͱ>=2048ɻ kind>=2048͸ObjCΫϥεɻ 8

Slide 9

Slide 9 text

LLVM-IR struct Stone { var weight: Int = 3 var size: Int = 4 } $ swiftc -emit-ir b.swift 9

Slide 10

Slide 10 text

LLVM-IR %T1b5StoneV = type <{ %TSi, %TSi }> %TSi = type <{ i64 }> @"$S1b5StoneVWV" = ... @"$S1b5StoneVMn" = ... @"$S1b5StoneVMf" = ... @"$S1b5StoneVMF" = ... @"$S1b5StoneVN" = ... 10

Slide 11

Slide 11 text

mangleͷಡղ Mangling.rst https://github.com/apple/swift/blob/master/docs/ABI/ Mangling.rst 11

Slide 12

Slide 12 text

swift demangle $ swift demangle -expand '$S1b5StoneVWV' Demangling for $S1b5StoneVWV kind=Global kind=ValueWitnessTable kind=Type kind=Structure kind=Module, text="b" kind=Identifier, text="Stone" $S1b5StoneVWV ---> value witness table for b.Stone 12

Slide 13

Slide 13 text

LLVM-IR demangle $S1b5StoneVWV: value witness table $S1b5StoneVMn: nominal type descriptor $S1b5StoneVMf: full type metadata $S1b5StoneVMF: reflection metadata field descriptor $S1b5StoneVN : type metadata 13

Slide 14

Slide 14 text

Full Type Metadata ͱ Type Matadata Type MetadataͷΦϑηοτ͢Δલͷߏ଄ମɻ Αͬͯ [0] ʹ Value Witness Table ͕ೖ͍ͬͯΔɻ Type Metadata͸͜ΕΛKind·ͰΦϑηοτͨ͠ϙΠϯλɻ 14

Slide 15

Slide 15 text

Full Type Metadata ΛಡΉ @"$S1b5StoneVMf" = internal constant <{ ... }> <{ i8** getelementptr inbounds ( [11 x i8*], [11 x i8*]* @"$S1b5StoneVWV", i32 0, i32 0), i64 1, <{ ... }>* @"$S1b5StoneVMn", i32 0, i32 8 }>, align 8 15

Slide 16

Slide 16 text

Type Metadata ΛಡΉ @"$S1b5StoneVN" = hidden alias %swift.type, bitcast ( i64* getelementptr inbounds ( <{ i8**, i64, <{ ... }>*, i32, i32 }>, <{ ... }>* @"$S1b5StoneVMf", i32 0, i32 1) to %swift.type*) 16

Slide 17

Slide 17 text

Type Metadata @ IRGen in swiftc swift::irgen::emitStructMetadata at swift/lib/IRGen/GenMeta.cpp:2796 swift::irgen::IRGenModule::emitStructDecl at swift/lib/IRGen/GenStruct.cpp:862 swift::irgen::IRGenModule::emitGlobalDecl at swift/lib/IRGen/GenDecl.cpp:2065 swift::irgen::IRGenModule::emitSourceFile at swift/lib/IRGen/GenDecl.cpp:484 performIRGeneration at swift/lib/IRGen/IRGen.cpp:764 swift::performIRGeneration at swift/lib/IRGen/IRGen.cpp:1086 generateIR at swift/lib/FrontendTool/FrontendTool.cpp:1106 performCompileStepsPostSILGen at swift/lib/FrontendTool/FrontendTool.cpp:1330 performCompile at swift/lib/FrontendTool/FrontendTool.cpp:980 swift::performFrontend at swift/lib/FrontendTool/FrontendTool.cpp:1792 main at swift/tools/driver/driver.cpp:175 17

Slide 18

Slide 18 text

Type Metadata @ IRGen in swiftc void irgen::emitStructMetadata(IRGenModule &IGM, StructDecl *structDecl) { ConstantInitBuilder initBuilder(IGM); auto init = initBuilder.beginStruct(); ... if (...) { } else { StructMetadataBuilder builder(IGM, structDecl, init); builder.layout(); ... } IGM.defineTypeMetadata(..., init.finishAndCreateFuture()); ... } 18

Slide 19

Slide 19 text

template class NominalMetadataVisitor { ... public: void layout() { asImpl().addValueWitnessTable(); ... asImpl().addMetadataFlags(); } }; template class StructMetadataVisitor : public NominalMetadataVisitor { ... public: void layout() { super::layout(); asImpl().addNominalTypeDescriptor(); ... asImpl().addGenericFields(Target, Target->getDeclaredTypeInContext()); for (VarDecl *prop : Target->getStoredProperties()) asImpl().addFieldOffset(prop); ... } }; 19

Slide 20

Slide 20 text

namespace MetadataAdjustmentIndex { enum : unsigned { Class = 2, ValueType = 1, None = 0, }; } llvm::GlobalValue *IRGenModule::defineTypeMetadata(...) { ... unsigned adjustmentIndex; ... if (...) { ... } else { ... adjustmentIndex = MetadataAdjustmentIndex::ValueType; } ... llvm::GlobalVariable *var = cast(getAddrOfLLVMVariable(...)); ... llvm::Constant *addr = var; if (adjustmentIndex) { llvm::Constant *indices[] = { llvm::ConstantInt::get(Int32Ty, 0), llvm::ConstantInt::get(Int32Ty, adjustmentIndex) }; addr = llvm::ConstantExpr::getInBoundsGetElementPtr(/*Ty=*/nullptr, addr, indices); } addr = llvm::ConstantExpr::getBitCast(addr, TypeMetadataPtrTy); ... auto *alias = llvm::GlobalAlias::create(..., addr, ...); ... return alias; } 20

Slide 21

Slide 21 text

·ͱΊ • struct↓ Full Type Metadata [ Value Witness Table, Type Metadata -> Kind, Nominal Type Descriptor, ... ] • LLVM-IRΛಡΉͱྑ͍ • IRGenΛಡΉͱྑ͍ 21

Slide 22

Slide 22 text

એ఻ iOSDCʹCfPΛग़͠·ͨ͠ SwiftͷδΣωϦΫε͸Ͳ͏΍ͬͯಈ͍͍ͯΔͷ͔ίϯύΠϥͷ ιʔε͔Β୳Δ https://fortee.jp/iosdc-japan-2018/api/proposal/ 3d60b2ae-5841-4f60-8dd7-830377dc110e 22

Slide 23

Slide 23 text

͓ΘΓ 23