コンパイラの定義と目的
ANDRZEJ WOJCICKI /ゲッティイメージズ
あ コンパイラ です プログラム 人間が読める形式に翻訳する ソースコード コンピューターで実行可能なマシン コードに変換します。これを成功させるには、人間が読めるコードが 構文 コンパイラは単なるプログラムであり、コードを修正することはできません。間違えた場合は、構文を修正する必要があります。そうしないと、コンパイルできません。
コードをコンパイルするとどうなりますか?
コンパイラの複雑さは、言語の構文と抽象化の程度に依存します そのプログラミング言語 提供します。 C コンパイラは、C++ や C# のコンパイラよりもはるかに単純です。
字句解析
コンパイル時に、コンパイラは最初にソース コード ファイルから文字のストリームを読み取り、語彙トークンのストリームを生成します。たとえば、C++ コードは次のとおりです。
|_+_||_+_|次のトークンとして分析される場合があります。
- タイプ「int」
- 変数「C」
- 等しい
- 左ブラケット
- 変数「A」
- 回
- 変数「B」
- 右ブラケット
- プラス
- リテラル '10'
構文解析
字句出力はコンパイラの構文解析部に送られ、文法規則を使用して入力が有効かどうかが判断されます。そうでもなければ 変数 A と B は以前に宣言されていてスコープ内にあった場合、コンパイラは次のように言うかもしれません。
- 'A' : 宣言されていない識別子。
それらが宣言されているが初期化されていない場合。コンパイラは次の警告を発行します。
- ローカル変数 'A' が初期化されずに使用されました。
コンパイラの警告は無視しないでください。それらは、奇妙で予期しない方法でコードを壊す可能性があります。コンパイラの警告を常に修正します。
ワンパスまたはツーパス?
一部のプログラミング言語は、コンパイラがソース コードを 1 回だけ読み取ってマシン コードを生成できるように記述されています。 パスカル はそのような言語の 1 つです。たくさんの コンパイラ 少なくとも 2 つのパスが必要です。時々、それはの前方宣言が原因です 機能 またはクラス。
C++ では、クラスを宣言することはできますが、後で定義することはできません。コンパイラは、クラスの本体をコンパイルするまで、クラスが必要とするメモリ量を判断できません。正しいマシン コードを生成する前に、ソース コードを再度読み取る必要があります。
マシンコードの生成
コンパイラが字句解析と構文解析を正常に完了すると仮定すると、最終段階はマシン コードの生成です。これは、特に最近の CPU では複雑なプロセスです。
コンパイルの速さ 実行可能 コードは可能な限り高速である必要があり、生成されたコードの品質と要求された最適化の程度に応じて大幅に変化する可能性があります。
ほとんどのコンパイラでは、最適化の量を指定できます。これは通常、迅速なデバッグ コンパイルとリリースされたコードの完全な最適化で知られています。
コード生成は難しい
コンパイラの作成者は、コード ジェネレーターを作成するときに課題に直面します。多くのプロセッサは、
- 命令パイプライン
- 内部 キャッシュ .
コード内のすべての命令が ループ で開催できます CPU CPU がメイン RAM から命令をフェッチする必要がある場合よりもはるかに高速にループが実行されます。 CPU キャッシュは、CPU チップに組み込まれたメモリのブロックであり、メイン RAM のデータよりもはるかに高速にアクセスされます。
キャッシュとキュー
ほとんどの CPU には、CPU が命令を実行する前に命令をキャッシュに読み込むプリフェッチ キューがあります。条件分岐が発生した場合、CPU はキューをリロードする必要があります。これを最小限に抑えるようにコードを生成する必要があります。
多くの CPU には、次のパーツがあります。
- 整数演算 (整数)
- 浮動小数点演算 (分数)
これらの操作は、多くの場合、速度を上げるために並行して実行できます。
コンパイラは通常、マシン コードをオブジェクト ファイルに生成します。 リンクされた リンカプログラムで一緒に。