Perché la rappresentazione intermedia di LLVM (LLVM IR) è simile all'assemblaggio piuttosto che ad albero?
In alternativa, perché le implementazioni linguistiche hanno come target LLVM IR piuttosto che l'AST di clang?
Non sto cercando di porre due domande diverse contemporaneamente se sembra che sia così. Per me, sembra semplicemente che sia i programmatori di client che di biblioteca abbiano raggiunto il consenso sul fatto che l'API di LLVM, niente di più e niente di meno, è ovviamente un buon design del software e la mia domanda è "perché?".
La ragione per cui chiedo è che sembra che LLVM potrebbe fornire più funzionalità ai frontend se è IR come AST, perché allora gli strumenti basati su AST di clang potrebbero essere utilizzati per qualsiasi frontend. In alternativa, le lingue che hanno come target LLVM IR potrebbero ottenere più funzionalità se mirassero all'AST di clang.
Clang ha classi e funzioni per creare e lavorare con AST ed è il progetto di frontend solo che è strongmente legato al progetto LLVM, quindi perché la funzionalità AST di clang è esterna a LLVM?
In cima alla mia testa, so che Rust (ruggine), D (ldc) e Haskell (GHC) possono tutti usare LLVM come back-end ma non usano il Clang AST (per quanto ne so , Potrei sbagliarmi). Non conosco tutti i dettagli interni di questi compilatori, ma almeno Rust e D sembrano certamente essere compilati per fare clang di AST. Forse anche Haskell potrebbe farlo, ma io ne sono molto meno certo.
Questo è dovuto a motivi storici (LLVM originariamente era una "macchina virtuale di basso livello" e si verificava un clang in seguito)? Questo perché altri frontend vogliono avere il maggior controllo possibile su ciò che alimentano a LLVM? Ci sono delle ragioni fondamentali per cui l'AST di clang è inappropriato per le lingue "non simili a C"?
Non intendo che questa domanda sia un esercizio di mindreading. Voglio solo che sia utile per quelli di noi che sono curiosi, ma non già fluenti, nella progettazione del compilatore. Dato che 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 compilati che si sentono abbastanza sicuri di rispondere.
Per anticipare alcune risposte ovvie ma insoddisfacenti:
Sì, avere un IR simile a un assembly dà più controllo a chiunque faccia l'IR (forse X lang ha un codice e un formato AST migliori di clang) ma se questa è l'unica risposta, allora la domanda diventa "perché LLVM solo hanno un IR simile a un assieme invece di un IR ad alto livello e un IR di basso livello come un assembly? ".
Sì, non è così difficile analizzare un linguaggio di programmazione in un AST (almeno rispetto agli altri passaggi della compilazione). Anche così, perché utilizzare AST separati? Se non altro, l'utilizzo dello stesso AST consente di utilizzare strumenti che operano su AST (anche solo cose semplici come le stampanti AST).
Sì, io con forza sono d'accordo sul fatto che essere più modulare è una buona cosa, ma se questa è l'unica ragione, allora perché le implementazioni di altre lingue tendono a colpire LLVM IR invece dell'AST di clang?
Queste pre-emption potrebbero essere errate o trascurare i dettagli, quindi sentiti libero di dare queste risposte se hai maggiori dettagli o se le mie supposizioni sono sbagliate.
Per tutti coloro che desiderano rispondere a una domanda più definitiva: quali sono i vantaggi e gli svantaggi di un IR simile a un assieme o un IR simile a un albero?