[Arm64EC] Refer to dllimport'ed functions correctly.
commita6ac968360183013affa8cb372bd5b80cba00ac9
authorEli Friedman <efriedma@quicinc.com>
Thu, 20 Oct 2022 22:06:20 +0000 (20 15:06 -0700)
committerEli Friedman <efriedma@quicinc.com>
Thu, 20 Oct 2022 22:08:56 +0000 (20 15:08 -0700)
treedfb7811921508a566ce49563fa4867f45d2db576
parentf01702752af84661cc9d1cec4ec508530dd9e2ec
[Arm64EC] Refer to dllimport'ed functions correctly.

Arm64EC has two different ways to refer to dllimport'ed functions in an
object file. One is using the usual __imp_ prefix, the other is using an
Arm64EC-specific prefix __imp_aux_. As far as I can tell, if a function
is in an x64 DLL, __imp_aux_ refers to the actual x64 address, while
__imp_ points to some linker-generated code that calls the exit thunk.
So __imp_aux_ is used to refer to the address in non-call contexts,
while __imp_ is used for calls to avoid the indirect call checker.

There's one twist to this, though: if an object refers to a symbol using
the __imp_aux_ prefix, the object file's symbol table must also contain
the symbol with the usual __imp_ prefix. The symbol doesn't actually
have to be used anywhere, it just has to exist; otherwise, the linker's
symbol lookup in x64 import libraries doesn't work correctly. Currently,
this is handled by emitting a .globl __imp_foo directive; we could try
to design some better way to handle this.

One minor quirk I haven't figured out: apparently, in Arm64EC mode, MSVC
prefers to use a linker-synthesized stub to call dllimport'ed functions,
instead of branching directly. The linker stub appears to do the same
thing that inline code would do, so not sure if it's just a code-size
optimization, or if the synthesized stub can actually do something other
than just load from the import table in some circumstances.

Differential Revision: https://reviews.llvm.org/D136202
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
llvm/lib/Target/AArch64/AArch64Subtarget.cpp
llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
llvm/test/CodeGen/AArch64/arm64ec-dllimport.ll [new file with mode: 0644]