Page MenuHomePhabricator

[ARM64EC 8/?] Implement ARM64EC "thunk" calling conventions
Needs ReviewPublic

Authored by efriedma on Jun 1 2022, 12:39 PM.
This revision needs review, but there are no reviewers specified.

Details

Reviewers
None
Summary

Part of initial Arm64EC patchset.

A key part of Arm64EC is the presence of "thunks"; bits of code that translate between the x64 calling convention, and the ARM64 calling convention. To lower these, we need to emit calls in a unique way.

This patch adds two calling conventions: one for each side of a thunk. The native side of the thunk just uses the ARM64 calling convention, with the called function stored in x9. The x64 side uses the x64 calling convention with the registers renamed:

- RAX -> X8
- RCX - >X0
- RDX -> X1
- RBX -> X27
- RSP -> SP
- RBP -> FP
- RSI -> X25
- RDI -> X26
- R8  -> X2
- R9  -> X3
- R10 -> X4
- R11 -> X5
- R12 -> X19
- R13 -> X20
- R14 -> X21
- R15 -> X22
- XMMn -> Qn

Putting the complete list here because it isn't part of the documentation yet. It's part of the ABI, though, described in winnt.h.

Note that this doesn't deal with variadic functions; we need to do something a bit different for that. (I'm currently thinking we won't actually represent the thunks as "variadic"; we don't need to access any arguments via sp, so we can just treat x0-x5 as the arguments.)

Diff Detail

Event Timeline

efriedma created this revision.Jun 1 2022, 12:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 1 2022, 12:39 PM
efriedma requested review of this revision.Jun 1 2022, 12:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 1 2022, 12:39 PM
dpaoliello added inline comments.
llvm/lib/Target/AArch64/AArch64CallingConvention.td
247–252

I'm not sure that this is correct: x64 doesn't have a way to read half- or single-precision floating point numbers, and (as I understand it) AArch64 half/single-precision floating point register writes don't modify the upper-bits. What happens on x64 when you write an f16/f32 to an XMM register? I assume that it gets sign-extended...

263

I'll get some clarification on this...

dpaoliello added inline comments.Jun 1 2022, 4:16 PM
llvm/include/llvm/IR/CallingConv.h
258

When adding a calling convention, does it not also need to be added to the IR AsmWriter/AsmPrinter?

efriedma added inline comments.Jun 1 2022, 4:23 PM
llvm/lib/Target/AArch64/AArch64CallingConvention.td
247–252

AArch64 half/single float register writes do zero the high bits. x86 is the one that's a bit inconsistent (the behavior of movss depends on whether the source is a register or memory).

In any case, I think the high bits of a floating-point register are undefined in both conventions.

263

I copy-pasted the X86_ThisCall thing from the x86 code. It might be a red herring, though; I just looked at this in clang, and it looks like clang doesn't actually use the X86_ThisCall on x64 Windows, so this doesn't actually do anything, even in the original? I'm sort of confused how it ended up that way. Maybe can just delete it, though.

I probably do need some handling for C++ methods, though, which I haven't implemented yet. (In particular, I need to ensure we emit the arguments for exit thunks for C++ methods in the correct order.)

efriedma added inline comments.Jun 1 2022, 4:26 PM
llvm/include/llvm/IR/CallingConv.h
258

If you don't add it to the asmparser/writer, there's some default handling that just uses the number, I think. But it might be better to give them proper names in IR.

Alternatively, I was thinking about marking the calls using an attribute instead of a calling convention. Which is basically equivalent to using a calling convention, but doesn't consume calling convention numbers. Probably doesn't matter much in practice.

mstorsjo added inline comments.
llvm/lib/Target/AArch64/AArch64CallingConvention.td
263

thiscall (similarly to stdcall, fastcall and vectorcall) are all no-ops on x86_64, they're only a thing on x86_32 windows.

dpaoliello added inline comments.Jun 2 2022, 11:48 AM
llvm/include/llvm/IR/CallingConv.h
258

I think using a calling convention makes more sense, and should avoid these functions being accidentally treated like a normal function.

llvm/lib/Target/AArch64/AArch64CallingConvention.td
263

vectorcall still exists for x64, however Arm64EC currently only supports standard x64 calling convention.

For now, I think we can drop the thiscall special case, but I will double check if it is required (we can always add it back later if so).

dpaoliello added inline comments.Jun 2 2022, 11:50 AM
llvm/lib/Target/AArch64/AArch64CallingConvention.td
215

For comments like these that reference the x64 register, can you please add a note of what the equivalent AArch64 register is?