Slide 1

Slide 1 text

@gregheo NSMeetup February 7, 2018

Slide 2

Slide 2 text

Stack views Auto Layout Frame calculations UIViews CALayers Core Animation OpenGL Metal putpixel() OLEDs Individual photons Quantum physics GUI toolkits Standard library Unix processes fork vs exec bash Kernel modules Operating systems Linkers Compilers Assembly Toggle switches emacs

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

— Jesse Squires

Slide 5

Slide 5 text

Swift Runtime Instances Standard Library SIL Reflection Debug Toolchains

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

SIL IR Object CodeGen IRGen AST Sema SILGen Parse

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

00 e3 8e c0 〇〇〇 〇〇〇〇〇〇〇〇 〇〇〇〇〇〇 〇〇〇〇 add bl,ah mov es,eax

Slide 10

Slide 10 text

ASM Binary

Slide 11

Slide 11 text

ASM C Binary C++

Slide 12

Slide 12 text

ASM C Binary C++ Obj-C

Slide 13

Slide 13 text

ASM C Binary C++ Obj-C

Slide 14

Slide 14 text

ASM C Binary C++ IR Obj-C

Slide 15

Slide 15 text

printf(“hello world!”); subq $32, %rsp leaq L_.str(%rip), %rax movl $0, -4(%rbp) movl %edi, -8(%rbp) movq %rsi, -16(%rbp) movq %rax, %rdi movb $0, %al callq_printf define i32 @main(i32, i8**) #0 { %3 = alloca i32, align 4 %4 = alloca i32, align 4 %5 = alloca i8**, align 8 store i32 0, i32* %3, align 4 store i32 %0, i32* %4, align 4 store i8** %1, i8*** %5, align 8 %6 = call i32 (i8*, …)
 @printf(i8* getelementptr inbounds… ret i32 0 }

Slide 16

Slide 16 text

ASM C Binary C++ IR Obj-C

Slide 17

Slide 17 text

SIL IR …

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

class NSMeetup { func sayHello() { print("Hello") } } let m = NSMeetup() m.sayHello()

Slide 20

Slide 20 text

sil_stage canonical import Builtin import Swift import SwiftShims // m sil_global hidden [let] @_T06simple1mAA8NSMeetupCv : $NSMeetup // _swiftEmptyArrayStorage sil_global [serialized] @_swiftEmptyArrayStorage : $_SwiftEmptyArrayStorage // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer>>) -> Int32 { bb0(%0 : $Int32, %1 :

Slide 21

Slide 21 text

sil_vtable NSMeetup { #NSMeetup.sayHello!1: (NSMeetup) -> () -> () : _T06simple8NSMeetupC8sayHelloyyF // NSMeetup.sayHello() #NSMeetup.init!initializer.1: (NSMeetup.Type) -> () -> NSMeetup : _T06simple8NSMeetupCACycfc // NSMeetup.init() #NSMeetup.deinit!deallocator: _T06simple8NSMeetupCfD // NSMeetup.__deallocating_deinit } sil_vtable _ContiguousArrayStorage { #_SwiftNativeNSArrayWithContiguousStorage.withUnsafeBufferOfObjects!1 (_SwiftNativeNSArrayWithContiguousStorage) -> ((UnsafeBufferPointer) throws -> R) throws -> R : _T0s27_ContiguousArrayStorageBaseC25withUnsafeBufferOfObjectsxxSRyyXlGK KlF // _ContiguousArrayStorageBase.withUnsafeBufferOfObjects(_:) #_ContiguousArrayStorageBase._withVerbatimBridgedUnsafeBuffer!1: (_ContiguousArrayStorageBase) -> ((UnsafeBufferPointer)

Slide 22

Slide 22 text

// NSMeetup.sayHello() sil hidden @_T06simple8NSMeetupC8sayHelloyyF : $@convention(method) (@guaranteed NSMeetup) -> () { // %0 // user: %1 bb0(%0 : $NSMeetup): debug_value %0 : $NSMeetup, let, name "self", argno 1 // id: %1 // function_ref print(_:separator:terminator:) %2 = function_ref @_T0s5printySayypGd_SS9separatorSS10terminatortF : $@convention(thin) (@owned Array, @owned String, @owned String) -> () // user: %23 %3 = integer_literal $Builtin.Word, 1 // user: %5 // function_ref specialized _allocateUninitializedArray(_:) %4 = function_ref @_T0s27_allocateUninitializedArraySayxG_BptBwlFyp_Tgq5 : $@convention(thin) (Builtin.Word) -> (@owned Array, Builtin.RawPointer) // user: %5 %5 = apply %4(%3) : $@convention(thin) (Builtin.Word) -> (@owned

Slide 23

Slide 23 text

$ xcrun swift-demangle
 _T0s5printySayypGd_SS9separatorSS10terminatortF
 Swift.print(Any...,
 separator: Swift.String,
 terminator: Swift.String) -> ()

Slide 24

Slide 24 text

retain_value %6 : $Array // id: %7 %8 = tuple_extract %5 : $(Array, Builtin.RawPointer), 1 // user: %10 release_value %5 : $(Array, Builtin.RawPointer) // id: %9 %10 = pointer_to_address %8 : $Builtin.RawPointer to [strict] $*Any / user: %11 %11 = init_existential_addr %10 : $*Any, $String // user: %18 %12 = string_literal utf8 "Hello" // user: %17 %13 = integer_literal $Builtin.Word, 5 // user: %17 %14 = integer_literal $Builtin.Int1, -1 // user: %17 %15 = metatype $@thin String.Type // user: %17 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %16 = function_ref @_T0S2SBp21_builtinStringLiteral_Bw17utf8CodeUnitCountBi1_7isASCIItcfC $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %17 %17 = apply %16(%12, %13, %14, %15) : $@convention(method)

Slide 25

Slide 25 text

class NSMeetup { func sayHello() { print("Hello") } } // let m = NSMeetup()
 var m = NSMeetup()
 m.sayHello()

Slide 26

Slide 26 text

%9 = load %8 : $*NSMeetup %10 = class_method %9 : $NSMeetup, #NSMeetup.sayHello!1 : (NSMeetup) -> () -> (), $@convention(method) (@guaranteed NSMeetup) -> () %11 = apply %10(%9) : $@convention(method) (@guaranteed NSMeetup) -> ()

Slide 27

Slide 27 text

%8 = begin_access [read] [dynamic] %3 : $*NSMeetup %9 = load %8 : $*NSMeetup strong_retain %9 : $NSMeetup end_access %8 : $*NSMeetup %10 = class_method %9 : $NSMeetup, #NSMeetup.sayHello!1 : (NSMeetup) -> () -> (), $@convention(method) (@guaranteed NSMeetup) -> () %11 = apply %10(%9) : $@convention(method) (@guaranteed NSMeetup) -> () strong_release %9 : $NSMeetup

Slide 28

Slide 28 text

call void @llvm.lifetime.start(i64 -1, i8* %13) call void @swift_beginAccess(i8* bitcast (%TSi* @_T011simpleprint1aSiv to i8*), [24 x i8]* %access-scratch, i64 0, i8* null) #6 %14 = load i64, i64* getelementptr inbounds (%TSi, %TSi* @_T011simpleprint1aSiv, i32 0, i32 0), align 8 call void @swift_endAccess([24 x i8]* %access-scratch) #6 %15 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.end(i64 -1, i8* %15) %._value = getelementptr inbounds %TSi, %TSi* %12, i32 0, i32 0 store i64 %14, i64* %._value, align 8 %16 = call swiftcc { i64, i64, i64 } @_T0s5printySayypGd_SS9separatorSS10terminatortFfA0_() %17 = extractvalue { i64, i64, i64 } %16, 0 %18 = extractvalue { i64, i64, i64 } %16, 1 %19 = extractvalue { i64, i64, i64 } %16, 2

Slide 29

Slide 29 text

call void @llvm.lifetime.start(i64 -1, i8* %13) call void @swift_beginAccess(i8* bitcast (%TSi* @_T011simpleprint1aSiv to i8*), [24 x i8]* %access-scratch, i64 0, i8* null) #6
 
 call void @#__tsan_read8(i8* bitcast (%TSi* @_T011simpleprint1aSiv to i8*)) %14 = load i64, i64* getelementptr inbounds (%TSi, %TSi* @_T011simpleprint1aSiv, i32 0, i32 0), align 8 call void @swift_endAccess([24 x i8]* %access-scratch) #6 %15 = bitcast [24 x i8]* %access-scratch to i8* call void @llvm.lifetime.end(i64 -1, i8* %15) %._value = getelementptr inbounds %TSi, %TSi* %12, i32 0, i32 0 store i64 %14, i64* %._value, align 8 %16 = call swiftcc { i64, i64, i64 } @_T0s5printySayypGd_SS9separatorSS10terminatortFfA0_()

Slide 30

Slide 30 text

• Your code, lowered • ARC & memory management • Change code; see diffs on SIL

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

Queries Modifications Construction

Slide 33

Slide 33 text

Reflection Demo

Slide 34

Slide 34 text

• Objective-C runtime functions • Mirror for “read-only reflection” • Direct pointer access • More advanced reflection to come?

Slide 35

Slide 35 text

ASM C Binary C++ IR Obj-C

Slide 36

Slide 36 text

Language Standard Library

Slide 37

Slide 37 text

Standard library demo

Slide 38

Slide 38 text

• Standard library is open source! • Standard library code in the debugger • Running custom Xcode toolchains

Slide 39

Slide 39 text

Swift Runtime Instances Standard Library SIL Reflection Debug Toolchains

Slide 40

Slide 40 text

So What?

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

https://gregheo.com

Slide 45

Slide 45 text

Getting Under
 Swift’s Skin @gregheo NSMeetup February 7, 2018