Кажется, вы не можете без взлома исходного кода GCC.
Не существует стандартного соглашения о вызовах x86-64, в котором используются неэффективные аргументы стека.
GCC знает, как использовать стандартные вызовысоглашения, в данном случае x86-64 SysV и MS Windows fastcall и vectorcall. (например, __attribute__((ms_abi))
или vectorcall
). Обычно никто не хочет этого;Соглашение о вызовах MS уже достаточно дружественно для упаковщиков или функций с переменными числами. Вы можете использовать это для некоторых функций (управляемых __attribute__
) даже при компиляции для Linux, MacOS, * BSD и т. Д., Если это поможет. Трудно представить вариант использования для чистых аргументов стека.
GCC позволяет вам задавать регистр как фиксированный (никогда не затрагиваемый GCC, как -ffixed-rdi
), закрытый вызовом или сохраненный вызовом. Но использование регистров с передачей аргументов создает неправильный код, а не то, что вам нужно.
например
int foo(int a, int b, int c);
void caller(int x) {
foo(1,2,3);
//foo(4,x,6);
}
скомпилировано gcc9.2 -O3 -fcall-saved-rdi
caller:
push rdi
mov edx, 3
mov esi, 2
pop rdi
jmp foo
Сохраняет / восстанавливает RDI, но не помещает в него 1
перед вызовом foo
.
И не оставляет RDI внепоследовательность прохождения arg и позже поднять другие args. (Я думал, что вы могли бы придумать соглашение о вызовах, в котором все регистры передачи аргументов были fixed
или call-saved
, возможно, заставив GCC вернуться к аргументам стека. Но нет.)