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

IRGenから見たType Metadata

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

IRGenから見たType Metadata

Avatar for omochimetaru

omochimetaru

June 22, 2018
Tweet

More Decks by omochimetaru

Other Decks in Programming

Transcript

  1. Metatype Swiftݴޠʹ͓͚ΔܕΛද͢ΦϒδΣΫτɻ // ܕͷܕͷม਺ʹܕͷΦϒδΣΫτΛ୅ೖ let stoneType: Stone.Type = Stone.self //

    ܕͷܕͷαϒλΠϐϯά let anyType: Any.Type = stoneType // ಈతʹܕͷΦϒδΣΫτΛऔಘ let dynamicType = type(of: Stone()) 3
  2. Metatype -> Type Metadata Any.Type͸Type Metadata΁ͷϙΠϯλɻ struct Stone {} var

    type: Any.Type = Stone.self var typePtr: UnsafePointer<Int> = unsafeBitCast(type, to: UnsafePointer<Int>.self) var kind: Int = typePtr.pointee print(kind) // 1 structͷ৔߹͸ઌ಄ʹkind=1͕ೖͬͯΔɻ 4
  3. structͷType Metadata [-1]: Value Witness Table [ 0]: Kind =

    1 [ 1]: Nominal Type Descriptor [..]: (Generic Argument Vector)* [..]: (Field Offset)* 6
  4. offset=0ʹkind͕͋Δཧ༝ ObjectiveCͰ͸ܕ΋ΦϒδΣΫτɻ struct objc_class { struct objc_class *isa; struct objc_class

    *super_class; const char *name; ... }; ϙΠϯλ͸੔਺ͰݟΔͱ>=2048ɻ kind>=2048͸ObjCΫϥεɻ 8
  5. LLVM-IR struct Stone { var weight: Int = 3 var

    size: Int = 4 } $ swiftc -emit-ir b.swift 9
  6. LLVM-IR %T1b5StoneV = type <{ %TSi, %TSi }> %TSi =

    type <{ i64 }> @"$S1b5StoneVWV" = ... @"$S1b5StoneVMn" = ... @"$S1b5StoneVMf" = ... @"$S1b5StoneVMF" = ... @"$S1b5StoneVN" = ... 10
  7. 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
  8. LLVM-IR demangle $S1b5StoneVWV: value witness table $S1b5StoneVMn: nominal type descriptor

    $S1b5StoneVMf: full type metadata $S1b5StoneVMF: reflection metadata field descriptor $S1b5StoneVN : type metadata 13
  9. Full Type Metadata ͱ Type Matadata Type MetadataͷΦϑηοτ͢Δલͷߏ଄ମɻ Αͬͯ [0]

    ʹ Value Witness Table ͕ೖ͍ͬͯΔɻ Type Metadata͸͜ΕΛKind·ͰΦϑηοτͨ͠ϙΠϯλɻ 14
  10. 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
  11. Type Metadata ΛಡΉ @"$S1b5StoneVN" = hidden alias %swift.type, bitcast (

    i64* getelementptr inbounds ( <{ i8**, i64, <{ ... }>*, i32, i32 }>, <{ ... }>* @"$S1b5StoneVMf", i32 0, i32 1) to %swift.type*) 16
  12. 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
  13. 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
  14. template <class Impl> class NominalMetadataVisitor { ... public: void layout()

    { asImpl().addValueWitnessTable(); ... asImpl().addMetadataFlags(); } }; template <class Impl> class StructMetadataVisitor : public NominalMetadataVisitor<Impl> { ... public: void layout() { super::layout(); asImpl().addNominalTypeDescriptor(); ... asImpl().addGenericFields(Target, Target->getDeclaredTypeInContext()); for (VarDecl *prop : Target->getStoredProperties()) asImpl().addFieldOffset(prop); ... } }; 19
  15. 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<llvm::GlobalVariable>(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
  16. ·ͱΊ • struct↓ Full Type Metadata [ Value Witness Table,

    Type Metadata -> Kind, Nominal Type Descriptor, ... ] • LLVM-IRΛಡΉͱྑ͍ • IRGenΛಡΉͱྑ͍ 21