Low Level Virtual Machine
| LLVM | |
| Тип | |
|---|---|
| Разработчик |
LLVM Developer Group |
| Написана на | |
| Операционная система | |
| Первый выпуск | |
| Последняя версия |
3.0 (30 ноября 2011) |
| Лицензия | |
| Сайт | |
Low Level Virtual Machine (LLVM) — универсальная система анализа, трансформации и оптимизации программ, реализующая виртуальную машину с RISC-подобными инструкциями. Может использоваться как оптимизирующий компилятор этого байткода в машинный код для различных архитектур либо для его интерпретации и JIT-компиляции (для некоторых платформ).
LLVM позволяет компилировать программы написанные на языках С, C++, Objective-C, Fortran, Ada, Haskell, Java, Python, Ruby, JavaScript, GLSL или любом другом, для которого реализован front-end. В рамках проекта разработан фронтенд Clang для языков C и C++ и версия GCC, использующие llvm в качестве бэкенда. В Glasgow Haskell Compiler также реализована компиляция посредством llvm, существует ещё множество программ, использующих данную инфраструктуру.
Содержание |
[править] История
История LLVM началась в 2000 году в Университете Иллинойса, а теперь LLVM используют такие гиганты индустрии как Adobe, Apple и Google. В частности, на LLVM основана подсистема OpenGL в Mac OS X 10.5, а iPhone SDK использует GCC с бэкэндом на LLVM. Apple и Google являются одними из основных спонсоров проекта, а вдохновитель LLVM — Крис Латтнер — теперь работает в Apple.
[править] Особенности
В основе LLVM лежит промежуточное представление кода (Intermediate Representation, IR), над которым можно производить трансформации во время компиляции, компоновки и выполнения. Из этого представления генерируется оптимизированный машинный код для целого ряда платформ, как статически, так и динамически (JIT-компиляция). LLVM поддерживает статическую генерацию кода для x86, x86-64, ARM, PowerPC, SPARC, MIPS, IA-64, Alpha. JIT (генерация машинного кода во время исполнения) поддержан для архитектур x86, x86_64, PowerPC и частично ARM (только целочисленные, без NEON и Thumb) [1]
LLVM написана на C++ и портирована на большинство nix-систем и Windows. Система имеет модульную структуру, отдельные ее модули могут быть встроены в различные программные комплексы, она может расширяться дополнительными алгоритмами трансформации и кодогенераторами для новых аппаратных платформ.
В LLVM включена обертка API для OCaml.
[править] Платформы
LLVM поддерживает работу на следующих платформах:
| Операционная система | Архитектура | Компилятор |
|---|---|---|
| FreeBSD | x86 | GCC, Clang |
| FreeBSD | AMD64 | GCC, Clang |
| Linux | AMD64 | GCC, Clang |
| Linux | x86 | GCC, Clang |
| Mac OS X | PowerPC | GCC |
| Mac OS X | x86 | GCC |
| Solaris | UltraSPARC | GCC |
| Cygwin/Win32 | x86 | GCC 3.4.X, Binutils 2.15 |
| MinGW/Win32 | x86 | GCC 3.4.X, Binutils 2.15 |
LLVM имеет частичную поддержку следующих платформ:
| Операционная система | Архитектура | Компилятор |
|---|---|---|
| Windows | x86 | MSVC |
| AIX | PowerPC | GCC |
| Linux | PowerPC | GCC |
| Linux | Alpha | GCC |
| Linux | Itanium (IA-64) | GCC |
| HP-UX | Itanium (IA-64) | HP aCC |
[править] Типы данных
[править] Простые типы
| Целые числа произвольной разрядности | iразрядность |
|
|
||
| Числа с плавающей точкой | float, double, типы, специфичные для конкретной платформы (например, x86_fp80) | |
| Пустое значение | void | |
[править] Производные типы
| Указатели | тип* | i32* — указатель на 32-битное целое |
| Массивы | [число элементов x тип] |
|
| Структуры | { i32, i32, double } | |
| Вектор — специальный тип для упрощения SIMD-операций. Вектор состоит из 2n значений примитивного типа — целого или с плавающей точкой. | ||
| < число элементов x тип > | < 4 x float > — вектор XMM | |
| Функции |
|
|
Система типов рекурсивна, то есть можно использовать многомерные массивы, массивы структур, указатели на структуры и функции и т. д.
[править] Операции
Большинство инструкций в LLVM принимают два аргумента (операнда) и возвращают одно значение (трёхадресный код). Значения определяются текстовым идентификатором. Локальные значения обозначаются префиксом %, а глобальные — @. Локальные значения также называют регистрами, а LLVM — виртуальной машиной с бесконечным числом регистров. Пример:
%sum = add i32 %n, 5 %diff = sub double %a, %b %z = add <4 x float> %v1, %v2 ; поэлементное сложение %cond = icmp eq %x, %y ; Сравнение целых чисел. Результат имеет тип i1. %success = call i32 @puts(i8* %str)
Тип операндов всегда указывается явно, и однозначно определяет тип результата. Операнды арифметических инструкций должны иметь одинаковый тип, но сами инструкции «перегружены» для любых числовых типов и векторов.
LLVM поддерживает полный набор арифметических операций, побитовых логических операций и операций сдвига, а также специальные инструкции для работы с векторами.
LLVM IR строго типизирован, поэтому существуют операции приведения типов, которые явно кодируются специальными инструкциями. Набор из 9 инструкций покрывает всевозможные приведения между различными числовыми типами: целыми и с плавающей точкой, со знаком и без, различной разрядности и пр. Кроме этого есть инструкции преобразования между целыми и указателями, а также инструкция bitcast, которая приведёт всё ко всему, но за результат вы отвечаете сами.
[править] Память
Помимо значений-регистров, в LLVM есть и работа с памятью. Значения в памяти адресуются типизированными указателями. Обратиться к памяти можно с помощью двух инструкций: load и store. Например:
%x = load i32* %x.ptr ; загрузить значение типа i32 по указателю %x.ptr %tmp = add i32 %x, 5 ; прибавить 5 store i32 %tmp, i32* %x.ptr ; и положить обратно
Инструкция malloc транслируется в вызов одноименной системной функции и выделяет память на куче, возвращая значение — указатель определенного типа. В паре с ней идёт инструкция free.
%struct.ptr = malloc { double, double }
%string = malloc i8, i32 %length
%array = malloc [16 x i32]
free i8* %string
Инструкция alloca выделяет память на стеке.
%x.ptr = alloca double ; %x.ptr имеет тип double* %array = alloca float, i32 8 ; %array имеет тип float*, а не [8 x float]!
Память, выделенная alloca, автоматически освобождается при выходе из функции при помощи инструкций ret или unwind.
[править] Операции с указателями
Для вычисления адресов элементов массивов, структур и т. д. с правильной типизацией выполняется с помощью инструкции getelementptr.
%array = alloca i32, i32 %size %ptr = getelementptr i32* %array, i32 %index ; значение типа i32*
getelementptr только вычисляет адрес, но не обращается к памяти. Инструкция принимает произвольное количество индексов и может разыменовывать структуры любой вложенности.
Также существует инструкции extractvalue и insertvalue. Они отличаются от getelementptr тем, что принимают не указатель на агрегатный тип данных (массив или структуру), а само значение такого типа. extractvalue возвращает соответственное значение подэлемента, а insertvalue порождает новое значение агрегатного типа.
%n = extractvalue { i32, [4 x i8*] } %s, 0
%tmp = add i32 %n, 1
%s.1 = insertvalue { i32, [4 x i8*] } %s, i32 %tmp, 0
[править] Примечания
- ↑ http://llvm.org/docs/CodeGenerator.html раздел Target Feature Matrix
[править] Ссылки
- LLVM
- SAFECode
- libJIT Linear Scan Register Allocator
- Amy Brown and Greg Wilson (eds.) Chapter 11. LLVM (Chris Lattner) // The Architecture of Open Source Applications. — 2011. — P. 155-170. — 432 p. — ISBN 978-1-257-63801-7
[править] Смотреть также
- Сравнение областей применения различных виртуальных машин (англ.). Архивировано из первоисточника 14 февраля 2012.
- Библиотека для компиляции на лету libjit (англ.).(недоступная ссылка)
|
|
|
|---|---|
| Главное | |
| История |
Linux • Mozilla (Suite • Firefox • Thunderbird) • Revolution OS (фильм) |
| Разработка |
GCC • LLVM |
| Организации | |
| Лицензии |
Apache • BSD • CDDL • GPL • LGPL • MIT • MPL • zlib • Пермиссивные лицензии • Разнообразие лицензий |
| Проблемы | |