LLVM 17: инфраструктура для разработки компиляторов. Руководство для начинающих по LLVM – системе разработки компиляторов и сопутствующих библиотек на C++
Покупка
Новинка
Тематика:
Программирование на C и C++
Издательство:
ДМК Пресс
Перевод:
Слинкин Алексей Александрович
Год издания: 2024
Кол-во страниц: 370
Дополнительно
Вид издания:
Практическое пособие
Уровень образования:
Дополнительное образование
ISBN: 978-5-93700-303-4
Артикул: 856484.01.99
Перед вами руководство по LLVM 17 — системе разработки компиляторов и сопутствующих библиотек на C++. Вы узнаете, как написать и использовать реальные компиляторы, включая фронтальную часть, конвейер оптимизации и кодогенератор.
Книга ориентирована на разработчиков компиляторов, энтузиастов и инженеров, только начинающих знакомство с LLVM. Также будет полезна программистам на C++, которые хотели бы использовать в своей работе инструменты для анализа улучшения кода.
Тематика:
ББК:
УДК:
ОКСО:
- ВО - Бакалавриат
- 09.03.01: Информатика и вычислительная техника
- 09.03.02: Информационные системы и технологии
ГРНТИ:
Скопировать запись
Фрагмент текстового слоя документа размещен для индексирующих роботов
Кай Наке, Эми Кван LLVM 17: инфраструктура для разработки компиляторов
Learn LLVM 17 A beginner’s guide to learning LLVM compiler tools and core libraries with C++ KAI NACKE AMY KWAN BIRMINGHAM — MUMBAI
Москва, 2024 LLVM 17: инфраструктура для разработки компиляторов Руководство для начинающих по LLVM – системе разработки компиляторов и сопутствующих библиотек на C++ КАЙ НАКЕ ЭМИ КВАН
УДК 004.42LLVM ББК 32.973 П32 Наке К., Кван Э. П32 LLVM 17: инфраструктура для разработки компиляторов / пер. с англ. А. А. Слинкина. – М.: ДМК Пресс, 2024. – 370 с.: ил. ISBN 978-5-93700-303-4 Перед вами руководство по LLVM 17 – системе разработки компиляторов и сопутствующих библиотек на C++. Вы узнаете, как написать и использовать реальные компиляторы, включая фронтальную часть, конвейер оптимизации и кодогенератор. Книга ориентирована на разработчиков компиляторов, энтузиастов и инженеров, только начинающих знакомство с LLVM. Также будет полезна программистам на C++, которые хотели бы использовать в своей работе инструменты для анализа улучшения кода. УДК 004.42LLVM ББК 32.973 First published in the English language under the title ‘Learn LLVM 17 – (9781837631346)’. Все права защищены. Любая часть этой книги не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. ISBN 978-1-83763-134-6 (англ.) Copyright © 2024 Packt Publishing ISBN 978-5-93700-303-4 (рус.) © Перевод, оформление, издание, ДМК Пресс, 2024
Для написания книги нужны время и силы. Без поддержки и понимания моей жены Тани и дочери Полины эта книга не состоялась бы. Спасибо, что вы всегда на моей стороне! Из-за некоторых проблем личного характера этот проект находился под угрозой, и я благодарен Эми, ставшей моим соавтором. Без нее книга получилась бы не такой хорошей. И еще, коллектив издательства Packt не только подсказывал мне, как нужно писать, но и проявлял понимание, когда я работал медленно, и всегда настаивал на продолжении. Я всем им очень признателен. – Кай Наке 2023 год стал поворотным в моей жизни, и привнесение моих знаний о LLVM в эту книгу сыграло в этом не последнюю роль. Я никогда не помышляла о том, чтобы присоединиться к Каю в этом волнующем предприятии с целью разделить LLVM 17 со всеми вами! Спасибо Каю за техническое наставничество и руководство, спасибо коллективу Packt и, конечно, моей семье и близким за поддержку и мотивацию во время работы над этой книгой. – Эми Кван
Содержание От издательства ......................................................................................................12 Об авторах ................................................................................................................13 О рецензентах..........................................................................................................14 Предисловие.............................................................................................................15 Часть I. ОСНОВЫ ПОСТРОЕНИЯ С ПОМОЩЬЮ LLVM..........................19 Глава 1. Установка LLVM........................................................................................20 Компиляция LLVM или установка двоичных файлов?..........................................20 Подготовка среды.......................................................................................................21 Ubuntu.......................................................................................................................22 Fedora и RedHat.......................................................................................................22 FreeBSD.....................................................................................................................22 OS X...........................................................................................................................23 Windows....................................................................................................................23 Клонирование репозитория и сборка из исходного кода.....................................24 Конфигурирование Git...........................................................................................24 Клонирование репозитория..................................................................................25 Создание каталога сборки.....................................................................................25 Генерирование файлов системы сборки.............................................................26 Компиляция и установка LLVM............................................................................27 Настройка процесса сборки.......................................................................................28 Переменные, определенные CMake.....................................................................28 Использование конфигурационных переменных сборки, определенных LLVM...............................................................................................30 Резюме..........................................................................................................................33 Глава 2. Структура компилятора........................................................................34 Структурные элементы компилятора......................................................................34 Язык арифметических выражений..........................................................................35 Формализм для определения синтаксиса языка программирования............36 Как грамматика помогает автору компилятора?..............................................36
Содержание 7 Лексический анализ...................................................................................................37 Рукописный лексический анализатор.................................................................37 Синтаксический анализ.............................................................................................41 Рукописный синтаксический анализатор..........................................................42 Абстрактное синтаксическое дерево...................................................................47 Семантический анализ..............................................................................................50 Генерирование кода с помощью кодогенератора LLVM.......................................52 Текстовое представление LLVM IR.......................................................................52 Генерирование IR-кода на основе AST................................................................54 Недостающие части – драйвер и библиотека времени выполнения..............58 Резюме..........................................................................................................................61 Часть II. ОТ ИСХОДНОГО КОДА К ГЕНЕРИРОВАНИЮ МАШИННОГО КОДА...........................................................................................62 Глава 3. Преобразование исходного файла в абстрактное синтаксическое дерево.........................................................................................63 Определение реального языка программирования..............................................64 Создание структуры проекта....................................................................................66 Управление входными файлами компилятора......................................................67 Работа с сообщениями для пользователя...............................................................68 Структура лексического анализатора......................................................................71 Построение парсера с рекурсивным спуском........................................................75 Выполнение семантического анализа.....................................................................81 Обработка области видимости имен...................................................................81 Использование RTTI в стиле LLVM для AST........................................................84 Создание семантического анализатора..............................................................85 Резюме..........................................................................................................................91 Глава 4. Основы генерирования IR-кода.........................................................92 Генерирование IR-кода по AST.................................................................................92 Разбираемся в IR-коде...........................................................................................93 Подход «загрузи и сохрани»..................................................................................97 Отображение потока управления на простые блоки........................................98 Использование нумерации AST для генерирования IR-кода в форме SSA......100 Определение структуры данных для хранения значений..............................100 Чтение и запись значений, локальных в простом блоке................................101 Поиск значения в блоках-предшественниках..................................................101 Оптимизация сгенерированных команд phi....................................................103 Запечатывание блока...........................................................................................104 Создание IR-кода для выражений......................................................................105 Порождение IR-кода функции............................................................................106 Управление видимостью с помощью стиля компоновки и декорирования имен.........................................................................................106 Преобразование типа из описания в AST в типы LLVM..................................107 Создание IR-кода функции в LLVM....................................................................108
8 Содержание Создание IR-кода тела функции.........................................................................109 Создание модуля и драйвера..................................................................................110 Обертывание всего кодогенератором...............................................................110 Инициализация класса целевой машины.........................................................112 Порождение ассемблерного и объектного кодов.............................................113 Резюме........................................................................................................................116 Глава 5. Генерирование IR-кода для конструкций языка высокого уровня....................................................................................................118 Технические требования..........................................................................................118 Работа с массивами, структурами и указателями................................................119 Работа с двоичным интерфейсом приложений...................................................122 Создание IR-кода для классов и виртуальных функций.....................................124 Реализация одиночного наследования.............................................................124 Расширение одиночного наследования за счет интерфейсов.......................128 Добавление поддержки множественного наследования................................130 Резюме........................................................................................................................132 Глава 6. Генерирование более сложного IR-кода......................................133 Возбуждение и перехват исключений...................................................................133 Возбуждение исключения...................................................................................138 Обработка исключения........................................................................................140 Включение кода обработки исключений в приложение................................143 Генерирование метаданных для анализа псевдонимов на основе типов........144 Зачем нужны дополнительные метаданные....................................................144 Создание TBAA-метаданных в LLVM.................................................................146 Добавление TBAA-метаданных в tinylang........................................................147 Добавление отладочных метаданных....................................................................151 Общая структура отладочных метаданных......................................................151 Прослеживание переменных и их значений....................................................154 Добавление номеров строк.................................................................................157 Добавление поддержки отладки в tinylang.......................................................158 Резюме........................................................................................................................164 Глава 7. Оптимизация IR-кода...........................................................................165 Технические требования..........................................................................................165 Диспетчер проходов LLVM.......................................................................................165 Реализация нового прохода....................................................................................167 Разработка прохода ppprofiler в виде плагина.................................................167 Добавление прохода в дерево исходного кода LLVM......................................171 Использование прохода ppprofiler совместно с инструментами LLVM............174 Добавление конвейера оптимизации к компилятору.........................................181 Создание конвейера оптимизации....................................................................181 Расширение конвейера проходов......................................................................186 Резюме........................................................................................................................189
Содержание 9 Часть III. ПЕРЕХОД НА СЛЕДУЮЩИЙ УРОВЕНЬ LLVM.....................190 Глава 8. Язык TableGen........................................................................................191 Технические требования..........................................................................................191 Знакомство с языком TableGen...............................................................................191 Эксперименты с языком TableGen.........................................................................192 Определение записей и классов.........................................................................193 Создание сразу нескольких записей с помощью мультиклассов..................196 Имитация вызовов функций..............................................................................198 Генерирование C++-кода по файлу на языке TableGen.......................................200 Определение данных на языке TableGen..........................................................201 Реализация кодогенератора TableGen...............................................................203 Недостатки TableGen................................................................................................212 Резюме........................................................................................................................213 Глава 9. JIT-компиляция......................................................................................214 Технические требования..........................................................................................214 Обзор реализации JIT-компиляции в LLVM и ее применений..........................214 Применение JIT-компиляции для непосредственного выполнения................216 Знакомство с программой lli..............................................................................216 Реализация собственного JIT-компилятора с помощью LLJIT.........................................................................218 Интеграция движка LLJIT в калькулятор..........................................................219 Изменения в генерировании кода с целью поддержки JIT-компиляции посредством LLJIT.................................................................................................223 Построение калькулятора, основанного на LLJIT............................................225 Построение JIT-компилятора с чистого листа......................................................228 Создание класса JIT-компилятора.....................................................................229 Использование нового класса JIT-компилятора..............................................236 Резюме........................................................................................................................239 Глава 10. Отладка с применением инструментов LLVM..........................240 Технические требования..........................................................................................240 Оснащение приложения контролерами................................................................241 Обнаружение проблем доступа к памяти с помощью контролера адресов...................................................................................................................241 Нахождение ошибок доступа к неинициализированной памяти с помощью контролера памяти..........................................................................243 Обнаружение гонки за данные с помощью контролера потоков.................244 Нахождение ошибок с помощью libFuzzer............................................................246 Ограничения и альтернативы.............................................................................249 Профилирование с помощью XRay........................................................................249 Проверка исходного кода с помощью статического анализатора clang..........254 Добавление нового проверщика в статический анализатор clang...............256 Создание собственного инструмента на основе clang........................................265 Резюме........................................................................................................................271
10 Содержание Часть IV. СОЗДАНИЕ СОБСТВЕННОГО КОДОГЕНЕРАТОРА...........273 Глава 11. Описание целевой платформы.....................................................274 Подготовка сцены для нового кодогенератора....................................................274 Добавление новой архитектуры в класс Triple.....................................................275 Расширение определения файлового формата ELF в LLVM...............................276 Создание описания целевой платформы..............................................................278 Добавление определения регистров..................................................................278 Определение форматов команд и информации о командах.........................281 Создание верхнеуровневого файла для описания целевой платформы......284 Добавление кодогенератора для M88k в LLVM.....................................................285 Реализация парсера языка ассемблера..................................................................289 Создание дизассемблера..........................................................................................301 Резюме........................................................................................................................303 Глава 12. Выбор команд.....................................................................................304 Определение правил соглашения о вызове..........................................................305 Реализация правил соглашения о вызове.........................................................305 Выбор команд с помощью DAG выбора.................................................................306 Реализация DAG – обработка легальных типов и задание операций...........308 Реализация DAG – трансляция формальных аргументов...............................310 Реализация DAG – трансляция возвращаемых значений...............................312 Реализация преобразований DAG в схеме выбора команд............................314 Добавление информации о регистрах и командах..............................................315 Пустой код трансляции кадра стека.......................................................................319 Вывод машинных команд........................................................................................320 Создание целевой платформы и субплатформы.................................................322 Реализация класса M88kSubtarget......................................................................323 Реализация M88kTargetMachine – определения..............................................325 Реализация M88kTargetMachine – добавление кода........................................326 Глобальный выбор команд......................................................................................329 Трансляция аргументов и возвращаемых значений......................................330 Легализация обобщенных машинных команд................................................332 Выбор банка регистров для операндов.............................................................333 Трансляция обобщенных машинных команд..................................................335 Пример...................................................................................................................336 В какую сторону развивать кодогенератор...........................................................336 Резюме........................................................................................................................337 Глава 13. За пределами выбора команд.......................................................338 Добавление нового прохода по машинным функциям в LLVM.........................338 Реализация верхнеуровневого интерфейса с платформой M88k.................339 Добавление реализации класса TargetMachine для прохода по машинным функциям....................................................................................339 Разработка прохода по машинным функциям................................................340 Сборка с новым проходом по машинным функциям.....................................346