backend/arm64: Add MSVC C++ ABI devirtualization (#718)

MSVC C++ uses a non-standard ABI definition that must be specially
handled:
https://rants.vastheman.com/2021/09/21/msvc
This commit is contained in:
Wunk 2022-11-15 12:22:47 -08:00 committed by GitHub
parent dd36a52048
commit e23d61d124
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -16,8 +16,16 @@ struct DevirtualizedCall {
u64 this_ptr;
};
// https://rants.vastheman.com/2021/09/21/msvc/
template<auto mfp>
DevirtualizedCall Devirtualize(mcl::class_type<decltype(mfp)>* this_) {
DevirtualizedCall DevirtualizeWindows(mcl::class_type<decltype(mfp)>* this_) {
static_assert(sizeof(mfp) == 8);
return DevirtualizedCall{mcl::bit_cast<u64>(mfp), reinterpret_cast<u64>(this_)};
}
// https://github.com/ARM-software/abi-aa/blob/main/cppabi64/cppabi64.rst#representation-of-pointer-to-member-function
template<auto mfp>
DevirtualizedCall DevirtualizeDefault(mcl::class_type<decltype(mfp)>* this_) {
struct MemberFunctionPointer {
// Address of non-virtual function or index into vtable.
u64 ptr;
@ -34,7 +42,16 @@ DevirtualizedCall Devirtualize(mcl::class_type<decltype(mfp)>* this_) {
u64 vtable = mcl::bit_cast_pointee<u64>(this_ptr);
fn_ptr = mcl::bit_cast_pointee<u64>(vtable + fn_ptr);
}
return {fn_ptr, this_ptr};
return DevirtualizedCall{fn_ptr, this_ptr};
}
template<auto mfp>
DevirtualizedCall Devirtualize(mcl::class_type<decltype(mfp)>* this_) {
#if defined(_WIN32)
return DevirtualizeWindows<mfp>(this_);
#else
return DevirtualizeDefault<mfp>(this_);
#endif
}
} // namespace Dynarmic::Backend::Arm64