mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 23:00:17 +02:00
- Do compiler/architecture checks EARLY, don't waste time doing random configuration stuff if the user can't even compile in the first place - MSVC is unsupported, I assume? So add a check to disallow. There's literally no MSVC or MSC_VER checks anywhere, so... - Rather than using the MSVC architecture definitions, use our own `ARCHITECTURE_arm64` et al. Hijacking existing "standard" definitions is a very bad idea. Also makes it more readable in CMake - Change the x86 host check to `x86|amd64`. Some systems still refer to themselves as x86 despite being 64-bit for... reasons, and I saw one a very long time ago that referred to it as amd64. This should basically never come up, nor is it really relevant given that FEX is for arm64... but it kinda annoyed me so whatever. TODOs: - Should we check `CMAKE_SIZEOF_VOID_P (equal) 64`? I don't think anyone is even trying to compile this thing on armv7 or older, but might as well? maybe? - What's the status of *BSD, Solaris, macOS? Technically macOS does support Wine, not sure about the others. Signed-off-by: crueter <crueter@eden-emu.dev>
83 lines
3.1 KiB
C++
83 lines
3.1 KiB
C++
// SPDX-License-Identifier: MIT
|
|
#pragma once
|
|
|
|
#include <FEXCore/Utils/LogManager.h>
|
|
|
|
#include <cstdint>
|
|
|
|
namespace FEXCore::Utils {
|
|
|
|
/**
|
|
* @brief Casts a class's member function pointer to a raw pointer that we can JIT
|
|
*
|
|
* Has additional validation to ensure we aren't casting a class member that is invalid
|
|
*/
|
|
template<typename PointerToMemberType>
|
|
class MemberFunctionToPointerCast final {
|
|
public:
|
|
MemberFunctionToPointerCast(PointerToMemberType Function) {
|
|
memcpy(&PMF, &Function, sizeof(PMF));
|
|
}
|
|
|
|
uintptr_t GetConvertedPointer() const {
|
|
#ifdef ARCHITECTURE_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_A_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(ARCHITECTURE_arm64)
|
|
// 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_A_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;
|
|
}
|
|
|
|
// Gets the vtable entry position of a virtual member function.
|
|
size_t GetVTableOffset() const {
|
|
#ifdef ARCHITECTURE_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_A_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(ARCHITECTURE_arm64)
|
|
// 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_A_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:
|
|
struct PointerToMember {
|
|
uintptr_t ptr;
|
|
uintptr_t adj;
|
|
};
|
|
|
|
PointerToMember PMF;
|
|
|
|
// Ensure the representation of PointerToMember matches
|
|
static_assert(sizeof(PMF) == sizeof(PointerToMemberType));
|
|
};
|
|
} // namespace FEXCore::Utils
|