Rustコンパイラの処理の流れ(1)

Rustのプログラムは以下のようなステップから構成されており、上から順に処理されている。

  1. .rsファイルをパースし、ASTを生成
  2. マクロの展開、名前解決、#[cfg] アトリビュートの解釈
  3. ASTをHIRに変換
  4. 型推論、型解析
  5. HIRをMIRに変換
  6. MIRをLLVM IRに変換、最適化
  7. .o ファイルをリンク

.rsファイルのパース

パーサはlibsyntax crateにまとまっている。一般的なパーサと同じく、字句を解析しASTを作る。

rust/src/libsysntax/codemap.rsでもともとのソースコードの位置の情報とASTのノードをマッピングしている。CodeMapのフィールドの1つであるfilesにファイルの情報がFileMapというデータ構造で入っている。また、CodeMapの先頭からの絶対的な位置がSpanというデータ構造に格納される。StringReader がFileMapをもとに、文字列の情報を次々に読んでいき、TokenStream 生成する。TokenStreamはTokenTreeのシーケンスであり、TokenTreeはTokenと区切り文字で構成されている。

Parser がTokenStreamをもとにASTを生成している。parse_ から始まるいくつかの関数がパースする際のエントリーポイントになっている。また、ASTはrust/src/libsysntax/ast.rs で定義されている。

ASTの内容を確認したい場合、rustc -Z ast-json ファイル名 を実行すれば、ASTがJSON形式で表示される。

また、StringReaderとParserはパース中に必要な情報を保持する ParseSess に紐付いており、無駄なコピーが発生しないようになっている。

参考

Like what you read? Give Takanori a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.