Perché LLVM ha un IR simile ad un assieme piuttosto che un IR simile ad un albero? Oppure: perché i progetti prendono di mira LLVM IR invece di AST di clang?


14

Perché la rappresentazione intermedia di LLVM (LLVM IR) assomiglia piuttosto che ad un albero?

In alternativa, perché le implementazioni linguistiche hanno come obiettivo LLVM IR anziché l'AST di clang?

Non sto provando a fare due domande diverse contemporaneamente se sembra così. A me sembra semplicemente che sia i programmatori di client che quelli di biblioteche abbiano raggiunto il consenso sul fatto che l'API di LLVM, niente di più e niente di meno, è ovviamente una buona progettazione del software e la mia domanda è "perché?".

Il motivo per cui lo chiedo è che sembra che LLVM possa fornire più funzionalità ai frontend se l'IR fosse simile ad AST perché allora gli strumenti basati su AST di clang potrebbero essere usati per qualsiasi frontend. In alternativa, le lingue che hanno come target LLVM IR potrebbero ottenere più funzionalità se prendessero di mira l'AST di clang.

Clang ha classi e funzioni per creare e lavorare con AST ed è l' unico progetto frontend fortemente legato al progetto LLVM, quindi perché la funzionalità AST di clang è esterna a LLVM?

Dalla parte superiore della mia testa, so che Rust (rustc), D (ldc) e Haskell (GHC) possono tutti usare LLVM come backend ma non usano il Clang AST (per quanto ne so, potrei sbagliarsi). Non conosco tutti i dettagli interni di questi compilatori, ma almeno Rust e D sembrano certamente essere compilati per l'AST di Clang. Forse potrebbe anche Haskell, ma ne sono molto meno sicuro.

È a causa di ragioni storiche (LLVM era in origine una "macchina virtuale di basso livello" e il clanging arrivava più tardi)? Questo perché altri frontend vogliono avere il maggior controllo possibile su ciò che forniscono a LLVM? Ci sono ragioni fondamentali per cui l'AST di clang è inappropriato per le lingue "non-C-like"?

Non intendo che questa domanda sia un esercizio di lettura mentale. Voglio solo che sia utile per quelli di noi che sono curiosi di conoscere, ma non sono già fluenti, nel design del compilatore. Poiché i progetti LLVM e clang sono sviluppati in pubblico, spero che qualcuno che abbia familiarità con lo sviluppo di questi progetti possa rispondere o che la risposta sia abbastanza ovvia per alcuni nerd di compilazione che si sentono abbastanza sicuri per rispondere.


Per anticipare alcune risposte ovvie ma insoddisfacenti:

Sì, avere un IR simile ad un assembly dà più controllo a chiunque crea l'IR (forse X lang ha una base di codice e un formato AST migliori di clang) ma se questa è l'unica risposta, allora la domanda diventa "perché LLVM ha solo un assembly- come IR invece di un IR ad alto livello simile ad un albero e un IR di basso livello simile ad un assieme? ".

Sì, non è così difficile analizzare un linguaggio di programmazione in un AST (almeno rispetto alle altre fasi della compilazione). Anche così, perché usare AST separati? Se non altro, l'utilizzo dello stesso AST ti consente di utilizzare strumenti che funzionano su AST (anche solo cose semplici come le stampanti AST).

Sì, sono pienamente d'accordo sul fatto che essere più modulari sia una buona cosa, ma se questa è l'unica ragione, allora perché altre implementazioni linguistiche tendono a colpire LLVM IR anziché l'AST di clang?

Queste prelazioni potrebbero essere errate o trascurare i dettagli, quindi sentiti libero di dare queste risposte se hai maggiori dettagli o i miei presupposti sono sbagliati.


Per chiunque voglia rispondere a una domanda con una risposta più definitiva: quali sono i vantaggi e gli svantaggi di un IR simile ad un assemblaggio rispetto a un IR simile ad un albero?


1
Non sono un esperto di LLVM, ma penso che ci sia un piccolo malinteso dalla tua parte. LLVM non ha asm come IR. In effetti, il suo IR è più simile a un grafico che a un albero. Suppongo che con "asm-like" ti riferisci all'IR leggibile dall'uomo (file * .ll), in tal caso viene fatto solo per comodità. Ma aspettiamo un vero esperto che possa dare una risposta più completa :)
AlexDenisov,

1
Un aspetto importante potrebbe essere la storia: LLVM è stato originariamente progettato per disaccoppiare i backend del compilatore dai frontend del compilatore. L'idea era che i produttori di compilatori avrebbero gareggiato sulle ottimizzazioni del linguaggio e i fornitori di CPU avrebbero gareggiato sulle ottimizzazioni di basso livello. Ad esempio, Microsoft e Apple competerebbero l'una contro l'altra il cui compilatore C produce il "miglior" bitcode da C, e Intel e AMD sarebbero in competizione tra loro il cui backend LLVM produce il "migliore" codice macchina da bitcode. I fornitori di applicazioni spedirebbero le loro applicazioni in bitcode e la compilazione finale verrebbe eseguita dall'utente ...
Jörg W Mittag

1
... macchina. LLVM è iniziato in un momento, in cui non era affatto chiaro che tutti avrebbero usato Intel. Apple era ancora su PowerPC, Intel stava ancora spingendo Itanium e così via. AFAIK, Apple usa ancora LLVM in questo modo, in alcuni dei suoi framework 3D, in cui il codice viene spedito come bitcode e quindi compilato per nVidia o ATI a seconda del tipo di scheda installata.
Jörg W Mittag,

1
Perdonami, ma cos'è un IR?
Adam Copley,

1
Rappresentazione intermedia di
Prassolitica

Risposte:


13

Ci sono un certo numero di domande correlate qui, cercherò di separarle nel miglior modo possibile.

Perché altre lingue si basano su LLVM IR e non clangolano AST?

Questo semplicemente perché clang è un front-end C / C ++ e l'AST che produce è strettamente accoppiato a C / C ++. Un altro linguaggio potrebbe usarlo ma avrebbe bisogno di una semantica quasi identica a qualche sottoinsieme di C / C ++ che è molto limitante. Come hai sottolineato, l'analisi di un AST è abbastanza semplice, quindi è improbabile che limitare le tue scelte semantiche valga il piccolo risparmio.

Tuttavia, se stai scrivendo strumenti per C / C ++, ad esempio analizzatori statici, riutilizzare l'AST ha molto senso poiché è molto più semplice lavorare con l'AST rispetto al testo non elaborato se stai lavorando con C / C ++ .

Perché LLVM IR è la forma in cui si trova?

LLVM IR è stato scelto come modulo appropriato per scrivere ottimizzazioni del compilatore. Pertanto, la sua caratteristica principale è che è in formato SSA . È un livello IR piuttosto basso, quindi è applicabile a una vasta gamma di lingue, ad esempio non digita la memoria poiché varia molto da una lingua all'altra.

Ora, capita che scrivere ottimizzazioni del compilatore sia un compito piuttosto specialistico ed è spesso ortogonale alla progettazione delle caratteristiche del linguaggio. Tuttavia, avere un linguaggio compilato veloce è un requisito abbastanza generale. Inoltre, la conversione da LLVM IR ad ASM è abbastanza meccanica e generalmente non interessante per i progettisti di lingue.

Pertanto, abbassare una lingua a LLVM IR offre a un designer linguistico molte "cose ​​gratuite" che sono molto utili nella pratica lasciandole concentrarsi sulla lingua stessa.

Sarebbe utile un diverso IR (OK, non chiesto ma implicito)?

Assolutamente! Gli AST sono abbastanza buoni per alcune trasformazioni nella struttura del programma ma sono molto difficili da usare se si desidera trasformare il flusso del programma. Un modulo SSA è generalmente migliore. Tuttavia, LLVM IR ha un livello molto basso, quindi gran parte della struttura di alto livello viene persa (apposta, quindi è più generalmente applicabile). Avere un IR tra l'AST e l'IR di basso livello può essere utile qui. Sia Rust che Swift adottano questo approccio e hanno un livello IR elevato tra i due.


Anche Haskell ha un certo numero di IR prima di arrivare a LLVM.
DylanSp

1
@ DylanSp Infatti. Sta iniziando a diventare la migliore pratica di fatto per le lingue complesse. Ad esempio, Rust non lo ha fatto inizialmente e ha effettuato il refactoring per includere un IR di alto livello. Credo anche che si sia parlato di fare questo per clang, ma non sono sicuro di dove sia andato.
Alex,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.