共通中間言語(きょうつうちゅうかんげんご、英語: Common Intermediate Language、略称 : CIL("sil" や "kil" と発音される))は、共通言語基盤 (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コードは安全のため実行時に検証され、ネイティブにコンパイルされた実行可能ファイルよりも優れた安全性と信頼性を提供する。

実行プロセスは以下のようなものである。

1. ソースコードはCILに変換される。CILは、CLIにとってはCPUに対するアセンブリと等価なものである。
2. さらに、CILはいわゆるバイトコードの形に組み立てられ、アセンブリが生成される。
3. CLIアセンブリの実行中、ネイティブコードを生成するためランタイムのJITコンパイラにコードが渡される。このステップを省き事前コンパイルも利用できるが、実行可能ファイルの移植性が犠牲となる。
4. ネイティブコードがコンピュータのプロセッサで実行される。

## 命令

CILバイトコードは以下のタスクのグループに分けられる命令である。

- ロードおよびストア
- 算術
- 型変換
- オブジェクトの作成および操作
- 評価スタック管理 (push / pop)
- 制御転送 (分岐)
- メソッド呼び出しおよび復帰
- 例外を投げる
- モニタベースの同時実行制御

## 計算モデル

CILはオブジェクト指向かつスタックベースである。これは、たいていのプログラミング言語同様、命令のパラメータと結果が、いくつかのレジスタや他のメモリ領域に保持されるのではなく、単一のスタック上に保持されることを意味する。

x86における加算命令のアセンブリコード例を挙げる。

ここで、eaxとedxは汎用レジスタであり、上記はeaxにedxの内容を加算代入している。

これに相当する中間言語 (IL) のコードは以下のように表せる。

ここで、スタック上に2つのローカル変数がプッシュされる。加算命令が呼び出された際にオペランドがポップされ結果がプッシュされる。残った値はその後ポップされ最初のローカル変数にストアされる。

### オブジェクト指向概念

CILは同様にオブジェクト指向概念に拡張される。オブジェクトを作成したり、メソッドを呼び出したり、そしてフィールドのような他の型のメンバーを使用したりできる。

CILはオブジェクト指向に設計され、各メソッドは(いくつかの例外を除き)クラスに属する必要がある。これは静的メソッドにもあてはまる。

このメソッドは、`Foo`のインスタンスを宣言することを要求しない。なぜならそれは静的だからである。このことは、メソッドがクラスに属し、C#では以下のように利用されることを意味する。

CILにおいては、以下のようになる。

#### インスタンスクラス

インスタンスクラスには、最低でも1つのコンストラクタと、いくつかのインスタンスメンバーが含まれる。以下のクラスは`Car`オブジェクトの振る舞いを表すメソッドのセットである。

#### オブジェクト作成

C#クラスインスタンスは以下のようにして作成される。

上記のステートメントは大体以下のような命令と同じである。

#### インスタンスメソッド呼び出し

インスタンスメソッドは以下のように呼び出される。

CILにおいては、以下のようになる。

### メタデータ

CLIはコンパイルされたクラスについての情報をメタデータとして記録する。Component Object Modelのタイプライブラリのように、メタデータによってアプリケーションが、アセンブリ内にあるインターフェイス、クラス、型、メソッド、そしてフィールドをサポートし発見することを可能とする。このようなメタデータを読み取る処理はリフレクションと呼ばれる。

メタデータは属性 の形式のデータである。カスタム属性は`Attribute`クラスを継承することで作ることができる。これはとても強力な機能である。クラスの作成者が付加した追加情報は、クラスの消費者によってアプリケーション毎に様々な方法で活用される。

## 例

以下はCILで書かれた基本的なHello worldプログラムであり、文字列 "Hello, world!" をコンソールに表示する。

以下のコードはオペコードの数をより複雑にしたものである。

以下のコードはJavaバイトコードについての記事の当該コードと比較することもできる。

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にも、事前コンパイルを処理するためのオプションがある。