У меня есть компилятор, написанный с LLVM, и я ищу свое соответствие ABI. Например, мне трудно найти документы спецификации для C ABI в Windows x86 или Linux. И те, которые я нашел, объясняют это с точки зрения RAX/EAX/etc, а не термины IR, которые я могу использовать.
До сих пор, я думаю, я понял, что LLVM обрабатывает агрегаты незаметно, т.е. рассматривает их членов как отдельный параметр каждый. Так, например, в Windows x64, если я хочу обрабатывать агрегат, как говорит документ, мне нужно будет принуждать к одному целому числу этого размера, если 8, 16, 32 или 64 бита. В противном случае пропустите указатель.
Для Windows x86 кажется, что __cdecl и __stdcall не нуждаются ни в каких действиях от меня, так как все параметры передаются в стек. __fastcall говорит, что первые два 32-битных или меньших аргумента передаются по регистру, поэтому мне нужно будет принуждать агрегаты такого размера или меньше. __thiscall передает это в регистре, а остальное - в стеке, поэтому мне кажется, что мне не нужно выполнять какую-либо корректировку.
Для __vectorcall передайте агрегаты не более sizeof (void *) целым числом. Для других агрегатов, если они являются HVAs, затем передаются по значению; else передать значение на x86 или передать указатель на x64.
Это кажется простым (ну, относительно), но в документах LLVM для sext
четко указано "Это указывает генератору кода, что значение параметра или возвращаемое значение должно быть расширено в соответствии с целями ABI (которые обычно 32 бита) вызывающим (для параметра) или вызываемым (для возвращаемого значения).". На страницах Microsoft для соглашений о вызовах x86 ничего не говорится о расширении любой ширины.
И я наблюдал LLVM IR, созданный Clang, который генерирует атрибут byval
в Windows. Понимание, которое я почерпнул из вышеизложенного, никогда не требует использования byval
.
Как бы я опустил различные платформы C ABI на LLVM IR?