Як влаштований компілятор: від вихідного коду до головного файлу
А ви знаєте, як працює компілятор? Зробимо детальний розбір пристрою компілятора: як вихідний код проходить через стадії аналізу, трансформації та генерації, перетворюючись на готовий файл.
Компілятор — це програма, яка перетворює вихідний код, написаний мовою програмування високого рівня (наприклад, C, C++, Rust), у низькорівневий код — машинний код або байт-код, придатний для виконання на комп’ютері. Мета компіляції — зробити код зрозумілим для процесора, оптимізувати його виконання та усунути синтаксичні помилки до запуску.
Загальні етапи роботи компілятора
Робота компілятора ділиться на кілька ключових фаз. Кожна з них вирішує окрему задачу на шляху до формування виконуваного файлу. Ці фази наступні:
1. Лексичний аналіз (Lexical Analysis)
На цьому етапі вихідний текст розбивається на токени — мінімальні смислові одиниці мови: ключові слова, ідентифікатори, оператори, літерали та інше. Спеціальний компонент, який називається лексером, відповідає за зчитування тексту та видалення зайвих пробілів, коментарів і символів переносу рядка.
// Приклад токенізації
int count = 10;
// Токени: [int] [count] [=] [10] [;]2. Синтаксичний аналіз (Syntax Analysis)
Тепер токени збираються в структуру, яка називається деревом розбору (parse tree або syntax tree). Це робить парсер — компонент, який перевіряє граматику мови та правильність побудови виразів. Якщо вираз порушує правила, компілятор викидає помилку.
Курс з вивчення C#
Можете пройти наш безкоштовний курс з вивчення C#
3. Семантичний аналіз (Semantic Analysis)
На цьому етапі компілятор перевіряє, чи має написаний код сенс. Наприклад, чи правильно використовуються типи даних, чи всі змінні визначені, чи немає конфліктів імен. Тут формується абстрактне синтаксичне дерево (AST), з яким далі працює компілятор.
4. Генерація проміжного коду (Intermediate Code Generation)
Після аналізу компілятор перетворює AST у проміжне представлення, незалежне від платформи. Це може бути трьохадресний код, SSA (Static Single Assignment) або байт-код. Цей код дозволяє проводити оптимізацію та слугує мостом до конкретної архітектури процесора.
// Приклад проміжного коду LLVM
%1 = add i32 %a, %b5. Оптимізація коду (Code Optimization)
На цьому етапі компілятор покращує продуктивність і зменшує обсяг коду. Видаляються мертві ділянки (код, який ніколи не виконується), об'єднуються повторювані вирази, прибираються зайві змінні. Існує багато технік оптимізації — від локальних до глобальних.
6. Генерація машинного коду (Code Generation)
На цій фазі проміжний код перетворюється у конкретні машинні інструкції для архітектури CPU (наприклад, x86, ARM). Це інструкції, які безпосередньо виконує процесор. Компілятор враховує регістри, адресацію та особливості обладнання.
7. Компонування (Linking)
Фінальний етап — об’єднання всіх об’єктів і зовнішніх залежностей (наприклад, стандартної бібліотеки) в один виконуваний файл. Лінковщик (linker) збирає окремі одиниці в зв’язаний код, усуває зовнішні посилання та формує готову до запуску програму.

Різновиди компіляторів
Існує кілька видів компіляторів, кожен з яких вирішує свої завдання:
- Традиційні компілятори — перетворюють код напряму у виконуваний файл (GCC, Clang).
- Компілятори в байт-код — перетворюють код у проміжний байт-код для віртуальної машини (Java, C#).
- JIT-компілятори — компілюють код під час виконання (використовуються в JVM, .NET, V8).
- Крос-компілятори — створюють виконувані файли для іншої платформи (наприклад, для ARM під Windows).
Компілятор vs інтерпретатор
Важливо розуміти різницю між компілятором та інтерпретатором. Компілятор перетворює весь код одразу у виконуваний файл, тоді як інтерпретатор виконує код построково. Інтерпретатори частіше використовуються в мовах, орієнтованих на скриптове або інтерактивне виконання (, Ruby). Компілятори — в мовах, де важлива продуктивність і контроль (, Rust).
Курс з вивчення Java
Можете пройти наш безкоштовний курс з вивчення Java
Популярні компілятори та інструменти
Нижче наведено деякі з найбільш часто використовуваних компіляторів і компіляційних інструментів:
- GCC — GNU Compiler Collection, компілює C, C++, Objective-C та ін.
- Clang — сучасний фронтенд до компілятора LLVM, популярний в екосистемі Apple та open-source.
- Rustc — компілятор мови Rust, який використовує LLVM для генерації машинного коду.
- javac — компілятор мови Java, генерує байт-код для JVM.
- tsc — компілятор TypeScript, перетворює у JavaScript.
Більше цікавих новин
Лучшие библиотеки React: ТОП-7
5 лучших JavaScript фреймворков и библиотек
7 найкращих книг з геймдизайну 2024 року
Самый мощный ПК в мире против коронавируса