コンパイラの処理過程
人間にわかりやすいC言語で書かれたプログラムをコンピュータが実行できるようにするには、コンパイル(翻訳)作業が必須です。
キー一つで自動でコンパイルしてくれるので、普段あまり意識するものではありませんが、ここではコンパイラがコンパイルを行う過程を順を追ってみましょう。
コンパイルは以下の手順で行われます。
- 字句解析
- 構文解析
- 意味解析
- オブジェクト最適化
- レジスタの割り当て
- コード生成
これらの手順を一つずつ見ていきましょう。
字句解析
最終的には書かれている命令の意味を解析しなければなりませんが、まずはそれらを構成する字句(単語)を識別します。
読み込んだプログラムを字句ごとに切り出し、それらがどんな意味をもつのかを決定します。
意味とは、それが変数名なのか演算子なのか、といった言語の使用上の意味です。
構文解析
意味を決定した字句を、構文を木構造をで表現した、構文木を元に構文に当てはめていきます。
演算は項で演算子を挟むという性質上、二分木の構造で表現できます。
余談ですが、C言語では関数の呼び出しや配列の要素の参照などもすべて演算となります。
演算子一覧を見れば、関数の()や配列の[]なども優先順位がついていることがわかるでしょう。
意味解析
構文解析で構文が決まると、各単語や演算子の意味を正確に判別できます。
例えば、整数型の変数の演算に使われている演算子は整数型の演算子となります。
これもあまり意識することはありませんが、演算子にも型があります。型の違う値を演算すると予期しない結果になるのはこれが原因の一つです。
意味解析ではこのように式や記号の意味を明確にします。
ここで得た情報は記号表として、ソースコードに使われる記号の意味を記録されます。
また、文字列や図式での表現はコンピュータにはわかりにくいので、中間言語に変換します。
オブジェクト最適化
命令ごとに、処理時間は変わります。
特に、外部の機器やストレージの使用には時間がかかります。
これによる待ち時間を、順番を変えるなどして効率のよいプログラムに変更するのがオブジェクトの最適化です。
レジスタの割り当て
コンピュータはCPUのレジスタという機関で演算処理を行います。
複数のレジスタにどの命令を割り当てていくかを決めるのがレジスタの割り当てです。
コード生成
実際にコンピュータが理解できる機械語に変換します。
コンピュータはコンパイルする一瞬のうちにこれだけの作業を実行しています。