Обновить
48.94

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

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

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

Ahead-of-Time компиляция и Blazor

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

В .NET 6 запланирована поддержка AOT компиляции для Blazor WebAssembly приложений. Давайте попробуем запустить в Preview 2 версии.

Анонса и инструкций пока что нету. Поэтому и решено написать этот пост.

Читать далее

Планирование редакции Rust 2021

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

Рабочая группа Rust 2021 Edition рада сообщить, что следующая редакция Rust — Rust 2021 — запланирована на этот год. Пока что формально описывающий её RFC остаётся открытым, но мы ожидаем, что в скором времени он будет принят. Планирование и подготовка уже начались, и мы идём по графику!


Если вам интересно, какие новшества появятся в Rust 2021 или когда эта редакция выйдет в стабильной версии, — читайте нашу статью!


Что входит в эту редакцию?


Конечный список нововведений, которые войдут в Rust 2021, ещё не определён до конца. В целом мы планируем, что выпуск Rust 2021 будет намного меньше, чем Rust 2018, по следующим причинам:


  • Ритм выпусков стал регулярным Это значит, что мы будем активно использовать плюсы "цепочечной" модели на уровне редакций Rust.
  • Редакция Rust 2018 выбилась из модели "минимального стресса" выпусков.
  • Сейчас просто нужно меньше фундаментальных изменений, чтобы язык продолжал развиваться.

Более подробно о развитии концепции редакций вы можете почитать в RFC.


Решение, войдёт ли та или иная функциональность в Rust 2021, является частью процесса RFC — поэтому список ожидаемых функций может и будет меняться. Это будет происходить до самого момента выпуска, но тем не менее, уже сейчас мы можем рассмотреть список функций, которые, скорее всего, в неё войдут.

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

Кросс-компилятор для Raspberry Pi4

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

Хочу рассказать, как я собрал себе кросс-компилятор для Raspberry Pi4 с помощью crosstool-ng. Возможно кому-то тема покажется слишком примитивной и скучной. Я и сам поначалу думал, что быстро смогу собрать кросс-компилятор, но пришлось повозиться и изучать вопрос, некоторые нюансы были для меня неожиданны. Дальше расскажу что и как я делал.
Читать дальше →

Как скомпилировать Python

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

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

Я хочу рассказать об удивительном событии, о котором я узнал пару месяцев назад. Оказывается, одна популярная python-утилита уже более года распространяется в виде бинарных файлов, которые компилируются прямо из python. И речь не про банальную упаковку каким-нибудь PyInstaller-ом, а про честную Ahead-of-time компиляцию целого python-пакета. Если вы удивлены так же как и я, добро пожаловать под кат.

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

Rust 1.50.0: улучшение индексации массивов, безопасность полей объединений и усовершенствование файловых дескрипторов

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

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


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


rustup update stable

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


Что вошло в стабильную версию 1.50.0


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

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

Threadripper 3990X: компилируем 1 миллиард строк C++ на 64 ядрах

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


RAD Studio состоит из Delphi и C++Builder. Компилятор Object Pascal в Delphi является однопроходным компилятором, и сам компилятор не является параллельным, однако при компиляции нескольких проектов параллельно он оказался способен скомпилировать 1 миллиард строк кода Object Pascal за 5 минут на машине с 16-ядерным AMD Ryzen 9 5950x. Я хотел выяснить, возможно ли сделать что-то подобное для C++. Этот пост является частью серии статей, в которой мы исследуем значительный прирост производительности, которого можно достичь на самых быстрых на начало 2021 года процессорах. Сколько это — 1 миллиард строк кода? Взгляните сюда.

Cheney on the M.T.A.: компилятор, в котором стек служит заодно и кучей

Время на прочтение8 мин
Количество просмотров4.7K
 
Did he ever return? No, he never returned,
And his fate is still unlearned,
He may ride forever ‘neath the streets of Boston,
He’s the man who never returned.

“Charlie on the M.T.A.”, 1949

1. Замыкания


Одна из удобных возможностей современных языков программирования – вложенные функции:

def bubble(arr, comp):

    def swap(i, j):
        temp = arr[i]
        arr[i] = arr[j]
        arr[j] = temp

    flag = True
    while flag:
        flag = False
        for i in range(len(arr) - 1):
            if comp(arr[i], arr[i+1]) > 0:
                swap(i, i+1)
                flag = True

Сама эта возможность не нова: она была уже в Алголе (1958) и многим знакома из Паскаля (1970). В компиляции вложенных функций нет ничего сложного: например, в стековом кадре внутренней функции может храниться указатель на стековый кадр внешней функции, чтобы внутренняя функция могла обращаться к параметрам и локальным переменным внешней. Кто-то может вспомнить, что инструкции enter и leave, появившиеся в 80186 (1982), реализуют именно такую поддержку вложенных функций (хотя я не встречал ни один компилятор, который бы её задействовал).

Сложности начинаются, если язык позволяет передать внутреннюю функцию наружу внешней:

def by_field(name):

    def comp(x, y):
        return x[name] – y[name]

    return comp

bubble(my_records, by_field("year"))

Как внутренняя функция сможет обращаться к параметрам и локальным переменным внешней после того, как возврат из внешней функции уничтожил её стековый кадр? Каким-то образом внутренняя функция должна «захватить» используемые переменные вместе с собой; функция вместе с захваченными извне переменными называется «замыканием». Паскаль такое уже не поддерживает;
Читать дальше →

Клонированные переменные

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

Как-то попалось интересное (для меня), хотя и довольно давнее обсуждение языков программирования, где упоминался и язык PL/1. В конце концов, как всегда и бывает на таких форумах, все стороны остались при своем мнении, и тогда один из участников предложил написать на разных языках и затем сравнить простой тест, один из тех, которые часто дают студентам «для закрепления пройденного»:

 Стандартный входной поток содержит произвольное (и заранее не известное) количество целых чисел. Нужно все их прочитать, а затем вывести нечетные числа в стандартный выходной поток в порядке, обратном исходному. Чтобы "не заслонять лес деревьями", будем считать, что доступная память бесконечна. Критерии сравнения предлагаю следующие (в порядке убывания их приоритета):

Читать далее

Погружаемся в логово ржавчины. Как работает компилятор rust

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

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

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

Ну, Fe2+mH2O + 2OH- = mH2O + Fe(OH)2↓

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

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

Как-то в одном ЖЖ возникло обсуждение работы транслятора IBM для Windows с языка PL/1. Для алгоритмически довольно простого решения стационарного уравнения теплопроводности методом Либмана ответ вообще не удавалось получить, поскольку быстро возникало исключение типа «исчезновение порядка» («антипереполнение»). Мне предложили попробовать решить задачу своим транслятором, изначально разработанным для x86.

Поясню саму эту несложную задачу: матрица T (в примере 5000х5000) значений float первоначально заполняется вся нулями и единицами «по краям» - верхняя строка и левый столбец. Затем начинается длительный итерационный процесс изменения этой матрицы (N=5000)

Читать далее

Экстракоды при синтезе программ

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

Впервые термин «экстракод» я услышал еще применительно к командам БЭСМ-6. Сейчас это слово практически не используется, наиболее близкое понятие - «системный вызов». Из-за особенностей системы команд БЭСМ-6, те экстракоды действительно больше напоминали дополнительные встроенные инструкции, чем, например, вызов функции в MS-DOS с помощью INT 21H.

Смысл термина «экстракод» вполне прозрачен: это расширение системы команд для того, чтобы создать из реальной машины виртуальную машину для заданного языка, например, Паскаль-машину или Лисп-машину. А транслятор после этапа анализа исходного текста программы должен провести синтез программы – т.е. перевести результаты анализа в команды этой виртуальной машины.

Кстати, Лисп-машину когда-то действительно собирались воплотить в аппаратуре. Однако создание таких машин для конкретных языков было бы экономически слишком невыгодно по сравнению с универсальными и поэтому мы используем исключительно универсальные (с точки зрения языков) компьютеры. Правда, по мере развития и удешевления технологий разработки и производства процессоров, экономические преимущества универсальных систем команд над специальными могут стать не столь очевидными.

Читать далее

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

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

Конец восьмидесятых. Всего два года я отсутствовал на родном предприятии, а меня встретил уже меняющийся компьютерный мир. В отделах стали появляться персоналки: у кого IBM-PC/XT, у кого «Правец», а у кого ЕС-1840. Число пользователей БЭСМ-6 и даже ЕС и СМ-4 стало асимптотически приближаться к нулю. На фоне новых возможностей все их «фишки» сразу побледнели. Например, смешно, что еще недавно какая-нибудь замена терминала VT-340 на VT-52100 c памятью на 5 страниц, позволяющей вводить текст еще до включения БЭСМ, казалась важной.

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

Впрочем, последние годы работа с БЭСМ-6 через диалоговую программу «Пульт» разработки МГУ, как раз очень напоминала работу за первыми персоналками и поэтому переход был несложным.

А вот задачи стали другие. Отдел занимался разработкой ПО системы управления «Энергия-Буран». Точнее, отдел занимался комплексацией, верификацией, взаимодействием с наземным ПО и т.п., а собственно разработкой занималось сразу несколько отделов. Я впервые принимал участие в проекте, где были заняты десятки программистов. Язык программирования – ПРОЛ-2 разработки ИПМ АН СССР.

Вообще-то, девичья фамилия этого языка была «Пролог-Ц» от ПРОграммирования ЛОГики. А литера «Ц» - это, вероятно, ЦУП. Но поскольку в то время на слуху был японский Пролог с его транспьютерами, вероятно разработчикам надоело отвечать на вопросы о применении транспьютеров в «Буране», поэтому вторая версия языка вышла под таким скромным и безликим именем.

Язык был специфический, для задач управления. Типичный алгоритм выглядел так: выдать такую-то команду, подождать 0.3 миллисекунды, проверить такую-то переменную. Если она нулевая – выдать другую команду и запустить такой-то процесс. И все в таком духе.

Разумеется, инструментальных средств под x86 еще не было. Поэтому в отделе родилась идея, а затем – предложение – указание – распоряжение – создать отладочный или, точнее, проверочный транслятор для персоналки. Во-первых, он облегчит процесс комплексирования и верификации, а во-вторых, возможно, несколько увеличит производительность и в других отделах, сократив число подходов к штатному транслятору (на ЕС ЭВМ).

Читать далее

И на Солнце есть пятна

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

В предыдущей заметке «Планировщик Windows? Это очень просто» было рассказано о технологии получения дизассемблированного текста ядра операционной системы Windows XP образца 2013 года. Такой текст потребовался для анализа и корректировки кода ядра, что позволило изменить политику планирования потоков в Windows и выполнить одну конкретную задачу с уменьшением времени отклика операционной системы.

После решения этой задачи я напоследок просто «полистал» текст ядра, особо не вникая, что именно делается в том или ином участке кода. Хотелось посмотреть, какие приемы локальной (т.е. в пределах 1-2 команд) оптимизации применяет использованный для создания ядра транслятор. Или, может быть, несколько трансляторов, если ядро собрано из нескольких отдельных частей. Сознаюсь, главная цель была в поиске таких приемов генерации кода, которые я не догадался использовать в своем трансляторе.

Поскольку Windows является, наверное, самой дорогой программой в мире по затратам на разработку и сопровождение, уровень качества кода ее ядра должен бы быть одним из самых высоких. Именно поэтому было интересно посмотреть, как устроен код с точки зрения эффективности отдельных команд. Однако я увидел не совсем то, что ожидал и поэтому решил поделиться несколькими соображениями. Для иллюстрации ниже приведены фрагменты дизассемблированного кода ядра Windows XP сборки от 4 июля 2013 года.

Хотя Windows XP и Windows 7 уже, так сказать, «сняты с вооружения», на мой взгляд, изучение даже неподдерживаемых программ имеет смысл. Ядро Windows XP сопровождалось и развивалось около 10 лет. Поэтому на основании анализа кода можно, например, даже прогнозировать пути дальнейшего развития системы. Замечу также, что различия в коде ядер различных версий Windows не так велики как различия некоторых других компонентов.

Читать далее

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

Микрохирургия ELF'а или «А что, так можно было?!»

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

Разбираемся в устройстве PE и рождественских ELF'ов, реверс-инжинирим runtime-библиотеку, портируем ассемблерный код, собираем и редактируем исполняемые файлы и периодически спрашиваем себя "А так можно было?".

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

Но обо всём по порядку

Java HotSpot JIT компилятор — устройство, мониторинг и настройка (часть 2)

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

В предыдущей статье мы рассмотрели устройство JIT компилятора и способы мониторинга его работы. В этой статье мы рассмотрим счетчики, которые JVM использует для принятия решения о необходимости компиляции кода, потоки компиляции, оптимизации, выполняемые JVM при компиляции, а также что такое деоптимизация кода.

Читать далее

Модификация исполняемого кода как способ реализации массивов с изменяемым границами

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

В свете все возрастающего потока англоязычных околонаучных терминов в области программирования и следуя за модой, в названии статьи можно было бы вместо некрасивого «модификация исполняемого кода» написать что-нибудь вроде «run-time reflection». Суть от этого не меняется. Речь о реализации в компиляторе такого непростого объекта, как массив с заранее неизвестными границами. Типичный пример использования подобных объектов – это операции (в математическом смысле) с матрицами разных размеров.

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

Обычно текущие значения границ пишутся в специальную структуру («паспорт» массива) и затем используются в командах вычисления адресов элементов массива. Для границ-констант, известных при компиляции, «паспорт» в общем случае в выполняемой программе не требуется.

Из сложности реализации таких массивов следует неприятное следствие: обращение к массивам с «динамическими» границами выполняется существенно медленнее, чем к массивам с границами-константами. Желательно было бы соединить мощь и удобство работы с массивами с задаваемыми при исполнении кода границами с быстротой доступа к массивам с границами-константами, когда часть вычислений адресов элементов может производиться уже на этапе компиляции программы.

Далее все рассуждения приводятся на примере конкретной реализации компилятора PL/1-KT с языка PL/1 для Win64.

Читать далее

Java HotSpot JIT компилятор — устройство, мониторинг и настройка (часть 1)

Время на прочтение8 мин
Количество просмотров43K
JIT (Just-in-Time) компилятор оказывает огромное влияние на быстродействие приложения. Понимание принципов его работы, способов мониторинга и настройки является важным для каждого Java-программиста. В цикле статей из двух частей мы рассмотрим устройство JIT компилятора в HotSpot JVM, способы мониторинга его работы, а также возможности его настройки. В этой, первой части мы рассмотрим устройство JIT компилятора и способы мониторинга его работы.
Читать дальше →

О реализации ввода-вывода с именами

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

Как-то на одном из компьютерных форумов участники делились соображениями, чего им не хватает в языках, так сказать, в повседневной деятельности. Один заявил, что ему очень не хватает оператора типа put data. Для тех, кто не слышал о таком, поясню, что в языке PL/1 был предусмотрен оператор вывода (или ввода) значений переменных вместе с их именами, т.е. вместе с идентификаторами.

Например, если обычный вывод put list(X,Y); давал что-нибудь вроде:

1280    1024

то оператор put data(X,Y); печатал:

X=   1280  Y=   1024

не заставляя писать для этого вывод в виде оператора:

put list(’X=’,X,’Y=’,Y);

Чаще всего это использовалось в отладочных целях, но не обязательно. Например, используя вывод в текстовый файл с помощью put data, а затем ввод этих же данных как исходных в другой программе с помощью «зеркального» оператора get data можно было получить удобную для чтения и редактирования форму представления исходных данных в текстовом виде.

Можно возразить, что современные «оболочки» систем программирования легко позволяют вывести значения (и имена) любых объектов программы в интерактивном режиме безо всяких put data и поэтому в нем больше нет необходимости.

Я тоже использую встроенный интерактивный отладчик, с помощью которого можно посмотреть любые, даже сложные (составные) данные. Однако потребность в возможностях put data не исчезла. Иногда нужен и анализ данных «на распечатке», (т.е. в логе) с возможностью быстрого и удобного добавления вывода для отладки. К тому же для работы отладочных интерактивных систем используется дополнительная информация, которая обычно в выполняемом exe-файле отсутствует. В этом же случае все имена переменных «зашиты» в самой программе. Таким образом, удобства, предоставляемые языком в виде оператора, подобного put data, не заменяют, а дополняют возможности отладчиков. Кстати, в стародавние времена так называемая «посмертная» выдача на печать после ошибки иногда включала в себя и вывод полного списка всех имен переменных вместе с их текущими значениями. Некоторым программистам так нравился такой вывод, что они специально в конце своей программы ставили деление на ноль.

Читать далее

Ещё один способ использования python в браузере (и не только)

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

Весной 2020 года я впервые попробовал себя в разработке сайтов бэкенд я писал на питоне а на фронте пришлось использовать js и он вызвал у меня отторжение(тут надо уточнить, что я не считаю js ужасным языком, просто он мне не понравился). Не долго думая я начал писать транслятор с питона в явускрипт(а если бы погуглил то нашел бы это https://brython.info/, https://www.transcrypt.org/). об этом трансляторе и пойдет речь.

Читать далее

Rust 1.49.0: aarch64 и улучшения во фреймворке тестирования

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

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


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


rustup update stable

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


Что вошло в стабильную версию 1.49.0


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

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

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