[llvm-dev] Automatically backing up and restoring x18 around function calls on AArch64?

Kristof Beyls via llvm-dev llvm-dev at lists.llvm.org
Fri Apr 26 05:58:11 PDT 2019


Hi Martin,

Doesn't implementing "always back up and restore x18 on any call to any
other function" boil down to having a PCS (procedure call standard)
variation where x18 is caller saved?
I think that in the calling convention code (e.g. see
AArch64CallingConvention.td) when a register is not marked as callee saved
(CalleeSavedRegs), it is implicitly caller saved.
My guess without looking further as to what results in x18 not being
saved/restored around function calls is that it is marked as a Reserved
Register when the -ffixed-x18 command line optoin is used. AFAIU, reserved
registers are not taking into account during liveness analysis, and code to
save/restore it will never be generated.
See e.g. AArch64Subtarget::AArch64Subtarget doing the following:
  if (AArch64::isX18ReservedByDefault(TT))
    ReserveXRegister.set(18);

Apart from how to implement this behaviour: are you sure that always
saving/restoring x18 on function boundaries would be the correct thing to
do?
Couldn't some functions on the windows/WINE side change the value of X18?
In that case you'd want to see the new value of X18 after a function
returns, not restore the value from before the function call?

Thanks,

Kristof

Op vr 26 apr. 2019 om 14:30 schreef Martin Storsjö via llvm-dev <
llvm-dev at lists.llvm.org>:

> Hi,
>
> When using Wine to run Windows ARM64 executables on Linux, there's one
> major ABI incompatibility between the two; Windows treats the x18
> register as the reserved platform register, while it is free to be
> clobbered anywhere in code on Linux.
>
> The Wine code sets up this register before passing control over to the
> Windows executable code, but whenever the Windows code calls a function
> implemented in Wine, this register ends up clobbered.
>
> The initial solution is to compile Wine itself with the -ffixed-x18 flag,
> to treat the x18 register as reserved within Wine, so that no compiler
> generated code touches it. This works fine as long as Wine makes no calls
> to other libraries from the outside Linux distribution - but e.g. as soon
> as any glibc function is called, it can end up clobbered again.
>
> The full, proper solution would of course to be rebuilding one's Linux
> distribution from scratch with -ffixed-x18 on every single library. But
> this is of course pretty much impractical.
>
> My current makeshift workaround for the matter is to reroute calls from
> native Windows code to Wine functions via a relay wrapper, which backs up
> and restores the register. This works in practice, but hasn't been
> accepted upstream, as it is not deemed a correct/complete solution. Also,
> if the emulated Windows API functions do callbacks, the register would
> need to be restored before the callbacks call windows code.
>
> Another idea which was raised in
> https://bugs.winehq.org/show_bug.cgi?id=38780#c13, which disucsses this
> matter, was if it would be possible to make Clang/LLVM always back up and
> restore x18 on any call to any other function, to make sure that the
> register maintains the right value as long as running in Wine code. (One
> concern is that this could end up rather expensive though.)
>
> I didn't really find any straighforward way of starting to implement this
> however. Does anyone here happen to have ideas about how one could either
> implement this, or solve it in another way?
>
> // Martin
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190426/203e3b6e/attachment.html>


More information about the llvm-dev mailing list