2019-07-11-tanabe
@escaping属性を付けた引数のクロージャが非同期に実行される仕組みをSILを読みながら調べる
SwiftはSIL -> LLVM IR -> 機械語の順に生成される
順番に読んでいくとpartial_applyという命令が鍵になっているみたい
この後のfunction_ref 命令とapply命令の繰り返しで何をしているのかとexisitential containerについてわかればきちんと仕組みが把握できそう
raw SILを生成して読んでる
これがraw SIL
code:sh
sil_stage canonical
import Builtin
import Swift
import SwiftShims
func hoge(closure: @escaping (String) -> ())
// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
// function_ref closure #1 in %2 = function_ref @$s7closureySScfU_ : $@convention(thin) (@guaranteed String) -> () // user: %3
%3 = thin_to_thick_function %2 : $@convention(thin) (@guaranteed String) -> () to $@callee_guaranteed (@guaranteed String) -> () // users: %6, %5
// function_ref hoge(closure:)
%4 = function_ref @$s7closure4hogeAAyySSc_tF : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> () // user: %5
%5 = apply %4(%3) : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> ()
strong_release %3 : $@callee_guaranteed (@guaranteed String) -> () // id: %6
%7 = integer_literal $Builtin.Int32, 0 // user: %8
%8 = struct $Int32 (%7 : $Builtin.Int32) // user: %9
return %8 : $Int32 // id: %9
} // end sil function 'main'
// hoge(closure:)
sil hidden @$s7closure4hogeAAyySSc_tF : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> () {
// %0 // users: %11, %9, %2, %1
bb0(%0 : $@callee_guaranteed (@guaranteed String) -> ()):
debug_value %0 : $@callee_guaranteed (@guaranteed String) -> (), let, name "closure", argno 1 // id: %1
strong_retain %0 : $@callee_guaranteed (@guaranteed String) -> () // id: %2
%3 = string_literal utf8 "hoge" // user: %8
%4 = integer_literal $Builtin.Word, 4 // user: %8
%5 = integer_literal $Builtin.Int1, -1 // user: %8
%6 = metatype $@thin String.Type // user: %8
// function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
%7 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %8
%8 = apply %7(%3, %4, %5, %6) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // users: %10, %9
%9 = apply %0(%8) : $@callee_guaranteed (@guaranteed String) -> ()
release_value %8 : $String // id: %10
strong_release %0 : $@callee_guaranteed (@guaranteed String) -> () // id: %11
%12 = tuple () // user: %13
return %12 : $() // id: %13
} // end sil function '$s7closure4hogeAAyySSc_tF'
// String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
sil private @$s7closureySScfU_ : $@convention(thin) (@guaranteed String) -> () {
// %0 // user: %1
bb0(%0 : $String):
debug_value %0 : $String, let, name "string", argno 1 // id: %1
%2 = integer_literal $Builtin.Word, 1 // user: %4
// function_ref specialized _allocateUninitializedArray<A>(_:)
%3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlFyp_Tg5 : $@convention(thin) (Builtin.Word) -> (@owned Array<Any>, Builtin.RawPointer) // user: %4
%4 = apply %3(%2) : $@convention(thin) (Builtin.Word) -> (@owned Array<Any>, Builtin.RawPointer) // users: %5, %6
%5 = tuple_extract %4 : $(Array<Any>, Builtin.RawPointer), 0 // users: %22, %19
%6 = tuple_extract %4 : $(Array<Any>, Builtin.RawPointer), 1 // user: %7
%7 = pointer_to_address %6 : $Builtin.RawPointer to strict $*Any // user: %12 // function_ref hoge(closure:)
%8 = function_ref @$s7closure4hogeAAyySSc_tF : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> () // user: %9
%9 = thin_to_thick_function %8 : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> () to $@callee_guaranteed (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> () // user: %11
// function_ref thunk for @escaping @callee_guaranteed (@guaranteed @escaping @callee_guaranteed (@guaranteed String) -> ()) -> ()
%10 = function_ref @$sSSIegg_Iegg_SSytIegnr_ytIegnr_TR : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed String) -> @out (), @guaranteed @callee_guaranteed (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> ()) -> @out () // user: %11
%11 = partial_apply callee_guaranteed %10(%9) : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed String) -> @out (), @guaranteed @callee_guaranteed (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> ()) -> @out () // user: %13 %12 = init_existential_addr %7 : $*Any, $(@escaping (String) -> ()) -> () // user: %13
store %11 to %12 : $*@callee_guaranteed (@in_guaranteed @callee_guaranteed (@in_guaranteed String) -> @out ()) -> @out () // id: %13
// function_ref default argument 1 of print(_:separator:terminator:)
%14 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %15
%15 = apply %14() : $@convention(thin) () -> @owned String // users: %21, %19
// function_ref default argument 2 of print(_:separator:terminator:)
%16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %17
%17 = apply %16() : $@convention(thin) () -> @owned String // users: %20, %19
// function_ref print(_:separator:terminator:)
%18 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %19
%19 = apply %18(%5, %15, %17) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()
release_value %17 : $String // id: %20
release_value %15 : $String // id: %21
release_value %5 : $Array<Any> // id: %22
%23 = tuple () // user: %24
return %23 : $() // id: %24
} // end sil function '$s7closureySScfU_'
// _allocateUninitializedArray<A>(_:)
sil serialized always_inline @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // thunk for @escaping @callee_guaranteed (@guaranteed @escaping @callee_guaranteed (@guaranteed String) -> ()) -> ()
sil shared transparent serializable reabstraction_thunk @$sSSIegg_Iegg_SSytIegnr_ytIegnr_TR : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed String) -> @out (), @guaranteed @callee_guaranteed (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> ()) -> @out () { // %1 // user: %3
// %2 // user: %7
bb0(%0 : $*(), %1 : $*@callee_guaranteed (@in_guaranteed String) -> @out (), %2 : $@callee_guaranteed (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> ()):
%3 = load %1 : $*@callee_guaranteed (@in_guaranteed String) -> @out () // users: %6, %5
// function_ref thunk for @escaping @callee_guaranteed (@in_guaranteed String) -> (@out ())
%4 = function_ref @$sSSytIegnr_SSIegg_TR : $@convention(thin) (@guaranteed String, @guaranteed @callee_guaranteed (@in_guaranteed String) -> @out ()) -> () // user: %6
strong_retain %3 : $@callee_guaranteed (@in_guaranteed String) -> @out () // id: %5
%6 = partial_apply callee_guaranteed %4(%3) : $@convention(thin) (@guaranteed String, @guaranteed @callee_guaranteed (@in_guaranteed String) -> @out ()) -> () // users: %9, %7 %7 = apply %2(%6) : $@callee_guaranteed (@guaranteed @callee_guaranteed (@guaranteed String) -> ()) -> ()
%8 = tuple () // user: %10
strong_release %6 : $@callee_guaranteed (@guaranteed String) -> () // id: %9
return %8 : $() // id: %10
} // end sil function '$sSSIegg_Iegg_SSytIegnr_ytIegnr_TR'
// thunk for @escaping @callee_guaranteed (@in_guaranteed String) -> (@out ())
// %0 // users: %4, %3
// %1 // user: %6
bb0(%0 : $String, %1 : $@callee_guaranteed (@in_guaranteed String) -> @out ()):
%2 = alloc_stack $String // users: %4, %10, %9, %6
retain_value %0 : $String // id: %3
store %0 to %2 : $*String // id: %4
%5 = alloc_stack $() // users: %8, %6
%6 = apply %1(%5, %2) : $@callee_guaranteed (@in_guaranteed String) -> @out ()
%7 = tuple () // user: %11
dealloc_stack %5 : $*() // id: %8
destroy_addr %2 : $*String // id: %9
dealloc_stack %2 : $*String // id: %10
return %7 : $() // id: %11
} // end sil function '$sSSytIegnr_SSIegg_TR'
// default argument 1 of print(_:separator:terminator:)
sil shared_external serialized @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String { bb0:
%0 = string_literal utf8 " " // user: %5
%1 = integer_literal $Builtin.Word, 1 // user: %5
%2 = integer_literal $Builtin.Int1, -1 // user: %5
%3 = metatype $@thin String.Type // user: %5
// function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
%4 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %5
%5 = apply %4(%0, %1, %2, %3) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %6
return %5 : $String // id: %6
} // end sil function '$ss5print_9separator10terminatoryypd_S2StFfA0_'
// default argument 2 of print(_:separator:terminator:)
sil shared_external serialized @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String { bb0:
%0 = string_literal utf8 "\n" // user: %5
%1 = integer_literal $Builtin.Word, 1 // user: %5
%2 = integer_literal $Builtin.Int1, -1 // user: %5
%3 = metatype $@thin String.Type // user: %5
// function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
%4 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %5
%5 = apply %4(%0, %1, %2, %3) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %6
return %5 : $String // id: %6
} // end sil function '$ss5print_9separator10terminatoryypd_S2StFfA1_'
// print(_:separator:terminator:)
sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()
// specialized _allocateUninitializedArray<A>(_:)
sil always_inline @$ss27_allocateUninitializedArrayySayxG_BptBwlFyp_Tg5 : $@convention(thin) (Builtin.Word) -> (@owned Array<Any>, Builtin.RawPointer)