C ABI с LLVM

У меня есть компилятор, написанный с 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?

Ответ 1

Я не могу сказать, что я понимаю ваш вопрос на 100%, но стоит отметить, что LLVM IR просто не может представлять все тонкости платформы ABI. Поэтому в инструментальной цепочке Clang это интерфейс, который отвечает за снижение ABI, например, правильное прохождение объектов по значению в функции и т.д.

Взгляните на lib/Basic/Targets.cpp в дереве источников Clang для определений. Детали gory далее находятся в lib/CodeGen/TargetInfo.cpp

Ответ 2

Я закончил взломать внутренние функции Clang CodeGen для выполнения вызова C ABI для меня (поддержка С++ ABI уже была выполнена). Таким образом, вместо того, чтобы повторно реализовать (и перепроверить) их код, я просто повторно использовал их работу. Официально API-интерфейсы CodeGen не являются общедоступными и не предназначены для использования кем-либо, но в этом случае мне удалось заставить его работать. Оказывается, это гораздо менее страшно, чем кажется - многие из классов, таких как LValue/RValue/ReturnValueSlot, являются только обертками на llvm:: Value * с добавлением дополнительной дополнительной семантики.

Более проблематичным будет создание батутов от C ABI до моего собственного ABI. Интерфейс CodeGenFunction не кажется таким же поддающимся этому. Но я думаю, что смогу заставить его работать.

Ответ 3

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