¿Qué pinta LLVM en Rust?, es más, ¿qué es LLVM?

Rust es un lenguaje de programación compilado, y si lees sobre él pronto encontrarás referencias a LLVM y querrás saber qué es. Yo también me lo he preguntado.

En su página oficial (llvm.org) está todo lo que hay que saber sobre The LLVM Compiler Infraestructure, La Infraestructura de Compilación LLVM, o directamente la LLVM. Al principio era acrónimo de Low Level Virtual Machine, pero realmente tiene poco que ver con las máquinas virtuales tradicionales, así que optaron por convertir el nombre en marca para identificar al proyecto en sí mismo.

Esencialmente el proyecto LLVM es una colección de tecnologías, herramientas y módulos reutilizables para la compilación de programas. Está compuesto por varios subproyectos importantes y se usa para una amplia variedad de tareas: desde hacer compilaciones JIT ligeras de lenguajes embebidos como Lua hasta compilar código Fortran para superordenadores.

LLVM se creó originalmente para C y C++, pero su diseño agnóstico, versatilidad, flexibilidad y capacidad de reutilización permitió incorporarla en las herramientas de compilación de otros lenguajes como Swift o Haskell. Y, por supuesto, Rust.

LLVM IR

Básicamente compilar consiste en traducir un código fuente escrito en un lenguaje de programación de alto nivel que no es directamente ejecutable, a un código de más bajo nivel como lenguaje ensamblador o el propio código máquina binario que se ejecuta en la computadora.

En el caso de la LLVM, cuando se compila un programa, se traduce inicialmente a una representación intermedia (LLVM IR) que el compilador optimizará posteriormente para generar el ejecutable final.

Es típico en muchos compiladores. Puesto que muchas técnicas de optimización son generales, se pueden aplicar directamente en el nivel IR y compartirse luego para generar el código máquina final de cualquier plataforma (por ejemplo x86).

Por eso pueden identificarse en LLVM tres componentes, cada uno con una función específica:

  • front-end, se encarga de compilar el lenguaje fuente a LLVM IR;
  • middle-end, aplica las optimizaciones en el IR (LLVM optimizer); y
  • back-end, genera el código máquina para la plataforma destino (LLVM static compiler).

Compiladores, transpiladores e intérpretes

No todos los lenguajes de programación requieren compiladores.

También existen los intérpretes, que procesan y ejecutan el código fuente línea a línea, actuando como una interfaz entre el programa y el procesador de la máquina.

O programas que se ejecutan aplicando técnicas mixtas, como los lenguajes que se precompilan para generar un código que luego es interpretado. Perl es uno de esos lenguajes que también uso mucho para programar.

Por otro lado están los transpiladores, que traducen código entre dos lenguajes que están al mismo nivel de abstracción. Podríamos decir que un transpilador es también un compilador, pero al revés no ocurre. Por ejemplo, la traducción de Java a bytecode sería una compilación, y la traducción de TypeScript a JavaScript, muy de moda últimamente, sería una transpilación.

Rust y LLVM

Rust cuenta oficialmente con un grupo de trabajo dedicado a retocar y mejorar el código de LLVM para el compilador de Rust (rustc).

Si quieres ver cómo se genera LLVM IR desde un programa Rust accede a Rust Playground, un entorno donde puedes escribir, compilar y ejecutar código Rust directamente desde tu navegador. Sólo tienes que pulsar en el botón de los tres puntos, al lado del botón RUN, y pulsar la opción LLVM IR.

Si tienes instalado Rust, puedes escribir un programa:

fn main() {
    println!("¡Hola, mundo!");
}

y compilarlo usando la siguiente opción:

$ rustc hola.rs --emit=llvm-ir

para generar su correspondiente código LLVM en representación intermedia (IR). También puedes compilar a bitcode con:

$ rustc hola.rs --emit=llvm-bc

0 comentarios

Dejar un comentario

¿Quieres unirte a la conversación?
Siéntete libre de contribuir!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *