summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
authorTor Lillqvist <tlillqvist@novell.com>2011-02-21 09:46:34 +0200
committerTor Lillqvist <tlillqvist@novell.com>2011-02-21 09:46:34 +0200
commit82062268958cfb90a31088de23215989c25583fb (patch)
treeb2a1323a0712e59be2c9ce8f42dba30735b2eed9 /bridges
parent92008e811e7587d71c1d6c33ec88a281b4a86133 (diff)
More work on x64 Windows C++-UNO bridge
Diffstat (limited to 'bridges')
-rwxr-xr-x[-rw-r--r--]bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx259
1 files changed, 174 insertions, 85 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
index e3def617bbd2..2157568ad915 100644..100755
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
@@ -81,92 +81,164 @@ typedef uint32_t rva_t;
///\note the calling convention should not matter since this has no arguments
typedef void generic_function_t();
- struct ptrtomember // _PMD
- {
- typedef __w64 int32_t mdiff_t;
- mdiff_t member_offset;
- mdiff_t vbtable_offset; // -1 if not a virtual base
- mdiff_t vdisp_offset; // offset to the displacement value inside the vbtable
+struct ptrtomember // _PMD
+{
+ typedef __w64 int32_t mdiff_t;
+ mdiff_t member_offset;
+ mdiff_t vbtable_offset; // -1 if not a virtual base
+ mdiff_t vdisp_offset; // offset to the displacement value inside the vbtable
- template<typename T>
- T * operator()(T * const thisptr) const
+ template<typename T>
+ T * operator()(T * const thisptr) const
+ {
+ uintptr_t tp = reinterpret_cast<uintptr_t>(thisptr);
+ uintptr_t ptr = tp + member_offset;
+ if ( vbtable_offset != -1 ) // !(vbtable_offset < 0)
{
- uintptr_t tp = reinterpret_cast<uintptr_t>(thisptr);
- uintptr_t ptr = tp + member_offset;
- if ( vbtable_offset != -1 ) // !(vbtable_offset < 0)
- {
- ptr += *reinterpret_cast<mdiff_t*>( static_cast<intptr_t>(vdisp_offset + *reinterpret_cast<mdiff_t*>(tp + vbtable_offset)) )
- + vbtable_offset;
- }
- return reinterpret_cast<T*>(ptr);
+ ptr += *reinterpret_cast<mdiff_t*>( static_cast<intptr_t>(vdisp_offset + *reinterpret_cast<mdiff_t*>(tp + vbtable_offset)) )
+ + vbtable_offset;
}
- };
+ return reinterpret_cast<T*>(ptr);
+ }
+};
+
+struct eobject
+{
+ typedef void (* dtor_ptr )(eobject*);
+ typedef void (* ctor_ptr )(eobject*, eobject*);
+ typedef void (* ctor_ptr2)(eobject*, eobject*, int);
+};
struct catchabletype
{
- /** is simple type */
- uint32_t memmoveable : 1;
- /** catchable as reference only */
- uint32_t refonly : 1;
- /** class with virtual base */
- uint32_t hasvirtbase : 1;
- /** offset to the type descriptor */
- rva_t typeinfo;
-
- /** catch type instance location within a thrown object */
- ptrtomember thiscast;
- /** size of the simple type or offset into buffer of \c this pointer for catch object */
- uint32_t object_size;
-
- union
- {
- rva_t copyctor;
- rva_t copyctor2;
- };
+ /** is simple type */
+ uint32_t memmoveable : 1;
+ /** catchable as reference only */
+ uint32_t refonly : 1;
+ /** class with virtual base */
+ uint32_t hasvirtbase : 1;
+ /** offset to the type descriptor */
+ rva_t typeinfo;
+
+ /** catch type instance location within a thrown object */
+ ptrtomember thiscast;
+ /** size of the simple type or offset into buffer of \c this pointer for catch object */
+ uint32_t object_size;
+
+ union
+ {
+ rva_t copyctor;
+ rva_t copyctor2;
};
+};
#pragma pack(push, 4)
- struct catchabletypearray
- {
- uint32_t size;
- rva_t type[1];
- };
+struct catchabletypearray
+{
+ uint32_t size;
+ rva_t type[1];
+};
#pragma pack(pop)
#pragma pack(push, 4)
- struct throwinfo
- {
- typedef exception_disposition __cdecl forwardcompathandler_t(...);
-
- /* 0x00 */ uint32_t econst : 1;
- /* 0x00 */ uint32_t evolatile : 1;
- /* 0x00 */ uint32_t : 1;
- /* 0x00 */ uint32_t e8 : 1;
- /* 0x04 */ rva_t exception_dtor;
- /* 0x08 */ rva_t forwardcompathandler;
- /* 0x0C */ rva_t catchabletypearray; ///< types able to catch the exception.
- };
+struct throwinfo
+{
+ typedef exception_disposition __cdecl forwardcompathandler_t(...);
+
+ /* 0x00 */ uint32_t econst : 1;
+ /* 0x00 */ uint32_t evolatile : 1;
+ /* 0x00 */ uint32_t : 1;
+ /* 0x00 */ uint32_t e8 : 1;
+ /* 0x04 */ rva_t exception_dtor;
+ /* 0x08 */ rva_t forwardcompathandler;
+ /* 0x0C */ rva_t catchabletypearray; ///< types able to catch the exception.
+};
#pragma pack(pop)
- /// This type represents the catch clause
- struct ehandler
+/// This type represents the catch clause
+struct ehandler
+{
+ // union { uint32_t adjectives; void * ptr; };
+ uint32_t isconst : 1;
+ uint32_t isvolatile : 1;
+ uint32_t isunaligned : 1;// guess it is not used on x86
+ uint32_t isreference : 1;
+
+ uint32_t :27;
+ uint32_t ishz : 1;
+
+ /** offset to the type descriptor of this catch object */
+ /*0x04*/ rva_t typeinfo; // dispType
+ /*0x08*/ int eobject_bpoffset; // dispCatchObj
+ /** offset to the catch clause funclet */
+ /*0x0C*/ rva_t handler; // dispOfHandler
+ /*0x10*/ uint32_t frame; // dispFrame
+}
+
+// ___BuildCatchObject
+/// 15.3/16 When the exception-declaration specifies a class type, a copy
+/// constructor is used to initialize either the object declared
+/// in the exception-declaration or,
+/// if the exception-declaration does not specify a name,
+/// a temporary object of that type.
+///\note This is the question may we optimize out the last case.
+///\warning If the copy constructor throws an exception, std::unexpected would be called
+void
+ constructcatchobject(
+ cxxregistration * cxxreg,
+ const ehandler * const catchblock,
+ catchabletype * const convertable,
+ const dispatcher_context* const dispatch
+ )
+ const
+{
+ _EH_TRACE_ENTER();
+ // build helper
+ __try {
+ struct typeinfo_t { void* vtbl; void* spare; char name[1]; };
+ enum catchable_info { cidefault, cicomplex, civirtual } cinfo = cidefault;
+
+ const typeinfo_t* ti = catchblock->typeinfo ? dispatch->va<typeinfo_t*>(catchblock->typeinfo) : NULL;
+ if(ti && *ti->name && (catchblock->eobject_bpoffset || catchblock->ishz)){
+ eobject** objplace = catchblock->ishz
+ ? reinterpret_cast<eobject**>(cxxreg)
+ : reinterpret_cast<eobject**>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers);
+ if(catchblock->isreference){
+ // just ref/pointer
+ *objplace = adjust_pointer(get_object(), convertable);
+ }else if(convertable->memmoveable){
+ // POD
+ std::memcpy(objplace, get_object(), convertable->object_size);
+ if(convertable->object_size == sizeof(void*) && *objplace)
+ *objplace = adjust_pointer((void*)*objplace, convertable);
+ }else{
+ // if copy ctor exists, call it; binary copy otherwise
+ if(convertable->copyctor){
+ cinfo = convertable->hasvirtbase ? civirtual : cicomplex;
+ }else{
+ std::memcpy(objplace, (const void*)adjust_pointer(get_object(), convertable), convertable->object_size);
+ }
+ }
+ }
+ // end of build helper
+ if(cinfo != cidefault){
+ eobject* objthis = catchblock->ishz
+ ? reinterpret_cast<eobject*>(cxxreg)
+ : reinterpret_cast<eobject*>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers);
+ void* copyctor = thrown_va(convertable->copyctor);
+ eobject* copyarg = adjust_pointer(get_object(), convertable);
+ if(cinfo == cicomplex)
+ (eobject::ctor_ptr (copyctor))(objthis, copyarg);
+ else
+ (eobject::ctor_ptr2(copyctor))(objthis, copyarg, 1);
+ }
+ }
+ __except(cxxregistration::unwindfilter(static_cast<nt::ntstatus>(_exception_code())))
{
- // union { uint32_t adjectives; void * ptr; };
- uint32_t isconst : 1;
- uint32_t isvolatile : 1;
- uint32_t isunaligned : 1;// guess it is not used on x86
- uint32_t isreference : 1;
-
- uint32_t :27;
- uint32_t ishz : 1;
-
- /** offset to the type descriptor of this catch object */
- /*0x04*/ rva_t typeinfo; // dispType
- /*0x08*/ int eobject_bpoffset; // dispCatchObj
- /** offset to the catch clause funclet */
- /*0x0C*/ rva_t handler; // dispOfHandler
- /*0x10*/ uint32_t frame; // dispFrame
+ nt::exception::inconsistency();
}
+ _EH_TRACE_LEAVE();
+}
#endif // 0
@@ -345,29 +417,43 @@ void * __cdecl destruct(
const int codeSnippetSize = 40;
void GenerateConstructorTrampoline(
- sal_uChar * pCode,
+ unsigned char * code,
typelib_TypeDescription * pTD ) throw ()
{
- // push typelib_TypeDescription pTD
- *pCode++ = 0x68;
- *(void **)pCode = pTD;
- pCode += sizeof(void *);
- // jmp rel64 fpFunc
- *pCode++ = 0xe9;
- *(sal_Int64 *)pCode = (sal_uChar *)&copyConstruct - pCode - sizeof(sal_Int64);
+ unsigned char *p = code;
+
+ // mov r8, pTD
+ *p++ = 0x49; *p++ = 0xB8;
+ *((void **)p) = pTD; p += 8;
+
+ // mov r11, copyConstruct
+ *p++ = 0x49; *p++ = 0xBB;
+ *((void **)p) = &copyConstruct; p += 8;
+
+ // jmp r11
+ *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
+
+ OSL_ASSERT( p < code + codeSnippetSize );
}
void GenerateDestructorTrampoline(
- sal_uChar * pCode,
+ unsigned char * code,
typelib_TypeDescription * pTD ) throw ()
{
+ unsigned char *p = code;
+
// mov rdx, pTD
- *pCode++ = 0x68;
- *(void **)pCode = pTD;
- pCode += sizeof(void *);
- // jmp rel64 fpFunc
- *pCode++ = 0xe9;
- *(sal_Int64 *)pCode = (sal_uChar *)destruct - pCode - sizeof(sal_Int64);
+ *p++ = 0x48; *p++ = 0xBA;
+ *((void **)p) = pTD; p += 8;
+
+ // mov r11, destruct
+ *p++ = 0x49; *p++ = 0xBB;
+ *((void **)p) = &destruct; p += 8;
+
+ // jmp r11
+ *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
+
+ OSL_ASSERT( p < code + codeSnippetSize );
}
// This looks like it is the struct catchabletype above
@@ -390,6 +476,9 @@ struct ExceptionType
, _n3( 0 )
, _n4( pTD->nSize )
{
+ // As _n0 is always initialized to zero, that means the
+ // hasvirtbase flag (see the ONTL catchabletype struct) is
+ // off, and thus the copyctor is of the ctor_ptr kind.
_pTypeInfo = (sal_uInt32) ((sal_uInt64) mscx_getRTTI( pTD->pTypeName ) - pCodeBase);
GenerateConstructorTrampoline( pCode, pTD );
_pCopyCtor = (sal_uInt32) ((sal_uInt64) pCode - pCodeBase);