Дневник разработчика
25 subscribers
1 file
3 links
Здесь собраны рабочие инженерные практики, интересные беседы об информатике, коде, а также советы по изучению языка Rust.
加入频道
Как компилируется Rust

Компилятор Rust, известный как rustc, проходит через несколько стадий, чтобы преобразовать исходный код на языке Rust в исполняемый файл.

1. Парсинг и проверка синтаксиса

Исходный код, который вы пишете, это последовательность символов. Задача лексического анализатора — преобразовать эту последовательность в токены. Токены — это основные единицы, такие как ключевые слова, идентификаторы, литералы и знаки препинания.

Как только код токенизирован, начинает работу синтаксический анализатор. Он использует токены для создания абстрактного синтаксического дерева (abstract syntax tree). AST — это древовидное представление исходного кода, где каждый узел соответствует конструкции в коде.

Например, рассмотрим код на Rust:
fn main() {
let x = 5;
}


AST может представлять fn, main, (), {, let, x, =, 5 и } как отдельные узлы, формируя дерево, которое отражает их иерархические отношения.

2. Семантический анализ

На этапе семантического анализа работа ведется уже с AST. Этот шаг включает:

Разрешение (Resolving): Компилятор определяет, что означает каждое имя (например, переменная или функция).

Проверка типов (Type checking): Rust обеспечивает безопасность типов, поэтому компилятор проверяет, чтобы, например, вы не пытались добавить строку к целому числу.

Проверка заимствований (Borrow checking):
Одной из уникальных особенностей Rust является его проверка заимствования. Это гарантирует соблюдение правил владения и заимствования для ссылок на данные.

3. Высокоуровневое промежуточное представление (High-Level Intermediate Representation)

Затем компилятор преобразует AST в высокоуровневое промежуточное представление (HIR). HIR упрощает AST, упрощая компилятору выполнение конкретных преобразований и оптимизаций. Оно более абстрактно, чем исходный код, но все же тесно с ним связано.

4. Промежуточное представление среднего уровня (Mid-Level Intermediate Representation)

Затем HIR преобразуется в промежуточное представление среднего уровня (MIR). MIR — это более простое, более абстрактное представление вашего кода на Rust. На этом этапе многие продвинутые функции Rust были преобразованы в набор более простых конструкций.

MIR позволяет проводить продвинутые анализы и преобразования потока данных. Именно здесь работает проверка заимствований, которая гарантирует, что ссылки следуют строгим правилам заимствования и владения Rust.

5. Бекенд компиляция (LLVM)

После MIR, предпоследним этапом вступает backend компиляция. Backend отвечает за преобразование MIR в исполняемый код. Это включает:

Преобразование в промежуточное представление LLVM (LLVM IR): Rust использует инфраструктуру компилятора LLVM (возможны и другие бекенды, например rustc-codegen-ssa или rustc-codegen-cranelift). MIR преобразуется в промежуточное представление LLVM (LLVM IR). LLVM IR — это независимое от платформы представление на низком уровне.

Оптимизация: Как только код преобразован в LLVM IR, запускается серия проходов оптимизации для повышения эффективности кода.

Генерация байт кода:
Наконец, оптимизированный LLVM IR переводится в машинный код для целевой платформы.

6. Связывание

Как и большинство языков, Rust позволяет разбивать код на несколько файлов и даже связываться с предварительно скомпилированными библиотеками. Последняя стадия компиляции включает в себя связывание всех этих частей вместе, чтобы создать единый исполняемый файл или библиотеку.
1