Открыть сервис

LLVM

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

История

Проект LLVM был начат в 2000 году исследователем Викрамом Адве (Vikram Adve) и аспирантом Крисом Латтнером (Chris Lattner) в Иллинойсском университете в Урбане-Шампейне. Первоначально он разрабатывался как исследовательская платформа для изучения методов динамической компиляции и оптимизации. В 2003 году была выпущена первая публичная версия. В 2005 году компания Apple Inc. наняла Криса Латтнера и начала активно использовать LLVM в своих продуктах, включая компилятор для языка Objective-C и инструменты разработки Xcode. В 2011 году LLVM стал основой для компилятора Clang, который заменил GCC в экосистеме Apple. В 2012 году проект был передан под управление некоммерческой организации LLVM Foundation, которая координирует его развитие и поддерживает сообщество разработчиков. С тех пор LLVM стал стандартом де-факто для многих индустриальных и академических проектов, включая компиляторы для языков C, C++, Rust, Swift, Julia и других.

Архитектура

LLVM построен по модульному принципу, что позволяет использовать его компоненты независимо друг от друга. Основные элементы архитектуры:

Промежуточное представление (LLVM IR)

LLVM IR — это низкоуровневый, типизированный, трёхадресный код, который служит мостом между исходным кодом и машинным кодом. Он обладает следующими свойствами:

  • Переносимость: IR не зависит от архитектуры целевой платформы.
  • Оптимизация: IR позволяет применять универсальные оптимизации (например, свёртку констант, удаление мёртвого кода, инлайнинг) до генерации машинного кода.
  • Форматы: IR может быть представлен в трёх формах: текстовый (.ll), бинарный (.bc) и встроенный в память.

Фронтенды

Фронтенды (frontends) отвечают за синтаксический анализ исходного кода и преобразование его в LLVM IR. Наиболее известные фронтенды:

  • Clang — компилятор для языков C, C++, Objective-C и Objective-C++. Он обеспечивает высокую скорость компиляции, подробные сообщения об ошибках и совместимость с GCC.
  • LLVM-GCC — устаревший фронтенд, основанный на GCC, который использовался на ранних этапах проекта.
  • Rustc — компилятор языка Rust, который использует LLVM в качестве бэкенда.
  • Swiftc — компилятор языка Swift, разработанный Apple.
  • Flang — фронтенд для языка Fortran.
  • MLIR — мультиуровневое промежуточное представление, используемое для машинного обучения и других специализированных задач.

Оптимизатор (Pass Manager)

Оптимизатор LLVM состоит из набора проходов (passes), которые обрабатывают LLVM IR. Проходы могут быть:

  • Анализирующие — собирают информацию о коде (например, граф потока управления, зависимости данных).
  • Трансформирующие — изменяют IR для улучшения производительности или уменьшения размера (например, распространение констант, векторизация, удаление неиспользуемого кода).

Оптимизатор поддерживает как стандартные уровни оптимизации (-O0, -O1, -O2, -O3, -Os, -Oz), так и пользовательские конвейеры.

Бэкенды

Бэкенды (backends) генерируют машинный код для конкретных архитектур из LLVM IR. LLVM поддерживает широкий спектр процессоров, включая:

Бэкенды также включают генерацию отладочной информации (DWARF), ассемблерный код и объектные файлы.

Ключевые компоненты

Помимо ядра LLVM, в проект входят несколько важных инструментов и библиотек:

Clang

Clang — это фронтенд для языков семейства C, который также включает в себя:

  • Статический анализатор — находит потенциальные ошибки (например, утечки памяти, неопределённое поведение) без выполнения программы.
  • Инструменты для рефакторинга — автоматическое изменение кода (например, переименование переменных, изменение сигнатур функций).
  • Поддержка санитайзеровAddressSanitizer (ASan), UndefinedBehaviorSanitizer (UBSan), MemorySanitizer (MSan) и другие для обнаружения ошибок во время выполнения.

LLDB

LLDB — это отладчик, использующий LLVM и Clang для анализа кода. Он поддерживает отладку на уровне исходного кода, машинного кода и ассемблера, а также имеет встроенный скриптовый движок на Python.

LLD

LLD — это быстрый компоновщик (линкер), который заменяет GNU ld. Он поддерживает форматы ELF, COFF, Mach-O и WebAssembly, и отличается высокой скоростью работы и низким потреблением памяти.

libc++ и libc++abi

libc++ — это реализация стандартной библиотеки C++ (включая STL), а libc++abi — поддержка ABI (Application Binary Interface) для C++. Они разрабатываются в рамках проекта LLVM и оптимизированы для работы с Clang.

Polly

Polly — это оптимизатор, основанный на полиэдральной модели, который выполняет высокоуровневые преобразования циклов (например, распараллеливание, векторизацию, развёртывание) для повышения производительности.

Применение

LLVM широко используется в различных областях разработки программного обеспечения:

Компиляция языков программирования

Благодаря модульной архитектуре, LLVM служит основой для компиляторов многих языков:

  • C/C++/Objective-C — через Clang.
  • Rust — официальный компилятор rustc.
  • Swift — компилятор Apple.
  • Julia — использует LLVM для JIT-компиляции.
  • Kotlin/Native — компилирует Kotlin в нативный код.
  • Crystal — язык с синтаксисом, подобным Ruby, компилируется через LLVM.
  • Zig — системный язык, использующий LLVM в качестве бэкенда.

Разработка инструментов анализа

LLVM используется для создания статических анализаторов, инструментов проверки типов и рефакторинга. Например, Clang Static Analyzer встроен в Xcode и используется для поиска ошибок в коде на C/C++.

Оптимизация кода

LLVM применяется в высокопроизводительных вычислениях (HPC) для автоматической векторизации, распараллеливания и оптимизации под конкретные архитектуры. Проект Polly позволяет выполнять полиэдральные преобразования, которые улучшают локальность данных и использование кэша.

Встраиваемые системы и мобильные платформы

LLVM используется для компиляции кода под Android (через NDK) и iOS (через Xcode). Благодаря поддержке ARM и RISC-V, он популярен в разработке для встраиваемых устройств.

Веб-технологии

LLVM используется в проектах, связанных с WebAssembly, например, компилятор Emscripten преобразует C/C++ код в WebAssembly, используя LLVM в качестве бэкенда.

Интересные факты

  • Название «LLVM» изначально расшифровывалось как «Low Level Virtual Machine», но с развитием проекта это значение устарело, и теперь LLVM — это просто бренд, не имеющий прямой расшифровки.
  • LLVM не является виртуальной машиной в классическом смысле (как JVM или .NET CLR), так как не выполняет код напрямую, а генерирует машинный код для целевой платформы.
  • Крис Латтнер, создатель LLVM, покинул Apple в 2017 году и работал над проектом Swift, а затем в Google над языком Mojo.
  • LLVM поддерживает более 50 различных архитектур процессоров, включая экспериментальные (например, для квантовых вычислений).
  • Проект LLVM распространяется под лицензией Apache 2.0 с исключением LLVM, что позволяет использовать его в коммерческих продуктах без обязательного открытия исходного кода.

Критика

Несмотря на широкое распространение, LLVM имеет некоторые недостатки:

  • Сложность архитектуры: из-за модульности и большого количества проходов, настройка оптимизаций может быть нетривиальной.
  • Производительность компиляции: для некоторых языков (например, C++) компиляция через Clang может быть медленнее, чем через GCC, хотя в других случаях она быстрее.
  • Зависимость от сообщества: развитие новых бэкендов и оптимизаций часто зависит от сторонних разработчиков, что может приводить к неравномерной поддержке архитектур.
  • Ограничения в поддержке некоторых языков: например, фронтенд для Fortran (Flang) долгое время был экспериментальным и не достиг зрелости GCC.

Источники

  • LLVM Foundation. «The LLVM Compiler Infrastructure.» Официальная документация проекта.
  • Lattner, C., & Adve, V. (2004). «LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation.» Proceedings of the International Symposium on Code Generation and Optimization.
  • Aho, A. V., Lam, M. S., Sethi, R., & Ullman, J. D. (2006). «Compilers: Principles, Techniques, and Tools.» (2nd ed.). Addison-Wesley.
  • «Clang: a C language family frontend for LLVM.» Официальная документация Clang.
  • «LLDB: The LLVM Debugger.» Официальная документация LLDB.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →