Common Intermediate Language

Z Wikipedie, otevřené encyklopedie
Skočit na: Navigace, Hledání

Common Intermediate Language (CIL, vyslovováno jako „sil“, případně „kil“, dříve Microsoft Intermediate Language, MSIL) je v informatice nejnižší člověkem čitelný programovací jazyk definovaný specifikací Common Language Infrastructure používaný projekty .NET Framework a Mono. Jazyky, které se zaměřují na CLI kompatibilní prostředí, jsou sestavovány do byte kódu (Bytecode). CIL patří mezi objektově orientované jazyky výhradně zásobníkového typu (anglicky stack-based). Prováděn je prostřednictvím virtuálního stroje.

CIL byl původně během uvolňování beta .NET jazyků znám jako Microsoft Intermediate Language (MSIL). Vzhledem ke standardizaci C# a Common Language Infrastructure je byte-kód nově a oficiálně označován jako CIL.

Základní informace[editovat | editovat zdroj]

Při kompilování .NET programovacích jazyků je zdrojový kód přeložen do CIL kódu (nepoužívá se platformně nebo do výpočetně specifický objektový kód). CIL je procesorově a zároveň platformě nezávislý soubor instrukcí, které mohou být realizovány v jakémkoli prostředí podporující Common Language Infrastructure (může se jednat buď o .NET runtime pro operační systém Microsoft Windows, nebo samostatně odvozené Mono, které pracuje pod operačními systémy jako Linux či Unix). CIL kód je za běhu ověřován z hlediska bezpečnosti, a proto poskytuje lepší zabezpečení a spolehlivost, než nativně kompilované binární soubory.

Proces spuštění vypadá takto:

  1. Zdrojový kód je převeden do Common Intermediate Language, CLI ekvivalent k nižším programovacím jazykům pro CPU.
  2. CIL je pak převeden do byte-kódu a je vytvořeno .NET assembly.
  3. Po provedení .NET assembly, jeho byte kód projde skrz provozní JIT kompilátor, aby generoval nativní kód.
  4. Nativní kód je zpracováván pomocí procesoru.

Instrukce[editovat | editovat zdroj]

CIL bytecode má instrukce pro následující skupiny úloh:

  • Načítání a ukládání
  • Aritmetické
  • Typ konverze
  • Vytváření objektů a manipulaci s nimi
  • Operand managementu zásobníku (push / pop)
  • Kontrola převodu (větvení - Branching)
  • Volání metod
  • Vyhazování výjimky
  • Synchronizace

Výpočetní model[editovat | editovat zdroj]

Common Intermediate Language je považován za objektově orientovaný jazyk zásobníkového typu (stack-based). To znamená, že data jsou ukládána z registrů do zásobníku místo toho, aby byla odkládána do paměti jako ve většině CPU architektur.

V architektuře x86 by to mohlo vypadat následovně:

add eax, edx
mov ecx, eax

Odpovídající kód v CIL by mohl vypadat takto:

ldloc.0
ldloc.1
add
stloc.0 // a = a + b or a += b;

V programu jsou použity dvě lokálně proměnné, které jsou přesunuty do fronty. Když je přidaná instrukce zavolána, operand je ze zásobníku vyzvednut a výsledek je na něj obratem uložen. Hodnota je pak vyzvednuta a uložena jako první lokální proměnná.

Objektově-orientované koncepty[editovat | editovat zdroj]

V objektově-orientovaném konceptu můžete vytvářet objekty, volat metody a používat další typy členů, jako jsou například pole. CIL je navržen jako objektově orientovaný a všechny metody (až na výjimky) musí být obsažené v příslušné třídě.

Příklad statické metody:

.class public Foo
 {
 .method public static int32 Add(int32, int32) cil managed
 {
 .maxstack 2
 .locals init (
 [0] int32 num1,
 [1] int32 num2
 )
 
 ldloc.0
 ldloc.1
 add
 stloc.0 // a = a + b or a += b;
 ret // return a;
 }
 }

Použitá metoda nevyžaduje žádnou deklaraci instance třídy Foo, protože je statická. To znamená, že náleží do třídy a může být následně použita jako v tomto případě v C#.

int r = Foo.Add(2, 3); //5

V CIL

ldc.i4.2
ldc.i4.3
call int32 Foo::Add(int32, int32)
stloc.0

Instance tříd[editovat | editovat zdroj]

Instance třídy obsahuje nejméně jeden konstruktor a nějaké další členy. Tato třída má sadu metod reprezentujících akce objektu Car.

.class public Car
 {
 .method public specialname rtspecialname
 instance void .ctor(int32, int32) cil managed
 {
 /* Constructor */
 }
 
 .method public void Move(int32) cil managed
 {
 /* Omitting implementation */
 }
 
 .method public void TurnRight() cil managed
 {
 /* Omitting implementation */
 }
 
 .method public void TurnLeft() cil managed
 {
 /* Omitting implementation */
 }
 
 .method public void Break() cil managed
 {
 /* Omitting implementation */
 }
 }

Vytváření objektů[editovat | editovat zdroj]

Instance tříd jsou v C# vytvářeny následujícím způsobem:

Car myCar = new Car(1, 4); 
Car yourCar = new Car(1, 3);

Příkazy jsou přibližně stejné jako tyto instrukce:

ldc.i4.1
ldc.i4.4
newobj instance void Car::.ctor(int, int)
stloc.0 // myCar = new Car(1, 4);
ldc.i4.1
ldc.i4.3
newobj instance void Car::.ctor(int, int)
stloc.1 // yourCar = new Car(1, 3);

Vyvolání metody instance[editovat | editovat zdroj]

Například metody jsou volány následovně:

myCar.Move(3);

V CIL

ldloc.0 // Load the object "myCar" on the stack
ldc.i4.3
call instance void Car::Move(int32)

Metadata[editovat | editovat zdroj]

.NET zaznamenává informace o kompilovaných třídách jako metadata. Proces čtení těchto metadat se nazývá zrcadlení (reflection). Metadata mohou být data v podobě atributů. Ty mohou být volně rozšířeny o atributy třídy, čímž se stávají velmi silným nástrojem.

Příklad[editovat | editovat zdroj]

Příklad je napsán v CIL a demonstruje kód „Hello, World“:

.assembly Hello {}
.assembly extern mscorlib {}
.method static void Main()
{
 .entrypoint
 .maxstack 1
 ldstr "Hello, world!"
 call void [mscorlib]System.Console::WriteLine(string)
 ret
}

Tento kód může být porovnán s odpovídajícím kódem Java Bytecode:

static void Main(string[] args)
{
outer:
 for (int i = 2; i < 1000; i++)
 {
 for (int j = 2; j < i; j++)
 {
 if (i % j == 0)
 goto outer;
 }
 Console.WriteLine(i);
 }
}

V CIL-syntaxi by zápis vypadal následovně:

.method private hidebysig static void Main(string[] args) cil managed
 {
 .entrypoint
 .maxstack 2
 .locals init (int32 V_0,
 int32 V_1)
 
 IL_0000: ldc.i4.2
 stloc.0
 br.s IL_001f
 IL_0004: ldc.i4.2
 stloc.1
 br.s IL_0011
 IL_0008: ldloc.0
 ldloc.1
 rem
 brfalse.s IL_0000
 ldloc.1
 ldc.i4.1
 add
 stloc.1
 IL_0011: ldloc.1
 ldloc.0
 blt.s IL_0008
 ldloc.0
 call void [mscorlib]System.Console::WriteLine(int32)
 ldloc.0
 ldc.i4.1
 add
 stloc.0
 IL_001f: ldloc.0
 ldc.i4 0x3e8
 blt.s IL_0004
 ret
 }

Výše je správná reprezentace toho, jak vypadá CIL blízko VM úrovně. Když jsou zkompilované metody uloženy v tabulkách a instrukce zase v bytech uvnitř assembly, který je přenosně spustitelným souborem (Portable Executable-file).

Vývoj[editovat | editovat zdroj]

CIL assembly a instrukce jsou generovány buď kompilátorem nebo nástrojem zvaným jako IL Assembler (ILASM). Složené IL může být také znovu rozloženo do kódu užitím IL Disassembler (ILDASM). Existují další nástroje jako .NET Reflektor, které umožní dekompilaci IL do jazyků vyšší úrovně (např. C#, Visual Basic). Tato vlastnost je sdílená s Java bytecode. Ale existují nástroje, které mohou zmást kód, a to tak, že vlastní kód nemůže být rozložen, ale přesto je spustitelný.

Kompilace just-in-time[editovat | editovat zdroj]

Kompilace just-in-time (JIT) překládá byte-kód do kódu vykonatelného přímo CPU, tzv. nativního kódu. Tento překlad je prováděn během provádění programu. JIT kompilace poskytuje optimalizace specifické pro prostředí, typovou bezpečnost kontrolovanou za běhu a verifikaci. K dosažení tohoto kompilátor testuje metadata nashromážděná během překladu na nepovolené přístupy do paměti.

Externí odkazy[editovat | editovat zdroj]

V tomto článku byl použit překlad textu z článku Common Intermediate Language na anglické Wikipedii.