共通中間言語

共通中間言語（きょうつうちゅうかんげんご、、略称 : CIL（））は、共通言語基盤 (Common Language Infrastructure、CLI) において定義されている、人間が解読可能な最も低水準なプログラミング言語である。これは.NET FrameworkやMonoにより使用される。CLI互換な実行環境をターゲットとしている言語はCILにコンパイルされる。そのCILはバイトコードスタイルフォーマットであるオブジェクトコードにより組み立てられている。CILはオブジェクト指向なアセンブリ言語であり、完全なスタックベースである。そのバイトコードはネイティブコードに翻訳されるか、仮想機械により実行される。
.NET言語がベータリリースである間、CILはMicrosoft Intermediate Language (MSIL) と呼ばれていた。C#およびCLIの標準化により、現在ではバイトコードは公式にCILと呼ばれる。
概要.
CLIプログラミング言語のコンパイルにより、ソースコードはプラットフォームやプロセッサ固有のオブジェクトコードではなく、CILコードに翻訳される。CILはCPUやプラットフォームに依存しない命令セットである。従って、CILはWindows上の.NETランタイムやクロスプラットフォームなMonoランタイムのようなCLIをサポートするどんな環境でも動作する。この性質により、理論的にはプラットフォームやCPUの種類に応じて異なる実行可能ファイルを配布する必要がなくなる。CILコードは安全のため実行時に検証され、ネイティブにコンパイルされた実行可能ファイルよりも優れた安全性と信頼性を提供する。
実行プロセスは以下のようなものである。
命令.
CILバイトコードは以下のタスクのグループに分けられる命令である。
計算モデル.
CILはオブジェクト指向かつスタックベースである。これは、たいていのプログラミング言語同様、命令のパラメータと結果が、いくつかのレジスタや他のメモリ領域に保持されるのではなく、単一のスタック上に保持されることを意味する。
x86における加算命令のアセンブリコード例を挙げる。
add eax, edx
ここで、eaxとedxは汎用レジスタであり、上記はeaxにedxの内容を加算代入している。
これに相当する中間言語 (IL) のコードは以下のように表せる。
ここで、スタック上に2つのローカル変数がプッシュされる。加算命令が呼び出された際にオペランドがポップされ結果がプッシュされる。残った値はその後ポップされ最初のローカル変数にストアされる。
オブジェクト指向概念.
CILは同様にオブジェクト指向概念に拡張される。オブジェクトを作成したり、メソッドを呼び出したり、そしてフィールドのような他の型のメンバーを使用したりできる。
CILはオブジェクト指向に設計され、各メソッドは（いくつかの例外を除き）クラスに属する必要がある。これは静的メソッドにもあてはまる。
このメソッドは、codice_1のインスタンスを宣言することを要求しない。なぜならそれは静的だからである。このことは、メソッドがクラスに属し、C#では以下のように利用されることを意味する。
int r = Foo.Add(2, 3); // 5
CILにおいては、以下のようになる。
インスタンスクラス.
インスタンスクラスには、最低でも1つのコンストラクタと、いくつかのインスタンスメンバーが含まれる。以下のクラスはcodice_2オブジェクトの振る舞いを表すメソッドのセットである。
オブジェクト作成.
C#クラスインスタンスは以下のようにして作成される。
Car myCar = new Car(1, 4); 
Car yourCar = new Car(1, 3); 
上記のステートメントは大体以下のような命令と同じである。
インスタンスメソッド呼び出し.
インスタンスメソッドは以下のように呼び出される。
myCar.Move(3);
CILにおいては、以下のようになる。
メタデータ.
CLIはコンパイルされたクラスについての情報をメタデータとして記録する。Component Object Modelのタイプライブラリのように、メタデータによってアプリケーションが、アセンブリ内にあるインターフェイス、クラス、型、メソッド、そしてフィールドをサポートし発見することを可能とする。このようなメタデータを読み取る処理は"リフレクション"と呼ばれる。
メタデータは"属性" の形式のデータである。カスタム属性はcodice_3クラスを継承することで作ることができる。これはとても強力な機能である。クラスの作成者が付加した追加情報は、クラスの消費者によってアプリケーション毎に様々な方法で活用される。
例.
以下はCILで書かれた基本的なHello worldプログラムであり、文字列 "Hello, world!" をコンソールに表示する。
以下のコードはオペコードの数をより複雑にしたものである。
以下のコードはJavaバイトコードについての記事の当該コードと比較することもできる。
static void Main(string[] args)
 for (int i = 2; i < 1000; i++)
 for (int j = 2; j < i; j++)
 if (i % j == 0)
 goto outer;
 Console.WriteLine(i);
outer:
CILシンタックスでは、以下のようになる。
これはVMレベル近くでどのようにCILが見えるかを表現したものである。コンパイルされた場合、メソッドはテーブルにストアされ、アセンブリ内部にバイトとして命令がストアされる。そしてそれはPortable Executable (PE) である。
生成.
CILアセンブリおよび命令は、コンパイラと、実行環境と共に送られる"IL アセンブラー" (ILASM) と呼ばれるユーティリティのどちらかで生成される。
アセンブルされたILは"IL 逆アセンブラー" (ILDASM) を使用して再びコードへと逆アセンブルすることもできる。高水準言語（例えばC#やVisual Basic）へと逆コンパイルする.NET Reflectorのような他のツールもある。これにより、ILはリバースエンジニアリングのとても容易なターゲットとなる。この特徴はJavaバイトコードと共通である。しかしながら、コードを難読化するツールもあり、そうすることによりコードが容易に読めなくなるが実行はできるようになる。
実行.
実行時コンパイル.
実行時コンパイルによりバイトコードは、CPUにより即座に実行可能なコードへと変換される。この変換はプログラムの実行中、徐々に実行される。実行時コンパイルは環境固有の最適化、実行時型安全性、そしてアセンブリ検証を提供する。これを達成するため、実行時コンパイラは、任意の不正アクセスに対してアセンブリメタデータを調査し、違反を適切に処理する。
事前コンパイル.
CLI互換な実行環境には、実行時のJIT処理を省いてより高速に実行できるようにするため、アセンブリの事前コンパイルを処理するためのオプションがある。
.NET Frameworkには、事前コンパイルを行う (Native Image Generator、NGEN) と呼ばれる特殊なツールがある。Monoにも、事前コンパイルを処理するためのオプションがある。