美文网首页
002-Swift进阶-编译简介、sil文件的分析

002-Swift进阶-编译简介、sil文件的分析

作者: Stronger_J | 来源:发表于2020-12-15 18:08 被阅读0次

    一、swift编译简介

    IOS开发的语言不管是OC还是swift,后端都是通过LLVM进行编译的,如下:


    image.png

    可以看到OC是clang编译器,编译IR,然后在生成可执行文件.0(机器码),Swift是通过swift编译器,编译成IR,然后生成可执行文件。


    image.png

    二、SIL

    swift使用的编译器为swiftc,OC使用的为Clang。
    swiftc命令查询:swiftc -h
    参考视频:链接
    参考文档:SIL参考文档

    编译成SIL文件:

    swiftc -emit-sil main.swift >> main.sil && open main.sil 
    //带转译
    swiftc -emit-sil main.swift | xcrun swift-demangle >> main.sil && open main.sil 
    
    //IR
    swiftc -emit-ir main.swift | xcrun swift-demangle >> main.ll && open main.ll
    
    //UIKit
     swiftc -emit-sil -target x86_64-apple-ios13.5-simulator -sdk $(xcrun --show-sdk-path --sdk iphonesimulator) ViewController.swift > ViewController.sil
    

    swift文件的入口函数


    image.png
    • @main 是main.swift的入口函数,SIL中标识符名称以@作为前缀,入口函数有两个参数,一个32位Int,一个指针,一个返回值。
    • %0、%1......在SIL中叫做寄存器,可以视为长量,赋值后不可更改,在SIL中以累加数字的模式继续使用。这里所说的寄存器是虚拟的,最终运行到我们的机器上会使用真的寄存器。
    • alloc_global 创建一个全局变量
    • global_addr 拿到全局变量的地址,赋值给%3
    • metatype 拿到LJTest的Metadata赋值给%4
    • 将__allocating_init 的函数地址赋值给%5
    • apply 调用 __allocating_init,并赋值给%6
    • 将%6的值存储到%3
    • 构建Int, 并return返回
    • Buildin LLVM指令格式

    转译命令xcrun swift-demangle s4main2t1AA6LJTestCvp
    寄存器读取:register read register read x8

    xcode添加符号断点


    image.png

    三、HeapObject.cpp中alloc_Object方法

    image.png

    1、初始化调度

    • 一个swift对象的内存结构HeapObject,默认占用16字节大小,metadata,refCount
    • swift内存分配过程调用顺序:__allocating_init ---> swift_allocObject ---> swift_allocObject ---> swift_slowAlloc ---> Malloc

    2、打印占用空间大小

    import Foundation
    class LJTest{
        var age = 18
        var name: String = "swift"
    }
    var t1 = LJTest()
    print(MemoryLayout<String>.stride)          //步长
    print(MemoryLayout<String>.size)            //大小
    print(class_getInstanceSize(LJTest.self))   //大小
    

    3、类结构探索

    • swift初始化函数swift_allocObject
      函数3个参数:
      HeapMetadata const *metadata :元数据
      size_t requiredSize :大小
      size_t requiredAlignmentMask :对齐格式,
    static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
                                           size_t requiredSize,
                                           size_t requiredAlignmentMask) {
      assert(isAlignmentMask(requiredAlignmentMask));
      auto object = reinterpret_cast<HeapObject *>(
          swift_slowAlloc(requiredSize, requiredAlignmentMask));
    
      // NOTE: this relies on the C++17 guaranteed semantics of no null-pointer
      // check on the placement new allocator which we have observed on Windows,
      // Linux, and macOS.
      new (object) HeapObject(metadata);
    
      // If leak tracking is enabled, start tracking this object.
      SWIFT_LEAKS_START_TRACKING_OBJECT(object);
    
      SWIFT_RT_TRACK_INVOCATION(object, swift_allocObject);
    
      return object;
    }
    
    • Matedata
      TargetMetadata结构体重包含一个属性kind,是一个存储指针(isa),是用来区分哪种类型的元数据,在#include "MetadataKind.def"文件中存储了所有的元数据类型。
      image.png

    获取当前kind

    /// Get the metadata kind.
      MetadataKind getKind() const {
        return getEnumeratedMetadataKind(Kind);
      }
    

    获取类对象
    const TargetClassMetadata<Runtime> *getClassObject() const;
    getClassObject()方法获取的就是kind类型,通过getKind()方法获取类型(MetadataKind::Class),

    template<> inline const ClassMetadata *
      Metadata::getClassObject() const {
        switch (getKind()) {
        case MetadataKind::Class: {
          // Native Swift class metadata is also the class object.
          return static_cast<const ClassMetadata *>(this);
        }
        case MetadataKind::ObjCClassWrapper: {
          // Objective-C class objects are referenced by their Swift metadata wrapper.
          auto wrapper = static_cast<const ObjCClassWrapperMetadata *>(this);
          return wrapper->Class;
        }
        // Other kinds of types don't have class objects.
        default:
          return nullptr;
        }
      }
    
    • Matedata::Class
      TargetClassMetadata(ClassMetadata一样,所有的属性) --> TargetAnyClassMetadata(kind, superclass, cacheData) --> TargetHeapMetadata(HeapMetadata) --> TargetMetadata(kind)

    Metadata结构体:

     struct swift_class_t: NSObject{
        void *kind; //isa, kind(unsigned long) 
        void *superClass;
        void *cacheData 
        void *data 
        uint32_t flags; //4 
        uint32_t instanceAddressOffset; //4 
        uint32_t instanceSize;//4 
        uint16_t instanceAlignMask; //2 
        uint16_t reserved; //2 
        uint32_t classSize; //4  
        uint32_t classAddressOffset; //4 
        void *description;  // ... 
    };
    

    相关文章

      网友评论

          本文标题:002-Swift进阶-编译简介、sil文件的分析

          本文链接:https://www.haomeiwen.com/subject/iwaigktx.html