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ň