如何创建SIL项目

声明:

(一)⚠️⚠️⚠️目前的举例都是在Github里面可以下载的,链接放在了项目地址(全文搜一下就知道了),大家到时候自己去看呀~

(二)⚠️⚠️⚠️创建常规项目也是没有问题的。你可以直接在你的项目文件目录下创建运行命令

例如:你的项目目录可能是这样创建的

Swift-SIL生成(包教但不保证会系列-updating...)
Swift-SIL生成(包教但不保证会系列-updating...)

命令行

步骤一:

cd /Users/chill/Desktop/Github/SourceCodeAnalyse/Test-Swift-FuncDispatch/Test-Swift-FuncDispatch

步骤二:

swiftc -emit-silgen -O AClass.swift

既然我单独创建正常的项目没有问题,那我为什么还要创建一个单独的SIL项目。先解释一下为什么要单独要创建一个SIL的项目,因为我们就是怕其他的项目文件问题会对我当前的文件AClass.swift有影响(小心谨慎的❤️❤️❤️心态),那就我们按照我下面说的新建的步骤实现试一下,你可能心里更舒服。但是如果你觉得无所谓,我都会,那就可以退出了,已经没有什么值得看的了,哈哈哈。

开整!

1. 新建工程-步骤一

Swift-SIL生成(包教但不保证会系列-updating...)

2. 新建工程-步骤二

Swift-SIL生成(包教但不保证会系列-updating...)

2.1 main.swift详细的代码
class AClass {
    func test1() {
    }
    func test2() {
    }
}
extension AClass {
    func test3() {
    }
}
2.2 转换后的代码
chill@Chills-MacBook-Pro Test-CommonLineTool-Dispatch % swiftc main.swift
chill@Chills-MacBook-Pro Test-CommonLineTool-Dispatch % swiftc -emit-sil main.swift 
sil_stage canonical
import Builtin
import Swift
import SwiftShims
import Foundation
class AClass {
  func test1()
  func test2()
  @objc deinit
  init()
}
extension AClass {
  func test3()
}
// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
  %2 = integer_literal $Builtin.Int32, 0          // user: %3
  %3 = struct $Int32 (%2 : $Builtin.Int32)        // user: %4
  return %3 : $Int32                              // id: %4
} // end sil function 'main'
// AClass.test1()
sil hidden @$s4main6AClassC5test1yyF : $@convention(method) (@guaranteed AClass) -> () {
// %0 "self"                                      // user: %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  %2 = tuple ()                                   // user: %3
  return %2 : $()                                 // id: %3
} // end sil function '$s4main6AClassC5test1yyF'
// AClass.test2()
sil hidden @$s4main6AClassC5test2yyF : $@convention(method) (@guaranteed AClass) -> () {
// %0 "self"                                      // user: %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  %2 = tuple ()                                   // user: %3
  return %2 : $()                                 // id: %3
} // end sil function '$s4main6AClassC5test2yyF'
// AClass.deinit
sil hidden @$s4main6AClassCfd : $@convention(method) (@guaranteed AClass) -> @owned Builtin.NativeObject {
// %0 "self"                                      // users: %2, %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  %2 = unchecked_ref_cast %0 : $AClass to $Builtin.NativeObject // user: %3
  return %2 : $Builtin.NativeObject               // id: %3
} // end sil function '$s4main6AClassCfd'
// AClass.__deallocating_deinit
sil hidden @$s4main6AClassCfD : $@convention(method) (@owned AClass) -> () {
// %0 "self"                                      // users: %3, %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  // function_ref AClass.deinit
  %2 = function_ref @$s4main6AClassCfd : $@convention(method) (@guaranteed AClass) -> @owned Builtin.NativeObject // user: %3
  %3 = apply %2(%0) : $@convention(method) (@guaranteed AClass) -> @owned Builtin.NativeObject // user: %4
  %4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $AClass // user: %5
  dealloc_ref %4 : $AClass                        // id: %5
  %6 = tuple ()                                   // user: %7
  return %6 : $()                                 // id: %7
} // end sil function '$s4main6AClassCfD'
// AClass.__allocating_init()
sil hidden [exact_self_class] @$s4main6AClassCACycfC : $@convention(method) (@thick AClass.Type) -> @owned AClass {
// %0 "$metatype"
bb0(%0 : $@thick AClass.Type):
  %1 = alloc_ref $AClass                          // user: %3
  // function_ref AClass.init()
  %2 = function_ref @$s4main6AClassCACycfc : $@convention(method) (@owned AClass) -> @owned AClass // user: %3
  %3 = apply %2(%1) : $@convention(method) (@owned AClass) -> @owned AClass // user: %4
  return %3 : $AClass                             // id: %4
} // end sil function '$s4main6AClassCACycfC'
// AClass.init()
sil hidden @$s4main6AClassCACycfc : $@convention(method) (@owned AClass) -> @owned AClass {
// %0 "self"                                      // users: %2, %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  return %0 : $AClass                             // id: %2
} // end sil function '$s4main6AClassCACycfc'
// AClass.test3()
sil hidden @$s4main6AClassC5test3yyF : $@convention(method) (@guaranteed AClass) -> () {
// %0 "self"                                      // user: %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  %2 = tuple ()                                   // user: %3
  return %2 : $()                                 // id: %3
} // end sil function '$s4main6AClassC5test3yyF'
sil_vtable AClass {
  #AClass.test1: (AClass) -> () -> () : @$s4main6AClassC5test1yyF	// AClass.test1()
  #AClass.test2: (AClass) -> () -> () : @$s4main6AClassC5test2yyF	// AClass.test2()
  #AClass.init!allocator: (AClass.Type) -> () -> AClass : @$s4main6AClassCACycfC	// AClass.__allocating_init()
  #AClass.deinit!deallocator: @$s4main6AClassCfD	// AClass.__deallocating_deinit
}
// Mappings from '#fileID' to '#filePath':
//   'main/main.swift' => 'main.swift'

看到上面生成的东西,我们可能会很费解s4main6AClassC5test1yyF是什么东西,细心的同学就会发现上面注释了AClass.test1(),但是我们可能还会有问题,这东西到底长啥样。那我们就来-名称重整。

3. 解决文件中的名称(名称重整)
命令行
xcrun swift-demangle
chill@Chills-MacBook-Pro Test-CommonLineTool-Dispatch % xcrun swift-demangle s4main6AClassC5test1yyF
$s4main6AClassC5test1yyF ---> main.AClass.test1() -> ()

这个时候你就会说:那我也不能一个方法名一个方法名转换呀,我想要的是整体替换呀

3.1 名称重整后的代码
命令行
swiftc -emit-sil main.swift | xcrun swift-demangle
chill@Chills-MacBook-Pro Test-CommonLineTool-Dispatch % swiftc -emit-sil main.swift | xcrun swift-demangle
sil_stage canonical
import Builtin
import Swift
import SwiftShims
import Foundation
class AClass {
  func test1()
  func test2()
  @objc deinit
  init()
}
extension AClass {
  func test3()
}
// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
  %2 = integer_literal $Builtin.Int32, 0          // user: %3
  %3 = struct $Int32 (%2 : $Builtin.Int32)        // user: %4
  return %3 : $Int32                              // id: %4
} // end sil function 'main'
// AClass.test1()
sil hidden @main.AClass.test1() -> () : $@convention(method) (@guaranteed AClass) -> () {
// %0 "self"                                      // user: %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  %2 = tuple ()                                   // user: %3
  return %2 : $()                                 // id: %3
} // end sil function 'main.AClass.test1() -> ()'
// AClass.test2()
sil hidden @main.AClass.test2() -> () : $@convention(method) (@guaranteed AClass) -> () {
// %0 "self"                                      // user: %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  %2 = tuple ()                                   // user: %3
  return %2 : $()                                 // id: %3
} // end sil function 'main.AClass.test2() -> ()'
// AClass.deinit
sil hidden @main.AClass.deinit : $@convention(method) (@guaranteed AClass) -> @owned Builtin.NativeObject {
// %0 "self"                                      // users: %2, %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  %2 = unchecked_ref_cast %0 : $AClass to $Builtin.NativeObject // user: %3
  return %2 : $Builtin.NativeObject               // id: %3
} // end sil function 'main.AClass.deinit'
// AClass.__deallocating_deinit
sil hidden @main.AClass.__deallocating_deinit : $@convention(method) (@owned AClass) -> () {
// %0 "self"                                      // users: %3, %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  // function_ref AClass.deinit
  %2 = function_ref @main.AClass.deinit : $@convention(method) (@guaranteed AClass) -> @owned Builtin.NativeObject // user: %3
  %3 = apply %2(%0) : $@convention(method) (@guaranteed AClass) -> @owned Builtin.NativeObject // user: %4
  %4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $AClass // user: %5
  dealloc_ref %4 : $AClass                        // id: %5
  %6 = tuple ()                                   // user: %7
  return %6 : $()                                 // id: %7
} // end sil function 'main.AClass.__deallocating_deinit'
// AClass.__allocating_init()
sil hidden [exact_self_class] @main.AClass.__allocating_init() -> main.AClass : $@convention(method) (@thick AClass.Type) -> @owned AClass {
// %0 "$metatype"
bb0(%0 : $@thick AClass.Type):
  %1 = alloc_ref $AClass                          // user: %3
  // function_ref AClass.init()
  %2 = function_ref @main.AClass.init() -> main.AClass : $@convention(method) (@owned AClass) -> @owned AClass // user: %3
  %3 = apply %2(%1) : $@convention(method) (@owned AClass) -> @owned AClass // user: %4
  return %3 : $AClass                             // id: %4
} // end sil function 'main.AClass.__allocating_init() -> main.AClass'
// AClass.init()
sil hidden @main.AClass.init() -> main.AClass : $@convention(method) (@owned AClass) -> @owned AClass {
// %0 "self"                                      // users: %2, %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  return %0 : $AClass                             // id: %2
} // end sil function 'main.AClass.init() -> main.AClass'
// AClass.test3()
sil hidden @main.AClass.test3() -> () : $@convention(method) (@guaranteed AClass) -> () {
// %0 "self"                                      // user: %1
bb0(%0 : $AClass):
  debug_value %0 : $AClass, let, name "self", argno 1, implicit // id: %1
  %2 = tuple ()                                   // user: %3
  return %2 : $()                                 // id: %3
} // end sil function 'main.AClass.test3() -> ()'
sil_vtable AClass {
  #AClass.test1: (AClass) -> () -> () : @main.AClass.test1() -> ()	// AClass.test1()
  #AClass.test2: (AClass) -> () -> () : @main.AClass.test2() -> ()	// AClass.test2()
  #AClass.init!allocator: (AClass.Type) -> () -> AClass : @main.AClass.__allocating_init() -> main.AClass	// AClass.__allocating_init()
  #AClass.deinit!deallocator: @main.AClass.__deallocating_deinit	// AClass.__deallocating_deinit
}
// Mappings from '#fileID' to '#filePath':
//   'main/main.swift' => 'main.swift'
4. 写入文件,方便查询记录
命令行
swiftc -emit-sil main.swift | xcrun swift-demangle > ./main.sil

Swift-SIL生成(包教但不保证会系列-updating...)

5. 如果你出现了UIKit的相关问题

例如我:

chill@Chills-MacBook-Pro Test-Swift-FuncDispatch % swiftc -emit-silgen -O ViewController.swift
ViewController.swift:8:8: error: no such module 'UIKit'

参考资料里面写的是

swiftc -emit-sil -target x86_64-apple-ios15.3-simulator -sdk $(xcrun --show-sdk-path --sdk iphonesimulator) ViewController.swift > ViewController.sil

但是我实验过了,不起作用,还是会报错,等我研究下哈

xcrun: error: SDK "iphonesimulator" cannot be located
xcrun: error: SDK "iphonesimulator" cannot be located
xcrun: error: unable to lookup item 'Path' in SDK 'iphonesimulator'
<unknown>:0: error: no input files

还有一点是参考材料上说生成脚本,但我的报错了就没有跟下去。上面的问题不影响进度,我们继续,等回来的时候处理。

还有就是show me code,下面的项目名称和图上面的截屏是对的上的,您就学吧 项目地址:

参考资料:

上面的都学费了了吗?我们接下来准备干什么,我还是准备分析一下消息派发的机制能不能从SIL中看出来,但是可能还需要研究下… 如果感兴趣,不妨点个赞!收藏下! 我们改天继续…