Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arm64: Removes a vtable indirection in syscalls #3327

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions FEXCore/Source/Utils/MemberFunctionToPointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,52 @@ class MemberFunctionToPointerCast final {
public:
MemberFunctionToPointerCast(PointerToMemberType Function) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to lose the assertions. Is that intended?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intended, the asserts get moved to the accessor functions GetConvertedPointer and GetVTableOffset instead.

memcpy(&PMF, &Function, sizeof(PMF));
}

uintptr_t GetConvertedPointer() const {
#ifdef _M_X86_64
// Itanium C++ ABI (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-function-pointers)
// Low bit of ptr specifies if this Member function pointer is virtual or not
// Throw an assert if we were trying to cast a virtual member
LOGMAN_THROW_AA_FMT((PMF.ptr & 1) == 0, "C++ Pointer-To-Member representation didn't have low bit set to 0. Are you trying to cast a virtual member?");
#elif defined(_M_ARM_64 )
#elif defined(_M_ARM_64)
// C++ ABI for the Arm 64-bit Architecture (IHI 0059E)
// 4.2.1 Representation of pointer to member function
// Differs from Itanium specification
LOGMAN_THROW_AA_FMT(PMF.adj == 0, "C++ Pointer-To-Member representation didn't have adj == 0. Are you trying to cast a virtual member?");
#else
#error Don't know how to cast Member to function here. Likely just Itanium
#endif
return PMF.ptr;
}

uintptr_t GetConvertedPointer() const {
// Gets the vtable entry position of a virtual member function.
size_t GetVTableOffset() const {
#ifdef _M_X86_64
// Itanium C++ ABI (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-function-pointers)
// Low bit of ptr specifies if this Member function pointer is virtual or not
// Throw an assert if we are not loading a virtual member.
LOGMAN_THROW_AA_FMT((PMF.ptr & 1) == 1, "C++ Pointer-To-Member representation didn't have low bit set to 1. This cast only works for virtual members.");
return PMF.ptr & ~1ULL;
#elif defined(_M_ARM_64)
// C++ ABI for the Arm 64-bit Architecture (IHI 0059E)
// 4.2.1 Representation of pointer to member function
// Differs from Itanium specification
LOGMAN_THROW_AA_FMT((PMF.adj & 1) == 1, "C++ Pointer-To-Member representation didn't have adj == 1. This cast only works for virtual members.");
return PMF.ptr;
#else
#error Don't know how to cast Member to function here. Likely just Itanium
#endif
}

// Gets the pointer to the vtable entry for the object passed it.
template<typename Class>
uintptr_t GetVTableEntry(Class *VirtualClass) const {
// VTable is always stored at the beginning of a class object.
uintptr_t *VTable = *reinterpret_cast<uintptr_t**>(VirtualClass);

size_t Offset = GetVTableOffset() / sizeof(void*);
return VTable[Offset];
}

private:
Expand Down