summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/ppmf.cpp
blob: 85088b256380412ecd7f8e8501d193ff30724e2a (plain) (blame)
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