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

Swift中間言語を読む

matuyuji
September 12, 2015

 Swift中間言語を読む

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

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 }