LLVM | |
---|---|
Tipo de | compilador |
Desarrollador | Vikram Adwe [d] y Chris Lattner [d] |
Escrito en | C++ [3] , C [4] y lenguaje ensamblador [4] |
Sistema operativo | multiplataforma |
Primera edición | 24 de octubre de 2003 [1] |
ultima versión |
|
Licencia | Licencia abierta de la Universidad de Illinois [d] [5]yLicencia Apache 2.0[6] |
Sitio web | www.llvm.org _ |
Archivos multimedia en Wikimedia Commons |
LLVM (anteriormente Low Level Virtual Machine [7] ) es un proyecto de infraestructura de software para crear compiladores y utilidades relacionadas . Consiste en un conjunto de compiladores de lenguajes de alto nivel (los llamados "frontends"), un sistema de optimización, interpretación y compilación en código máquina. La infraestructura se basa en un sistema de codificación de instrucciones de máquina independiente de la plataforma similar a RISC (código de bytes LLVM IR ), que es un ensamblador de alto nivel con el que funcionan varias transformaciones.
Escrito en C++, proporciona optimizaciones en las etapas de compilación, enlace y ejecución. Inicialmente, los compiladores para los lenguajes C y C ++ se implementaron en el proyecto utilizando el front-end de Clang , luego aparecieron front-end para muchos lenguajes, incluidos: ActionScript , Ada , C # [8] , Common Lisp , Crystal , CUDA , D , Delphi , Dylan, Fortran , lenguaje de programación gráfico G, Halide , Haskell , Java (código de bytes), JavaScript , Julia , Kotlin , Lua , Objective-C , lenguaje de sombreado OpenGL , Ruby , Rust , Scala , Swift , Xojo .
LLVM puede producir código nativo para una variedad de arquitecturas, incluidas ARM , x86 , x86-64 , PowerPC , MIPS , SPARC , RISC-V y más (incluidas las GPU de Nvidia y AMD ).
Algunos proyectos tienen sus propios compiladores LLVM (por ejemplo, la versión LLVM de GCC), otros utilizan el marco LLVM [9] , como el compilador Glasgow Haskell .
El desarrollo comenzó en 2000 en la Universidad de Illinois . A mediados de la década de 2010, LLVM se había generalizado en la industria: lo usaban, entre otros, Adobe , Apple y Google . En particular, el subsistema OpenGL en Mac OS X 10.5 se basa en LLVM, y el iPhone SDK usa el preprocesador GCC (frontend) con un backend LLVM. Apple y Google son uno de los principales patrocinadores del proyecto, y uno de los principales desarrolladores, Chris Lattner, trabaja en Apple desde hace 11 años (desde 2017 - en Tesla Motors [10] , desde 2020 - en el desarrollo de procesadores y microcontroladores basados en la arquitectura RISC-V SiFive [11] ).
LLVM se basa en una representación de código intermedio ( Representación intermedia, IR ), que se puede transformar durante la compilación, el enlace y la ejecución. A partir de esta representación, se genera código máquina optimizado para una variedad de plataformas, tanto estática como dinámicamente ( compilación JIT ). LLVM 9.0.0 admite la generación de código estático para x86 , x86-64 , ARM , PowerPC , SPARC , MIPS , RISC-V , Qualcomm Hexagon , NVPTX, SystemZ, Xcore. La compilación JIT (generación de código de máquina en tiempo de ejecución) es compatible con arquitecturas x86, x86_64, PowerPC, MIPS, SystemZ y parcialmente ARM [12] .
LLVM está escrito en C++ y ha sido portado a la mayoría de los sistemas tipo Unix y Windows . El sistema tiene una estructura modular, sus módulos individuales pueden integrarse en varios sistemas de software, puede expandirse con algoritmos de transformación adicionales y generadores de código para nuevas plataformas de hardware.
LLVM incluye un contenedor de API para OCaml .
LLVM es compatible con las siguientes plataformas:
Sistema operativo | Arquitectura | Compilador |
---|---|---|
linux | x86 / AMD64 | CCG , Clang |
FreeBSD | x86 / AMD64 | CCG , Clang |
OpenBSD | x86 / AMD64 | CCG , Clang |
Mac OS X | PowerPC | CCG |
Mac OS X | x86 / AMD64 | CCG , Clang |
Solaris | UltraSPARC | CCG |
Cygwin / Win32 | x86 | GCC 3.4.X, Binutils 2.15 |
MinGW / Win32 | x86 | GCC 3.4.X, Binutils 2.15 |
LLVM tiene soporte parcial para las siguientes plataformas:
Sistema operativo | Arquitectura | Compilador |
---|---|---|
AIX | PowerPC | CCG |
linux | PowerPC | CCG |
sistema operativo amigo | m68k , PowerPC | CCG |
ventanas | x86 | MSVC |
Enteros de bitness arbitrario | un poco de profundidad |
|
| ||
Números de punto flotante | float , double , tipos específicos de plataforma (por ejemplo, x86_fp80 ) | |
valor vacío | vacío |
Punteros | tipo de* | i32* - puntero a entero de 32 bits |
arreglos | [número de elementos x tipo] |
|
estructuras | {i32, i32, doble} | |
Un vector es un tipo especial para simplificar operaciones SIMD .
El vector consta de 2 n valores de un tipo primitivo: entero o coma flotante. |
<número de elementos x tipo> | < 4 x flotante > - vector XMM |
Funciones |
|
El sistema de tipos admite la superposición/anidamiento, es decir, puede usar matrices multidimensionales, matrices de estructuras, punteros a estructuras y funciones, etc.
La mayoría de las instrucciones en LLVM toman dos argumentos (operando) y devuelven un valor (código de tres direcciones). Los valores se definen mediante un identificador de texto. Los valores locales tienen el prefijo %, y los valores globales tienen el prefijo @. Los valores locales también se denominan registros, y LLVM también se denomina máquina virtual con un número infinito de registros. Ejemplo:
%suma = suma i32 %n, 5 %diff = subdoble %a, %b %z = agregar <4 x float> %v1, %v2 ; suma por elementos %cond = icmp eq %x, %y ; Comparación de enteros. El resultado es de tipo i1. %éxito = llamar a i32 @puts(i8* %str)El tipo de los operandos siempre se especifica explícitamente y determina sin ambigüedades el tipo del resultado. Los operandos de las instrucciones aritméticas deben ser del mismo tipo, pero las propias instrucciones están "sobrecargadas" para cualquier vector y tipo numérico.
LLVM admite un conjunto completo de operaciones aritméticas, operaciones lógicas bit a bit y operaciones de cambio, así como instrucciones especiales para trabajar con vectores.
LLVM IR está fuertemente tipado, por lo que hay operaciones de conversión que están codificadas explícitamente con instrucciones especiales. Un conjunto de 9 instrucciones cubre todas las conversiones posibles entre diferentes tipos numéricos: entero y coma flotante, con signo y sin signo, diferente longitud de bit, etc. Además, hay instrucciones para convertir entre números enteros y punteros, así como una instrucción universal para el tipo casting bitcast(responsable de la corrección de tales transformaciones recae en el programador).
Además de los valores de registro, LLVM también tiene manejo de memoria. Los valores en la memoria son direccionados por punteros escritos . Puede acceder a la memoria usando dos instrucciones: loady store. Por ejemplo:
%x = cargar i32* %x.ptr ; carga el valor de tipo i32 en el puntero %x.ptr %tmp = agregar i32 %x, 5 ; añadir 5 almacenar i32 %tmp, i32* %x.ptr ; y poner de nuevoLa instrucción mallocse traduce en una llamada de la función del sistema del mismo nombre y asigna memoria en el montón , devolviendo un valor: un puntero de cierto tipo. Viene con instrucciones free.
%struct.ptr = malloc { doble, doble } %cadena = malloc i8, i32 %longitud %matriz = malloc [16 x i32] libre i8* %cadenaLa instrucción allocaasigna memoria en la pila.
%x.ptr = asignar doble ; %x.ptr es de tipo doble* %matriz = asignación flotante, i32 8 ; ¡%array es de tipo float*, no [8 x float]!La memoria asignada allocase libera automáticamente cuando la función sale usando las instrucciones reto unwind.
Para calcular las direcciones de elementos de arreglos, estructuras, etc. con la escritura correcta, se usa la instrucción getelementptr.
%matriz = asignar i32, i32 %tamaño %ptr = getelementptr i32* %matriz, i32 %index ; valor de tipo i32*getelementptrsolo calcula la dirección, pero no accede a la memoria. La instrucción acepta un número arbitrario de índices y puede desreferenciar estructuras de cualquier anidamiento.
También hay instrucciones extractvaluey insertvalue. Se diferencian en getelementptrque no llevan un puntero a un tipo de dato agregado (matriz o estructura), sino el valor de este tipo en sí. extractvaluedevuelve el valor correspondiente del subelemento, pero insertvaluegenera un nuevo valor del tipo agregado.
%n = valor extraído { i32, [4 x i8*] } %s, 0 %tmp = agregar i32 %n, 1 %s.1 = valor de inserción { i32, [4 x i8*] } %s, i32 %tmp, 0Software gratuito y de código abierto | |
---|---|
Lo principal |
|
Comunidad |
|
Organizaciones |
|
Licencias | |
Problemas | |
Otro |
|
|