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

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

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

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

Компилятор за выходные: таблицы символов

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

Как водится воскресным вечером, снова я с моим компилятором. На этот раз я расскажу, как работают области видимости переменных и как перегружать функции. Это позволит нам скомпилировать демку про́клятого огня, а также я накидал фантазию на тему игрушки арканоид (скриншот на КПДВ, видео в конце статьи). Я на удивление сам долго залипал на эту анимацию :)

На всякий случай я даю код и на wend, и на C, поскольку понимаю, что код на моём языке вряд ли интересен кому-то помимо того, кто реально возьмётся за компилятор. А вот мелкий код с интересными эффектами всегда найдёт свою публику. Кстати, если у вас есть идеи на тему чего-то интересного, что можно запрограммировать в полста строчек кода, делитесь в комментариях, я внимательно слушаю!

Читать далее
Всего голосов 26: ↑26 и ↓0+26
Комментарии2

Делаем двоичные файлы Rust меньше по умолчанию

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

Вы когда-нибудь пробовали компилировать program helloworld на Rust в режиме --release? Если да, то видели, какой размер двоичного файла получается? Достаточно сказать, что он не очень маленький. Или, по крайней мере, не был таким до недавнего времени. В этом посте я расскажу, как узнал об этой проблеме и попытался устранить её в Cargo.

Читать далее
Всего голосов 38: ↑38 и ↓0+38
Комментарии13

Сравнение производительности dict() и {} в Python

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

Какое-то время назад, во время разбора кода, мы обсудили выбор dict() вместо {} в новом коде на Python. Коллега утверждал, что dict() более читаем и чётче выражает цель, поэтому следует предпочесть его. Меня это не убедило, но в тот момент контраргуентов не нашлось, поэтому я воздержался.

Это заставило меня задуматься: в чём разница между типом dict и литеральным выражением {}?

Давайте изучим этот вопрос.

Читать далее
Всего голосов 26: ↑23 и ↓3+20
Комментарии19

Umka обрастает мясом: улучшения в языке, менеджер пакетов, применение в играх

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

Только что вышла новая версия 1.3 моего встраиваемого скриптового языка Umka со статической типизацией. С момента выпуска версии 1.0 язык пополнился замыканиями, инструкцией выбора switch по фактическому типу интерфейса, тернарным условным оператором, более удобным API для взаимодействия с кодом на C, другими мелкими радостями.

Маленькое, но упрямое сообщество пользователей Umka всерьёз озаботилось библиотеками, появился менеджер пакетов UmBox, загружающий и устанавливающий библиотеки и отслеживающий их зависимости.

Umka живёт в ядре фреймворка Tophat для создания 2D игр. На основе этого фреймворка развивается платформер-головоломка SaveScum. Коллекция пробных уровней для игры была выпущена в декабре в виде адвент-календаря, принеся с собой дух простого геймерского счастья в наш проект.

Читать далее
Всего голосов 9: ↑9 и ↓0+9
Комментарии3

Истории

Компилятор за выходные: лексер и парсер

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

Продолжаем разговор. На прошлой неделе я пообещал за выходные написать компилятор из простенького мной придуманного языка в ассемблер. В назначенное время уложился, и компилятор даже вроде работает, см. заглавную картинку. Теперь дело за малым, потихоньку причесать и стройно изложить. В прошлый раз я рассказал про синтаксические деревья и показал простейший транслятор в питон (по факту, обычный pretty print дерева). Но если в предыдущей статье я синтаксическое дерево строил вручную, то сегодня всё же будем автоматизировать процесс.

Сегодня я публикую две статьи разом, поскольку по дороге меня довольно круто занесло, и получился небольшой спин-офф. Очень рекомендую к прочтению :)

Ну а тема этой статьи - автоматическое построение синтаксического дерева aka лексер и парсер.

Читать далее
Всего голосов 39: ↑39 и ↓0+39
Комментарии44

Про́клятый огонь, или магия препроцессора C

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

Задавались ли вы когда-нибудь вопросом, можно ли полноценно программировать при помощи директивы #define в языке C? Полнота по Тьюрингу шаблонов C++ известна весьма широко, например, люди пишут трассировщики лучей, делающие все вычисления во время компиляции (вместо времени исполнения). А как обстоят дела с препроцессором C? Вопрос оказался сильно нетривиальнее, и эта история является, на мой вкус, отличным анекдотом для курса лекций по теории компиляторов, что я готовлю в данный момент. В частности, для лучшего понимания происходящего здесь, рекомендую ознакомиться со второй статьёй, которую я опубликовал параллельно этой: лексер и парсер.

Чтобы не было обманутых впечатлений, предупрежу сразу, что рейтрейсера не будет, но про́клятый код будет очень даже! Итак, поехали. Для начала, почему я вообще задался этим вопросом? Если обычный код компьютерной графики вам скучен, следующий раздел можно пропустить, перематывайте до последней картинки.

Читать далее
Всего голосов 169: ↑169 и ↓0+169
Комментарии54

К вопросу о gcc в разрезе RISCV

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

Разбирался тут на досуге с (относительно) новыми МК фирмы WCH с ядром RISCV (CH32V307FBP6) с целью осветить данный прибор, скачал рекомендованную среду разработки (mounriver) и на первом же примере наткнулся на совершенно неожиданную вещь. Пример совершенно классический (нет, не мигание светодиодом и даже не приветствие миру) и посвящен использованию функции printf, вот он:

USART_Printf_Init(115200);
printf("SystemClk:%d\r\n"),SystemCoreClоck);
printf("This is printf example\r\n");

Пнп: Вы (программисты сайта) думайте, что хотите, но я считаю, что редактор у Вас ("вот это слово еще ...") омерзительный.

И что же могло удивить ?
Всего голосов 10: ↑6 и ↓4+2
Комментарии11

Кратко про то, как устроен компилятор Go

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

Привет, Хабр!

В back in 2007 трое гуру из Google — Роб Пайк, Кен Томпсон и Роберт Гриземер — решили, что мир нуждается в чем-то свежем и быстром. Они метили на упрощение процесса разработки, но при этом хотели сохранить весь перфоманс на уровне C. И вот, в 2009 году появился Golang.

Первые версии были далеки от совершенства, но с каждым релизом Go становился только круче. Garbage collector, goroutines, channels — эти фичи сделали Go особенным. С каждым апдейтом Go становился только быстрее и надежнее. И не забудем про экосистему — с каждым годом она росла как на дрожжах, предлагая всё новые инструменты и библиотеки.

С версии 1.5 компилятор Go сам начал компилироваться в Go. С тех пор производительность только растет. JIT, улучшения в escape analysis, введение модулей в версии 1.11 — каждая фича делала Go всё более мощным.

В последниях версиях появились дженерики, которые все так долго ждали. Это был следующий шаг в удобстве написания кода в go.

Читать далее
Всего голосов 24: ↑16 и ↓8+8
Комментарии8

Компилятор за выходные: синтаксические деревья

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

Вам когда-нибудь приходилось задаваться вопросом, как работает компилятор, но так руки и не дошли разобраться? Тогда этот текст для вас. Мне тоже не доводилось заглядывать под капот, но тут так случилось, что мне нужно прочитать курс лекций о компиляторах местным третьекурсникам. Кто встречался с некомпетентными преподавателями? Здравствуйте, это я :)

Итак, чтобы самому разобраться в теме, я собираюсь написать транслятор с эзотерического языка программирования wend (сокращение от week-end), который я только что сам придумал, в обычный ассемблер. Задача уложиться в несколько сотен строк питоновского кода. Основной репозиторий живёт на гитхабе (не забудьте заглянуть в мой профиль и посмотреть другие tiny* репозитории).

Читать далее
Всего голосов 75: ↑75 и ↓0+75
Комментарии28

Собираем автономную игру на C# в 2 килобайтах

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

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

В наши дни дисковое пространство стало настолько дешёвым, что люди отказались от оптимизации по размеру.

Размер важен только при передаче: если вы передаёте программу по проводам, мегабайты равны секундам. По быстрому соединению на 100 Мбит в лучшем случае можно передать 12 МБ в секунду. Если на другом конце провода находится человек, ожидающий завершения скачивания, то разница между пятью и одной секундой может существенно повлиять на его ощущения.

Человек может зависеть от времени передачи как напрямую (пользователь, скачивающий программу по сети), так и косвенно (serverless-сервис, отвечающий на веб-запрос).

Люди обычно воспринимают всё, что длится меньше 0,1 секунды, как мгновенное, 3 секунды — это примерно тот предел, после которого прерывается состояние потока пользователя; а уж 10 секунд удержать внимание пользователя очень сложно.

Хотя уменьшение сегодня уже необязательно, оно всё равно лучше.

Эта статья задумывалась как эксперимент, позволяющий выяснить, каким может быть минимальный размер полезного автономного исполняемого файла C#. Могут ли приложения на C# достичь размеров, при которых пользователи будут ощущать их скачивание как мгновенное? Позволит ли это использовать C# там, где он не используется сейчас?
Читать дальше →
Всего голосов 128: ↑127 и ↓1+126
Комментарии34

Поговорим об оптимизирующих компиляторах. Сказ восьмой: размотка циклов

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

Есть оптимизации, польза от которых очевидна всегда или почти всегда. Например, не делать лишнюю проверку лучше, чем делать. Не считать два раза одно и то же обычно лучше, чем считать (если только мы не упёрлись в нехватку регистров или имеем другие подобные проблемы на нижнем уровне). Вычислять выражения вне цикла выгоднее, чем в цикле. И так далее.

Но есть оптимизации, применение которых имеет как плюсы, так и минусы. Выиграв в одном месте, мы можем получить отрицательные эффекты в другом. Например, сэкономив на количестве проверок, мы можем раздуть общий объём кода и поломать микрооптимизации. Каноничным примером такой оптимизации, решение вопроса об использовании которой больше похоже на искусство, чем на науку, является размотка циклов (Loop Unrolling), о которой мы сегодня поговорим. В статье я попробую осветить как можно больше (хотя, наверное, и не все) соображения о том, почему эту оптимизацию может быть нужно или не нужно применять.

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

Читать далее
Всего голосов 55: ↑55 и ↓0+55
Комментарии6

11lc — инновационный компилятор для нового языка программирования

Время на прочтение23 мин
Количество просмотров17K
Данная статья посвящена находящемуся на стадии проектирования компилятору 11lc. В ней перечисляются наиболее яркие особенности этого компилятора.

Отсутствие скрытой неэффективности


Это свойство скорее языка программирования 11l, нежели компилятора. Однако оно настолько важно и настолько отличает язык 11l от C++, D или даже Nim, что я решил разобрать его подробно в данной статье.

Уолтер Брайт, создатель языка D, писал:
Templates in C++ have evolved from little more than token substitution into a programming language in itself. Many useful aspects of C++ templates have been discovered rather than designed.

Так вот, как я считаю, нечто похожее произошло и с семантикой перемещения (move semantics). И в C++ и в D она появилась достаточно поздно, и если бы эти языки проектировались с опорой на семантику перемещения изначально, то в них было бы гораздо меньше скрытой неэффективности (hidden inefficiency). О чём идёт речь? Рассмотрю это на примере C++.
Читать дальше →
Всего голосов 39: ↑36 и ↓3+33
Комментарии57

Rust 1.75.0: API адресной арифметики, async fn и impl Trait в трейтах, уcкорение rustc

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

Команда Rust рада сообщить о новой версии языка — 1.75.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.


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


rustup update stable

Если у вас ещё не установлен rustup, вы можете установить его с соответствующей страницы нашего веб-сайта, а также посмотреть подробные примечания к выпуску на GitHub.


Если вы хотите помочь нам протестировать будущие выпуски, вы можете использовать канал beta (rustup default beta) или nightly (rustup default nightly). Пожалуйста, сообщайте обо всех встреченных вами ошибках.

Читать дальше →
Всего голосов 19: ↑18 и ↓1+17
Комментарии1

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

Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн
Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург

4 миллиарда операторов if

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

Просматривая недавно соцсети, я наткнулся на этот скриншот. Разумеется, его сопровождало множество злобных комментариев, критикующих попытку этого новичка в программировании решить классическую задачу computer science: операцию деления с остатком.

В современном мире, где ИИ постепенно заменяет программистов, отнимая у них работу и совершая переворот в том, как мы подходим к рассуждениям о коде, нам, возможно, следует быть более открытыми к мыслям людей, недавно пришедших в нашу отрасль? На самом деле, показанный выше код — идеальный пример компромисса между временем и задействованной памятью. Мы жертвуем временем и в то же время памятью и временем компьютера! Поистине чудесный алгоритм!

Поэтому я решил изучить эту идею проверки чётности числа при помощи одних сравнений, чтобы понять, насколько хорошо она работает в реальных ситуациях. Я сторонник высокопроизводительного кода, поэтому решил реализовать это на языке программирования C, потому что он и сегодня остаётся самым быстрым языком в мире с большим отрывом от других (благодаря гению Денниса Ричи).

Читать далее
Всего голосов 376: ↑359 и ↓17+342
Комментарии153

Разработка тензорного компилятора под RISC-V CPU с помощью OpenVINO и MLIR

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

Привет, Хабр! Меня зовут Владислав Виноградов, я инженер группы исследований и разработки ПО глубокого обучения в YADRO. Моя команда создает и оптимизирует связанное с искусственным интеллектом программное обеспечение. Сегодня я расскажу, как можно разработать тензорный компилятор для процессора на базе открытой архитектуры RISC-V. 

Подход сочетает в себе автоматическую кодогенерацию и использование ручных оптимизаций. Это позволяет существенно экономить ресурсы команды для работы над наиболее вычислительно трудоемкими операциями, которые реализуются средствами внешних библиотек. Статья будет полезна, если вы ищете инструменты реализации оптимизирующих компиляторов для эффективного исполнения моделей глубокого обучения или вам интересно посмотреть на пример использования MLIR.

Читать далее
Всего голосов 18: ↑17 и ↓1+16
Комментарии6

std fs в Rust медленнее, чем Python? Нет, это аппаратный баг

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

В этой статье я поделюсь с вами долгой историей, которая начинается с op.read() opendal, а заканчивается неожиданным поворотом. Это путешествие оказалось для меня достаточно поучительным, надеюсь, и для вас оно будет таким же. Я постараюсь максимально точно воссоздать свой опыт и дополню его выводами, которые сделал в процессе.

Читать далее
Всего голосов 75: ↑75 и ↓0+75
Комментарии9

Об изучении компиляторов и создании языков программирования

Уровень сложностиСредний
Время на прочтение7 мин
Количество просмотров7.4K
Когда я только начинал изучать компиляторы, я не понимал одного важного момента: Разработка языка программирования и написание компилятора — это два почти совершенно разных навыка. Конечно, между ними есть некоторое пересечение, но меньшее, чем может показаться на первый взгляд!

Я думаю, что это важно знать, потому что обе эти задачи очень сложны! Легче овладеть этими навыками, если решать их по очереди. Ваше первое решение сложной задачи, скорее всего, будет… ну, не таким хорошим, как десятое! Однако довольно часто разработчики создают игрушечный язык, когда пишут свой первый компилятор, а это значит, что они совершают ошибки и учатся сразу на двух сложных проблемах. Хуже того, эти две проблемы взаимосвязаны: Ошибка в одной из них усложняет жизнь в другой. Кроме того, как мы увидим, хотя компиляторы и сложны на первых порах, они, по сути, являются решенной проблемой, в то время как разработка языка программирования — это, скажем так, область продолжающихся исследований.
Читать дальше →
Всего голосов 18: ↑18 и ↓0+18
Комментарии5

Развитие RISC-V & мультиклеточная архитектура

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

Рост популярности RISC-V с момента его появления в 2010 году позволяет говорить, что архитектура состоялась.

Пока успех архитектуры RISC-V — это, в первую очередь, ее открытость. Все остальные факторы вторичны. Минимализм системы команд, ее стандартизация, программная инфрастуктура — все это очень важно. Но, если бы за все это платили, как платят создателям ARM, то RISC-V, скорее всего, не было бы. Говорить о действительном успехе этой архитектуры можно будет только тогда, когда она создаст реальную конкуренцию ARM и х86 на высокомаржинальных рынках мобильных телефонов, планшетов, ПК, встроенных систем, суперкомпьютеров и искусственного интеллекта.

Мультиклеточная архитектура может быть использована не только на архитектурном уровне процессора доступном компилятору и программисту, но и на микроархитектурном уровне.

Так, если уровень системы команд RISC-V рассматривать как
архитектурный, доступный компилятору и программисту, то реализация этого уровня
внутри процессора на мультиклеточных принципах будет микроархитектурным
уровнем, недоступным программисту, но именно этот уровень отвечает за
характеристики процессора.

Читать далее
Всего голосов 13: ↑12 и ↓1+11
Комментарии27

Rust 1.74.0: конфигурация проверки в Cargo, авторизация для приватных реестров, проекции возвращаемых типов

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

Команда Rust рада сообщить о новой версии языка — 1.74.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.


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


rustup update stable

Если у вас ещё не установлен rustup, вы можете установить его с соответствующей страницы нашего веб-сайта, а также посмотреть подробные примечания к выпуску на GitHub.


Если вы хотите помочь нам протестировать будущие выпуски, вы можете использовать beta (rustup default beta) или nightly (rustup default nightly) канал. Пожалуйста, сообщайте обо всех встреченных вами ошибках.

Читать дальше →
Всего голосов 18: ↑16 и ↓2+14
Комментарии4

Поговорим об оптимизирующих компиляторах. Сказ седьмой: борьба с проверками диапазонов

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

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

Читать далее
Всего голосов 33: ↑33 и ↓0+33
Комментарии14

Вклад авторов