Interested Article - LLVM

LLVM (ранее Low Level Virtual Machine ) — проект программной инфраструктуры для создания компиляторов и сопутствующих им утилит . Состоит из набора компиляторов из языков высокого уровня (так называемых «фронтендов»), системы оптимизации, интерпретации и компиляции в машинный код. В основе инфраструктуры используется RISC -подобная платформонезависимая система кодирования машинных инструкций ( байткод LLVM IR), которая представляет собой высокоуровневый ассемблер, с которым работают различные преобразования.

Написан на C++, обеспечивает оптимизации на этапах компиляции, компоновки и исполнения. Изначально в проекте были реализованы компиляторы для языков Си и C++ при помощи фронтенда Clang , позже появились фронтенды для множества языков, в том числе: ActionScript , Ада , C# , Common Lisp , Crystal , CUDA , D , Delphi , Dylan, Fortran , Graphical G Programming Language , , Haskell , Java (байткод), JavaScript , Julia , Kotlin , Lua , Objective-C , OpenGL Shading Language , Ruby , Rust , Scala , Swift , Xojo , Zig .

LLVM может создавать машинный код для множества архитектур, в том числе ARM , x86 , x86-64 , PowerPC , MIPS , SPARC , RISC-V и других (включая GPU от Nvidia и AMD ).

Некоторые проекты имеют собственные LLVM-компиляторы (например LLVM-версия GCC), другие используют инфраструктуру LLVM , например таков Glasgow Haskell Compiler .

Разработка начата в 2000 году в Университете Иллинойса . К середине 2010-х годов LLVM получил широкое распространение в индустрии: использовался, в том числе, в компаниях Adobe , Apple и Google . В частности, на LLVM основана подсистема OpenGL в Mac OS X 10.5, а iPhone SDK использует препроцессор (фронтенд) GCC с бэкэндом на LLVM. Apple и Google являются одними из основных спонсоров проекта, а один из основных разработчиков — Крис Латтнер — 11 лет проработал в Apple (с 2017 года — в Tesla Motors , с 2020 года — в разработчике процессоров и микроконтроллеров на архитектуре RISC-V SiFive ).

Особенности

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

LLVM написана на C++ и портирована на большинство Unix-подобных систем и Windows . Система имеет модульную структуру, отдельные её модули могут быть встроены в различные программные комплексы, она может расширяться дополнительными алгоритмами трансформации и кодогенераторами для новых аппаратных платформ.

В LLVM включена обёртка API для OCaml .

Платформы

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

Операционная система Архитектура Компилятор
Linux x86 / AMD64 GCC , Clang
FreeBSD x86 / AMD64 GCC , Clang
OpenBSD x86 / AMD64 GCC , Clang
macOS PowerPC GCC
macOS x86 / AMD64 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 -операций.

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

< число элементов 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 .

Инструкция 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. (англ.) — 2023.
  2. — 2006.
  3. (англ.)
  4. (англ.)
  5. — 2019.
  6. от 3 ноября 2016 на Wayback Machine , 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.»
  7. . Дата обращения: 14 апреля 2015. 19 мая 2019 года.
  8. (англ.) . llvm. Дата обращения: 24 мая 2018. 24 мая 2018 года.
  9. . Дата обращения: 11 января 2017. 11 января 2017 года.
  10. . Дата обращения: 28 января 2020. 28 января 2020 года.
  11. от 1 мая 2021 на Wayback Machine раздел Target Feature Matrix (англ.)

Литература

  • Андрей Боровский. // Linux Format . — Вып. 2010 , № 2 (128) . — С. 76—79 .
  • Amy Brown and Greg Wilson (eds.). Chapter 11. LLVM (Chris Lattner) // . — 2011. — P. 155—170. — 432 p. — ISBN 978-1-257-63801-7 . ( )
  • Арпан Сен. . IBM developerWorks (12 ноября 2012). Дата обращения: 15 мая 2015. ,
  • Chris Lattner. . Dr. Dobb’s Journal (29 мая 2012). Дата обращения: 15 мая 2015.
  • John Siracusa. . Ars Technica (1 сентября 2009). Дата обращения: 15 мая 2015.

Ссылки

  • — официальный сайт LLVM
Источник —

Same as LLVM