áttekintés a GCC kiterjesztett összeállítási csővezetékéről, beleértve az olyan speciális programokat, mint az előfeldolgozó, assembler és a linker.
GCC követi a többnyelvű és több CPU-fordítókra jellemző 3-fokozatú architektúrát. Minden program fák alakítjuk egy közös absztrakt ábrázolása a “középső végén”, amely lehetővé teszi a kód optimalizálás, bináris kód generációs létesítmények kell osztani az összes nyelven.,
a GCC külső felülete a Unix konvenciókat követi. A felhasználók Nyelvspecifikus illesztőprogram-programot (gcc
C, g++
C++ stb.), amely értelmezi parancs argumentumok, felhívja a tényleges fordító, fut az assembler a kimeneten, majd opcionálisan fut a linker, hogy készítsen egy teljes végrehajtható bináris.
a nyelvi fordítók mindegyike egy külön program, amely forráskódot olvas, és gépi kódot ad ki. Mindegyiknek közös belső szerkezete van., Egy nyelvenkénti front end értelmezi a forráskódot ezen a nyelven, és egy absztrakt szintaxisfát állít elő (röviden” fa”).
Ezek, ha szükséges, átalakítják a középső vég bemeneti ábrázolására, általános formának nevezik; a középső vég ezután fokozatosan átalakítja a programot a végső formája felé. A kódra fordítóoptimalizációkat és statikus kódelemzési technikákat (például FORTIFY_SOURCE, egy fordítóprogram, amely megpróbálja felfedezni a puffer túlcsordulásokat) alkalmaznak., Ezek több ábrázoláson dolgoznak, elsősorban az architektúrától független GIMPLE reprezentáción és az architektúrától függő RTL reprezentáción. Végül a gépi kódot architektúra-specifikus mintaillesztéssel állítják elő, amely eredetileg Jack Davidson és Chris Fraser algoritmusán alapul.
a GCC-t elsősorban C-ben írták, kivéve az Ada elülső részének részeit. A disztribúció tartalmazza az Ada, C++ és Java szabványos könyvtárait, amelyek kódja többnyire ezeken a nyelveken van írva., Néhány platformon, a forgalmazási is tartalmaz egy alacsony szintű runtime library, libgcc, írt egy kombinált gép-független C processzor-konkrét gép kód, amelyet elsősorban kezelni aritmetikai műveleteket, hogy a cél a processzor nem tudja végrehajtani közvetlenül.
a GCC számos szabványos eszközt használ felépítésében, beleértve a Perl-t, a Flex-et, a bölényt és más közös eszközöket. Ezenkívül jelenleg három további könyvtárra van szükség az építéshez: GMP, MPC és MPFR.
2010 májusában a GCC irányítóbizottsága úgy döntött, hogy engedélyezi a C++ fordító használatát a GCC összeállításához., A fordító célja az volt, hogy írt többnyire C plusz egy részhalmaza funkciók C++. Ezt úgy határozták meg, hogy a GCC fejlesztői használhassák a C++destruktorait és generikus funkcióit.
2012 augusztusában a GCC irányítóbizottsága bejelentette, hogy a GCC most a C++ – ot használja végrehajtási nyelvként. Ez azt jelenti, hogy a GCC forrásokból történő felépítéséhez C++ fordítóra van szükség, amely megérti az ISO/IEC C++03 szabványt.,
Front endsEdit
az elülső végek előfeldolgozásból, lexikai elemzésből, szintaktikai elemzésből (elemzésből) és szemantikai elemzésből állnak. A fordító front ends célja, hogy vagy elfogadja vagy elutasítja a jelölt programok szerint a nyelvtan és szemantika, hibák azonosítása és kezelni érvényes program reprezentációk későbbi fordító szakaszában. Ez a példa a C-ben írt egyszerű programhoz végrehajtott lexer-és elemzési lépéseket mutatja.,
minden előlap egy elemzőt használ egy adott forrásfájl absztrakt szintaxisfájának előállításához. A szintaxisfa absztrakciónak köszönhetően a különböző támogatott nyelvek forrásfájljai ugyanazon a hátoldalon dolgozhatók fel. A GCC a bölénnyel generált lalr Parser-ekkel kezdte, de 2004-ben fokozatosan áttért a C++, 2006-ban pedig a C és az Objective-C kézzel írt rekurzív-descent Parser-ekre. 2021-től minden Elülső oldal kézzel írt rekurzív-süllyedő parsert használ.
amíg GCC 4.,0 a program fa ábrázolása nem volt teljesen független a megcélzott processzortól. A fa jelentése némileg eltérő volt a különböző nyelvi front végeinél, az elülső végek pedig megadhatják saját fa kódjaikat. Ezt egyszerűsítették a GENERIC és a GIMPLE bevezetésével, a nyelvfüggetlen fák két új formájával, amelyeket a GCC 4.0 megjelenésével vezettek be. A generikus bonyolultabb, a GCC 3 alapján.x Java front end közbenső ábrázolása. GIMPLE egy egyszerűsített Generikus, amelyben a különböző konstrukciók leengedjük több GIMPLE utasításokat., A C, C++, Java front ends Generikus közvetlenül a front end. Más elülső végek helyett különböző közbenső ábrázolások elemzése után átalakítani ezeket a generikus.
mindkét esetben az úgynevezett “gimplifier” ezt a bonyolultabb formát az egyszerűbb SSA-alapú GIMPLE formává alakítja, amely számos nagy teljesítményű nyelv – és architektúrafüggetlen globális (funkciókör) optimalizálás közös nyelve.,
GENERIC and GIMPLEEdit
GENERIC is an intermediate representation language used as a “middle end” while compiling source code into executable binaries. A GIMPLE nevű részhalmazt a GCC összes elülső vége célozza meg.
a GCC középső szakasza elvégzi az összes kódelemzést és optimalizálást, függetlenül mind az összeállított nyelvtől, mind a célarchitektúrától, kezdve az Általános reprezentációtól, majd kiterjesztve az átviteli nyelv regisztrálására (RTL)., A generikus ábrázolás csak a középső végére optimalizált imperatív programozási konstrukciók részhalmazát tartalmazza.
a forráskód GIMPLE-ként történő átalakításakor a komplex kifejezések ideiglenes változók segítségével három címkódra oszthatók. Ezt a reprezentációt A Laurie J. Hendren által a McCAT fordítóban javasolt egyszerű ábrázolás ihlette az imperatív programok elemzésének és optimalizálásának egyszerűsítésére.,
OptimizationEdit
optimalizálás az összeállítás bármely szakaszában előfordulhat; az optimalizálások nagy része azonban az előlap szintaxisának és szemantikai elemzésének elvégzése után, valamint a hátsó vég kód generálása előtt történik; így a fordító ezen részének közös, bár kissé ellentmondásos neve a “középső vég”.”
A pontos készlet GCC optimalizálás változik kiadásról kiadásra, ahogy alakul ki, de magában foglalja a szabványos algoritmusok, mint a hurok optimalizálás, ugrás threading, közös subexpression megszüntetése, utasítás, ütemezés, stb., Az RTL-optimalizációk kevésbé fontosak a globális SSA-alapú optimalizációk hozzáadásával a GIMPLE trees-en, mivel az RTL-optimalizációk sokkal korlátozottabbak, kevésbé magas szintű információkkal rendelkeznek.
Back endEdit
a GCC ‘ s back end részben meghatározott preprocessor makrók és funkciók specifikus cél architektúra, például, hogy meghatározza a endianness, word size, and calling conventions., A hátsó rész elülső része ezeket használja az RTL generáció eldöntéséhez, tehát bár a GCC RTL névlegesen processzorfüggetlen, az absztrakt utasítások kezdeti sorrendje már alkalmazkodik a célhoz. A program reprezentációját alkotó tényleges RTL utasításoknak bármikor meg kell felelniük a cél architektúra gépleírásának.
a gépleíró fájl RTL mintákat tartalmaz, valamint operanduskorlátokat, valamint kódrészleteket a végső összeállítás kiadásához., A megszorítások azt mutatják, hogy egy adott RTL minta csak bizonyos hardverregiszterekre vonatkozhat (például), vagy (például) csak korlátozott méretű azonnali operandus-eltolásokat tesz lehetővé (például 12, 16, 24,… bit eltolások stb.). Az RTL generáció alatt ellenőrzik az adott célarchitektúra korlátait. Annak érdekében, hogy a kérdést egy adott kódrészletet az RTL, meg kell egyeznie egy (vagy több), az RTL minták a gép leírása a fájl megfelel a korlátait, hogy a minta; különben lehetetlen lenne átalakítani a végső RTL a gépi kód.,
az összeállítás vége felé az érvényes RTL szigorú formára redukálódik, amelyben minden utasítás valódi gépregiszterekre és a cél gépleírási fájljának mintájára utal. A szigorú RTL kialakítása bonyolult feladat, fontos lépés a regiszterelosztás, ahol az eredetileg hozzárendelt pszeudo-regiszterek helyett valódi hardverregisztereket választanak. Ezt követi egy “újratöltési” fázis; minden olyan álregiszter, amely nem kapott valódi hardverregisztert, “kiömlik” a verembe, az RTL pedig ezt a kiömlést generálja., Hasonlóképpen, a túl nagy, hogy beleférjen egy tényleges utasításba, azokat fel kell bontani, és azokat az RTL-sorozatok váltják fel, amelyek betartják az eltolási korlátokat.
az utolsó szakaszban a gépkód úgy épül fel, hogy egy kis kódrészletet hív meg, amely minden mintához kapcsolódik, hogy a valós utasításokat a cél utasításkészletéből generálja az újratöltési szakaszban kiválasztott végső regiszterek, eltolások és címek segítségével. Az assembly-generation töredék lehet csak egy string, ebben az esetben a regiszterek, eltolások és/vagy címek egyszerű karakterlánc-helyettesítése kerül végrehajtásra a karakterláncba., Az összeszerelési generációs töredék lehet egy rövid C kódblokk is, amely további munkát végez, de végül visszaadja az érvényes összeszerelési kódot tartalmazó karakterláncot.
Egyéb funkciókszerkesztés
a GCC egyes funkciói a következők:
- Link-idő optimalizálás optimalizálja az objektumfájl határait, hogy közvetlenül javítsa a kapcsolt bináris értéket. A Link-time optimization egy közbenső fájlra támaszkodik, amely az objektumfájlban található néhány Gimple reprezentáció sorozatosítását tartalmazza. A fájl az objektumfájl mellett keletkezik a forrás összeállítása során., Minden forrás-összeállítás külön objektumfájlt és link-time helper fájlt generál. Amikor az objektumfájlok összekapcsolódnak, a fordító ismét végrehajtásra kerül, majd a segítő fájlokat használja a kód optimalizálására a külön összeállított objektumfájlokon keresztül.
- Plugins kiterjesztheti a GCC fordító közvetlenül. A bővítmények lehetővé teszik, hogy egy állomány-fordítót a pluginként betöltött külső kód egyedi igényekhez igazítson. Például a bővítmények hozzáadhatják, cserélhetik vagy akár eltávolíthatják a Gimple ábrázolásokon működő középkategóriás bérleteket., Számos GCC plugin már megjelent, nevezetesen a GCC Python plugin, amely összeköti ellen libpython, és lehetővé teszi az egyik, hogy hivatkozhat tetszőleges Python szkriptek belülről a fordító. A cél az, hogy a GCC plugins Python nyelven írható legyen. Az olvadék plugin magas szintű Lisp-szerű nyelvet biztosít a GCC kiterjesztéséhez.
- C++ tranzakciós memória a-fgnu-tm-vel történő összeállításkor.
- a GCC 10-től kezdve az azonosítók lehetővé teszik az UTF-8 (Unicode) kódolást, azaz a C forráskód alapértelmezés szerint UTF-8 kódolást használ.