Swift internals
Transcript of Swift internals
let swift(16)
InternalsLLVM, Type system, Swift Foundation
OSXDEV.orgj�
Agenda
Swift Compiler Swift Type System Swift Type Internals Swift Foundation Summary
let swift(16)
Swift CompilerLLVM, Clang, Swiftc
A LoNG Time AGo,
in a galaxy far, far away...
LLVMLow-Level Virtual Machine An Infrastructure for Multi-stage Optimization − by Chris Arthur Lattner @2002
Design and Implementation of a compiler infrastructure − support a unique multi-stage optimization system − support inter-procedural and profile-driven optimizations
LLVM virtual instruction (IR) − with high-level type information
Sponsored by APPLE
Chris LattnerThe Father of LLVM
LLVM CompilerGCC#4.2#
프론트엔드#
C"Tree*SSA#최적화기# 코드 생성기#C++"
Objec)ve+C"실행파일"
GCC"4.2"
GCC#4.2#프론트엔드#
C"LLVM#
최적화기#LLVM#
코드 생성기#C++"
Objec)ve+C"실행파일"
LLVM+GCC"4.2"
Clang#프론트엔드#
C"LLVM#
최적화기#LLVM#
코드 생성기#C++"
Objec)ve+C"실행파일"
LLVM"
Swift Compiler
yp�RVHES� � ��
− � 9 RHMF � DL MSH � M RHR �
− � %� � < OD� GD D �
� � p�
− � � d� S MREN L %�-: � %� DMD H �
> � :� � c�
k�ib � p�ib� y AHM �
.swift 기계코드
let swift(16)
Swift Type SystemDuck Type vs. HM Type Inference
Objective-C Type SystemStatic Type + Duck Type System − C-style static type − Smalltalk-style duck type
Duck Type History − a message to comp.lang.python Newsgroup (2000)
Don't check whether it IS-a duck: check whether it QUACKS-like-a duck, WALKS-like-a duck, etc, etc, depending on exactly what subset of duck-like behaviour you need to play your language-games with.
“”
Swift Type System
Bi-directional type inference Constraint-based type checker − Based classical Hindley-Milner type system − Include polymorphic types & function overloading − Step : Generate ➔ Solve ➔ Solution Application
func foo(x: Double) -> Int { … }var doubleValue : Double = 3.141592var unknown = foo(doubleValue)
func bar<T>(x: T) -> T { return x }var floatValue: Float = -bar(1.414)
“The Principal Type-Scheme of an Object in Combinatory Logic” Hindley, J. Roger (1969) − Describe what types an expression can have − Present an algorithm actually computing a type.
Deductive System
First implemented as part of the system of ML.
Hindley-Milner Type System
A, A ➔ BB (rule)
Hindley-Milner Type SystemExpression e = x
| e1 e2 | !x . e | let x=e1 in e2
Types mono " = # | D "…" poly $ = " | ∀#.$
variable
application
abstraction
variableapplication
quantifier
Syntax Context % = & | %, x : # Typing = % ⊢e : $
Hindley-Milner Algorithm W[Var]
[App]
[Abs]
[Let]
Type Checker - Constraints0PT HS � �x� � � �
TAS OD� �r � � �
NMUD RHNM� �r � � � q � DPT HS � �RTAS OD ��
NMRS T SHNM� � s� � �r � � � q �
DLAD � � � � � c%�h� � � �
NMEN L M D� � � � p� �
GD DC� RS� � R� � � � q ��
-OO H A D�ETM SHNM� � d� � � �
UD N C�AHMCHMF� � � y� � � �
RR� � � �
NMITMSHNM� �/HRITM SHNM� �a i� p� i
Constraint SolvingTake a given set of constraints
Determine the most specific type binding for each of the type variables
The Design of the solver − Simplification : Relational, Member constraints − Strategies : solver scope, overload selection − Comparing solutions : choose solution with smaller scores
“more specific” type
the super-type of overload binds
let swift(16)
Swift Type Internalsclass, enumeration, struct, protocol
Native class typeclass NativePen { let id = 512 var sequence = 1024 }
// class.NativePen.__deallocating_deinit @_TFC5class9NativePenD : $@convention(method) (@owned NativePen) -> () { %0 : $NativePen, let, name "self", argno 1 %3 = class.NativePen.deinit(%0) %4 = unchecked_ref_cast(%3) // $Builtin.NativeObject to $NativePen dealloc_ref(%4) } // class.NativePen.deinit @_TFC5class9NativePend : $@convention(method) (@guaranteed NativePen) -> @owned Builtin.NativeObject { %0 : $NativePen, let, name "self", argno 1 %2 = unchecked_ref_cast(%0) // $NativePen to $Builtin.NativeObject return %2 // $Builtin.NativeObject }
deinit
Native class type// class.NativePen.init () -> class.NativePen @_TFC5class9NativePencfT_S0_ : $@convention(method) (@owned NativePen) -> @owned NativePen { %0 : $NativePen, let, name "self" %2 = mark_uninitialized([rootself], %0) %4 = metatype(Int.Type) %5 = integer_literal($Builtin.Int2048, 512) %6 = Swift.Int.init(%5, %4) %7 = ref_element_addr(%2 : $NativePen, #NativePen.id) assign(%6 to %7) %10 = metatype(Int.Type) %11 = integer_literal($Builtin.Int2048, 1024) %12 = Swift.Int.init(%11, %10) %13 = ref_element_addr(%2 : $NativePen, #NativePen.sequence) assign (%12 to %13) return %2 // $NativePen } // class.NativePen.__allocating_init () -> class.NativePen @_TFC5class9NativePenCfT_S0_ : $@convention(thin) (@thick NativePen.Type) -> @owned NativePen { %1 = alloc_ref($NativePen) %3 = class.NativePen.init(%1) return %3 : $NativePen }
init
enumeration type_ p� � �r � � � q ��
− � _l� u� q � p� �
RG A D�O NSN N �
0PT S A D�O NSN N
public protocol Hashable : Equatable { var hashValue: Int { get } }
public protocol Equatable { @warn_unused_result func == (lhs: Self, rhs: Self) -> Bool }
enum type exampleenum PenModels { case BallPen case NamePen }// enum.PenModels.hashValue.getter : Swift.Int @_TFO4enum9PenModelsg9hashValueSi : $@convention(method) (PenModels) -> Int { %2 = alloc_box($Int, var, name "index") %3 = mark_uninitialized([var] %2#1 : $*Int) switch_enum %0 : $PenModels, case #PenModels.BallPen!enumelt: bb1, case #PenModels.NamePen!enumelt: bb2 bb1: %6 = metatype($@thin Int.Type) %7 = integer_literal($Builtin.Int2048, 0) %8 = Swift.Int.init(%7, %6) // (Builtin.Int2048, @thin Int.Type) -> Int assign(%8 to %3) br bb3 bb2: %12 = metatype($@thin Int.Type) %13 = integer_literal($Builtin.Int2048, 1) %14 = Swift.Int.init(%13, %12) // (Builtin.Int2048, @thin Int.Type) -> Int assign(%14 to %3) br bb3 bb3: %17 = load(%3 : $*Int) %19 = Swift.Int.hashValue.getter(%17) // $@convention(method) (Int) -> Int strong_release(%2#0) // $@box Int return %19 }
getter
enum type example// protocol witness for static Swift.Equatable.== infix (A, A) -> Swift.Bool @_TTWO4enum9PenModelss9EquatableS_ZFS1_oi2eefTxx_Sb : $@convention(witness_method) (@in PenModels, @in PenModels, @thick PenModels.Type) -> Bool { %3 = load(%0 : $*PenModels) %4 = load(%1 : $*PenModels) %6 = enum.== infix(%3, %4) return %6 // $Bool } // protocol witness for Swift.Hashable.hashValue.getter : Swift.Int @_TTWO4enum9PenModelss8HashableS_FS1_g9hashValueSi : $@convention(witness_method) (@in_guaranteed PenModels) -> Int { %1 = alloc_stack($PenModels) copy_addr(%0 to [initialization] %1 : $*PenModels) %3 = load(%1 : $*PenModels) %5 = enum.PenModels.hashValue.getter(%3) dealloc_stack(%1 : $*PenModels) return %5 // $Int } sil_witness_table PenModels: Equatable module enum { method #Equatable."=="!1: @_TTWO4enum9PenModelss9EquatableS_ZFS1_oi2eefTxx_Sb } sil_witness_table PenModels: Hashable module enum { base_protocol Equatable: PenModels: Equatable module enum method #Hashable.hashValue!getter.1: @_TTWO4enum9PenModelss8HashableS_FS1_g9hashValueSi }
Protocol Witness Table
struct type
� �i �wp� p� � �
− MS� � �- %� DS%�/H SHNM �t �)( �f �
i� HED D � c� �
− � � � � r�
n � � g �b r�
− DS HM� � D D RD�
struct type - let examplestruct Car { let model = "apple" }
// struct.Car.init () -> struct.Car @_TFV6struct3CarCfT_S0_ : $@convention(thin) (@thin Car.Type) -> @owned Car { %1 = alloc_box($Car, var, name "self", argno 1) %2 = mark_uninitialized([rootself] %1#1 : $*Car) %4 = metatype($@thin String.Type) %5 = string_literal(utf8 "apple") %6 = integer_literal($Builtin.Word, 5) %7 = integer_literal($Builtin.Int1, -1) %8 = Swift.String.init(%5, %6, %7, %4) %9 = struct_element_addr(%2 : $*Car, #Car.model) assign(%8 to %9 : $*String) %11 = load(%2 : $*Car) retain_value(%11 : $Car) strong_release(%1#0 : $@box Car) return %11 } // struct.Car.model.getter : Swift.String @_TFV6struct3Carg5modelSS : $@convention(method) (@guaranteed Car) -> @owned String { %2 = struct_extract(%0 : $Car, #Car.model) retain_value(%2 : $String) return %2 }
struct type - var examplestruct Car { var driver = "tim" }
// struct.Car.init (driver : Swift.String) -> struct.Car @_TFV6struct3CarCfT6driverSS_S0_ : $@convention(thin) (@owned String, @thin Car.Type) -> @owned Car { %2 = struct.$Car(%0 : $String) return %2 } // struct.Car.init () -> struct.Car @_TFV6struct3CarCfT_S0_ : $@convention(thin) (@thin Car.Type) -> @owned Car { %1 = alloc_box($Car, var, name "self", argno 1) %2 = mark_uninitialized([rootself] %1#1 : $*Car) %4 = metatype($@thin String.Type) %5 = string_literal(utf8 "tim") %6 = integer_literal($Builtin.Word, 3) %7 = integer_literal($Builtin.Int1, -1) %8 = Swift.String.init(%5, %6, %7, %4) %9 = struct_element_addr(%2 : $*Car, #Car.driver) assign(%8 to %9 : $*String) %11 = load(%2 : $*Car) retain_value(%11 : $Car) strong_release(%1#0 : $@box Car) return %11 }
init
struct type - var example// struct.Car.driver.getter : Swift.String @_TFV6struct3Carg6driverSS : $@convention(method) (@guaranteed Car) -> @owned String { %2 = struct_extract(%0 : $Car, #Car.driver) retain_value(%2 : $String) return %2 } // struct.Car.driver.setter : Swift.String @_TFV6struct3Cars6driverSS : $@convention(method) (@owned String, @inout Car) -> () { %3 = alloc_box($Car, var, name "self", argno 2) copy_addr(%1 to [initialization] %3#1 : $*Car) retain_value(%0 : $String) %6 = struct_element_addr(%3#1 : $*Car, #Car.driver) assign(%0 to %6 : $*String) copy_addr(%3#1 to %1 : $*Car) strong_release(%3#0 : $@box Car) release_value(%0 : $String) %11 = tuple () return %11 } // struct.Car.driver.materializeForSet : Swift.String @_TFV6struct3Carm6driverSS : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Car) -> (Builtin.RawPointer, Optional<@convention(thin) (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer, inout Car, @thick Car.Type) -> ()>) { %3 = struct_element_addr(%2 : $*Car, #Car.driver) %4 = address_to_pointer(%3 : $*String to $Builtin.RawPointer) %5 = enum $Optional<@convention(thin) (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer, inout Car, @thick Car.Type) -> ()>, #Optional.None!enumelt %6 = tuple (%4 : $Builtin.RawPointer, %5 : $Optional<@convention(thin) (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer, inout Car, @thick Car.Type) -> ()>) return %6 : $(Builtin.RawPointer, Optional<@convention(thin) (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer, inout Car, @thick Car.Type) -> ()>) }
getter/setter
let swift(16)
Swift 3 Foundation
Foundation SDK
source : WWDC 2016. Session207. Whats new in foundation for swift
파일�구분 관련�타입들 설명
AffineTransform OTA H �RS T S�-EEHMD< MREN L -EEHMD< MREN L �v p�f �
CharacterSetHMSD M �EHM � RR�
VHES G SD DSG SD DS�d� TS A D G SD DS � p�n
� �
Data HMSD M �EHM � RR� VHES / S / S � TS A D/ S � p�n �
Date OTA H �RS T S�/ SD <HLD MSD U � � SHLD � m �b p�
DateComponents OTA H �RS T S�/ SD NLONMDMSR / SD NLONMDMSR � p�m � �
DateInterval OTA H �RS T S�/ SD MSD U / SD MSD U � p�m i � �o �
Decimal D SDMRHNM�/D HL� �t � � %� e� %� /D HL TLAD �
a � p�
FileManager OTA H � RR� H D M FD H D M FD � �
IndexPath OTA H �RS T S� MCD 9 SG MCD 9 SG �v p�o �f �
IndexSet OTA H �RS T S� MCD DS MCD DS �v p�o �f �
Measurement OTA H �RS T S� D RT DLDMS+ MHS< OD� �MHS,
D RT DLDMS �v p�o �f �
Notification OTA H �RS T S� NSHEH SHNM NSHEH SHNM �v p�o �f �
NSError D SDMRHNM� 0 N � �0 N 9 NSN N 0 N �o � � � � u �
URL OTA H �RS T S� : : � p�f �
URLComponents OTA H �RS T S� : NLONMDMSR : NLONMDMSR � p�f �
URLRequest OTA H �RS T S� : :DPTDRS TS A D : :DPTDRS � p�f �
SummarySwift Compiler − LLVM + Chris Lattner, Talyer swift
Type System − HM Type System + W Algorithm
Type Internals − class, enumeration, struct, protocol Types
Swift Foundation − IndexPath, IndexSet, Measurement, Notification
Referencesllvm.org
swift.org
https://github.com/apple/swift-evolution
https://github.com/apple/swift/tree/swift-3.0-preview-2-branch
https://en.wikipedia.org/wiki/Duck_typing
https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system
http://akgupta.ca/blog/2013/05/14/so-you-still-dont-understand-hindley-milner/
https://developer.apple.com/videos/wwdc2016/
let swift(16)