Cómo hacer compilación clang a llvm IR

150

Quiero que clang compile mi C/C++código para LLVMbytecode en lugar de ejecutable binario. ¿Cómo puedo lograr eso? Y si obtengo el LLVMcódigo de bytes, ¿cómo puedo tomarlo para compilarlo en un ejecutable binario?

Básicamente quiero agregar algo de mi propio código al LLVMbytecode antes de compilarlo en el ejecutable binario.

pitónico
fuente
Supongo que se llama como código de bits LLVM
PreeJackie

Respuestas:

204

Dado algún archivo C / C ++ foo.c:

> clang -S -emit-llvm foo.c

Produce foo.llun archivo IR LLVM.

La -emit-llvmopción también se puede pasar al front-end del compilador directamente, y no al controlador mediante -cc1:

> clang -cc1 foo.c -emit-llvm

Produce foo.llcon el IR. -cc1agrega algunas opciones interesantes como -ast-print. Echa un vistazo -cc1 --helppara más detalles.


Para compilar LLVM IR más allá del ensamblaje, use la llcherramienta:

> llc foo.ll

Produce foo.scon ensamblaje (predeterminado en la arquitectura de la máquina en la que lo ejecuta). llces una de las herramientas de LLVM, aquí está su documentación .

Eli Bendersky
fuente
77
¿Qué hace -S aquí?
meawoppl
13
@meawoppl: -S como en gcc dice emitir ensamblaje textual en lugar de ensamblado binario
Eli Bendersky
Ahha Me estaba costando encontrar algo en los documentos al respecto. ¿Es seguro asumir que muchas banderas en clang reflejan la estructura de la bandera de gcc?
meawoppl
@EliBendersky ¿Sabe cómo compilar múltiples archivos .c y .h en un IR legible para que pueda ejecutar el IR usando 'lli theIrFile'? Gracias
caché
1
@ caché: compile cada uno en su propio archivo IR y luego use el enlazador LLVM para combinar
Eli Bendersky
20

Utilizar

clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc
Christoph
fuente
9
Recomiendo mantener intactos los significados de extensión. IOW, .odebe referirse a archivos de objetos binarios, .sa archivos de ensamblaje y algo más (por convención .ll) a archivos IR LLVM. De lo contrario, es fácil confundirse. Clang / LLVM ahora no tiene un enlazador propio para objetos binarios (aunque uno está en proceso). El enlazador LLVM llvm-ldsolo une varios archivos IR en uno
Eli Bendersky,
1
@EliBendersky: tiene razón en lo que respecta a las extensiones de archivo, y la interfaz de sonido metálico hace lo correcto si .bcse usa; también, tenga en cuenta que llvm-ldpuede actuar como interfaz para la cadena de herramientas del sistema, es decir, mi respuesta anterior llvm-ld -nativedebería funcionar como se esperaba ...
Christoph
1
@rickfoosusa: funciona para mí - foo.bces un archivo de código de bits LLVM
Christoph
1
Que funciona para mí: clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode.
ntc2
18

Si tiene varios archivos de origen, probablemente quiera utilizar la optimización del tiempo de enlace para generar un archivo de código de bits para todo el programa. Las otras respuestas dadas harán que termines con un archivo de código de bits para cada archivo fuente.

En cambio, desea compilar con link-time-optimization

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

y para el paso final de vinculación, agregue el argumento -Wl, -plugin-opt = also-emit-llvm

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

Esto le da tanto un programa compilado y el código binario correspondiente a la misma (program.bc). Luego puede modificar program.bc de la forma que desee y volver a compilar el programa modificado en cualquier momento haciendo

clang program.bc -o program

aunque tenga en cuenta que debe incluir cualquier indicador de enlace necesario (para bibliotecas externas, etc.) en este paso nuevamente.

Tenga en cuenta que debe usar el vinculador de oro para que esto funcione. Si desea obligar a clang a usar un enlazador específico, cree un enlace simbólico a ese enlazador llamado "ld" en un directorio especial llamado "fakebin" en algún lugar de su computadora, y agregue la opción

-B/home/jeremy/fakebin

a cualquier paso de enlace anterior.

Jeremy Salwen
fuente
13

Si tiene varios archivos y no desea tener que escribir cada archivo, le recomendaría que siga estos pasos simples (estoy usando clang-3.8pero puede usar cualquier otra versión):

  1. generar todos los .llarchivos

    clang-3.8 -S -emit-llvm *.c
  2. vincularlos en uno solo

    llvm-link-3.8 -S -v -o single.ll *.ll
  3. (Opcional) Optimice su código (quizás un análisis de alias)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
  4. Generar ensamblaje (genera un optimised.sarchivo)

    llc-3.8 optimised.ll
  5. Crear ejecutable (nombrado a.out)

    clang-3.8 optimised.s
Kiko Fernandez
fuente
Su solución es bastante única: usó "-S" en lugar de simplemente dejarlo como salida binaria. ¿Hay alguna diferencia entre tener "-S" y no tener "-S"?
Peter Teoh
@PeterTeoh Uso la -Sopción (en el paso 2), especifico que me gustaría producir la salida en LLVM IR. Básicamente, coloque todos los archivos * .ll en uno solo. Hago esto para verificar que las optimizaciones realmente cambian el código, es decir, single.lly optimised.llahora deberían verse diferentes (en cuanto al código) y también podría mostrar el informe para ver si hay alguna diferencia.
Kiko Fernández el
-basicaaaes un indicador incorrecto, -basicaadebe usarse en su lugar.
anton_rh