美文网首页
swift编译浅析

swift编译浅析

作者: GitArtOS | 来源:发表于2021-01-19 16:11 被阅读0次
    
    //
    //  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).SHTest.name@main.swift:13:9 direct_to_storage
                  (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>.self@main.swift: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).SHTest.name@main.swift:13:9 direct_to_storage
                  (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>.self@main.swift:13:9 function_ref=unapplied))
                (declref_expr implicit type='String' decl=main.(file).SHTest.<anonymous>.value@main.swift: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).SHTest.name@main.swift:13:9 direct_to_impl
                    (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>.self@main.swift: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).SHTest.size@main.swift:14:9 direct_to_storage
                  (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>.self@main.swift: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).SHTest.size@main.swift:14:9 direct_to_storage
                  (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>.self@main.swift:14:9 function_ref=unapplied))
                (declref_expr implicit type='Double' decl=main.(file).SHTest.<anonymous>.value@main.swift: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).SHTest.size@main.swift:14:9 direct_to_impl
                    (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>.self@main.swift: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).SHTest.height@main.swift:15:9 direct_to_storage
                  (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>.self@main.swift: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).SHTest.height@main.swift:15:9 direct_to_storage
                  (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>.self@main.swift:15:9 function_ref=unapplied))
                (declref_expr implicit type='Double' decl=main.(file).SHTest.<anonymous>.value@main.swift: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).SHTest.height@main.swift:15:9 direct_to_impl
                    (declref_expr implicit type='SHTest' decl=main.(file).SHTest.<anonymous>.self@main.swift: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
    
    

    相关文章

      网友评论

          本文标题:swift编译浅析

          本文链接:https://www.haomeiwen.com/subject/tltczktx.html