Posted at

Swiftの中間言語を出力して読む方法

More than 3 years have passed since last update.

https://speakerdeck.com/matuyuji/swiftzhong-jian-yan-yu-wodu-mu

この資料によると、Swiftは


  1. .swift

  2. Swift AST

  3. SIL

  4. LLVM IR

  5. LLVM BC

  6. Native asm

  7. Native binary

と辿っていくらしいです。どうやれば各段階のコードを得られるかというお話。



.swift

今回は.swift単品が対象。適当に


hello.swift

print("hello, world!")


とか書いておく。


Swift AST

swiftc -dump-ast hello.swift

いきなり長いものが出るが、

print() があって、括弧の中には "hello, world!" がある……

というのがちゃんと読める。


SIL

swiftc -emit-silgen hello.swift > hello.sil

swiftc -emit-silgen は結果を標準出力してくるので適当なファイルに書かせておく。

できたhello.silは

swiftc -parse-sil hello.sil

./hello

といった感じで実行するとこまで進められる。


LLVM IR

swiftc -emit-ir hello.swift > hello.ll

この辺りはまだ人間の目で読める。


LLVM BC

読めない。

swiftc -emit-bc hello.swift > hello.bc


LLVM周りの話


LLVMインストール

Mac(Xcode?どっちだろう)にはこの手のものが最初から入っているらしいが、LLVMをフルで使うには足りないので、今後LLVMで遊ぶ予定がある場合は

brew install llvm

とか


.hogerc

export PATH=$PATH:/usr/local/opt/llvm/bin


とかしておく。


IRからBCへ

↑で llvm-as というのが使えるようになっているはずなので、そいつでhello.llからhello.bcをつくる。

llvm-as hello.ll


.bcの実行

ちゃんとした.bcなら

lli hello.bc

で実行できるはずなのだが、

LLVM ERROR: Program used external function '_swift_once' which could not be resolved!

と怒られてしまう。多分なんか方法あるんだろうけど面倒くさいので省略。


Native asm

読める。

swiftc -emit-asm hello.swift > hello.s


LLVM BCからアセンブリへ

llc hello.bc

でhello.sが増える。↑とはちょっと違うけどだいたい似たようなことが書いてあるような気がする。


Native binary

できあがり

swiftc hello.swift

./hello

hello.sをgccに渡したらlswiftCoreがないって言われた(lswiftCore.dylibのことかな)。