diff options
author | 2017-02-04 01:23:12 +0100 | |
---|---|---|
committer | 2017-02-05 17:19:53 +0100 | |
commit | 70051f6c1f009bae411d68a8afa229259504e866 (patch) | |
tree | 0c19623b17b546ffe6cba8697aa9ddce687cf00a | |
parent | 427cf984dbcab7584f0f75ed6295d97543422a4a (diff) |
Netlist: It is now possible to have multiple handlers per device ...
... for updates. This will make device implementation more flexible and
faster. A nice side-effect is that there was some minor (<5%)
performance increase already. Each input is now assigned a notification
handler. Currently this is update, but going forward this may be a
custom handler. In addition
- fixed MEMPOOL on OSX
- removed dead code
- avoid bit-rot
- added delegate support for emscripten and arm processors
- added delegate support for VS 2015 x64
[Couriersud]
-rw-r--r-- | src/lib/netlist/build/makefile | 9 | ||||
-rw-r--r-- | src/lib/netlist/devices/net_lib.cpp | 6 | ||||
-rw-r--r-- | src/lib/netlist/devices/nld_am2847.cpp | 7 | ||||
-rw-r--r-- | src/lib/netlist/nl_base.cpp | 151 | ||||
-rw-r--r-- | src/lib/netlist/nl_base.h | 18 | ||||
-rw-r--r-- | src/lib/netlist/nl_config.h | 15 | ||||
-rw-r--r-- | src/lib/netlist/nl_lists.h | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | src/lib/netlist/plib/palloc.cpp | 23 | ||||
-rw-r--r-- | src/lib/netlist/plib/palloc.h | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | src/lib/netlist/plib/pconfig.h | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | src/lib/netlist/plib/ppmf.h | 97 | ||||
-rw-r--r-- | src/lib/netlist/solver/nld_solver.cpp | 1 |
12 files changed, 233 insertions, 116 deletions
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile index 670047a421f..d2b1afa6b36 100644 --- a/src/lib/netlist/build/makefile +++ b/src/lib/netlist/build/makefile @@ -172,15 +172,18 @@ maketree: $(sort $(OBJDIRS)) # Special targets #------------------------------------------------- -.PHONY: clang mingw doc +.PHONY: clang clang-5 mingw doc clang: - $(MAKE) CC=clang++-5.0 LD=clang++-5.0 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors" + $(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors" + +clang-5: + $(MAKE) CC=clang++-5.0 LD=clang++-5.0 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-unreachable-code -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors" # # Mostly done: -Wno-weak-vtables -Wno-cast-align # FIXME: -Wno-weak-vtables -Wno-missing-variable-declarations -Wno-conversion -Wno-exit-time-destructors -# +# FIXME: -Wunreachable-code : False warnings, this a documented clang bug: https://llvm.org/bugs/show_bug.cgi?id=28994 mingw: $(MAKE) LDEXTRAFLAGS="-Wl,--subsystem,console" LIBS= MD=@mkdir.exe SHELL=sh.exe diff --git a/src/lib/netlist/devices/net_lib.cpp b/src/lib/netlist/devices/net_lib.cpp index bc1d7051b39..3fb47772c45 100644 --- a/src/lib/netlist/devices/net_lib.cpp +++ b/src/lib/netlist/devices/net_lib.cpp @@ -15,14 +15,8 @@ #define xstr(s) # s -#if 0 -#define ENTRY1(nic, name, defparam) factory.register_device<nic>( # name, xstr(nic), defparam ); -#define ENTRY(nic, name, defparam) ENTRY1(NETLIB_NAME(nic), name, defparam) -#endif - #define NETLIB_DEVICE_DECL(chip) extern factory::constructor_ptr_t decl_ ## chip; -//#define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (# name, xstr(nic), defparam) ); #define ENTRYX1(nic, name, defparam, decl) factory.register_device( decl (pstring(# name), pstring(xstr(nic)), pstring(defparam)) ); #define ENTRYX(nic, name, defparam) { NETLIB_DEVICE_DECL(nic) ENTRYX1(NETLIB_NAME(nic), name, defparam, decl_ ## nic) } diff --git a/src/lib/netlist/devices/nld_am2847.cpp b/src/lib/netlist/devices/nld_am2847.cpp index be5f75c3774..29a3b2417eb 100644 --- a/src/lib/netlist/devices/nld_am2847.cpp +++ b/src/lib/netlist/devices/nld_am2847.cpp @@ -22,6 +22,8 @@ namespace netlist { } + NETLIB_UPDATEI(); + public: void shift(); @@ -109,6 +111,11 @@ namespace netlist m_last_CP = m_CP(); } + NETLIB_UPDATE(Am2847_shifter) + { + /* do nothing */ + } + inline NETLIB_FUNC_VOID(Am2847_shifter, shift, (void)) { uint32_t out = m_buffer[0] & 1; diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index dfd07bdd8f2..c2e81ee69a2 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -25,31 +25,35 @@ namespace netlist { namespace detail { -#if (USE_MEMPOOL) -static plib::mempool pool(6553600, 64); -void * object_t::operator new (size_t size) -{ - return pool.alloc(size); -} + static plib::mempool *pool() + { + static plib::mempool *s_pool = nullptr; + if (s_pool == nullptr) + s_pool = new plib::mempool(65536, 16); + return s_pool; + } -void object_t::operator delete (void * mem) -{ - if (mem) - pool.free(mem); -} -#else -void * object_t::operator new (size_t size) -{ - return ::operator new(size); -} + void * object_t::operator new (size_t size) + { + void *ret = nullptr; + if ((USE_MEMPOOL)) + ret = pool()->alloc(size); + else + ret = ::operator new(size); + return ret; + } -void object_t::operator delete (void * mem) -{ - if (mem) - ::operator delete(mem); -} -#endif + void object_t::operator delete (void * mem) + { + if (mem) + { + if ((USE_MEMPOOL)) + pool()->free(mem); + else + ::operator delete(mem); + } + } } @@ -361,12 +365,6 @@ void netlist_t::start() /* resolve inputs */ setup().resolve_inputs(); - /* Make sure devices are fully created - now done in register_dev */ - - log().debug("Setting delegate pointers ...\n"); - for (auto &dev : m_devices) - dev->set_delegate_pointer(); - log().verbose("looking for two terms connected to rail nets ..."); for (auto & t : get_device_list<analog::NETLIB_NAME(twoterm)>()) { @@ -391,6 +389,14 @@ void netlist_t::start() else m_solver->post_start(); + for (auto &n : m_nets) + for (auto & term : n->m_core_terms) + { + //core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object()); + core_device_t *dev = &term->device(); + dev->set_default_delegate(*term); + } + } void netlist_t::stop() @@ -427,6 +433,14 @@ void netlist_t::reset() //if (m_solver != nullptr) // m_solver->do_reset(); + std::unordered_map<core_device_t *, bool> m; + + for (auto &d : m_devices) + { + m[d.get()] = d->get_hint_deactivate(); + } + + // Reset all nets once ! for (auto & n : m_nets) n->reset(); @@ -444,15 +458,66 @@ void netlist_t::reset() * INFO: The order here affects power up of e.g. breakout. However, such * variations are explicitly stated in the breakout manual. */ -#if 0 - for (std::size_t i = 0; i < m_devices.size(); i++) + + const unsigned startup_strategy = 1; //! \note make this a parameter + + switch (startup_strategy) { - m_devices[i]->update_dev(); + case 0: + { + std::vector<core_device_t *> d; + std::vector<nldelegate *> t; + log().verbose("Using default startup strategy"); + for (auto &n : m_nets) + for (auto & term : n->m_core_terms) + if (term->m_delegate.has_object()) + { + if (!plib::container::contains(t, &term->m_delegate)) + { + t.push_back(&term->m_delegate); + term->m_delegate(); + } + core_device_t *dev = reinterpret_cast<core_device_t *>(term->m_delegate.object()); + if (!plib::container::contains(d, dev)) + d.push_back(dev); + } + log().verbose("Call update on devices which need parameter update:"); + for (auto & dev : m_devices) + if (dev->needs_update_after_param_change()) + { + if (!plib::container::contains(d, dev.get())) + { + d.push_back(dev.get()); + log().verbose("\t ...{1}", dev->name()); + dev->update_dev(); + } + } + log().verbose("Devices not yet updated:"); + for (auto &dev : m_devices) + if (!plib::container::contains(d, dev.get())) + log().verbose("\t ...{1}", dev->name()); + //x->update_dev(); + } + break; + case 1: // brute force backward + { + std::size_t i = m_devices.size(); + while (i>0) + m_devices[--i]->update_dev(); + } + break; + case 2: // brute force forward + { + for (std::size_t i = 0; i < m_devices.size(); i++) + m_devices[i]->update_dev(); + } + break; } -#else - std::size_t i = m_devices.size(); - while (i>0) - m_devices[--i]->update_dev(); + +#if 1 + /* the above may screw up m_active and the list */ + for (auto &n : m_nets) + n->rebuild_list(); #endif } @@ -594,9 +659,6 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name) , logic_family_t() , netlist_ref(owner) , m_hint_deactivate(false) -#if (!NL_USE_PMF_VIRTUAL) - , m_static_update() -#endif { if (logic_family() == nullptr) set_logic_family(family_TTL()); @@ -607,9 +669,6 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name) , logic_family_t() , netlist_ref(owner.netlist()) , m_hint_deactivate(false) -#if (!NL_USE_PMF_VIRTUAL) - , m_static_update() -#endif { set_logic_family(owner.logic_family()); if (logic_family() == nullptr) @@ -621,11 +680,9 @@ core_device_t::~core_device_t() { } -void core_device_t::set_delegate_pointer() +void core_device_t::set_default_delegate(detail::core_terminal_t &term) { -#if (!NL_USE_PMF_VIRTUAL) - m_static_update.set_base(&core_device_t::update, this); -#endif + term.m_delegate.set(&core_device_t::update, this); } plib::plog_base<NL_DEBUG> &core_device_t::log() @@ -789,7 +846,7 @@ void detail::net_t::update_devs() NL_NOEXCEPT { p.device().m_stat_call_count.inc(); if ((p.state() & mask) != 0) - p.device().update_dev(); + p.m_delegate(); } } @@ -891,6 +948,8 @@ detail::core_terminal_t::core_terminal_t(core_device_t &dev, const pstring &anam , m_net(nullptr) , m_state(*this, "m_state", state) { + //m_delegate.set(&core_device_t::update, &dev); + //m_delegate.set(&core_device_t::update_dev, &dev); } detail::core_terminal_t::~core_terminal_t() diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index d6e177be9c9..3e06144168d 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -455,6 +455,10 @@ namespace netlist core_device_t & m_device; }; + /*! Delegate type for device notification. + * + */ + typedef plib::pmfp<void> nldelegate; // ----------------------------------------------------------------------------- // core_terminal_t @@ -509,6 +513,8 @@ namespace netlist void reset(); + nldelegate m_delegate; + private: net_t * m_net; state_var<state_e> m_state; @@ -1044,14 +1050,16 @@ namespace netlist void do_reset() { reset(); } void set_hint_deactivate(bool v) { m_hint_deactivate = v; } + bool get_hint_deactivate() { return m_hint_deactivate; } - void set_delegate_pointer(); + void set_default_delegate(detail::core_terminal_t &term); /* stats */ nperftime_t m_stat_total_time; nperfcount_t m_stat_call_count; nperfcount_t m_stat_inc_active; + protected: virtual void update() NL_NOEXCEPT { } @@ -1061,11 +1069,7 @@ namespace netlist void do_update() NL_NOEXCEPT { - #if (NL_USE_PMF_VIRTUAL) update(); - #else - m_static_update.call(this); - #endif } plib::plog_base<NL_DEBUG> &log(); @@ -1081,10 +1085,6 @@ namespace netlist private: bool m_hint_deactivate; - - #if (!NL_USE_PMF_VIRTUAL) - plib::pmfp_base<void> m_static_update; - #endif }; // ----------------------------------------------------------------------------- diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index ded567717f9..57b6a03f031 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -95,16 +95,6 @@ using nl_double = double; * approach will be automatically selected. */ -//#define NL_USE_PMF_VIRTUAL 1 - -#ifndef NL_USE_PMF_VIRTUAL - #if PPMF_TYPE == PPMF_TYPE_PMF - #define NL_USE_PMF_VIRTUAL 1 - #else - #define NL_USE_PMF_VIRTUAL 0 - #endif -#endif - //============================================================ // WARNINGS //============================================================ @@ -115,9 +105,4 @@ using nl_double = double; #endif #endif -#ifdef __APPLE__ -#undef USE_MEMPOOL -#define USE_MEMPOOL (0) -#endif - #endif /* NLCONFIG_H_ */ diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h index f0789b909a1..a841db1e084 100644 --- a/src/lib/netlist/nl_lists.h +++ b/src/lib/netlist/nl_lists.h @@ -54,7 +54,7 @@ namespace netlist struct entry_t final { - constexpr entry_t() { } + constexpr entry_t() : m_exec_time(), m_object(nullptr) { } constexpr entry_t(const Time &t, const Element &o) : m_exec_time(t), m_object(o) { } constexpr entry_t(const entry_t &e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { } constexpr entry_t(entry_t &&e) : m_exec_time(e.m_exec_time), m_object(e.m_object) { } diff --git a/src/lib/netlist/plib/palloc.cpp b/src/lib/netlist/plib/palloc.cpp index ceee5a75904..1377edabde5 100644..100755 --- a/src/lib/netlist/plib/palloc.cpp +++ b/src/lib/netlist/plib/palloc.cpp @@ -5,6 +5,8 @@ * */ +#include <algorithm> + #include "pconfig.h" #include "palloc.h" #include "pfmtlog.h" @@ -27,7 +29,7 @@ mempool::~mempool() { fprintf(stderr, "Found block with %d dangling allocations\n", static_cast<int>(b.m_num_alloc)); } - delete b.data; + ::operator delete(b.data); } m_blocks.clear(); } @@ -35,7 +37,7 @@ mempool::~mempool() size_t mempool::new_block() { block b; - b.data = new char[m_min_alloc]; + b.data = static_cast<char *>(::operator new(m_min_alloc)); b.cur_ptr = b.data; b.m_free = m_min_alloc; b.m_num_alloc = 0; @@ -43,10 +45,19 @@ size_t mempool::new_block() return m_blocks.size() - 1; } +size_t mempool::mininfosize() +{ + size_t sinfo = sizeof(mempool::info); + size_t ma = 8; +#ifdef __APPLE__ + ma = 16; +#endif + return ((std::max(m_min_align, sinfo) + ma - 1) / ma) * ma; +} void *mempool::alloc(size_t size) { - size_t rs = (size + sizeof(info) + m_min_align - 1) & ~(m_min_align - 1); + size_t rs = (size + mininfosize() + m_min_align - 1) & ~(m_min_align - 1); for (size_t bn=0; bn < m_blocks.size(); bn++) { auto &b = m_blocks[bn]; @@ -56,7 +67,7 @@ void *mempool::alloc(size_t size) b.m_num_alloc++; auto i = reinterpret_cast<info *>(b.cur_ptr); i->m_block = bn; - auto ret = reinterpret_cast<void *>(b.cur_ptr + sizeof(info)); + auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize()); b.cur_ptr += rs; return ret; } @@ -68,7 +79,7 @@ void *mempool::alloc(size_t size) b.m_free = m_min_alloc - rs; auto i = reinterpret_cast<info *>(b.cur_ptr); i->m_block = bn; - auto ret = reinterpret_cast<void *>(b.cur_ptr + sizeof(info)); + auto ret = reinterpret_cast<void *>(b.cur_ptr + mininfosize()); b.cur_ptr += rs; return ret; } @@ -78,7 +89,7 @@ void mempool::free(void *ptr) { auto p = reinterpret_cast<char *>(ptr); - auto i = reinterpret_cast<info *>(p - sizeof(info)); + auto i = reinterpret_cast<info *>(p - mininfosize()); block *b = &m_blocks[i->m_block]; if (b->m_num_alloc == 0) fprintf(stderr, "Argh .. double free\n"); diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h index 2e4c2809048..02249f09168 100644 --- a/src/lib/netlist/plib/palloc.h +++ b/src/lib/netlist/plib/palloc.h @@ -144,6 +144,7 @@ private: }; size_t new_block(); + size_t mininfosize(); struct info { @@ -151,6 +152,11 @@ private: size_t m_block; }; + size_t m_min_alloc; + size_t m_min_align; + + std::vector<block> m_blocks; + public: mempool(size_t min_alloc, size_t min_align); ~mempool(); @@ -158,10 +164,6 @@ public: void *alloc(size_t size); void free(void *ptr); - size_t m_min_alloc; - size_t m_min_align; - - std::vector<block> m_blocks; }; } diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h index e3870206cbd..e5a98fb5be8 100644..100755 --- a/src/lib/netlist/plib/pconfig.h +++ b/src/lib/netlist/plib/pconfig.h @@ -71,13 +71,13 @@ typedef __int128_t INT128; #define MEMBER_ABI _thiscall #elif defined(__clang__) && defined(__i386__) && defined(_WIN32) #define PHAS_PMF_INTERNAL 0 - #elif defined(EMSCRIPTEN) - #define PHAS_PMF_INTERNAL 0 - #elif defined(__arm__) || defined(__ARMEL__) - #define PHAS_PMF_INTERNAL 0 + #elif defined(__arm__) || defined(__ARMEL__) || defined(__aarch64__) || defined(__MIPSEL__) || defined(__mips_isa_rev) || defined(__mips64) || defined(EMSCRIPTEN) + #define PHAS_PMF_INTERNAL 2 #else #define PHAS_PMF_INTERNAL 1 #endif +#elif defined(_MSC_VER) && defined (_M_X64) + #define PHAS_PMF_INTERNAL 3 #else #define PHAS_PMF_INTERNAL 0 #endif @@ -87,7 +87,7 @@ typedef __int128_t INT128; #endif #ifndef PPMF_TYPE - #if PHAS_PMF_INTERNAL + #if (PHAS_PMF_INTERNAL > 0) #define PPMF_TYPE PPMF_TYPE_INTERNAL #else #define PPMF_TYPE PPMF_TYPE_PMF diff --git a/src/lib/netlist/plib/ppmf.h b/src/lib/netlist/plib/ppmf.h index 03a2a65baa4..a80fbf2ec86 100644..100755 --- a/src/lib/netlist/plib/ppmf.h +++ b/src/lib/netlist/plib/ppmf.h @@ -51,44 +51,82 @@ namespace plib { * It derives a pointer to a member function. */ -#if (PHAS_PMF_INTERNAL) +#if (PHAS_PMF_INTERNAL > 0) class mfp { public: // construct from any member function pointer +#ifdef _MSC_VER + class __single_inheritance si_generic_class; + class generic_class { }; +#else class generic_class; +#endif using generic_function = void (*)(); template<typename MemberFunctionType> mfp(MemberFunctionType mftp) - : m_function(0), m_this_delta(0) + : m_function(0), m_this_delta(0), m_size(sizeof(mfp)) { *reinterpret_cast<MemberFunctionType *>(this) = mftp; } - template<typename FunctionType, typename MemberFunctionType, typename ObjectType> - static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object) + template<typename MemberFunctionType, typename FunctionType, typename ObjectType> + static void get_mfp(MemberFunctionType mftp, FunctionType &func, ObjectType *&object) { mfp mfpo(mftp); //return mfpo.update_after_bind<FunctionType>(object); - return reinterpret_cast<FunctionType>( - mfpo.convert_to_generic(reinterpret_cast<generic_class *>(object))); + generic_function rfunc(nullptr); + generic_class *robject = reinterpret_cast<generic_class *>(object); + mfpo.convert_to_generic(rfunc, robject); + func = reinterpret_cast<FunctionType>(rfunc); + object = reinterpret_cast<ObjectType *>(robject); } private: // extract the generic function and adjust the object pointer - generic_function convert_to_generic(generic_class * object) const + void convert_to_generic(generic_function &func, generic_class *&object) const { - // apply the "this" delta to the object first - generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); + if (PHAS_PMF_INTERNAL == 1) + { + // apply the "this" delta to the object first + generic_class * o_p_delta = reinterpret_cast<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)) + func = reinterpret_cast<generic_function>(m_function); + else + { + // otherwise, it is the byte index into the vtable where the actual function lives + std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta); + func = *reinterpret_cast<generic_function *>(vtable_base + m_function - 1); + } + object = o_p_delta; + } + else if (PHAS_PMF_INTERNAL == 2) + { + if ((m_this_delta & 1) == 0) { + object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); + func = reinterpret_cast<generic_function>(m_function); + } + else + { + object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object)); + + // otherwise, it is the byte index into the vtable where the actual function lives + std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object); + func = *reinterpret_cast<generic_function *>(vtable_base + m_function + m_this_delta - 1); + } + } + else if (PHAS_PMF_INTERNAL == 3) + { + const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (generic_class::*)()); + + func = reinterpret_cast<generic_function>(m_function); + if (m_size == SINGLE_MEMFUNCPTR_SIZE + sizeof(int)) + object = reinterpret_cast<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)) - return reinterpret_cast<generic_function>(m_function); - - // otherwise, it is the byte index into the vtable where the actual function lives - std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta); - return *reinterpret_cast<generic_function *>(vtable_base + m_function - 1); } // actual state @@ -96,6 +134,10 @@ namespace plib { // if even, it's a pointer to the function // if odd, it's the byte offset into the vtable int m_this_delta; // delta to apply to the 'this' pointer + + int m_dummy1; // only used for visual studio x64 + int m_dummy2; + int m_size; }; #endif @@ -107,12 +149,18 @@ namespace plib { class generic_class; #if defined (__INTEL_COMPILER) && defined (_M_X64) // needed for "Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 14.0.2.176 Build 20140130" at least using generic_function = int [((sizeof(void *) + 4 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)]; -#elif defined(_MSC_VER)// all other cases - for MSVC maximum size is one pointer, plus 3 ints; all other implementations seem to be smaller - using generic_function = int [((sizeof(void *) + 3 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)]; +#elif defined(_MSC_VER) // all other cases - for MSVC maximum size is one pointer, plus 3 ints; all other implementations seem to be smaller + using generic_function = int[((sizeof(void *) + 3 * sizeof(int)) + (sizeof(int) - 1)) / sizeof(int)]; #else using generic_function = R (generic_class::*)(Targs...); #endif - pmfp_base() {} + pmfp_base() + { + int *p = reinterpret_cast<int *>(&m_func); + int *e = p + sizeof(generic_function) / sizeof(int); + for (; p < e; p++) + *p = 0; + } template<typename MemberFunctionType, typename O> void set_base(MemberFunctionType mftp, O *object) @@ -130,6 +178,9 @@ namespace plib { } private: generic_function m_func; +#if 0 && defined(_MSC_VER) + int dummy[4]; +#endif }; #elif ((PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) || (PPMF_TYPE == PPMF_TYPE_INTERNAL)) @@ -146,7 +197,9 @@ namespace plib { { #if (PPMF_TYPE == PPMF_TYPE_INTERNAL) using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args); - m_func = reinterpret_cast<generic_function>(plib::mfp::get_mfp<function_ptr>(mftp, object)); + function_ptr func(nullptr); + plib::mfp::get_mfp(mftp, func, object); + m_func = reinterpret_cast<generic_function>(func); #elif (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) R (O::* pFunc)(Targs...) = mftp; m_func = reinterpret_cast<generic_function>((object->*pFunc)); @@ -159,6 +212,7 @@ namespace plib { return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...); } bool is_set() { return m_func != nullptr; } + generic_function get_function() const { return m_func; } private: generic_function m_func; }; @@ -188,6 +242,9 @@ namespace plib { { return this->call(m_obj, std::forward<Targs>(args)...); } + + generic_class *object() const { return m_obj; } + bool has_object() const { return m_obj != nullptr; } private: generic_class *m_obj; }; diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index d2ecf3c5bd2..e769797c42e 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -404,7 +404,6 @@ void NETLIB_NAME(solver)::post_start() } // FIXME ... - ms->set_delegate_pointer(); ms->setup(grp); log().verbose("Solver {1}", ms->name()); |