Kompiler
^^^^^^^^
Nejdůležitelší program pod GNU je nesporně kompiler. Ten umožnil
aby vzniklo všechno ostatní. A není to jen tak ledajaký kompiler.
Chtěl bych vysvětlit, čím se odlišuje od klasických (třeba
Borlandích) kompilerů.
Klasický kompiler napřed načte vstup, rozloží ho na tokeny a
poruzumí mu. Když už ví, co programátor napsal, přidělí pamětová
místa proměným (modernější používají i registry) a potom pomocí
jakýchsi prefabrikátů na každý příkaz jazyka složí výsledný kód.
Případně se ješte pokusí předvyhodnotit výrazy, kde je očividně
všechno konstantní, nebo se rozhlédne po vzniklém assembleru a
vymění pár instrukcí, které se často špatně generují. Vzniklou
skládačku potom pošle dál.
GNU kompiler má jiné řešení. Nejprve porozumí programu. Toto je
jediná část závislá na jazyce a nazývá se parsing. Potom se
vygeneruje mezijazyk zvaný Register transfer language (RTL). Od
tohoto okamžiku už je kompileru jedno, jestli kompiluje C, nebo
pascal. Mezijazyk je podobný lispu. Tedy ideální pro strojové
zpracování, protože všechny příkazy mají stejnou syntax (liší se
pouze akcí) a obsahují dodatečně šikonvé informace, jako třeba co
potřebuje za vstup/výstup a co modifikuje. Všechny proměné/pamět
jsou unifikovány do registrů (tedy třeba pole je také registr).
Jazyk není reprezentován textově ale ve specialní struktuře tak, aby
se s ním dobře pracovalo. Jde ale uložit do textové podoby. Třeba
následující hloupý přiklad:
main()
{
return(0);
}
Má mezikód
No je vidět, že to není zrovna nic moc optimálního :). Ale je to
něco. Teď se dostanou ke slovu optimizéry. Valná většina je
nezávislá na architektuře (procesoru) protože ani RTL se zatím moc
asembleru nepodobá (snad až na jména registrů). Optimizerů je hodně.
Takže jenom krátký popis:
Optimizace skoků - zrušení skoků na skoky
Scanování registrů - tady se najde kdy který registr (krycí název
pro proměnou) byl použit poprvé/naposled
Optimizace skoků, které skačou na stejný/opačný test - ty můžou být
vyhozeny
Propagace konstant, eliminace expresion - propagace konstant se snaží
dosadit konstanty za registry. Pokud jsou nějaké
expresion bez vstupů/výstupů a vedlejších efektů,
nebo můžou byt vyhodnoceny tak se vyhodí/vypočtou.
To zkracuje výrazy, vyhodí nepotřebné části
programu atd.
Optimizace smyček - Snaží se všechno, co jenom jde vyhodit ven
znova eliminace expresion
Analýza toku dat - Rozdělí program do bloků, vyhazuje nedosažitelné
smyčky, a zjištůje, kde který registr je "živý" to
znamená že je třeba uchovávat jeho hodnotu, najde
výpočty, kde výsledek není použit.
Kombinace instrukcí - (ne assemblerových ale těch RTL) Spojuje
instrukce, keré jdou do jedné, používa algebru na
optimizaci mat. výrazů a přidělí RTL kódu opravdové
instrukce, které odpovídají popisu procesoru. (ano
tahle část je částečně závislá na architektuře)
Scheduling instrukcí - poskládá instrukce tak, aby dobře lezly do
superskalárních riscových procesorů. Verze 2.8.0
(která ještě není to bude dělat i pro pentia/sextia)
Třídy registrů - hardwarové registry mají několik tříd. Tak třeba pamět
(zásobník), registry procesoru, registry koprocesoru.
Tato část rozhodne, které třídy registru použít pro
ten daný pseudoregistr.
Alokace registrů - tady se konečně rozhodne, které proměné budou ve
výsledném programu uloženy a kdy
Globální alokace registrů - to samé ale pro globání proměné
Reloading - tady se dosadí hardwarové registry registrům a zbytek se
uloží do zásobníku
Další scheduling - aby se instrukce nehádaly o pamět
Znova optimizace skoků, další scheduling
optimizace zasobníkových registrů - to je special pro 386kový kopr
Převod do assembleru - a dílo je hotovo.
Tohle zbylo z našeho příkladu
Z toho vyrobit assembler je uz hračka: (Je v AT&T syntaxi. Ale
snad to je jasné)
main:
xorl %eax,%eax
ret
Abych ukázal kvalitu kódu ještě jeden hloupý příklad:
main()
{int i,a=1,b=0;
for(i=0;i<9999;i++)
a=a+b,b=2*a;
printf("%i\n",a);
}
Z gnu vylezo (teda mimo toho kometáře) A tohle vyrobil borland
No myslím že srovnání je dost výmluvné ale v časopisech bývají
nějaké ty tabulky s časem. Tak dobře. Rozhodl jsem se pro výpočet
mandelbrotky. Je to celkem netriviální, koprocedor využívající
smyčka z realného života. Tak se na tom má kompiler co činit. Testy
si ale musíte přečíst až na druhé stránce
výheň