LLVM — это набор технологий компилятора и инструментальной цепочки [4] , которые можно использовать для разработки внешнего интерфейса для любого языка программирования и внутреннего интерфейса для любой архитектуры набора команд . LLVM разработан на основе независимого от языка промежуточного представления (IR), которое служит переносимым языком ассемблера высокого уровня , который можно оптимизировать с помощью различных преобразований за несколько проходов. [5] Название LLVM изначально означало «Виртуальная машина низкого уровня», однако проект расширился, и официально это имя больше не является инициализмом .
LLVM написан на C++ и предназначен для оптимизации во время компиляции , компоновки , выполнения и во время простоя. Первоначально реализованный для C и C++, независимый от языка дизайн LLVM с тех пор породил большое количество интерфейсов: языки с компиляторами, которые используют LLVM (или которые не используют LLVM напрямую, но могут генерировать скомпилированные программы как LLVM IR), включают ActionScript , Ada. , C# для .NET , [6] [7] [8] Common Lisp , PicoLisp , Crystal , CUDA , D , Delphi , Dylan , Forth , [9] Fortran , FreeBASIC , Free Pascal , Halide , Haskell , Байт-код Java , Julia , Kotlin , язык G LabVIEW , [10] [11] Lua , Objective-C , OpenCL , [12] SQL PostgreSQL и PLpgSQL, [13] Ruby , [14] Rust , [15] Scala , [16 ] [17] Свифт , Ксоджо и Зиг .
Проект LLVM стартовал в 2000 году в Университете Иллинойса в Урбане-Шампейне под руководством Викрама Адве и Криса Латтнера . LLVM изначально разрабатывался как исследовательская инфраструктура для изучения методов динамической компиляции статических и динамических языков программирования. LLVM был выпущен под лицензией открытого исходного кода Университета Иллинойса/NCSA , [3] — разрешительной лицензией свободного программного обеспечения . В 2005 году компания Apple Inc. наняла Латтнера и сформировала команду для работы над системой LLVM для различных применений в системах разработки Apple. [18] LLVM является неотъемлемой частью инструментов разработки Apple Xcode для macOS и iOS , начиная с Xcode 4 в 2011 году. [19]
В 2006 году Латтнер приступил к работе над новым проектом под названием Clang . Комбинация внешнего интерфейса Clang и внутреннего интерфейса LLVM называется Clang/LLVM или просто Clang.
Название LLVM изначально было инициализмом для виртуальной машины низкого уровня . Однако проект LLVM превратился в зонтичный проект, который имеет мало общего с тем, что большинство нынешних разработчиков называют виртуальной машиной . Это сделало инициализм «сбивающим с толку» и «неуместным», и с 2011 года LLVM «официально больше не является аббревиатурой», [20] а является брендом, применимым к зонтичному проекту LLVM. [21] Проект включает в себя промежуточное представление LLVM (IR), отладчик LLVM , реализацию LLVM стандартной библиотеки C++ (с полной поддержкой C++11 и C++14 [22] ) и т. д. LLVM администрируется. Фондом LLVM. Инженер-компилятор Таня Латтнер стала ее президентом в 2014 году [23] и занимала эту должность по состоянию на 2023 год [обновлять]. [24]
«За разработку и внедрение LLVM» Ассоциация вычислительной техники вручила Викраму Адве, Крису Латтнеру и Эвану Ченгу премию ACM Software System Award 2012 . [25]
Изначально проект был доступен по лицензии UIUC . После выпуска версии 9.0.0 в 2019 году [26] LLVM была заменена лицензией Apache License 2.0 с исключениями LLVM. [3] По состоянию на ноябрь 2022 года [обновлять]около 400 вкладов не получили повторную лицензию. [27] [28]
LLVM может обеспечить средние уровни полной системы компилятора, принимая код промежуточного представления (IR) от компилятора и создавая оптимизированный IR. Затем этот новый IR можно преобразовать и связать с машинно-зависимым кодом ассемблера для целевой платформы. LLVM может принимать IR из инструментальной цепочки GNU Compiler Collection (GCC) , что позволяет использовать его с широким спектром существующих интерфейсов компилятора, написанных для этого проекта. LLVM также можно собрать с помощью gcc после версии 7.5. [29]
LLVM также может генерировать перемещаемый машинный код во время компиляции или компоновки или даже двоичный машинный код во время выполнения.
LLVM поддерживает независимый от языка набор инструкций и систему типов . [5] Каждая инструкция имеет статическую форму одиночного присваивания (SSA), что означает, что каждая переменная (называемая типизированным регистром) назначается один раз, а затем фиксируется. Это помогает упростить анализ зависимостей между переменными. LLVM позволяет компилировать код статически, как в традиционной системе GCC, или оставлять его для поздней компиляции из IR в машинный код посредством JIT- компиляции , аналогично Java . Система типов состоит из базовых типов, таких как целые числа или числа с плавающей запятой , и пяти производных типов : указателей , массивов , векторов , структур и функций . Конструкцию типа на конкретном языке можно представить путем объединения этих базовых типов в LLVM. Например, класс в C++ может быть представлен сочетанием структур, функций и массивов указателей на функции .
JIT-компилятор LLVM может оптимизировать ненужные статические ветки программы во время выполнения и, таким образом, полезен для частичной оценки в тех случаях, когда программа имеет много опций, большинство из которых можно легко определить как ненужные в конкретной среде. Эта функция используется в конвейере OpenGL Mac OS X Leopard (v10.5) для обеспечения поддержки недостающих аппаратных функций. [30]
Графический код в стеке OpenGL можно оставить в промежуточном представлении, а затем скомпилировать при запуске на целевой машине. В системах с высокопроизводительными графическими процессорами (GPU) результирующий код остается довольно тонким, передавая инструкции графическому процессору с минимальными изменениями. В системах с графическими процессорами низкого уровня LLVM компилирует дополнительные процедуры, выполняемые на локальном центральном процессоре (ЦП), которые эмулируют инструкции, которые графический процессор не может выполнять внутри себя. LLVM улучшил производительность на машинах начального уровня с использованием чипсетов Intel GMA . Похожая система была разработана в рамках Gallium3D LLVMpipe и включена в оболочку GNOME , чтобы позволить ей работать без загрузки надлежащего драйвера 3D-оборудования. [31]
В 2011 году программы, составленные GCC, превзошли программы LLVM в среднем на 10%. [32] [33] В 2013 году компания phoronix сообщила, что LLVM догнал GCC, компилируя двоичные файлы примерно с одинаковой производительностью. [34]
LLVM стал зонтичным проектом, состоящим из нескольких компонентов.
Первоначально LLVM был написан как замена существующему генератору кода в стеке GCC [35] , и многие интерфейсы GCC были модифицированы для работы с ним, в результате чего появился ныне несуществующий пакет LLVM-GCC. Модификации обычно включают этап IR из GIMPLE в LLVM, чтобы можно было использовать оптимизаторы и генератор кода LLVM вместо системы GIMPLE GCC. Apple была активным пользователем LLVM-GCC до Xcode 4.x (2013). [36] [37] Такое использование интерфейса GCC считалось в основном временной мерой, но с появлением Clang и преимуществами LLVM и современной модульной кодовой базы Clang (а также скоростью компиляции) оно по большей части устарело.
LLVM в настоящее время [ на момент? ] поддерживает компиляцию Ada , C , C++ , D , Delphi , Fortran , Haskell , Julia , Objective-C , Rust и Swift с использованием различных интерфейсов .
Широкий интерес к LLVM привел к нескольким попыткам разработать новые интерфейсы для многих языков. Наибольшее внимание привлек Clang, новый компилятор, поддерживающий C, C++ и Objective-C. Clang, поддерживаемый в первую очередь Apple, нацелен на замену компилятора C/Objective-C в системе GCC системой, которая легче интегрируется с интегрированными средами разработки (IDE) и имеет более широкую поддержку многопоточности . Поддержка директив OpenMP включена в Clang начиная с версии 3.8. [38]
Компилятор Utrecht Haskell может генерировать код для LLVM. Хотя генератор находился на ранней стадии разработки, во многих случаях он был более эффективен, чем генератор кода C. [39] Бэкэнд Glasgow Haskell Compiler (GHC) использует LLVM и обеспечивает 30%-ное ускорение скомпилированного кода по сравнению с компиляцией собственного кода посредством GHC или генерации кода C с последующей компиляцией, при этом отсутствует только один из многих методов оптимизации, реализованных в компиляторе Glasgow Haskell Compiler (GHC). ГХК. [40]
Многие другие компоненты находятся на разных стадиях разработки, включая, помимо прочего, компилятор Rust , интерфейс байт-кода Java , интерфейс Common Intermediate Language (CIL), реализацию Ruby 1.9 для MacRuby , различные интерфейсы для Standard ML и новый распределитель регистров раскраски графов . [ нужна цитата ]
Ядром LLVM является промежуточное представление (IR), язык программирования низкого уровня, похожий на ассемблер. IR — это строго типизированный набор команд компьютера с сокращенным набором команд (RISC), который абстрагирует большую часть деталей цели. Например, соглашение о вызовах абстрагируется с помощью call
инструкций ret
с явными аргументами. Кроме того, вместо фиксированного набора регистров IR использует бесконечный набор временных регистров формы %0, %1 и т. д. LLVM поддерживает три эквивалентные формы IR: удобочитаемый формат ассемблера, [41] файл в памяти. формат, подходящий для внешних интерфейсов, и плотный формат битового кода для сериализации. Простое «Привет, мир!» программа в формате IR:
@.str = внутренняя константа [ 14 x i8 ] c «Привет, мир\0A\00» объявить i32 @printf ( ptr , ...) define i32 @main ( i32 %argc , ptr %argv ) nounwind { запись: %tmp1 = getelementptr [ 14 x i8 ], ptr @.str , i32 0 , i32 0 %tmp2 = вызов i32 ( ptr , ...) @ printf ( ptr %tmp1 ) nounwind ret i32 0 }
Множество различных используемых соглашений и функций, предоставляемых разными целями, означают, что LLVM не может по-настоящему создать независимый от цели IR и перенацелить его, не нарушая некоторых установленных правил. Примеры целевой зависимости помимо того, что явно упомянуто в документации, можно найти в предложении 2011 года по «слововому коду», полностью независимому от цели варианту LLVM IR, предназначенному для распространения в Интернете. [42] Более практичным примером является PNaCl . [43]
Проект LLVM также представляет другой тип промежуточного представления, названный MLIR [44] , который помогает создавать многократно используемую и расширяемую инфраструктуру компилятора за счет использования подключаемой архитектуры под названием Dialect. [45] Это позволяет использовать информацию более высокого уровня о структуре программы в процессе оптимизации, включая полиэдральную компиляцию .
В версии 16 LLVM поддерживает множество наборов инструкций , включая IA-32 , x86-64 , ARM , Qualcomm Hexagon , LoongArch , M68K , MIPS , NVIDIA Parallel Thread Execution (PTX, в документации LLVM также называется NVPTX ), PowerPC , AMD TeraScale , [46] большинство последних графических процессоров AMD (также называемых AMDGPU в документации LLVM), [47] SPARC , z/Architecture (также называемых SystemZ в документации LLVM) и XCore .
Некоторые функции недоступны на некоторых платформах. Большинство функций присутствует для IA-32, x86-64, z/Architecture, ARM и PowerPC. [48] RISC-V поддерживается начиная с версии 7.
В прошлом LLVM также полностью или частично поддерживал другие серверные части, включая серверную часть C, Cell SPU , mblaze (MicroBlaze) , [49] AMD R600, DEC/Compaq Alpha ( Alpha AXP ) [50] и Nios2 , [51] , но это оборудование по большей части устарело, и разработчики LLVM решили, что затраты на поддержку и обслуживание больше не оправданы. [ нужна цитата ]
LLVM также поддерживает WebAssembly в качестве цели, позволяя скомпилированным программам выполняться в средах с поддержкой WebAssembly, таких как Google Chrome / Chromium , Firefox , Microsoft Edge , Apple Safari или WAVM. Компиляторы WebAssembly, совместимые с LLVM, обычно поддерживают в основном немодифицированный исходный код, написанный на C, C++, D, Rust, Nim, Kotlin и некоторых других языках.
Подпроект машинного кода LLVM (MC) — это платформа LLVM для перевода машинных инструкций между текстовыми формами и машинным кодом. Раньше LLVM полагалась на системный ассемблер или на инструментальную цепочку для перевода ассемблера в машинный код. Встроенный ассемблер LLVM MC поддерживает большинство целей LLVM, включая IA-32, x86-64, ARM и ARM64. Для некоторых целей, включая различные наборы инструкций MIPS, можно использовать встроенную поддержку ассемблера, но она все еще находится на стадии бета-тестирования. [ нужна цитата ]
Подпроект lld — это попытка разработать встроенный, независимый от платформы компоновщик для LLVM. [52] lld стремится устранить зависимость от стороннего компоновщика. По состоянию на май 2017 года [обновлять]lld поддерживает ELF , PE/COFF , Mach-O и WebAssembly [53] в порядке убывания полноты. lld работает быстрее, чем обе версии GNU ld . [ нужна цитата ]
В отличие от компоновщиков GNU, lld имеет встроенную поддержку оптимизации времени компоновки (LTO). Это позволяет ускорить генерацию кода, минуя использование плагина компоновщика, но, с другой стороны, запрещает взаимодействие с другими разновидностями LTO. [54]
Проект LLVM включает реализацию стандартной библиотеки C++ под названием libc++, имеющую двойную лицензию: лицензию MIT и лицензию UIUC . [55]
Начиная с версии 9.0.0, лицензия была заменена на лицензию Apache 2.0 с исключениями LLVM. [3]
Это реализует набор оптимизаций локальности кэша, а также автопараллелизм и векторизацию с использованием многогранной модели . [56]
llvm-libc — это неполная, готовящаяся к выпуску независимая от ABI стандартная библиотека C , разработанная проектом LLVM и для него. [57]
Благодаря разрешительной лицензии многие поставщики выпускают собственные версии LLVM. Это официально признано в документации LLVM, которая по этой причине не рекомендует использовать номера версий при проверке функций. [58] Некоторые из поставщиков включают в себя:
RubyMotion
преобразует исходный код Ruby вашего проекта в ... машинный код с помощью [n] ... опережающего компилятора (AOT), основанного на LLVM.
«LLVM» официально больше не является аббревиатурой. Акроним, который он когда-то расширил, тоже сбивал с толку и был неуместен почти с самого первого дня. :) По мере того, как LLVM разросся и включил в себя другие подпроекты, он стал еще менее полезным и бессмысленным.
Название «LLVM» когда-то было аббревиатурой, но сейчас это просто бренд зонтичного проекта.
Обратите внимание, что номера маркетинговых версий не следует использовать для проверки языковых функций, поскольку разные поставщики используют разные схемы нумерации.
Вместо этого используйте макросы проверки функций.
Текущий NVVM IR основан на LLVM 5.0.