Swiftコード
func foo(g: @escaping () -> Void) {}
@_optimize(none)
func sink<X>(_ x: X) {}
func main(a: Int) {
foo { [a] () in
sink(a)
}
}これをコンパイル
swift -emit-ir a.swiftLLVM-IRが得られる
; ModuleID = '<swift-imported-modules>'
source_filename = "<swift-imported-modules>"
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "arm64-apple-macosx15.0.0"
%swift.full_boxmetadata = type { ptr, ptr, %swift.type, i32, ptr }
%swift.type = type { i64 }
%swift.function = type { ptr, ptr }
%swift.refcounted = type { ptr, i64 }
%TSi = type <{ i64 }>
@"symbolic Si" = linkonce_odr hidden constant <{ [2 x i8], i8 }> <{ [2 x i8] c"Si", i8 0 }>, section "__TEXT,__swift5_typeref, regular", no_sanitize_address, align 2
@"\01l__swift5_reflection_descriptor" = private constant { i32, i32, i32, i32 } { i32 1, i32 0, i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @"symbolic Si" to i64), i64 ptrtoint (ptr getelementptr inbounds ({ i32, i32, i32, i32 }, ptr @"\01l__swift5_reflection_descriptor", i32 0, i32 3) to i64)) to i32) }, section "__TEXT,__swift5_capture, regular", no_sanitize_address, align 4
@metadata = private constant %swift.full_boxmetadata { ptr @objectdestroy, ptr null, %swift.type { i64 1024 }, i32 16, ptr @"\01l__swift5_reflection_descriptor" }, align 8
@"\01l_entry_point" = private constant { i32, i32 } { i32 trunc (i64 sub (i64 ptrtoint (ptr @main to i64), i64 ptrtoint (ptr @"\01l_entry_point" to i64)) to i32), i32 0 }, section "__TEXT, __swift5_entry, regular, no_dead_strip", align 4
@"$sSiN" = external global %swift.type, align 8
@__swift_reflection_version = linkonce_odr hidden constant i16 3
@llvm.used = appending global [7 x ptr] [ptr @main, ptr @"$s1a3foo1gyyyc_tF", ptr @"$s1a4sinkyyxlF", ptr @"$s1a4mainAAySi_tF", ptr @"\01l__swift5_reflection_descriptor", ptr @"\01l_entry_point", ptr @__swift_reflection_version], section "llvm.metadata"
define i32 @main(i32 %0, ptr %1) #0 {
entry:
ret i32 0
}
define hidden swiftcc void @"$s1a3foo1gyyyc_tF"(ptr %0, ptr %1) #0 {
entry:
%g.debug = alloca %swift.function, align 8
call void @llvm.memset.p0.i64(ptr align 8 %g.debug, i8 0, i64 16, i1 false)
call void @llvm.lifetime.start.p0(i64 16, ptr %g.debug)
%g.debug.fn = getelementptr inbounds %swift.function, ptr %g.debug, i32 0, i32 0
store ptr %0, ptr %g.debug.fn, align 8
%g.debug.data = getelementptr inbounds %swift.function, ptr %g.debug, i32 0, i32 1
store ptr %1, ptr %g.debug.data, align 8
ret void
}
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #2
define hidden swiftcc void @"$s1a4sinkyyxlF"(ptr noalias %0, ptr %X) #0 {
entry:
%X1 = alloca ptr, align 8
%x.debug = alloca ptr, align 8
call void @llvm.memset.p0.i64(ptr align 8 %x.debug, i8 0, i64 8, i1 false)
store ptr %X, ptr %X1, align 8
store ptr %0, ptr %x.debug, align 8
ret void
}
define hidden swiftcc void @"$s1a4mainAAySi_tF"(i64 %0) #0 {
entry:
%a.debug = alloca i64, align 8
call void @llvm.memset.p0.i64(ptr align 8 %a.debug, i8 0, i64 8, i1 false)
store i64 %0, ptr %a.debug, align 8
%1 = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata, i32 0, i32 2), i64 24, i64 7) #3
%2 = getelementptr inbounds <{ %swift.refcounted, %TSi }>, ptr %1, i32 0, i32 1
%._value = getelementptr inbounds %TSi, ptr %2, i32 0, i32 0
store i64 %0, ptr %._value, align 8
call swiftcc void @"$s1a3foo1gyyyc_tF"(ptr @"$s1a4mainAAySi_tFyycfU_TA", ptr %1)
call void @swift_release(ptr %1) #3
ret void
}
define internal swiftcc void @"$s1a4mainAAySi_tFyycfU_"(i64 %0) #0 {
entry:
%a.debug = alloca i64, align 8
call void @llvm.memset.p0.i64(ptr align 8 %a.debug, i8 0, i64 8, i1 false)
%1 = alloca %TSi, align 8
store i64 %0, ptr %a.debug, align 8
call void @llvm.lifetime.start.p0(i64 8, ptr %1)
%._value = getelementptr inbounds %TSi, ptr %1, i32 0, i32 0
store i64 %0, ptr %._value, align 8
call swiftcc void @"$s1a4sinkyyxlF"(ptr noalias %1, ptr @"$sSiN")
call void @llvm.lifetime.end.p0(i64 8, ptr %1)
ret void
}
define private swiftcc void @objectdestroy(ptr swiftself %0) #0 {
entry:
call void @swift_deallocObject(ptr %0, i64 24, i64 7) #3
ret void
}
; Function Attrs: nounwind
declare void @swift_deallocObject(ptr, i64, i64) #3
; Function Attrs: nounwind
declare ptr @swift_allocObject(ptr, i64, i64) #3
define internal swiftcc void @"$s1a4mainAAySi_tFyycfU_TA"(ptr swiftself %0) #0 {
entry:
%1 = getelementptr inbounds <{ %swift.refcounted, %TSi }>, ptr %0, i32 0, i32 1
%._value = getelementptr inbounds %TSi, ptr %1, i32 0, i32 0
%2 = load i64, ptr %._value, align 8
tail call swiftcc void @"$s1a4mainAAySi_tFyycfU_"(i64 %2)
ret void
}
; Function Attrs: nounwind
declare void @swift_release(ptr) #3
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
attributes #0 = { "frame-pointer"="non-leaf" "no-trapping-math"="true" "probe-stack"="__chkstk_darwin" "stack-protector-buffer-size"="8" "target-cpu"="apple-a12" "target-features"="+aes,+ccidx,+complxnum,+crc,+fp-armv8,+fullfp16,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+v8.1a,+v8.2a,+v8.3a,+v8a,+zcm,+zcz" }
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #3 = { nounwind }
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11}
!swift.module.flags = !{!12}
!llvm.linker.options = !{!13, !14, !15, !16, !17}
!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 15, i32 5]}
!1 = !{i32 1, !"Objective-C Version", i32 2}
!2 = !{i32 1, !"Objective-C Image Info Version", i32 0}
!3 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"}
!4 = !{i32 4, !"Objective-C Garbage Collection", i32 100730624}
!5 = !{i32 1, !"Objective-C Class Properties", i32 64}
!6 = !{i32 1, !"Objective-C Enforce ClassRO Pointer Signing", i8 0}
!7 = !{i32 1, !"wchar_size", i32 4}
!8 = !{i32 8, !"PIC Level", i32 2}
!9 = !{i32 7, !"uwtable", i32 1}
!10 = !{i32 7, !"frame-pointer", i32 1}
!11 = !{i32 1, !"Swift Version", i32 7}
!12 = !{!"standard-library", i1 false}
!13 = !{!"-lswiftSwiftOnoneSupport"}
!14 = !{!"-lswiftCore"}
!15 = !{!"-lswift_Concurrency"}
!16 = !{!"-lswift_StringProcessing"}
!17 = !{!"-lobjc"}クロージャを作るためにキャプチャオブジェクトを生成するところ
define hidden swiftcc void @"$s1a4mainAAySi_tF"(i64 %0) #0 {
...
%1 = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata, i32 0, i32 2), i64 24, i64 7) #3
...
}渡してるメタデータ
@metadata = private constant %swift.full_boxmetadata { ptr @objectdestroy, ptr null, %swift.type { i64 1024 }, i32 16, ptr @"\01l__swift5_reflection_descriptor" }, align 85番目のフィールドにリフレクションデータがある
@"\01l__swift5_reflection_descriptor" = private constant { i32, i32, i32, i32 } {
i32 1, i32 0, i32 0,
... ptr @"symbolic Si" to i64 ...,
section "__TEXT,__swift5_capture, regular", no_sanitize_address, align 4読み解くと、フィールド1個で、それが Swift.Int だと書いてある。
ChatGPT との会話 https://chatgpt.com/share/689970ce-b278-8006-a239-983a9eab341c