LLVM è di livello inferiore rispetto alle VM tipiche come JVM e CLR. Ad esempio, sebbene abbia hook per un Garbage Collector, non fornisce un Garbage Collector stesso.
Allo stesso modo, JVM ha un compilatore JIT integrato (tranne nelle versioni davvero antiche). LLVM ha alcuni compilatori JIT per LLVM IR, ma spetta ancora allo sviluppatore agganciare le cose e in realtà il codice JIT.
Quando JVM incontra un esterno non risolto, esce e trova la classe giusta per soddisfarlo e sa come cercare i file .class direttamente nel file system e nei file .jar 1 . I compilatori JIT di LLVM hanno hook in cui puoi decidere come gestire cose del genere. Come ci si aspetterebbe, alcune persone hanno scritto alcune versioni predefinite, quindi può fare le cose all'incirca nello stesso ordine della JVM, ma sei anche libero di ignorarle e fare le cose in modo diverso se lo desideri.
In poche parole, se stai sviluppando un compilatore (o qualcosa su quell'ordine) ha molti strumenti per semplificarti la vita. Invece di preoccuparti molto dell'ottimizzazione, puoi fare all'incirca la traduzione più semplice che puoi gestire dal tuo codice sorgente a LLVM IR, quindi utilizzare le librerie LLVM per gestire l'ottimizzazione, il JIT, il collegamento, ecc. Tuttavia, sono librerie - fornisce alcune funzioni davvero utili, quindi non devi occuparti di tutti i dettagli, ma sono comunque funzioni e stai ancora scrivendo codice per invocarle. Non è un prodotto finito, solo strumenti utili per costruire prodotti in modo relativamente rapido e semplice.
1 Tecnicamente, non tutto questo è integrato nella JVM corretta. Specifica quello che di solito viene chiamato il caricatore di classi primordiale come parte della JVM propria, e quindi ci sono caricatori di classi utente specificati in java.util.ClassLoader che gestiscono altre cose. Alcuni caricatori di classi sono inclusi per impostazione predefinita e, se lo si desidera, è possibile integrare quelli definendone uno proprio.