SlideShare a Scribd company logo
1 of 83
Download to read offline
Swiftとメソッドのアレコレ
@tarunon
1
自己紹介
@tarunon
イカガチ勢 2015-09-26現在
ランク50 ウデマエS55
守備範囲: Swift, Objective-
C, JavaScript, Java, etc…
2
Resume
3
復習Objective-C
Swiftは何故速い?
struct/enum
アクセス修飾子
Any vs Generics
Protocol Extension
optional func
Closure
復習Objective-C
復習Objective-C
Objective-Cは動的言語
objc_msgSend
ランタイムAPI
5
objc_msgSend
6
Class
IMP
void aFunction(id self, SEL _cmd) {
…
}
SEL
処理はCの関数と同等のIMPに存在
IMPへの参照とSelectorの組を持つ
objc_msgSend
7
objc_msgSend
Object
SEL
Arguments
objc_msgSendが

IMPを検索して実行する
高コスト!遅い!
objc_msgSend
8
「クリティカルな部分はCで書く」
「C++」
ランタイムAPI
9
クラスにメソッドを追加
クラスにプロパティを追加
Method Swizzling
クラスを追加
objc_msgSendの恩恵
10
クラスの継承
UIControl::addTarget:action:forControlEvents:
@optionalなメソッド(Protocol)
CoreData
モデルを定義するためにObjective-Cランタイ
ムを駆使
Swiftは何故速い?
※LLVM中間コードが大量に出現します。ご注意下さい。
Swiftは何故速い?
12
@interface A : NSObject
@property (nonatomic) NSString *str;
@property (nonatomic) NSInteger integer;
@end
@implementation A
- (void)function
{
}
@end
Swiftは何故速い?
13
clang -S -emit-llvm source.m
Swiftは何故速い?
14
@"OBJC_IVAR_$_A._str" = hidden global i64 8, section "__DATA, __objc_ivar", align 8
@"OBJC_IVAR_$_A._integer" = hidden global i64 16, section "__DATA, __objc_ivar", align 8
@_objc_empty_cache = external global %struct._objc_cache
@"OBJC_METACLASS_$_NSObject" = external global %struct._class_t
@OBJC_CLASS_NAME_ = private global [2 x i8] c"A00", section "__TEXT,__objc_classname,cstring_literals", align 1
@"01l_OBJC_METACLASS_RO_$_A" = private global %struct._class_ro_t { i32 1, i32 40, i32 40, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0),
%struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8
@"OBJC_METACLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache,
i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_METACLASS_RO_$_A" }, section "__DATA, __objc_data", align 8
@"OBJC_CLASS_$_NSObject" = external global %struct._class_t
@OBJC_METH_VAR_NAME_ = private global [9 x i8] c"function00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_ = private global [8 x i8] c"v16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_1 = private global [4 x i8] c"str00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_2 = private global [8 x i8] c"@16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_3 = private global [8 x i8] c"setStr:00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_4 = private global [11 x i8] c"v24@0:8@1600", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_5 = private global [8 x i8] c"integer00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_6 = private global [8 x i8] c"q16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_7 = private global [12 x i8] c"setInteger:00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_8 = private global [11 x i8] c"v24@0:8q1600", section "__TEXT,__objc_methtype,cstring_literals", align 1
@"01l_OBJC_$_INSTANCE_METHODS_A" = private global { i32, i32, [5 x %struct._objc_method] } { i32 24, i32 5, [5 x %struct._objc_method] [%struct._objc_method { i8* getelementptr inbounds
([9 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast (void (%0*, i8*)* @"01-[A function]" to i8*) },
%struct._objc_method { i8* getelementptr inbounds ([4 x i8]* @OBJC_METH_VAR_NAME_1, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_2, i32 0, i32 0), i8* bitcast
(%1* (%0*, i8*)* @"01-[A str]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_3, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]*
@OBJC_METH_VAR_TYPE_4, i32 0, i32 0), i8* bitcast (void (%0*, i8*, %1*)* @"01-[A setStr:]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_5,
i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_6, i32 0, i32 0), i8* bitcast (i64 (%0*, i8*)* @"01-[A integer]" to i8*) }, %struct._objc_method { i8*
getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_NAME_7, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_8, i32 0, i32 0), i8* bitcast (void (%0*, i8*, i64)*
@"01-[A setInteger:]" to i8*) }] }, section "__DATA, __objc_const", align 8
@OBJC_METH_VAR_NAME_9 = private global [5 x i8] c"_str00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_10 = private global [12 x i8] c"@22NSString2200", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_11 = private global [9 x i8] c"_integer00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_12 = private global [2 x i8] c"q00", section "__TEXT,__objc_methtype,cstring_literals", align 1
@"01l_OBJC_$_INSTANCE_VARIABLES_A" = private global { i32, i32, [2 x %struct._ivar_t] } { i32 32, i32 2, [2 x %struct._ivar_t] [%struct._ivar_t { i64* @"OBJC_IVAR_$_A._str", i8*
getelementptr inbounds ([5 x i8]* @OBJC_METH_VAR_NAME_9, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_TYPE_10, i32 0, i32 0), i32 3, i32 8 }, %struct._ivar_t
{ i64* @"OBJC_IVAR_$_A._integer", i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_11, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8]* @OBJC_METH_VAR_TYPE_12, i32 0, i32
0), i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8
@OBJC_PROP_NAME_ATTR_ = private global [4 x i8] c"str00", section "__TEXT,__cstring,cstring_literals", align 1
@OBJC_PROP_NAME_ATTR_13 = private global [21 x i8] c"T@22NSString22,N,V_str00", section "__TEXT,__cstring,cstring_literals", align 1
@OBJC_PROP_NAME_ATTR_14 = private global [8 x i8] c"integer00", section "__TEXT,__cstring,cstring_literals", align 1
@OBJC_PROP_NAME_ATTR_15 = private global [15 x i8] c"Tq,N,V_integer00", section "__TEXT,__cstring,cstring_literals", align 1
@"01l_OBJC_$_PROP_LIST_A" = private global { i32, i32, [2 x %struct._prop_t] } { i32 16, i32 2, [2 x %struct._prop_t] [%struct._prop_t { i8* getelementptr inbounds ([4 x i8]*
@OBJC_PROP_NAME_ATTR_, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8]* @OBJC_PROP_NAME_ATTR_13, i32 0, i32 0) }, %struct._prop_t { i8* getelementptr inbounds ([8 x i8]*
@OBJC_PROP_NAME_ATTR_14, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8]* @OBJC_PROP_NAME_ATTR_15, i32 0, i32 0) }] }, section "__DATA, __objc_const", align 8
@"01l_OBJC_CLASS_RO_$_A" = private global %struct._class_ro_t { i32 0, i32 8, i32 24, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0),
%struct.__method_list_t* bitcast ({ i32, i32, [5 x %struct._objc_method] }* @"01l_OBJC_$_INSTANCE_METHODS_A" to %struct.__method_list_t*), %struct._objc_protocol_list* null,
%struct._ivar_list_t* bitcast ({ i32, i32, [2 x %struct._ivar_t] }* @"01l_OBJC_$_INSTANCE_VARIABLES_A" to %struct._ivar_list_t*), i8* null, %struct._prop_list_t* bitcast ({ i32, i32, [2
x %struct._prop_t] }* @"01l_OBJC_$_PROP_LIST_A" to %struct._prop_list_t*) }, section "__DATA, __objc_const", align 8
@"OBJC_CLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_A", %struct._class_t* @"OBJC_CLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*,
i8*)** null, %struct._class_ro_t* @"01l_OBJC_CLASS_RO_$_A" }, section "__DATA, __objc_data", align 8
@"OBJC_LABEL_CLASS_$" = private global [1 x i8*] [i8* bitcast (%struct._class_t* @"OBJC_CLASS_$_A" to i8*)], section "__DATA, __objc_classlist, regular, no_dead_strip", align 8
Swiftは何故速い?
15
@"OBJC_IVAR_$_A._str" = hidden global i64 8, section "__DATA, __objc_ivar", align 8
@"OBJC_IVAR_$_A._integer" = hidden global i64 16, section "__DATA, __objc_ivar", align 8
@_objc_empty_cache = external global %struct._objc_cache
@"OBJC_METACLASS_$_NSObject" = external global %struct._class_t
@OBJC_CLASS_NAME_ = private global [2 x i8] c"A00", section "__TEXT,__objc_classname,cstring_literals", align 1
@"01l_OBJC_METACLASS_RO_$_A" = private global %struct._class_ro_t { i32 1, i32 40, i32 40, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0),
%struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8
@"OBJC_METACLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache,
i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_METACLASS_RO_$_A" }, section "__DATA, __objc_data", align 8
@"OBJC_CLASS_$_NSObject" = external global %struct._class_t
@OBJC_METH_VAR_NAME_ = private global [9 x i8] c"function00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_ = private global [8 x i8] c"v16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_1 = private global [4 x i8] c"str00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_2 = private global [8 x i8] c"@16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_3 = private global [8 x i8] c"setStr:00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_4 = private global [11 x i8] c"v24@0:8@1600", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_5 = private global [8 x i8] c"integer00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_6 = private global [8 x i8] c"q16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_7 = private global [12 x i8] c"setInteger:00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_8 = private global [11 x i8] c"v24@0:8q1600", section "__TEXT,__objc_methtype,cstring_literals", align 1
@"01l_OBJC_$_INSTANCE_METHODS_A" = private global { i32, i32, [5 x %struct._objc_method] } { i32 24, i32 5, [5 x %struct._objc_method] [%struct._objc_method { i8* getelementptr inbounds
([9 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast (void (%0*, i8*)* @"01-[A function]" to i8*) },
%struct._objc_method { i8* getelementptr inbounds ([4 x i8]* @OBJC_METH_VAR_NAME_1, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_2, i32 0, i32 0), i8* bitcast
(%1* (%0*, i8*)* @"01-[A str]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_3, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]*
@OBJC_METH_VAR_TYPE_4, i32 0, i32 0), i8* bitcast (void (%0*, i8*, %1*)* @"01-[A setStr:]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_5,
i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_6, i32 0, i32 0), i8* bitcast (i64 (%0*, i8*)* @"01-[A integer]" to i8*) }, %struct._objc_method { i8*
getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_NAME_7, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_8, i32 0, i32 0), i8* bitcast (void (%0*, i8*, i64)*
@"01-[A setInteger:]" to i8*) }] }, section "__DATA, __objc_const", align 8
@OBJC_METH_VAR_NAME_9 = private global [5 x i8] c"_str00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_10 = private global [12 x i8] c"@22NSString2200", section "__TEXT,__objc_methtype,cstring_literals", align 1
@OBJC_METH_VAR_NAME_11 = private global [9 x i8] c"_integer00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_12 = private global [2 x i8] c"q00", section "__TEXT,__objc_methtype,cstring_literals", align 1
@"01l_OBJC_$_INSTANCE_VARIABLES_A" = private global { i32, i32, [2 x %struct._ivar_t] } { i32 32, i32 2, [2 x %struct._ivar_t] [%struct._ivar_t { i64* @"OBJC_IVAR_$_A._str", i8*
getelementptr inbounds ([5 x i8]* @OBJC_METH_VAR_NAME_9, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_TYPE_10, i32 0, i32 0), i32 3, i32 8 }, %struct._ivar_t
{ i64* @"OBJC_IVAR_$_A._integer", i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_11, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8]* @OBJC_METH_VAR_TYPE_12, i32 0, i32
0), i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8
@OBJC_PROP_NAME_ATTR_ = private global [4 x i8] c"str00", section "__TEXT,__cstring,cstring_literals", align 1
@OBJC_PROP_NAME_ATTR_13 = private global [21 x i8] c"T@22NSString22,N,V_str00", section "__TEXT,__cstring,cstring_literals", align 1
@OBJC_PROP_NAME_ATTR_14 = private global [8 x i8] c"integer00", section "__TEXT,__cstring,cstring_literals", align 1
@OBJC_PROP_NAME_ATTR_15 = private global [15 x i8] c"Tq,N,V_integer00", section "__TEXT,__cstring,cstring_literals", align 1
@"01l_OBJC_$_PROP_LIST_A" = private global { i32, i32, [2 x %struct._prop_t] } { i32 16, i32 2, [2 x %struct._prop_t] [%struct._prop_t { i8* getelementptr inbounds ([4 x i8]*
@OBJC_PROP_NAME_ATTR_, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8]* @OBJC_PROP_NAME_ATTR_13, i32 0, i32 0) }, %struct._prop_t { i8* getelementptr inbounds ([8 x i8]*
@OBJC_PROP_NAME_ATTR_14, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8]* @OBJC_PROP_NAME_ATTR_15, i32 0, i32 0) }] }, section "__DATA, __objc_const", align 8
@"01l_OBJC_CLASS_RO_$_A" = private global %struct._class_ro_t { i32 0, i32 8, i32 24, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0),
%struct.__method_list_t* bitcast ({ i32, i32, [5 x %struct._objc_method] }* @"01l_OBJC_$_INSTANCE_METHODS_A" to %struct.__method_list_t*), %struct._objc_protocol_list* null,
%struct._ivar_list_t* bitcast ({ i32, i32, [2 x %struct._ivar_t] }* @"01l_OBJC_$_INSTANCE_VARIABLES_A" to %struct._ivar_list_t*), i8* null, %struct._prop_list_t* bitcast ({ i32, i32, [2
x %struct._prop_t] }* @"01l_OBJC_$_PROP_LIST_A" to %struct._prop_list_t*) }, section "__DATA, __objc_const", align 8
@"OBJC_CLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_A", %struct._class_t* @"OBJC_CLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*,
i8*)** null, %struct._class_ro_t* @"01l_OBJC_CLASS_RO_$_A" }, section "__DATA, __objc_data", align 8
@"OBJC_LABEL_CLASS_$" = private global [1 x i8*] [i8* bitcast (%struct._class_t* @"OBJC_CLASS_$_A" to i8*)], section "__DATA, __objc_classlist, regular, no_dead_strip", align 8
Selectorの宣言
Swiftは何故速い?
16
%a = alloca %0*, align 8
%1 = load %struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_"
%2 = load i8** @OBJC_SELECTOR_REFERENCES_, !invariant.load !6
%3 = bitcast %struct._class_t* %1 to i8*
%4 = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %3,
i8* %2)
%5 = bitcast i8* %4 to %0*
store %0* %5, %0** %a, align 8
%6 = load %0** %a, align 8
%7 = load i8** @OBJC_SELECTOR_REFERENCES_17, !invariant.load !6
%8 = bitcast %0* %6 to i8*
call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* %8, i8*
%7)
ret i32 0
Swiftは何故速い?
17
call void bitcast (i8* (i8*, i8*, ...)*
@objc_msgSend to void (i8*, i8*)*)(i8*
%8, i8* %7)
Swiftは何故速い?
18
class A {
var str: String?
var int: Int?
func function() {
}
}
Swiftは何故速い?
19
swiftc -emit-ir source.swift > source.ll
Swiftは何故速い?
20
@_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr
inbounds ([11 x i8]* @4, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @5, i64 0, i64 0), %swift.type** (%swift.type*)*
@get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 }
@_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8
@_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8
@_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8
@_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8
@_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8
@_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8
@_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8
@_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8
@_TMLC6source1A = global %swift.type* null, align 8
@_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64,
i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq*, %C6source1A*)*, void (%Sq*, %C6source1A*)*,
{ i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*,
%C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBo, i64 ptrtoint
(%objc_class* @_TMmC6source1A to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable,
i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, i8* }* @_DATA__TtC6source1A to
i64), i64 1), i32 3, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32,
i32, i32 }* @_TMnC6source1A, void (%Sq*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 }
(i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)*
@_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)*
@_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }
Swiftは何故速い?
21
@_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr
inbounds ([11 x i8]* @4, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @5, i64 0, i64 0), %swift.type** (%swift.type*)*
@get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 }
@_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8
@_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8
@_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8
@_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8
@_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8
@_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8
@_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8
@_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8
@_TMLC6source1A = global %swift.type* null, align 8
@_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64,
i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq*, %C6source1A*)*, void (%Sq*, %C6source1A*)*,
{ i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*,
%C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBo, i64 ptrtoint
(%objc_class* @_TMmC6source1A to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable,
i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, i8* }* @_DATA__TtC6source1A to
i64), i64 1), i32 3, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32,
i32, i32 }* @_TMnC6source1A, void (%Sq*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 }
(i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)*
@_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)*
@_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }
vtable
Swiftは何故速い?
22
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0,
i32 0), align 8
%5 = call %swift.type* @_TMaC6source1A() #2
%6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5)
store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8
%7 = load %C6source1A** @_Tv6source1aCS_1A, align 8
%8 = bitcast %C6source1A* %7 to %swift.refcounted*
call void @swift_retain_noresult(%swift.refcounted* %8) #3
%9 = bitcast %C6source1A* %7 to %swift.type**
%.metadata = load %swift.type** %9, align 8
%10 = bitcast %swift.type* %.metadata to void (%C6source1A*)**
%11 = getelementptr inbounds void (%C6source1A*)** %10, i64 9
%.metadata1 = load void (%C6source1A*)** %11, align 8, !invariant.load !29
%12 = bitcast void (%C6source1A*)* %.metadata1 to i8*
%13 = bitcast i8* %12 to void (%C6source1A*)*
call void %13(%C6source1A* %7)
call void bitcast (void (%swift.refcounted*)* @swift_release to void (%C6source1A*)*)(%C6source1A* %7) #3
ret i32 0
Swiftは何故速い?
23
store i8* %2, i8** getelementptr inbounds
(%VSs20UnsafeMutablePointer* @
%5 = call %swift.type* @_TMaC6source1A() #2
%6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5)
store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8
%7 = load %C6source1A** @_Tv6source1aCS_1A, align 8
%8 = bitcast %C6source1A* %7 to %swift.refcounted*
call void @swift_retain_noresult(%swift.refcounted* %8) #3
%9 = bitcast %C6source1A* %7 to %swift.type**
%.metadata = load %swift.type** %9, align 8
%10 = bitcast %swift.type* %.metadata to void (%C6source1A*)**
%11 = getelementptr inbounds void (%C6source1A*)** %10, i64 9
%.metadata1 = load void (%C6source1A*)** %11, align 8,
%12 = bitcast void (%C6source1A*)* %.metadata1 to i8*
%13 = bitcast i8* %12 to void (%C6source1A*)*
call void %13(%C6source1A* %7)
Swiftは何故速い?
24
%11 = getelementptr inbounds void
(%C6source1A*)** %10, i64 9
Swiftは何故速い?
25
class A: NSObject {
var str: String?
var int: Int?
func function() {
}
}
Swiftは何故速い?
26
@8 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00"
@_METACLASS_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8*
getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8
@_INSTANCE_METHODS__TtC6source1A = private constant { i32, i32, [5 x { i8*, i8*, i8* }] } { i32 24, i32 5, [5 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8*
getelementptr inbounds ([4 x i8]* @"01L_selector_data(str)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%0* (%1*, i8*)*
@_TToFC6source1Ag3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(setStr:)", i64 0, i64 0), i8* getelementptr
inbounds ([11 x i8]* @4, i64 0, i64 0), i8* bitcast (void (%1*, i8*, %0*)* @_TToFC6source1As3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([9 x
i8]* @"01L_selector_data(function)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @6, i64 0, i64 0), i8* bitcast (void (%1*, i8*)*
@_TToFC6source1A8functionfS0_FT_T_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), i8* getelementptr
inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%1* (%1*, i8*)* @_TToFC6source1AcfMS0_FT_S0_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8]*
@"01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8* getelementptr inbounds ([3 x i8]* @7, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1AE to i8*) }]
}, section "__DATA, __objc_const", align 8
@_IVARS__TtC6source1A = private constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32,
i32 } { i64* @_TWvdvC6source1A3strGSqSS_, i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32
25 }, { i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3intGSqSi_, i8* getelementptr inbounds ([4 x i8]* @5, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]*
@1, i64 0, i64 0), i32 3, i32 9 }] }, section "__DATA, __objc_const", align 8
@_PROPERTIES__TtC6source1A = private constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([4 x i8]*
@0, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8]* @2, i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8
@_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*,
i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 16, i32 57, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), { i32, i32, [5 x { i8*,
i8*, i8* }] }* @_INSTANCE_METHODS__TtC6source1A, i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS__TtC6source1A, i8* null, { i32, i32, [1 x { i8*,
i8* }] }* @_PROPERTIES__TtC6source1A }, section "__DATA, __objc_const", align 8
@9 = private unnamed_addr constant [11 x i8] c"C6source1A00"
@10 = private unnamed_addr constant [9 x i8] c"str00int0000"
@_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x
i8]* @9, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @10, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern*
null, i32 0, i32 0, i32 0 }
@_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8
@_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8
@_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8
@_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8
@_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8
@_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8
@_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8
@_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8
@_TMLC6source1A = global %swift.type* null, align 8
@_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32,
i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq.16*, %C6source1A*)*, void (%Sq.16*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*,
%C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A*
(%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBO, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC6source1A" to i64), %objc_class*
@"OBJC_CLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x
{ i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC6source1A to i64), i64 1), i32 1,
i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void
(%Sq.16*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq.16*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*
@_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x
i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16,
i64 48 }, section "__DATA,__objc_data, regular, no_dead_strip"
Swiftは何故速い?
27
@8 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00"
@_METACLASS_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8*
getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8
@_INSTANCE_METHODS__TtC6source1A = private constant { i32, i32, [5 x { i8*, i8*, i8* }] } { i32 24, i32 5, [5 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8*
getelementptr inbounds ([4 x i8]* @"01L_selector_data(str)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%0* (%1*, i8*)*
@_TToFC6source1Ag3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(setStr:)", i64 0, i64 0), i8* getelementptr
inbounds ([11 x i8]* @4, i64 0, i64 0), i8* bitcast (void (%1*, i8*, %0*)* @_TToFC6source1As3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([9 x
i8]* @"01L_selector_data(function)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @6, i64 0, i64 0), i8* bitcast (void (%1*, i8*)*
@_TToFC6source1A8functionfS0_FT_T_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), i8* getelementptr
inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%1* (%1*, i8*)* @_TToFC6source1AcfMS0_FT_S0_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8]*
@"01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8* getelementptr inbounds ([3 x i8]* @7, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1AE to i8*) }]
}, section "__DATA, __objc_const", align 8
@_IVARS__TtC6source1A = private constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32,
i32 } { i64* @_TWvdvC6source1A3strGSqSS_, i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32
25 }, { i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3intGSqSi_, i8* getelementptr inbounds ([4 x i8]* @5, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]*
@1, i64 0, i64 0), i32 3, i32 9 }] }, section "__DATA, __objc_const", align 8
@_PROPERTIES__TtC6source1A = private constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([4 x i8]*
@0, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8]* @2, i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8
@_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*,
i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 16, i32 57, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), { i32, i32, [5 x { i8*,
i8*, i8* }] }* @_INSTANCE_METHODS__TtC6source1A, i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS__TtC6source1A, i8* null, { i32, i32, [1 x { i8*,
i8* }] }* @_PROPERTIES__TtC6source1A }, section "__DATA, __objc_const", align 8
@9 = private unnamed_addr constant [11 x i8] c"C6source1A00"
@10 = private unnamed_addr constant [9 x i8] c"str00int0000"
@_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x
i8]* @9, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @10, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern*
null, i32 0, i32 0, i32 0 }
@_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8
@_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8
@_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8
@_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8
@_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8
@_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8
@_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8
@_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8
@_TMLC6source1A = global %swift.type* null, align 8
@_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32,
i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq.16*, %C6source1A*)*, void (%Sq.16*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*,
%C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A*
(%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBO, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC6source1A" to i64), %objc_class*
@"OBJC_CLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x
{ i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC6source1A to i64), i64 1), i32 1,
i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void
(%Sq.16*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq.16*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*
@_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x
i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16,
i64 48 }, section "__DATA,__objc_data, regular, no_dead_strip"
Selectorの宣言
vtable
Swiftは何故速い?
28
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0,
i32 0), align 8
%5 = call %swift.type* @_TMaC6source1A() #2
%6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5)
store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8
%7 = load %C6source1A** @_Tv6source1aCS_1A, align 8
%8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #3
%9 = bitcast %C6source1A* %7 to i64*
%10 = load i64* %9, align 8
%11 = load i64* @swift_isaMask, align 8
%12 = and i64 %10, %11
%13 = inttoptr i64 %12 to %swift.type*
%14 = bitcast %swift.type* %13 to void (%C6source1A*)**
%15 = getelementptr inbounds void (%C6source1A*)** %14, i64 15
%16 = load void (%C6source1A*)** %15, align 8, !invariant.load !29
%17 = bitcast void (%C6source1A*)* %16 to i8*
%18 = bitcast i8* %17 to void (%C6source1A*)*
call void %18(%C6source1A* %7)
call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %7) #3
ret i32 0
Swiftは何故速い?
29
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0,
i32 0), align 8
%5 = call %swift.type* @_TMaC6source1A() #2
%6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5)
store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8
%7 = load %C6source1A** @_Tv6source1aCS_1A, align 8
%8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #3
%9 = bitcast %C6source1A* %7 to i64*
%10 = load i64* %9, align 8
%11 = load i64* @swift_isaMask, align 8
%12 = and i64 %10, %11
%13 = inttoptr i64 %12 to %swift.type*
%14 = bitcast %swift.type* %13 to void (%C6source1A*)**
%15 = getelementptr inbounds void (%C6source1A*)** %14, i64 15
%16 = load void (%C6source1A*)** %15, align 8, !invariant.load !29
%17 = bitcast void (%C6source1A*)* %16 to i8*
%18 = bitcast i8* %17 to void (%C6source1A*)*
call void %18(%C6source1A* %7)
call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %7) #3
ret i32 0
objc_msgSendではない
Swiftは何故速い?
classメソッドの呼び出しが
objc_msgSendからvtableに変更されパ
フォーマンスが向上した
NSObjectを継承すると、objc_msgSend
が使用できる状態になるが、vtableも存
在し、vtableが優先的に使用される
30
Swiftは何故速い?
vtableを利用しているため、ランタ
イムAPIを使ったテクニックの幾つか
が使えなくなっていることに注意
Method SwizzlingはSwift製の

クラスには無効
31
struct/enum
struct/enum
33
struct A {
var str: String?
var int: Int?
func function() {
}
}
34
swiftc -emit-ir source.swift > source.ll
struct/enum
struct/enum
35
@_Tv6source1aVS_1A = global %V6source1A zeroinitializer, align 8
@_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5Int32, align 4
@globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6 = external global i64, align 8
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__ = external global %VSs20UnsafeMutablePointer, align 8
@_TWVV6source1A = constant [20 x i8*] [i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwXXV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*,
[24 x i8]*, %swift.type*)* @_TwCPV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwprV6source1A to i8*), i8* bitcast (void
([24 x i8]*, %swift.type*)* @_TwdeV6source1A to i8*), i8* bitcast (void (%swift.opaque*, %swift.type*)* @_TwxxV6source1A to i8*), i8* bitcast
(%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwCpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*,
%swift.type*)* @_TwcpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcaV6source1A to i8*), i8*
bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwTkV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)*
@__swift_memcpy41_8 to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwtaV6source1A to i8*), i8* bitcast
(%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwalV6source1A to i8*), i8* bitcast (i8* (i8**, i8**, %swift.type*)* @__swift_copy_outline_pointer to
i8*), i8* bitcast (void (%swift.opaque*, i64, %swift.type*)* @_TwXxV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, i64,
%swift.type*)* @_TwCcV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* bitcast (i8* (i8*, i8*,
i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* inttoptr (i64 41 to i8*), i8* inttoptr (i64 196615 to i8*), i8* inttoptr (i64 48 to i8*)]
@0 = private unnamed_addr constant [11 x i8] c"V6source1A00"
@1 = private unnamed_addr constant [9 x i8] c"str00int0000"
@_TMnV6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 1, i8* getelementptr
inbounds ([11 x i8]* @0, i64 0, i64 0), i32 2, i32 3, i8* getelementptr inbounds ([9 x i8]* @1, i64 0, i64 0), %swift.type** (%swift.type*)*
@get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 }
@_TMdV6source1A = constant { i8**, i64, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, %swift.type*,
i64, i64 } { i8** getelementptr inbounds ([20 x i8*]* @_TWVV6source1A, i32 0, i32 0), i64 1, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*,
%swift.type_pattern*, i32, i32, i32 }* @_TMnV6source1A, %swift.type* null, i64 0, i64 32 }
struct/enum
36
@_Tv6source1aVS_1A = global %V6source1A zeroinitializer, align 8
@_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5Int32, align 4
@globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6 = external global i64, align 8
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__ = external global %VSs20UnsafeMutablePointer, align 8
@_TWVV6source1A = constant [20 x i8*] [i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwXXV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*,
[24 x i8]*, %swift.type*)* @_TwCPV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwprV6source1A to i8*), i8* bitcast (void
([24 x i8]*, %swift.type*)* @_TwdeV6source1A to i8*), i8* bitcast (void (%swift.opaque*, %swift.type*)* @_TwxxV6source1A to i8*), i8* bitcast
(%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwCpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*,
%swift.type*)* @_TwcpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcaV6source1A to i8*), i8*
bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwTkV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)*
@__swift_memcpy41_8 to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwtaV6source1A to i8*), i8* bitcast
(%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwalV6source1A to i8*), i8* bitcast (i8* (i8**, i8**, %swift.type*)* @__swift_copy_outline_pointer to
i8*), i8* bitcast (void (%swift.opaque*, i64, %swift.type*)* @_TwXxV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, i64,
%swift.type*)* @_TwCcV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* bitcast (i8* (i8*, i8*,
i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* inttoptr (i64 41 to i8*), i8* inttoptr (i64 196615 to i8*), i8* inttoptr (i64 48 to i8*)]
@0 = private unnamed_addr constant [11 x i8] c"V6source1A00"
@1 = private unnamed_addr constant [9 x i8] c"str00int0000"
@_TMnV6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 1, i8* getelementptr
inbounds ([11 x i8]* @0, i64 0, i64 0), i32 2, i32 3, i8* getelementptr inbounds ([9 x i8]* @1, i64 0, i64 0), %swift.type** (%swift.type*)*
@get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 }
@_TMdV6source1A = constant { i8**, i64, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, %swift.type*,
i64, i64 } { i8** getelementptr inbounds ([20 x i8*]* @_TWVV6source1A, i32 0, i32 0), i64 1, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*,
%swift.type_pattern*, i32, i32, i32 }* @_TMnV6source1A, %swift.type* null, i64 0, i64 32 }
functionの記述が存在しない
struct/enum
37
define hidden void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41)) #0 {
entry:
%.str = getelementptr inbounds %V6source1A* %0, i32 0, i32 0
%1 = bitcast %Sq* %.str to { i64, i64, i64 }*
%2 = getelementptr inbounds { i64, i64, i64 }* %1, i32 0, i32 0
%3 = load i64* %2, align 8
%4 = getelementptr inbounds { i64, i64, i64 }* %1, i32 0, i32 1
%5 = load i64* %4, align 8
%6 = getelementptr inbounds { i64, i64, i64 }* %1, i32 0, i32 2
%7 = load i64* %6, align 8
%8 = getelementptr inbounds %Sq* %.str, i32 0, i32 1
%9 = bitcast [1 x i8]* %8 to i1*
%10 = load i1* %9, align 8
%.int = getelementptr inbounds %V6source1A* %0, i32 0, i32 2
%11 = bitcast %Sq.17* %.int to i64*
%12 = load i64* %11, align 8
%13 = getelementptr inbounds %Sq.17* %.int, i32 0, i32 1
%14 = bitcast [1 x i8]* %13 to i1*
%15 = load i1* %14, align 8
ret void
}
struct/enum
38
%.str = getelementptr inbounds %V6source1A* %2, i32 0, i32 0
%31 = bitcast %Sq* %.str to { i64, i64, i64 }*
%32 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 0
store i64 %21, i64* %32, align 8
%33 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 1
store i64 %22, i64* %33, align 8
%34 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 2
store i64 %23, i64* %34, align 8
%35 = getelementptr inbounds %Sq* %.str, i32 0, i32 1
%36 = bitcast [1 x i8]* %35 to i1*
store i1 %24, i1* %36, align 8
%.int = getelementptr inbounds %V6source1A* %2, i32 0, i32 2
%37 = bitcast %Sq.17* %.int to i64*
store i64 %25, i64* %37, align 8
%38 = getelementptr inbounds %Sq.17* %.int, i32 0, i32 1
%39 = bitcast [1 x i8]* %38 to i1*
store i1 %26, i1* %39, align 8
call void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41) %2)
br i1 %24, label %43, label %40
struct/enum
39
%.str = getelementptr inbounds %V6source1A* %2, i32 0, i32 0
%31 = bitcast %Sq* %.str to { i64, i64, i64 }*
%32 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 0
store i64 %21, i64* %32, align 8
%33 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 1
store i64 %22, i64* %33, align 8
%34 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 2
store i64 %23, i64* %34, align 8
%35 = getelementptr inbounds %Sq* %.str, i32 0, i32 1
%36 = bitcast [1 x i8]* %35 to i1*
store i1 %24, i1* %36, align 8
%.int = getelementptr inbounds %V6source1A* %2, i32 0, i32 2
%37 = bitcast %Sq.17* %.int to i64*
store i64 %25, i64* %37, align 8
%38 = getelementptr inbounds %Sq.17* %.int, i32 0, i32 1
%39 = bitcast [1 x i8]* %38 to i1*
store i1 %26, i1* %39, align 8
call void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41) %2)
br i1 %24, label %43, label %40
関数を直接実行している
struct/enum
40
struct/enumのメソッドはただの関数への
エイリアス
selfを利用する際にコピーが発生しない
vtableよりも高パフォーマンス
struct/enumは値型であるため、事ある毎
にコピーのコストが発生する
アクセス修飾子の話
アクセス修飾子
Swiftのアクセス修飾子は3種類
public
internal
private
classにはfinal修飾子もある
classメソッドの実行方法が変化
42
アクセス修飾子
Swiftのアクセス修飾子は3種類
public…フレームワーク外から参照可
internal…同一フレームワーク内から参照可
private…同一ファイル内から参照可
クラスにはfinal修飾子もある
43
アクセス修飾子
44
class A: NSObject {
var str: String?
var int: Int?
private func function() {
print(self)
}
}
アクセス修飾子
45
@_Tv6source1aCS_1A = global %C6source1A* null, align 8
@_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5Int32, align 4
@globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6 = external global i64, align 8
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__ = external global %VSs20UnsafeMutablePointer, align 8
@_swiftEmptyArrayStorage = external global %VSC23_SwiftEmptyArrayStorage, align 8
@_TWvdvC6source1A3strGSqSS_ = global i64 16, align 8
@"01L_selector_data(dealloc)" = internal constant [8 x i8] c"dealloc00", section "__TEXT,__objc_methname,cstring_literals", align 1
@"01L_selector(dealloc)" = internal global i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(dealloc)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
@_TWvdvC6source1A3intGSqSi_ = global i64 48, align 8
@"01L_selector_data(init)" = internal constant [5 x i8] c"init00", section "__TEXT,__objc_methname,cstring_literals", align 1
@"01L_selector(init)" = internal global i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
@"01L_selector_data(allocWithZone:)" = internal constant [15 x i8] c"allocWithZone:00", section "__TEXT,__objc_methname,cstring_literals", align 1
@"01L_selector(allocWithZone:)" = internal global i8* getelementptr inbounds ([15 x i8]* @"01L_selector_data(allocWithZone:)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
@_TWVBO = external global i8*
@"OBJC_METACLASS_$__TtC6source1A" = global %objc_class { %objc_class* @"OBJC_METACLASS_$_NSObject", %objc_class* @"OBJC_METACLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 ptrtoint ({ i32, i32,
i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_METACLASS_DATA__TtC6source1A to i64) }
@"OBJC_CLASS_$_NSObject" = external global %objc_class
@_objc_empty_cache = external global %swift.opaque
@_objc_empty_vtable = external global %swift.opaque
@0 = private unnamed_addr constant [4 x i8] c"str00"
@1 = private unnamed_addr constant [1 x i8] zeroinitializer
@2 = private unnamed_addr constant [22 x i8] c"T@22NSString22,N,C,Vstr00"
@"01L_selector_data(str)" = internal constant [4 x i8] c"str00", section "__TEXT,__objc_methname,cstring_literals", align 1
@3 = private unnamed_addr constant [8 x i8] c"@16@0:800"
@"01L_selector_data(setStr:)" = internal constant [8 x i8] c"setStr:00", section "__TEXT,__objc_methname,cstring_literals", align 1
@4 = private unnamed_addr constant [11 x i8] c"v24@0:8@1600"
@5 = private unnamed_addr constant [4 x i8] c"int00"
@"01L_selector_data(.cxx_destruct)" = internal constant [14 x i8] c".cxx_destruct00", section "__TEXT,__objc_methname,cstring_literals", align 1
@6 = private unnamed_addr constant [3 x i8] c"@?00"
@"OBJC_METACLASS_$_NSObject" = external global %objc_class
@7 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00"
@_METACLASS_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @7, i64 0, i64 0), i8* null, i8* null, i8* null,
i8* null, i8* null }, section "__DATA, __objc_const", align 8
@_INSTANCE_METHODS__TtC6source1A = private constant { i32, i32, [4 x { i8*, i8*, i8* }] } { i32 24, i32 4, [4 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @"01L_selector_data(str)", i64 0, i64 0), i8*
getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%0* (%1*, i8*)* @_TToFC6source1Ag3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(setStr:)", i64 0, i64 0), i8*
getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i8* bitcast (void (%1*, i8*, %0*)* @_TToFC6source1As3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), i8*
getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%1* (%1*, i8*)* @_TToFC6source1AcfMS0_FT_S0_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8]* @"01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8*
getelementptr inbounds ([3 x i8]* @6, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1AE to i8*) }] }, section "__DATA, __objc_const", align 8
@_IVARS__TtC6source1A = private constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3strGSqSS_, i8* getelementptr inbounds ([4 x
i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 25 }, { i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3intGSqSi_, i8* getelementptr inbounds ([4 x i8]* @5, i64 0, i64 0), i8* getelementptr
inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 9 }] }, section "__DATA, __objc_const", align 8
@_PROPERTIES__TtC6source1A = private constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8]* @2, i64 0,
i64 0) }] }, section "__DATA, __objc_const", align 8
@_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [4 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 16, i32 57, i32
0, i8* null, i8* getelementptr inbounds ([14 x i8]* @7, i64 0, i64 0), { i32, i32, [4 x { i8*, i8*, i8* }] }* @_INSTANCE_METHODS__TtC6source1A, i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS__TtC6source1A, i8* null,
{ i32, i32, [1 x { i8*, i8* }] }* @_PROPERTIES__TtC6source1A }, section "__DATA, __objc_const", align 8
@8 = private unnamed_addr constant [11 x i8] c"C6source1A00"
@9 = private unnamed_addr constant [9 x i8] c"str00int0000"
@_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @8, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x
i8]* @9, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 }
@_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8
@_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8
@_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8
@_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8
@_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8
@_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8
@_TWoFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_ = hidden constant i64 136, align 8
@_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8
@_TMLC6source1A = global %swift.type* null, align 8
@_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32,
i32 }*, void (%Sq.16*, %C6source1A*)*, void (%Sq.16*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void
(%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBO, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC6source1A" to i64), %objc_class* @"OBJC_CLASS_$_NSObject", %swift.opaque*
@_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [4 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*,
i8* }] }* }* @_DATA__TtC6source1A to i64), i64 1), i32 1, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq.16*,
%C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq.16*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64,
i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_, %C6source1A* (%C6source1A*)*
@_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }, section "__DATA,__objc_data, regular, no_dead_strip"
functionのSelectorが存在しない
アクセス修飾子
46
@"01L_selector_data(dealloc)" = internal constant [8 x i8] c"dealloc00", section
"__TEXT,__objc_methname,cstring_literals", align 1
@"01L_selector(dealloc)" = internal global i8* getelementptr inbounds ([8 x i8]*
@"01L_selector_data(dealloc)", i64 0, i64 0), section
"__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
@_TWvdvC6source1A3intGSqSi_ = global i64 48, align 8
@"01L_selector_data(init)" = internal constant [5 x i8] c"init00", section
"__TEXT,__objc_methname,cstring_literals", align 1
@"01L_selector(init)" = internal global i8* getelementptr inbounds ([5 x i8]*
@"01L_selector_data(init)", i64 0, i64 0), section
"__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
@"01L_selector_data(allocWithZone:)" = internal constant [15 x i8] c"allocWithZone:00", section
"__TEXT,__objc_methname,cstring_literals", align 1
@"01L_selector(allocWithZone:)" = internal global i8* getelementptr inbounds ([15 x i8]*
@"01L_selector_data(allocWithZone:)", i64 0, i64 0), section
"__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
@_TWVBO = external global i8*
@"OBJC_METACLASS_$__TtC6source1A" = global %objc_class { %objc_class* @"OBJC_METACLASS_
$_NSObject", %objc_class* @"OBJC_METACLASS_$_NSObject", %swift.opaque* @_objc_empty_cache,
%swift.opaque* @_objc_empty_vtable, i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*,
i8*, i8* }* @_METACLASS_DATA__TtC6source1A to i64) }
@"OBJC_CLASS_$_NSObject" = external global %objc_class
アクセス修飾子
47
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0),
align 8
%5 = call %swift.type* @_TMaC6source1A() #3
%6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5)
store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8
%7 = load %C6source1A** @_Tv6source1aCS_1A, align 8
%8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to
%C6source1A* (%C6source1A*)*)(%C6source1A* %7) #4
call void
@_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_(%C6source1A* %7)
call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)
(%C6source1A* %7) #4
ret i32 0 関数を直接実行している
アクセス修飾子
48
class B: A {
override private func function() {
}
}
アクセス修飾子
49
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8
%5 = call %swift.type* @_TMaC6source1A() #2
%6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5)
store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8
%7 = load %C6source1A** @_Tv6source1aCS_1A, align 8
%8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A*
(%C6source1A*)*)(%C6source1A* %7) #3
%9 = bitcast %C6source1A* %7 to i64*
%10 = load i64* %9, align 8
%11 = load i64* @swift_isaMask, align 8
%12 = and i64 %10, %11
%13 = inttoptr i64 %12 to %swift.type*
%14 = bitcast %swift.type* %13 to void (%C6source1A*)**
%15 = getelementptr inbounds void (%C6source1A*)** %14, i64 15
%16 = load void (%C6source1A*)** %15, align 8, !invariant.load !29
%17 = bitcast void (%C6source1A*)* %16 to i8*
%18 = bitcast i8* %17 to void (%C6source1A*)*
call void %18(%C6source1A* %7)
call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %7) #3
%19 = call %swift.type* @_TMaC6source1B() #2
%20 = call %C6source1B* @_TFC6source1BCfMS0_FT_S0_(%swift.type* %19)
store %C6source1B* %20, %C6source1B** @_Tv6source1bCS_1B, align 8
%21 = load %C6source1B** @_Tv6source1bCS_1B, align 8
%22 = call %C6source1B* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1B*
(%C6source1B*)*)(%C6source1B* %21) #3
call void @_TFC6source1BP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_(%C6source1B* %21)
call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1B*)*)(%C6source1B* %21) #3
ret i32 0
直接実行
vtable
アクセス修飾子
private修飾子
終端のメソッドは直接呼び出し
オーバーライドされたものはvtable
selectorは存在しない (objc_msgSendできない)
final修飾子
直接呼び出し
selectorは存在しない (objc_msgSendできない)
50
selectorは存在します
アクセス修飾子
privateやfinalのついたメソッドを
addTarget:action:に渡すと死ぬ
隠蔽したい場合は?
モジュール切ってinternalに

 しましょう
51
Any vs Generics
Any
Swiftで定義された「なんでも代入可
能な型」
typealias protocol<>
Objective-Cのid型はAnyObjectに
相当
53
Any
Optionalの値を格納することも可能だが…
Any?型の値をAny型に格納することも可
能。
ネストしたOptionalを取り出すのは面倒。
予めAny?で宣言するが吉。
54
Any
例えばString?型の値をAny型に格納した場合、
a as? Optional<Any>では取り出せない。

a as? Optional<String>で取り出す必要があ
る。
Any型の引数には、渡した変数が型ごと含ま
れているため。暗黙のキャストは走っていな
い。
55
Any
56
define hidden void @_TF6source8functionFP_T_(%"protocol<>"* noalias
nocapture dereferenceable(32)) #0 {
entry:
%1 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 1
%.metadata = load %swift.type** %1, align 8
%2 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 0
%3 = bitcast %swift.type* %.metadata to i8***
%4 = getelementptr inbounds i8*** %3, i64 -1
%.metadata.valueWitnesses = load i8*** %4, align 8, !invariant.load !
29, !dereferenceable !30
%5 = load i8** %.metadata.valueWitnesses, align 8, !invariant.load !29
%destroyBuffer = bitcast i8* %5 to void ([24 x i8]*, %swift.type*)*
call void %destroyBuffer([24 x i8]* %2, %swift.type* %.metadata) #1
ret void
}
Any
57
define hidden void @_TF6source8functionFP_T_(%"protocol<>"* noalias
nocapture dereferenceable(32)) #0 {
entry:
%1 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 1
%.metadata = load %swift.type** %1, align 8
%2 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 0
%3 = bitcast %swift.type* %.metadata to i8***
%4 = getelementptr inbounds i8*** %3, i64 -1
%.metadata.valueWitnesses = load i8*** %4, align 8, !invariant.load !
29, !dereferenceable !30
%5 = load i8** %.metadata.valueWitnesses, align 8, !invariant.load !29
%destroyBuffer = bitcast i8* %5 to void ([24 x i8]*, %swift.type*)*
call void %destroyBuffer([24 x i8]* %2, %swift.type* %.metadata) #1
ret void
}
Any型
Generics
Generics引数は、型引数と曖昧な型
に分割されて渡される。
Genericsの制約が増えれば、型引数
も増える。
58
Generics
59
define hidden void @_TF6source8functionuRq_S_1P_Fq_T_(%swift.opaque*
noalias nocapture, %swift.type* %A, i8** %A.P) #0 {
entry:
%A1 = alloca %swift.type*, align 8
store %swift.type* %A, %swift.type** %A1, align 8
%1 = bitcast %swift.type* %A to i8***
%2 = getelementptr inbounds i8*** %1, i64 -1
%A.valueWitnesses = load i8*** %2, align 8, !invariant.load !29, !
dereferenceable !30
%3 = getelementptr inbounds i8** %A.valueWitnesses, i32 4
%4 = load i8** %3, align 8, !invariant.load !29
%destroy = bitcast i8* %4 to void (%swift.opaque*, %swift.type*)*
call void %destroy(%swift.opaque* %0, %swift.type* %A) #1
ret void
}
Generics
60
define hidden void @_TF6source8functionuRq_S_1P_Fq_T_(%swift.opaque*
noalias nocapture, %swift.type* %A, i8** %A.P) #0 {
entry:
%A1 = alloca %swift.type*, align 8
store %swift.type* %A, %swift.type** %A1, align 8
%1 = bitcast %swift.type* %A to i8***
%2 = getelementptr inbounds i8*** %1, i64 -1
%A.valueWitnesses = load i8*** %2, align 8, !invariant.load !29, !
dereferenceable !30
%3 = getelementptr inbounds i8** %A.valueWitnesses, i32 4
%4 = load i8** %3, align 8, !invariant.load !29
%destroy = bitcast i8* %4 to void (%swift.opaque*, %swift.type*)*
call void %destroy(%swift.opaque* %0, %swift.type* %A) #1
ret void
}
型引数 
Any vs Generics
特殊な要求が無いのであれば、
Genericsを使うべき
とりあえずAnyやAnyObjectの引数
はGenericsにしてみよう
61
Protocol Extension
Protocol Extension
63
protocol P {
}
extension P {
func function() {
}
}
class A: NSObject, P {
var str: String?
var int: Int?
}
Protocol Extension
64
store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32
0, i32 0), align 8
%6 = call %swift.type* @_TMaC6source1A() #2
%7 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %6)
store %C6source1A* %7, %C6source1A** @_Tv6source1aCS_1A, align 8
%8 = load %C6source1A** @_Tv6source1aCS_1A, align 8
%9 = call %C6source1A* bitcast (%objc_object* (%objc_object*)*
@objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %8) #3
store %C6source1A* %8, %C6source1A** %2, align 8
%10 = bitcast %C6source1A** %2 to %swift.opaque*
call void @_TFeRq_6source1P_S_S0_8functionuRq_S0__fq_FT_T_(%swift.type*
%6, i8** getelementptr inbounds ([0 x i8*]* @_TWPC6source1AS_1PS_, i32 0,
i32 0), %swift.opaque* noalias nocapture %10)
%11 = load %C6source1A** %2, align 8
call void bitcast (void (%objc_object*)* @objc_release to void
(%C6source1A*)*)(%C6source1A* %11) #3
ret i32 0
Protocol Extension
65
call void
@_TFeRq_6source1P_S_S0_8functionuRq_S0__fq_FT_T_(%swift.t
ype* %6, i8** getelementptr inbounds ([0 x i8*]*
@_TWPC6source1AS_1PS_, i32 0, i32 0), %swift.opaque*
noalias nocapture %10)
が
型がProtocolだった場合、
Protocol Extension
67
store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8
%6 = call %swift.type* @_TMaC6source1A() #2
store %swift.type* %6, %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8
store i8** getelementptr inbounds ([1 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), i8*** getelementptr inbounds (%P6source1P_*
@_Tv6source1aPS_1P_, i32 0, i32 2), align 8
%7 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %6)
store %C6source1A* %7, %C6source1A** bitcast (%P6source1P_* @_Tv6source1aPS_1P_ to %C6source1A**), align 8
%_Tv6source1aPS_1P_.metadata = load %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8
%8 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1
store %swift.type* %_Tv6source1aPS_1P_.metadata, %swift.type** %8, align 8
%9 = load i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8
%10 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2
store i8** %9, i8*** %10, align 8
%11 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0
%12 = bitcast %swift.type* %_Tv6source1aPS_1P_.metadata to i8***
%13 = getelementptr inbounds i8*** %12, i64 -1
%_Tv6source1aPS_1P_.metadata.valueWitnesses = load i8*** %13, align 8, !invariant.load !29, !dereferenceable !30
%14 = getelementptr inbounds i8** %_Tv6source1aPS_1P_.metadata.valueWitnesses, i32 1
%15 = load i8** %14, align 8, !invariant.load !29
%initializeBufferWithCopyOfBuffer = bitcast i8* %15 to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)*
%16 = call %swift.opaque* %initializeBufferWithCopyOfBuffer([24 x i8]* noalias %11, [24 x i8]* getelementptr inbounds (%P6source1P_*
@_Tv6source1aPS_1P_, i32 0, i32 0), %swift.type* %_Tv6source1aPS_1P_.metadata) #3
%17 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1
%.metadata = load %swift.type** %17, align 8
%18 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0
%19 = bitcast %swift.type* %.metadata to i8***
%20 = getelementptr inbounds i8*** %19, i64 -1
%.metadata.valueWitnesses = load i8*** %20, align 8, !invariant.load !29, !dereferenceable !30
%21 = getelementptr inbounds i8** %.metadata.valueWitnesses, i32 2
%22 = load i8** %21, align 8, !invariant.load !29
%projectBuffer = bitcast i8* %22 to %swift.opaque* ([24 x i8]*, %swift.type*)*
%23 = call %swift.opaque* %projectBuffer([24 x i8]* %18, %swift.type* %.metadata) #3
%24 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2
%witness-table = load i8*** %24, align 8
store %swift.type* %.metadata, %swift.type** %.metadata1, align 8
%25 = load i8** %witness-table, align 8, !invariant.load !29
%26 = bitcast i8* %25 to void (%swift.opaque*, %swift.type*)*
call void %26(%swift.opaque* noalias nocapture %23, %swift.type* %.metadata)
Protocol Extension
68
store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8
%6 = call %swift.type* @_TMaC6source1A() #2
store %swift.type* %6, %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8
store i8** getelementptr inbounds ([1 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), i8*** getelementptr inbounds (%P6source1P_*
@_Tv6source1aPS_1P_, i32 0, i32 2), align 8
%7 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %6)
store %C6source1A* %7, %C6source1A** bitcast (%P6source1P_* @_Tv6source1aPS_1P_ to %C6source1A**), align 8
%_Tv6source1aPS_1P_.metadata = load %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8
%8 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1
store %swift.type* %_Tv6source1aPS_1P_.metadata, %swift.type** %8, align 8
%9 = load i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8
%10 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2
store i8** %9, i8*** %10, align 8
%11 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0
%12 = bitcast %swift.type* %_Tv6source1aPS_1P_.metadata to i8***
%13 = getelementptr inbounds i8*** %12, i64 -1
%_Tv6source1aPS_1P_.metadata.valueWitnesses = load i8*** %13, align 8, !invariant.load !29, !dereferenceable !30
%14 = getelementptr inbounds i8** %_Tv6source1aPS_1P_.metadata.valueWitnesses, i32 1
%15 = load i8** %14, align 8, !invariant.load !29
%initializeBufferWithCopyOfBuffer = bitcast i8* %15 to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)*
%16 = call %swift.opaque* %initializeBufferWithCopyOfBuffer([24 x i8]* noalias %11, [24 x i8]* getelementptr inbounds (%P6source1P_*
@_Tv6source1aPS_1P_, i32 0, i32 0), %swift.type* %_Tv6source1aPS_1P_.metadata) #3
%17 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1
%.metadata = load %swift.type** %17, align 8
%18 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0
%19 = bitcast %swift.type* %.metadata to i8***
%20 = getelementptr inbounds i8*** %19, i64 -1
%.metadata.valueWitnesses = load i8*** %20, align 8, !invariant.load !29, !dereferenceable !30
%21 = getelementptr inbounds i8** %.metadata.valueWitnesses, i32 2
%22 = load i8** %21, align 8, !invariant.load !29
%projectBuffer = bitcast i8* %22 to %swift.opaque* ([24 x i8]*, %swift.type*)*
%23 = call %swift.opaque* %projectBuffer([24 x i8]* %18, %swift.type* %.metadata) #3
%24 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2
%witness-table = load i8*** %24, align 8
store %swift.type* %.metadata, %swift.type** %.metadata1, align 8
%25 = load i8** %witness-table, align 8, !invariant.load !29
%26 = bitcast i8* %25 to void (%swift.opaque*, %swift.type*)*
call void %26(%swift.opaque* noalias nocapture %23, %swift.type* %.metadata) witness-tableを利用
optional func
optional func
70
@objc protocol Delegate: NSObjectProtocol {
optional func function()
}
71
swiftc -emit-ir source.swift > source.ll
struct/enum
optional func
できませんでした。。。
コンパイラが賢い?
同一ファイル内はチェックしてい
るっぽい
72
Closure
Closure
Swiftではメソッドへの参照を
Closureとして利用することが可能
(2.0 )
74
Closure
75
class A: NSObject {
var str: String?
var int: Int?
private func function() {
print(self)
}
}
var a = A()
var m = a.function
Closure
76
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8
%5 = call %swift.type* @_TMaC6source1A() #3
%6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5)
store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8
%7 = load %C6source1A** @_Tv6source1aCS_1A, align 8
%8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A*
(%C6source1A*)*)(%C6source1A* %7) #4
%9 = call { i8*, %swift.refcounted* }
@_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionFS0_FT_T_(%C6source1A* %7)
%10 = extractvalue { i8*, %swift.refcounted* } %9, 0
%11 = extractvalue { i8*, %swift.refcounted* } %9, 1
store i8* %10, i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32
0), align 8
store %swift.refcounted* %11, %swift.refcounted** getelementptr inbounds (%swift.function*
@_Tv6source1mFT_T_, i32 0, i32 1), align 8
%12 = load i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0),
align 8
%13 = load %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_,
i32 0, i32 1), align 8
call void @swift_retain_noresult(%swift.refcounted* %13) #4
%14 = bitcast i8* %12 to void (%swift.refcounted*)*
call void %14(%swift.refcounted* %13)
ret i32 0
Closure
77
store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer*
@_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8
%5 = call %swift.type* @_TMaC6source1A() #3
%6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5)
store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8
%7 = load %C6source1A** @_Tv6source1aCS_1A, align 8
%8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A*
(%C6source1A*)*)(%C6source1A* %7) #4
%9 = call { i8*, %swift.refcounted* }
@_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionFS0_FT_T_(%C6source1A* %7)
%10 = extractvalue { i8*, %swift.refcounted* } %9, 0
%11 = extractvalue { i8*, %swift.refcounted* } %9, 1
store i8* %10, i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32
0), align 8
store %swift.refcounted* %11, %swift.refcounted** getelementptr inbounds (%swift.function*
@_Tv6source1mFT_T_, i32 0, i32 1), align 8
%12 = load i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0),
align 8
%13 = load %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_,
i32 0, i32 1), align 8
call void @swift_retain_noresult(%swift.refcounted* %13) #4
%14 = bitcast i8* %12 to void (%swift.refcounted*)*
call void %14(%swift.refcounted* %13)
ret i32 0
Closureを生成してラッピング
Swiftのこれから
Swiftのこれから
Objective-Cランタイムから切り離
される可能性
objc_msgSendを使わなくても、代
替可能な環境が出来つつある
79
Swiftのこれから
addTarget:action:
クロージャで代替が十分可能
メソッドをクロージャとして渡せるよ
うになった(実際はラップされている)
ReferenceCountingの問題
80
Swiftのこれから
optional func
Protocol Extensionにデフォルト
実装を書くことで代替可能に見え
るが…
ちょっと挙動がバグっぽい
81
Swiftのこれから
optional func
Protocol Extensionにデフォルト
実装を書くことで代替可能に見え
るが…
82
まとめ
Swift実際速い
struct/enumはメソッドが直接実行なの
で超速い
private, final付けると直接実行になるの
で超速い
Objective-Cランタイムに依存しない方向へ
83

More Related Content

What's hot

Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveJeff Smith
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascriptAbimbola Idowu
 
VTU DSA Lab Manual
VTU DSA Lab ManualVTU DSA Lab Manual
VTU DSA Lab ManualAkhilaaReddy
 
Hexadite Real Life Django ORM
Hexadite Real Life Django ORMHexadite Real Life Django ORM
Hexadite Real Life Django ORMMaxim Braitmaiere
 
5分で学ぶ差分更新とRxDataSources
5分で学ぶ差分更新とRxDataSources5分で学ぶ差分更新とRxDataSources
5分で学ぶ差分更新とRxDataSourcesYuji Hato
 
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...ssuserd6b1fd
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptVisual Engineering
 
OpenERP Technical Memento
OpenERP Technical MementoOpenERP Technical Memento
OpenERP Technical MementoOdoo
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...ssuserd6b1fd
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with PythonHan Lee
 

What's hot (19)

Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascript
 
OpenSL ES 1.1 Reference Card
OpenSL ES 1.1 Reference CardOpenSL ES 1.1 Reference Card
OpenSL ES 1.1 Reference Card
 
VTU DSA Lab Manual
VTU DSA Lab ManualVTU DSA Lab Manual
VTU DSA Lab Manual
 
OpenCL 2.2 Reference Guide
OpenCL 2.2 Reference GuideOpenCL 2.2 Reference Guide
OpenCL 2.2 Reference Guide
 
SYCL 1.2.1 Reference Card
SYCL 1.2.1 Reference CardSYCL 1.2.1 Reference Card
SYCL 1.2.1 Reference Card
 
Unit 3
Unit 3 Unit 3
Unit 3
 
Hexadite Real Life Django ORM
Hexadite Real Life Django ORMHexadite Real Life Django ORM
Hexadite Real Life Django ORM
 
5分で学ぶ差分更新とRxDataSources
5分で学ぶ差分更新とRxDataSources5分で学ぶ差分更新とRxDataSources
5分で学ぶ差分更新とRxDataSources
 
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
OpenCL 2.1 Reference Guide
OpenCL 2.1 Reference GuideOpenCL 2.1 Reference Guide
OpenCL 2.1 Reference Guide
 
OpenERP Technical Memento
OpenERP Technical MementoOpenERP Technical Memento
OpenERP Technical Memento
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
package org dev
package org devpackage org dev
package org dev
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
 
Java script obfuscation
Java script obfuscationJava script obfuscation
Java script obfuscation
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
 
Exceptional exceptions
Exceptional exceptionsExceptional exceptions
Exceptional exceptions
 

Similar to Swiftとメソッドのアレコレ

Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedPascal-Louis Perez
 
Data Structure in C (Lab Programs)
Data Structure in C (Lab Programs)Data Structure in C (Lab Programs)
Data Structure in C (Lab Programs)Saket Pathak
 
droidQuery: The Android port of jQuery
droidQuery: The Android port of jQuerydroidQuery: The Android port of jQuery
droidQuery: The Android port of jQueryPhDBrown
 
Part II: LLVM Intermediate Representation
Part II: LLVM Intermediate RepresentationPart II: LLVM Intermediate Representation
Part II: LLVM Intermediate RepresentationWei-Ren Chen
 
Chapter 7 functions (c)
Chapter 7 functions (c)Chapter 7 functions (c)
Chapter 7 functions (c)hhliu
 
Swift internals
Swift internalsSwift internals
Swift internalsJung Kim
 
Introduction to Spring MVC
Introduction to Spring MVCIntroduction to Spring MVC
Introduction to Spring MVCRichard Paul
 
Models, controllers and views
Models, controllers and viewsModels, controllers and views
Models, controllers and viewspriestc
 
Practical Model View Programming (Roadshow Version)
Practical Model View Programming (Roadshow Version)Practical Model View Programming (Roadshow Version)
Practical Model View Programming (Roadshow Version)Marius Bugge Monsen
 
Hidden Gems in Swift
Hidden Gems in SwiftHidden Gems in Swift
Hidden Gems in SwiftNetguru
 

Similar to Swiftとメソッドのアレコレ (20)

Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
Data Structure in C (Lab Programs)
Data Structure in C (Lab Programs)Data Structure in C (Lab Programs)
Data Structure in C (Lab Programs)
 
Objective-c Runtime
Objective-c RuntimeObjective-c Runtime
Objective-c Runtime
 
droidQuery: The Android port of jQuery
droidQuery: The Android port of jQuerydroidQuery: The Android port of jQuery
droidQuery: The Android port of jQuery
 
Part II: LLVM Intermediate Representation
Part II: LLVM Intermediate RepresentationPart II: LLVM Intermediate Representation
Part II: LLVM Intermediate Representation
 
Chapter 7 functions (c)
Chapter 7 functions (c)Chapter 7 functions (c)
Chapter 7 functions (c)
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
Swift internals
Swift internalsSwift internals
Swift internals
 
Introduction to Spring MVC
Introduction to Spring MVCIntroduction to Spring MVC
Introduction to Spring MVC
 
Live Updating Swift Code
Live Updating Swift CodeLive Updating Swift Code
Live Updating Swift Code
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
Treinamento Qt básico - aula II
Treinamento Qt básico - aula IITreinamento Qt básico - aula II
Treinamento Qt básico - aula II
 
Array
ArrayArray
Array
 
Advance java
Advance javaAdvance java
Advance java
 
Awt components
Awt componentsAwt components
Awt components
 
Models, controllers and views
Models, controllers and viewsModels, controllers and views
Models, controllers and views
 
Unit 3
Unit 3 Unit 3
Unit 3
 
var, let in SIL
var, let in SILvar, let in SIL
var, let in SIL
 
Practical Model View Programming (Roadshow Version)
Practical Model View Programming (Roadshow Version)Practical Model View Programming (Roadshow Version)
Practical Model View Programming (Roadshow Version)
 
Hidden Gems in Swift
Hidden Gems in SwiftHidden Gems in Swift
Hidden Gems in Swift
 

Recently uploaded

CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdfCCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdfAsst.prof M.Gokilavani
 
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdfCCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdfAsst.prof M.Gokilavani
 
IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024Mark Billinghurst
 
Sachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
Sachpazis Costas: Geotechnical Engineering: A student's Perspective IntroductionSachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
Sachpazis Costas: Geotechnical Engineering: A student's Perspective IntroductionDr.Costas Sachpazis
 
Concrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptxConcrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptxKartikeyaDwivedi3
 
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)dollysharma2066
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024hassan khalil
 
Introduction-To-Agricultural-Surveillance-Rover.pptx
Introduction-To-Agricultural-Surveillance-Rover.pptxIntroduction-To-Agricultural-Surveillance-Rover.pptx
Introduction-To-Agricultural-Surveillance-Rover.pptxk795866
 
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxJoão Esperancinha
 
main PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfidmain PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfidNikhilNagaraju
 
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort serviceGurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort servicejennyeacort
 
An introduction to Semiconductor and its types.pptx
An introduction to Semiconductor and its types.pptxAn introduction to Semiconductor and its types.pptx
An introduction to Semiconductor and its types.pptxPurva Nikam
 
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catcherssdickerson1
 
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdfCCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdfAsst.prof M.Gokilavani
 
Artificial-Intelligence-in-Electronics (K).pptx
Artificial-Intelligence-in-Electronics (K).pptxArtificial-Intelligence-in-Electronics (K).pptx
Artificial-Intelligence-in-Electronics (K).pptxbritheesh05
 
Application of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptxApplication of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptx959SahilShah
 
computer application and construction management
computer application and construction managementcomputer application and construction management
computer application and construction managementMariconPadriquez1
 

Recently uploaded (20)

CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdfCCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
CCS355 Neural Network & Deep Learning UNIT III notes and Question bank .pdf
 
Design and analysis of solar grass cutter.pdf
Design and analysis of solar grass cutter.pdfDesign and analysis of solar grass cutter.pdf
Design and analysis of solar grass cutter.pdf
 
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdfCCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
 
IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024
 
Sachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
Sachpazis Costas: Geotechnical Engineering: A student's Perspective IntroductionSachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
Sachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
 
Concrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptxConcrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptx
 
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
Call Us ≽ 8377877756 ≼ Call Girls In Shastri Nagar (Delhi)
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024
 
Introduction-To-Agricultural-Surveillance-Rover.pptx
Introduction-To-Agricultural-Surveillance-Rover.pptxIntroduction-To-Agricultural-Surveillance-Rover.pptx
Introduction-To-Agricultural-Surveillance-Rover.pptx
 
young call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Service
young call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Serviceyoung call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Service
young call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Service
 
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptxDecoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
Decoding Kotlin - Your guide to solving the mysterious in Kotlin.pptx
 
main PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfidmain PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfid
 
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort serviceGurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
 
An introduction to Semiconductor and its types.pptx
An introduction to Semiconductor and its types.pptxAn introduction to Semiconductor and its types.pptx
An introduction to Semiconductor and its types.pptx
 
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
 
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdfCCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
CCS355 Neural Networks & Deep Learning Unit 1 PDF notes with Question bank .pdf
 
Artificial-Intelligence-in-Electronics (K).pptx
Artificial-Intelligence-in-Electronics (K).pptxArtificial-Intelligence-in-Electronics (K).pptx
Artificial-Intelligence-in-Electronics (K).pptx
 
Application of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptxApplication of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptx
 
computer application and construction management
computer application and construction managementcomputer application and construction management
computer application and construction management
 
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptxExploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
 

Swiftとメソッドのアレコレ

  • 6. objc_msgSend 6 Class IMP void aFunction(id self, SEL _cmd) { … } SEL 処理はCの関数と同等のIMPに存在 IMPへの参照とSelectorの組を持つ
  • 12. Swiftは何故速い? 12 @interface A : NSObject @property (nonatomic) NSString *str; @property (nonatomic) NSInteger integer; @end @implementation A - (void)function { } @end
  • 14. Swiftは何故速い? 14 @"OBJC_IVAR_$_A._str" = hidden global i64 8, section "__DATA, __objc_ivar", align 8 @"OBJC_IVAR_$_A._integer" = hidden global i64 16, section "__DATA, __objc_ivar", align 8 @_objc_empty_cache = external global %struct._objc_cache @"OBJC_METACLASS_$_NSObject" = external global %struct._class_t @OBJC_CLASS_NAME_ = private global [2 x i8] c"A00", section "__TEXT,__objc_classname,cstring_literals", align 1 @"01l_OBJC_METACLASS_RO_$_A" = private global %struct._class_ro_t { i32 1, i32 40, i32 40, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8 @"OBJC_METACLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_METACLASS_RO_$_A" }, section "__DATA, __objc_data", align 8 @"OBJC_CLASS_$_NSObject" = external global %struct._class_t @OBJC_METH_VAR_NAME_ = private global [9 x i8] c"function00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_ = private global [8 x i8] c"v16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_1 = private global [4 x i8] c"str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_2 = private global [8 x i8] c"@16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_3 = private global [8 x i8] c"setStr:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_4 = private global [11 x i8] c"v24@0:8@1600", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_5 = private global [8 x i8] c"integer00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_6 = private global [8 x i8] c"q16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_7 = private global [12 x i8] c"setInteger:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_8 = private global [11 x i8] c"v24@0:8q1600", section "__TEXT,__objc_methtype,cstring_literals", align 1 @"01l_OBJC_$_INSTANCE_METHODS_A" = private global { i32, i32, [5 x %struct._objc_method] } { i32 24, i32 5, [5 x %struct._objc_method] [%struct._objc_method { i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast (void (%0*, i8*)* @"01-[A function]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([4 x i8]* @OBJC_METH_VAR_NAME_1, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_2, i32 0, i32 0), i8* bitcast (%1* (%0*, i8*)* @"01-[A str]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_3, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_4, i32 0, i32 0), i8* bitcast (void (%0*, i8*, %1*)* @"01-[A setStr:]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_5, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_6, i32 0, i32 0), i8* bitcast (i64 (%0*, i8*)* @"01-[A integer]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_NAME_7, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_8, i32 0, i32 0), i8* bitcast (void (%0*, i8*, i64)* @"01-[A setInteger:]" to i8*) }] }, section "__DATA, __objc_const", align 8 @OBJC_METH_VAR_NAME_9 = private global [5 x i8] c"_str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_10 = private global [12 x i8] c"@22NSString2200", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_11 = private global [9 x i8] c"_integer00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_12 = private global [2 x i8] c"q00", section "__TEXT,__objc_methtype,cstring_literals", align 1 @"01l_OBJC_$_INSTANCE_VARIABLES_A" = private global { i32, i32, [2 x %struct._ivar_t] } { i32 32, i32 2, [2 x %struct._ivar_t] [%struct._ivar_t { i64* @"OBJC_IVAR_$_A._str", i8* getelementptr inbounds ([5 x i8]* @OBJC_METH_VAR_NAME_9, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_TYPE_10, i32 0, i32 0), i32 3, i32 8 }, %struct._ivar_t { i64* @"OBJC_IVAR_$_A._integer", i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_11, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8]* @OBJC_METH_VAR_TYPE_12, i32 0, i32 0), i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8 @OBJC_PROP_NAME_ATTR_ = private global [4 x i8] c"str00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_13 = private global [21 x i8] c"T@22NSString22,N,V_str00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_14 = private global [8 x i8] c"integer00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_15 = private global [15 x i8] c"Tq,N,V_integer00", section "__TEXT,__cstring,cstring_literals", align 1 @"01l_OBJC_$_PROP_LIST_A" = private global { i32, i32, [2 x %struct._prop_t] } { i32 16, i32 2, [2 x %struct._prop_t] [%struct._prop_t { i8* getelementptr inbounds ([4 x i8]* @OBJC_PROP_NAME_ATTR_, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8]* @OBJC_PROP_NAME_ATTR_13, i32 0, i32 0) }, %struct._prop_t { i8* getelementptr inbounds ([8 x i8]* @OBJC_PROP_NAME_ATTR_14, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8]* @OBJC_PROP_NAME_ATTR_15, i32 0, i32 0) }] }, section "__DATA, __objc_const", align 8 @"01l_OBJC_CLASS_RO_$_A" = private global %struct._class_ro_t { i32 0, i32 8, i32 24, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* bitcast ({ i32, i32, [5 x %struct._objc_method] }* @"01l_OBJC_$_INSTANCE_METHODS_A" to %struct.__method_list_t*), %struct._objc_protocol_list* null, %struct._ivar_list_t* bitcast ({ i32, i32, [2 x %struct._ivar_t] }* @"01l_OBJC_$_INSTANCE_VARIABLES_A" to %struct._ivar_list_t*), i8* null, %struct._prop_list_t* bitcast ({ i32, i32, [2 x %struct._prop_t] }* @"01l_OBJC_$_PROP_LIST_A" to %struct._prop_list_t*) }, section "__DATA, __objc_const", align 8 @"OBJC_CLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_A", %struct._class_t* @"OBJC_CLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_CLASS_RO_$_A" }, section "__DATA, __objc_data", align 8 @"OBJC_LABEL_CLASS_$" = private global [1 x i8*] [i8* bitcast (%struct._class_t* @"OBJC_CLASS_$_A" to i8*)], section "__DATA, __objc_classlist, regular, no_dead_strip", align 8
  • 15. Swiftは何故速い? 15 @"OBJC_IVAR_$_A._str" = hidden global i64 8, section "__DATA, __objc_ivar", align 8 @"OBJC_IVAR_$_A._integer" = hidden global i64 16, section "__DATA, __objc_ivar", align 8 @_objc_empty_cache = external global %struct._objc_cache @"OBJC_METACLASS_$_NSObject" = external global %struct._class_t @OBJC_CLASS_NAME_ = private global [2 x i8] c"A00", section "__TEXT,__objc_classname,cstring_literals", align 1 @"01l_OBJC_METACLASS_RO_$_A" = private global %struct._class_ro_t { i32 1, i32 40, i32 40, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8 @"OBJC_METACLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._class_t* @"OBJC_METACLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_METACLASS_RO_$_A" }, section "__DATA, __objc_data", align 8 @"OBJC_CLASS_$_NSObject" = external global %struct._class_t @OBJC_METH_VAR_NAME_ = private global [9 x i8] c"function00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_ = private global [8 x i8] c"v16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_1 = private global [4 x i8] c"str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_2 = private global [8 x i8] c"@16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_3 = private global [8 x i8] c"setStr:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_4 = private global [11 x i8] c"v24@0:8@1600", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_5 = private global [8 x i8] c"integer00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_6 = private global [8 x i8] c"q16@0:800", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_7 = private global [12 x i8] c"setInteger:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_8 = private global [11 x i8] c"v24@0:8q1600", section "__TEXT,__objc_methtype,cstring_literals", align 1 @"01l_OBJC_$_INSTANCE_METHODS_A" = private global { i32, i32, [5 x %struct._objc_method] } { i32 24, i32 5, [5 x %struct._objc_method] [%struct._objc_method { i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast (void (%0*, i8*)* @"01-[A function]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([4 x i8]* @OBJC_METH_VAR_NAME_1, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_2, i32 0, i32 0), i8* bitcast (%1* (%0*, i8*)* @"01-[A str]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_3, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_4, i32 0, i32 0), i8* bitcast (void (%0*, i8*, %1*)* @"01-[A setStr:]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_NAME_5, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @OBJC_METH_VAR_TYPE_6, i32 0, i32 0), i8* bitcast (i64 (%0*, i8*)* @"01-[A integer]" to i8*) }, %struct._objc_method { i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_NAME_7, i32 0, i32 0), i8* getelementptr inbounds ([11 x i8]* @OBJC_METH_VAR_TYPE_8, i32 0, i32 0), i8* bitcast (void (%0*, i8*, i64)* @"01-[A setInteger:]" to i8*) }] }, section "__DATA, __objc_const", align 8 @OBJC_METH_VAR_NAME_9 = private global [5 x i8] c"_str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_10 = private global [12 x i8] c"@22NSString2200", section "__TEXT,__objc_methtype,cstring_literals", align 1 @OBJC_METH_VAR_NAME_11 = private global [9 x i8] c"_integer00", section "__TEXT,__objc_methname,cstring_literals", align 1 @OBJC_METH_VAR_TYPE_12 = private global [2 x i8] c"q00", section "__TEXT,__objc_methtype,cstring_literals", align 1 @"01l_OBJC_$_INSTANCE_VARIABLES_A" = private global { i32, i32, [2 x %struct._ivar_t] } { i32 32, i32 2, [2 x %struct._ivar_t] [%struct._ivar_t { i64* @"OBJC_IVAR_$_A._str", i8* getelementptr inbounds ([5 x i8]* @OBJC_METH_VAR_NAME_9, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8]* @OBJC_METH_VAR_TYPE_10, i32 0, i32 0), i32 3, i32 8 }, %struct._ivar_t { i64* @"OBJC_IVAR_$_A._integer", i8* getelementptr inbounds ([9 x i8]* @OBJC_METH_VAR_NAME_11, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8]* @OBJC_METH_VAR_TYPE_12, i32 0, i32 0), i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8 @OBJC_PROP_NAME_ATTR_ = private global [4 x i8] c"str00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_13 = private global [21 x i8] c"T@22NSString22,N,V_str00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_14 = private global [8 x i8] c"integer00", section "__TEXT,__cstring,cstring_literals", align 1 @OBJC_PROP_NAME_ATTR_15 = private global [15 x i8] c"Tq,N,V_integer00", section "__TEXT,__cstring,cstring_literals", align 1 @"01l_OBJC_$_PROP_LIST_A" = private global { i32, i32, [2 x %struct._prop_t] } { i32 16, i32 2, [2 x %struct._prop_t] [%struct._prop_t { i8* getelementptr inbounds ([4 x i8]* @OBJC_PROP_NAME_ATTR_, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8]* @OBJC_PROP_NAME_ATTR_13, i32 0, i32 0) }, %struct._prop_t { i8* getelementptr inbounds ([8 x i8]* @OBJC_PROP_NAME_ATTR_14, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8]* @OBJC_PROP_NAME_ATTR_15, i32 0, i32 0) }] }, section "__DATA, __objc_const", align 8 @"01l_OBJC_CLASS_RO_$_A" = private global %struct._class_ro_t { i32 0, i32 8, i32 24, i8* null, i8* getelementptr inbounds ([2 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* bitcast ({ i32, i32, [5 x %struct._objc_method] }* @"01l_OBJC_$_INSTANCE_METHODS_A" to %struct.__method_list_t*), %struct._objc_protocol_list* null, %struct._ivar_list_t* bitcast ({ i32, i32, [2 x %struct._ivar_t] }* @"01l_OBJC_$_INSTANCE_VARIABLES_A" to %struct._ivar_list_t*), i8* null, %struct._prop_list_t* bitcast ({ i32, i32, [2 x %struct._prop_t] }* @"01l_OBJC_$_PROP_LIST_A" to %struct._prop_list_t*) }, section "__DATA, __objc_const", align 8 @"OBJC_CLASS_$_A" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_A", %struct._class_t* @"OBJC_CLASS_$_NSObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"01l_OBJC_CLASS_RO_$_A" }, section "__DATA, __objc_data", align 8 @"OBJC_LABEL_CLASS_$" = private global [1 x i8*] [i8* bitcast (%struct._class_t* @"OBJC_CLASS_$_A" to i8*)], section "__DATA, __objc_classlist, regular, no_dead_strip", align 8 Selectorの宣言
  • 16. Swiftは何故速い? 16 %a = alloca %0*, align 8 %1 = load %struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_" %2 = load i8** @OBJC_SELECTOR_REFERENCES_, !invariant.load !6 %3 = bitcast %struct._class_t* %1 to i8* %4 = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %3, i8* %2) %5 = bitcast i8* %4 to %0* store %0* %5, %0** %a, align 8 %6 = load %0** %a, align 8 %7 = load i8** @OBJC_SELECTOR_REFERENCES_17, !invariant.load !6 %8 = bitcast %0* %6 to i8* call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* %8, i8* %7) ret i32 0
  • 17. Swiftは何故速い? 17 call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* %8, i8* %7)
  • 18. Swiftは何故速い? 18 class A { var str: String? var int: Int? func function() { } }
  • 20. Swiftは何故速い? 20 @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @5, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq*, %C6source1A*)*, void (%Sq*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBo, i64 ptrtoint (%objc_class* @_TMmC6source1A to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, i8* }* @_DATA__TtC6source1A to i64), i64 1), i32 3, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }
  • 21. Swiftは何故速い? 21 @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @5, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq*, %C6source1A*)*, void (%Sq*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBo, i64 ptrtoint (%objc_class* @_TMmC6source1A to i64), %objc_class* @"OBJC_CLASS_$_SwiftObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, i8* }* @_DATA__TtC6source1A to i64), i64 1), i32 3, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 } vtable
  • 22. Swiftは何故速い? 22 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = bitcast %C6source1A* %7 to %swift.refcounted* call void @swift_retain_noresult(%swift.refcounted* %8) #3 %9 = bitcast %C6source1A* %7 to %swift.type** %.metadata = load %swift.type** %9, align 8 %10 = bitcast %swift.type* %.metadata to void (%C6source1A*)** %11 = getelementptr inbounds void (%C6source1A*)** %10, i64 9 %.metadata1 = load void (%C6source1A*)** %11, align 8, !invariant.load !29 %12 = bitcast void (%C6source1A*)* %.metadata1 to i8* %13 = bitcast i8* %12 to void (%C6source1A*)* call void %13(%C6source1A* %7) call void bitcast (void (%swift.refcounted*)* @swift_release to void (%C6source1A*)*)(%C6source1A* %7) #3 ret i32 0
  • 23. Swiftは何故速い? 23 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @ %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = bitcast %C6source1A* %7 to %swift.refcounted* call void @swift_retain_noresult(%swift.refcounted* %8) #3 %9 = bitcast %C6source1A* %7 to %swift.type** %.metadata = load %swift.type** %9, align 8 %10 = bitcast %swift.type* %.metadata to void (%C6source1A*)** %11 = getelementptr inbounds void (%C6source1A*)** %10, i64 9 %.metadata1 = load void (%C6source1A*)** %11, align 8, %12 = bitcast void (%C6source1A*)* %.metadata1 to i8* %13 = bitcast i8* %12 to void (%C6source1A*)* call void %13(%C6source1A* %7)
  • 24. Swiftは何故速い? 24 %11 = getelementptr inbounds void (%C6source1A*)** %10, i64 9
  • 25. Swiftは何故速い? 25 class A: NSObject { var str: String? var int: Int? func function() { } }
  • 26. Swiftは何故速い? 26 @8 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00" @_METACLASS_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8 @_INSTANCE_METHODS__TtC6source1A = private constant { i32, i32, [5 x { i8*, i8*, i8* }] } { i32 24, i32 5, [5 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @"01L_selector_data(str)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%0* (%1*, i8*)* @_TToFC6source1Ag3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(setStr:)", i64 0, i64 0), i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i8* bitcast (void (%1*, i8*, %0*)* @_TToFC6source1As3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([9 x i8]* @"01L_selector_data(function)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @6, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1A8functionfS0_FT_T_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%1* (%1*, i8*)* @_TToFC6source1AcfMS0_FT_S0_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8]* @"01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8* getelementptr inbounds ([3 x i8]* @7, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1AE to i8*) }] }, section "__DATA, __objc_const", align 8 @_IVARS__TtC6source1A = private constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3strGSqSS_, i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 25 }, { i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3intGSqSi_, i8* getelementptr inbounds ([4 x i8]* @5, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 9 }] }, section "__DATA, __objc_const", align 8 @_PROPERTIES__TtC6source1A = private constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8]* @2, i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8 @_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 16, i32 57, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), { i32, i32, [5 x { i8*, i8*, i8* }] }* @_INSTANCE_METHODS__TtC6source1A, i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS__TtC6source1A, i8* null, { i32, i32, [1 x { i8*, i8* }] }* @_PROPERTIES__TtC6source1A }, section "__DATA, __objc_const", align 8 @9 = private unnamed_addr constant [11 x i8] c"C6source1A00" @10 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @9, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @10, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq.16*, %C6source1A*)*, void (%Sq.16*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBO, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC6source1A" to i64), %objc_class* @"OBJC_CLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC6source1A to i64), i64 1), i32 1, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq.16*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq.16*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }, section "__DATA,__objc_data, regular, no_dead_strip"
  • 27. Swiftは何故速い? 27 @8 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00" @_METACLASS_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8 @_INSTANCE_METHODS__TtC6source1A = private constant { i32, i32, [5 x { i8*, i8*, i8* }] } { i32 24, i32 5, [5 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @"01L_selector_data(str)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%0* (%1*, i8*)* @_TToFC6source1Ag3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(setStr:)", i64 0, i64 0), i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i8* bitcast (void (%1*, i8*, %0*)* @_TToFC6source1As3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([9 x i8]* @"01L_selector_data(function)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @6, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1A8functionfS0_FT_T_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%1* (%1*, i8*)* @_TToFC6source1AcfMS0_FT_S0_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8]* @"01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8* getelementptr inbounds ([3 x i8]* @7, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1AE to i8*) }] }, section "__DATA, __objc_const", align 8 @_IVARS__TtC6source1A = private constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3strGSqSS_, i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 25 }, { i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3intGSqSi_, i8* getelementptr inbounds ([4 x i8]* @5, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 9 }] }, section "__DATA, __objc_const", align 8 @_PROPERTIES__TtC6source1A = private constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8]* @2, i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8 @_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 16, i32 57, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @8, i64 0, i64 0), { i32, i32, [5 x { i8*, i8*, i8* }] }* @_INSTANCE_METHODS__TtC6source1A, i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS__TtC6source1A, i8* null, { i32, i32, [1 x { i8*, i8* }] }* @_PROPERTIES__TtC6source1A }, section "__DATA, __objc_const", align 8 @9 = private unnamed_addr constant [11 x i8] c"C6source1A00" @10 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @9, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @10, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1A8functionfS0_FT_T_ = constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq.16*, %C6source1A*)*, void (%Sq.16*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBO, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC6source1A" to i64), %objc_class* @"OBJC_CLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC6source1A to i64), i64 1), i32 1, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq.16*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq.16*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1A8functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }, section "__DATA,__objc_data, regular, no_dead_strip" Selectorの宣言 vtable
  • 28. Swiftは何故速い? 28 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #3 %9 = bitcast %C6source1A* %7 to i64* %10 = load i64* %9, align 8 %11 = load i64* @swift_isaMask, align 8 %12 = and i64 %10, %11 %13 = inttoptr i64 %12 to %swift.type* %14 = bitcast %swift.type* %13 to void (%C6source1A*)** %15 = getelementptr inbounds void (%C6source1A*)** %14, i64 15 %16 = load void (%C6source1A*)** %15, align 8, !invariant.load !29 %17 = bitcast void (%C6source1A*)* %16 to i8* %18 = bitcast i8* %17 to void (%C6source1A*)* call void %18(%C6source1A* %7) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %7) #3 ret i32 0
  • 29. Swiftは何故速い? 29 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #3 %9 = bitcast %C6source1A* %7 to i64* %10 = load i64* %9, align 8 %11 = load i64* @swift_isaMask, align 8 %12 = and i64 %10, %11 %13 = inttoptr i64 %12 to %swift.type* %14 = bitcast %swift.type* %13 to void (%C6source1A*)** %15 = getelementptr inbounds void (%C6source1A*)** %14, i64 15 %16 = load void (%C6source1A*)** %15, align 8, !invariant.load !29 %17 = bitcast void (%C6source1A*)* %16 to i8* %18 = bitcast i8* %17 to void (%C6source1A*)* call void %18(%C6source1A* %7) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %7) #3 ret i32 0 objc_msgSendではない
  • 33. struct/enum 33 struct A { var str: String? var int: Int? func function() { } }
  • 34. 34 swiftc -emit-ir source.swift > source.ll struct/enum
  • 35. struct/enum 35 @_Tv6source1aVS_1A = global %V6source1A zeroinitializer, align 8 @_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5Int32, align 4 @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6 = external global i64, align 8 @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__ = external global %VSs20UnsafeMutablePointer, align 8 @_TWVV6source1A = constant [20 x i8*] [i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwXXV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_TwCPV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwprV6source1A to i8*), i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwdeV6source1A to i8*), i8* bitcast (void (%swift.opaque*, %swift.type*)* @_TwxxV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwCpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcaV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwTkV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy41_8 to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwtaV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwalV6source1A to i8*), i8* bitcast (i8* (i8**, i8**, %swift.type*)* @__swift_copy_outline_pointer to i8*), i8* bitcast (void (%swift.opaque*, i64, %swift.type*)* @_TwXxV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, i64, %swift.type*)* @_TwCcV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* inttoptr (i64 41 to i8*), i8* inttoptr (i64 196615 to i8*), i8* inttoptr (i64 48 to i8*)] @0 = private unnamed_addr constant [11 x i8] c"V6source1A00" @1 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnV6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 1, i8* getelementptr inbounds ([11 x i8]* @0, i64 0, i64 0), i32 2, i32 3, i8* getelementptr inbounds ([9 x i8]* @1, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TMdV6source1A = constant { i8**, i64, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, %swift.type*, i64, i64 } { i8** getelementptr inbounds ([20 x i8*]* @_TWVV6source1A, i32 0, i32 0), i64 1, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnV6source1A, %swift.type* null, i64 0, i64 32 }
  • 36. struct/enum 36 @_Tv6source1aVS_1A = global %V6source1A zeroinitializer, align 8 @_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5Int32, align 4 @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6 = external global i64, align 8 @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__ = external global %VSs20UnsafeMutablePointer, align 8 @_TWVV6source1A = constant [20 x i8*] [i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwXXV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_TwCPV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwprV6source1A to i8*), i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwdeV6source1A to i8*), i8* bitcast (void (%swift.opaque*, %swift.type*)* @_TwxxV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwCpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcpV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcaV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwTkV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy41_8 to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwtaV6source1A to i8*), i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.type*)* @_TwalV6source1A to i8*), i8* bitcast (i8* (i8**, i8**, %swift.type*)* @__swift_copy_outline_pointer to i8*), i8* bitcast (void (%swift.opaque*, i64, %swift.type*)* @_TwXxV6source1A to i8*), i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, i64, %swift.type*)* @_TwCcV6source1A to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array48_8 to i8*), i8* inttoptr (i64 41 to i8*), i8* inttoptr (i64 196615 to i8*), i8* inttoptr (i64 48 to i8*)] @0 = private unnamed_addr constant [11 x i8] c"V6source1A00" @1 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnV6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 1, i8* getelementptr inbounds ([11 x i8]* @0, i64 0, i64 0), i32 2, i32 3, i8* getelementptr inbounds ([9 x i8]* @1, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TMdV6source1A = constant { i8**, i64, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, %swift.type*, i64, i64 } { i8** getelementptr inbounds ([20 x i8*]* @_TWVV6source1A, i32 0, i32 0), i64 1, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnV6source1A, %swift.type* null, i64 0, i64 32 } functionの記述が存在しない
  • 37. struct/enum 37 define hidden void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41)) #0 { entry: %.str = getelementptr inbounds %V6source1A* %0, i32 0, i32 0 %1 = bitcast %Sq* %.str to { i64, i64, i64 }* %2 = getelementptr inbounds { i64, i64, i64 }* %1, i32 0, i32 0 %3 = load i64* %2, align 8 %4 = getelementptr inbounds { i64, i64, i64 }* %1, i32 0, i32 1 %5 = load i64* %4, align 8 %6 = getelementptr inbounds { i64, i64, i64 }* %1, i32 0, i32 2 %7 = load i64* %6, align 8 %8 = getelementptr inbounds %Sq* %.str, i32 0, i32 1 %9 = bitcast [1 x i8]* %8 to i1* %10 = load i1* %9, align 8 %.int = getelementptr inbounds %V6source1A* %0, i32 0, i32 2 %11 = bitcast %Sq.17* %.int to i64* %12 = load i64* %11, align 8 %13 = getelementptr inbounds %Sq.17* %.int, i32 0, i32 1 %14 = bitcast [1 x i8]* %13 to i1* %15 = load i1* %14, align 8 ret void }
  • 38. struct/enum 38 %.str = getelementptr inbounds %V6source1A* %2, i32 0, i32 0 %31 = bitcast %Sq* %.str to { i64, i64, i64 }* %32 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 0 store i64 %21, i64* %32, align 8 %33 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 1 store i64 %22, i64* %33, align 8 %34 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 2 store i64 %23, i64* %34, align 8 %35 = getelementptr inbounds %Sq* %.str, i32 0, i32 1 %36 = bitcast [1 x i8]* %35 to i1* store i1 %24, i1* %36, align 8 %.int = getelementptr inbounds %V6source1A* %2, i32 0, i32 2 %37 = bitcast %Sq.17* %.int to i64* store i64 %25, i64* %37, align 8 %38 = getelementptr inbounds %Sq.17* %.int, i32 0, i32 1 %39 = bitcast [1 x i8]* %38 to i1* store i1 %26, i1* %39, align 8 call void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41) %2) br i1 %24, label %43, label %40
  • 39. struct/enum 39 %.str = getelementptr inbounds %V6source1A* %2, i32 0, i32 0 %31 = bitcast %Sq* %.str to { i64, i64, i64 }* %32 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 0 store i64 %21, i64* %32, align 8 %33 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 1 store i64 %22, i64* %33, align 8 %34 = getelementptr inbounds { i64, i64, i64 }* %31, i32 0, i32 2 store i64 %23, i64* %34, align 8 %35 = getelementptr inbounds %Sq* %.str, i32 0, i32 1 %36 = bitcast [1 x i8]* %35 to i1* store i1 %24, i1* %36, align 8 %.int = getelementptr inbounds %V6source1A* %2, i32 0, i32 2 %37 = bitcast %Sq.17* %.int to i64* store i64 %25, i64* %37, align 8 %38 = getelementptr inbounds %Sq.17* %.int, i32 0, i32 1 %39 = bitcast [1 x i8]* %38 to i1* store i1 %26, i1* %39, align 8 call void @_TFV6source1A8functionfS0_FT_T_(%V6source1A* noalias nocapture dereferenceable(41) %2) br i1 %24, label %43, label %40 関数を直接実行している
  • 44. アクセス修飾子 44 class A: NSObject { var str: String? var int: Int? private func function() { print(self) } }
  • 45. アクセス修飾子 45 @_Tv6source1aCS_1A = global %C6source1A* null, align 8 @_TZvOSs7Process5_argcVSs5Int32 = external global %VSs5Int32, align 4 @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token6 = external global i64, align 8 @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__ = external global %VSs20UnsafeMutablePointer, align 8 @_swiftEmptyArrayStorage = external global %VSC23_SwiftEmptyArrayStorage, align 8 @_TWvdvC6source1A3strGSqSS_ = global i64 16, align 8 @"01L_selector_data(dealloc)" = internal constant [8 x i8] c"dealloc00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(dealloc)" = internal global i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(dealloc)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @_TWvdvC6source1A3intGSqSi_ = global i64 48, align 8 @"01L_selector_data(init)" = internal constant [5 x i8] c"init00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(init)" = internal global i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @"01L_selector_data(allocWithZone:)" = internal constant [15 x i8] c"allocWithZone:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(allocWithZone:)" = internal global i8* getelementptr inbounds ([15 x i8]* @"01L_selector_data(allocWithZone:)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @_TWVBO = external global i8* @"OBJC_METACLASS_$__TtC6source1A" = global %objc_class { %objc_class* @"OBJC_METACLASS_$_NSObject", %objc_class* @"OBJC_METACLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_METACLASS_DATA__TtC6source1A to i64) } @"OBJC_CLASS_$_NSObject" = external global %objc_class @_objc_empty_cache = external global %swift.opaque @_objc_empty_vtable = external global %swift.opaque @0 = private unnamed_addr constant [4 x i8] c"str00" @1 = private unnamed_addr constant [1 x i8] zeroinitializer @2 = private unnamed_addr constant [22 x i8] c"T@22NSString22,N,C,Vstr00" @"01L_selector_data(str)" = internal constant [4 x i8] c"str00", section "__TEXT,__objc_methname,cstring_literals", align 1 @3 = private unnamed_addr constant [8 x i8] c"@16@0:800" @"01L_selector_data(setStr:)" = internal constant [8 x i8] c"setStr:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @4 = private unnamed_addr constant [11 x i8] c"v24@0:8@1600" @5 = private unnamed_addr constant [4 x i8] c"int00" @"01L_selector_data(.cxx_destruct)" = internal constant [14 x i8] c".cxx_destruct00", section "__TEXT,__objc_methname,cstring_literals", align 1 @6 = private unnamed_addr constant [3 x i8] c"@?00" @"OBJC_METACLASS_$_NSObject" = external global %objc_class @7 = private unnamed_addr constant [14 x i8] c"_TtC6source1A00" @_METACLASS_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @7, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8 @_INSTANCE_METHODS__TtC6source1A = private constant { i32, i32, [4 x { i8*, i8*, i8* }] } { i32 24, i32 4, [4 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @"01L_selector_data(str)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%0* (%1*, i8*)* @_TToFC6source1Ag3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(setStr:)", i64 0, i64 0), i8* getelementptr inbounds ([11 x i8]* @4, i64 0, i64 0), i8* bitcast (void (%1*, i8*, %0*)* @_TToFC6source1As3strGSqSS_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8]* @3, i64 0, i64 0), i8* bitcast (%1* (%1*, i8*)* @_TToFC6source1AcfMS0_FT_S0_ to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8]* @"01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8* getelementptr inbounds ([3 x i8]* @6, i64 0, i64 0), i8* bitcast (void (%1*, i8*)* @_TToFC6source1AE to i8*) }] }, section "__DATA, __objc_const", align 8 @_IVARS__TtC6source1A = private constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3strGSqSS_, i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 25 }, { i64*, i8*, i8*, i32, i32 } { i64* @_TWvdvC6source1A3intGSqSi_, i8* getelementptr inbounds ([4 x i8]* @5, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8]* @1, i64 0, i64 0), i32 3, i32 9 }] }, section "__DATA, __objc_const", align 8 @_PROPERTIES__TtC6source1A = private constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([4 x i8]* @0, i64 0, i64 0), i8* getelementptr inbounds ([22 x i8]* @2, i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8 @_DATA__TtC6source1A = private constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [4 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 16, i32 57, i32 0, i8* null, i8* getelementptr inbounds ([14 x i8]* @7, i64 0, i64 0), { i32, i32, [4 x { i8*, i8*, i8* }] }* @_INSTANCE_METHODS__TtC6source1A, i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS__TtC6source1A, i8* null, { i32, i32, [1 x { i8*, i8* }] }* @_PROPERTIES__TtC6source1A }, section "__DATA, __objc_const", align 8 @8 = private unnamed_addr constant [11 x i8] c"C6source1A00" @9 = private unnamed_addr constant [9 x i8] c"str00int0000" @_TMnC6source1A = constant { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 } { i64 0, i8* getelementptr inbounds ([11 x i8]* @8, i64 0, i64 0), i32 2, i32 17, i8* getelementptr inbounds ([9 x i8]* @9, i64 0, i64 0), %swift.type** (%swift.type*)* @get_field_types_A, %swift.type_pattern* null, i32 0, i32 0, i32 0 } @_TWoFC6source1Ag3strGSqSS_ = constant i64 88, align 8 @_TWoFC6source1As3strGSqSS_ = constant i64 96, align 8 @_TWoFC6source1Am3strGSqSS_ = constant i64 104, align 8 @_TWoFC6source1Ag3intGSqSi_ = constant i64 112, align 8 @_TWoFC6source1As3intGSqSi_ = constant i64 120, align 8 @_TWoFC6source1Am3intGSqSi_ = constant i64 128, align 8 @_TWoFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_ = hidden constant i64 136, align 8 @_TWoFC6source1ACfMS0_FT_S0_ = constant i64 144, align 8 @_TMLC6source1A = global %swift.type* null, align 8 @_TMdC6source1A = global { void (%C6source1A*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }*, void (%Sq.16*, %C6source1A*)*, void (%Sq.16*, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, { i64, i1 } (%C6source1A*)*, void (i64, i1, %C6source1A*)*, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)*, void (%C6source1A*)*, %C6source1A* (%C6source1A*)*, i64, i64 } { void (%C6source1A*)* @_TFC6source1AD, i8** @_TWVBO, i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$__TtC6source1A" to i64), %objc_class* @"OBJC_CLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [4 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* }* @_DATA__TtC6source1A to i64), i64 1), i32 1, i32 0, i32 57, i16 7, i16 0, i32 168, i32 16, { i64, i8*, i32, i32, i8*, %swift.type** (%swift.type*)*, %swift.type_pattern*, i32, i32, i32 }* @_TMnC6source1A, void (%Sq.16*, %C6source1A*)* @_TFC6source1Ag3strGSqSS_, void (%Sq.16*, %C6source1A*)* @_TFC6source1As3strGSqSS_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3strGSqSS_, { i64, i1 } (%C6source1A*)* @_TFC6source1Ag3intGSqSi_, void (i64, i1, %C6source1A*)* @_TFC6source1As3intGSqSi_, { i8*, i64 } (i8*, [24 x i8]*, %C6source1A*)* @_TFC6source1Am3intGSqSi_, void (%C6source1A*)* @_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_, %C6source1A* (%C6source1A*)* @_TFC6source1AcfMS0_FT_S0_, i64 16, i64 48 }, section "__DATA,__objc_data, regular, no_dead_strip" functionのSelectorが存在しない
  • 46. アクセス修飾子 46 @"01L_selector_data(dealloc)" = internal constant [8 x i8] c"dealloc00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(dealloc)" = internal global i8* getelementptr inbounds ([8 x i8]* @"01L_selector_data(dealloc)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @_TWvdvC6source1A3intGSqSi_ = global i64 48, align 8 @"01L_selector_data(init)" = internal constant [5 x i8] c"init00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(init)" = internal global i8* getelementptr inbounds ([5 x i8]* @"01L_selector_data(init)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @"01L_selector_data(allocWithZone:)" = internal constant [15 x i8] c"allocWithZone:00", section "__TEXT,__objc_methname,cstring_literals", align 1 @"01L_selector(allocWithZone:)" = internal global i8* getelementptr inbounds ([15 x i8]* @"01L_selector_data(allocWithZone:)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8 @_TWVBO = external global i8* @"OBJC_METACLASS_$__TtC6source1A" = global %objc_class { %objc_class* @"OBJC_METACLASS_ $_NSObject", %objc_class* @"OBJC_METACLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* @_objc_empty_vtable, i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_METACLASS_DATA__TtC6source1A to i64) } @"OBJC_CLASS_$_NSObject" = external global %objc_class
  • 47. アクセス修飾子 47 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #3 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #4 call void @_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_(%C6source1A* %7) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*) (%C6source1A* %7) #4 ret i32 0 関数を直接実行している
  • 48. アクセス修飾子 48 class B: A { override private func function() { } }
  • 49. アクセス修飾子 49 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #2 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #3 %9 = bitcast %C6source1A* %7 to i64* %10 = load i64* %9, align 8 %11 = load i64* @swift_isaMask, align 8 %12 = and i64 %10, %11 %13 = inttoptr i64 %12 to %swift.type* %14 = bitcast %swift.type* %13 to void (%C6source1A*)** %15 = getelementptr inbounds void (%C6source1A*)** %14, i64 15 %16 = load void (%C6source1A*)** %15, align 8, !invariant.load !29 %17 = bitcast void (%C6source1A*)* %16 to i8* %18 = bitcast i8* %17 to void (%C6source1A*)* call void %18(%C6source1A* %7) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %7) #3 %19 = call %swift.type* @_TMaC6source1B() #2 %20 = call %C6source1B* @_TFC6source1BCfMS0_FT_S0_(%swift.type* %19) store %C6source1B* %20, %C6source1B** @_Tv6source1bCS_1B, align 8 %21 = load %C6source1B** @_Tv6source1bCS_1B, align 8 %22 = call %C6source1B* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1B* (%C6source1B*)*)(%C6source1B* %21) #3 call void @_TFC6source1BP33_EDAF7582627E67611B2602683AEC23D58functionfS0_FT_T_(%C6source1B* %21) call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1B*)*)(%C6source1B* %21) #3 ret i32 0 直接実行 vtable
  • 55. Any 例えばString?型の値をAny型に格納した場合、 a as? Optional<Any>では取り出せない。
 a as? Optional<String>で取り出す必要があ る。 Any型の引数には、渡した変数が型ごと含ま れているため。暗黙のキャストは走っていな い。 55
  • 56. Any 56 define hidden void @_TF6source8functionFP_T_(%"protocol<>"* noalias nocapture dereferenceable(32)) #0 { entry: %1 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 1 %.metadata = load %swift.type** %1, align 8 %2 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 0 %3 = bitcast %swift.type* %.metadata to i8*** %4 = getelementptr inbounds i8*** %3, i64 -1 %.metadata.valueWitnesses = load i8*** %4, align 8, !invariant.load ! 29, !dereferenceable !30 %5 = load i8** %.metadata.valueWitnesses, align 8, !invariant.load !29 %destroyBuffer = bitcast i8* %5 to void ([24 x i8]*, %swift.type*)* call void %destroyBuffer([24 x i8]* %2, %swift.type* %.metadata) #1 ret void }
  • 57. Any 57 define hidden void @_TF6source8functionFP_T_(%"protocol<>"* noalias nocapture dereferenceable(32)) #0 { entry: %1 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 1 %.metadata = load %swift.type** %1, align 8 %2 = getelementptr inbounds %"protocol<>"* %0, i32 0, i32 0 %3 = bitcast %swift.type* %.metadata to i8*** %4 = getelementptr inbounds i8*** %3, i64 -1 %.metadata.valueWitnesses = load i8*** %4, align 8, !invariant.load ! 29, !dereferenceable !30 %5 = load i8** %.metadata.valueWitnesses, align 8, !invariant.load !29 %destroyBuffer = bitcast i8* %5 to void ([24 x i8]*, %swift.type*)* call void %destroyBuffer([24 x i8]* %2, %swift.type* %.metadata) #1 ret void } Any型
  • 59. Generics 59 define hidden void @_TF6source8functionuRq_S_1P_Fq_T_(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.P) #0 { entry: %A1 = alloca %swift.type*, align 8 store %swift.type* %A, %swift.type** %A1, align 8 %1 = bitcast %swift.type* %A to i8*** %2 = getelementptr inbounds i8*** %1, i64 -1 %A.valueWitnesses = load i8*** %2, align 8, !invariant.load !29, ! dereferenceable !30 %3 = getelementptr inbounds i8** %A.valueWitnesses, i32 4 %4 = load i8** %3, align 8, !invariant.load !29 %destroy = bitcast i8* %4 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* %0, %swift.type* %A) #1 ret void }
  • 60. Generics 60 define hidden void @_TF6source8functionuRq_S_1P_Fq_T_(%swift.opaque* noalias nocapture, %swift.type* %A, i8** %A.P) #0 { entry: %A1 = alloca %swift.type*, align 8 store %swift.type* %A, %swift.type** %A1, align 8 %1 = bitcast %swift.type* %A to i8*** %2 = getelementptr inbounds i8*** %1, i64 -1 %A.valueWitnesses = load i8*** %2, align 8, !invariant.load !29, ! dereferenceable !30 %3 = getelementptr inbounds i8** %A.valueWitnesses, i32 4 %4 = load i8** %3, align 8, !invariant.load !29 %destroy = bitcast i8* %4 to void (%swift.opaque*, %swift.type*)* call void %destroy(%swift.opaque* %0, %swift.type* %A) #1 ret void } 型引数 
  • 63. Protocol Extension 63 protocol P { } extension P { func function() { } } class A: NSObject, P { var str: String? var int: Int? }
  • 64. Protocol Extension 64 store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %6 = call %swift.type* @_TMaC6source1A() #2 %7 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %6) store %C6source1A* %7, %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %9 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %8) #3 store %C6source1A* %8, %C6source1A** %2, align 8 %10 = bitcast %C6source1A** %2 to %swift.opaque* call void @_TFeRq_6source1P_S_S0_8functionuRq_S0__fq_FT_T_(%swift.type* %6, i8** getelementptr inbounds ([0 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), %swift.opaque* noalias nocapture %10) %11 = load %C6source1A** %2, align 8 call void bitcast (void (%objc_object*)* @objc_release to void (%C6source1A*)*)(%C6source1A* %11) #3 ret i32 0
  • 65. Protocol Extension 65 call void @_TFeRq_6source1P_S_S0_8functionuRq_S0__fq_FT_T_(%swift.t ype* %6, i8** getelementptr inbounds ([0 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), %swift.opaque* noalias nocapture %10)
  • 67. Protocol Extension 67 store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %6 = call %swift.type* @_TMaC6source1A() #2 store %swift.type* %6, %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8 store i8** getelementptr inbounds ([1 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8 %7 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %6) store %C6source1A* %7, %C6source1A** bitcast (%P6source1P_* @_Tv6source1aPS_1P_ to %C6source1A**), align 8 %_Tv6source1aPS_1P_.metadata = load %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8 %8 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1 store %swift.type* %_Tv6source1aPS_1P_.metadata, %swift.type** %8, align 8 %9 = load i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8 %10 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2 store i8** %9, i8*** %10, align 8 %11 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0 %12 = bitcast %swift.type* %_Tv6source1aPS_1P_.metadata to i8*** %13 = getelementptr inbounds i8*** %12, i64 -1 %_Tv6source1aPS_1P_.metadata.valueWitnesses = load i8*** %13, align 8, !invariant.load !29, !dereferenceable !30 %14 = getelementptr inbounds i8** %_Tv6source1aPS_1P_.metadata.valueWitnesses, i32 1 %15 = load i8** %14, align 8, !invariant.load !29 %initializeBufferWithCopyOfBuffer = bitcast i8* %15 to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* %16 = call %swift.opaque* %initializeBufferWithCopyOfBuffer([24 x i8]* noalias %11, [24 x i8]* getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 0), %swift.type* %_Tv6source1aPS_1P_.metadata) #3 %17 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1 %.metadata = load %swift.type** %17, align 8 %18 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0 %19 = bitcast %swift.type* %.metadata to i8*** %20 = getelementptr inbounds i8*** %19, i64 -1 %.metadata.valueWitnesses = load i8*** %20, align 8, !invariant.load !29, !dereferenceable !30 %21 = getelementptr inbounds i8** %.metadata.valueWitnesses, i32 2 %22 = load i8** %21, align 8, !invariant.load !29 %projectBuffer = bitcast i8* %22 to %swift.opaque* ([24 x i8]*, %swift.type*)* %23 = call %swift.opaque* %projectBuffer([24 x i8]* %18, %swift.type* %.metadata) #3 %24 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2 %witness-table = load i8*** %24, align 8 store %swift.type* %.metadata, %swift.type** %.metadata1, align 8 %25 = load i8** %witness-table, align 8, !invariant.load !29 %26 = bitcast i8* %25 to void (%swift.opaque*, %swift.type*)* call void %26(%swift.opaque* noalias nocapture %23, %swift.type* %.metadata)
  • 68. Protocol Extension 68 store i8* %3, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %6 = call %swift.type* @_TMaC6source1A() #2 store %swift.type* %6, %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8 store i8** getelementptr inbounds ([1 x i8*]* @_TWPC6source1AS_1PS_, i32 0, i32 0), i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8 %7 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %6) store %C6source1A* %7, %C6source1A** bitcast (%P6source1P_* @_Tv6source1aPS_1P_ to %C6source1A**), align 8 %_Tv6source1aPS_1P_.metadata = load %swift.type** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 1), align 8 %8 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1 store %swift.type* %_Tv6source1aPS_1P_.metadata, %swift.type** %8, align 8 %9 = load i8*** getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 2), align 8 %10 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2 store i8** %9, i8*** %10, align 8 %11 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0 %12 = bitcast %swift.type* %_Tv6source1aPS_1P_.metadata to i8*** %13 = getelementptr inbounds i8*** %12, i64 -1 %_Tv6source1aPS_1P_.metadata.valueWitnesses = load i8*** %13, align 8, !invariant.load !29, !dereferenceable !30 %14 = getelementptr inbounds i8** %_Tv6source1aPS_1P_.metadata.valueWitnesses, i32 1 %15 = load i8** %14, align 8, !invariant.load !29 %initializeBufferWithCopyOfBuffer = bitcast i8* %15 to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* %16 = call %swift.opaque* %initializeBufferWithCopyOfBuffer([24 x i8]* noalias %11, [24 x i8]* getelementptr inbounds (%P6source1P_* @_Tv6source1aPS_1P_, i32 0, i32 0), %swift.type* %_Tv6source1aPS_1P_.metadata) #3 %17 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 1 %.metadata = load %swift.type** %17, align 8 %18 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 0 %19 = bitcast %swift.type* %.metadata to i8*** %20 = getelementptr inbounds i8*** %19, i64 -1 %.metadata.valueWitnesses = load i8*** %20, align 8, !invariant.load !29, !dereferenceable !30 %21 = getelementptr inbounds i8** %.metadata.valueWitnesses, i32 2 %22 = load i8** %21, align 8, !invariant.load !29 %projectBuffer = bitcast i8* %22 to %swift.opaque* ([24 x i8]*, %swift.type*)* %23 = call %swift.opaque* %projectBuffer([24 x i8]* %18, %swift.type* %.metadata) #3 %24 = getelementptr inbounds %P6source1P_* %2, i32 0, i32 2 %witness-table = load i8*** %24, align 8 store %swift.type* %.metadata, %swift.type** %.metadata1, align 8 %25 = load i8** %witness-table, align 8, !invariant.load !29 %26 = bitcast i8* %25 to void (%swift.opaque*, %swift.type*)* call void %26(%swift.opaque* noalias nocapture %23, %swift.type* %.metadata) witness-tableを利用
  • 70. optional func 70 @objc protocol Delegate: NSObjectProtocol { optional func function() }
  • 71. 71 swiftc -emit-ir source.swift > source.ll struct/enum
  • 75. Closure 75 class A: NSObject { var str: String? var int: Int? private func function() { print(self) } } var a = A() var m = a.function
  • 76. Closure 76 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #3 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #4 %9 = call { i8*, %swift.refcounted* } @_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionFS0_FT_T_(%C6source1A* %7) %10 = extractvalue { i8*, %swift.refcounted* } %9, 0 %11 = extractvalue { i8*, %swift.refcounted* } %9, 1 store i8* %10, i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0), align 8 store %swift.refcounted* %11, %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 1), align 8 %12 = load i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0), align 8 %13 = load %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 1), align 8 call void @swift_retain_noresult(%swift.refcounted* %13) #4 %14 = bitcast i8* %12 to void (%swift.refcounted*)* call void %14(%swift.refcounted* %13) ret i32 0
  • 77. Closure 77 store i8* %2, i8** getelementptr inbounds (%VSs20UnsafeMutablePointer* @_TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__, i32 0, i32 0), align 8 %5 = call %swift.type* @_TMaC6source1A() #3 %6 = call %C6source1A* @_TFC6source1ACfMS0_FT_S0_(%swift.type* %5) store %C6source1A* %6, %C6source1A** @_Tv6source1aCS_1A, align 8 %7 = load %C6source1A** @_Tv6source1aCS_1A, align 8 %8 = call %C6source1A* bitcast (%objc_object* (%objc_object*)* @objc_retain to %C6source1A* (%C6source1A*)*)(%C6source1A* %7) #4 %9 = call { i8*, %swift.refcounted* } @_TFC6source1AP33_EDAF7582627E67611B2602683AEC23D58functionFS0_FT_T_(%C6source1A* %7) %10 = extractvalue { i8*, %swift.refcounted* } %9, 0 %11 = extractvalue { i8*, %swift.refcounted* } %9, 1 store i8* %10, i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0), align 8 store %swift.refcounted* %11, %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 1), align 8 %12 = load i8** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 0), align 8 %13 = load %swift.refcounted** getelementptr inbounds (%swift.function* @_Tv6source1mFT_T_, i32 0, i32 1), align 8 call void @swift_retain_noresult(%swift.refcounted* %13) #4 %14 = bitcast i8* %12 to void (%swift.refcounted*)* call void %14(%swift.refcounted* %13) ret i32 0 Closureを生成してラッピング