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

Contributing to the Swift Compiler

Contributing to the Swift Compiler

Slides on my talk on contributing to the Swift compiler at NextDoor Conf 2018.

David Hart

June 05, 2018
Tweet

More Decks by David Hart

Other Decks in Programming

Transcript

  1. Front-end AST (Abstract Syntax Tree) / * 2 x 40

    / * 2 x 40 Tokens Parsing (Syntax Analysis)
  2. Front-end AST (Abstract Syntax Tree) / * 2 x 40

    Decorated AST / * 2 x 40 int int int int int Semantic Analysis
  3. Front-end Decorated AST / * 2 x 40 int int

    int int int IR (Internal Representation) push x push 40 multiply push 2 divide IR Generation
  4. Middle-end Optimized IR push x push 20 multiply IR (Internal

    Representation) push x push 40 multiply push 2 divide Optimization
  5. Swift Front-end print("Hello World") Source Code AST (source_file (top_level_code_decl (brace_stmt

    (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>' name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) Parse (Lexer + Parser) % swiftc -dump-parse -O file.swift
  6. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) print("Hello World")
  7. (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>' name=print function_ref=unapplied)

    (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) print("Hello World") Swift Front-end (/ (* x 40) 2) / * 2 x 40
  8. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) ( ) "Hello World" print
  9. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) ( ) "Hello World" print
  10. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) ( ) "Hello World" print
  11. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) ( ) "Hello World" print
  12. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) ( ) "Hello World" print
  13. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) ( ) "Hello World" print
  14. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) ( ) "Hello World" print
  15. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) ( ) "Hello World" print
  16. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>'

    name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) print("Hello World")
  17. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='()' nothrow arg_labels=_: (declref_expr

    type='(Any..., String, String) -> ()' decl=Swift.(file).print(_:separator:terminator:) function_ref=single) (tuple_shuffle_expr implicit type='(Any..., separator: String, terminator: String)' (paren_expr type='Any' (erasure_expr implicit type='Any' (string_literal_expr type='String' encoding=utf8 value="Hello World")))))))) Decorated AST (source_file (top_level_code_decl (brace_stmt (call_expr type='<null>' arg_labels=_: (unresolved_decl_ref_expr type='<null>' name=print function_ref=unapplied) (paren_expr type='<null>' (string_literal_expr type='<null>' encoding=utf8 value="Hello World")))))) AST Sema % swiftc -dump-ast -O file.swift
  18. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='()' nothrow arg_labels=_: (declref_expr

    type='(Any..., String, String) -> ()' decl=Swift.(file).print(_:separator:terminator:) function_ref=single) (tuple_shuffle_expr implicit type='(Any..., separator: String, terminator: String)' (paren_expr type='Any' (erasure_expr implicit type='Any' (string_literal_expr type='String' encoding=utf8 value="Hello World"))))))))
  19. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='()' nothrow arg_labels=_: (declref_expr

    type='(Any..., String, String) -> ()' decl=Swift.(file).print(_:separator:terminator:) function_ref=single) (tuple_shuffle_expr implicit type='(Any..., separator: String, terminator: String)' (paren_expr type='Any' (erasure_expr implicit type='Any' (string_literal_expr type='String' encoding=utf8 value="Hello World"))))))))
  20. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='()' nothrow arg_labels=_: (declref_expr

    type='(Any..., String, String) -> ()' decl=Swift.(file).print(_:separator:terminator:) function_ref=single) (tuple_shuffle_expr implicit type='(Any..., separator: String, terminator: String)' (paren_expr type='Any' (erasure_expr implicit type='Any' (string_literal_expr type='String' encoding=utf8 value="Hello World"))))))))
  21. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='()' nothrow arg_labels=_: (declref_expr

    type='(Any..., String, String) -> ()' decl=Swift.(file).print(_:separator:terminator:) function_ref=single) (tuple_shuffle_expr implicit type='(Any..., separator: String, terminator: String)' (paren_expr type='Any' (erasure_expr implicit type='Any' (string_literal_expr type='String' encoding=utf8 value="Hello World"))))))))
  22. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='()' nothrow arg_labels=_: (declref_expr

    type='(Any..., String, String) -> ()' decl=Swift.(file).print(_:separator:terminator:) function_ref=single) (tuple_shuffle_expr implicit type='(Any..., separator: String, terminator: String)' (paren_expr type='Any' (erasure_expr implicit type='Any' (string_literal_expr type='String' encoding=utf8 value="Hello World"))))))))
  23. Swift Front-end (source_file (top_level_code_decl (brace_stmt (call_expr type='()' nothrow arg_labels=_: (declref_expr

    type='(Any..., String, String) -> ()' decl=Swift.(file).print(_:separator:terminator:) function_ref=single) (tuple_shuffle_expr implicit type='(Any..., separator: String, terminator: String)' (paren_expr type='Any' (erasure_expr implicit type='Any' (string_literal_expr type='String' encoding=utf8 value="Hello World")))))))) Decorated AST sil_stage raw import Builtin import Swift import SwiftShims // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @_T0s27_allocateUninitializedArraySayxG_BptBwlF : $@convention(thin) < _0_0> (Builtin.Word) -> (@owned Array< _0_0>, Builtin.RawPointer) // user: %4 ... SIL (Swift Intermediate Language) SILGen % swiftc -emit-silgen -O file.swift
  24. Swift Middle-end sil_stage raw import Builtin import Swift import SwiftShims

    // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @_T0s27_allocateUninitializedArraySayxG_BptBwlF : $@convention(thin) < _0_0> (Builtin.Word) -> (@owned Array< _0_0>, Builtin.RawPointer) // user: %4 ... SIL (Swift Intermediate Language) sil_stage canonical import Builtin import Swift import SwiftShims // _swiftEmptyArrayStorage sil_global @_swiftEmptyArrayStorage : $_SwiftEmptyArrayStorage // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %5 %3 = integer_literal $Builtin.Int64, 1 // user: %4 ... Optimized SIL SILOptimizer % swiftc -emit-sil -O file.swift
  25. Swift Middle-end sil_stage canonical import Builtin import Swift import SwiftShims

    // _swiftEmptyArrayStorage sil_global @_swiftEmptyArrayStorage : $_SwiftEmptyArrayStorage // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %5 %3 = integer_literal $Builtin.Int64, 1 // user: %4 ... Optimized SIL ; ModuleID = '-' source_filename = "-" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.13" define i32 @main(i32, i8**) #0 { entry: %2 = bitcast i8** %1 to i8* %3 = call %swift.type* @_T0s23_ContiguousArrayStorageCyypGMa() #6 %4 = bitcast %swift.type* %3 to i8* %5 = getelementptr inbounds i8, i8* %4, i32 48 %6 = bitcast i8* %5 to i32* %7 = load i32, i32* %6, align 8 %8 = zext i32 %7 to i64 %9 = getelementptr inbounds i8, i8* %4, i32 52 %10 = bitcast i8* %9 to i16* %11 = load i16, i16* %10, align 4 ... LLVM-IR IRGen % swiftc -emit-ir -Xfrontend -disable-llvm-optzns -O file.swift
  26. Prerequisites 20Gb of free disk space A recent version of

    Xcode https://ci.swift.org As fast a CPU as you can get
  27. Building (Generator) Xcode -x, --xcode ! Fast " No IDE

    Ninja default ! IDE " Test integration
  28. Building (Variant) Release ! Debug symbols " Slow, Large Debug

    ! Fast, Small " No debug symbols -R, --release -d, --debug
  29. Compiler Directive SE-0212 struct GridPoint: Hashable { let x: Int

    let y: Int static func == (lhs: GridPoint, rhs: GridPoint) -> Bool { return lhs.x == rhs.x && lhs.y == lhs.y } var hashValue: Int { return x ^ y } }
  30. Compiler Directive SE-0212 struct GridPoint: Hashable { let x: Int

    let y: Int static func == (lhs: GridPoint, rhs: GridPoint) -> Bool { return lhs.x == rhs.x && lhs.y == lhs.y } var hashValue: Int { return x ^ y } }
  31. Compiler Directive SE-0212 struct GridPoint: Hashable { let x: Int

    let y: Int static func == (lhs: GridPoint, rhs: GridPoint) -> Bool { return lhs.x == rhs.x && lhs.y == lhs.y } var hashValue: Int { return x ^ y } }
  32. Compiler Directive SE-0212 struct GridPoint: Hashable { let x: Int

    let y: Int #if !swift(>=4.1) static func == (lhs: GridPoint, rhs: GridPoint) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } var hashValue: Int { return x ^ y } #endif }
  33. Compiler Directive SE-0212 struct GridPoint: Hashable { let x: Int

    let y: Int #if !swift(>=3.3) static func == (lhs: GridPoint, rhs: GridPoint) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } var hashValue: Int { return x ^ y } #endif }
  34. Compiler Directive SE-0212 struct GridPoint: Hashable { let x: Int

    let y: Int #if !swift(>=3.3) || (swift(>=4) && !swift(>=4.1)) static func == (lhs: GridPoint, rhs: GridPoint) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } var hashValue: Int { return x ^ y } #endif }
  35. Compiler Directive SE-0212 struct GridPoint: Hashable { let x: Int

    let y: Int #if !compiler(>=4.1) static func == (lhs: GridPoint, rhs: GridPoint) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } var hashValue: Int { return x ^ y } #endif }
  36. LIT // RUN: %target-typecheck-verify-swift // RUN: %target-swift-frontend -c -verify %s

    -o /dev/null #warning("this should be a warning”) // expected-warning {{this should be a warning}} // expected-error@+1 {{this should be an error}} #error("this should be an error”) #if false #error("this shouldn't cause any errors") #endif // expected-error@+1 {{expected string literal in #error directive}}{{8-8="}}{{16-16="}} #error(test 123) test/Sema/pound_diagnostics.swift
  37. LIT // RUN: %target-typecheck-verify-swift // RUN: %target-swift-frontend -c -verify %s

    -o /dev/null #warning("this should be a warning”) // expected-warning {{this should be a warning}} // expected-error@+1 {{this should be an error}} #error("this should be an error”) #if false #error("this shouldn't cause any errors") #endif // expected-error@+1 {{expected string literal in #error directive}}{{8-8="}}{{16-16="}} #error(test 123) test/Sema/pound_diagnostics.swift
  38. LIT // RUN: %target-typecheck-verify-swift // RUN: %target-swift-frontend -c -verify %s

    -o /dev/null #warning("this should be a warning”) // expected-warning {{this should be a warning}} // expected-error@+1 {{this should be an error}} #error("this should be an error”) #if false #error("this shouldn't cause any errors") #endif // expected-error@+1 {{expected string literal in #error directive}}{{8-8="}}{{16-16="}} #error(test 123) test/Sema/pound_diagnostics.swift
  39. LIT // RUN: %target-typecheck-verify-swift // RUN: %target-swift-frontend -c -verify %s

    -o /dev/null #warning("this should be a warning”) // expected-warning {{this should be a warning}} // expected-error@+1 {{this should be an error}} #error("this should be an error”) #if false #error("this shouldn't cause any errors") #endif // expected-error@+1 {{expected string literal in #error directive}}{{8-8="}}{{16-16="}} #error(test 123) test/Sema/pound_diagnostics.swift
  40. LIT // RUN: %target-typecheck-verify-swift // RUN: %target-swift-frontend -c -verify %s

    -o /dev/null #warning("this should be a warning”) // expected-warning {{this should be a warning}} // expected-error@+1 {{this should be an error}} #error("this should be an error”) #if false #error("this shouldn't cause any errors") #endif // expected-error@+1 {{expected string literal in #error directive}}{{8-8="}}{{16-16="}} #error(test 123) test/Sema/pound_diagnostics.swift
  41. LIT // RUN: %target-typecheck-verify-swift // RUN: %target-swift-frontend -c -verify %s

    -o /dev/null #warning("this should be a warning”) // expected-warning {{this should be a warning}} // expected-error@+1 {{this should be an error}} #error("this should be an error”) #if false #error("this shouldn't cause any errors") #endif // expected-error@+1 {{expected string literal in #error directive}}{{8-8="}}{{16-16="}} #error(test 123) test/Sema/pound_diagnostics.swift
  42. Apparent Complexity A type of complex situation that appears complicated,

    but simple patterns lie underneath the surface.