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

IRGenから見たType Metadata

IRGenから見たType Metadata

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