LLVM: различия между версиями

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
[отпатрулированная версия][отпатрулированная версия]
Содержимое удалено Содержимое добавлено
м Преамбула: капитализация
Преамбула: добавлено упоминание про Rust
Строка 11: Строка 11:
В рамках проекта LLVM был разработан [[Front and back ends|фронтенд]] [[Clang]] для языков [[Си (язык программирования)|C]], [[C++]] и [[Objective-C]], транслирующий исходные коды в байткод LLVM и позволяющий использовать LLVM в качестве полноценного компилятора.
В рамках проекта LLVM был разработан [[Front and back ends|фронтенд]] [[Clang]] для языков [[Си (язык программирования)|C]], [[C++]] и [[Objective-C]], транслирующий исходные коды в байткод LLVM и позволяющий использовать LLVM в качестве полноценного компилятора.


Для LLVM создано несколько фронтендов, в том числе сторонними разработчиками, которые позволяют компилировать программы, написанные на языках [[C (язык программирования)|С]], [[C++]], [[C Sharp|C#]]<ref>{{Cite web|url = https://github.com/dotnet/llilc/wiki|title = LLILC|author = |work = |date = |publisher = }}</ref>, [[D (язык программирования)|D]], [[Objective-C]], [[Fortran]], [[Ада (язык программирования)|Ada]], [[Haskell]], [[Java]], [[Kotlin]], [[Python]], [[Ruby]], [[JavaScript]], [[GLSL]]. Ранее также была подготовлена версия [[GCC]], транслирующая программы в байт-код LLVM. В [[Glasgow Haskell Compiler]] также реализована компиляция посредством LLVM.
Для LLVM создано несколько фронтендов, в том числе сторонними разработчиками, которые позволяют компилировать программы, написанные на языках [[C (язык программирования)|С]], [[C++]], [[C Sharp|C#]]<ref>{{Cite web|url = https://github.com/dotnet/llilc/wiki|title = LLILC|author = |work = |date = |publisher = }}</ref>, [[D (язык программирования)|D]], [[Objective-C]], [[Fortran]], [[Ада (язык программирования)|Ada]], [[Haskell]], [[Java]], [[Kotlin]], [[Python]], [[Ruby]], [[JavaScript]], [[GLSL]], [[Rust (язык программирования)|Rust]]. Ранее также была подготовлена версия [[GCC]], транслирующая программы в байт-код LLVM. В [[Glasgow Haskell Compiler]] также реализована компиляция посредством LLVM.


Существует множество программ и проектов, использующих инфраструктуру LLVM для генерации машинного кода.
Существует множество программ и проектов, использующих инфраструктуру LLVM для генерации машинного кода.

Версия от 06:46, 12 февраля 2018

LLVM
Логотип программы LLVM
Тип компилятор
Разработчик LLVM Developer Group
Написана на C++[3], Си[4] и язык ассемблера[4]
Операционные системы кроссплатформенность, NetBSD, FreeBSD, OpenBSD, Linux, Миникс 3, Windows и Illumos
Первый выпуск 24 октября 2003[1]
Последняя версия
Репозиторий github.com/llvm/llvm-pro…
Лицензия University of Illinois/NCSA Open Source License
Сайт llvm.org (англ.)
Логотип Викисклада Медиафайлы на Викискладе

LLVM (ранее Low Level Virtual Machine[5]) — универсальная система анализа, трансформации и оптимизации программ, реализующая виртуальную машину с RISC-подобными инструкциями. Может использоваться как оптимизирующий компилятор этого байткода в машинный код для различных архитектур либо для его интерпретации и JIT-компиляции (для некоторых платформ).

В рамках проекта LLVM был разработан фронтенд Clang для языков C, C++ и Objective-C, транслирующий исходные коды в байткод LLVM и позволяющий использовать LLVM в качестве полноценного компилятора.

Для LLVM создано несколько фронтендов, в том числе сторонними разработчиками, которые позволяют компилировать программы, написанные на языках С, C++, C#[6], D, Objective-C, Fortran, Ada, Haskell, Java, Kotlin, Python, Ruby, JavaScript, GLSL, Rust. Ранее также была подготовлена версия GCC, транслирующая программы в байт-код LLVM. В Glasgow Haskell Compiler также реализована компиляция посредством LLVM.

Существует множество программ и проектов, использующих инфраструктуру LLVM для генерации машинного кода.

История

История LLVM началась в 2000 году в Университете Иллинойса. В настоящее время LLVM используется, в том числе, в компаниях Adobe, Apple и Google. В частности, на LLVM основана подсистема OpenGL в Mac OS X 10.5, а iPhone SDK использует препроцессор (фронтенд) GCC с бэкэндом на LLVM. Apple и Google являются одними из основных спонсоров проекта, а вдохновитель LLVM — Крис Латтнер — 11 лет работал в Apple. C января 2017 работает в компании Tesla Motors[7].

Особенности

В основе LLVM лежит промежуточное представление кода (Intermediate Representation, IR), над которым можно производить трансформации во время компиляции, компоновки и выполнения. Из этого представления генерируется оптимизированный машинный код для целого ряда платформ, как статически, так и динамически (JIT-компиляция). LLVM 3.6 поддерживает статическую генерацию кода для x86, x86-64, ARM, PowerPC, SPARC, MIPS, Qualcomm Hexagon, NVPTX, SystemZ, Xcore. JIT-компиляция (генерация машинного кода во время исполнения) поддержана для архитектур x86, x86_64, PowerPC, MIPS, SystemZ, и частично ARM[8].

LLVM написана на C++ и портирована на большинство UNIX-подобных систем и 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, Clang
Solaris UltraSPARC GCC
Cygwin/Win32 x86 GCC 3.4.X, Binutils 2.15
MinGW/Win32 x86 GCC 3.4.X, Binutils 2.15

LLVM имеет частичную поддержку следующих платформ:

Операционная система Архитектура Компилятор
AIX PowerPC GCC
Linux PowerPC GCC
AmigaOS m68k, PowerPC GCC
Windows x86 MSVC

Типы данных

Простые типы

Целые числа произвольной разрядности iразрядность
  • i1 — булево значение — 0 или 1
  • i32 — 32-разрядное целое
  • i17
  • i256
  • Генерация машинного кода для типов очень большой разрядности не поддерживается. Но для промежуточного представления никаких ограничений нет.
  • Числа считаются представленными в дополнительном коде. Различий между знаковыми и беззнаковыми целыми на уровне типов не делается: в тех случаях, когда это имеет значение, с ними работают разные инструкции.
Числа с плавающей точкой float, double, типы, специфичные для конкретной платформы (например, x86_fp80)
Пустое значение void

Производные типы

Указатели тип* i32* — указатель на 32-разрядное целое
Массивы [число элементов x тип]
  • [10 x i32]
  • [8 x double]
Структуры { i32, i32, double }
Вектор — специальный тип для упрощения SIMD-операций.

Вектор состоит из 2n значений примитивного типа — целого или с плавающей точкой.

< число элементов x тип > < 4 x float > — вектор XMM
Функции
  • i32 (i32, i32)
  • float ({ float, float }, { float, float })

Система типов рекурсивна, то есть можно использовать многомерные массивы, массивы структур, указатели на структуры и функции и т. д.

Операции

Большинство инструкций в 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

См. также

Примечания

  1. Латтнер К. The LLVM 1.0 Release is finally available!
  2. LLVM 19.1.6 Released! (англ.) — 2024.
  3. The llvm Open Source Project on Open Hub: Languages Page — 2006.
  4. 1 2 The llvm Open Source Project on Open Hub: Languages Page (англ.)
  5. LLVMdev: The name of LLVM, Chris Lattner (Apple), 2011-12-21 ""LLVM" is officially no longer an acronym. The acronym it once expanded too was confusing, and inappropriate almost from day 1."
  6. LLILC.
  7. https://www.tesla.com/blog/welcome-chris-lattner
  8. The LLVM Target-Independent Code Generator раздел Target Feature Matrix  (англ.)

Литература

  • Андрей Боровский. LLVM: Генератор быстрого кода // LinuxFormat. — Вып. 2010, № 2 (128). — С. 76-79.
  • Bruno Cardoso Lopes, Rafael Auler. Getting Started with LLVM Core Libraries. — Packt Publishing, авг. 2014. — 314 с. — (Community Experience Distilled). — ISBN 978-1-78216-693-1.
  • 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. (перевод)
  • Арпан Сен. Создание действующего компилятора с помощью инфраструктуры LLVM. Часть 1. IBM developerWorks (12 ноября 2012). Дата обращения: 15 мая 2015., Часть 2
  • Chris Lattner. The Design of LLVM. Dr. Dobb’s Journal (29 мая 2012). Дата обращения: 15 мая 2015.
  • John Siracusa. Mac OS X 10.6 Snow Leopard: the Ars Technica review → LLVM and Clang. Ars Technica (1 сентября 2009). Дата обращения: 15 мая 2015.

Ссылки