Přehled GCC je rozšířena sestavování potrubí, včetně specializovaných programů jako preprocesor, assembler a linker.
GCC následuje 3-fáze typickou architekturou multi-jazyk a multi-CPU kompilátory. Všechny programové stromy jsou převedeny na společnou abstraktní reprezentaci na „Středním konci“, což umožňuje optimalizaci kódu a zařízení pro generování binárních kódů sdílet všechny jazyky.,
externí rozhraní GCC se řídí unixovými konvencemi. Uživatelé vyvolat jazyk-konkrétní program ovladače (gcc
C, g++
pro C++, atd.), který interpretuje příkazové argumenty, volá skutečný kompilátor, spustí assembler na výstupu a poté volitelně spustí linker, aby vytvořil kompletní spustitelný binární soubor.
každý z překladačů jazyků je samostatný program, který čte zdrojový kód a výstupy strojový kód. Všechny mají společnou vnitřní strukturu., Per-language front end analyzuje zdrojový kód v tomto jazyce a vytváří abstraktní strom syntaxe (zkráceně“ strom“).
ty jsou v případě potřeby převedeny na vstupní reprezentaci středního konce, nazývanou generická forma; střední konec pak postupně transformuje program směrem k jeho konečné podobě. Optimalizace kompilátoru a techniky statické analýzy kódu (například fortify_source, směrnice kompilátoru, která se pokouší objevit některé přetečení vyrovnávací paměti) jsou aplikovány na kód., Pracují na více reprezentacích, většinou na architektuře nezávislé gimple reprezentaci a na architektuře závislé RTL reprezentace. Konečně, strojový kód je vyráběn pomocí architektury specifické vzorové shody původně založené na algoritmu Jacka Davidsona a Chrise Frasera.
GCC byl napsán primárně v C s výjimkou částí předního konce Ada. Distribuce zahrnuje standardní knihovny pro ada, C++ a Java, jejichž kód je většinou napsán v těchto jazycích., Na některých platformách, distribuce také obsahuje low-level runtime knihovny libgcc, napsaný v kombinaci stroj-nezávislý C a procesor-konkrétní strojový kód, určený především zvládnout aritmetické operace, že cílový procesor nelze provést přímo.
GCC používá ve své konstrukci mnoho standardních nástrojů, včetně Perl, Flex, Bison a dalších běžných nástrojů. Kromě toho v současné době vyžaduje, aby byly k dispozici tři další knihovny: GMP, MPC a MPFR.
v květnu 2010 se řídící výbor GCC rozhodl povolit použití kompilátoru C++ pro kompilaci GCC., Kompilátor měl být napsán převážně v C plus podmnožině funkcí z c++. Zejména bylo rozhodnuto, aby vývojáři GCC mohli používat destruktory a generické funkce C++.
v srpnu 2012 řídící výbor GCC oznámil, že GCC nyní používá C++ jako implementační jazyk. To znamená, že pro sestavení GCC ze zdrojů je vyžadován kompilátor C++, který chápe normu ISO/IEC C++03.,
Přední endsEdit
Přední končí skládá z předzpracování, lexikální analýza, syntaktická analýza (parsování) a sémantické analýzy. Cílem kompilátoru front ends je buď přijmout nebo odmítnout kandidátské programy podle jazykové gramatiky a sémantiky, identifikovat chyby a zpracovat platné programové reprezentace do pozdějších fází kompilátoru. Tento příklad ukazuje kroky lexer a parser provedené pro jednoduchý program napsaný v C.,
každý přední konec používá analyzátor k vytvoření abstraktního stromu syntaxe daného zdrojového souboru. Vzhledem k abstrakci stromu syntaxe mohou být zdrojové soubory kteréhokoli z různých podporovaných jazyků zpracovány stejným zadním koncem. GCC začal používat LALR parsery generované s Bizonem, ale postupně přešel na ruku-napsaný rekurzivní-sestup parsery pro C++ v roce 2004, a pro C a Objective-C v roce 2006. Od roku 2021 používají všechny přední konce ručně psané rekurzivní sestupové parsery.
do GCC 4.,0 stromová reprezentace programu nebyla zcela nezávislá na cíleném procesoru. Význam stromu byl poněkud odlišný pro různé jazykové přední konce a přední konce mohly poskytnout své vlastní stromové kódy. To bylo zjednodušeno zavedením generických a GIMPLE, dvou nových forem jazykově nezávislých stromů, které byly zavedeny s příchodem GCC 4.0. GENERIC je složitější, založený na GCC 3.x Java front end je střední reprezentace. GIMPLE je zjednodušený generik, ve kterém jsou různé konstrukty sníženy na více instrukcí GIMPLE., Přední konce C, C++ a Java produkují generické přímo na předním konci. Ostatní přední konce místo toho mají různé mezilehlé reprezentace po analýze a převést je na generické.
v obou případech takzvaný“ gimplifier “ pak převádí tuto složitější formu na jednodušší GIMPLE formu založenou na SSA, která je společným jazykem pro velké množství výkonných globálních optimalizací nezávislých na jazyce a architektuře.,
GENERIC a GIMPLEEdit
GENERIC je mezilehlý reprezentační jazyk používaný jako“ prostřední konec “ při kompilaci zdrojového kódu do spustitelných binárních souborů. Podmnožina, nazývaná GIMPLE, je zaměřena na všechny přední konce GCC.
střední fázi GCC dělá všechny kód analýzy a optimalizace, pracující nezávisle na sobě z obou zkompilovaný jazyk a cílové architektury, počínaje DRUHOVÉ zastoupení a rozšíření k registraci převodu jazyk (RTL)., Generická reprezentace obsahuje pouze podmnožinu imperativních programovacích konstruktů optimalizovaných středním koncem.
při transformaci zdrojového kódu na GIMPLE jsou složité výrazy rozděleny do tří adresního kódu pomocí dočasných proměnných. Tato reprezentace byla inspirována JEDNODUCHÉ znázornění navrhované v McCAT kompilátor Laurie J. Hendren pro zjednodušení analýzy a optimalizace nezbytné programy.,
OptimizationEdit
Optimalizace může nastat v každé fázi kompilace; nicméně, většina z optimalizace jsou prováděny po syntaktické a sémantické analýzy přední konec a před generování kódu z back-end; tak běžný, i když poněkud rozporuplné, název pro tuto část kompilátor je „middle end.“
sada GCC optimalizace se liší od vydání k vydání, jak se to vyvíjí, ale zahrnuje standardní algoritmy, jako jsou smyčky optimalizace, skok threading, společné seskupení odstranění, instrukce plánování, a tak dále., Optimalizace RTL mají menší význam s přidáním globálních optimalizací založených na SSA na GIMPLE stromech, protože optimalizace RTL mají mnohem omezenější rozsah a mají méně informací na vysoké úrovni.
některé z těchto optimalizací provedených na této úrovni zahrnují eliminaci mrtvého kódu, eliminaci částečné redundance, číslování globální hodnoty, řídké podmíněné konstantní množení a skalární výměnu agregátů. Jsou také prováděny optimalizace založené na závislosti na poli, jako je automatická vektorizace a automatická paralelizace. Optimalizace s řízeným profilem je také možná.,
Back endEdit
GCC back-end je částečně uvedeno do preprocesoru makra a funkce specifické pro cílovou architekturu, například definovat jeho endian, slovo velikost, a volací konvence., Přední část zadního konce je používá k rozhodování o generaci RTL, takže i když je RTL GCC nominálně nezávislý na procesoru, počáteční sekvence abstraktních pokynů je již přizpůsobena cíli. V každém okamžiku musí skutečné pokyny RTL tvořící reprezentaci programu splňovat strojový popis cílové architektury.
soubor s popisem stroje obsahuje RTL vzory spolu s omezeními operandu a úryvky kódu pro výstup konečné sestavy., Omezení naznačují, že určitý vzor RTL se může vztahovat pouze (například) na určité hardwarové Registry, nebo (například) povolit okamžité offsety operand pouze omezené velikosti (např… bitové offsety atd.). Během generování RTL jsou kontrolována omezení pro danou cílovou architekturu. Aby bylo možné vydat daný úryvek RTL, musí odpovídat jednomu (nebo více) vzorců RTL v souboru popisu stroje a splňovat omezení pro tento vzor; V opačném případě by nebylo možné převést konečný RTL na strojový kód.,
ke konci kompilace je platný RTL redukován na přísný formulář, ve kterém každá instrukce odkazuje na reálné registry strojů a vzor Ze souboru popisu stroje cíle. Vytvoření přísného RTL je složitý úkol; důležitým krokem je přidělování registrů, kde jsou vybrány skutečné hardwarové registry, které nahradí původně přiřazené pseudo-registry. Následuje fáze „překládky“; všechny pseudo-registry, kterým nebyl přidělen skutečný hardwarový registr, jsou „rozlité“ do zásobníku a RTL k provedení tohoto rozlití je generován., Stejně tak musí být kompenzace, které jsou příliš velké, aby se vešly do skutečné instrukce, rozděleny a nahrazeny sekvencemi RTL, které budou dodržovat omezení posunu.
V konečné fázi, stroj je postaven kód voláním malý fragment kódu, spojené s každou vzor, generovat skutečné instrukce z cílové instrukční sadu, pomocí konečné registrů, offsety, a adresy, které byly vybrány v jiný fázi. Úryvek generace sestavy může být pouze řetězec, v takovém případě se provede jednoduchá náhrada řetězců registrů, offsetů a/nebo adres do řetězce., Úryvek generace sestavy může být také krátkým blokem kódu C, který provádí nějakou další práci, ale nakonec vrací řetězec obsahující platný montážní kód.
Další featuresEdit
Některé funkce GCC patří:
- Link-time optimization optimalizuje přes object file hranice přímo zlepšit spojeny binární. Optimalizace Link-time závisí na mezilehlém souboru obsahujícím serializaci nějaké reprezentace Gimple obsažené v objektovém souboru. Soubor je generován spolu s objektovým souborem během kompilace zdroje., Každá zdrojová kompilace generuje samostatný soubor objektu a pomocný soubor link-time. Když jsou soubory objektů propojeny, kompilátor je znovu spuštěn a používá pomocné soubory k optimalizaci kódu v rámci Samostatně kompilovaných objektových souborů.
- pluginy mohou přímo rozšířit kompilátor GCC. Pluginy umožňují skladový kompilátor přizpůsobit specifickým potřebám externím kódem načteným jako pluginy. Například pluginy mohou přidávat, nahrazovat nebo dokonce odstraňovat prostřední koncové průchody pracující na reprezentacích Gimple., Několik GCC pluginy již byly zveřejněny, zejména GCC Python plugin, který spojuje proti libpython, a umožňuje vyvolat libovolné Python skripty zevnitř kompilátoru. Cílem je umožnit GCC pluginy, které mají být napsány v Pythonu. Plugin MELT poskytuje jazyk Lisp na vysoké úrovni pro rozšíření GCC.
- C++ transakční paměť při kompilaci s-fgnu-tm.
- od GCC 10, identifikátory umožňují kódování UTF-8 (Unicode), tj. zdrojový kód C používá ve výchozím nastavení kódování UTF-8.