如何创建SIL项目
声明:
(一)⚠️⚠️⚠️目前的举例都是在Github里面可以下载的,链接放在了项目地址
(全文搜一下就知道了),大家到时候自己去看呀~
(二)⚠️⚠️⚠️创建常规项目也是没有问题的。你可以直接在你的项目文件目录下创建运行命令行
例如:你的项目目录可能是这样创建的
命令行
步骤一:
cd /Users/chill/Desktop/Github/SourceCodeAnalyse/Test-Swift-FuncDispatch/Test-Swift-FuncDispatch
步骤二:
swiftc -emit-silgen -O AClass.swift
既然我单独创建正常的项目没有问题,那我为什么还要创建一个单独的SIL项目。先解释一下为什么要单独要创建一个SIL的项目,因为我们就是怕其他的项目文件问题会对我当前的文件AClass.swift
有影响(小心谨慎的❤️❤️❤️心态),那就我们按照我下面说的新建的步骤实现试一下,你可能心里更舒服。但是如果你觉得无所谓,我都会,那就可以退出了,已经没有什么值得看的了,哈哈哈。
开整!
1. 新建工程-步骤一
2. 新建工程-步骤二
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
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中看出来,但是可能还需要研究下… 如果感兴趣,不妨点个赞!收藏下! 我们改天继续…