Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:43

0001 // Copyright 2016 Klemens Morgenstern, Antony Polukhin
0002 //
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 // For more information, see http://www.boost.org
0008 
0009 #ifndef BOOST_DLL_DETAIL_CTOR_DTOR_HPP_
0010 #define BOOST_DLL_DETAIL_CTOR_DTOR_HPP_
0011 
0012 #include <boost/dll/config.hpp>
0013 #ifdef BOOST_HAS_PRAGMA_ONCE
0014 # pragma once
0015 #endif
0016 
0017 #include <boost/dll/detail/aggressive_ptr_cast.hpp>
0018 #include <boost/dll/detail/get_mem_fn_type.hpp>
0019 
0020 #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows
0021 #   include <boost/dll/detail/demangling/msvc.hpp>
0022 #else
0023 #   include <boost/dll/detail/demangling/itanium.hpp>
0024 #endif
0025 
0026 
0027 namespace boost { namespace dll { namespace detail {
0028 
0029 /*!
0030  * This class stores a constructor.
0031  *
0032  * In some compilers there are several constructors in code, which may include an allocating one.
0033  * This can be used if the imported class shall be put on the heap, which is why the class provied both types.
0034  */
0035 template<typename Signature>
0036 struct constructor;
0037 
0038 template<typename Class, typename ...Args>
0039 struct constructor<Class(Args...)> {
0040     typedef typename detail::get_mem_fn_type<Class, void(Args...)>::mem_fn standard_t;
0041     typedef Class*(*allocating_t)(Args...);
0042 
0043 
0044     //! The standard, i.e. not allocating constructor. @warning May differ with the compiler. Use @ref constructor::call_standard instead.
0045     standard_t standard;
0046     //! The allocating constructor.  @warning May differ with the compiler. Use @ref constructor::call_allocating instead.
0047     allocating_t allocating;
0048 
0049     //! Call the standard constructor
0050     void call_standard  (Class * const ptr, Args...args){ (ptr->*standard)(static_cast<Args>(args)...); }
0051 
0052     //! Call the deleting destructor
0053     Class * call_allocating(Args...args){ return allocating(static_cast<Args>(args)...); }
0054 
0055 
0056     //! True if a allocating constructor could be loaded.
0057     bool has_allocating() const { return allocating != nullptr; }
0058 
0059     //! True if a standard constructor could be loaded.
0060     bool has_standard() const { return standard != nullptr; }
0061 
0062     //! False if neither the allocating nor the standard constructor is available.
0063     bool is_empty() const { return (allocating == nullptr) && (standard == nullptr) ; }
0064 
0065     constructor() = delete;
0066     constructor(const constructor &) = default;
0067 
0068     explicit constructor(standard_t standard, allocating_t allocating = nullptr)
0069         : standard(standard)
0070         , allocating(allocating)
0071     {}
0072 };
0073 
0074 
0075 
0076 template <typename Class>
0077 struct destructor {
0078 #if !defined(_WIN32)
0079     typedef void(*type)(Class* const);
0080 #elif !defined(_WIN64)
0081     typedef void(__thiscall * type)(Class* const);
0082 #else
0083     typedef void(__cdecl * type)(Class* const);
0084 #endif
0085 
0086     typedef type standard_t;
0087     typedef type deleting_t;
0088 
0089     //! The standard, i.e. not deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_standard instead.
0090     standard_t standard;
0091     //! The deleting destructor. @warning May differ with the compiler. Use @ref destructor::call_deallocating instead.
0092     deleting_t deleting;
0093 
0094     //! Call the standard constructor
0095     void call_standard(Class * const ptr){ standard(ptr); }
0096 
0097     //! Call the deleting destructor
0098     void call_deleting(Class * const ptr){ deleting(ptr); }
0099 
0100     //! True if a deleting destructor could be loaded.
0101     bool has_deleting() const { return deleting != nullptr; }
0102 
0103     //! True if a standard destructor could be loaded.
0104     bool has_standard() const { return standard != nullptr; }
0105 
0106     //! False if neither the deleting nor the standard destructor is available.
0107     bool is_empty() const { return (deleting == nullptr) && (standard == nullptr) ; }
0108     destructor() = delete;
0109 
0110     //! Copy destructor.
0111     destructor(const destructor &) = default;
0112 
0113     //! Construct it from both the standard destructor and the allocating destructor
0114     explicit destructor(const standard_t &standard, const deleting_t &deleting = nullptr)
0115         : standard(standard)
0116         , deleting(deleting)
0117     {}
0118 };
0119 
0120 #if defined(_MSC_VER) // MSVC, Clang-cl, and ICC on Windows
0121 
0122 template<typename Signature, typename Lib>
0123 constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) {
0124     typedef typename constructor<Signature>::standard_t standard_t;
0125     standard_t ctor = lib.template get<standard_t>(ct);
0126     return constructor<Signature>(ctor);
0127 }
0128 
0129 template<typename Class, typename Lib>
0130 destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) {
0131     typedef typename destructor<Class>::standard_t standard_t;
0132     //@apolukhin That does NOT work this way with MSVC-14 x32 via memcpy. The x64 is different.
0133     //standard_t dtor = &lib.template get< typename boost::remove_pointer<standard_t>::type >(dt);
0134     void * buf = &lib.template get<unsigned char>(dt);
0135     standard_t dtor;
0136     std::memcpy(&dtor, &buf, sizeof(dtor));
0137     return destructor<Class>(dtor);
0138 }
0139 
0140 #else
0141 
0142 template<typename Signature, typename Lib>
0143 constructor<Signature> load_ctor(Lib & lib, const mangled_storage_impl::ctor_sym & ct) {
0144     typedef typename constructor<Signature>::standard_t   stand;
0145     typedef typename constructor<Signature>::allocating_t alloc;
0146 
0147     stand s = nullptr;
0148     alloc a = nullptr;
0149 
0150     //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor
0151 
0152     if (!ct.C1.empty())
0153     {
0154         //the only way this works on mingw/win.
0155         //For some reason there is always an 0xA in the following poniter, which screws with the this pointer.
0156         void *buf = &lib.template get<unsigned char>(ct.C1);
0157         std::memcpy(&s, &buf, sizeof(void*));
0158     }
0159     if (!ct.C3.empty())
0160     {
0161         void *buf = &lib.template get<unsigned char>(ct.C3);
0162         std::memcpy(&a, &buf, sizeof(void*));
0163     }
0164 
0165     return constructor<Signature>(s,a);
0166 }
0167 
0168 template<typename Class, typename Lib>
0169 destructor<Class> load_dtor(Lib & lib, const mangled_storage_impl::dtor_sym & dt) {
0170     typedef typename destructor<Class>::standard_t stand;
0171     typedef typename destructor<Class>::deleting_t delet;
0172 
0173     stand s = nullptr;
0174     delet d = nullptr;
0175 
0176     //see here for the abi http://mentorembedded.github.io/cxx-abi/abi.html#mangling-special-ctor-dtor
0177     if (!dt.D1.empty()) {
0178         s = &lib.template get< typename boost::remove_pointer<stand>::type >(dt.D1);
0179     }
0180 
0181     if (!dt.D0.empty()) {
0182         d = &lib.template get< typename boost::remove_pointer<delet>::type >(dt.D0);
0183     }
0184 
0185     return destructor<Class>(s,d);
0186 
0187 }
0188 
0189 #endif
0190 
0191 }}} // namespace boost::dll::detail
0192 
0193 #endif /* BOOST_DLL_DETAIL_CTOR_DTOR_HPP_ */