LLVM è diventato un progetto ombrello che contiene più componenti.
Front endsEdit
LLVM è stato originariamente scritto per sostituire il generatore di codice esistente nello stack GCC, e molti dei front ends di GCC sono stati modificati per lavorare con esso, dando vita all’ormai defunta suite LLVM-GCC. Le modifiche generalmente comportano un passaggio da GIMPLE a LLVM IR in modo che gli ottimizzatori e il codegen di LLVM possano essere usati al posto del sistema GIMPLE di GCC. Apple è stata un utente significativo di LLVM-GCC attraverso Xcode 4.x (2013). Questo uso del frontend GCC era considerato per lo più una misura temporanea, ma con l’avvento di Clang e i vantaggi di LLVM e della codebase moderna e modulare di Clang (così come la velocità di compilazione), è per lo più obsoleto.
LLVM attualmente supporta la compilazione di Ada, C, C++, D, Delphi, Fortran, Haskell, Julia, Objective-C, Rust e Swift usando vari front end.
L’interesse diffuso per LLVM ha portato a diversi sforzi per sviluppare nuovi front end per una varietà di linguaggi. Quello che ha ricevuto più attenzione è Clang, un nuovo compilatore che supporta C, C++ e Objective-C. Principalmente supportato da Apple, Clang mira a sostituire il compilatore C/Objective-C nel sistema GCC con un sistema più facilmente integrabile con gli ambienti di sviluppo integrati (IDE) e con un più ampio supporto per il multithreading. Il supporto per le direttive OpenMP è stato incluso in Clang dal rilascio 3.8.
Il compilatore Haskell di Utrecht può generare codice per LLVM. Sebbene il generatore sia nelle prime fasi di sviluppo, in molti casi è stato più efficiente del generatore di codice C. C’è un backend Glasgow Haskell Compiler (GHC) che usa LLVM che raggiunge un 30% di accelerazione del codice compilato rispetto alla compilazione di codice nativo tramite GHC o la generazione di codice C seguita dalla compilazione, mancando solo una delle molte tecniche di ottimizzazione implementate dal GHC.
Molti altri componenti sono in varie fasi di sviluppo, inclusi, ma non limitati a, il compilatore Rust, un front end per il bytecode Java, un front end per il Common Intermediate Language (CIL), l’implementazione MacRuby di Ruby 1.9, vari front end per Standard ML, e un nuovo allocatore di registri per la colorazione del grafico.
Rappresentazione intermediaEdit
Il nucleo di LLVM è la rappresentazione intermedia (IR), un linguaggio di programmazione a basso livello simile all’assembly. IR è un set di istruzioni RISC (reduced instruction set computing) fortemente tipizzato che astrae la maggior parte dei dettagli dell’obiettivo. Per esempio, la convenzione di chiamata è astratta attraverso istruzioni call e ret con argomenti espliciti. Inoltre, invece di un set fisso di registri, IR usa un set infinito di temporali della forma %0, %1, ecc. LLVM supporta tre forme equivalenti di IR: un formato assembly leggibile dall’uomo, un formato in-memory adatto ai frontend, e un formato bitcode denso per la serializzazione. Un semplice programma “Hello, world!” nel formato IR:
@.str = internal constant c"hello, world\0A\00"declare i32 @printf(i8*, ...)define i32 @main(i32 %argc, i8** %argv) nounwind {entry: %tmp1 = getelementptr , * @.str, i32 0, i32 0 %tmp2 = call i32 (i8*, ...) @printf( i8* %tmp1 ) nounwind ret i32 0}
Le molte convenzioni diverse usate e le caratteristiche fornite dai diversi target significano che LLVM non può veramente produrre un IR indipendente dal target e ritargettarlo senza infrangere alcune regole stabilite. Esempi di dipendenza dal target oltre a ciò che è esplicitamente menzionato nella documentazione possono essere trovati in una proposta del 2011 per “wordcode”, una variante completamente indipendente dal target di LLVM IR destinata alla distribuzione online. Un esempio più pratico è PNaCl.
Back endsEdit
Alla versione 3.4, LLVM supporta molti set di istruzioni, inclusi ARM, Qualcomm Hexagon, MIPS, Nvidia Parallel Thread Execution (PTX; chiamato NVPTX nella documentazione di LLVM), PowerPC, AMD TeraScale, AMD Graphics Core Next (GCN), SPARC, z/Architecture (chiamato SystemZ nella documentazione di LLVM), x86, x86-64, e XCore. Alcune caratteristiche non sono disponibili su alcune piattaforme. La maggior parte delle caratteristiche sono presenti per x86, x86-64, z/Architecture, ARM e PowerPC. RISC-V è supportato dalla versione 7. In passato LLVM ha supportato completamente o parzialmente anche altri backend, tra cui C backend, Cell SPU, mblaze (MicroBlaze), AMD R600, DEC/Compaq Alpha (Alpha AXP) e Nios2, ma la maggior parte di questo hardware è per lo più obsoleto, e il supporto e la manutenzione di LLVM non potrebbero essere giustificati.
LLVM supporta anche WebAssembly come target, permettendo ai programmi compilati di essere eseguiti in ambienti abilitati a WebAssembly come Google Chrome / Chromium, Firefox, Microsoft Edge, Apple Safari o WAVM. I compilatori LLVM-compliant WebAssembly tipicamente supportano per lo più codice sorgente non modificato scritto in C, C++, D, Rust, Nim, Kotlin e molti altri linguaggi.
Il sottoprogetto LLVM machine code (MC) è il framework di LLVM per tradurre istruzioni macchina tra forme testuali e codice macchina. In precedenza, LLVM si affidava all’assemblatore di sistema, o a uno fornito da una toolchain, per tradurre l’assembly in codice macchina. L’assemblatore integrato di LLVM MC supporta la maggior parte dei target di LLVM, inclusi x86, x86-64, ARM e ARM64. Per alcuni target, tra cui i vari set di istruzioni MIPS, il supporto all’assembly integrato è utilizzabile ma ancora in fase beta.
LinkerEdit
Il sottoprogetto lld è un tentativo di sviluppare un linker integrato e indipendente dalla piattaforma per LLVM. lld mira a rimuovere la dipendenza da un linker terzo. A partire da maggio 2017, lld supporta ELF, PE/COFF, Mach-O e WebAssembly in ordine decrescente di completezza. lld è più veloce di entrambe le versioni di GNU ld.
A differenza dei linker GNU, lld ha un supporto integrato per l’ottimizzazione del link-time. Questo permette una generazione di codice più veloce in quanto bypassa l’uso di un plugin per il linker, ma d’altra parte proibisce l’interoperabilità con altre versioni di LTO.
C++ Standard LibraryEdit
Il progetto LLVM include un’implementazione della libreria standard C++ chiamata libc++, con doppia licenza sotto la licenza MIT e la licenza UIUC.
Dalla versione 9.0.0, è stata rilasciata la licenza Apache 2.0 con LLVM Exceptions.
PollyEdit
Questa implementa una serie di ottimizzazioni per la cache-località, così come l’auto-parallelismo e la vettorizzazione usando un modello poliedrico.