Введение
LLVM — это набор технологий компиляторов и инструментальных средств, которые можно использовать для разработки фронтенда для любого языка программирования и бэкенда для любой архитектуры набора команд. LLVM спроектирован вокруг языково-независимого промежуточного представления (IR), которое служит переносимым ассемблером высокого уровня, оптимизируемым с помощью различных преобразований в несколько проходов. Изначально название LLVM расшифровывалось как Low Level Virtual Machine, однако проект расширился, и теперь это название официально не является акронимом. LLVM написан на C++ и предназначен для оптимизации на этапах компиляции, линковки, выполнения и в "простой" режим. Первоначально разработанный для языков C и C++, языково-независимая архитектура LLVM впоследствии привела к появлению широкого спектра фронтендов: языки с компиляторами, использующими LLVM (или не использующими LLVM напрямую, но способными генерировать скомпилированные программы в формате LLVM IR), включают ActionScript, Ada, C# для .NET, Common Lisp, PicoLisp, Crystal, CUDA, D, Delphi, Dylan, Forth, Fortran, FreeBASIC, Free Pascal, Halide, Haskell, байт-код Java, Julia, Kotlin, язык G LabVIEW, Lua, Objective-C, OpenCL, SQL и PLpgSQL в PostgreSQL, Ruby, Rust, Scala, Swift, Xojo и Zig.
LLVM is a set of compiler and toolchain technologies that can be used to develop a frontend for any programming language and a backend for any instruction set architecture. LLVM is designed around a language independent intermediate representation (IR) that serves as a portable, high level assembly language that can be optimized with a variety of transformations over multiple passes. The name LLVM originally stood for Low Level Virtual Machine, though the project has expanded and the name is no longer officially an initialism. LLVM is written in C++ and is designed for compile time, link time, runtime, and "idle time" optimization. Originally implemented for C and C++, the language agnostic design of LLVM has since spawned a wide variety of frontends: languages with compilers that use LLVM (or which do not directly use LLVM but can generate compiled programs as LLVM IR) include ActionScript, Ada, C# for NET, Common Lisp, PicoLisp, Crystal, CUDA, D, Delphi, Dylan, Forth, Fortran, FreeBASIC, Free Pascal, Halide, Haskell, Java bytecode, Julia, Kotlin, LabVIEW's G language, Lua, Objective C, OpenCL, PostgreSQL's SQL and PLpgSQL, Ruby, Rust, Scala, Swift, Xojo, and Zig.
История
Проект LLVM начался в 2000 году в Университете Иллинойса в Урбана-Шампейн под руководством Викрама Адве и Криса Латтнера. LLVM первоначально разрабатывалась как исследовательская инфраструктура для изучения техник динамической компиляции для статических и динамических языков программирования. LLVM была выпущена под лицензией Университета Иллинойса/NCSA Open Source License. LLVM является неотъемлемой частью инструментов разработки Apple Xcode для macOS и iOS, начиная с Xcode 4 в 2011 году. В 2006 году Латтнер начал работу над новым проектом под названием Clang. Комбинация фронтенда Clang и бэкенда LLVM называется Clang/LLVM или просто Clang. Изначально название LLVM было акронимом от Low Level Virtual Machine (виртуальной машины низкого уровня). Однако проект LLVM превратился в зонтичный проект, который мало связан с тем, что большинство современных разработчиков представляют себе как виртуальную машину. Это сделало акроним "сбивающим с толку" и "неуместным", и с 2011 года LLVM "официально перестала быть акронимом", став брендом, применяемым ко всему проекту LLVM. Проект включает в себя промежуточное представление LLVM (IR), отладчик LLVM, реализацию LLVM стандартной библиотеки C++ (с полной поддержкой C++11 и C++14) и т.д. Управляется LLVM Фондом LLVM. Инженер-компилятор Таня Латтнер стала его президентом в 2014 году и занимала эту должность по состоянию на 2024 год. "За разработку и реализацию LLVM" Ассоциация вычислительной техники (ACM) вручила Викраму Адве, Крису Латтнеру и Эвану Ченгу премию ACM Software System Award в 2012 году. Изначально проект распространялся под лицензией UIUC. После выпуска версии 9.0.0 в 2019 году LLVM была перелицензирована на Apache License 2.0 с исключениями LLVM.
Особенности
LLVM может предоставлять средние уровни полноценной системы компиляторов, принимая промежуточное представление (IR) от компилятора и выдавая оптимизированный IR. Этот новый IR затем может быть преобразован и скомпонован в машинно-зависимый код ассемблера для целевой платформы. LLVM может принимать IR из инструментария GNU Compiler Collection (GCC), что позволяет использовать его с широким спектром существующих фронтендов компилятора, разработанных для этого проекта. LLVM также можно собрать с помощью gcc, начиная с версии 7.5. LLVM также может генерировать переносимый машинный код во время компиляции или компоновки, или даже двоичный машинный код во время выполнения. LLVM поддерживает языково-независимый набор инструкций и систему типов. Графический код в стеке OpenGL может оставаться в промежуточном представлении и компилироваться непосредственно на целевом устройстве. На системах с высокопроизводительными графическими процессорами (GPU) результирующий код остается достаточно компактным, передавая инструкции на GPU с минимальными изменениями. На системах с низкопроизводительными GPU, LLVM будет компилировать дополнительные процедуры, выполняемые на локальном центральном процессоре (CPU), эмулирующие инструкции, которые GPU не может выполнять аппаратно. LLVM повысила производительность на маломощных машинах с использованием чипсетов Intel GMA. Аналогичная система была разработана в рамках Gallium3D LLVMpipe и интегрирована в оболочку GNOME, позволяя ей работать без загрузки полноценного 3D-драйвера. В 2011 году программы, скомпилированные GCC, в среднем на 10% превосходили программы, скомпилированные LLVM. В 2013 году phoronix сообщила, что LLVM сравнялась с GCC по производительности при компиляции бинарных файлов.
Компоненты
LLVM превратился в зонтичный проект, содержащий множество компонентов.
Передние части
LLVM изначально разрабатывалась как замена существующему генератору кода в стеке GCC, и многие фронтенды GCC были модифицированы для работы с ней, что привело к появлению ныне не поддерживаемого набора LLVM GCC. Модификации обычно включают преобразование из GIMPLE в LLVM IR, чтобы использовать оптимизаторы и генератор кода LLVM вместо системы GIMPLE в GCC. Apple была крупным пользователем LLVM GCC в Xcode 4.x (2013). Использование фронтенда GCC рассматривалось в основном как временная мера, но с появлением Clang и преимуществ LLVM и современной модульной кодовой базы Clang (а также скорости компиляции) стало в значительной степени устаревшим. В настоящее время LLVM поддерживает компиляцию Ada, C, C++, D, Delphi, Fortran, Haskell, Julia, Objective C, Rust и Swift с использованием различных фронтендов. Широкий интерес к LLVM привел к нескольким попыткам разработки новых фронтендов для многих языков. Наибольшее внимание привлек Clang – более новый компилятор, поддерживающий C, C++ и Objective C. В основном поддерживаемый Apple, Clang предназначен для замены компилятора C/Objective C в GCC системой, которая легче интегрируется со средами разработки (IDE) и обеспечивает более широкую поддержку многопоточности. Поддержка директив OpenMP была включена в Clang с версии 3.8. Компилятор Utrecht Haskell может генерировать код для LLVM. Хотя генератор находился на ранних стадиях разработки, во многих случаях он был эффективнее, чем генератор кода на C. Бэкенд Glasgow Haskell Compiler (GHC) использует LLVM и обеспечивает ускорение компилируемого кода на 30% по сравнению с нативной компиляцией через GHC или генерацией кода на C с последующей компиляцией, упуская лишь одну из множества техник оптимизации, реализованных в GHC. Многие другие компоненты находятся на разных стадиях разработки, включая, помимо прочего, компилятор Rust, фронтенд для байт-кода Java, фронтенд Common Intermediate Language (CIL), реализацию MacRuby Ruby 1.9, различные фронтенды для Standard ML и новый распределитель регистров на основе раскраски графов.
Бэкэнды
На версии 16 LLVM поддерживает множество наборов инструкций, включая IA 32, x86 64, ARM, Qualcomm Hexagon, LoongArch, M68K, MIPS, NVIDIA Parallel Thread Execution (PTX, также называемый NVPTX в документации LLVM), PowerPC, AMD TeraScale, большинство современных AMD GPU (также называемых AMDGPU в документации LLVM), SPARC, z/Architecture (также называемая SystemZ в документации LLVM) и XCore. Некоторые функции могут быть недоступны на определенных платформах. Большинство функций реализованы для IA 32, x86 64, z/Architecture, ARM и PowerPC. Поддержка RISC V добавлена начиная с версии 7. Ранее LLVM также поддерживала другие бэкенды, полностью или частично, включая бэкенд C, Cell SPU, mblaze (MicroBlaze), AMD R600, DEC/Compaq Alpha (Alpha AXP) и Nios2, однако это оборудование устарело, и разработчики 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. Цель lld — устранить зависимость от стороннего линкера. По состоянию на 2017 год lld поддерживает ELF, PE/COFF, Mach-O и WebAssembly в порядке убывания степени завершённости. lld работает быстрее, чем оба варианта GNU ld. В отличие от линкеров GNU, lld имеет встроенную поддержку оптимизации времени линковки (LTO). Это позволяет ускорить генерацию кода, поскольку обходит использование плагина линкера, но, с другой стороны, ограничивает совместимость с другими реализациями LTO.
Стандартная библиотека C++
Проект LLVM включает реализацию стандартной библиотеки C++ libc++, распространяемую по двойной лицензии MIT и UIUC. Начиная с версии 9.0.0, она была перелицензирована на Apache License 2.0 с исключениями LLVM.
C Стандартная библиотека
llvm libc — это разрабатываемая, неполная стандартная библиотека C, независимая от ABI, созданная для и проектом LLVM.