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. IRGen͔Βݟͨ
    Type Metadata
    Θ͍Θ͍swiftc #3, 2018/06/22
    omochimetaru @
    1

    View Slide

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

    View Slide

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

    View Slide

  4. 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

    View Slide

  5. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  10. LLVM-IR
    %T1b5StoneV = type
    %TSi = type
    @"$S1b5StoneVWV" = ...
    @"$S1b5StoneVMn" = ...
    @"$S1b5StoneVMf" = ...
    @"$S1b5StoneVMF" = ...
    @"$S1b5StoneVN" = ...
    10

    View Slide

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

    View Slide

  12. 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

    View Slide

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

    View Slide

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

    View Slide

  15. 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

    View Slide

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

    View Slide

  17. 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

    View Slide

  18. 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

    View Slide

  19. 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

    View Slide

  20. 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

    View Slide

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

    View Slide

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

    View Slide

  23. ͓ΘΓ
    23

    View Slide