openlang

Соглашения о вызовах RISC-V по выводу -O0 или -O2

Соглашения о вызовах запоминаются лучше, когда их вычитывают из настоящего вывода компилятора, а не заучивают по таблице регистров. Хорошее упражнение это функция на C с тремя параметрами int, возвращающая их сумму, скомпилированная под RV32 один раз с -O0 и один раз с -O2.

На -O0 листинг шумный. Функция строит кадр, сохраняет a0, a1 и a2 в стек, загружает их обратно, складывает и оставляет результат в a0 перед ret. На -O2 всё сжимается до двух инструкций add и ret. Соглашение то же, листинг совсем другой, и в этом сравнении весь смысл. Аргументы в обоих случаях приходят в регистрах аргументов, результат в обоих случаях уходит в a0. Остальное было собственной бухгалтерией компилятора.

Дальше пусть функция вызовет другую функцию, и вопрос в том, почему теперь нужно сохранять ra. ret это просто jalr x0, 0(ra), а внутренний call перезаписывает ra.

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

Разговор продолжается 3

Следуя доводам
  1. Ссылка на ответ

    Если хочется соглашения, которое можно потрогать без дизассемблера, C API Lua отлично подходит для разминки. Сначала функция, затем аргументы по порядку кладутся на виртуальный стек, вызывается lua_call(L, nargs, nresults), и результаты занимают их место. Это соглашение о вызовах, расписанное библиотечными вызовами, а ошибка в количестве сразу видна, если напечатать lua_gettop(L). Как ни странно, регистровая версия после этого кажется менее загадочной.

  2. Ссылка на ответ

    Одно ограничение стоит назвать сразу. Стандарт C вообще не говорит ни о регистрах, ни о кадрах стека. Соглашение задаёт ABI платформы, так что листинг учит RISC-V psABI, а не C. Это становится важным, когда кто-то компилирует ту же функцию под другую цель и решает, что изменился язык.

Другие стороны того же вопроса

  1. (x, x) не значит, что обе половины равны

    Ученики раз за разом читают (x, x) в OCaml как «обе половины равны». Это не так, и такой паттерн вообще недопустим. Новичок о…

    Ответы 3ocamlpython