swift編譯淺析


//
//  main.swift
//  swiftstudy
//
//  Created by GitArtOS on 2021/1/19.
//

import Foundation

print("Hello, World!")

class SHTest {
    var name = "hello"
    var size = 10.5
    var height = 13.4
}

let test1 = SHTest()


1. 編譯器介紹

swift的編譯器是swiftc

1.1 編譯歷程

SwiftCode源碼->通過詞法分析、語法分析(-dump-parse)->生成AST抽象語法樹(-dump-ast)->通過SILGen生成未優化代碼量巨大的RawSIL文件(-emit-silgen)->再拿到優化後更簡潔的Canonical SIL(-emit-sil)->通過IRGen生成IR(-emit-ir)->最終生成二進制代碼

輸入swiftc -h可以看到如下:

OVERVIEW: Swift compiler

USAGE: swiftc

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-pcm              Dump debugging information about a precompiled Clang module
  -dump-scope-maps <expanded-or-list-of-line:column>
                         Parse and type-check input file(s) and dump the scope map(s)
  -dump-type-info        Output YAML dump of fixed-size types from all imported modules
  -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-imported-modules Emit a list of the imported modules
  -emit-ir               Emit LLVM IR file(s)
  -emit-library          Emit a linked library
  -emit-object           Emit object file(s) (-c)
  -emit-pcm              Emit a precompiled Clang module from a module map
  -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)
  -index-file            Produce index data for a source file
  -parse                 Parse input file(s)
  -print-ast             Parse and type-check input file(s) and pretty print AST(s)
  -resolve-imports       Parse and resolve imports in input file(s)
  -typecheck             Parse and type-check input file(s)

OPTIONS:
  -api-diff-data-dir <path>
                          Load platform and version specific API migration data files from <path>. Ignored if -api-diff-data-file is specified.
  -api-diff-data-file <path>
                          API migration data is from <path>
  -application-extension  Restrict code to those available for App Extensions
  -assert-config <value>  Specify the assert_configuration replacement. Possible values are Debug, Release, Unchecked, DisableReplacement.
  -avoid-emit-module-source-info
                          don't emit Swift source info file
  -color-diagnostics      Print diagnostics in color
  -continue-building-after-errors
                          Continue building, even after errors are encountered
  -debug-info-format=<value>
                          Specify the debug info format type to either 'dwarf' or 'codeview'
  -debug-info-store-invocation
                          Emit the compiler invocation in the debug info.
  -debug-prefix-map <value>
                          Remap source paths in debug info
  -disable-astscope-lookup
                          Disable ASTScope-based unqualified name lookup
  -disable-autolinking-runtime-compatibility-dynamic-replacements
                          Do not use autolinking for the dynamic replacement runtime compatibility library
  -disable-autolinking-runtime-compatibility
                          Do not use autolinking for runtime compatibility libraries
  -disable-migrator-fixits
                          Disable the Migrator phase which automatically applies fix-its
  -disable-only-one-dependency-file
                          Disables incremental build optimization that only produces one dependencies file
  -disable-parser-lookup  Disable parser lookup & use ast scope lookup only (experimental)
  -driver-compare-incremental-schemes-path <path>
                          Path to use for machine-readable comparision
  -driver-compare-incremental-schemes
                          Print a simple message comparing dependencies with source ranges (w/ fallback)
  -driver-time-compilation
                          Prints the total time it took to execute all compilation tasks
  -dump-migration-states-dir <path>
                          Dump the input text, output text, and states for migration to <path>
  -dump-usr               Dump USR for each declaration reference
  -D <value>              Marks a conditional compilation flag as true
  -embed-bitcode-marker   Embed placeholder LLVM IR data as a marker
  -embed-bitcode          Embed LLVM IR bitcode as data
  -emit-dependencies      Emit basic Make-compatible dependencies files
  -emit-loaded-module-trace-path <path>
                          Emit the loaded module trace JSON to <path>
  -emit-loaded-module-trace
                          Emit a JSON file containing information about what modules were loaded
  -emit-module-interface-path <path>
                          Output module interface file to <path>
  -emit-module-interface  Output module interface file
  -emit-module-path <path>
                          Emit an importable module to <path>
  -emit-module-source-info-path <path>
                          Output module source info file to <path>
  -emit-module            Emit an importable module
  -emit-objc-header-path <path>
                          Emit an Objective-C header file to <path>
  -emit-objc-header       Emit an Objective-C header file
  -emit-tbd-path <path>   Emit the TBD file to <path>
  -emit-tbd               Emit a TBD file
  -enable-astscope-lookup Enable ASTScope-based unqualified name lookup
  -enable-experimental-concise-pound-file
                          Enable experimental concise '#file' identifier and '#filePath' alternative
  -enable-experimental-differentiable-programming
                          Enable experimental differentiable programming features
  -enable-library-evolution
                          Build the module to allow binary-compatible library evolution
  -enable-only-one-dependency-file
                          Enables incremental build optimization that only produces one dependencies file
  -enable-source-range-dependencies
                          Try using source range information
  -enforce-exclusivity=<enforcement>
                          Enforce law of exclusivity
  -fixit-all              Apply all fixits from diagnostics without any filtering
  -framework <value>      Specifies a framework which should be linked against
  -Fsystem <value>        Add directory to system framework search path
  -F <value>              Add directory to framework search path
  -gdwarf-types           Emit full DWARF type info.
  -gline-tables-only      Emit minimal debug info for backtraces only
  -gnone                  Don't emit debug info
  -g                      Emit debug info. This is the preferred setting for debugging with LLDB.
  -help                   Display available options
  -import-underlying-module
                          Implicitly imports the Objective-C half of a module
  -index-file-path <path> Produce index data for file <path>
  -index-ignore-system-modules
                          Avoid indexing system modules
  -index-store-path <path>
                          Store indexing data to <path>
  -I <value>              Add directory to the import search path
  -j <n>                  Number of commands to execute in parallel
  -libc <value>           libc runtime library to use
  -L <value>              Add directory to library link search path
  -l<value>               Specifies a library which should be linked against
  -migrate-keep-objc-visibility
                          When migrating, add '@objc' to declarations that would've been implicitly visible in Swift 3
  -migrator-update-sdk    Does nothing. Temporary compatibility flag for Xcode.
  -migrator-update-swift  Does nothing. Temporary compatibility flag for Xcode.
  -module-cache-path <value>
                          Specifies the Clang module cache path
  -module-link-name <value>
                          Library to link against when using this module
  -module-name <value>    Name of the module to build
  -no-color-diagnostics   Do not print diagnostics in color
  -nostdimport            Don't search the standard library import path for modules
  -num-threads <n>        Enable multi-threading and specify number of threads
  -Onone                  Compile without any optimization
  -Osize                  Compile with optimizations and target small code size
  -Ounchecked             Compile with optimizations and remove runtime safety checks
  -output-file-map <path> A file which specifies the location of outputs
  -O                      Compile with optimizations
  -o <file>               Write output to <file>
  -parse-as-library       Parse the input file(s) as libraries, not scripts
  -parse-sil              Parse the input file as SIL code, not Swift source
  -parseable-output       Emit textual output in a parseable format
  -print-target-info      Print target information for the given target <triple>, such as x86_64-apple-macos10.9
  -profile-coverage-mapping
                          Generate coverage data for use with profiled execution counts
  -profile-generate       Generate instrumented code to collect execution counts
  -profile-use=<profdata> Supply a profdata file to enable profile-guided optimization
  -remove-runtime-asserts Remove runtime safety checks.
  -require-explicit-availability-target <target>
                          Suggest fix-its adding @available(<target>, *) to public declarations without availability
  -require-explicit-availability
                          Require explicit availability on public declarations
  -Rpass-missed=<value>   Report missed transformations by optimization passes whose name matches the given POSIX regular expression
  -Rpass=<value>          Report performed transformations by optimization passes whose name matches the given POSIX regular expression
  -runtime-compatibility-version <value>
                          Link compatibility library for Swift runtime version, or 'none'
  -sanitize-coverage=<type>
                          Specify the type of coverage instrumentation for Sanitizers and additional options separated by commas
  -sanitize-recover=<check>
                          Specify which sanitizer runtime checks (see -sanitize=) will generate instrumentation that allows error recovery. Listed checks should be comma separated. Default behavior is to not allow error recovery.
  -sanitize=<check>       Turn on runtime checks for erroneous behavior.
  -save-optimization-record-path <value>
                          Specify the file name of any generated YAML optimization record
  -save-optimization-record
                          Generate a YAML optimization record file
  -save-temps             Save intermediate compilation results
  -sdk <sdk>              Compile against <sdk>
  -serialize-diagnostics  Serialize diagnostics in a binary format
  -static-executable      Statically link the executable
  -static-stdlib          Statically link the Swift standard library
  -static                 Make this module statically linkable and make the output of -emit-library a static library.
  -suppress-warnings      Suppress all warnings
  -swift-version <vers>   Interpret input according to a specific Swift language version number
  -target-cpu <value>     Generate code for a particular CPU variant
  -target-variant <value> Generate code that may run on a particular variant of the  deployment target
  -target <triple>        Generate code for the given target <triple>, such as x86_64-apple-macos10.9
  -tools-directory <directory>
                          Look for external executables (ld, clang, binutils) in <directory>
  -track-system-dependencies
                          Track system dependencies while emitting Make-style dependencies
  -use-ld=<value>         Specifies the linker to be used
  -verify-debug-info      Verify the binary representation of debug output.
  -version                Print version information and exit
  -vfsoverlay <value>     Add directory to VFS overlay file
  -v                      Show commands to run and use verbose output
  -warn-implicit-overrides
                          Warn about implicit overrides of protocol members
  -warn-swift3-objc-inference-complete
                          Warn about deprecated @objc inference in Swift 3 for every declaration that will no longer be inferred as @objc in Swift 4
  -warn-swift3-objc-inference-minimal
                          Warn about deprecated @objc inference in Swift 3 based on direct uses of the Objective-C entrypoint
  -warnings-as-errors     Treat warnings as errors
  -whole-module-optimization
                          Optimize input files together instead of individually
  -working-directory <path>
                          Resolve file paths relative to the specified directory
  -Xcc <arg>              Pass <arg> to the C/C++/Objective-C compiler
  -Xlinker <value>        Specifies an option which should be passed to the linker

SEE ALSO: swift build, swift run, swift package, swift test 

其中主要的命令是:
-dump-ast    語法和類型檢查,打印AST語法樹
-dump-parse    語法檢查,打印AST語法樹
-dump-pcm    轉儲有關預編譯Clang模塊的調試信息
-dump-scope-maps <expanded-or-list-of-line:column>    Parse and type-check input file(s) and dump the scope map(s)
-dump-type-info    Output YAML dump of fixed-size types from all imported modules
-dump-type-refinement-contexts    Type-check input file(s) and dump type refinement contexts(s)
-emit-assembly    輸出彙編文件 (-S)
-emit-bc    輸出一個LLVM的BC文件
-emit-executable    輸出一個可執行文件
-emit-imported-modules    展示導入的模塊列表
-emit-ir    展示IR中間代碼
-emit-library    輸出一個dylib動態庫
-emit-object    輸出一個.o機器文件
-emit-pcm    從模塊映射中輸出預編譯Clang模塊
-emit-sibgen    輸出一個.sib的原始SIL文件
-emit-sib    輸出一個.sib的標準SIL文件
-emit-silgen    展示原始SIL文件
-emit-sil    展示標準的SIL文件
-index-file    爲源文件生成索引數據
-parse    解析文件
-print-ast    解析文件並打印(漂亮/簡潔的)語法樹
-resolve-imports    解析import導入的文件
-typecheck    檢查文件類型
1.2 通過詞法分析、語法分析 swiftc -dump-parse main.swift
➜  swiftstudy swiftc -dump-parse main.swift
(source_file "main.swift"
  (import_decl range=[main.swift:8:1 - line:8:8] 'Foundation')
  (top_level_code_decl range=[main.swift:10:1 - line:10:22]
    (brace_stmt range=[main.swift:10:1 - line:10:22]
      (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!" builtin_initializer=**NULL** initializer=**NULL**)))))
  (class_decl range=[main.swift:12:1 - line:16:1] "SHTest"
    (pattern_binding_decl range=[main.swift:13:5 - line:13:16]
      (pattern_named 'name')
      Original init:
      (string_literal_expr type='<null>' encoding=utf8 value="hello" builtin_initializer=**NULL** initializer=**NULL**)
      Processed init:
      (string_literal_expr type='<null>' encoding=utf8 value="hello" builtin_initializer=**NULL** initializer=**NULL**))
    (var_decl range=[main.swift:13:9 - line:13:9] "name" type='<null type>' readImpl=stored writeImpl=stored readWriteImpl=stored)
    (pattern_binding_decl range=[main.swift:14:5 - line:14:16]
      (pattern_named 'size')
      Original init:
      (float_literal_expr type='<null>' value=10.5 builtin_initializer=**NULL** initializer=**NULL**)
      Processed init:
      (float_literal_expr type='<null>' value=10.5 builtin_initializer=**NULL** initializer=**NULL**))
    (var_decl range=[main.swift:14:9 - line:14:9] "size" type='<null type>' readImpl=stored writeImpl=stored readWriteImpl=stored)
    (pattern_binding_decl range=[main.swift:15:5 - line:15:18]
      (pattern_named 'height')
      Original init:
      (float_literal_expr type='<null>' value=13.4 builtin_initializer=**NULL** initializer=**NULL**)
      Processed init:
      (float_literal_expr type='<null>' value=13.4 builtin_initializer=**NULL** initializer=**NULL**))
    (var_decl range=[main.swift:15:9 - line:15:9] "height" type='<null type>' readImpl=stored writeImpl=stored readWriteImpl=stored))
  (top_level_code_decl range=[main.swift:18:1 - line:18:20]
    (brace_stmt implicit range=[main.swift:18:1 - line:18:20]
      (pattern_binding_decl range=[main.swift:18:1 - line:18:20]
        (pattern_named 'test1')
        Original init:
        (call_expr type='<null>' arg_labels=
          (unresolved_decl_ref_expr type='<null>' name=SHTest function_ref=unapplied)
          (tuple_expr type='()' location=main.swift:18:19 range=[main.swift:18:19 - line:18:20]))
        Processed init:
        (call_expr type='<null>' arg_labels=
          (unresolved_decl_ref_expr type='<null>' name=SHTest function_ref=unapplied)
          (tuple_expr type='()' location=main.swift:18:19 range=[main.swift:18:19 - line:18:20])))
))
  (var_decl range=[main.swift:18:5 - line:18:5] "test1" type='<null type>' let readImpl=stored immutable))

1.3 生成AST抽象語法樹(-dump-ast)
➜  swiftstudy swiftc -dump-ast main.swift  
(source_file "main.swift"
  (import_decl range=[main.swift:8:1 - line:8:8] 'Foundation')
  (top_level_code_decl range=[main.swift:10:1 - line:10:22]
    (brace_stmt range=[main.swift:10:1 - line:10:22]
      (call_expr type='()' location=main.swift:10:1 range=[main.swift:10:1 - line:10:22] nothrow arg_labels=_:
        (declref_expr type='(Any..., String, String) -> ()' location=main.swift:10:1 range=[main.swift:10:1 - line:10:1] decl=Swift.(file).print(_:separator:terminator:) function_ref=single)
        (tuple_expr implicit type='(Any..., separator: String, terminator: String)' location=main.swift:10:6 range=[main.swift:10:6 - line:10:22] names='',separator,terminator
          (vararg_expansion_expr implicit type='[Any]' location=main.swift:10:7 range=[main.swift:10:7 - line:10:7]
            (array_expr implicit type='[Any]' location=main.swift:10:7 range=[main.swift:10:7 - line:10:7] initializer=**NULL**
              (erasure_expr implicit type='Any' location=main.swift:10:7 range=[main.swift:10:7 - line:10:7]
                (string_literal_expr type='String' location=main.swift:10:7 range=[main.swift:10:7 - line:10:7] encoding=utf8 value="Hello, World!" builtin_initializer=Swift.(file).String extension.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) initializer=**NULL**))))
          (default_argument_expr implicit type='String' location=main.swift:10:6 range=[main.swift:10:6 - line:10:6] default_args_owner=Swift.(file).print(_:separator:terminator:) param=1)
          (default_argument_expr implicit type='String' location=main.swift:10:6 range=[main.swift:10:6 - line:10:6] default_args_owner=Swift.(file).print(_:separator:terminator:) param=2)))))
  (class_decl range=[main.swift:12:1 - line:16:1] "SHTest" interface type='SHTest.Type' access=internal non-resilient
    (pattern_binding_decl range=[main.swift:13:5 - line:13:16]
      (pattern_named type='String' 'name')
      Original init:
      (string_literal_expr type='String' location=main.swift:13:16 range=[main.swift:13:16 - line:13:16] encoding=utf8 value="hello" builtin_initializer=Swift.(file).String extension.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) initializer=**NULL**)
      Processed init:
      (string_literal_expr type='String' location=main.swift:13:16 range=[main.swift:13:16 - line:13:16] encoding=utf8 value="hello" builtin_initializer=Swift.(file).String extension.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) initializer=**NULL**))
    (var_decl range=[main.swift:13:9 - line:13:9] "name" type='String' interface type='String' access=internal readImpl=stored writeImpl=stored readWriteImpl=stored
      (accessor_decl implicit range=[main.swift:13:9 - line:13:9] 'anonname=0x7f80ee150a90' interface type='(SHTest) -> () -> String' access=internal get_for=name
        (parameter "self" type='SHTest' interface type='SHTest')
        (parameter_list)
        (brace_stmt implicit range=[main.swift:13:9 - line:13:9]
          (return_stmt implicit
            (member_ref_expr implicit type='String' decl=main.(file)[email protected]:13:9 direct_to_storage
              (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>[email protected]:13:9 function_ref=unapplied)))))
      (accessor_decl implicit range=[main.swift:13:9 - line:13:9] 'anonname=0x7f80ee150cc0' interface type='(SHTest) -> (String) -> ()' access=internal set_for=name
        (parameter "self" type='SHTest' interface type='SHTest')
        (parameter_list
          (parameter "value" type='String' interface type='String') range=[main.swift:13:9 - line:13:9])
        (brace_stmt implicit range=[main.swift:13:9 - line:13:9]
          (assign_expr implicit type='()'
            (member_ref_expr implicit type='@lvalue String' decl=main.(file)[email protected]:13:9 direct_to_storage
              (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>[email protected]:13:9 function_ref=unapplied))
            (declref_expr implicit type='String' decl=main.(file).SHTest.<anonymous>[email protected]:13:9 function_ref=unapplied))))
      (accessor_decl implicit range=[main.swift:13:9 - line:13:9] 'anonname=0x7f80ee150e20' interface type='(SHTest) -> () -> ()' access=internal _modify_for=name
        (parameter "self" type='SHTest' interface type='SHTest')
        (parameter_list)
        (brace_stmt implicit range=[main.swift:13:9 - line:13:9]
          (yield_stmt implicit range=[main.swift:13:9 - line:13:9]
            (inout_expr implicit type='inout String'
              (member_ref_expr implicit type='@lvalue String' decl=main.(file)[email protected]:13:9 direct_to_impl
                (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>[email protected]:13:9 function_ref=unapplied)))))))
    (pattern_binding_decl range=[main.swift:14:5 - line:14:16]
      (pattern_named type='Double' 'size')
      Original init:
      (float_literal_expr type='Double' location=main.swift:14:16 range=[main.swift:14:16 - line:14:16] value=10.5 builtin_initializer=Swift.(file).Double extension.init(_builtinFloatLiteral:) initializer=**NULL** builtin_type='Builtin.FPIEEE80')
      Processed init:
      (float_literal_expr type='Double' location=main.swift:14:16 range=[main.swift:14:16 - line:14:16] value=10.5 builtin_initializer=Swift.(file).Double extension.init(_builtinFloatLiteral:) initializer=**NULL** builtin_type='Builtin.FPIEEE80'))
    (var_decl range=[main.swift:14:9 - line:14:9] "size" type='Double' interface type='Double' access=internal readImpl=stored writeImpl=stored readWriteImpl=stored
      (accessor_decl implicit range=[main.swift:14:9 - line:14:9] 'anonname=0x7f80ee151f90' interface type='(SHTest) -> () -> Double' access=internal get_for=size
        (parameter "self" type='SHTest' interface type='SHTest')
        (parameter_list)
        (brace_stmt implicit range=[main.swift:14:9 - line:14:9]
          (return_stmt implicit
            (member_ref_expr implicit type='Double' decl=main.(file)[email protected]:14:9 direct_to_storage
              (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>[email protected]:14:9 function_ref=unapplied)))))
      (accessor_decl implicit range=[main.swift:14:9 - line:14:9] 'anonname=0x7f80ee1521c0' interface type='(SHTest) -> (Double) -> ()' access=internal set_for=size
        (parameter "self" type='SHTest' interface type='SHTest')
        (parameter_list
          (parameter "value" type='Double' interface type='Double') range=[main.swift:14:9 - line:14:9])
        (brace_stmt implicit range=[main.swift:14:9 - line:14:9]
          (assign_expr implicit type='()'
            (member_ref_expr implicit type='@lvalue Double' decl=main.(file)[email protected]:14:9 direct_to_storage
              (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>[email protected]:14:9 function_ref=unapplied))
            (declref_expr implicit type='Double' decl=main.(file).SHTest.<anonymous>[email protected]:14:9 function_ref=unapplied))))
      (accessor_decl implicit range=[main.swift:14:9 - line:14:9] 'anonname=0x7f80ee152320' interface type='(SHTest) -> () -> ()' access=internal _modify_for=size
        (parameter "self" type='SHTest' interface type='SHTest')
        (parameter_list)
        (brace_stmt implicit range=[main.swift:14:9 - line:14:9]
          (yield_stmt implicit range=[main.swift:14:9 - line:14:9]
            (inout_expr implicit type='inout Double'
              (member_ref_expr implicit type='@lvalue Double' decl=main.(file)[email protected]:14:9 direct_to_impl
                (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>[email protected]:14:9 function_ref=unapplied)))))))
    (pattern_binding_decl range=[main.swift:15:5 - line:15:18]
      (pattern_named type='Double' 'height')
      Original init:
      (float_literal_expr type='Double' location=main.swift:15:18 range=[main.swift:15:18 - line:15:18] value=13.4 builtin_initializer=Swift.(file).Double extension.init(_builtinFloatLiteral:) initializer=**NULL** builtin_type='Builtin.FPIEEE80')
      Processed init:
      (float_literal_expr type='Double' location=main.swift:15:18 range=[main.swift:15:18 - line:15:18] value=13.4 builtin_initializer=Swift.(file).Double extension.init(_builtinFloatLiteral:) initializer=**NULL** builtin_type='Builtin.FPIEEE80'))
    (var_decl range=[main.swift:15:9 - line:15:9] "height" type='Double' interface type='Double' access=internal readImpl=stored writeImpl=stored readWriteImpl=stored
      (accessor_decl implicit range=[main.swift:15:9 - line:15:9] 'anonname=0x7f80ef021260' interface type='(SHTest) -> () -> Double' access=internal get_for=height
        (parameter "self" type='SHTest' interface type='SHTest')
        (parameter_list)
        (brace_stmt implicit range=[main.swift:15:9 - line:15:9]
          (return_stmt implicit
            (member_ref_expr implicit type='Double' decl=main.(file)[email protected]:15:9 direct_to_storage
              (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>[email protected]:15:9 function_ref=unapplied)))))
      (accessor_decl implicit range=[main.swift:15:9 - line:15:9] 'anonname=0x7f80ef021438' interface type='(SHTest) -> (Double) -> ()' access=internal set_for=height
        (parameter "self" type='SHTest' interface type='SHTest')
        (parameter_list
          (parameter "value" type='Double' interface type='Double') range=[main.swift:15:9 - line:15:9])
        (brace_stmt implicit range=[main.swift:15:9 - line:15:9]
          (assign_expr implicit type='()'
            (member_ref_expr implicit type='@lvalue Double' decl=main.(file)[email protected]:15:9 direct_to_storage
              (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>[email protected]:15:9 function_ref=unapplied))
            (declref_expr implicit type='Double' decl=main.(file).SHTest.<anonymous>[email protected]:15:9 function_ref=unapplied))))
      (accessor_decl implicit range=[main.swift:15:9 - line:15:9] 'anonname=0x7f80ef021528' interface type='(SHTest) -> () -> ()' access=internal _modify_for=height
        (parameter "self" type='SHTest' interface type='SHTest')
        (parameter_list)
        (brace_stmt implicit range=[main.swift:15:9 - line:15:9]
          (yield_stmt implicit range=[main.swift:15:9 - line:15:9]
            (inout_expr implicit type='inout Double'
              (member_ref_expr implicit type='@lvalue Double' decl=main.(file)[email protected]:15:9 direct_to_impl
                (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>[email protected]:15:9 function_ref=unapplied)))))))
    (destructor_decl implicit range=[main.swift:12:7 - line:12:7] "deinit" interface type='(SHTest) -> () -> ()' access=internal
      (parameter "self")
      (parameter_list)
      (brace_stmt implicit range=[main.swift:12:7 - line:12:7]))
    (constructor_decl implicit range=[main.swift:12:7 - line:12:7] "init()" interface type='(SHTest.Type) -> () -> SHTest' access=internal designated
      (parameter "self")
      (parameter_list)
      (brace_stmt implicit range=[main.swift:12:7 - line:12:7]
        (return_stmt range=[main.swift:12:7 - line:12:7]))))
  (top_level_code_decl range=[main.swift:18:1 - line:18:20]
    (brace_stmt implicit range=[main.swift:18:1 - line:18:20]
      (pattern_binding_decl range=[main.swift:18:1 - line:18:20]
        (pattern_named type='SHTest' 'test1')
        Original init:
        (call_expr type='SHTest' location=main.swift:18:13 range=[main.swift:18:13 - line:18:20] nothrow arg_labels=
          (constructor_ref_call_expr type='() -> SHTest' location=main.swift:18:13 range=[main.swift:18:13 - line:18:13] nothrow
            (declref_expr implicit type='(SHTest.Type) -> () -> SHTest' location=main.swift:18:13 range=[main.swift:18:13 - line:18:13] decl=main.(file).SHTest.init()@main.swift:12:7 function_ref=single)
            (type_expr type='SHTest.Type' location=main.swift:18:13 range=[main.swift:18:13 - line:18:13] typerepr='SHTest'))
          (tuple_expr type='()' location=main.swift:18:19 range=[main.swift:18:19 - line:18:20]))
        Processed init:
        (call_expr type='SHTest' location=main.swift:18:13 range=[main.swift:18:13 - line:18:20] nothrow arg_labels=
          (constructor_ref_call_expr type='() -> SHTest' location=main.swift:18:13 range=[main.swift:18:13 - line:18:13] nothrow
            (declref_expr implicit type='(SHTest.Type) -> () -> SHTest' location=main.swift:18:13 range=[main.swift:18:13 - line:18:13] decl=main.(file).SHTest.init()@main.swift:12:7 function_ref=single)
            (type_expr type='SHTest.Type' location=main.swift:18:13 range=[main.swift:18:13 - line:18:13] typerepr='SHTest'))
          (tuple_expr type='()' location=main.swift:18:19 range=[main.swift:18:19 - line:18:20])))
))
  (var_decl range=[main.swift:18:5 - line:18:5] "test1" type='SHTest' interface type='SHTest' access=internal let readImpl=stored immutable))
1.4通過SILGen生成未優化代碼量巨大的RawSIL文件(-emit-silgen)
1.5 再拿到優化後更簡潔的Canonical SIL(-emit-sil)

➜  swiftstudy swiftc -emit-sil main.swift
sil_stage canonical

import Builtin
import Swift
import SwiftShims

import Foundation

class SHTest {
  @_hasStorage @_hasInitialValue var name: String { get set }
  @_hasStorage @_hasInitialValue var size: Double { get set }
  @_hasStorage @_hasInitialValue var height: Double { get set }
  @objc deinit
  init()
}

@_hasStorage @_hasInitialValue let test1: SHTest { get }

// test1
sil_global hidden [let] @$s4main5test1AA6SHTestCvp : $SHTest

// 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 @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4
  %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // users: %6, %5
  %5 = tuple_extract %4 : $(Array<Any>, Builtin.RawPointer), 0 // users: %24, %21
  %6 = tuple_extract %4 : $(Array<Any>, Builtin.RawPointer), 1 // user: %7
  %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14
  %8 = string_literal utf8 "Hello, World!"        // user: %13
  %9 = integer_literal $Builtin.Word, 13          // user: %13
  %10 = integer_literal $Builtin.Int1, -1         // user: %13
  %11 = metatype $@thin String.Type               // user: %13
  // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
  %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13
  %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15
  %14 = init_existential_addr %7 : $*Any, $String // user: %15
  store %13 to %14 : $*String                     // id: %15
  // function_ref default argument 1 of print(_:separator:terminator:)
  %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17
  %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21
  // function_ref default argument 2 of print(_:separator:terminator:)
  %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19
  %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21
  // function_ref print(_:separator:terminator:)
  %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21
  %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()
  release_value %19 : $String                     // id: %22
  release_value %17 : $String                     // id: %23
  release_value %5 : $Array<Any>                  // id: %24
  alloc_global @$s4main5test1AA6SHTestCvp         // id: %25
  %26 = global_addr @$s4main5test1AA6SHTestCvp : $*SHTest // user: %30
  %27 = metatype $@thick SHTest.Type              // user: %29
  // function_ref SHTest.__allocating_init()
  %28 = function_ref @$s4main6SHTestCACycfC : $@convention(method) (@thick SHTest.Type) -> @owned SHTest // user: %29
  %29 = apply %28(%27) : $@convention(method) (@thick SHTest.Type) -> @owned SHTest // user: %30
  store %29 to %26 : $*SHTest                     // id: %30
  %31 = integer_literal $Builtin.Int32, 0         // user: %32
  %32 = struct $Int32 (%31 : $Builtin.Int32)      // user: %33
  return %32 : $Int32                             // id: %33
} // end sil function 'main'

// _allocateUninitializedArray<A>(_:)
sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer)

// String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String

// default argument 1 of print(_:separator:terminator:)
sil shared_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String {
bb0:
  %0 = string_literal utf8 " "                    // user: %5
  %1 = integer_literal $Builtin.Word, 1           // user: %5
  %2 = integer_literal $Builtin.Int1, -1          // user: %5
  %3 = metatype $@thin String.Type                // user: %5
  // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
  %4 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %5
  %5 = apply %4(%0, %1, %2, %3) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %6
  return %5 : $String                             // id: %6
} // end sil function '$ss5print_9separator10terminatoryypd_S2StFfA0_'

// default argument 2 of print(_:separator:terminator:)
sil shared_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String {
bb0:
  %0 = string_literal utf8 "\n"                   // user: %5
  %1 = integer_literal $Builtin.Word, 1           // user: %5
  %2 = integer_literal $Builtin.Int1, -1          // user: %5
  %3 = metatype $@thin String.Type                // user: %5
  // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
  %4 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %5
  %5 = apply %4(%0, %1, %2, %3) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %6
  return %5 : $String                             // id: %6
} // end sil function '$ss5print_9separator10terminatoryypd_S2StFfA1_'

// print(_:separator:terminator:)
sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()

// variable initialization expression of SHTest.name
sil hidden [transparent] @$s4main6SHTestC4nameSSvpfi : $@convention(thin) () -> @owned String {
bb0:
  %0 = string_literal utf8 "hello"                // user: %5
  %1 = integer_literal $Builtin.Word, 5           // user: %5
  %2 = integer_literal $Builtin.Int1, -1          // user: %5
  %3 = metatype $@thin String.Type                // user: %5
  // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
  %4 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %5
  %5 = apply %4(%0, %1, %2, %3) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %6
  return %5 : $String                             // id: %6
} // end sil function '$s4main6SHTestC4nameSSvpfi'

// SHTest.name.getter
sil hidden [transparent] @$s4main6SHTestC4nameSSvg : $@convention(method) (@guaranteed SHTest) -> @owned String {
// %0                                             // users: %2, %1
bb0(%0 : $SHTest):
  debug_value %0 : $SHTest, let, name "self", argno 1 // id: %1
  %2 = ref_element_addr %0 : $SHTest, #SHTest.name // user: %3
  %3 = begin_access [read] [dynamic] %2 : $*String // users: %4, %6
  %4 = load %3 : $*String                         // users: %7, %5
  retain_value %4 : $String                       // id: %5
  end_access %3 : $*String                        // id: %6
  return %4 : $String                             // id: %7
} // end sil function '$s4main6SHTestC4nameSSvg'

// SHTest.name.setter
sil hidden [transparent] @$s4main6SHTestC4nameSSvs : $@convention(method) (@owned String, @guaranteed SHTest) -> () {
// %0                                             // users: %11, %8, %4, %2
// %1                                             // users: %5, %3
bb0(%0 : $String, %1 : $SHTest):
  debug_value %0 : $String, let, name "value", argno 1 // id: %2
  debug_value %1 : $SHTest, let, name "self", argno 2 // id: %3
  retain_value %0 : $String                       // id: %4
  %5 = ref_element_addr %1 : $SHTest, #SHTest.name // user: %6
  %6 = begin_access [modify] [dynamic] %5 : $*String // users: %8, %7, %10
  %7 = load %6 : $*String                         // user: %9
  store %0 to %6 : $*String                       // id: %8
  release_value %7 : $String                      // id: %9
  end_access %6 : $*String                        // id: %10
  release_value %0 : $String                      // id: %11
  %12 = tuple ()                                  // user: %13
  return %12 : $()                                // id: %13
} // end sil function '$s4main6SHTestC4nameSSvs'

// SHTest.name.modify
sil hidden [transparent] @$s4main6SHTestC4nameSSvM : $@yield_once @convention(method) (@guaranteed SHTest) -> @yields @inout String {
// %0                                             // users: %2, %1
bb0(%0 : $SHTest):
  debug_value %0 : $SHTest, let, name "self", argno 1 // id: %1
  %2 = ref_element_addr %0 : $SHTest, #SHTest.name // user: %3
  %3 = begin_access [modify] [dynamic] %2 : $*String // users: %5, %8, %4
  yield %3 : $*String, resume bb1, unwind bb2     // id: %4

bb1:                                              // Preds: bb0
  end_access %3 : $*String                        // id: %5
  %6 = tuple ()                                   // user: %7
  return %6 : $()                                 // id: %7

bb2:                                              // Preds: bb0
  end_access %3 : $*String                        // id: %8
  unwind                                          // id: %9
} // end sil function '$s4main6SHTestC4nameSSvM'

// variable initialization expression of SHTest.size
sil hidden [transparent] @$s4main6SHTestC4sizeSdvpfi : $@convention(thin) () -> Double {
bb0:
  %0 = float_literal $Builtin.FPIEEE64, 0x4025000000000000 // 10.5 // user: %1
  %1 = struct $Double (%0 : $Builtin.FPIEEE64)    // user: %2
  return %1 : $Double                             // id: %2
} // end sil function '$s4main6SHTestC4sizeSdvpfi'

// Double.init(_builtinFloatLiteral:)
sil public_external [transparent] [serialized] @$sSd20_builtinFloatLiteralSdBf80__tcfC : $@convention(method) (Builtin.FPIEEE80, @thin Double.Type) -> Double {
// %0                                             // user: %2
bb0(%0 : $Builtin.FPIEEE80, %1 : $@thin Double.Type):
  %2 = builtin "fptrunc_FPIEEE80_FPIEEE64"(%0 : $Builtin.FPIEEE80) : $Builtin.FPIEEE64 // user: %3
  %3 = struct $Double (%2 : $Builtin.FPIEEE64)    // user: %4
  return %3 : $Double                             // id: %4
} // end sil function '$sSd20_builtinFloatLiteralSdBf80__tcfC'

// SHTest.size.getter
sil hidden [transparent] @$s4main6SHTestC4sizeSdvg : $@convention(method) (@guaranteed SHTest) -> Double {
// %0                                             // users: %2, %1
bb0(%0 : $SHTest):
  debug_value %0 : $SHTest, let, name "self", argno 1 // id: %1
  %2 = ref_element_addr %0 : $SHTest, #SHTest.size // user: %3
  %3 = begin_access [read] [dynamic] %2 : $*Double // users: %4, %5
  %4 = load %3 : $*Double                         // user: %6
  end_access %3 : $*Double                        // id: %5
  return %4 : $Double                             // id: %6
} // end sil function '$s4main6SHTestC4sizeSdvg'

// SHTest.size.setter
sil hidden [transparent] @$s4main6SHTestC4sizeSdvs : $@convention(method) (Double, @guaranteed SHTest) -> () {
// %0                                             // users: %6, %2
// %1                                             // users: %4, %3
bb0(%0 : $Double, %1 : $SHTest):
  debug_value %0 : $Double, let, name "value", argno 1 // id: %2
  debug_value %1 : $SHTest, let, name "self", argno 2 // id: %3
  %4 = ref_element_addr %1 : $SHTest, #SHTest.size // user: %5
  %5 = begin_access [modify] [dynamic] %4 : $*Double // users: %6, %7
  store %0 to %5 : $*Double                       // id: %6
  end_access %5 : $*Double                        // id: %7
  %8 = tuple ()                                   // user: %9
  return %8 : $()                                 // id: %9
} // end sil function '$s4main6SHTestC4sizeSdvs'

// SHTest.size.modify
sil hidden [transparent] @$s4main6SHTestC4sizeSdvM : $@yield_once @convention(method) (@guaranteed SHTest) -> @yields @inout Double {
// %0                                             // users: %2, %1
bb0(%0 : $SHTest):
  debug_value %0 : $SHTest, let, name "self", argno 1 // id: %1
  %2 = ref_element_addr %0 : $SHTest, #SHTest.size // user: %3
  %3 = begin_access [modify] [dynamic] %2 : $*Double // users: %5, %8, %4
  yield %3 : $*Double, resume bb1, unwind bb2     // id: %4

bb1:                                              // Preds: bb0
  end_access %3 : $*Double                        // id: %5
  %6 = tuple ()                                   // user: %7
  return %6 : $()                                 // id: %7

bb2:                                              // Preds: bb0
  end_access %3 : $*Double                        // id: %8
  unwind                                          // id: %9
} // end sil function '$s4main6SHTestC4sizeSdvM'

// variable initialization expression of SHTest.height
sil hidden [transparent] @$s4main6SHTestC6heightSdvpfi : $@convention(thin) () -> Double {
bb0:
  %0 = float_literal $Builtin.FPIEEE64, 0x402ACCCCCCCCCCCD // 13.4 // user: %1
  %1 = struct $Double (%0 : $Builtin.FPIEEE64)    // user: %2
  return %1 : $Double                             // id: %2
} // end sil function '$s4main6SHTestC6heightSdvpfi'

// SHTest.height.getter
sil hidden [transparent] @$s4main6SHTestC6heightSdvg : $@convention(method) (@guaranteed SHTest) -> Double {
// %0                                             // users: %2, %1
bb0(%0 : $SHTest):
  debug_value %0 : $SHTest, let, name "self", argno 1 // id: %1
  %2 = ref_element_addr %0 : $SHTest, #SHTest.height // user: %3
  %3 = begin_access [read] [dynamic] %2 : $*Double // users: %4, %5
  %4 = load %3 : $*Double                         // user: %6
  end_access %3 : $*Double                        // id: %5
  return %4 : $Double                             // id: %6
} // end sil function '$s4main6SHTestC6heightSdvg'

// SHTest.height.setter
sil hidden [transparent] @$s4main6SHTestC6heightSdvs : $@convention(method) (Double, @guaranteed SHTest) -> () {
// %0                                             // users: %6, %2
// %1                                             // users: %4, %3
bb0(%0 : $Double, %1 : $SHTest):
  debug_value %0 : $Double, let, name "value", argno 1 // id: %2
  debug_value %1 : $SHTest, let, name "self", argno 2 // id: %3
  %4 = ref_element_addr %1 : $SHTest, #SHTest.height // user: %5
  %5 = begin_access [modify] [dynamic] %4 : $*Double // users: %6, %7
  store %0 to %5 : $*Double                       // id: %6
  end_access %5 : $*Double                        // id: %7
  %8 = tuple ()                                   // user: %9
  return %8 : $()                                 // id: %9
} // end sil function '$s4main6SHTestC6heightSdvs'

// SHTest.height.modify
sil hidden [transparent] @$s4main6SHTestC6heightSdvM : $@yield_once @convention(method) (@guaranteed SHTest) -> @yields @inout Double {
// %0                                             // users: %2, %1
bb0(%0 : $SHTest):
  debug_value %0 : $SHTest, let, name "self", argno 1 // id: %1
  %2 = ref_element_addr %0 : $SHTest, #SHTest.height // user: %3
  %3 = begin_access [modify] [dynamic] %2 : $*Double // users: %5, %8, %4
  yield %3 : $*Double, resume bb1, unwind bb2     // id: %4

bb1:                                              // Preds: bb0
  end_access %3 : $*Double                        // id: %5
  %6 = tuple ()                                   // user: %7
  return %6 : $()                                 // id: %7

bb2:                                              // Preds: bb0
  end_access %3 : $*Double                        // id: %8
  unwind                                          // id: %9
} // end sil function '$s4main6SHTestC6heightSdvM'

// SHTest.deinit
sil hidden @$s4main6SHTestCfd : $@convention(method) (@guaranteed SHTest) -> @owned Builtin.NativeObject {
// %0                                             // users: %4, %2, %1
bb0(%0 : $SHTest):
  debug_value %0 : $SHTest, let, name "self", argno 1 // id: %1
  %2 = ref_element_addr %0 : $SHTest, #SHTest.name // user: %3
  destroy_addr %2 : $*String                      // id: %3
  %4 = unchecked_ref_cast %0 : $SHTest to $Builtin.NativeObject // user: %5
  return %4 : $Builtin.NativeObject               // id: %5
} // end sil function '$s4main6SHTestCfd'

// SHTest.__deallocating_deinit
sil hidden @$s4main6SHTestCfD : $@convention(method) (@owned SHTest) -> () {
// %0                                             // users: %3, %1
bb0(%0 : $SHTest):
  debug_value %0 : $SHTest, let, name "self", argno 1 // id: %1
  // function_ref SHTest.deinit
  %2 = function_ref @$s4main6SHTestCfd : $@convention(method) (@guaranteed SHTest) -> @owned Builtin.NativeObject // user: %3
  %3 = apply %2(%0) : $@convention(method) (@guaranteed SHTest) -> @owned Builtin.NativeObject // user: %4
  %4 = unchecked_ref_cast %3 : $Builtin.NativeObject to $SHTest // user: %5
  dealloc_ref %4 : $SHTest                        // id: %5
  %6 = tuple ()                                   // user: %7
  return %6 : $()                                 // id: %7
} // end sil function '$s4main6SHTestCfD'

// SHTest.__allocating_init()
sil hidden [exact_self_class] @$s4main6SHTestCACycfC : $@convention(method) (@thick SHTest.Type) -> @owned SHTest {
bb0(%0 : $@thick SHTest.Type):
  %1 = alloc_ref $SHTest                          // user: %3
  // function_ref SHTest.init()
  %2 = function_ref @$s4main6SHTestCACycfc : $@convention(method) (@owned SHTest) -> @owned SHTest // user: %3
  %3 = apply %2(%1) : $@convention(method) (@owned SHTest) -> @owned SHTest // user: %4
  return %3 : $SHTest                             // id: %4
} // end sil function '$s4main6SHTestCACycfC'

// SHTest.init()
sil hidden @$s4main6SHTestCACycfc : $@convention(method) (@owned SHTest) -> @owned SHTest {
// %0                                             // users: %24, %20, %14, %8, %1
bb0(%0 : $SHTest):
  debug_value %0 : $SHTest, let, name "self", argno 1 // id: %1
  %2 = string_literal utf8 "hello"                // user: %7
  %3 = integer_literal $Builtin.Word, 5           // user: %7
  %4 = integer_literal $Builtin.Int1, -1          // user: %7
  %5 = metatype $@thin String.Type                // user: %7
  // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
  %6 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %7
  %7 = apply %6(%2, %3, %4, %5) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %10
  %8 = ref_element_addr %0 : $SHTest, #SHTest.name // user: %9
  %9 = begin_access [modify] [dynamic] %8 : $*String // users: %10, %11
  store %7 to %9 : $*String                       // id: %10
  end_access %9 : $*String                        // id: %11
  %12 = float_literal $Builtin.FPIEEE64, 0x4025000000000000 // 10.5 // user: %13
  %13 = struct $Double (%12 : $Builtin.FPIEEE64)  // user: %16
  %14 = ref_element_addr %0 : $SHTest, #SHTest.size // user: %15
  %15 = begin_access [modify] [dynamic] %14 : $*Double // users: %16, %17
  store %13 to %15 : $*Double                     // id: %16
  end_access %15 : $*Double                       // id: %17
  %18 = float_literal $Builtin.FPIEEE64, 0x402ACCCCCCCCCCCD // 13.4 // user: %19
  %19 = struct $Double (%18 : $Builtin.FPIEEE64)  // user: %22
  %20 = ref_element_addr %0 : $SHTest, #SHTest.height // user: %21
  %21 = begin_access [modify] [dynamic] %20 : $*Double // users: %22, %23
  store %19 to %21 : $*Double                     // id: %22
  end_access %21 : $*Double                       // id: %23
  return %0 : $SHTest                             // id: %24
} // end sil function '$s4main6SHTestCACycfc'

sil_vtable SHTest {
  #SHTest.name!getter.1: (SHTest) -> () -> String : @$s4main6SHTestC4nameSSvg   // SHTest.name.getter
  #SHTest.name!setter.1: (SHTest) -> (String) -> () : @$s4main6SHTestC4nameSSvs // SHTest.name.setter
  #SHTest.name!modify.1: (SHTest) -> () -> () : @$s4main6SHTestC4nameSSvM   // SHTest.name.modify
  #SHTest.size!getter.1: (SHTest) -> () -> Double : @$s4main6SHTestC4sizeSdvg   // SHTest.size.getter
  #SHTest.size!setter.1: (SHTest) -> (Double) -> () : @$s4main6SHTestC4sizeSdvs // SHTest.size.setter
  #SHTest.size!modify.1: (SHTest) -> () -> () : @$s4main6SHTestC4sizeSdvM   // SHTest.size.modify
  #SHTest.height!getter.1: (SHTest) -> () -> Double : @$s4main6SHTestC6heightSdvg   // SHTest.height.getter
  #SHTest.height!setter.1: (SHTest) -> (Double) -> () : @$s4main6SHTestC6heightSdvs // SHTest.height.setter
  #SHTest.height!modify.1: (SHTest) -> () -> () : @$s4main6SHTestC6heightSdvM   // SHTest.height.modify
  #SHTest.init!allocator.1: (SHTest.Type) -> () -> SHTest : @$s4main6SHTestCACycfC  // SHTest.__allocating_init()
  #SHTest.deinit!deallocator.1: @$s4main6SHTestCfD  // SHTest.__deallocating_deinit
}

######1.5.1

我們來看這段

class SHTest {
  @_hasStorage @_hasInitialValue var name: String { get set }
  @_hasStorage @_hasInitialValue var size: Double { get set }
  @_hasStorage @_hasInitialValue var height: Double { get set }
  @objc deinit
  init()
}

@_hasStorage @_hasInitialValue let test1: SHTest { get }

// test1
sil_global hidden [let] @$s4main5test1AA6SHTestCvp : $SHTest

通過xcrun命令還原混寫後的字符串:
xcrun swift-demangle s4main5test1AA6SHTestCvp
可以得到:
$s4main5test1AA6SHTestCvp ---> main.test1 : main.SHTest

1.5.2 main
// 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 @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4
  %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // users: %6, %5
  %5 = tuple_extract %4 : $(Array<Any>, Builtin.RawPointer), 0 // users: %24, %21
  %6 = tuple_extract %4 : $(Array<Any>, Builtin.RawPointer), 1 // user: %7
  %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14
  %8 = string_literal utf8 "Hello, World!"        // user: %13
  %9 = integer_literal $Builtin.Word, 13          // user: %13
  %10 = integer_literal $Builtin.Int1, -1         // user: %13
  %11 = metatype $@thin String.Type               // user: %13
  // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
  %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13
  %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15
  %14 = init_existential_addr %7 : $*Any, $String // user: %15
  store %13 to %14 : $*String                     // id: %15
  // function_ref default argument 1 of print(_:separator:terminator:)
  %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17
  %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21
  // function_ref default argument 2 of print(_:separator:terminator:)
  %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19
  %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21
  // function_ref print(_:separator:terminator:)
  %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21
  %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()
  release_value %19 : $String                     // id: %22
  release_value %17 : $String                     // id: %23
  release_value %5 : $Array<Any>                  // id: %24
  alloc_global @$s4main5test1AA6SHTestCvp         // id: %25
  %26 = global_addr @$s4main5test1AA6SHTestCvp : $*SHTest // user: %30
  %27 = metatype $@thick SHTest.Type              // user: %29
  // function_ref SHTest.__allocating_init()
  %28 = function_ref @$s4main6SHTestCACycfC : $@convention(method) (@thick SHTest.Type) -> @owned SHTest // user: %29
  %29 = apply %28(%27) : $@convention(method) (@thick SHTest.Type) -> @owned SHTest // user: %30
  store %29 to %26 : $*SHTest                     // id: %30
  %31 = integer_literal $Builtin.Int32, 0         // user: %32
  %32 = struct $Int32 (%31 : $Builtin.Int32)      // user: %33
  return %32 : $Int32                             // id: %33
} // end sil function 'main'
1.6通過IRGen生成IR(-emit-ir)
1.7最終生成二進制代碼

看下彙編代碼 swiftc -emit-assembly main.swift

......
globl   _$s4main6SHTestC4nameSSvgTq
    .private_extern _$s4main6SHTestC4nameSSvgTq
    .alt_entry  _$s4main6SHTestC4nameSSvgTq
.set _$s4main6SHTestC4nameSSvgTq, _$s4main6SHTestCMn+52
    .globl  _$s4main6SHTestC4nameSSvsTq
    .private_extern _$s4main6SHTestC4nameSSvsTq
    .alt_entry  _$s4main6SHTestC4nameSSvsTq
.set _$s4main6SHTestC4nameSSvsTq, _$s4main6SHTestCMn+60
    .globl  _$s4main6SHTestC4nameSSvMTq
    .private_extern _$s4main6SHTestC4nameSSvMTq
    .alt_entry  _$s4main6SHTestC4nameSSvMTq
.set _$s4main6SHTestC4nameSSvMTq, _$s4main6SHTestCMn+68
    .globl  _$s4main6SHTestC4sizeSdvgTq
    .private_extern _$s4main6SHTestC4sizeSdvgTq
    .alt_entry  _$s4main6SHTestC4sizeSdvgTq
.set _$s4main6SHTestC4sizeSdvgTq, _$s4main6SHTestCMn+76
    .globl  _$s4main6SHTestC4sizeSdvsTq
    .private_extern _$s4main6SHTestC4sizeSdvsTq
    .alt_entry  _$s4main6SHTestC4sizeSdvsTq
.set _$s4main6SHTestC4sizeSdvsTq, _$s4main6SHTestCMn+84
    .globl  _$s4main6SHTestC4sizeSdvMTq
    .private_extern _$s4main6SHTestC4sizeSdvMTq
    .alt_entry  _$s4main6SHTestC4sizeSdvMTq
.set _$s4main6SHTestC4sizeSdvMTq, _$s4main6SHTestCMn+92
    .globl  _$s4main6SHTestC6heightSdvgTq
    .private_extern _$s4main6SHTestC6heightSdvgTq
    .alt_entry  _$s4main6SHTestC6heightSdvgTq
.set _$s4main6SHTestC6heightSdvgTq, _$s4main6SHTestCMn+100
    .globl  _$s4main6SHTestC6heightSdvsTq
    .private_extern _$s4main6SHTestC6heightSdvsTq
    .alt_entry  _$s4main6SHTestC6heightSdvsTq
.set _$s4main6SHTestC6heightSdvsTq, _$s4main6SHTestCMn+108
    .globl  _$s4main6SHTestC6heightSdvMTq
    .private_extern _$s4main6SHTestC6heightSdvMTq
    .alt_entry  _$s4main6SHTestC6heightSdvMTq
.set _$s4main6SHTestC6heightSdvMTq, _$s4main6SHTestCMn+116
    .globl  _$s4main6SHTestCACycfCTq
    .private_extern _$s4main6SHTestCACycfCTq
    .alt_entry  _$s4main6SHTestCACycfCTq
.set _$s4main6SHTestCACycfCTq, _$s4main6SHTestCMn+124
    .globl  _$s4main6SHTestCN
    .private_extern _$s4main6SHTestCN
    .alt_entry  _$s4main6SHTestCN
.set _$s4main6SHTestCN, _$s4main6SHTestCMf+16
.subsections_via_symbols

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章