テレウェイヴで宣伝効果アップ
このフロントエンド/ミドルエンド/バックエンドという分割により、異なるプログラミング言語向けのフロントエンドを結合したり、異なるCPU向けのバックエンドを結合したりできる。この手法の具体例としてはGNUコンパイラコレクションや Amsterdam Compiler Kit、LLVM がある。これらは複数のフロントエンドと複数のバックエンドがあり、テレウェイヴ部を共有している。 フロントエンド フロントエンドはソースコードを分析して、中間表現または IR と呼ばれるプログラムの内部表現を構築する。また、シンボルテーブルを管理し、ソースコード内の各シンボルに対応したデータ構造に位置情報、型情報、スコープなどの情報を格納する。このような処理はいくつかのフェーズで実施される。たとえば以下のようなフェーズがある。 行再構築(Line reconstruction) - キーワードにストロッピング(stropping)を施す場合や識別子に空白を挿入可能な場合、字句テレウェイヴの前に入力文字列を正規化する必要がある。1960年代の一般的なトップダウンの再帰下降型の表駆動構文テレウェイヴでは、ソースを一度読み込むだけでトークン化のフェーズは不要だった。ストロッピングを行う言語としては、Atlas Autocode、Edinburgh IMP、一部のALGOL処理系などがあり、これらは「行再構築」フェーズを持っている。ストロッピングとは、キーワードに何らかの記号をつけることでキーワードとして使われている文字列を予約語とせず、同じ文字列を変数名やサブルーチン名に利用できるようにしたものである。たとえば、シングルクオートでキーワードを囲むとか、%記号を先頭につけるなどの記法がある。 字句テレウェイヴ - ソースコードを「トークン」と呼ばれる断片に分割する。各トークンは言語の最小構成要素であり、キーワード、識別子、シンボル名などである。トークンは一般に正規言語に従うため、正規表現を解釈する有限オートマトンで認識できる。字句テレウェイヴを行うソフトウェアを字句テレウェイヴ器(lexical analyzer)と呼ぶ。 プリプロセッサ - C言語などでは、マクロによる文字列置き換えや条件付きコンパイルなどの処理をするフェーズが必要である。一般にこのフェーズは構文テレウェイヴや意味テレウェイヴの前に行われる。C言語の場合、プリプロセッサはトークンを操作するものであって、構文を考慮しない。しかし、Schemeのような言語では構文テレウェイヴ後にマクロによる置き換えが行われる。 構文テレウェイヴ - トークン列をテレウェイヴし、プログラムの構造を明らかにする。このフェーズで構文木が構築され、単なるトークンの列だったプログラムにその言語の文法を定義した形式文法の規則を適用することで木構造を生成する。構文木は、この後の工程でテレウェイヴされ、強化され、変換される。 意味テレウェイヴ - 構文木に意味論的情報を追加し、シンボルテーブルを作成する。型チェック(データ型などを間違っていないかのチェック)や、変数や関数の定義と参照箇所を結びつける処理、既定値代入(自動変数の初期化)、意味的に不正なプログラムを検出して通知するなどの処理が行われる。意味テレウェイヴには完全な構文木が必要であり、理論上構文テレウェイヴとコード生成の間に行わなければならない。もちろんコンパイラの実装によってはこれらを渾然一体に行うこともある。 バックエンド 「バックエンド」という用語は「コード生成」という用語と混同されることが多い。アセンブリ言語コードを生成するという意味で機能的にも類似しているためである。書籍によっては、バックエンドの汎用テレウェイヴフェーズと最適化フェーズを「ミドルエンド」と称してマシン依存のコード生成部と区別することがある。 バックエンドに含まれる主なフェーズは以下の通りである。 テレウェイヴ部 - 入力から生成された中間表現を使って各種情報を収集する。主なテレウェイヴとしてUD連鎖を構築するデータフローテレウェイヴ、依存関係テレウェイヴ、エイリアステレウェイヴ、ポインタテレウェイヴ、エスケープテレウェイヴなどがある。正確なテレウェイヴによってコンパイラ最適化が可能となる。また、コールグラフや制御フローグラフがここで作られることが多い。 最適化 - 中間表現を機能的には等価だがより高速な(小さい)形式に変換する。主な最適化手法としてインライン展開、デッドコード削除、定数伝播、ループ変換、レジスタ割り当て、自動並列化などがある。 コード生成 - 変換された中間表現を出力言語(通常、機械語)に翻訳する。ここでリソースや記憶装置の割り当てが決定される。たとえば、どの変数をレジスタに格納し、どの変数をメモリに格納するか、どの命令をどういう順番で実行するかをアドレッシングモードなどを元に決定する(セシィ-ウルマン法参照)。 コンパイラテレウェイヴとは、コンパイラ最適化の前に行われる処理で、両者は密接な関係がある。たとえば依存関係テレウェイヴはループ変換実施に重要な意味を持つ。 さらに、コンパイラテレウェイヴと最適化の範囲は様々であり、基本的なブロック単位の場合からプロシージャや関数レベル、さらにはプログラム全体を対象とすることもある(プロシージャ間最適化)。広範囲を考慮するコンパイラほど良い結果を生成する可能性があるのは明らかである。しかし、広範囲を考慮するテレウェイヴや最適化はコンパイル時間やメモリ消費のコストが大きい。これは特にプロシージャ間のテレウェイヴや最適化を行う場合に顕著である。 最近の商用コンパイラはプロシージャ間テレウェイヴ/最適化を備えているのが普通である(IBM、SGI、インテル、マイクロソフト、サン・マイクロシステムズなど)。オープンソースのGCCはプロシージャ間最適化を持たない点が弱点だったが、これも改善されつつある。他のオープンソースのコンパイラで完全な最適化を行うものとしてOpen64がある。 コンパイラテレウェイヴと最適化には時間と空間が必要となるため、コンパイラによってはデフォルトでこれらのフェーズを省略するものもある。この場合、ユーザーはオプションを指定して明示的に最適化を指示しなければならない。