Как стать автором
Обновить
40.06

Компиляторы *

Из исходного кода в машинный

Сначала показывать
Порог рейтинга
Уровень сложности

Что будет, если заинлайнить всё

Время на прочтение25 мин
Количество просмотров12K

Усаживайтесь поудобнее, ребята! Сегодня мы с вами разберём следующий увлекательный вопрос: что будет, если заинлайнить вообще всё?

Если вы пока не знакомы с техникой встраивания (inlining) то примите к сведению, что в сообществе специалистов по разработке компиляторов многие, в том числе очень авторитетные фигуры (например, Чендлер Каррут) считают этот приём наиважнейшим при оптимизации компиляторов. Подробнее о том, как устроено встраивание, рассказано здесь — мы беззастенчиво хвалимся той презентацией, с которой выступили перед участниками конференции LLVM Developers' Meeting по межпроцедурной оптимизации. Я рассказывал о встраивании и очень рекомендую вам посмотреть хотя бы первые 6 минут. В этом видео я рассказываю, почему встраивание — очень простое преобразование, а вот тут вашему вниманию предлагается реализация встраивания, предложенная великим Крисом Латтнером уже около 20 лет назад — в ней всего около 200 строк кода. К сожалению, сегодня даже само преобразование пропорционально выросло: в качестве примера взгляните хотя бы на InlineFunction.cpp.

В вышеупомянутом видео я рассказываю, что у встраивания есть свои недостатки. Иными словами, встраивание позиционируется как супер-пупер инструмент в арсенале компиляторщика, но пользоваться этой штукой следует с осторожностью. И следует ли вообще?

Читать далее

Новости

QapDSL — декларативное описание AST и парсеров для C++

Уровень сложностиСредний
Время на прочтение4 мин
Количество просмотров1.5K



QapDSL — декларативное описание AST и парсеров для C++


QapDSL — это специализированный язык (DSL), который позволяет описывать абстрактные синтаксические деревья (AST) и правила их разбора для языков программирования, прежде всего C++. Такая формализация помогает автоматизировать построение парсеров, генерацию кода, анализ исходников и даже рефакторинг.



Зачем нужен QapDSL?


  • Компактно и наглядно описывать структуру и грамматику языка.
  • Автоматически генерировать C++-структуры, парсеры, сериализаторы и визиторы.
  • Ускорять эксперименты с языками, создавая прототипы компиляторов и анализаторов.
  • Упрощать анализ и рефакторинг сложных языков, в т.ч. C++.


Пример QapDSL-описания


Рассмотрим, как описывается объявление класса C++ на QapDSL:


t_class{
  string keyword;
  t_sep sep0;
  string name;
  t_sep sep1;
  TAutoPtr<t_parents> parents;
  t_sep sep2;
  TAutoPtr<t_class_body> body;
  t_sep sep3;
  {
    M+=go_any_str_from_vec(keyword,split("struct,class,union",","));
    O+=go_auto(sep0);
    M+=go_str<t_name>(name);
    O+=go_auto(sep1);
    O+=go_auto(parents);
    O+=go_auto(sep2);
    O+=go_auto(body);
    O+=go_auto(sep3);
    M+=go_const(";");
  }
}

Читать дальше →

Оптимизируем C++ шаблоны: от инлайнинга до модулей

Уровень сложностиСредний
Время на прочтение18 мин
Количество просмотров3.7K

Мы рассмотрим, чем опасны шаблоны для проекта на C++ и как минимизировать эти риски. В оптимизации нам помогут инлайн-файлы, явные инстанциации и даже модули из C++20.

Читать далее

Возможное расширение языка C++ операцией скалярного произведения

Уровень сложностиПростой
Время на прочтение4 мин
Количество просмотров4.6K

У меня возникла идея, как можно расширить синтаксис C++ операцией скалярного произведения. Если кратко, то произведение двух матриц в новых обозначениях будет выглядеть так:

C[>i][>j] = A[i][>k] * B[>k][j];

Насколько мне известно, сочетания операторов [> и [< вроде бы нигде не используются. Их можно применить для декларации индексов, которые существуют только в пределах данного выражения. Сочетание [> используется для декларации индекса, который пробегает от начала до конца массива в прямом направлении, а сочетание [< для декларации индекса, который пробегает в обратном направлении. Для повторяющихся индексов в произведении подразумевается суммирование - они аналогичны немым индексам в тензорных обозначениях.

Разберём на примерах, как это будет работать.

Читать далее

Может, если бы у C++ было больше времени, он стал бы лучше?

Уровень сложностиСредний
Время на прочтение9 мин
Количество просмотров11K

В своей предыдущей статье [перевод на Хабре] я говорил о множестве недостатков C++, которые, по сути, устранил Rust. Благодаря этому код теперь легко использовать правильно и сложно использовать неверно. Я не говорил о безопасности по памяти, просто привёл пример того, что пользователь функции не может случайно поменять местами аргументы количества и цены.

На написание статьи меня вдохновил доклад Мэтта Годболта о том, как можно сделать интерфейсы C++ более надёжными: Correct by Construction: APIs That Are Easy to Use and Hard to Misuse. Вам стоит его посмотреть!

В той статье я сказал, что Rust гораздо лучше помогает разработчику, возможно, благодаря тому, что у него были десятки лет, чтобы учиться. В конце концов, первая версия C++ была выпущена в начале 80-х, а Rust — в начале 2010-х. Если дать C++ несколько десятков лет для обучения, то, разумеется, появятся новые структуры, которые будут обладать высоким качеством и которые сложно использовать неправильно.

Но так ли это?

Читать далее

Корутины с точки зрения компилятора

Уровень сложностиСложный
Время на прочтение10 мин
Количество просмотров6.8K

Привет! Меня зовут Абакар, я работаю главным техническим лидером разработки в Альфа-Банке.

Сегодня мы поговорим на тему, связанную с корутинами, а именно погрузимся чуть глубже в недра компилятора Kotlin. На данную тему мы с Александром Гиревым готовили доклад на «Мобиус».

В рамках подготовки доклада нам пришлось заглянуть в святая святых для всех «андроидеров», а именно в исходники компилятора Kotlin. Ну что ж, поглядим, что мы там накопали. Поехали!

Читать далее

Выравнивание AST (и других структур данных, используемых при работе с компилятором)

Время на прочтение15 мин
Количество просмотров3.1K

Два варианта абстрактного синтаксического дерева (AST) для выражения a * b + c.

Арены, также называемые регионами, повсюду встречаются в современных языках программирования. Есть такая разновидность арен, которая одновременно супер-проста и удивительно эффективна при работе с компиляторами и тому подобными инструментами. Может быть, именно по причине такой простоты эта элементарная техника не попадалась мне во многих курсах по компиляторам — и вообще в теоретическом минимуме по информатике, если уж на то пошло. В этом посте я познакомлю вас с этой идеей, а также с её многочисленными достоинствами.

Многие по-разному понимают, что такое арены или регионы, поэтому здесь я собираюсь называть интересующую меня разновидность этих структур данных «выровненной», а сам процесс — «выравниванием» (flattening). Выровненная арена содержит всего один тип, то есть, в сущности, это обычный массив. В таком массиве можно обойтись индексами, тогда как обычно для работы с массивом требуются указатели. Здесь мы поговорим прежде всего о выравнивании абстрактных синтаксических деревьев (AST), но вообще описанная идея применима с любой структурой данных, отягощённой указателями.

Чтобы изучить выравнивание, мы дважды напишем простейший интерпретатор: сначала как обычно, а затем с применением выравнивания. Логика поста прослеживается по коду из этого репозитория, где можно сравнить две ветки. Здесь важнее всего отметить, что изменения минимальны, но при этом микробенчмарки показывают, что после выравнивания код работает в 2,4 раза быстрее. Благодаря выравниванию не только повышается производительность, но и сам код становится эргономичнее, на чём я также остановлюсь.

Читать далее

Двоичная Java: CDS, CRaC и AOT для ускорения запуска и прогрева JVM

Уровень сложностиСредний
Время на прочтение19 мин
Количество просмотров3.1K

Это текстовая версия доклада с HighLoad++ 2024, с которым выступал один из наших бывших девелопер-адвокатов @RustamKuramshin Также есть отдельная запись доклада, сделанная силами участников программного комитета HighLoad++.

Читать далее

Ускоряем работу видеодекодера rav1d на 1%

Уровень сложностиСредний
Время на прочтение12 мин
Количество просмотров3K

Какое-то время назад memorysafety.org объявил о конкурсе по повышению производительности rav1d — порта AV1-декодера dav1d на Rust.

Моя фамилия Равид, совсем как название декодера, поэтому я решил, что будет забавно попробовать (хоть я и, вероятно, не смогу участвовать в конкурсе).

Эта статья посвящена двум найденным мной небольшим улучшениям производительности (первый PRвторой PR) и рассказу о том, как я их нашёл.

Читать далее

Создание режима GNU Emacs для C-подобного языка

Уровень сложностиСложный
Время на прочтение6 мин
Количество просмотров1.2K

Недавно я разработал ещё один режим GNU Emacs для C-подобного языка программирования C2. Если в предыдущий раз для другого C-подобного языка я написал код с нуля, то в этот раз решил воспользоваться возможностью так называемого наследования режимов. В этой статье хочу поделиться с вами как это делается, и что у меня из этого вышло. (Предполагается, что читатель ознакомился с материалом предыдущей статьи Как написать свой режим для GNU Emacs и опубликовать его в MELPA или имеет собственный уникальный опыт разработки режимов GNU Emacs.)

Читать далее

О том как я писал компилятор Си

Время на прочтение2 мин
Количество просмотров5.5K

Сегодня вы узнаете мой опыт писания компилятора си на python.

Пробуйте тоже так! (если захотите)

Данная статья в две части.

Читать далее

Rust 1.87.0: 10 лет Rust, анонимные каналы, безопасный вызов встроенных интринсиков

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров2.7K

Rust 1.87.0 и 10 лет Rust!


Команда Rust празднует 10-летие Rust в Утрехте, Нидерланды, и рада сообщить о новой версии языка — 1.87.0!



Сегодняшний день релиза выпал на 10-летний юбилей выхода Rust 1.0!


Спасибо мириадам участников, кто работал или работает над Rust. Выпьем за ещё многие десятилетия впереди! 🎉




Как обычно, новая версия включает в себя все изменения, которые были внесены в бета-версию за последние шесть недель согласно последовательному и регулярному циклу выпуска. Мы следуем ему начиная с Rust 1.0.


Если у вас есть предыдущая версия Rust, установленная через rustup, то для обновления до версии 1.87.0 вам достаточно выполнить команду:

Читать дальше →

Оптимизация производительности кода — это тяжёлый труд

Уровень сложностиСредний
Время на прочтение10 мин
Количество просмотров3.6K

Я не говорю о навыках или о знаниях, равно как и не пытаюсь внушить миру идею о необходимости оптимизации производительности. Наш мир и без этого поставил во главу угла ускорение всего и вся. Оптимизация производительности кода — это тяжёлый труд из-за того, что речь идёт о задаче, природа которой диктует использование при её решении метода грубой силы — полного перебора вариантов — и ничего с этим не поделаешь.

Статья, которую вы читаете — это, отчасти, рассуждения о том, сколько огорчений мне приносит оптимизация кода. Но я, кроме того, попытаюсь дать здесь практические советы, которые, надеюсь скрасят путь тем, кто идёт дорогами оптимизации.

Читать далее

Ближайшие события

Уменьшил синтаксис Си ради 15 байт

Уровень сложностиПростой
Время на прочтение4 мин
Количество просмотров7K

Скучая на очередном уроке биологии я вспомнил о таком прекрасном творении как brainfuck и о его интерпритаторах...

Вернувшись домой я нашел самый маленикий среди интерпритаторов:

Читать далее

Как Мэтт Годболт «продал» мне Rust (рассказав о C++)

Уровень сложностиПростой
Время на прочтение7 мин
Количество просмотров14K

Мэтт Годболт, знаменитый разработчик Compiler Explorer — потрясающий человек, вам стоит найти в вебе и изучить весь созданный им контент. Именно этим и занимался, просматривая Correct by Construction: APIs That Are Easy to Use and Hard to Misuse. Я уже больше двадцати лет работаю с C/C++, поэтому эта тема была мне близка.

Когда я смотрел его доклад, ко мне постоянно приходила мысль: «Да! И именно поэтому в Rust это делается так». После просмотра видео я подумал, что этот доклад — отличный способ понять, как Rust помогает разработчикам не только в безопасности по памяти, и в своей статье я расскажу об этом.

Но прежде нам следует поговорить о поднятых Мэттом проблемах и о том, как он предлагает решать их в C++. Сделайте себе одолжение и посмотрите доклад целиком, а я разберу один из его пунктов.

Читать далее

Golang на PlayStation 2

Уровень сложностиСредний
Время на прочтение17 мин
Количество просмотров5.5K

Мне всегда хотелось творить какую-нибудь дичь с консолями. Не знаю почему, но меня всегда привлекала идея реализовывать на устройствах неожиданные возможности. Это относится и к PlayStation 2, выпущенной Sony в 2000 году.

Sony, пожалуйста, не подавайте в суд на меня за этот пост.

Перейдём сразу к делу: я хочу научиться запускать код на консолях (подробнее о том, зачем это нужно, я расскажу в другом посте). Обычно это делается на языках низкого уровня, но сегодня мы можем проще и удобнее работать с языками наподобие Go. Поэтому я подумал: почему бы и нет?

Поискав онлайн, я не нашёл простого решения, поэтому взялся за эту задачу самостоятельно.

Читать далее

Переходим на C++26: как собрать и настроить GCC 15.1 в Ubuntu

Уровень сложностиСредний
Время на прочтение7 мин
Количество просмотров2.9K

На днях вышел GCC 15.1.0 с поддержкой некоторых фич C++26.

Однако нынешняя версия Ubuntu все еще использует старый GCC 13.

Здесь мы и рассмотрим, как вручную установить GCC 15.1 на Ubuntu и начать использовать новейшие элементы C++26 уже сегодня.

Поехали в будущее =>

Пишем самый примитивный компилятор на Python

Время на прочтение13 мин
Количество просмотров6.9K

Сегодня мы с вами напишем примитивный компилятор на Python. Ну очень примитивный! Но за то будет опыт.

Читать далее

Делаем собственный анализатор C++ кода в виде плагина для Clang

Уровень сложностиСредний
Время на прочтение11 мин
Количество просмотров4.8K


Есть много проектов, целью которых является превратить С++ более "безопасный" язык программирования. Но внесение изменений в синтаксис языка обычно нарушает обратную совместимость со старым кодом, который был написан до этого.


Недавно вышла новая версия библиотеки memsafe для языка С++, которая превращает его в Rust с помощью плагина Clang добавляет в С++ безопасное управление динамической памятью и контроль инвалидации ссылочных типов данных во время компиляции приложения.


Но данная статья не о библиотеке, а об особенностях разработки анализатора программы на С++ в виде плагина для Clang.


Можно считать, что это подведение итогов по результатам сравнения нескольких разных способов создания плагина для компилятора С++, а так же очередной Хабрахак для хранения результатов экспериментов и публикации итоговых выводов, которые я решил сохранить не только для себя, но и в виде статьи на Хабре, что бы результатами моего труда могли воспользоваться и другие хорошие люди :-), которым так же может потребоваться погрузиться в дебри парсинга исходного текста программ.

Читать дальше →

Удивительная оптимизация размера enum в компиляторе Rust

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров6.2K

Enum — одна из самых популярных фич Rust. Тип enum может иметь одно из значений в заданном множестве вариантов.

/// Foo имеет значение или 32-битного integer, или символа.
enum Foo {
Int(u32),
Char(char),
}

Значениями типа Foo могут быть или integer (например, вариант Foo::Int(3) с полезной нагрузкой 3), или символы (например, вариант Foo::Char('A') с полезной нагрузкой 'A'). struct можно считать AND-комбинациями их полей, а enum — OR-комбинациями их вариантов.

Этот пост посвящён удивительной оптимизации, выполняемой компилятором Rust с представлением в памяти значений enum, чтобы они занимали меньше места в памяти (спойлер: это не нишевая оптимизация). В общем случае, уменьшение размера значений может привести к ускорению программ, потому что значения передаются в регистрах CPU и в одну линию кэша CPU умещается больше значений.

Читать далее
1
23 ...