Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Why Does Our Swift Code Work? Understanding Swi...

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →

Why Does Our Swift Code Work? Understanding Swift Through Platforms, Runtime, and the Compiler

Avatar for freddi(Yuki Aki)

freddi(Yuki Aki)

October 15, 2026

More Decks by freddi(Yuki Aki)

Other Decks in Technology

Transcript

  1. Motivation Why go deeper into Swift? Swift is growing into

    a true multi-platform language Platform-native development benefits from knowing what's underneath It also shapes your Developer Experience in meaningful ways
  2. Platform constraints APIs arrive with OS versions — not all

    users are on the latest Your deployment target caps which APIs you can call @available #available // Deployment target: iOS 15 @Observable class Model { var count = 0 } ✕ 'Observable' is only available in iOS 17 or newer
  3. Platform constraints APIs arrive with OS versions — not all

    users are on the latest Your deployment target caps which APIs you can call @available #available // Deployment target: iOS 15 @available(iOS 17, *) @Observable class Model { var count = 0 }
  4. Invisible runtime costs Many codes are inserted by the compiler

    — not written by you Example: ARC A lot of Invisible reference counting code injected at compile time Looking at generated code helps improving your app performance let dog = Dog() let dog = Dog() let friend = dog friend.bark() strong_retain %2 let friend = dog friend.bark() strong_release %2
  5. What is Runtime The engine beneath every Swift program The

    program that handles Swift's runtime behavior The heart that makes Swift feel like Swift on every platform
  6. Calls at Runtime Swift Code Runtime Creating an instance swift_allocObject

    Reference counting (ARC) swift_retain / release as? / is casts swift_dynamicCast async / await Concurrency runtime Ships with OS
  7. Before iOS 12.2 App A App B App C Compiled

    code Compiled code Compiled code Swift Runtime Swift Runtime Swift Runtime Apple Platform
  8. After iOS 12.2 App A App B App C Compiled

    code Compiled code Compiled code Apple Platform Swift Runtime (Dynamic Library)
  9. App App calls newAPI() calls newAPI() iOS 18 Runtime iOS

    17 Runtime existingAPI() existingAPI() anotherAPI() anotherAPI() ✓ newAPI() ✕ newAPI()
  10. Launch Time Cost Static launch main() Dynamic launch dyld: load

    .dylib main() Longer launch time Meet mergeable libraries WWDC23
  11. After iOS 12.2 With ABI Stability (SE-0260) App A App

    B App C Compiled code (Swift 5) Compiled code (Swift 5.1) Compiled code (Swift 6) Apple Platform Swift 6.0 Runtime (Dynamic Library)
  12. After iOS 12.2 With ABI Stability App A App B

    App C Compiled code (Swift 5) Compiled code (Swift 5.1) Compiled code (Swift 6) Stable ABI (From Swift 5.0) Apple Platform Swift 6.0 Runtime (Dynamic Library)
  13. What is ABI Stability A stable contract between Swift binaries

    and the runtime Defines fixed contract of Application Binary Interface (ABI) for Swift Allows the OS to provide Swift Runtime loaded by all application
  14. Beyond ABI Stability Module Stability from Swift 5.1 Module Stability

    (from Swift 5.1) is introduced Allows importing libraries (.framework) built with different compiler versions
  15. Before Module stability Import-level compatibility at build time App Framework

    Built with Swift 5.1 .swiftmodule Built with Swift 5.1 ✓ import Framework
  16. Before Module stability Import-level compatibility at build time App Framework

    Built with Swift 5.1 .swiftmodule Built with Swift 5.1.2 ✕ import Framework module compiled with Swift 5.1 cannot be imported by the Swift 5.1.2 compiler
  17. After Module stability Import-level compatibility at build time App Framework

    Built with Swift 5.1 .swiftmodule Built with Swift 5.1 ✓ import Framework
  18. After Module stability Import-level compatibility at build time App Framework

    Built with Swift 5.1 .swiftinterface Built with Swift 5.1.2 ✓ import Framework Set BUILD_LIBRARY_FOR_DISTRIBUTION = YES
  19. A note for maintainers Don t too reply on Module

    Stability Stability keeps old binaries working It's a safety net, not a goal ’ Keep your libraries / frameworks updated
  20. Swift on Linux Static Runtime Dynamic Runtime Executable Executable Compiled

    .swift code Compiled .swift code libswiftCore.a (Runtime & Stdlib) Loaded at launch libswiftCore.so (Runtime & Stdlib) Linux
  21. Swift on Wasm Wasm Module (.wasm) Compiled .swift code libswiftCore.a

    (Runtime & Stdlib) JavaScriptKit JavaScript host Browser / Node.js / Bun / Deno Wasm Runtime (Browser / WASI) Introduction to WebAssembly for Swift Developers SwiftLeeds 2024
  22. Swift on Android .apk libMyLibrary.so Compiled .swift code Java /

    Kotlin swift-java (JNI) libswiftCore.a (Runtime & Stdlib) Android classes.dex (ART)
  23. Embedded Swift App Firmware Compiled .swift code Specialized app code

    Type metadata ✕ Type metadata Stdlib Stdlib subset Swift Runtime ✕ Swift Runtime iOS Bare metal / MCU
  24. Embedded Swift: Language Subset ✓ Available ✕ Not available Generics

    Reflection (Mirror) Protocols Existentials (any P) Enums with associated values Metatypes / Untyped throws Optionals / Tuples Codable Classes & inheritance Printing arbitrary types Runtime polymorphism weak / unowned references Arrays (copy-on-write) Non-final generic class methods Library Evolution / ObjC interop
  25. Embedded Swift: Language Subset ✓ Available ✕ Not available Generics

    Reflection (Mirror) Protocols Codable Enums with associated values Printing arbitrary types Optionals / Tuples weak / unowned references Classes & inheritance Non-final generic class methods Runtime polymorphism Library Evolution / ObjC interop Arrays (copy-on-write) Existentials (any P) Metatypes / Untyped throws
  26. Swift Compiler Pipeline .swift Parse Sema AST Typechecked AST SILGen

    SIL Optimize Canonical SIL Raw SIL IRGen LLVM IR CodeGen Object file (.o) Linker Executable
  27. Swift Compiler Pipeline .swift Parse Sema AST Typechecked AST SILGen

    SIL Optimize Canonical SIL Raw SIL IRGen LLVM IR CodeGen Object file (.o) Linker Executable
  28. Type Check Cost Example: Code that relies heavily on type

    inference can slow the compiler This is where you have room to optimize
  29. Too complex expression Type inference hits its time limit let

    x = Optional(1).map { $0 + 0.5 } .map { $0 * 2 } .map { $0 + 1 } .map { $0 / 2 } ✕ The compiler is unable to type-check this expression in reasonable time
  30. Break it up let x = Optional(1).map { $0 +

    0.5 } ✕ .map { $0 * 2 } .map { $0 + 1 } .map { $0 / 2 } let x: Double? = Optional(1).map { $0 + 0.5 } ✕ 1.8 s .map { $0 * 2 } .map { $0 + 1 } .map { $0 / 2 } let a = Optional(1).map { $0 + 0.5 } let b = a.map { $0 * 2 } let c = b.map { $0 + 1 } let x = c.map { $0 / 2 } ✓ 0.06 s
  31. Measure type checking Slow even without the error Find hot

    spots, cut build time -Xfrontend -warn-long-function-bodies=100 -Xfrontend -warn-long-expression-type-checking=100
  32. Swift Compiler Pipeline .swift Parse Sema AST Typechecked AST SILGen

    SIL Optimize Canonical SIL Raw SIL IRGen LLVM IR CodeGen Object file (.o) Linker Executable
  33. Swift Compiler Pipeline .swift Parse Sema AST Typechecked AST SILGen

    SIL Optimize Canonical SIL Raw SIL IRGen LLVM IR CodeGen Object file (.o) Linker Executable
  34. SIL Optimizer Optimizations and diagnostics on SIL Sits between SILGen

    and IRGen Optimize — inlining, specialization, ARC … Diagnose — Definite init / unreachable code / overflow even at -Onone
  35. SIL Optimizations / Generic specialization / Inlining / Devirtualization /

    Common subexpression elimination / ARC optimization / Closure specialization / Dead code elimination / Existential specialization / SROA / Copy propagation / Stack promotion / Constant propagation / Dead object elimination / Mem2Reg / Object outlining / String optimization / Simplify CFG / COW optimization / Alloc box to stack / Redundant load elimination / Release devirtualization / Exclusivity enforcement
  36. SIL Optimizations / Generic specialization / Inlining / Devirtualization /

    Common subexpression elimination / ARC optimization / Closure specialization / Dead code elimination / Existential specialization / SROA / Copy propagation / Stack promotion / Constant propagation / Dead object elimination / Mem2Reg / Object outlining / String optimization / Simplify CFG / COW optimization / Alloc box to stack / Redundant load elimination / Release devirtualization / Exclusivity enforcement
  37. Raw SIL Raw SIL from swiftc -emit-silgen sil hidden [ossa]

    @$s4demo5greetyyF : $@convention(thin) () -> () { bb0: %0 = metatype $@thick Dog.Type // function_ref Dog.__allocating_init() %1 = function_ref @$s4demo3DogCACycfC : $@convention(method) (@thick Dog.Type) -> @owned Dog %2 = apply %1(%0) : $@convention(method) (@thick Dog.Type) -> @owned Dog %3 = move_value [lexical] [var_decl] %2 debug_value %3, let, name "dog" %5 = begin_borrow %3 %6 = copy_value %5 %7 = move_value [lexical] [var_decl] %6 debug_value %7, let, name "friend" end_borrow %5 %10 = begin_borrow %7 // function_ref Dog.bark() %11 = function_ref @$s4demo3DogC4barkyyF : $@convention(method) (@guaranteed Dog) -> () %12 = apply %11(%10) : $@convention(method) (@guaranteed Dog) -> () end_borrow %10 destroy_value %7 destroy_value %3 %16 = tuple () return %16 }
  38. Canonical SIL Canonical SIL from swiftc -emit-sil sil hidden @$s4demo5greetyyF

    : $@convention(thin) () -> () { bb0: %0 = metatype $@thick Dog.Type // function_ref Dog.__allocating_init() %1 = function_ref @$s4demo3DogCACycfC : $@convention(method) (@thick Dog.Type) -> @owned Dog %2 = apply %1(%0) : $@convention(method) (@thick Dog.Type) -> @owned Dog debug_value %2, let, name "dog" strong_retain %2 debug_value %2, let, name "friend" // function_ref Dog.bark() %6 = function_ref @$s4demo3DogC4barkyyF : $@convention(method) (@guaranteed Dog) -> () %7 = apply %6(%2) : $@convention(method) (@guaranteed Dog) -> () strong_release %2 strong_release %2 %10 = tuple () return %10 }
  39. Canonical SIL Canonical SIL from swiftc -emit-sil sil hidden @$s4demo5greetyyF

    : $@convention(thin) () -> () { bb0: %0 = metatype $@thick Dog.Type // function_ref Dog.__allocating_init() %1 = function_ref @$s4demo3DogCACycfC : $@convention(method) (@thick Dog.Type) -> @owned Dog %2 = apply %1(%0) : $@convention(method) (@thick Dog.Type) -> @owned Dog debug_value %2, let, name "dog" strong_retain %2 debug_value %2, let, name "friend" // function_ref Dog.bark() %6 = function_ref @$s4demo3DogC4barkyyF : $@convention(method) (@guaranteed Dog) -> () %7 = apply %6(%2) : $@convention(method) (@guaranteed Dog) -> () strong_release %2 strong_release %2 %10 = tuple () return %10 }
  40. SIL Optimizations Redundant ARC pairs removed SemanticARCOpts ARCSequenceOpts func greet()

    { let dog = Dog() let friend = dog swift_retain(dog) friend.bark() swift_release(friend) swift_release(dog) }
  41. Don't over-trust the optimizer Optimizations are best-effort Results change across

    compilers Express performance in source code and inspect it
  42. ARC has a cost Retain / release calls remain —

    even at -O Invisible in your code func register(_ dog: Dog) { kennel.append(dog) } Impacts performance sil hidden @$s4demo8registeryyAA3DogCnF : $@convention(thin) (@owned Dog) -> () bb0(%0 : @noImplicitCopy @_eagerMove $Dog): strong_retain %0 ... // Array.append %42 = apply %40(%39, %41, %5) ...
  43. Ownership Transfer Ownership by consuming Move ownership to the callee

    consuming func register(_ dog: consuming Dog) { kennel.append(dog) } sil hidden @$s4demo8registeryyAA3DogCnF : $@convention(thin) (@owned Dog) -> () bb0(%0 : @noImplicitCopy @_eagerMove $Dog): strong_retain %0 ... // Array.append %42 = apply %40(%39, %41, %5) ...
  44. .swift Parse Sema AST Typechecked AST SILGen SIL Optimize Canonical

    SIL Raw SIL IRGen LLVM IR CodeGen Object file (.o) Linker Executable
  45. Go deeper The details are worth knowing Every new Swift

    feature has a design reason behind it Runtime and compiler knowledge helps you see those reasons Use this as your lens — and enjoy the next feature even more
  46. Example: Behind some and any some shipped alongside SwiftUI —

    Opaque Result Types (SE-0244) Overcomes several limitations of existing existential types Keyword: Existential Container Deep Dive into "any" and "some" SwiftHeroes 2023
  47. Example: Build Artifact Caching Swift frameworks and build outputs can

    be cached effectively Many tools exist to take advantage of this Try exploring them with the knowledge from today Tuist tuist/Tuist Scipio giginet/Scipio
  48. Understand from deep side of Swift Optimize by lens of

    Runtime and Compiler Enjoy your Swift life