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

Swift中間言語を読む

Avatar for matuyuji matuyuji
September 12, 2015

 Swift中間言語を読む

SIL (Swift Intermediate Language) を通してSwift内部の様子をちら見します。

Avatar for matuyuji

matuyuji

September 12, 2015
Tweet

More Decks by matuyuji

Other Decks in Technology

Transcript

  1. TXJGUDIFMQ $ swiftc --help OVERVIEW: Swift compiler USAGE: swiftc [options]

    <inputs> MODES: -dump-ast Parse and type-check input file(s) and dump AST(s) -dump-parse Parse input file(s) and dump AST(s) -dump-type-refinement-contexts Type-check input file(s) and dump type refinement contexts(s) -emit-assembly Emit assembly file(s) (-S) -emit-bc Emit LLVM BC file(s) -emit-executable Emit a linked executable -emit-ir Emit LLVM IR file(s) -emit-library Emit a linked library -emit-object Emit object file(s) (-c) -emit-sibgen Emit serialized AST + raw SIL file(s) -emit-sib Emit serialized AST + canonical SIL file(s) -emit-silgen Emit raw SIL file(s) -emit-sil Emit canonical SIL file(s) -parse Parse input file(s) -print-ast Parse and type-check input file(s) and pretty print AST(s)
  2. TXJGUDFNJUTJMHFO $ echo 'print("hello world!")' > hello.swift $ swiftc -emit-silgen

    hello.swift > hello.sil $ swiftc -parse-sil hello.sil $ ./hello hello world!
  3. $ grep -A 7 -B 4 hello hello.sil %11 =

    init_existential_addr %10 : $*protocol<>, $String // user: %18 // function_ref Swift.String.init (Swift.String.Type)(_builtinStringLitera %12 = function_ref @_TFSSCfMSSFT21_builtinStringLiteralBp8byteSizeBw7isASC %13 = metatype $@thin String.Type // user: %17 %14 = string_literal utf8 "hello world!" // user: %17 %15 = integer_literal $Builtin.Word, 12 // user: %17 %16 = integer_literal $Builtin.Int1, -1 // user: %17 %17 = apply %12(%14, %15, %16, %13) : $@convention(thin) (Builtin.RawPoint store %17 to %11 : $*String // id: %18 // function_ref Swift.(print (Swift.Array<protocol<>>, separator : Swift.S %19 = function_ref @_TIFSs5printFTGSaP__9separatorSS10terminatorSS_T_A0_ : %20 = apply %19() : $@convention(thin) () -> @owned String // user: %23 // pseudo code let p14 = "hello world!" let p15 = 12 let p16 = -1 let p17 = String.init(_builtinStringLiteral: p14, byteSize: p15, isASCII: p16) let p20 = print(p17)
  4. TXJGUD 4*- 4XJGU "45 --7. *3 TXJGU --7. #$ /BUJWF

    BTN TJM FNJUTJMHFO QBSTFTJM /BUJWF CJOBSZ
  5. --7. --7. 0QUJNJ[FS "3. #BDLFOE Y #BDLFOE $MBOH 'SPOUFOE 4XJGU

    'SPOUFOE $ $  0CK$ 4XJGU Y CJOBSZ "3. CJOBSZ 'SPOUFOE 0QUJNJ[FS #BDLFOE
  6. 4*-

  7. DPOE@CS bb0: : cond_br %9, bb1, bb2 // id: %11

    bb1: // Preds: bb0 // function_ref Swift.Bool.init (Swift.Bool.Type)(_builtinBooleanLiteral : Builtin %12 = function_ref @_TFSbCfMSbFT22_builtinBooleanLiteralBi1__Sb : $@convention(thi %13 = metatype $@thin Bool.Type // user: %15 %14 = integer_literal $Builtin.Int1, -1 // user: %15 %15 = apply %12(%14, %13) : $@convention(thin) (Builtin.Int1, @thin Bool.Type) -> br bb3(%15 : $Bool) // id: %16 bb2: // Preds: bb0 // function_ref Swift.Bool.init (Swift.Bool.Type)(_builtinBooleanLiteral : Builtin %17 = function_ref @_TFSbCfMSbFT22_builtinBooleanLiteralBi1__Sb : $@convention(thi %18 = metatype $@thin Bool.Type // user: %20 %19 = integer_literal $Builtin.Int1, 0 // user: %20 %20 = apply %17(%19, %18) : $@convention(thin) (Builtin.Int1, @thin Bool.Type) -> br bb3(%20 : $Bool) // id: %21 bb3(%22 : $Bool): // Preds: bb1 bb2 release_value %0 : $Array<Int> // id: %23 return %22 : $Bool // id: %24 if value { return true } else { return false }
  8. &MFNFOUDIFDL func exa_count(arr: [Int]) -> Bool { if arr.count >

    0 { return true } return false } func exa_empty(arr: [Int]) -> Bool { if !arr.isEmpty { return true } return false } func exa_first(arr: [Int]) -> Bool { if let _ = arr.first { return true } return false }
  9. DPVOU // function_ref static Swift.> infix (Swift.Int, Swift.Int) -> Swift.Bool

    %3 = function_ref @_TZFSsoi1gFTSiSi_Sb : $@convention(thin) (Int, Int) -> Bool // user: %10 // function_ref Swift.Array.count.getter : Swift.Int %4 = function_ref @_TFSag5countSi : $@convention(method) <ŵЮ0_0> (@guaranteed Array<ŵЮ0_0>) -> Int // user: %5 %5 = apply %4<Int>(%0) : $@convention(method) <ŵЮ0_0> (@guaranteed Array<ŵЮ0_0>) -> Int // user: %10 // function_ref Swift.Int.init (Swift.Int.Type) (_builtinIntegerLiteral : Builtin.Int2048) -> Swift.Int %6 = function_ref @_TFSiCfMSiFT22_builtinIntegerLiteralBi2048__Si : $@convention(thin) (Builtin.Int2048, @thin Int.Type) -> Int // user: %9 %7 = metatype $@thin Int.Type // user: %9 %8 = integer_literal $Builtin.Int2048, 0 // user: %9 %9 = apply %6(%8, %7) : $@convention(thin) (Builtin.Int2048, @thin Int.Type) -> Int // user: %10 %10 = apply %3(%5, %9) : $@convention(thin) (Int, Int) -> Bool // user: %11
  10. JT&NQUZ %2 = function_ref @_TFSb21_getBuiltinLogicValuefSbFT_Bi1_ : $@convention(method) (Bool) -> Builtin.Int1

    // user: %9 // function_ref static Swift.! prefix (Swift.Bool) -> Swift.Bool %3 = function_ref @_TZFSsop1nFSbSb : $@convention(thin) (Bool) -> Bool // user: %8 %4 = alloc_stack $Array<Int> // users: %5, %7, %10 store %0 to %4#1 : $*Array<Int> // id: %5 // function_ref ext.Swift.Swift.CollectionType<A where A: Swift.CollectionType>.isEmpty.getter : Swift.Bool %6 = function_ref @_TFeRq_Ss14CollectionType_SsS_g7isEmptySb : $@convention(method) <ŵЮ0_0 where ŵЮ0_0 : CollectionType, ŵЮ0_0.Generator : GeneratorType, ŵЮ0_0.Index : ForwardIndexType, ŵЮ0_0.Index.Distance : _SignedIntegerType, ŵЮ0_0.Index.Distance.IntegerLiteralType : _BuiltinIntegerLiteralConvertible, ŵЮ0_0.SubSequence : Indexable, ŵЮ0_0.SubSequence : SequenceType, ŵЮ0_0.SubSequence.Generator : GeneratorType, ŵЮ0_0.SubSequence.Index : ForwardIndexType, ŵЮ0_0.SubSequence.Index.Distance : _SignedIntegerType, ŵЮ0_0.SubSequence.Index.Distance.IntegerLiteralType : _BuiltinIntegerLiteralConvertible> (@in_guaranteed ŵЮ0_0) -> Bool // user: %7 %7 = apply %6<[Int], IndexingGenerator<Array<Int>>, Int, Int, Int, Int, Int, ArraySlice<Int>, IndexingGenerator<ArraySlice<Int>>, Int, Int, Int, Int, Int, ArraySlice<Int>, Int, Int>(%4#1) : $@convention(method) <ŵЮ0_0 where ŵЮ0_0 : CollectionType, ŵЮ0_0.Generator : GeneratorType, ŵЮ0_0.Index : ForwardIndexType, ŵЮ0_0.Index.Distance : _SignedIntegerType, ŵЮ0_0.Index.Distance.IntegerLiteralType : _BuiltinIntegerLiteralConvertible, ŵЮ0_0.SubSequence : Indexable, ŵЮ0_0.SubSequence : SequenceType, ŵЮ0_0.SubSequence.Generator : GeneratorType, ŵЮ0_0.SubSequence.Index : ForwardIndexType, ŵЮ0_0.SubSequence.Index.Distance : _SignedIntegerType, ŵЮ0_0.SubSequence.Index.Distance.IntegerLiteralType : _BuiltinIntegerLiteralConvertible> (@in_guaranteed ŵЮ0_0) -> Bool // user: %8 %8 = apply %3(%7) : $@convention(thin) (Bool) -> Bool // user: %9 %9 = apply %2(%8) : $@convention(method) (Bool) -> Builtin.Int1 // user: %11
  11. MB[Z let f = Foo() print(f.a) // 0 f.a =

    nil print(f.a) // 1 let g = Bar() print(g.a) // Optional(0) g.a = nil print(g.a) // nil class Foo { static var x: Int = 0 lazy var a: Int! = { return x++ }() } class Bar { static var x: Int = 0 lazy var a: Int? = { return x++ }() } SFJOJU
  12. MB[ZPQUJPOBM w lazyVTFTPQUJPOBMJOUFSOBMMZ class Foo { static var x: Int

    = 0 var lazy_a: Optional<Int!> var a: Int! { get { if self.lazy_a == nil { let v = { … }() self.lazy_a = .Some(.Some(v)) } return self.lazy_a } set { … } } }
  13. class Foo { static var x: Int = 0 var

    lazy_a: Optional<Int!> var a: Int! { set { switch newValue { case .None: self.lazy_a = nil case .Some(let v): self.lazy_a = .Some(.Some(v)) } } get { … } } } class Bar { static var x: Int = 0 var lazy_a: Optional<Int?> var a: Int? { set { self.lazy_a = .Some(newValue) } get { … } } }
  14. // main.Bar.a.setter : Swift.Optional<Swift.Int> sil hidden [transparent] @_TFC4main3Bars1bGSqSi_ : $@convention(method)

    (Optional<In bb0(%0 : $Optional<Int>, %1 : $Bar): debug_value %0 : $Optional<Int> // let value // id: %2 debug_value %1 : $Bar // let self // id: %3 %4 = enum $Optional<Optional<Int>>, #Optional.Some!enumelt.1, %0 : $Optional<Int> %5 = ref_element_addr %1 : $Bar, #Bar.a.storage // user: %6 store %4 to %5 : $*Optional<Optional<Int>> // id: %6 %7 = tuple () // user: %8 return %7 : $() // id: %8 }
  15. // main.Foo.a.setter : Swift.ImplicitlyUnwrappedOptional<Swift.Int> sil hidden [transparent] @_TFC4main3Foos1aGSQSi_ : $@convention(method)

    (ImplicitlyU bb0(%0 : $ImplicitlyUnwrappedOptional<Int>, %1 : $Foo): debug_value %0 : $ImplicitlyUnwrappedOptional<Int> // let value // id: %2 debug_value %1 : $Foo // let self // id: %3 %4 = integer_literal $Builtin.Int1, -1 // user: %6 %5 = integer_literal $Builtin.Int1, 0 // user: %6 %6 = select_enum %0 : $ImplicitlyUnwrappedOptional<Int>, case #ImplicitlyUnwrappedOptional.Some!enumelt.1: %4, default %5 : $Builtin.Int1 // user: %7 cond_br %6, bb1, bb3 // id: %7 bb1: // Preds: bb0 %8 = unchecked_enum_data %0 : $ImplicitlyUnwrappedOptional<Int>, #ImplicitlyUnwrap %9 = enum $ImplicitlyUnwrappedOptional<Int>, #ImplicitlyUnwrappedOptional.Some!enu %10 = enum $Optional<ImplicitlyUnwrappedOptional<Int>>, #Optional.Some!enumelt.1, br bb2(%10 : $Optional<ImplicitlyUnwrappedOptional<Int>>) // id: %11 bb2(%12 : $Optional<ImplicitlyUnwrappedOptional<Int>>): // Preds: bb1 bb3 %13 = ref_element_addr %1 : $Foo, #Foo.a.storage // user: %14 store %12 to %13 : $*Optional<ImplicitlyUnwrappedOptional<Int>> // id: %14 %15 = tuple () // user: %16 return %15 : $() // id: %16 bb3: // Preds: bb0 %17 = enum $Optional<ImplicitlyUnwrappedOptional<Int>>, #Optional.None!enumelt // br bb2(%17 : $Optional<ImplicitlyUnwrappedOptional<Int>>) // id: %18 }
  16. get { // main.Foo.a.getter let val: Int! if self.lazy_a !=

    nil { // bb0 switch self.lazy_a {// bb1 case .Some(let v): // bb2 val = v // bb5 case .None: // bb3, bb4 fatalError("unexpectedly found nil while unwrapping an Optional value") } } else { // bb6 let v = { return Foo.x++ }() val = .Some(v) let tmp: Optional<Int!> switch val { case .Some: // bb7 tmp = .Some(.Some(val)) case .None: // bb9 tmp = .None } self.lazy_a = tmp // bb8 } return val // bb10 }