E 'possibile scrivere un compilatore da IR a assembly al contrario di un backend LLVM?

1

Ho realizzato un processore virtuale con un semplice set di istruzioni e un modello di memoria come esercizio di apprendimento (e principalmente solo per divertimento). Posso scrivere programmi nel suo linguaggio assembly, assemblarli con il mio assemblatore e eseguirli con successo su una macchina virtuale.

Volevo scrivere un compilatore per un linguaggio di livello superiore che ha come target questa macchina, quindi non devo scrivere tutto in assembly. Ho sentito parlare di LLVM , un progetto di compilazione che supporta più front-end per lingue diverse e output IR che è in qualche modo simile a un assembly. Questo IR viene assegnato a un back-end specifico della piattaforma che lo trasforma in assembly / codice macchina per una piattaforma.

Ho cercato di scrivere il mio backend; Ho visto il tutorial del backend di LLVM e backend per il tutorial di Cpu0 e, francamente, sembra un po 'complicato.

È possibile scrivere un compilatore, esterno a LLVM, che legge i file * .ll di LLVM e genera l'assemblatore per la mia piattaforma, invece di scrivere un backend LLVM completamente nuovo?

Non mi importa molto del mio codice che corre veloce e che è altamente ottimizzato in questo momento, voglio solo ottenere la compilazione del codice reale ad esso. Sto bene a capire l'assegnazione del registro, et. al. da solo, non ho bisogno che sia efficiente.

    
posta Celarix 03.09.2018 - 22:32
fonte

1 risposta

4

Dipende da cosa intendi per fattibile. È certamente possibile.

Tuttavia, LLVM IR nella sua forma iniziale non è particolarmente adatto per la traduzione diretta. A parte l'IR generico inefficiente, è ancora pensato per una macchina piuttosto astratta. Ha molte istruzioni complicate che potrebbero non essere direttamente correlate agli equivalenti dalla tua parte, ad es. istruzioni vettoriali, elementptr, call-with-arguments. Ha un numero infinito di registri.

Quindi per scrivere un backend LLVM devi fare le cose delineate nella sezione dei passaggi di base di quel tutorial. Descrivi la macchina, descrivi i suoi registri, descrivi le sue istruzioni, scrivi un codice aggiuntivo per gli emettitori e, se lo desideri, aggiungi alcune ottimizzazioni degli spioncini. LLVM ha molti generatori di codice per rendere queste attività più compatte e meno stereotipate rispetto alla scrittura manuale del codice.

Per scrivere il tuo compilatore IR, devi:

  • Leggi l'IR, idealmente in entrambi i formati di testo e bitcode (potresti usare le librerie LLVM per questo).
  • Scrivi il codice per selezionare le istruzioni native in modo che corrispondano alle istruzioni IR.
    • In alcuni casi, questo può significare sequenze di istruzioni più lunghe, vale a dire una singola chiamata LLVM può risultare in una sequenza di push dello stack seguita da un'istruzione di chiamata seguita da un codice di pulizia.
  • Scrivi il codice per selezionare i registri nativi in cui inserire i valori.
    • Non hai registri infiniti. Potrebbe essere necessario generare ulteriori istruzioni per versare alcuni valori nello stack, ma senza interferire con altre operazioni di stack.
  • Scrivi codice per generare le sequenze di istruzioni risultanti. Questo significa molti tipi di piastre. Devi scrivere un po 'di codice per ogni istruzione della macchina.
  • Scrivi il codice per inserire il codice dell'oggetto risultante in un formato che la CPU può elaborare.

Questo è un sacco di lavoro che LLVM non fa più per te. Direi che è quasi certamente molto più veloce imparare solo a scrivere il backend LLVM. Sì, i concetti potrebbero essere un po 'scoraggianti, ma la quantità di lavoro risparmiata è significativa.

    
risposta data 04.09.2018 - 09:21
fonte

Leggi altre domande sui tag