1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
// license:BSD-3-Clause
// copyright-holders:Couriersud
#include "ppmf.h"
#if PPMF_USE_MAME_DELEGATES
#include "../../util/delegate.cpp"
#else
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpmf-conversions"
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
namespace plib {
void mfp_raw<ppmf_type::INTERNAL_ITANIUM>::convert_to_generic(generic_function &func, mfp_generic_class *&object) const
{
// apply the "this" delta to the object first
// NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult,cppcoreguidelines-pro-type-reinterpret-cast)
auto *o_p_delta = reinterpret_cast<mfp_generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
// if the low bit of the vtable index is clear, then it is just a raw function pointer
if ((m_function & 1) == 0)
{
// NOLINTNEXTLINE(performance-no-int-to-ptr,cppcoreguidelines-pro-type-reinterpret-cast)
func = reinterpret_cast<generic_function>(m_function);
}
else
{
// otherwise, it is the byte index into the vtable where the actual function lives
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta);
if (compile_info::abi_vtable_function_descriptors::value)
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
func = reinterpret_cast<generic_function>(uintptr_t(vtable_base + m_function - 1));
else
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
func = *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
}
object = o_p_delta;
}
void mfp_raw<ppmf_type::INTERNAL_ARM>::convert_to_generic(generic_function &func, mfp_generic_class *&object) const
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
object = reinterpret_cast<mfp_generic_class *>(reinterpret_cast<std::uint8_t *>(object) + (m_this_delta >> 1));
if ((m_this_delta & 1) == 0)
{
// NOLINTNEXTLINE(performance-no-int-to-ptr,cppcoreguidelines-pro-type-reinterpret-cast)
func = reinterpret_cast<generic_function>(m_function);
}
else
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object) + m_function;
if (compile_info::abi_vtable_function_descriptors::value)
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
func = reinterpret_cast<generic_function>(uintptr_t(vtable_base));
else
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
func = *reinterpret_cast<generic_function *>(vtable_base);
}
}
struct unknown_base_equiv_novtdisp { mfp_raw<ppmf_type::INTERNAL_MSC>::generic_function fptr; int thisdisp, vptrdisp; };
void mfp_raw<ppmf_type::INTERNAL_MSC>::convert_to_generic(generic_function &func, mfp_generic_class *&object) const
{
//printf("%lx, %lx, %lx, %lx %lx\n", m_function, m_this_delta, m_vptr_offs, m_vt_index, m_size);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto *byteptr = reinterpret_cast<std::uint8_t *>(object);
// test for pointer to member function cast across virtual inheritance relationship
//if ((sizeof(unknown_base_equiv) == m_size) && m_vt_index)
if ((sizeof(unknown_base_equiv) == m_size) || (sizeof(unknown_base_equiv_novtdisp) == m_size))
{
// add index from "this" pointer to location of vptr. This actually is an index,
// it needs to be multiplied by sizeof(void *)
byteptr += (m_vptr_index * static_cast<ptrdiff_t>(sizeof(void *)));
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(byteptr);
// and add offset to virtual base from vtable
if (sizeof(unknown_base_equiv) == m_size)
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
byteptr += *reinterpret_cast<int const *>(vptr + m_vt_index);
}
// add "this" pointer displacement if present in the pointer to member function
if (sizeof(single_base_equiv) < m_size)
byteptr += m_this_delta;
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
object = reinterpret_cast<mfp_generic_class *>(byteptr);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,performance-no-int-to-ptr)
auto const *funcx = reinterpret_cast<std::uint8_t const *>(m_function);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,performance-no-int-to-ptr)
func = reinterpret_cast<generic_function>(std::uintptr_t(funcx));
}
} // namespace plib
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
#endif
|