PInvoke methods using SetLastError get dropped on Windows x64 full AOT.
This happens because current implementation is doing a direct call to Win32
GetLastError in order to get the value before it get clobbered by the icall
setting the last error value in mono. When running AOT all constructs that tries
to call a method using a direct address will be dropped since that will not work
in full AOT. This results in incomplete compiled libraries causing runtime exceptions
in full AOT.
The fix on Windows x64 is to introduce a new OP code, GET_LAST_ERROR that will
retrieve the last error without clobbering it in the process. This is done by
emitting code reading the value directly from the TEB (thread environment block)
and will be lowered to just a move from the segment register holding the TEB data
structure on Windows x64. This is how GetLastError is doing this as well, but since
we won’t be able to call the method in a “safe” way in full AOT, using the segment
register directly will solve the issue. We use the segment register for accessing TLS,
so we already relying on the TEB structure.
NOTE, this will only be applied to Windows x64, full AOT for now.