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

一、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;  // ... 
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容