Cookpad Spring Intern 2019 - Swiftコンパイラ -

011714704c4a925e542d426d4cdaa4e3?s=47 giginet
March 28, 2019

Cookpad Spring Intern 2019 - Swiftコンパイラ -

011714704c4a925e542d426d4cdaa4e3?s=128

giginet

March 28, 2019
Tweet

Transcript

  1. Cookpad Spring Internship 2019 Swi$ίϯύΠϥίʔε 1

  2. ؀ڥߏஙऴΘͬͯͳ͍ਓ • ! • ͕͔͔࣌ؒΔͷͰߨٛΛฉ͖ͳ͕ΒΠϯετʔϧ͠·͠ΐ͏ • h#ps:/ /github.com/giginet/MinSwi6-workshop/blob/master/ bootstrap.md 2

  3. Agenda • 10:00 ~ 10:15 ! ձࣾ঺հ • 10:15 ~

    11:00 " ߨٛ • 11:00 ~ 13:00 # ϫʔΫγϣοϓޕલͷ෦ • 13:00 ~ 14:00 $ ϥϯν • 14:00 ~ 17:00 # ϫʔΫγϣοϓޕޙͷ෦ • 17:00 ~ 18:00 % ੒Ռൃදձ 3
  4. ୭ @giginet • ϞόΠϧج൫෦ • ๺ւಓവؗࢢग़਎ɹ • ๺ւಓେֶ৘ใՊֶݚڀՊଔ • 2015೥৽ଔೖࣾ

    • Core Contributor of Carthage/fastlane 4
  5. ࿩͢͜ͱ • ΦʔϓϯιʔεSwi%ͷݱঢ়ͱߏ੒ • LLVMೖ໳ • LLVM IRೖ໳ • MinSwi%

    Workshop 5
  6. swi$c • Swi%ίϯύΠϥ • Φʔϓϯιʔε h"ps:/ /github.com/apple/swi4 6

  7. Θ͍Θ͍swi$c 7

  8. h"ps:/ /academy.realm.io/jp/posts/tryswi5-jesse-squires-contribu;ng-open-source-swi5/ 8

  9. swi$c • ͍͔ͭ͘ͷαϒγεςϜʹΘ͔ΕΔ • શͯΛ೺Ѳ͢Δͷ͸೉͍͠ h"ps:/ /swi).org/compiler-stdlib/#compiler-architecture 9

  10. Parser • ࣈ۟ղੳΛߦͬͯASTʹม׵͢Δ • ͜ͷ࣌఺Ͱ͸ҙຯղੳ͸ߦ͍ͬͯͳ͍ɻܕ৘ใ΋ͳ͍ • h&ps:/ /github.com/apple/swi8/tree/master/lib/Parse 10

  11. Sema • ҙຯղੳ(Seman$c Analysis) • ܕਪ࿦ͳͲΛߦ͍ɺܕ৘ใ෇͖ͷASTʹม׵͢Δ • h1ps:/ /github.com/apple/swi>/tree/master/lib/Sema 11

  12. SIL • Swi% Intermediate Language • SIL is an SSA-form

    IR with high-level seman;c informa;on designed to implement the Swi% programming language • Swi%ίϯύΠϥ͕ੜ੒͢Δதؒݴޠ • h>ps:/ /github.com/apple/swi%/blob/master/docs/SIL.rst 12
  13. IRGen • SILΛLLVM IRʹม׵͢Δ • ͋ͱ͸LLVMόοΫΤϯυʹΑͬͯॲཧ͞ΕΔ 13

  14. LLVMʁ 14

  15. LLVMͱ͸ • ίϯύΠϥج൫ • ݱࡏͷίϯύΠϥ͸શͯΛ࣮૷͢Δʹ͸ෳࡶ͗͢ΔͷͰɺػցޠͷੜ੒΍࠷దԽͳͲΛڞ௨Խͯ͠࡞ΕΔΑ͏ʹͨ͠ ࢓૊Έ • ଟ͘ͷݴޠͷίϯύΠϥ͕LLVM IRΛੜ੒͢ΔLLVM Frontendͱ࣮ͯ͠૷͞Ε͍ͯΔ

    15
  16. ͖ͭͶ͞ΜͰ΋Θ͔ΔLLVM P8ΑΓ 16

  17. LLVM frontend • ιʔείʔυΛߏจղੳͯ͠LLVM IRΛੜ੒͢Δ΋ͷ • swi+cͰ͸IRGen·Ͱ͕͜͜ʹ૬౰ 17

  18. LLVM IR • LLVM Intermediate Representa2on • ͲͷݴޠͰ͋ͬͯ΋LLVM IRʹม׵͢Δ͜ͱͰLLVMͷج൫ʹ৐ ΕΔ

    18
  19. #include <stdio.h> int main(void) { printf("Hello World"); return 0; }

    $ clang -S -emit-llvm hello.c 19
  20. ; ModuleID = 'hello.c' source_filename = "hello.c" target datalayout =

    "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.14.0" @.str = private unnamed_addr constant [12 x i8] c"Hello World\00", align 1 ; Function Attrs: noinline nounwind optnone ssp uwtable define i32 @main() #0 { %1 = alloca i32, align 4 store i32 0, i32* %1, align 4 %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 !llvm.module.flags = !{!0, !1} !llvm.ident = !{!2} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{i32 7, !"PIC Level", i32 2} !2 = !{!"Apple LLVM version 10.0.0 (clang-1000.11.45.5)"} 20
  21. ; ModuleID = 'hello.c' source_filename = "hello.c" target datalayout =

    "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.14.0" @.str = private unnamed_addr constant [12 x i8] c"Hello World\00", align 1 ; Function Attrs: noinline nounwind optnone ssp uwtable define i32 @main() #0 { %1 = alloca i32, align 4 store i32 0, i32* %1, align 4 %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 !llvm.module.flags = !{!0, !1} !llvm.ident = !{!2} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{i32 7, !"PIC Level", i32 2} !2 = !{!"Apple LLVM version 10.0.0 (clang-1000.11.45.5)"} 20
  22. Pass • LLVM IRʹԿΒ͔ͷॲཧΛߦ͏΋ͷ • ࠷దԽͳͲ 21

  23. 22

  24. LLVM backend • LLVM IRΛॲཧͯ͠ग़ྗ͢Δ΍ͭ • ΞηϯϒϦ • ࣮ߦΦϒδΣΫτ •

    JITίϯύΠϧͰͷ࣮ߦ • ଞͷݴޠͷίʔυੜ੒ • ͱͯ΋೉͍͠ 23
  25. LLVMΛษڧ͢Δ • LLVM Tutorial(Kaleidoscope) • h7ps:/ /llvm.org/docs/tutorial/index.html • h7ps:/ /github.com/sonsongithub/llvm-tutorial

    • ͖ͭͶ͞ΜͰ΋Θ͔ΔLLVM • LLVM Cookbook 24
  26. LLVM IRೖ໳ 25

  27. LLVM IR define i32 @main() { ret i32 42 }

    26
  28. int main(void) { return 42; } $ clang -S -emit-llvm

    hello.c 27
  29. int main(void) { int a = 10; int b =

    20; return a + b; } 28
  30. define i32 @main() #0 { %1 = alloca i32, align

    4 %2 = alloca i32, align 4 %3 = alloca i32, align 4 store i32 0, i32* %1, align 4 store i32 10, i32* %2, align 4 store i32 20, i32* %3, align 4 %4 = load i32, i32* %2, align 4 %5 = load i32, i32* %3, align 4 %6 = add nsw i32 %4, %5 ret i32 %6 } 29
  31. define i32 @main() #0 { %1 = alloca i32, align

    4 %2 = alloca i32, align 4 %3 = alloca i32, align 4 store i32 0, i32* %1, align 4 store i32 10, i32* %2, align 4 store i32 20, i32* %3, align 4 %4 = load i32, i32* %2, align 4 %5 = load i32, i32* %3, align 4 %6 = add nsw i32 %4, %5 ret i32 %6 } 29
  32. define i32 @main() #0 { %1 = alloca i32, align

    4 %2 = alloca i32, align 4 %3 = alloca i32, align 4 store i32 0, i32* %1, align 4 store i32 10, i32* %2, align 4 store i32 20, i32* %3, align 4 %4 = load i32, i32* %2, align 4 %5 = load i32, i32* %3, align 4 %6 = add nsw i32 %4, %5 ret i32 %6 } 29
  33. define i32 @main() #0 { %1 = alloca i32, align

    4 %2 = alloca i32, align 4 %3 = alloca i32, align 4 store i32 0, i32* %1, align 4 store i32 10, i32* %2, align 4 store i32 20, i32* %3, align 4 %4 = load i32, i32* %2, align 4 %5 = load i32, i32* %3, align 4 %6 = add nsw i32 %4, %5 ret i32 %6 } 29
  34. define i32 @main() #0 { %1 = alloca i32, align

    4 %2 = alloca i32, align 4 %3 = alloca i32, align 4 store i32 0, i32* %1, align 4 store i32 10, i32* %2, align 4 store i32 20, i32* %3, align 4 %4 = load i32, i32* %2, align 4 %5 = load i32, i32* %3, align 4 %6 = add nsw i32 %4, %5 ret i32 %6 } 29
  35. define i32 @main() #0 { %1 = alloca i32, align

    4 %2 = alloca i32, align 4 %3 = alloca i32, align 4 store i32 0, i32* %1, align 4 store i32 10, i32* %2, align 4 store i32 20, i32* %3, align 4 %4 = load i32, i32* %2, align 4 %5 = load i32, i32* %3, align 4 %6 = add nsw i32 %4, %5 ret i32 %6 } 29
  36. SSA(੩త୯Ұ୅ೖࣜ) • ֤ม਺͕1౓͔͠มߋ͞Εͳ͍͜ͱΛอূͨ͠ॻࣜ • ͜ΕͩͱҰ൪্ͷ୅ೖ͕ҙຯΛ੒͞ͳ͍͜ͱΛύοͱ൑ఆͰ͖ ͳ͍ y := 1 y

    := 2 x := y 30
  37. SSA(੩త୯Ұ୅ೖࣜ) • ࠶୅ೖ͢Δͱ͖ʹผ໊Λ෇͚ͯόʔδϣχϯά • ͋ͱ͔Βy1͕ࢀর͞Εͳ͍ͷͰɺ࠷ॳͷ୅ೖ͕ແҙຯͳ͜ͱ͕ ൑ఆ͠΍͍͢ y1 := 1 y2

    := 2 x1 := y2 31
  38. LLVM IRͷಛ௃ • 1ͭͷIR͔Β͞·͟·ͳCPU޲͚ͷ੒Ռ෺Λੜ੒Ͱ͖Δ • ΞʔΩςΫνϟͷҧ͍Λҙࣝ͢Δඞཁ͕ݮΔ • ࠷దԽͷ࢓૊Έ͕͋Δ 32

  39. LLVM IRͷ࠷దԽ • 10 + 20 = 30͸ίϯύΠϧ࣌ʹܭࢉՄೳ • ࠷దԽΦϓγϣϯ

    -O3 int main(void) { int a = 10; int b = 20; return a + b; } $ clang -S -O3 -emit-llvm ssa.c -o ssa03.ll 33
  40. define i32 @main() local_unnamed_addr #0 { ret i32 30 }

    34
  41. func main() -> Int { let a = 10 let

    b = 20 return a + b } $ swiftc -emit-ir hello.swift > hello2.ll 35
  42. ; ModuleID = '-' source_filename = "-" target datalayout =

    "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.14.0" @__swift_reflection_version = linkonce_odr hidden constant i16 3 @llvm.used = appending global [1 x i8*] [i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata", align 8 define i32 @main(i32, i8**) #0 { entry: %2 = bitcast i8** %1 to i8* ret i32 0 } define hidden swiftcc i64 @"$S3ssa4mainSiyF"() #0 { entry: ret i64 30 } attributes #0 = { "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" } !llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7} !llvm.linker.options = !{!8, !9, !10} !llvm.asan.globals = !{!11} !0 = !{i32 1, !"Objective-C Version", i32 2} !1 = !{i32 1, !"Objective-C Image Info Version", i32 0} !2 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} !3 = !{i32 4, !"Objective-C Garbage Collection", i32 1536} !4 = !{i32 1, !"Objective-C Class Properties", i32 64} !5 = !{i32 1, !"wchar_size", i32 4} !6 = !{i32 7, !"PIC Level", i32 2} !7 = !{i32 1, !"Swift Version", i32 6} !8 = !{!"-lswiftSwiftOnoneSupport"} !9 = !{!"-lswiftCore"} !10 = !{!"-lobjc"} !11 = !{[1 x i8*]* @llvm.used, null, null, i1 false, i1 true} 36
  43. Workshop 37

  44. Workshop • 1೔ͰSwi&Λ࡞Δͷ͸ෆՄೳʢͦΕ͸ͦ͏ʣ • Swi&Λ࢖ͬͯSwi&͔ΒόΠφϦΛੜ੒͢ΔMinSwi&Λ࡞ͬͯΈ Δ • ཁ͸LLVMϑϩϯτΤϯυΛSwi&Ͱ࣮૷͢Δ 38

  45. h"ps:/ /github.com/giginet/ MinSwi5-workshop 39

  46. MinSwi& 1. Swi&ͷίʔυΛύʔε 2. Abstract Syntax Treeʹม׵ 3. LLVM IRΛੜ੒

    4. Ϗϧυͯ͠όΠφϦΛੜ੒ 5. Swi&͔ΒϦϯΫ࣮ͯ͠ߦ 40
  47. ߏ੒ • MinSwi'Kit • minswi' • MinSwi'KitTests 41

  48. MinSwi&Kit • MinSwi'ຊମ • ͜Ε͔Β࣮૷͍ͯ͘͠ 42

  49. minswi& • CLIͷλʔήοτ • MinSwi*KitΛ࣮ߦ͢ΔͨΊͷΠϯλʔϑΣΠεΛఏڙ 43

  50. MinSwi&KitTests • MinSwi'Kitͷςετέʔε • ࠓճ͸՝୊͕༻ҙ͞Ε͍ͯΔ • ͜ͷςετέʔε͕௨ΔΑ͏ʹ࣮૷͍ͯ͘͠ 44

  51. dependencies • apple/Swi*Syntax • llvm-swi*/LLVMSwi* • llvm-swi*/FileCheck 45

  52. Swi$Syntax • libSyntaxͷϥούʔ • h,ps:/ /github.com/apple/swi9/tree/master/lib/Syntax • ੩తղੳπʔϧͳͲʹ࢖ΘΕ͍ͯΔ • ύʔαʔͷ࣮૷ʹར༻

    46
  53. LLVMSwi' • libLLVMͷϥούʔ • LLVM IRͷੜ੒ʹར༻ • Swi-ͬΆ͍APIͰLLVM IRΛهड़Ͱ͖Δ 47

  54. FileCheck • LLVMͷఏڙ͢ΔFileCheckͷϥούʔ • IRੜ੒ͷςετέʔεهड़ʹར༻ • ՝୊தʹग़ͯ͘Δ 48

  55. Swi$PM • ϥΠϒϥϦ΍λʔήοτΛSwi%PM(Swi% Package Manager)Ͱ ؅ཧ • XcodeϓϩδΣΫτ΋Swi%PM͔Βੜ੒ 49

  56. // swift-tools-version:4.2 // The swift-tools-version declares the minimum version of

    Swift required to build this package. import PackageDescription let package = Package( name: "MinSwift", products: [ // Products define the executables and libraries produced by a package, and make them visible to other packages. .library( name: "MinSwiftKit", targets: ["MinSwiftKit"]) ], dependencies: [ .package(url: "https://github.com/apple/swift-syntax.git", .exact("0.40200.0")), .package(url: "https://github.com/llvm-swift/LLVMSwift.git", from: "0.4.0"), .package(url: "https://github.com/llvm-swift/FileCheck.git", from: "0.0.3") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages which this package depends on. .target(name: "minswift", dependencies: ["MinSwiftKit"]), .target( name: "MinSwiftKit", dependencies: ["SwiftSyntax", "LLVM"]), .testTarget( name: "MinSwiftKitTests", dependencies: ["MinSwiftKit", "FileCheck"]) ] ) 50
  57. $ swift package generate-xcodeproj --xcconfig-overrides Settings.xcconfig 51

  58. $ git clone https://github.com/giginet/MinSwift-workshop.git $ cd MinSwift-workshop h"ps:/ /github.com/giginet/MinSwi5-workshop/blob/master/ bootstrap.md

    52
  59. $ cat ./bootstrap $ ./bootstrap $ open MinSwift.xcodeproj 53

  60. • λʔήοτΛMinSwift-Packageʹ͢Δ • Ϣχοτςετͷ࣮ߦ • ⌘ + U 54

  61. ϫʔΫγϣοϓͷਐΊํ • ςετέʔε͕௨ΔΑ͏ʹMinSwi'Λ࣮૷͍ͯ͘͠ • MinSwi'KitTests/Prac2ce[1-8].swi' • ղઆ͕͋ΔͷͰಡΉ • handouts/prac2ce[1-8].md 55

  62. 56

  63. Prac%ce 1 ύʔαʔͷ࣮૷جຊฤ • Prac&ce 1Ͱ͸ɺSwi-ͷιʔεΛಡΈऔΔύʔαʔͷجૅΛ࡞Γ ·͢ • Swi-SyntaxΛ࢖ͬͯɺιʔεΛτʔΫϯʹ෼ׂ͢Δํ๏ͱɺ ύʔαʔΛॻ͍͍ͯͨ͘ΊͷϢʔςΟϦςΟΛ࡞Γ·͠ΐ͏

    57
  64. 58

  65. 59

  66. 60

  67. 61

  68. 62

  69. 63

  70. Mentors Θ͔Μͳ͔ͬͨΒั·͑ͯฉ͖·͠ΐ͏ 64

  71. ͔͜͜Β͸ϫʔΫγϣοϓͰ͢ Good Luck 65