Come compilare clang in llvm IR


150

Voglio che clang compili il mio C/C++codice in LLVMbytecode anziché in eseguibile binario. Come posso raggiungerlo? E se ottengo il LLVMbytecode, come posso prenderlo per compilarlo ulteriormente in eseguibile binario.

Fondamentalmente voglio aggiungere un po 'del mio codice al LLVMbytecode prima di compilare un eseguibile binario.


Immagino che sia chiamato come bitcode LLVM
PreeJackie il

Risposte:


204

Dato un file C / C ++ foo.c:

> clang -S -emit-llvm foo.c

Produce foo.llun file IR LLVM.

L' -emit-llvmopzione può anche essere passata direttamente al front-end del compilatore e non al driver mediante -cc1:

> clang -cc1 foo.c -emit-llvm

Produce foo.llcon IR. -cc1aggiunge alcune opzioni interessanti come -ast-print. Scopri -cc1 --helpper maggiori dettagli.


Per compilare LLVM IR oltre all'assemblaggio, utilizzare lo llcstrumento:

> llc foo.ll

Produce foo.scon assembly (impostazione predefinita per l'architettura della macchina su cui lo si esegue). llcè uno degli strumenti di LLVM: ecco la sua documentazione .


7
Cosa fa -S qui?
meawoppl,

13
@meawoppl: -S come in gcc dice che emette un assemblaggio testuale piuttosto che un binario assemblato
Eli Bendersky,

Ahha. Stavo facendo fatica a trovare qualcosa nei documenti a riguardo. È sicuro supporre che molte bandiere nella struttura della bandiera gcc specchio clang?
meawoppl,

@EliBendersky Sai come compilare più file .c e .h in un IR leggibile dall'uomo in modo che io possa eseguire l'IR usando 'lli theIrFile'? Grazie
cache

1
@cache: compila ciascuno nel suo file IR e poi usa il linker LLVM per combinare
Eli Bendersky

20

Uso

clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc

9
Consiglierei di mantenere intatti i significati dell'estensione. IOW, .odovrebbe fare riferimento a file di oggetti binari, file .sdi assembly e qualcos'altro (per convenzione .ll) a file IR LLVM. Altrimenti è facile confondersi. Clang / LLVM ora non hanno un proprio linker per oggetti binari (anche se uno è in lavorazione). Il linker LLVM llvm-ldunisce appena diversi file IR in uno solo
Eli Bendersky il

1
@EliBendersky: hai ragione riguardo alle estensioni dei file - e il frontend clang fa davvero la cosa giusta se .bcviene usato; inoltre, tieni presente che llvm-ldpuò fungere da frontend per la toolchain di sistema, vale a dire la mia precedente risposta llvm-ld -nativedovrebbe funzionare come previsto ....
Christoph,

1
@rickfoosusa: funziona per me - foo.bcè un file bitcode LLVM
Christoph

1
Lavora per me: clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode.
ntc2,

18

Se si dispone di più file di origine, probabilmente si desidera effettivamente utilizzare l'ottimizzazione del tempo di collegamento per generare un file bitcode per l'intero programma. Le altre risposte fornite ti faranno finire con un file bitcode per ogni file sorgente.

Invece, vuoi compilare con l'ottimizzazione del tempo di collegamento

clang -flto -c program1.c -o program1.o
clang -flto -c program2.c -o program2.o

e per il passaggio finale del collegamento, aggiungere l'argomento -Wl, -plugin-opt = also-emit-llvm

clang -flto -Wl,-plugin-opt=also-emit-llvm program1.o program2.o -o program

Questo ti dà sia un programma compilato che il bitcode corrispondente ad esso (program.bc). È quindi possibile modificare program.bc nel modo desiderato e ricompilare il programma modificato in qualsiasi momento

clang program.bc -o program

sebbene sia necessario tenere presente che in questo passaggio è necessario includere nuovamente eventuali flag di linker necessari (per librerie esterne, ecc.).

Si noti che è necessario utilizzare il linker oro per questo per funzionare. Se vuoi forzare clang a usare un linker specifico, crea un link simbolico a quel linker chiamato "ld" in una directory speciale chiamata "fakebin" da qualche parte sul tuo computer e aggiungi l'opzione

-B/home/jeremy/fakebin

a tutti i passaggi di collegamento sopra.


13

Se hai più file e non vuoi digitare ogni file, ti consiglio di seguire questi semplici passaggi (sto usando clang-3.8ma puoi usare qualsiasi altra versione):

  1. genera tutti i .llfile

    clang-3.8 -S -emit-llvm *.c
  2. collegali in un unico

    llvm-link-3.8 -S -v -o single.ll *.ll
  3. (Opzionale) Ottimizza il tuo codice (forse qualche analisi alias)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
  4. Genera assembly (genera un optimised.sfile)

    llc-3.8 optimised.ll
  5. Crea eseguibile (denominato a.out)

    clang-3.8 optimised.s

La tua soluzione è piuttosto unica: hai usato "-S" invece di lasciarla come output binario. C'è qualche differenza tra avere "-S" e non avere "-S"?
Peter Teoh,

@PeterTeoh Uso l' -Sopzione (al passaggio 2), specificando che vorrei produrre l'output in LLVM IR. Fondamentalmente, metti tutti i file * .ll in uno solo. Faccio questo per verificare che le ottimizzazioni cambino davvero il codice, vale a dire single.llche optimised.llora dovrebbero apparire diverse (per quanto riguarda il codice) e potresti anche mostrare il rapporto per vedere se c'è qualche differenza.
Kiko Fernandez,

-basicaaaè un flag sbagliato, -basicaadeve invece essere utilizzato.
anton_rh

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.