ページ

2016年5月14日土曜日

Swiftの中を見てみる 1 - コンパイルの流れ -


最近Swiftを触っているんですが、中をちゃんと見てなかったんで、
この機会に見てみようかと思います。今回はコンパイルに関してです。

コンパイルの流れ

Xcodeではビルドして実行・・・で簡単に実行できてますが、
その時どのようにコンパイルされ実行されているのかを見てみます。
ざっくりとしたビルド時の流れとしては上から順に、
  • Frontend
    C/C++、Haskell、Swiftなどで書かれたソースを構文解析し
    LLVM IR という中間コードを生成する
  • LLVM Optimizer
    様々な最適化を行う
  • Backend
    特定のマシンに基づいた機械語を生成
という流れになっています。
LLVMとは?
任意のプログラミング言語に対応可能なコンパイラ基盤
JavaとJava VMのように仮想マシンをターゲットにした中間コードを出力し、
特定のマシンの機械語に変換します。

Frontend

C/C++, Objective‑CのFrontendにClangというものがあります。
これはAppleがMacOSやiOS用に作成したものです。
コンパイルの流れとしては、、
  • ソースコード -> 抽象構文木(Abstract Syntax Tree、AST) というものに変換
  • LLVM IRを生成
  • LLVM IR -> 機械語を生成
という流れになってます。
Swift用のFrontend
SwiftではClangをより良くして以下のような流れになってます。
  • Swiftのソースコード -> ASTに変換
  • SIL(Swift intermediate Language)(LLVM IRのSwift版)を生成
  • SILからLLVM IRを生成 -> 最後に機械語が生成
Clangに比べてSILのフェーズが追加されています。

実験

Swiftではコンパイルのオプションで上で見てきた、ASTやSILを
出力してくれるオプションが存在します。
そのオプションを使って色々表示させてみたいと思います。
簡単なサンプルのコンパイル&実行
// hello.swift
print(“hello!!”)
↑をhello.swiftとして保存し、
$ swiftc hello.swift # コンパイル
$ ./hello # -> hello!!
コンパイル&実行します。
AST表示
今度はサンプルのASTを表示させてみたいと思います。
$ swift -dump-ast hello.swift
(source_file
  (top_level_code_decl
    (brace_stmt
      (call_expr type='()' location=hello.swift:1:1 range=[hello.swift:1:1 - line:1:21] nothrow
      ・・・
なにやらずらずらっと表示されたかと思います。
SIL表示
次はSILを表示してみます。
$ swiftc -emit-silgen hello.swift | xcrun swift-demangle
sil_stage raw

import Builtin
import Swift
import SwiftShims
・・・
LLVM IR表示
そしてLLVM IR
$ swiftc -emit-ir hello.swift
; ModuleID = '-'
target datalayout = ・・・
アセンブリ表示
最後にアセンブリ表示
$ swiftc -emit-assembly hello.swift
.section    __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 9
.globl    _main
.align    4, 0x90
_main:
.cfi_startproc
・・・
こうしてみると複数のフェーズを経由している事が分かります。
またSwiftからObjective-Cが使えるのも同じLLVM基盤を採用しているからなんですね。


0 件のコメント:

コメントを投稿