翻訳、コンパイル、コンパイラ、ソースコード、原始プログラム、ネイティブコード、ロードモジュール、実行可能プログラム、字句解析、構文解析、意味解析、中間コード、バイトコード、最適化、共通言語基盤 、CLI、仮想マシン、共通中間言語、CIL、基本クラスライブラリ、仮想実行システム、共通言語ランタイム、JITコンパイラ、JIS X 3016、ISO/IEC 23271、インタプリタ、ジェネレータ、シミュレータ、エミュレータ、目的プログラム、オブジェクトモジュール連係編集、リンカー、リンケージ・エディタ、静的リンキング、動的リンキング、プレコンパイラ、最適化コンパイラ、クロスコンパイラ、制御フロー図、CFG
翻訳(コンパイル)
プログラミング言語の文法に従って記述したプログラムをソースコード(ソースプログラム、原始プログラム)といいます。一方、実行するコンピュータが理解して動作する機械語の命令群になったプログラムをネイティブコード(ロードモジュール、実行プログラム、機械語)といいます。
ソースコードをネイティブコードに翻訳する機能をコンパイル、翻訳するソフトウェアをコンパイラといいます。
JavaやCなどは、ソースプログラム記述の仕様、文法であるとともに、その言語で記述したソースコードを翻訳するコンパイラでもあります。
コンパイラの基本構造と処理手順
通常の手続き型コンパイラは、字句解析→構文解析→意味解析のプロセスでいったん中間コードに翻訳し、その中間コードを、最適化→コード生成のプロセスでネイティブコードに翻訳します。
- 字句解析
- ソースコードを単語に分解して、変数、リテラル、予約語、演算子などに分類します。その分類区分をトークンといいます。
例えば、Z=X+Yという文から、Z,X,Y(変数)、=(代入演算子)、+(演算子)のように分解されます。
- 構文解析
- コンパイラ言語の文法はBNFのような形式言語で定義されています。構文解析では字句解析での単語とトークンにより、抽象構文木(Abstract Syntax Tree:AST)という木構造を用いて解析します。演算は項で演算子を挟むという性質上、二分木の構造で表現できます。
- 意味解析
-
各変数について型と記憶アドレスを与えた記号表を作成します。
抽象構文木から、「XにYを+したものをZに=する」(逆ポーランド表記法)であることを解析します。また、例えば、加算演算子(+)は整数型変数を対象にしたもの、浮動小数点数を対象にしたものでは異なりますが、それをXやYの型から決定します。
このようにして、中間コードが生成されます。
- 中間コード生成
- 現在のコンピュータのほとんどは記憶のアドレス付けが1バイト単位であるバイトマシンです。中間コードは、バイトマシンに共通した仕様になっています。それで、中間コードをバイトコードともいいます。これにより、移植性を高めています。
しかも、中間コードは、言語開発者が想定した仮想の処理体系(仮想マシン(Virtual Machine、VM))で実行できる命令体系になっています。
以降は、中間コードを、実際に稼働するOSや機種で実行できる機械語(ネイティブコード)にするプロセスです。
- 最適化
- 効率向上のために、中間コードを改良するプロセスです。このときにハードウェアやOSの特徴を考慮した改良をすることもあります。
- ネイティブコード生成
- 中間コードをさらに翻訳を進めて、CPU演算装置のアドレスの割当てや、命令の特定など、実行するハードウェアやOSに依存したネイティブコード(機械語)にする必要があります。その翻訳プログラムをJITコンパイラ(Just-In-Time Compiler)といいます。
共通言語基盤 (Common Language Infrastructure、CLI)
従来は、個々のプログラミング言語で、それぞれの中間コード体系をもち、それに対応したJITコンパイラを用いていました。言語に依存しない中間コード体系、JITコンパイラの環境を整備するために規格化、標準化をしたのが共通言語基盤です。
Microsoftは、Windowsの.NETに属する言語の共通化を進めていましたが、それをベースにして、共通言語基盤(CLI)になり、国際規格 ISO/IEC 23271 が策定され、JIS X 3016 にもなりました。
その後、主要言語の多くがこの規格に準拠するようになりました。
出典: フリー百科事典『ウィキペディア(Wikipedia)』https://ja.wikipedia.org/wiki/共通言語基盤
- 共通中間言語(Common Intermediate Language、CIL)
言語に依存しない中間コードの仕様です。多様なプログラム言語で記述されたソースコードは、CIL言語(オブジェクト指向のアセンブラのような形式)に従った中間コードに翻訳されます。
- 基本クラスライブラリ(Base Class Library, BCL)
多くのアプリケーションで共通に用いられる機能は、CILに準拠したクラスオブジェクトとして提供されます。それを呼び出して(アセンブル)中間コードを簡素化できますし、複数の言語からの中間コード間で相互に連携が容易になります。
- 仮想実行システム(Virtual Execution System、VES)
仮想マシンとして、中間コードをBCLとアセンブルしてネイティブコードに翻訳すること。それにはCLR(JITコンパイラ)が用いられます。
- 共通言語ランタイム(Common Language Runtime, CLR)
.NET での言語共通のJITコンパイラおよび動作環境です。CLIでも採用しています。
JIS X 3016:2010 (ISO/IEC 23271:2006)
https://kikakurui.com/x3/X3016-2010-01.html
第1章 概念及びアーキテクチャ
第2章 メタデータ定義及び意味
5 一般的な構文
6 アセンブリ,目録及びモジュール
15 メソッドの定義,参照,及び呼出し
第3章 CIL命令集合
3 基本命令
4 オブジェクトモデル命令
第4章 プロファイル及びライブラリ
5 標準ライブラリ
第5章 デバッグ情報交換形式
第6章 附属書
附属書B(参考)見本プログラム
附属書C(参考)CILアセンブラの実装
附属書E(参考)可搬性に関する考察
言語プロセッサの区分
翻訳の方法にはコンパイラ以外にインタプリタやジェネレータなどもあります。
- コンパイラ
- 多くの高水準言語(Java、C、COBOLなど)はコンパイラ方式です。この特徴は,ソースプログラムの全体を一つのかたまりとして翻訳しロードモジュールとして実行します。
- プログラム全体を作成しないと実行させてチェックすることができないし,プログラムの一部を修正したときも,全体を翻訳する必要があります。そのために,1回しか使わないようなプログラムを作成するのには非効率です。
- 逆に,1回ロードモジュールを作成しておけば,実行時に毎回コンパイルする必要がありませんので,何度も利用するプログラムに適しています。
- インタプリタ
- インタプリタは,ソースプログラムを1行づつ翻訳して実行する方式です。代表的なインタプリタ言語にJavascript、Ruby、Pythonなどスクリプト言語の多くはインタプリタです。
プログラムを一部作成して実行し逐次追加修正するのが容易ですから,プログラムを作成する段階では便利な方式です。
しかし,実行のたびに翻訳をする必要があるので,何度も利用するプログラムでは非効率です。また,大量のデータを用いるプログラムでは,一つのデータを処理するたびに翻訳することが起こりますので,処理が非効率になります。
- ジェネレータ
- プログラムの一部をパラメタとして与えることにより,完成したプログラムを出力する方式です。これにはソースプログラムを出力してコンパイルするものと,既に実行可能プログラムがあり最初にパラメタを読み込み,それを用いてデータを読み込み帳票作成などをするようなものがあります。
- シミュレータ
- 他のOSでのアプリケーションと同じように動作する環境を実現します。例えばゲーム専用機のゲームを通常のパソコンで実現し、利用者はゲーム専用機とパソコンとの区別ができない環境になります。
パソコン上でゲーム機の機能に相当するパソコンでの命令を生成する一種のコンパイラがシミュレータです。
- エミュレータ
- シミュレータとほぼ同じ目的ですが、シミュレータが外から見た振る舞いを再現するのに対して、エミュレータは中身の動作まで再現します。これを実現するには、コンパイラレベルのものもありますが、ゲーム機のプログラム命令を解読しながら実行するマイクロプログラムを用いる方法があります。
古典的高級言語のコンパイル
主にFORTRANやCOBOLなど、汎用コンピュータ用高級言語を対象とした手順です。
プログラミング言語の文法に従って記述されたソースプログラムは,コンパイルされて目的プログラムになり,連係編集されてロードモジュールになります。
- コンパイル
- プログラミング言語の文法に従って記述されたプログラムをソースプログラムあるいはソースコード、原始プログラムといいます。通常の高水準言語では,ソースプログラムをいったんアセンブラ言語に翻訳する必要があります。それをコンパイルといい,コンパイルするソフトウェアをコンパイラといいます。それで,高水準言語のことをコンパイラということもあります。
コンパイルされた結果を目的プログラムあるいはオブジェクトモジュールといいます。これは通常はアセンブラ言語になっています。ですから,アセンブラ言語で記述されたソースプログラムは,それ自体が目的プログラムになります。
- 連係編集(リンカー)
- 高水準言語では,全体の処理を一つのプログラムとして記述するのではなく,ロジックをいくつかのサブプログラムに分解し,それらをつなぎ合わせてプログラムにする方法が取られます。それらのサブプログラムは部品として他のプログラムにも利用されることがあります。また,言語プロセッサは多様な共通利用サブプログラムを多く持っています。それらはライブラリとして保管されています。
連係編集(リンカー)とは,作成した目的プログラムとライブラリにある既存の目的プログラム群を組み合わせて,一つの機械語プログラムに翻訳します。この機械語プログラムのことを実行可能プログラムあるいはバイナリーコード、ロードモジュールといいます。すなわち,機械語で作成したソースプログラムは,それ自体がロードモジュールになっています。
この翻訳プログラムを連係編集プログラムあるいはリンケージ・エディタといいます。言語プロセッサとしてのアセンブラはこの機能を持っています。なお,目的プログラムでは高水準言語の特性は失われますので,COBOLで作成した目的プログラムとFORTRANで作成したライブラリを連係することもできます。
- 静的リンキングと動的リンキング
- プログラムの実行前に,リンケージ・エディタを用いてリンクするのを静的リンキング(static linking)といいます。それに対して動的リンキング(dynamic linking)とは、プログラムの実行時に必要に応じて,主記憶上に変数領域やデータ領域をロードする機能です。これにより、実行前にすべてのモジュールを主記憶にロードする必要がなく,主記憶の無駄な使用が削減されます。
コンパイラに関する補足
- プレコンパイラ
- ソースプログラムで、よく用いられる記述、あるいは、コンパイラに指示する事項を特定の方法で記述しておき、それをプレコンパイラを通すことにより、正規の文法によるソースプログラムを生成します。
ジェネレータも一種のプレコンパイラだといえますが、ジェネレータは特定のプログラムを対象にしているのに対して、プレコンパイラは一般のプログラムを対象にしています。
- 最適化コンパイラ
- コンパイラがソースプログラムを翻訳するのに際して、効率の良いアルゴリズムや機械語に変換する機能を最適化機能といいます。
- 段階での最適化最適化
例えば、左のプログラムは右に変換することにより、負荷の大きな計算の回数を減らすことができます。
元のソースプログラム 改良したプログラム
sqx = sqrt(x);
for (i==1; i<=10; i++) { for (i==1; i<=10; i++) {
a[i] = a[i] + sqrt(x); a[i] = a[i] + sqx;
} }
コンパイル効率よりも実行処理効率を重視し、このような最適化を高度に行うコンパイラを最適化コンパイラといいます。
- 機械語命令に翻訳するときの最適化
VLIW(Very Long Instruction Word)とは、パイプライン方式などの並行処理をしやすくするために、複数の機械語命令を語長の長い固定長の命令に生成する技術です。VLIWを発展させたものにEPIC(Explicitly Parallel Instruction Computing)があります。
- クロスコンパイラ
- 他のコンピュータで実行するプログラムを生成するコンパイラです。異なる命令形式のコンピュータで実行できる目的プログラムを生成します。例えば、組込みシステム用のプログラムやスマートフォン用のアプリなどを、通常のシステム開発環境で作成するときに使われます。
シミュレータやエミュレータと似ていますが、これらが利用環境の模倣を目的としているのに対し、クロスコンパイラは対象コンピュータで動作するプログラムの生成を目的にしています。
- 制御フロー図(Control Flow Graph:CFG)
-
- プログラムを実行したときに通る制御の流れをを図で表したものです。プログラムの到達不能なコードを簡単に見つけることができ、ループなどの構文構造を見つけるのが簡単なので、静的コード解析やコンパイラ最適化などで使われます。