GNU Compiler Collection - GNU Compiler Collection

GNU Compiler Collection
GNU Compiler Collection logo.svg
GCC 10.2 GNU Compiler Collection self-compilation.png
Skjermbilde av GCC 10.2 som kompilerer sin egen kildekode
Originale forfattere Richard Stallman
Utvikler (er) GNU -prosjekt
Første utgivelse 23. mai 1987 ; 34 år siden ( 1987-05-23 )
Stabil utgivelse
11.2 / 27. juli 2021 ; 2 måneder siden ( 2021-07-27 )
Forhåndsvisningslansering
11.2.0-RC / 21. juli 2021 ; 2 måneder siden ( 2021-07-21 )
Oppbevaringssted
Skrevet inn C , C ++
Operativsystem Kryssplattform
Plattform GNU og mange andre
Størrelse ~ 15 millioner LOC
Type Kompilator
Tillatelse GPLv3+ med GCC Runtime Library Exception
Nettsted gcc .gnu .org

Den GNU Compiler Collection ( GCC ) er en optimalisering kompilatoren produsert av GNU-prosjektet støtter ulike programmeringsspråk , maskinvare-arkitekturer og operativsystemer . The Free Software Foundation (FSF) distribuerer GCC som fri programvare under GNU General Public License (GNU GPL). GCC er en nøkkelkomponent i GNU -verktøykjeden og standardkompilatoren for de fleste prosjekter relatert til GNU og Linux -kjernen . Med omtrent 15 millioner kodelinjer i 2019, er GCC et av de største gratisprogrammene som finnes. Det har spilt en viktig rolle i veksten av gratis programvare , som både et verktøy og et eksempel.

Da den først ble utgitt i 1987 av Richard Stallman , ble GCC 1.0 kåret til GNU C Compiler siden den bare håndterte C -programmeringsspråket . Den ble utvidet til å kompilere C ++ i desember samme år. Frontendene ble senere utviklet for blant annet Objective-C , Objective-C ++ , Fortran , Ada , D og Go . De OpenMP og OpenACC spesifikasjoner er også opplagret i C og C ++ kompilatorer.

GCC har blitt portet til flere plattformer og instruksjonsarkitekturer enn noen annen kompilator, og er utbredt som et verktøy i utviklingen av både gratis og proprietær programvare . GCC er også tilgjengelig for mange innebygde systemer , inkludert ARM -baserte og Power ISA -baserte sjetonger.

I tillegg til å være den offisielle kompilatoren av GNU operativsystemet har GCC blitt vedtatt som standard kompilatoren av mange andre moderne Unix-lignende datamaskin operativsystemer , inkludert de fleste Linux- distribusjoner. De fleste BSD -familieoperativsystemene byttet også til GCC kort tid etter utgivelsen, selv om FreeBSD , OpenBSD og Apple macOS siden har flyttet til Clang -kompilatoren, hovedsakelig på grunn av lisensiering. GCC kan også kompilere kode for Windows , Android , iOS , Solaris , HP-UX , AIX og DOS.

Historie

På slutten av 1983, i et forsøk på å starte opp GNU -operativsystemet, spurte Richard Stallman Andrew S. Tanenbaum , forfatteren av Amsterdam Compiler Kit (også kjent som Free University Compiler Kit ) om tillatelse til å bruke denne programvaren for GNU. Da Tanenbaum informerte ham om at kompilatoren ikke var gratis, og at bare universitetet var gratis, bestemte Stallman seg for å jobbe med en annen kompilator. Hans første plan var å skrive om en eksisterende kompilator fra Lawrence Livermore National Laboratory fra Pastel til C med litt hjelp fra Len Tower og andre. Stallman skrev en ny C -frontend for Livermore -kompilatoren, men innså da at det krevde megabyte med stakkplass, en umulighet på et 68000 Unix -system med bare 64 KB, og konkluderte med at han måtte skrive en ny kompilator fra bunnen av. Ingen av Pastel -kompilatorkoden havnet i GCC, selv om Stallman brukte C -frontenden han hadde skrevet.

GCC ble først utgitt 22. mars 1987, tilgjengelig av FTP fra MIT . Stallman ble oppført som forfatteren, men siterte andre for deres bidrag, inkludert Jack Davidson og Christopher Fraser for ideen om å bruke RTL som et mellomspråk, Paul Rubin for å skrive det meste av forarbeideren, og Leonard Tower for "deler av analysatoren, RTL generator, RTL -definisjoner og beskrivelsen av Vax -maskinen. " GNU -kompilatoren ble beskrevet som den "første gratis programvarehiten" av Peter H. Salus , og ankom akkurat på det tidspunktet da Sun Microsystems fjernet utviklingsverktøyene fra operativsystemet , og solgte dem separat til en høyere kombinert pris enn den forrige pakken, som fikk mange av Suns brukere til å kjøpe eller laste ned GCC i stedet for leverandørens verktøy. Mens Stallman betraktet GNU Emacs som sitt hovedprosjekt, støttet GCC i 1990 tretten datamaskinarkitekturer, var bedre enn flere leverandørkompilatorer og ble brukt kommersielt av flere selskaper.

EGCS gaffel

Siden GCC var lisensiert under GPL, kunne programmerere som ønsker å jobbe i andre retninger - spesielt de som skriver grensesnitt for andre språk enn C - utvikle sin egen gaffel av kompilatoren, forutsatt at de oppfyller GPLs vilkår, inkludert kravene til å distribuere kilde kode . Flere gafler viste seg imidlertid å være ineffektive og uhåndterlige, og vanskeligheten med å få arbeid godtatt av det offisielle GCC -prosjektet var sterkt frustrerende for mange, ettersom prosjektet favoriserte stabilitet fremfor nye funksjoner. FSF holdt så nær kontroll over det som ble lagt til den offisielle versjonen av GCC 2.x (utviklet siden 1992) at GCC ble brukt som et eksempel på utviklingen av "katedralen" i Eric S. Raymonds essay The Cathedral and the Basar .

I 1997 dannet en gruppe utviklere Experimental/Enhanced GNU Compiler System (EGCS) for å slå sammen flere eksperimentelle gafler til et enkelt prosjekt. Grunnlaget for fusjonen var et utviklingsbilde av GCC (tatt rundt 2.7.2 og senere fulgt opp til 2.8.1 -utgivelse). Fusjoner inkluderte g77 (Fortran), PGCC ( P5 Pentium -optimalisert GCC), mange C ++ forbedringer og mange nye arkitekturer og operativsystemvarianter .

Mens begge prosjektene fulgte hverandres endringer nøye, viste EGCS -utviklingen seg betydelig kraftigere, så mye at FSF offisielt stoppet utviklingen på GCC 2.x -kompilatoren, velsignet EGCS som den offisielle versjonen av GCC, og utnevnte EGCS -prosjektet som GCC vedlikeholdere i april 1999. Med utgivelsen av GCC 2.95 i juli 1999 ble de to prosjektene igjen forent. GCC har siden blitt vedlikeholdt av en variert gruppe programmerere fra hele verden under ledelse av en styringsgruppe.

GCC 3 (2002) fjernet en front-end for CHILL på grunn av mangel på vedlikehold.

Før versjon 4.0 var Fortran frontend g77, som bare støttet FORTRAN 77 , men senere ble droppet til fordel for den nye GNU Fortran frontenden som støtter Fortran 95 og store deler av Fortran 2003 og Fortran 2008 også.

Fra versjon 4.8 er GCC implementert i C ++.

Støtte for Cilk Plus eksisterte fra GCC 5 til GCC 7.

GCC har blitt portet til et bredt spekter av instruksjonsarkitekturer , og er utbredt som et verktøy i utviklingen av både gratis og proprietær programvare . GCC er også tilgjengelig for mange innebygde systemer , inkludert Symbian (kalt gcce ), ARM -basert og Power ISA -basert sjetonger. Kompilatoren kan målrette mot et bredt utvalg av plattformer, inkludert videospillkonsoller som PlayStation 2 , Cell SPE på PlayStation 3 og Dreamcast . Den har blitt portet til flere typer prosessorer og operativsystemer enn noen annen kompilator.

Støttede språk

Fra mai 2021 inkluderer den siste 11.1-utgaven av GCC frontendene for C ( gcc), C ++ ( g++), Objective-C , Fortran ( gfortran), Ada ( GNAT ), Go ( gccgo) og D ( gdc, siden 9.1) programmeringsspråk, med de OpenMP og OpenACC parallelt språk utvidelser blir støttet siden GCC 5.1. Versjoner før GCC 7 støttet også Java ( gcj), noe som tillot kompilering av Java til innfødt maskinkode.

Når det gjelder språkversjonsstøtte for C ++ og C, siden GCC 11.1 er standardmålet gnu ++ 17 , et supersett av C ++ 17 og gnu11 , et supersett av C11 , med streng standardstøtte også tilgjengelig. GCC gir også eksperimentell støtte for C ++ 20 og kommende C ++ 23 .

Tredjeparts frontend finnes for mange språk, for eksempel Pascal ( gpc), Modula-2 , Modula-3 , PL/I og VHDL ( GHDL). Noen få eksperimentelle grener finnes for å støtte flere språk, for eksempel GCC UPC -kompilatoren for Unified Parallel C eller Rust .

Design

Oversikt over GCCs utvidede kompileringsrørledning, inkludert spesialiserte programmer som preprocessor , assembler og linker .
GCC følger 3-trinns arkitektur som er typisk for flerspråklige og multi-CPU- kompilatorer . Alle programtrær konverteres til en felles abstrakt representasjon i "midtenden", slik at kodeoptimalisering og binære kodegenereringsfasiliteter kan deles av alle språk.

GCCs eksterne grensesnitt følger Unix -konvensjoner. Brukere påkaller et språkspesifikt driverprogram ( gccfor C, g++for C ++, etc.), som tolker kommandoargumenter , kaller den faktiske kompilatoren, kjører assembler på utgangen og deretter eventuelt kjører linkeren for å produsere en komplett kjørbar binær.

Hver av språkkompilatorene er et eget program som leser kildekode og sender ut maskinkode . Alle har en felles intern struktur. En grensesnitt per språk analyserer kildekoden på det språket og produserer et abstrakt syntaksetre (kort sagt "tre").

Disse blir om nødvendig konvertert til mellomendenes inngangsrepresentasjon, kalt GENERISK form; midtenden forvandler deretter programmet gradvis mot sin endelige form. Kompilatoroptimaliseringer og teknikker for statisk kodeanalyse (for eksempel FORTIFY_SOURCE, et kompilerdirektiv som prøver å oppdage noen bufferoverløp ) brukes på koden. Disse arbeider med flere representasjoner, for det meste den arkitekturuavhengige GIMPLE-representasjonen og den arkitekturavhengige RTL- representasjonen. Til slutt produseres maskinkode ved hjelp av arkitekturspesifikk mønstermatching opprinnelig basert på en algoritme av Jack Davidson og Chris Fraser.

GCC ble først og fremst skrevet i C bortsett fra deler av Ada -frontenden. Distribusjonen inkluderer standardbibliotekene for Ada og C ++ hvis kode for det meste er skrevet på disse språkene. På noen plattformer inkluderer distribusjonen også et lavt nivå kjøretidsbibliotek, libgcc , skrevet i en kombinasjon av maskinuavhengig C og prosessorspesifikk maskinkode , først og fremst designet for å håndtere aritmetiske operasjoner som målprosessoren ikke kan utføre direkte.

GCC bruker mange standardverktøy i byggingen, inkludert Perl , Flex , Bison og andre vanlige verktøy. I tillegg krever det for tiden tre ekstra biblioteker for å kunne bygge: GMP , MPC og MPFR .

I mai 2010 bestemte GCC -styringsgruppen for å tillate bruk av en C ++ - kompilator for å kompilere GCC. Kompilatoren var ment å være skrevet for det meste i C pluss et delsett av funksjoner fra C ++. Spesielt ble dette bestemt slik at GCCs utviklere kunne bruke destruktorene og generiske funksjonene til C ++.

I august 2012 kunngjorde GCC -styrekomiteen at GCC nå bruker C ++ som implementeringsspråk. Dette betyr at for å bygge GCC fra kilder, kreves en C ++ - kompilator som forstår ISO/IEC C ++ 03 -standarden.

18. mai 2020 flyttet GCC bort fra ISO/IEC C ++ 03 -standarden til ISO/IEC C ++ 11 -standarden (dvs. nødvendig for å kompilere, bootstrap, selve kompilatoren; som standard kompilerer den imidlertid senere versjoner av C ++).

Frontender

Frontendene består av forbehandling , leksikalsk analyse , syntaktisk analyse (parsing) og semantisk analyse. Målet med kompilatorfrontendene er å enten godta eller avvise kandidatprogrammer i henhold til språk grammatikk og semantikk, identifisere feil og håndtere gyldige programrepresentasjoner til senere kompilatorfaser. Dette eksemplet viser Lexer og analysetrinn som utføres for et enkelt program skrevet i C .

Hver frontend bruker en parser for å produsere det abstrakte syntaksetreet for en gitt kildefil . På grunn av syntaks -tre -abstraksjonen, kan kildefiler for alle de forskjellige støttede språkene behandles av den samme bakenden . GCC startet med å bruke LALR-parsere generert med Bison , men byttet gradvis til håndskrevne rekursive nedstignings-parsere for C ++ i 2004, og for C og Objective-C i 2006. Fra og med 2021 bruker alle frontendene håndskrevne rekursive nedstignings-parsere .

Fram til GCC 4.0 var trerepresentasjonen av programmet ikke helt uavhengig av at prosessoren ble målrettet. Betydningen av et tre var noe annerledes for frontendene på forskjellige språk, og frontendene kunne gi sine egne trekoder. Dette ble forenklet med introduksjonen av GENERIC og GIMPLE, to nye former for språkuavhengige trær som ble introdusert med ankomsten av GCC 4.0. GENERIC er mer kompleks, basert på GCC 3.x Java -frontendens mellomrepresentasjon. GIMPLE er en forenklet GENERISK, der forskjellige konstruksjoner senkes til flere GIMPLE -instruksjoner. De C , C ++ , og Java fremre ender produsere GENERISK direkte i frontenden. Andre frontender har i stedet forskjellige mellomrepresentasjoner etter parsing og konverterer disse til GENERIC.

I begge tilfeller konverterer den såkalte "gimplifier" denne mer komplekse formen til den enklere SSA- baserte GIMPLE-formen som er det vanlige språket for et stort antall kraftige språk- og arkitekturuavhengige globale (funksjonsomfang) optimaliseringer.

GENERISK og GIMPEL

GENERIC er et mellomrepresentasjonsspråk som brukes som en "midtre ende" mens du kompilerer kildekoden til kjørbare binære filer . Et delsett, kalt GIMPLE , er målrettet mot alle frontendene til GCC.

Midtfasen i GCC utfører all koden analyse og optimalisering , og arbeider uavhengig av både det kompilerte språket og målarkitekturen, fra den GENERISKE representasjonen og utvider den til å registrere overføringsspråk (RTL). Den GENERISKE representasjonen inneholder bare delsettet av de tvingende programmeringskonstruksjonene som er optimalisert i midten.

I transkildekoden til Gimple, komplekse uttrykk er delt inn i en tre-adresse kode ved hjelp av midlertidige variabler . Denne representasjonen ble inspirert av den ENKELE representasjonen som ble foreslått i McCAT -kompilatoren av Laurie J. Hendren for å forenkle analysen og optimaliseringen av tvingende programmer .

Optimalisering

Optimalisering kan skje under en hvilken som helst fase av samlingen; Imidlertid utføres hoveddelen av optimaliseringene etter syntaks og semantisk analyse av frontend og før kodegenerering av backend; Derfor er et vanlig, selv om det er litt motstridende, navnet på denne delen av kompilatoren "mellomenden".

Det nøyaktige settet med GCC -optimaliseringer varierer fra utgivelse til utgivelse etter hvert som det utvikler seg, men inkluderer standardalgoritmene, for eksempel sløyfeoptimalisering , hoppetråd , vanlig eliminering av subekspresjon , instruksjonsplanlegging og så videre. De RTL optimaliseringer er av mindre betydning med tillegg av globale SSA-baserte optimaliseringer på Gimple trær, som RTL optimaliseringer har en mye mer begrenset omfang, og har mindre informasjon på høyt nivå.

Noen av disse optimaliseringer utført på dette nivå omfatter død kode eliminering , delvis eliminering redundans , global verdi nummerering , sparsom betinget konstant forplantning , og skalar utskifting av aggregater . Arrayavhengighetsbaserte optimaliseringer som automatisk vektorisering og automatisk parallellisering utføres også. Profilstyrt optimalisering er også mulig.

Baksiden

GCCs bakside er delvis spesifisert av forprosessormakroer og funksjoner som er spesifikke for en målarkitektur, for eksempel for å definere dens endianness , ordstørrelse og ringekonvensjoner . Den fremre delen av bakenden bruker disse til å bestemme RTL-generasjon, så selv om GCCs RTL er nominelt prosessoruavhengig, er den første sekvensen av abstrakte instruksjoner allerede tilpasset målet. Når som helst må de faktiske RTL -instruksjonene som danner programrepresentasjonen overholde maskinbeskrivelsen av målarkitekturen.

Maskinbeskrivelsesfilen inneholder RTL -mønstre, sammen med operandbegrensninger og kodebiter for å sende ut den siste samlingen. Begrensningene indikerer at et bestemt RTL -mønster bare kan gjelde (for eksempel) på visse maskinvareregistre, eller (for eksempel) tillate umiddelbare operandforskyvninger av bare en begrenset størrelse (f.eks. 12, 16, 24, ... bitforskyvninger, etc. ). Under RTL -generasjon kontrolleres begrensningene for den gitte målarkitekturen. For å kunne gi en gitt utdrag av RTL, må den matche ett (eller flere) av RTL -mønstrene i maskinbeskrivelsesfilen og tilfredsstille begrensningene for det mønsteret; ellers ville det være umulig å konvertere den endelige RTL til maskinkode.

Mot slutten av samlingen reduseres gyldig RTL til en streng form der hver instruksjon refererer til virkelige maskinregistre og et mønster fra målets maskinbeskrivelsesfil. Å danne streng RTL er en komplisert oppgave; et viktig trinn er registerallokering , der ekte maskinvareregistre velges for å erstatte de opprinnelig tildelte pseudoregistrene. Dette etterfølges av en "omlasting" -fase; eventuelle pseudoregistre som ikke ble tildelt et ekte maskinvareregister, blir "sølt" til stabelen, og RTL for å utføre dette sølingen genereres. På samme måte må forskyvninger som er for store til å passe inn i en faktisk instruksjon, brytes opp og erstattes av RTL -sekvenser som vil følge offsetbegrensningene.

I den siste fasen blir maskinkoden bygget ved å kalle en liten kodebit, knyttet til hvert mønster, for å generere de virkelige instruksjonene fra målets instruksjonssett , ved hjelp av de siste registerene, forskyvningene og adressene som ble valgt under omlastingfasen. Monteringsgenerasjonskoden kan bare være en streng, i så fall utføres en enkel strengbytte av registre, forskyvninger og/eller adresser i strengen. Monteringsgenerasjonsbiten kan også være en kort blokk med C-kode som utfører noe ekstra arbeid, men til slutt returnerer en streng som inneholder den gyldige monteringskoden.

C ++ Standardbibliotek (libstdc ++)

GCC -prosjektet inkluderer en implementering av C ++ - standardbiblioteket kalt libstdc ++, lisensiert under GPLv3 -lisensen, med unntak for å koble til lukket kildeprogram når kilder bygges med GCC. Den nåværende versjonen er 11.

Andre funksjoner

Noen funksjoner i GCC inkluderer:

Optimalisering av lenketid
Optimalisering av koblingstid optimaliserer på tvers av objektfilgrenser for å forbedre den koblede binæren direkte. Optimalisering av lenketid er avhengig av en mellomliggende fil som inneholder serialiseringen av noen Gimple- representasjoner som er inkludert i objektfilen. Filen genereres ved siden av objektfilen under kildekompilering. Hver kildesamling genererer en egen objektfil og lenketidshjelperfil. Når objektfilene er koblet, kjøres kompilatoren på nytt og bruker hjelperfilene til å optimalisere koden for de separat kompilerte objektfilene.
Plugins
Plugins utvider GCC -kompilatoren direkte. Med plugins kan en aksjekompilator skreddersys til spesifikke behov ved hjelp av ekstern kode som er lastet inn som plugins. For eksempel kan plugins legge til, erstatte eller til og med fjerne mellomliggende passeringer som opererer på Gimple- representasjoner. Flere GCC -plugins har allerede blitt publisert, særlig:
  • Python -pluginet, som lenker mot libpython, og lar en påkalle vilkårlige Python -skript fra innsiden av kompilatoren. Målet er å la GCC -plugins skrives i Python.
  • MELT -pluginet gir et Lisp -lignende språk på høyt nivå for å utvide GCC.
Støtten til plugins var en gang et omstridt problem i 2007.
C ++ transaksjonelt minne
C ++ - språket har et aktivt forslag til transaksjonelt minne. Den kan aktiveres i GCC 6 og nyere når den kompileres med -fgnu-tm.
Unicode -identifikatorer
Selv om C ++ -språket krever støtte for ikke-ASCII Unicode-tegn i identifikatorer , har funksjonen bare blitt støttet siden GCC 10. Som med den eksisterende håndteringen av strengliteraler, antas kildefilen å være kodet i UTF-8 . Funksjonen er valgfri i C, men har blitt gjort tilgjengelig også siden denne endringen.

Arkitekturer

GCC kompilerer Hello WorldWindows

GCC -målprosessorfamilier fra versjon 11.1 inkluderer:

Mindre kjente målprosessorer som støttes i standardutgivelsen har inkludert:

Ytterligere prosessorer har blitt støttet av GCC -versjoner som vedlikeholdes separat fra FSF -versjonen:

Den GCJ Java kompilatoren kan målrette enten en innfødt maskinspråk arkitektur eller Java virtuell maskin 's Java bytecode . Når du målretter GCC til en ny plattform, brukes bootstrapping ofte. Motorola 68000, Zilog Z80 og andre prosessorer er også målrettet i GCC -versjonene utviklet for forskjellige Texas Instruments, Hewlett Packard, Sharp og Casio programmerbare grafkalkulatorer.

Tillatelse

GCC er lisensiert under GNU General Public License versjon 3. GCC -kjøretidsunntaket tillater kompilering av proprietære programmer (i tillegg til gratis programvare) med GCC. Dette påvirker ikke lisensvilkårene for GCC -kildekoden.

Se også

Referanser

Videre lesning

Eksterne linker

Offisielt

Annen