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

Martin Storsjö via llvm-dev llvm-dev at lists.llvm.org
Fri Apr 26 05:30:26 PDT 2019


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



More information about the llvm-dev mailing list