Обновить
266
Андрей Дмитриев@AndreyDmitriev

Пользователь

0,4
Рейтинг
114
Подписчики
Отправить сообщение

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

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

Человек уже понимал, что не укладывается в срок, но продолжал молчать

<...>

отсылает к книге Джорджо Нардонэ и Джулио Де Сантиса «Патологическое сомнение. Мыслю, следовательно страдаю».

Есть ещё одна замечательная книжка, которая даёт ответ на вопрос «как так получилось, что мы профукали сроки на несколько месяцев?». Это «Мифический человеко-месяц» Фредерика Брукса. Там есть золотые слова «в начале ваш проект задержался ровно на один день». И вот способность распознать этот день, и не молчать — и есть признак хорошего менеджера.

У меня есть пример — пару лет назад мы делали очередную систему для рентгеновского неразрушающего контроля, моя задача была автоматизировать хитрый механический сменный фильтр с парой шаговых моторов. В каждой системе есть что-то специальное. И вот, значит, привезли в цех новенькую кабину радиационной защиты, цех у нас двумя этажами ниже, я практически ежедневно наблюдал, как её неспеша собирают и в какой-то момент увидел, что несколько дней с ней ничего не происходило, стоит, пылится. Пошёл к менеджеру — почему задержка? Он мне объяснил, что у нас на складе внезапно кончились спец болты для сдвижной двери (а она весит больше тонны), и у поставщика их нет, и вот — ждём-с, абы какие туда не вкорячить. Я ему сразу сказал — что мы в опасносте, а он мне — да нифига, наверстаем, проект рассчитан почти на год, неделя-другая роли не играет. Короче, три недели ждали этих болтов, в итоге там получился снежный ком проблем, весь график улетел в тартары, и по итогу систему сдали с задержкой на четыре месяца, заказчик был сильно недоволен. Точнее поставили её в срок, но в полуживом состоянии, потому что признаваться в проблемах никто не хотел, опять же конец года, и уже зафрахтован кран и контейнер для перевозки, и всё такое. А два сервис инженера провели многие недели в одной жаркой стране на пусконаладке. Я с тех пор всегда этот пример привожу всем юным менеджерам — как так вышло что ты на двенадцать недель выбился из графика? А вначале был день первый, вот тот самый, когда на стеллаже не оказалось нужных болтов.

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

За наводку на книжку спасибо, полистаю на досуге.

У меня есть (дело в Германии), но я скептически на это смотрю - на рекламу много раз давил через Report ad, но она всё лезет.

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

«Старая жёсткая схема управления не заработала, поэтому перешли на гибкие методы. Наняли специалиста по процессам, начали проводить регулярные встречи и следить за производительностью команды. Похоже, компания всё больше движется в сторону модных подходов к управлению. Правда, руководитель команды уже устал и хочет взять длительный отпуск.» 🤣

Про бирюзу вот не сразу понял, но копилот пояснил, так что закинул себе в читалку Reinventing Organizations Фредерика Лалу, на досуге полистаю, спасибо.

Спасибо за статью, хотя каждодневное использование std::collections::HashMap - зависит от решаемых задач, я пользовался за последние пару лет ровно один раз.

Единственно - Вы показали кусочки кода, было б здорово, если б куда-нибудь, там на гитхаб или под спойлеры закинули полноценные примеры, желательно с бенчмарками, в идеале criterion. Сейчас, кстати, в свежем RustRover 2026.2 завезли удобный запуск criterion прямо из проекта и тут же и результаты и бенчмаркать "не отходя от кассы" стало ещё удобнее.

Капаситете тасков принято мерять в стори поинтах, где применяются числа Фибоначчи (ну там 1, 2, 3, 5, 8, и 13 и так далее). Консёрны надо бустить, конечно, иначе потом появится много ишью. У нас (дело в Германии происходит), чтобы не мешать немецкий и английский на созвонах просто перешли на английский, ну как-то само так получилось.

А учитывая стандартную противофазу на НЧ, в стереосигнале - при схлопывании в моно

А как тогда работает дешёвая акустика 2.1 с сабвуфером? Я не думаю, что там проц стоит, который всё это разруливает, просто высокие отфильтровали, тупо смешали оба канала и на выход, разве нет?

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

А да, верно. Я хотел было возразить, мол как тогда отлаживаться, но проверил — оно и в дебаге так, и в точки останов мы в таких функциях вообще не влетаем, всё честно:

Чисто математически waveform, конечно изменится, вопрос только в том - насколько. У меня есть проигрыватель Technics и High-Res плеер Surfans F35, и когда я слушаю пластинку или её же, но хорошо оцифрованную, то разница лишь в тембральной окраске, но в качестве я её не улавливаю. Немного напрягшись я ещё могу отличить зажатые в MP3 16-bit/44.1kHz от 24-bit/192kHz FLAC, но скажем, дискретизацию 96kHz от 192kHz на 24-х битах мои уши не различают, по крайней мере на той технике, что у меня есть. Возможно на системе неприличной стоимости она станет заметна на слух, да и то только после тщательнейшего прогрева проводов из бескислородной меди, уж не иначе. Некоторые любители качественного звука вообще утверждают, что проводникам нужно от нескольких дней до недель работы для «улучшения» звучания, чтоб все waveformы пришли в норму.

Но ведь компилятор в некоторых случаях и без const фолдит несложные вычисления в константы.

Ну вот как пример, совсем примитивно, без всяких констант:

fn add(a: i32, b: i32) -> i32 {
	a + b
}


fn main() {
	let sum = add(1111, 2222);
    println!("sum = {sum}");
}

Компиляем в релиз, вот так самое простое:

cargo rustc -r -- --emit=asm -C "llvm-args=-x86-asm-syntax=intel"

лезем в ассемблер, смотрим:

	...
	.seh_endprologue
	mov	dword ptr [rsp + 36], 3333 ; <---
	lea	rax, [rsp + 36]
	...

С Фибоначчи такой фокус не прокатит:

fn fib(n: u32) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => fib(n - 1) + fib(n - 2),
    }
}
 
fn main() {
	let n: u64 = fib(50);
    println!("fib = {n}");
}

Там всё честно

	...
	.seh_endprologue
	mov	ecx, 50 ; <---
	call	_RNvCs6ce6R4bzhVd_5r_fib3fib
	mov	qword ptr [rsp + 32], rax
	...

Теперь если мы вкорячим const, оставив 50

const fn fib(n: u32) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => fib(n - 1) + fib(n - 2),
    }
}

fn main() {
	const N: u64 = fib(50);
    println!("fib = {N}");
}

то результата вообще не получим, ибо

error: constant evaluation is taking a long time
  --> src\main.rs:5:27
   |
 5 |         _ => fib(n - 1) + fib(n - 2),
   |                           ^^^^^^^^^^
   |
   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
           If your compilation actually takes a long time, you can safely allow the lint
help: the constant being evaluated
  --> src\main.rs:10:2
   |
10 |     const N: u64 = fib(50);
   |     ^^^^^^^^^^^^
   = note: `#[deny(long_running_const_eval)]` on by default

Экспериментально я выяснил, что оно по умолчанию работает до 29:

fn main() {
	const N: u64 = fib(29);
    println!("fib = {N}");
}

Тогда да, причём оно вот сюда попадает и вот так используется:

	...
	mov	qword ptr [rsp + 48], rax
	lea	rcx, [rip + anon.80a170a4d4583f6fbc2a855e4161cdbb.2]
	lea	rdx, [rsp + 40]
	...
	.p2align	3, 0x0
anon.80a170a4d4583f6fbc2a855e4161cdbb.1:
	.asciz	"\265\330\007\000\000\000\000" < --- 514229 const N: u64 = fib(29);
	...

Ну или выставить allow(long_running_const_eval)

fn main() {
#[allow(long_running_const_eval)]
	const N: u64 = fib(50);
    println!("fib = {N}");
}

Тогда ошибка превратится в предупреждение и надо будет довольно долго ждать компиляции.

И, кстати, да, там не всё можно использовать, если скажем так:

const fn fib(n: u32) -> u64 {
    if n <= 1 {
        return n as u64;
    }

    let mut a: u64 = 0;
    let mut b: u64 = 1;

    for _ in 2..=n {
        let next = a + b;
        a = b;
        b = next;
    }

    b
}

То получим по лбу:

error[E0015]: cannot use `for` loop on `std::ops::RangeInclusive<u32>` in constant functions
 --> src\main.rs:9:14
  |
9 |     for _ in 2..=n {
  |              ^^^^^
  |
  = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

For more information about this error, try `rustc --explain E0015`.

Кстати, Си компиляторы тоже считают на этапе компиляции, и даже в непростых случаях.

Вот смотрите, на днях мы тут налетели вот на такой баг в распоследней Студии:

Вот этот код даёт неверный результат в июльской VS2026, v.18.8.1 (тикет):

#include <stdio.h>
#include <immintrin.h>

__declspec(noinline)
__m512i bug() {
    __m512i x = _mm512_set1_epi16(4);
    __m512i m = _mm512_set1_epi32(~0u);
    return _mm512_add_epi16(m, _mm512_add_epi16(m, x));
}

int main() {
    short lanes[32];
    __m512i v = bug();
    _mm512_storeu_si512((__m512i*)lanes, v);

    for (int i = 0; i < 32; i++) {
        printf("lane[%2d] = %d\n", i, lanes[i]);
    }

    return 0;
}

Должны быть все двойки, а мы получим 2 3 2 3 2..., потому что константа будет неверная. Я проверил свежие gcc и Intel OneAPI, и там всё корректно, но каково же было моё изумление, когда я заглянул в бинарники, а там Интеловский компилятор заменил всё тело константой, реально вычислив вот это вот всё на этапе компиляции, хотя казалось бы, тут интринсики... Но да.

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

Эх, мне вот тоже всегда хотелось иметь "хороший звук", я с завистью смотрел на всякие S90, Амфитоны и дорогущие катушечные магнитофоны у однокурсников, но студенческая стипендия не позволяла всё это заиметь, а началось всё с того, что давным-давно отец купил магнитофон-кассетник "Весна 211" , вот такой:

Там в комплекте две колонки из тонюсенького пластика с парой 4ГДШ35 вроде бы. Их можно было переключать последовательно или параллельно кнопкой на задней стенке, таким образом или 2 ома или 8. В "качестве" акустического оформления сомнений не возникало, там не было ни баса ни высоких, и поэтому первое, что я сделал после истечения гарантийного срока - в библиотеке политеха собрал все книжки, до которых смог дотянуться, журнал Радио опять же, я его всегда выписывал, и на калькуляторе МК61 рассчитал новые корпуса. Я выбрал фазонверторы, и сделал из двух четыре двухполосные системы из ДСП, рассчитав фильтры, настолько хорошо, насколько позволяли мои знания в радиотехнике. Для намотки индуктивностей я даже купил станочек со счётчиком. Венцом моего аудиостроения был четырёхканальный квадрофонический усилитель, вначале на П210А (по схеме, кажется из журнала Моделист-Конструктор, там для тыловых каналов вроде сдвиг фазы был), а потом, поднакопив денег на радиодетали, оконечные каскады я собрал по схеме Сухова, это был конец восьмидесятых где-то. Звук был хороший. Мне потом S30 подарили и моя самопальная акустика была даже лучше. Но потом я переехал, однако тема многоканального звука не отпускала, так что я по случаю купил шестиканальный комплект Eltax Summit, это датская компания, вот этот:

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

И потом сабвуфер той же фирмы добавил, и подкинул это всё к ресиверу Denon AVR 1707, смотреть фильмы с многоканальным звуком стало приятнее, я кинотеатр сделал с проектором. А, у ресивера в комплекте есть микрофончик на длинном проводе - кладёшь его там, где будешь сидеть, жамкаешь на кнопку, и он сам пищит и гудит во все каналы и самонастраивается. Я б не сказал, что звук был прям бомбический, но приятный и не утомительный, акустика за сотню играет на свои деньги, но не более. Для фильмов - норм, для музыки, пожалуй нет.

А потом случилось прекрасное, в газете в разделе "отдам даром" я увидел объявление, что чувак дарит пару колонок Kenwood, неисправных. Ну как я мог упустить такой шанс, мне всегда хотелось здоровенные S90, так что я немедленно их забрал.

Беда их заключалась в том, что низкочастотники пришли в состояние "хоронили тёщу — порвали два баяна" (извините за чёрный юмор), у них рассыпались подвесы, просто от старости:

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

Я решил, что ничем не рискую и хуже всё равно не сделаю, так что вообще не проверяя, насколько они по добротности и остальным параметрам подходят к этим ящикам, просто купил и вкорячил вместо старых, встали туда почти как родные. И наступило счастье. Извините за "пыльную" фотку, просто фотик так грязь вытянул, на самом деле они не такие ушатанные, хотя им почти сорок лет.

Это реально тот самый "тёплый" звук с мягким обволакивающим басом, можно весь день напролёт слушать. Формально ящик LS-880 им великоват, но он там звукопоглотителем заполнен, я думал, что придётся повозиться с настройкой фазоинвертора и фильтров, но нет в "стоковом" варианте меня всё устраивает (хотя если их дотошно замерить, то не думаю, что там всё хорошо, технически наверняка возникнут вопросы). Но тут важно просто субъективное восприятие, когда дома никого нет, я их иногда включаю погромче, что б прям как на концерте, и оно реально звучит как на концерте. С удовольствием слушаю хорошие качественные оцифровки с грампластинок, чтоб чуть-чуть шуршало, хотя и вертушка у меня тоже есть. Хотя я без фанатизма, акустическим оформлением помещения я вообще не заморачиваюсь, у меня комнатушка десяток квадратных метров где-то. Жалко, что на работу я их не могу оттащить, и хотя у меня отдельный кабинет, но в в соседних офисах тоже работают люди, так что тут у меня маленькие полочники, сначала были Wharfedale, старенькие, но неплохие, а недавно я по случаю проапгредился на Q Acoustics 3010, у них кстати, бас заметно лучше, но я больше на дизайн купился - они как бы кожей обклеены. Вот теперь я побаиваюсь, что после следующей статьи меня таки настигнет волна аудиофилии, там и до лампового усилка недалеко.

Да, конечно, StringZilla SIMD и есть, просто писать поиск подстрок с нуля - это "переизобретение колеса" в какой-то мере, кроме того есть ещё разные алгоритмы (ну там Кнут-Моррис-Пратт и т.д), в принципе под какие-то специфические данные можно повозиться, а вот в общем случае имеющиеся библиотеки типа этой потребности покрывают. А про i9-10900KF  - я прочитал статью слишком быстро и мне показалось, что там "эмулируемый" в камушке AVX512, которого в природе не существует. Так-то у меня есть пара Xeon с AVX-512, может на досуге гляну.

Эх, было бы ещё здорово рассмотреть то, как роботы программируются (ну там ABB RAPID, Kuka KRL, Fanuc KAREL, что там ещё?), где собственно крутится управляющая программа, и то, как они потом общаются с внешним миром - с ПЛК или промышленным компом, там OPC UA, полевые шины, АСУ ТП, СКАДА, вот это вот всё. В принципе там прям особых принципиальных отличий между марками нет, но есть нюансы. Самое классное, что видел - на выставке в Ганновере к Куке приделали пару кресел и катали там людей, как на аттракционе, но я не рискнул, зная что там в реалтайме крутилась Windows XP, хоть и с навешенным Wind River VxWorks, хотя это не подводило ни разу на моей памяти. На самом деле они довольно надёжные, как по аппаратной, так и по программной части.

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

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

Варианта "другое" не хватает в опросе. У меня StringZilla живёт, в общем не жалуюсь. Правда не .net, а LabVIEW и Раст. А вот то, что у  i9-10900KF нет аппаратного AVX512 — не знал, надо будет побенчмаркать на досуге, если до такого камушка доберусь.

— А о чём, товарищи, эта книга? — осведомился он.

— Да ни о чём, — сказал я.

Купите мощный UV фонарь, где-то 400 нм вроде, выйдите на поиски вечером и попробуйте поискать по флуоресценции.

замедление времени — всё это стоит на обычном школьном синусе, которому угол сделали мнимым.

Ну то есть мы можем, пользуясь такими синусами честно и численно показать аномальное смещение перигелия Меркурия, которое 43 угловые секунды? Было бы любопытно взглянуть на расчёты.

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

Вот смотрите, допустим такой примитивный код, тут восемь строчек всего:

fn main() {
    let mut x = 10; // создаём изменяемую переменную x со значением 10
    add_one(&mut x);// передаём изменяемую ссылку на x (mutable borrow)
    println!("x after mod: {x}"); // выводим значение x после изменения
}

fn add_one(n: &mut i32) {
    *n += 1; // разыменовываем ссылку и увеличиваем значение на 1
}

Вначале при компиляции идёт стадия HIR (High‑Level IR) - преобразование в высоко-уровневое промежуточное представление. С некоторой натяжкой его можно назвать "препроцессор", тут разворачиваются макросы, код очищается от "сахара", вот что получится, это всё ещё Раст:

extern crate std;
#[attr = PreludeImport]
use std::prelude::rust_2024::*;
fn main() {
    let mut x =
        10; // создаём изменяемую переменную x со значением 10
    add_one(&mut x); // передаём изменяемую ссылку на x (mutable borrow)
    // выводим значение x после изменения

    // разыменовываем ссылку и увеличиваем значение на 1
    {
        ::std::io::_print({
                super let args = (&x,);
                super let args = [format_argument::new_display(args.0)];
                unsafe {
                    format_arguments::new(b"\rx after mod: \xc0\x01\n\x00",
                        &args)
                }
            });
    };
}
fn add_one(n: &'_ mut i32) { *n += 1; }

Затем идёт вторая стадия, THIR (Typed High‑Level IR), тоже высокоуровневая, тут я только кусочек покажу:

DefId(0:4 ~ r_test[ee7e]::add_one):
params: [
    Param {
        ty: &'{erased} mut i32
        ty_span: Some(src\main.rs:7:15: 7:23 (#0))
        self_kind: None
        hir_id: Some(HirId(DefId(0:4 ~ r_test[ee7e]::add_one).1))
        param: Some( 
            Pat {
                ty: &'{erased} mut i32
                span: src\main.rs:7:12: 7:13 (#0)
                kind: PatKind {
                    Binding {
                        name: "n"
                        mode: BindingMode(No, Not)
Так-то там восемьсот(!) с лишним строк
DefId(0:3 ~ r_test[ee7e]::main):
params: [
]
body:
    Expr {
        ty: ()
        temp_scope_id: 54
        span: src\main.rs:1:11: 5:2 (#0)
        kind: 
            Scope {
                region_scope: Node(54)
                hir_id: HirId(DefId(0:3 ~ r_test[ee7e]::main).54)
                value:
                    Expr {
                        ty: ()
                        temp_scope_id: 54
                        span: src\main.rs:1:11: 5:2 (#0)
                        kind: 
                            Block {
                                targeted_by_break: false
                                span: src\main.rs:1:11: 5:2 (#0)
                                region_scope: Node(1)
                                safety_mode: Safe
                                stmts: [
                                    Stmt {
                                        kind: Let {
                                            remainder_scope: Remainder { block: 1, first_statement_index: 0}
                                            init_scope: Node(2)
                                            pattern: 
                                                Pat {
                                                    ty: i32
                                                    span: src\main.rs:2:9: 2:14 (#0)
                                                    kind: PatKind {
                                                        Binding {
                                                            name: "x"
                                                            mode: BindingMode(No, Mut)
                                                            var: LocalVarId(HirId(DefId(0:3 ~ r_test[ee7e]::main).5))
                                                            ty: i32
                                                            is_primary: true
                                                            is_shorthand: false
                                                            subpattern: None
                                                        }
                                                    }
                                                }
                                            ,
                                            initializer: Some(
                                                Expr {
                                                    ty: i32
                                                    temp_scope_id: 3
                                                    span: src\main.rs:2:17: 2:19 (#0)
                                                    kind: 
                                                        Scope {
                                                            region_scope: Node(3)
                                                            hir_id: HirId(DefId(0:3 ~ r_test[ee7e]::main).3)
                                                            value:
                                                                Expr {
                                                                    ty: i32
                                                                    temp_scope_id: 3
                                                                    span: src\main.rs:2:17: 2:19 (#0)
                                                                    kind: 
                                                                        Literal( lit: Spanned { node: Int(Pu128(10), Unsuffixed), span: src\main.rs:2:17: 2:19 (#0) }, neg: false)

                                                                }
                                                        }
                                                }
                                            )
                                            else_block: None
                                            hir_id: HirId(DefId(0:3 ~ r_test[ee7e]::main).4)
                                            span: src\main.rs:2:5: 2:19 (#0)
                                        }
                                    }
                                    Stmt {
                                        kind: Expr {
                                            scope: Node(12)
                                            expr:
                                                Expr {
                                                    ty: ()
                                                    temp_scope_id: 6
                                                    span: src\main.rs:3:5: 3:20 (#0)
                                                    kind: 
                                                        Scope {
                                                            region_scope: Node(6)
                                                            hir_id: HirId(DefId(0:3 ~ r_test[ee7e]::main).6)
                                                            value:
                                                                Expr {
                                                                    ty: ()
                                                                    temp_scope_id: 6
                                         ... дальше Хабр не разрешает

Следом идёт средняя промежуточная стадия MIR (Mid‑Level Intermediate Representation), тут мы ближе к llvm, и как раз на этом этапе разбираются заимствования, владения, времена жизни, и Miri, кстати, работает как раз на этом уровне:

    let _11: &[core::fmt::rt::Argument<'_>; 1];
    let mut _12: &i32;
    scope 1 {
        debug x => _1;
        let _6: (&i32,);
        scope 2 {
            debug args => _6;
            let _8: [core::fmt::rt::Argument<'_>; 1];
            scope 3 {
                debug args => _8;
            }
        }
    }

    bb0: {
        _1 = const 10_i32;
        _3 = &mut _1;
        _2 = add_one(copy _3) -> [return: bb1, unwind continue];
    }
Полностью
// WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
// HINT: See also -Z dump-mir for MIR at specific points during compilation.
fn main() -> () {
    let mut _0: ();
    let mut _1: i32;
    let _2: ();
    let mut _3: &mut i32;
    let _4: ();
    let mut _5: std::fmt::Arguments<'_>;
    let mut _7: &i32;
    let mut _9: core::fmt::rt::Argument<'_>;
    let mut _10: &[u8; 27];
    let _11: &[core::fmt::rt::Argument<'_>; 1];
    let mut _12: &i32;
    scope 1 {
        debug x => _1;
        let _6: (&i32,);
        scope 2 {
            debug args => _6;
            let _8: [core::fmt::rt::Argument<'_>; 1];
            scope 3 {
                debug args => _8;
            }
        }
    }

    bb0: {
        _1 = const 10_i32;
        _3 = &mut _1;
        _2 = add_one(copy _3) -> [return: bb1, unwind continue];
    }

    bb1: {
        _7 = &_1;
        _6 = (move _7,);
        _12 = no_retag copy (_6.0: &i32);
        _9 = core::fmt::rt::Argument::<'_>::new_display::<i32>(copy _12) -> [return: bb2, unwind continue];
    }

    bb2: {
        _8 = [move _9];
        _10 = const b"\x16x after modification: \xc0\x01\n\x00";
        _11 = &_8;
        _5 = Arguments::<'_>::new::<27, 1>(move _10, copy _11) -> [return: bb3, unwind continue];
    }

    bb3: {
        _4 = std::io::_print(move _5) -> [return: bb4, unwind continue];
    }

    bb4: {
        return;
    }
}

alloc1 (size: 27, align: 1) {
    0x00 │ 16 78 20 61 66 74 65 72 20 6d 6f 64 69 66 69 63 │ .x after modific
    0x10 │ 61 74 69 6f 6e 3a 20 c0 01 0a 00                │ ation: ....
}

fn add_one(_1: &mut i32) -> () {
    debug n => _1;
    let mut _0: ();
    let mut _2: (i32, bool);

    bb0: {
        _2 = AddWithOverflow(copy (*_1), const 1_i32);
        assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", copy (*_1), const 1_i32) -> [success: bb1, unwind continue];
    }

    bb1: {
        (*_1) = move (_2.0: i32);
        return;
    }
}

И лишь затем идёт собственно llvm, это четвёртая стадия, там видно как наша константа 10 с инкрементом "сфолдилась" в 11:

  call void @llvm.lifetime.start.p0(ptr nonnull %x)
  store i32 11, ptr %x, align 4 ; 11 
  call void @llvm.lifetime.start.p0(ptr nonnull %args)
; ...
  call void __print(ptr noundef, ...

.LLVM полностью:

LLVM
; ModuleID = 'r_test.decfb7566f1495f6-cgu.0'
source_filename = "r_test.decfb7566f1495f6-cgu.0"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"

@vtable.0 = private unnamed_addr constant <{ [24 x i8], ptr, ptr, ptr }> <{ [24 x i8] c"\00\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00", ptr @_RNSNvYNCINvNtCscd1f6iWV66h_3std2rt10lang_startuE0INtNtNtCsckEfzrs6Fp9_4core3ops8function6FnOnceuE9call_once6vtableCsj81e8EUiNGk_6r_test, ptr @_RNCINvNtCscd1f6iWV66h_3std2rt10lang_startuE0Csj81e8EUiNGk_6r_test, ptr @_RNCINvNtCscd1f6iWV66h_3std2rt10lang_startuE0Csj81e8EUiNGk_6r_test }>, align 8
@alloc_e5787bd0c3f1ea82bc1a90da9c1a53af = private unnamed_addr constant [27 x i8] c"\16x after modification: \C0\01\0A\00", align 1

; std::rt::lang_start::<()>
; Function Attrs: uwtable
define hidden noundef i64 @_RINvNtCscd1f6iWV66h_3std2rt10lang_startuECsj81e8EUiNGk_6r_test(ptr noundef nonnull %main, i64 noundef %argc, ptr noundef %argv, i8 noundef %sigpipe) unnamed_addr #0 {
start:
  %_7 = alloca [8 x i8], align 8
  call void @llvm.lifetime.start.p0(ptr nonnull %_7)
  store ptr %main, ptr %_7, align 8
; call std::rt::lang_start_internal
  %_0 = call noundef i64 @_RNvNtCscd1f6iWV66h_3std2rt19lang_start_internal(ptr noundef nonnull %_7, ptr noalias nofree noundef readonly align 8 captures(address, read_provenance) dereferenceable(48) @vtable.0, i64 noundef %argc, ptr noundef %argv, i8 noundef %sigpipe)
  call void @llvm.lifetime.end.p0(ptr nonnull %_7)
  ret i64 %_0
}

; std::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
; Function Attrs: noinline uwtable
define internal fastcc void @_RINvNtNtCscd1f6iWV66h_3std3sys9backtrace28___rust_begin_short_backtraceFEuuECsj81e8EUiNGk_6r_test(ptr noundef nonnull readonly captures(none) %f) unnamed_addr #1 {
start:
  tail call void %f()
  tail call void asm sideeffect "", "~{memory}"() #6, !srcloc !4
  ret void
}

; std::rt::lang_start::<()>::{closure#0}
; Function Attrs: inlinehint uwtable
define internal noundef i32 @_RNCINvNtCscd1f6iWV66h_3std2rt10lang_startuE0Csj81e8EUiNGk_6r_test(ptr noalias nofree noundef readonly align 8 captures(none) dereferenceable(8) %_1) unnamed_addr #2 {
start:
  %_4 = load ptr, ptr %_1, align 8, !nonnull !5, !noundef !5
; call std::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
  tail call fastcc void @_RINvNtNtCscd1f6iWV66h_3std3sys9backtrace28___rust_begin_short_backtraceFEuuECsj81e8EUiNGk_6r_test(ptr noundef nonnull %_4) #7
  ret i32 0
}

; <std::rt::lang_start<()>::{closure#0} as core::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
; Function Attrs: inlinehint uwtable
define internal noundef i32 @_RNSNvYNCINvNtCscd1f6iWV66h_3std2rt10lang_startuE0INtNtNtCsckEfzrs6Fp9_4core3ops8function6FnOnceuE9call_once6vtableCsj81e8EUiNGk_6r_test(ptr noundef readonly captures(none) %_1) unnamed_addr #2 personality ptr @__CxxFrameHandler3 {
start:
  %0 = load ptr, ptr %_1, align 8, !nonnull !5, !noundef !5
; call std::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
  tail call fastcc void @_RINvNtNtCscd1f6iWV66h_3std3sys9backtrace28___rust_begin_short_backtraceFEuuECsj81e8EUiNGk_6r_test(ptr noundef nonnull readonly %0) #7, !noalias !6
  ret i32 0
}

; r_test::main
; Function Attrs: uwtable
define hidden void @_RNvCsj81e8EUiNGk_6r_test4main() unnamed_addr #0 {
start:
  %args = alloca [16 x i8], align 8
  %x = alloca [4 x i8], align 4
  call void @llvm.lifetime.start.p0(ptr nonnull %x)
  store i32 11, ptr %x, align 4
  call void @llvm.lifetime.start.p0(ptr nonnull %args)
  store ptr %x, ptr %args, align 8
  %_6.sroa.4.0..sroa_idx = getelementptr inbounds nuw i8, ptr %args, i64 8
  store ptr @_RNvXs9_NtNtNtCsckEfzrs6Fp9_4core3fmt3num3implNtB9_7Display3fmt, ptr %_6.sroa.4.0..sroa_idx, align 8
; call std::io::stdio::_print
  call void @_RNvNtNtCscd1f6iWV66h_3std2io5stdio6__print(ptr noundef nonnull @alloc_e5787bd0c3f1ea82bc1a90da9c1a53af, ptr noundef nonnull %args)
  call void @llvm.lifetime.end.p0(ptr nonnull %args)
  call void @llvm.lifetime.end.p0(ptr nonnull %x)
  ret void
}

; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(ptr captures(none)) #3

; std::rt::lang_start_internal
; Function Attrs: uwtable
declare noundef i64 @_RNvNtCscd1f6iWV66h_3std2rt19lang_start_internal(ptr noundef nonnull, ptr noalias nofree noundef readonly align 8 captures(address, read_provenance) dereferenceable(48), i64 noundef, ptr noundef, i8 noundef) unnamed_addr #0

; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(ptr captures(none)) #3

; <i32 as core::fmt::Display>::fmt
; Function Attrs: uwtable
declare noundef zeroext i1 @_RNvXs9_NtNtNtCsckEfzrs6Fp9_4core3fmt3num3implNtB9_7Display3fmt(ptr noalias nofree noundef readonly align 4 captures(address, read_provenance) dereferenceable(4), ptr noalias nofree noundef align 8 dereferenceable(24)) unnamed_addr #0

; std::io::stdio::_print
; Function Attrs: uwtable
declare void @_RNvNtNtCscd1f6iWV66h_3std2io5stdio6__print(ptr noundef nonnull, ptr noundef nonnull) unnamed_addr #0

declare i32 @__CxxFrameHandler3(...) unnamed_addr #4

define noundef i32 @main(i32 %0, ptr %1) unnamed_addr #5 {
top:
  %_7.i = alloca [8 x i8], align 8
  %2 = sext i32 %0 to i64
  call void @llvm.lifetime.start.p0(ptr nonnull %_7.i)
  store ptr @_RNvCsj81e8EUiNGk_6r_test4main, ptr %_7.i, align 8
; call std::rt::lang_start_internal
  %_0.i = call noundef i64 @_RNvNtCscd1f6iWV66h_3std2rt19lang_start_internal(ptr noundef nonnull %_7.i, ptr noalias nofree noundef readonly align 8 captures(address, read_provenance) dereferenceable(48) @vtable.0, i64 noundef %2, ptr noundef %1, i8 noundef 0)
  call void @llvm.lifetime.end.p0(ptr nonnull %_7.i)
  %3 = trunc i64 %_0.i to i32
  ret i32 %3
}

attributes #0 = { uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse,+sse2,+sse3,+sahf" }
attributes #1 = { noinline uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse,+sse2,+sse3,+sahf" }
attributes #2 = { inlinehint uwtable "target-cpu"="x86-64" "target-features"="+cx16,+sse,+sse2,+sse3,+sahf" }
attributes #3 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #4 = { "target-cpu"="x86-64" }
attributes #5 = { "target-cpu"="x86-64" "target-features"="+cx16,+sse,+sse2,+sse3,+sahf" }
attributes #6 = { nounwind }
attributes #7 = { noinline }

!llvm.module.flags = !{!0, !1, !2}
!llvm.ident = !{!3}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 7, !"PIE Level", i32 2}
!2 = !{i32 7, !"uwtable", i32 2}
!3 = !{!"rustc version 1.99.0-nightly (375b1431b 2026-07-10)"}
!4 = !{i64 4735085480825446}
!5 = !{}
!6 = !{!7}
!7 = distinct !{!7, !8, !"_RNCINvNtCscd1f6iWV66h_3std2rt10lang_startuE0Csj81e8EUiNGk_6r_test: %_1"}
!8 = distinct !{!8, !"_RNCINvNtCscd1f6iWV66h_3std2rt10lang_startuE0Csj81e8EUiNGk_6r_test"}

На а дальше ассемблер, тут просто по итогу печатаем 11 в консоль, вот здесь:

	mov	dword ptr [rsp + 36], 11 загрузили 11
	lea	rax, [rsp + 36]
	mov	qword ptr [rsp + 40], rax
	lea	rax, [rip + Display3fmt]
	mov	qword ptr [rsp + 48], rax
	call __print ; напечатали

Ассемблер

полный листинг
	.def	@feat.00;
	.scl	3;
	.type	0;
	.endef
	.globl	@feat.00
@feat.00 = 0
	.intel_syntax noprefix
	.file	"r_test.f5a1b3f68eecb1a6-cgu.0"
	.def	_ZN3std2rt10lang_start17h28856b37936baaa7E;
	.scl	2;
	.type	32;
	.endef
	.section	.text,"xr",one_only,_ZN3std2rt10lang_start17h28856b37936baaa7E,unique,0
	.globl	_ZN3std2rt10lang_start17h28856b37936baaa7E
	.p2align	4
_ZN3std2rt10lang_start17h28856b37936baaa7E:
.seh_proc _ZN3std2rt10lang_start17h28856b37936baaa7E
	sub	rsp, 56
	.seh_stackalloc 56
	.seh_endprologue
	mov	rax, r8
	mov	r8, rdx
	mov	qword ptr [rsp + 48], rcx
	mov	byte ptr [rsp + 32], r9b
	lea	rdx, [rip + anon.e6415d161255c43dc2c05166e7cf7172.0]
	lea	rcx, [rsp + 48]
	mov	r9, rax
	call	_RNvNtCslk5dvTldH8g_3std2rt19lang_start_internal
	nop
	.seh_startepilogue
	add	rsp, 56
	.seh_endepilogue
	ret
	.seh_endproc

	.def	_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h3c899e35677daf87E;
	.scl	3;
	.type	32;
	.endef
	.section	.text,"xr",one_only,_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h3c899e35677daf87E,unique,1
	.p2align	4
_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h3c899e35677daf87E:
.seh_proc _ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h3c899e35677daf87E
	sub	rsp, 40
	.seh_stackalloc 40
	.seh_endprologue
	mov	rcx, qword ptr [rcx]
	call	_ZN3std3sys9backtrace28__rust_begin_short_backtrace17h8d3554b6567cef64E
	xor	eax, eax
	.seh_startepilogue
	add	rsp, 40
	.seh_endepilogue
	ret
	.seh_endproc

	.def	_ZN3std3sys9backtrace28__rust_begin_short_backtrace17h8d3554b6567cef64E;
	.scl	3;
	.type	32;
	.endef
	.section	.text,"xr",one_only,_ZN3std3sys9backtrace28__rust_begin_short_backtrace17h8d3554b6567cef64E,unique,2
	.p2align	4
_ZN3std3sys9backtrace28__rust_begin_short_backtrace17h8d3554b6567cef64E:
.seh_proc _ZN3std3sys9backtrace28__rust_begin_short_backtrace17h8d3554b6567cef64E
	sub	rsp, 40
	.seh_stackalloc 40
	.seh_endprologue
	call	rcx
	nop
	#APP
	#NO_APP
	.seh_startepilogue
	add	rsp, 40
	.seh_endepilogue
	ret
	.seh_endproc

	.def	_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17hdd5ea432718ad0c1E;
	.scl	3;
	.type	32;
	.endef
	.section	.text,"xr",one_only,_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17hdd5ea432718ad0c1E,unique,3
	.p2align	4
_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17hdd5ea432718ad0c1E:
.seh_proc _ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17hdd5ea432718ad0c1E
	sub	rsp, 40
	.seh_stackalloc 40
	.seh_endprologue
	mov	rcx, qword ptr [rcx]
	call	_ZN3std3sys9backtrace28__rust_begin_short_backtrace17h8d3554b6567cef64E
	xor	eax, eax
	.seh_startepilogue
	add	rsp, 40
	.seh_endepilogue
	ret
	.seh_endproc

	.def	_ZN6r_test4main17haba959300c4c510dE;
	.scl	2;
	.type	32;
	.endef
	.section	.text,"xr",one_only,_ZN6r_test4main17haba959300c4c510dE,unique,4
	.globl	_ZN6r_test4main17haba959300c4c510dE
	.p2align	4
_ZN6r_test4main17haba959300c4c510dE:
.seh_proc _ZN6r_test4main17haba959300c4c510dE
	sub	rsp, 56
	.seh_stackalloc 56
	.seh_endprologue
	mov	dword ptr [rsp + 36], 11
	lea	rax, [rsp + 36]
	mov	qword ptr [rsp + 40], rax
	lea	rax, [rip + _RNvXs9_NtNtNtCs9N2lWLRSIT9_4core3fmt3num3implNtB9_7Display3fmt]
	mov	qword ptr [rsp + 48], rax
	lea	rcx, [rip + anon.e6415d161255c43dc2c05166e7cf7172.1]
	lea	rdx, [rsp + 40]
	call	_RNvNtNtCslk5dvTldH8g_3std2io5stdio6__print
	nop
	.seh_startepilogue
	add	rsp, 56
	.seh_endepilogue
	ret
	.seh_endproc

	.def	main;
	.scl	2;
	.type	32;
	.endef
	.section	.text,"xr",one_only,main,unique,5
	.globl	main
	.p2align	4
main:
.seh_proc main
	sub	rsp, 56
	.seh_stackalloc 56
	.seh_endprologue
	mov	r9, rdx
	movsxd	r8, ecx
	lea	rax, [rip + _ZN6r_test4main17haba959300c4c510dE]
	mov	qword ptr [rsp + 48], rax
	mov	byte ptr [rsp + 32], 0
	lea	rdx, [rip + anon.e6415d161255c43dc2c05166e7cf7172.0]
	lea	rcx, [rsp + 48]
	call	_RNvNtCslk5dvTldH8g_3std2rt19lang_start_internal
	nop
	.seh_startepilogue
	add	rsp, 56
	.seh_endepilogue
	ret
	.seh_endproc

	.section	.rdata,"dr",one_only,anon.e6415d161255c43dc2c05166e7cf7172.0,unique,6
	.p2align	3, 0x0
anon.e6415d161255c43dc2c05166e7cf7172.0:
	.asciz	"\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000"
	.quad	_ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17hdd5ea432718ad0c1E
	.quad	_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h3c899e35677daf87E
	.quad	_ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h3c899e35677daf87E

	.section	.rdata,"dr",one_only,anon.e6415d161255c43dc2c05166e7cf7172.1,unique,7
anon.e6415d161255c43dc2c05166e7cf7172.1:
	.asciz	"\026x after modification: \300\001\n"

Вот что происходит всего с восемью строчками кода. Я полагаю, что основное время затрачивается на этапе THIR, но как-то руки не доходили проверить, да и не знаю как.

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

Это первое, что пришло в голову, даже недочитав до этого места, ведь хорошо известно, что проект с сотней-другой крейтов при компиляции после cargo clean занимает многоядерник на всю катушку:

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

1
23 ...

Информация

В рейтинге
2 388-й
Откуда
Ahrensburg, Schleswig-Holstein, Германия
Дата рождения
Зарегистрирован
Активность