QBE 1.3 lanseras med Windows-stöd och nästan dubbla prestandan
- Vad en compiler backend faktiskt gör
- Prestandan steg med över 50 procent
- Windows-stöd kommer äntligen
- Positionsoberoende kod öppnar för delade bibliotek
- mgen genererar instruktionsval automatiskt
- Varför det här spelar roll för svenska utvecklare
- FAQ
- Vad är QBE för något?
- Hur mycket snabbare är QBE 1.3 jämfört med 1.2?
- Fungerar QBE 1.3 på Windows?
- Vad är skillnaden mellan QBE och LLVM?
- Vilka språk använder QBE?
- Vad betyder positionsoberoende kod?
Compiler backend QBE släppte version 1.3, den största uppdateringen sedan 1.0. Den lilla kompilatorn klarar nu över 63 procent av en kommersiell kompilators prestanda på Coremark-benchmark, jämfört med ungefär 40 procent i 1.2. Samtidigt kommer fullständigt Windows-stöd och möjligheten att generera positionsoberoende kod. För dig som bygger egna programmeringsspråk eller pillar på kompilatorer är det här den intressantaste QBE-releasen på flera år.
QBE är en compiler backend, alltså den del av en kompilator som tar en mellanrepresentation och omvandlar den till maskinkod. Projektets filosofi är ovanlig: leverera 70 procent av prestandan hos industriella kompilatorer som GCC och LLVM men på 10 procent av kodmängden. Version 1.3 tar ett rejält kliv mot det målet.
Vad en compiler backend faktiskt gör
En compiler backend är den bakre halvan av en kompilator. Frontend läser källkoden och förstår språket. Backend tar resultatet och producerar körbar maskinkod. QBE sköter den senare delen.
Det praktiska värdet är att du som språkbyggare slipper skriva kodgenerering för varje processorarkitektur själv. Du matar QBE med ett mellanspråk (intermediate language, förkortat IL) och QBE genererar assembler. Den lösningen liknar idén bakom hur en API fungerar: ett tydligt gränssnitt mellan två delar som annars skulle vara svåra att koppla ihop.
QBE används redan av flera hobbyprojekt och språk. Hare och cproc bygger på det och tidigare använde även Zig QBE innan projektet bytte riktning. De stora konkurrenterna heter Cranelift och LLVM men båda är betydligt större och mer komplicerade att arbeta med.
Prestandan steg med över 50 procent
Den största nyheten i 1.3 är prestandahoppet. QBE 1.2 låg på ungefär 40 procent av en kommersiell kompilators resultat på Coremark-benchmark. Version 1.3 klarar över 63 procent. I Hare-projektets egen testsvit blev förbättringen 33 procent.
Två specifika funktioner stack ut som flaskhalsar i den gamla versionen: `ee_isdigit` och `crcu8`. Roland Paterson-Jones identifierade Coremark som optimeringsmål och stod bakom flera av de nya optimeringarna som löste problemen.
Förbättringen kommer från nya optimeringspass under huven:
- GVN och GCM, global value numbering och global code motion, två klassiska tekniker som tar bort onödiga beräkningar och flyttar kod till smartare positioner.
- Loop-optimeringar, kod inuti loopar körs många gånger, så vinsterna där väger tungt.
- Ny instruktionsval-algoritm, en originell metod för att matcha mellanspråket mot maskininstruktioner.
Hela releasen omfattar cirka 7 000 nya rader kod och ungefär 1 500 raderade. Det är en stor förändring för ett projekt som medvetet håller kodbasen liten.
Windows-stöd kommer äntligen
QBE 1.3 stödjer Windows ABI fullt ut via flaggan `-t amd64_win`. Det är ett skifte för ett projekt som länge varit ett unix-fenomen. Scott Graham bidrog med implementeringen, ursprungligen från ett derivatprojekt.
Men det finns hakar värda att känna till. QBE-binären bygger inte nativt på Windows än, på grund av mindre portabilitetsfel. Cross-compilation fungerar däremot, alltså att du bygger Windows-kod från ett annat system. Assembly-utdatan är i AT&T-syntax och kompileras bäst med mingw-assemblern.
Windows TLS, alltså thread local storage, verkar ännu inte vara implementerat. Om du bygger något som behöver tråd-lokala variabler på Windows får du räkna med att den biten saknas tills vidare.
Positionsoberoende kod öppnar för delade bibliotek
QBE kan nu generera position-independent code, ofta förkortat PIC eller PIE. Det innebär kod som fungerar oavsett var i minnet den laddas, vilket är ett krav för moderna delade bibliotek och en grund i många operativsystems säkerhetsmodell.
Michael Forney stod bakom planen för hur det skulle lösas. Två nya språkfunktioner gör det möjligt:
`DYNCONST`-flaggan hanterar indirekt åtkomst till globala variabler, medan det nya nyckelordet `extern` ger åtkomst till globaler i delade bibliotek på macOS, Haiku och FreeBSD.
Kombinationen `extern` plus `thread` möjliggör dessutom initial-exec TLS för tråd-lokala globaler som ligger i andra delade bibliotek. För den som bygger riktiga bibliotek och inte bara fristående program är det här en förutsättning som tidigare saknades.
mgen genererar instruktionsval automatiskt
En av de mer eleganta detaljerna i 1.3 är ett nytt verktyg som heter `mgen`. Det är en DSL, ett domänspecifikt litet språk, som genererar instruktionsval från Lisp-liknande mönster.
Tanken är att beskriva hur mellanspråket ska översättas till maskininstruktioner med korta mönster i stället för handskriven kod. Det gör backenden lättare att utöka till nya arkitekturer och håller kodmängden nere. Precis den sortens lösning man väntar sig av ett projekt som mäter sin framgång i hur lite kod det behöver.
Varför det här spelar roll för svenska utvecklare
QBE 1.3 markerar ett skifte. Projektet har gått från ett rent hobbyverktyg till något med bredare plattformsstöd, med Windows, macOS, Haiku och FreeBSD i blicken. Det öppnar dörren för fler svenska studenter och hobbyutvecklare som vill bygga egna språk utan att brottas med LLVM:s tunga maskineri.
För svenska tekniska utbildningar är det här relevant. Kompilatorkonstruktion är ett klassiskt ämne på tekniska universitet och ett litet och läsbart verktyg som QBE är lättare att förstå än de stora alternativen. Du kan läsa hela kodbasen på en eftermiddag, vilket är omöjligt med LLVM.
Är du nyfiken på hur den här typen av AI-stödd och lågnivå-utveckling utvecklas just nu? Då kan det vara värt att läsa om hur AI gör kodning billigare och förändrar utvecklarnas vardag. Kompilatorprojekt som QBE är en påminnelse om att det fortfarande finns djup teknik som kräver mänsklig insikt. Vill du se ett annat exempel på hur lite kod kan åstadkomma mycket, är kodningsagenten på 400 rader shell en intressant läsning i samma anda.
FAQ
Vad är QBE för något?
QBE är en compiler backend, alltså den del av en kompilator som omvandlar ett mellanspråk till körbar maskinkod. Projektets mål är att nå 70 procent av prestandan hos stora kompilatorer som GCC men med en bråkdel av kodmängden.
Hur mycket snabbare är QBE 1.3 jämfört med 1.2?
QBE 1.3 klarar över 63 procent av en kommersiell kompilators prestanda på Coremark-benchmark, jämfört med ungefär 40 procent i version 1.2. I Hare-projektets testsvit förbättrades prestandan med 33 procent.
Fungerar QBE 1.3 på Windows?
Ja, QBE 1.3 har fullständigt Windows ABI-stöd via flaggan `-t amd64_win`. Binären bygger dock inte nativt på Windows än men cross-compilation från andra system fungerar. Thread local storage på Windows är ännu inte implementerat.
Vad är skillnaden mellan QBE och LLVM?
LLVM är en stor och komplett kompilatorinfrastruktur med stöd för många språk och arkitekturer. QBE är medvetet minimalistisk och siktar på cirka 70 procent av prestandan på en bråkdel av kodmängden. Det gör QBE lättare att läsa, förstå och bygga vidare på för mindre projekt.
Vilka språk använder QBE?
Programmeringsspråket Hare och C-kompilatorn cproc bygger på QBE. Tidigare använde även Zig QBE som backend innan projektet bytte riktning. Verktyget är populärt bland hobbyister som bygger egna språk.
Vad betyder positionsoberoende kod?
Positionsoberoende kod (PIC eller PIE) är maskinkod som fungerar oavsett var i minnet den laddas. Det är ett krav för moderna delade bibliotek och en viktig del av säkerheten i de flesta operativsystem. QBE 1.3 kan generera sådan kod för första gången.
