美文网首页
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