[Libreoffice-commits] .: bridges/source

Tor Lillqvist tml at kemper.freedesktop.org
Wed Jan 19 16:41:55 PST 2011


 bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm |  328 +++++++++++++++++++
 bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx |   86 +---
 bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx  |  109 ++----
 bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk |    4 
 bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx |  173 +++-------
 5 files changed, 453 insertions(+), 247 deletions(-)

New commits:
commit 9425bdeae4d493fc491aebb704ad620b9119b891
Author: Tor Lillqvist <tlillqvist at novell.com>
Date:   Thu Jan 20 02:36:55 2011 +0200

    More hacking on the wntmscx bridge, still far from ready
    
    See asmbits.asm for some general comments and pointers to useful
    information.

diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm b/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm
new file mode 100644
index 0000000..29e75ff
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm
@@ -0,0 +1,328 @@
+; -*- Mode: text; tab-width: 8; indent-tabs-mode: nil comment-column: 32; comment-start: "; " comment-start-skip: "; *" -*-
+
+;*************************************************************************
+;*
+;* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+;* 
+;* Copyright 2000, 2011 Oracle and/or its affiliates.
+;*
+;* OpenOffice.org - a multi-platform office productivity suite
+;*
+;* This file is part of OpenOffice.org.
+;*
+;* OpenOffice.org is free software: you can redistribute it and/or modify
+;* it under the terms of the GNU Lesser General Public License version 3
+;* only, as published by the Free Software Foundation.
+;*
+;* OpenOffice.org is distributed in the hope that it will be useful,
+;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;* GNU Lesser General Public License version 3 for more details
+;* (a copy is included in the LICENSE file that accompanied this code).
+;*
+;* You should have received a copy of the GNU Lesser General Public License
+;* version 3 along with OpenOffice.org.  If not, see
+;* <http://www.openoffice.org/license.html>
+;* for a copy of the LGPLv3 License.
+;*
+;************************************************************************
+
+; Emacs asm-mode is not really ideal for the convention in this
+; file. So I use text-mode with custom comment syntax... not really
+; ideal either. Maybe I should just re-format this to match asm-mode's
+; conventions?
+
+; NOTE: EXTREMELY UNFINISHED, I KNOW. WORK IN PROGRESS.
+
+; I really don't have a good high-level understanding of the big
+; picture and what the actual task of the C++/UNO bridge is yet... I
+; should debug the x86 version and see what is actually going on to
+; get an understanding.
+
+; This is in a separate file for x86-64 as MSVC doesn't have in-line
+; assembly for x64. The code here is still partly just a crude copy of
+; the in-line x86 code from ../msvc_win32_intel that is totally
+; pointless on x64. But parts have been properly changed into x64
+; calling convention and might even work.
+
+; Random web links and other documentation about low-level
+; implementation details for the C++/UNO bridge on x64 Windows kept
+; here:
+
+; Caolan's "Lazy Hackers Guide To Porting" is useful:
+; http://wiki.services.openoffice.org/wiki/Lazy_Hackers_Guide_To_Porting
+
+; As for details about the x64 Windows calling convention, register
+; usage, stack usage, exception handling etc, the official
+; documentation (?) on MSDN is a bit fragmented and split up into a
+; needlessly large number of short pages. But still:
+; http://msdn.microsoft.com/en-us/library/7kcdt6fy%28v=VS.90%29.aspx
+
+; Also see Raymond Chen's blog post:
+; http://blogs.msdn.com/b/oldnewthing/archive/2004/01/14/58579.aspx
+
+; This one is actually more readable: "Improving Automated Analysis of
+; Windows x64 Binaries": 
+; http://www.uninformed.org/?v=4&a=1
+
+; The bridge uses dynamic code generation. For exception handling and
+; unwinding to work across that (as I assume we want?), one apparently
+; needs to use either RtlAddFunctionTable() or
+; RtlInstallFunctionTableCallback(). See Windows SDK documentation.
+
+; Random interesting discussion threads:
+; http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/300bd6d3-9381-4d2d-8129-e48b392c05d8
+
+; Ken Johnson's blog http://www.nynaeve.net/ has much interesting
+; information, for instance:
+; http://www.nynaeve.net/?p=11
+
+; From <typelib/typeclass.h>
+typelib_TypeClass_VOID = 0
+typelib_TypeClass_CHAR = 1
+typelib_TypeClass_BOOLEAN = 2
+typelib_TypeClass_BYTE = 3
+typelib_TypeClass_SHORT = 4
+typelib_TypeClass_UNSIGNED_SHORT = 5
+typelib_TypeClass_LONG = 6
+typelib_TypeClass_UNSIGNED_LONG = 7
+typelib_TypeClass_HYPER = 8
+typelib_TypeClass_UNSIGNED_HYPER = 9
+typelib_TypeClass_FLOAT = 10
+typelib_TypeClass_DOUBLE = 11
+typelib_TypeClass_ENUM = 15
+
+extrn __copyConstruct :  proc
+extrn __destruct :  proc
+extrn cpp_mediate:   proc
+
+.code
+
+; First we have three code snippets that aren't real functions, but
+; "naked" (in x86 calling convention parlance) functions jumped to
+; from code generated in C++. 
+
+; I think that for x64 Windows we shouldn't be jumping so wildly from
+; generated code snippets into fixed code snippets here. "Procedures"
+; should be continuous in memory, or the unwinding information will be
+; broken. (For dynamically generated code, that is dynamically
+; registered unwind information, obviously.)
+
+; So instead of generating jumps into here, we should just make the
+; C++ code copy the machine code that these three "naked" functions
+; compile after the snippet it is generating. Of course, that means
+; the code here needs to be position independent, or (eek) that we
+; would need to come up with some home-brewed minimal relocation
+; mechanism.
+
+; Jumped to from code generated in except.cxx: ObjectFunction::ObjectFunction()
+
+copyConstruct proc
+        ; ObjectFunction this already on stack
+        push    [rsp+8]         ; source exc object this
+        push    rcx             ; exc object
+        call    __copyConstruct
+        add     rsp, 12         ; + ObjectFunction this
+        ret     4
+copyConstruct endp
+
+; Ditto
+
+destruct proc
+        ; ObjectFunction this already on stack
+        push    rcx             ; exc object
+        call    __destruct
+        add     rsp, 8              ; + ObjectFunction this
+        ret
+destruct endp
+
+; Jumped to from code generated in cpp2uno.cxx:codeSnippet()
+
+cpp_vtable_call proc
+        sub     rsp, 8          ; space for immediate return type
+        push    rsp
+        push    rdx             ; vtable offset
+        push    rax             ; function index
+        mov     rax, rsp
+        add     rax, 20
+        push    rax             ; original stack ptr
+
+        call    cpp_mediate
+        add     rsp, 16
+
+        cmp     rax, typelib_TypeClass_FLOAT
+        je      Lfloat
+        cmp     rax, typelib_TypeClass_DOUBLE
+        je      Ldouble
+        cmp     rax, typelib_TypeClass_HYPER
+        je      Lhyper
+        cmp     eax, typelib_TypeClass_UNSIGNED_HYPER
+        je      Lhyper
+        ; rest is eax
+        pop     rax
+        add     rsp, 4
+        ret
+Lhyper:
+        pop     rax
+        pop     rdx
+        ret
+Lfloat:
+        fld     dword ptr [rsp]
+        add     rsp, 8
+        ret
+Ldouble:
+        fld     qword ptr [rsp]
+        add     rsp, 8
+        ret
+cpp_vtable_call endp
+
+; Called from uno2cpp.cxx
+
+; This one is now hopefully proper x64 Windows code following the
+; appropriate conventions and might actually work.
+
+; void callVirtualMethod(                       ; location on entry
+;    void * pAdjustedThisPtr,                   ; rcx
+;    sal_Int32 nVtableIndex,                    ; rdx
+;    void * pReturn,                            ; r8
+;    typelib_TypeClass eReturnTypeClass,        ; r9
+;    sal_Int64 * pStack,                        ; ((4+1)*8)[rsp]
+;    sal_Int32 nStack                           ; ((5+1)*8)[rsp]
+;    sal_uInt64 *pGPR,                          ; ((6+1)*8)[rsp]
+;    double *pFPR)                              ; ((7+1)*8)[rsp]
+
+callVirtualMethod proc frame
+        ; Prologue
+        mov     ((3+1)*8)[rsp], r9
+        mov     ((2+1)*8)[rsp], r8
+        mov     ((0+1)*8)[rsp], rcx
+        push    rsi
+        .pushreg rsi
+        push    rdi
+        .pushreg rdi
+
+        ; Our stack frame size is 24 qwords (space for 20 parameters
+        ; to pass, plus the two pushed registers rsi and rdi, plus
+        ; return address, rounded up to 16 bytes)
+
+        sub     rsp, (20+1)*8
+        .allocstack (20+1)*8
+        .endprolog
+
+        ; Stack parameters first
+
+        ; nStack is number of qwords of stack space (including spilled
+        ; registers). If four or less, 4 is passed in anyway to make
+        ; code here simpler.
+
+        mov     rcx, ((24+5)*8)[rsp] ; nStack
+        sub     rcx, 4
+        jle     Lxmmregs
+
+        mov     rsi, ((24+4)*8)[rsp] ; pStack
+        add     rsi, 32
+        lea     rdi, 32[rsp]
+        rep movsq
+
+Lxmmregs:
+        ; Parameters passed in XMM registers
+
+        ; We don't bother checking which actually needed, if any.
+        mov     rax, ((24+7)*8)[rsp] ; pFPR
+        movsd   xmm0, qword ptr [rax]
+        movsd   xmm1, qword ptr 8[rax]
+        movsd   xmm2, qword ptr 16[rax]
+        movsd   xmm3, qword ptr 24[rax]
+
+        ; Prepare pointer to function to call
+        mov     rcx, ((24+0)*8)[rsp]
+        mov     r12, [rcx]      ; pAdjustedThisPtr->vtable
+        shl     rdx, 3          ; nVtableIndex *= 8
+        add     r12, rdx
+
+        ; Fill parameters passed in general purpose registers
+        mov     rax, ((24+6)*8)[rsp] ; pGPR
+        mov     rcx, (0*8)[rax]
+        mov     rdx, (1*8)[rax]
+        mov     r8, (2*8)[rax]
+        mov     r9, (3*8)[rax]
+
+        call    qword ptr [r12]
+
+        ; Test return type
+        mov     r9, ((24+3)*8)[rsp]
+        cmp     r9, typelib_TypeClass_VOID
+        je      Lepilog
+
+        ; int32
+        cmp     r9, typelib_TypeClass_LONG
+        je      Lint32
+        cmp     r9, typelib_TypeClass_UNSIGNED_LONG
+        je      Lint32
+        cmp     r9, typelib_TypeClass_ENUM
+        je      Lint32
+
+        ; int8
+        cmp     r9, typelib_TypeClass_BOOLEAN
+        je      Lint8
+        cmp     r9, typelib_TypeClass_BYTE
+        je      Lint8
+
+        ; int16
+        cmp     r9, typelib_TypeClass_CHAR
+        je      Lint16
+        cmp     r9, typelib_TypeClass_SHORT
+        je      Lint16
+        cmp     r9, typelib_TypeClass_UNSIGNED_SHORT
+        je      Lint16
+
+        ; int64
+        cmp     r9, typelib_TypeClass_HYPER
+        je      Lint64
+        cmp     r9, typelib_TypeClass_UNSIGNED_HYPER
+        je      Lint64
+
+        ; float
+        cmp     r9, typelib_TypeClass_FLOAT
+        je      Lfloat
+
+        ; double
+        cmp     r9, typelib_TypeClass_DOUBLE
+        je      Ldouble
+
+        jmp     Lepilog        ; no simple type
+
+Lint8:
+        mov     byte ptr [r8], al
+        jmp     Lepilog
+
+Lint16:
+        mov     word ptr [r8], ax
+        jmp     Lepilog
+
+Lint32:
+        mov     dword ptr [r8], eax
+        jmp     Lepilog
+
+Lint64:
+        mov     qword ptr [r8], rax
+        jmp     Lepilog
+
+Lfloat:
+        movss   dword ptr [r8], xmm0
+        jmp     Lepilog
+
+Ldouble:
+        movsd   qword ptr [r8], xmm0
+
+Lepilog:
+        ; Epilogue
+        add     rsp, (20+1)*8
+        pop     rdi
+        pop     rsi
+        ret
+callVirtualMethod endp
+    
+end
+
+; vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
index 708cf8c..d3a445b 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
@@ -87,13 +87,11 @@ static inline typelib_TypeClass cpp2uno_call(
         }
     }
 
-    // stack space
-    OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
     // parameters
     void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
     void ** pCppArgs = pUnoArgs + nParams;
     // indizes of values this have to be converted (interface conversion cpp<=>uno)
-    sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
+    sal_Int64 * pTempIndizes = (sal_Int64 *)(pUnoArgs + (2 * nParams));
     // type descriptions for reconversions
     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
 
@@ -116,7 +114,7 @@ static inline typelib_TypeClass cpp2uno_call(
             case typelib_TypeClass_HYPER:
             case typelib_TypeClass_UNSIGNED_HYPER:
             case typelib_TypeClass_DOUBLE:
-                pCppStack += sizeof(sal_Int32); // extra long
+                pCppStack += sizeof(sal_Int64); // extra qword
                 break;
             default:
                 break;
@@ -155,7 +153,7 @@ static inline typelib_TypeClass cpp2uno_call(
                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
             }
         }
-        pCppStack += sizeof(sal_Int32); // standard parameter length
+        pCppStack += sizeof(sal_Int64); // standard parameter length
     }
 
     // ExceptionHolder
@@ -240,12 +238,10 @@ static inline typelib_TypeClass cpp2uno_call(
 }
 
 //==================================================================================================
-static typelib_TypeClass __cdecl cpp_mediate(
+typelib_TypeClass __cdecl cpp_mediate(
     void ** pCallStack, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
     sal_Int64 * pRegisterReturn /* space for register return */ )
 {
-    OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
-
     // pCallStack: ret adr, this, [ret *], params
     void * pThis = static_cast< char * >(pCallStack[1]) - nVtableOffset;
     bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
@@ -287,8 +283,8 @@ static typelib_TypeClass __cdecl cpp_mediate(
             typelib_MethodParameter aParam;
             aParam.pTypeRef =
                 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
-            aParam.bIn		= sal_True;
-            aParam.bOut		= sal_False;
+            aParam.bIn      = sal_True;
+            aParam.bOut     = sal_False;
 
             eRet = cpp2uno_call(
                 pCppI, aMemberDescr.get(),
@@ -361,74 +357,28 @@ static typelib_TypeClass __cdecl cpp_mediate(
     return eRet;
 }
 
-//==================================================================================================
-/**
- * is called on incoming vtable calls
- * (called by asm snippets)
- */
-static __declspec(naked) void __cdecl cpp_vtable_call(void)
-{
-__asm
-    {
-        sub		esp, 8		// space for immediate return type
-        push	esp
-        push    edx         // vtable offset
-        push	eax			// function index
-        mov		eax, esp
-        add		eax, 20
-        push	eax			// original stack ptr
-
-        call	cpp_mediate
-        add		esp, 16
-
-        cmp		eax, typelib_TypeClass_FLOAT
-        je		Lfloat
-        cmp		eax, typelib_TypeClass_DOUBLE
-        je		Ldouble
-        cmp		eax, typelib_TypeClass_HYPER
-        je		Lhyper
-        cmp		eax, typelib_TypeClass_UNSIGNED_HYPER
-        je		Lhyper
-        // rest is eax
-        pop		eax
-        add		esp, 4
-        ret
-Lhyper:
-        pop		eax
-        pop		edx
-        ret
-Lfloat:
-        fld		dword ptr [esp]
-        add		esp, 8
-        ret
-Ldouble:
-        fld		qword ptr [esp]
-        add		esp, 8
-        ret
-    }
-}
+extern void *cpp_vtable_call;
 
 //==================================================================================================
-int const codeSnippetSize = 16;
+int const codeSnippetSize = 28;
 
 unsigned char * codeSnippet(
     unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset)
 {
     unsigned char * p = code;
-    OSL_ASSERT(sizeof (sal_Int32) == 4);
-    // mov eax, functionIndex:
+    // mov rax, functionIndex:
     *p++ = 0xB8;
-    *reinterpret_cast< sal_Int32 * >(p) = functionIndex;
-    p += sizeof (sal_Int32);
-    // mov edx, vtableOffset:
+    *reinterpret_cast< sal_Int64 * >(p) = functionIndex;
+    p += sizeof (sal_Int64);
+    // mov rdx, vtableOffset:
     *p++ = 0xBA;
-    *reinterpret_cast< sal_Int32 * >(p) = vtableOffset;
-    p += sizeof (sal_Int32);
-    // jmp rel32 cpp_vtable_call:
+    *reinterpret_cast< sal_Int64 * >(p) = vtableOffset;
+    p += sizeof (sal_Int64);
+    // jmp rel64 cpp_vtable_call:
     *p++ = 0xE9;
-    *reinterpret_cast< sal_Int32 * >(p)
-        = ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int32);
-    p += sizeof (sal_Int32);
+    *reinterpret_cast< sal_Int64 * >(p)
+        = ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int64);
+    p += sizeof (sal_Int64);
     OSL_ASSERT(p - code <= codeSnippetSize);
     return code + codeSnippetSize;
 }
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 409cb95..a658ed5 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
@@ -102,8 +102,8 @@ typedef hash_map< OUString, void *, OUStringHash, equal_to< OUString > > t_strin
 //==================================================================================================
 class RTTInfos
 {
-    Mutex				_aMutex;
-    t_string2PtrMap		_allRTTI;
+    Mutex               _aMutex;
+    t_string2PtrMap     _allRTTI;
 
     static OUString toRawName( OUString const & rUNOname ) throw ();
 public:
@@ -238,9 +238,9 @@ ObjectFunction::ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpF
     *pCode++ = 0x68;
     *(void **)pCode = this;
     pCode += sizeof(void *);
-    // jmp rel32 fpFunc
+    // jmp rel64 fpFunc
     *pCode++ = 0xe9;
-    *(sal_Int32 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int32);
+    *(sal_Int64 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int64);
 }
 //__________________________________________________________________________________________________
 ObjectFunction::~ObjectFunction() throw ()
@@ -249,56 +249,34 @@ ObjectFunction::~ObjectFunction() throw ()
 }
 
 //==================================================================================================
-static void * __cdecl __copyConstruct( void * pExcThis, void * pSource, ObjectFunction * pThis )
+void * __cdecl __copyConstruct( void * pExcThis, void * pSource, ObjectFunction * pThis )
     throw ()
 {
     ::uno_copyData( pExcThis, pSource, pThis->_pTypeDescr, cpp_acquire );
     return pExcThis;
 }
 //==================================================================================================
-static void * __cdecl __destruct( void * pExcThis, ObjectFunction * pThis )
+void * __cdecl __destruct( void * pExcThis, ObjectFunction * pThis )
     throw ()
 {
     ::uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release );
     return pExcThis;
 }
 
-// these are non virtual object methods; there is no this ptr on stack => ecx supplies _this_ ptr
 
-//==================================================================================================
-static __declspec(naked) void copyConstruct() throw ()
-{
-    __asm
-    {
-        // ObjectFunction this already on stack
-        push [esp+8]  // source exc object this
-        push ecx	  // exc object
-        call __copyConstruct
-        add  esp, 12  // + ObjectFunction this
-        ret  4
-    }
-}
-//==================================================================================================
-static __declspec(naked) void destruct() throw ()
-{
-    __asm
-    {
-        // ObjectFunction this already on stack
-        push ecx	// exc object
-        call __destruct
-        add  esp, 8 // + ObjectFunction this
-        ret
-    }
-}
+// These are machine code snippets in asmbits.asm
+
+extern void *copyConstruct;
+extern void *destruct;
 
 //==================================================================================================
 struct ExceptionType
 {
-    sal_Int32			_n0;
-    type_info *			_pTypeInfo;
-    sal_Int32			_n1, _n2, _n3, _n4;
-    ObjectFunction *	_pCopyCtor;
-    sal_Int32			_n5;
+    sal_Int32           _n0;
+    type_info *         _pTypeInfo;
+    sal_Int32           _n1, _n2, _n3, _n4;
+    ObjectFunction *    _pCopyCtor;
+    sal_Int32           _n5;
 
     inline ExceptionType( typelib_TypeDescription * pTypeDescr ) throw ()
         : _n0( 0 )
@@ -315,11 +293,11 @@ struct ExceptionType
 //==================================================================================================
 struct RaiseInfo
 {
-    sal_Int32			_n0;
-    ObjectFunction *	_pDtor;
-    sal_Int32			_n2;
-    void *				_types;
-    sal_Int32			_n3, _n4;
+    sal_Int32           _n0;
+    ObjectFunction *    _pDtor;
+    sal_Int32           _n2;
+    void *              _types;
+    sal_Int32           _n3, _n4;
 
     RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
     ~RaiseInfo() throw ();
@@ -332,9 +310,6 @@ RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
     , _n3( 0 )
     , _n4( 0 )
 {
-    // a must be
-    OSL_ENSURE( sizeof(sal_Int32) == sizeof(ExceptionType *), "### pointer size differs from sal_Int32!" );
-
     typelib_CompoundTypeDescription * pCompTypeDescr;
 
     // info count
@@ -346,10 +321,10 @@ RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
     }
 
     // info count accompanied by type info ptrs: type, base type, base base type, ...
-    _types = ::rtl_allocateMemory( sizeof(sal_Int32) + (sizeof(ExceptionType *) * nLen) );
-    *(sal_Int32 *)_types = nLen;
+    _types = ::rtl_allocateMemory( sizeof(sal_Int64) + (sizeof(ExceptionType *) * nLen) );
+    *(sal_Int64 *)_types = nLen;
 
-    ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
+    ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1);
 
     sal_Int32 nPos = 0;
     for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
@@ -361,8 +336,8 @@ RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
 //__________________________________________________________________________________________________
 RaiseInfo::~RaiseInfo() throw ()
 {
-    ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
-    for ( sal_Int32 nTypes = *(sal_Int32 *)_types; nTypes--; )
+    ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1);
+    for ( sal_Int32 nTypes = *(sal_Int64 *)_types; nTypes--; )
     {
         delete ppTypes[nTypes];
     }
@@ -374,8 +349,8 @@ RaiseInfo::~RaiseInfo() throw ()
 //==================================================================================================
 class ExceptionInfos
 {
-    Mutex			_aMutex;
-    t_string2PtrMap	_allRaiseInfos;
+    Mutex           _aMutex;
+    t_string2PtrMap _allRaiseInfos;
 
 public:
     static void * getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
@@ -486,14 +461,10 @@ void mscx_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
     void * pCppExc = alloca( pTypeDescr->nSize );
     ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
 
-    // a must be
-    OSL_ENSURE(
-        sizeof(sal_Int32) == sizeof(void *),
-        "### pointer size differs from sal_Int32!" );
-    DWORD arFilterArgs[3];
+    ULONG_PTR arFilterArgs[3];
     arFilterArgs[0] = MSVC_magic_number;
-    arFilterArgs[1] = (DWORD)pCppExc;
-    arFilterArgs[2] = (DWORD)ExceptionInfos::getRaiseInfo( pTypeDescr );
+    arFilterArgs[1] = (ULONG_PTR)pCppExc;
+    arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTypeDescr );
 
     // destruct uno exception
     ::uno_any_destruct( pUnoExc, 0 );
@@ -514,13 +485,9 @@ int mscx_filterCppException(
     if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
         return EXCEPTION_CONTINUE_SEARCH;
     
-#if _MSC_VER < 1300 // MSVC -6
-    bool rethrow = (pRecord->NumberParameters < 3 ||
-                    pRecord->ExceptionInformation[ 2 ] == 0);
-#else
     bool rethrow = __CxxDetectRethrow( &pRecord );
     OSL_ASSERT( pRecord == pPointers->ExceptionRecord );
-#endif
+
     if (rethrow && pRecord == pPointers->ExceptionRecord)
     {
         // hack to get msvcrt internal _curexception field:
@@ -532,14 +499,12 @@ int mscx_filterCppException(
             // crt\src\mtdll.h:
             // offsetof (_tiddata, _curexception) -
             // offsetof (_tiddata, _tpxcptinfoptrs):
-#if _MSC_VER < 1300
-            0x18 // msvcrt,dll
-#elif _MSC_VER < 1310
-            0x20 // msvcr70.dll
-#elif _MSC_VER < 1400
-            0x24 // msvcr71.dll
+#if _MSC_VER < 1500
+            error, this compiler version is not supported
+#elif _MSC_VER < 1600
+            0x48 // msvcr90.dll
 #else
-            0x28 // msvcr80.dll
+            error, please find value for this compiler version
 #endif
             );
     }
@@ -548,7 +513,7 @@ int mscx_filterCppException(
         return EXCEPTION_CONTINUE_SEARCH;
     
     if (pRecord->NumberParameters == 3 &&
-//  		pRecord->ExceptionInformation[ 0 ] == MSVC_magic_number &&
+//          pRecord->ExceptionInformation[ 0 ] == MSVC_magic_number &&
         pRecord->ExceptionInformation[ 1 ] != 0 &&
         pRecord->ExceptionInformation[ 2 ] != 0)
     {
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
index d8e760c..44ea288 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
@@ -54,7 +54,8 @@ SLOFILES= \
     $(SLO)$/cpp2uno.obj		\
     $(SLO)$/uno2cpp.obj		\
     $(SLO)$/dllinit.obj		\
-    $(SLO)$/except.obj
+    $(SLO)$/except.obj		\
+    $(SLO)$/asmbits.obj
 
 NOOPTFILES= \
     $(SLO)$/except.obj
@@ -80,4 +81,3 @@ DEF1NAME=$(SHL1TARGET)
 # --- Targets ------------------------------------------------------
 
 .INCLUDE :  target.mk
-
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx
index 8e8d2df..b22601b 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx
@@ -47,106 +47,52 @@ using namespace ::com::sun::star::uno;
 namespace
 {
 
+// As "long" is 32 bit also in x64 Windows we don't use "longs" in names
+// to indicate pointer-sized stack slots etc like in the other x64 archs,
+// but "qword" as in ml64.
+
 //==================================================================================================
-inline static void callVirtualMethod(
+// In asmbits.asm
+extern void callVirtualMethod(
     void * pAdjustedThisPtr, sal_Int32 nVtableIndex,
-    void * pRegisterReturn, typelib_TypeClass eReturnTypeClass,
-    sal_Int32 * pStackLongs, sal_Int32 nStackLongs )
-{
-    // parameter list is mixed list of * and values
-    // reference parameters are pointers
+    void * pReturn, typelib_TypeClass eReturnTypeClass,
+    sal_Int64 * pStack, sal_Int32 nStack,
+    sal_uInt64 *pGPR,
+    double *pFPR);
 
-    OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" );
-    OSL_ENSURE( (sizeof(void *) == 4) &&
-                 (sizeof(sal_Int32) == 4), "### unexpected size of int!" );
-    
-__asm
+#if OSL_DEBUG_LEVEL > 1
+inline void callVirtualMethodwrapper(
+    void * pAdjustedThisPtr, sal_Int32 nVtableIndex,
+    void * pReturn, typelib_TypeDescriptionReference * pReturnTypeRef,
+    sal_Int64 * pStack, sal_Int32 nStack,
+    sal_uInt64 *pGPR, sal_uInt32 nGPR,
+    double *pFPR, sal_uInt32 nFPR)
+{
+    // Let's figure out what is really going on here
     {
-        mov		eax, nStackLongs
-        test	eax, eax
-        je		Lcall
-        // copy values
-        mov		ecx, eax
-        shl		eax, 2			 // sizeof(sal_Int32) == 4
-        add		eax, pStackLongs // params stack space
-Lcopy:	sub		eax, 4
-        push	dword ptr [eax]
-        dec		ecx
-        jne		Lcopy
-Lcall:
-        // call
-        mov		ecx, pAdjustedThisPtr
-        push	ecx				// this ptr
-        mov		edx, [ecx]		// pvft
-        mov		eax, nVtableIndex
-        shl		eax, 2			// sizeof(void *) == 4
-        add		edx, eax
-        call	[edx]			// interface method call must be __cdecl!!!
-
-        // register return
-        mov		ecx, eReturnTypeClass
-        cmp		ecx, typelib_TypeClass_VOID
-        je		Lcleanup
-        mov		ebx, pRegisterReturn
-// int32
-        cmp		ecx, typelib_TypeClass_LONG
-        je		Lint32
-        cmp		ecx, typelib_TypeClass_UNSIGNED_LONG
-        je		Lint32
-        cmp		ecx, typelib_TypeClass_ENUM
-        je		Lint32
-// int8
-        cmp		ecx, typelib_TypeClass_BOOLEAN
-        je		Lint8
-        cmp		ecx, typelib_TypeClass_BYTE
-        je		Lint8
-// int16
-        cmp		ecx, typelib_TypeClass_CHAR
-        je		Lint16
-        cmp		ecx, typelib_TypeClass_SHORT
-        je		Lint16
-        cmp		ecx, typelib_TypeClass_UNSIGNED_SHORT
-        je		Lint16
-// float
-        cmp		ecx, typelib_TypeClass_FLOAT
-        je		Lfloat
-// double
-        cmp		ecx, typelib_TypeClass_DOUBLE
-        je		Ldouble
-// int64
-        cmp		ecx, typelib_TypeClass_HYPER
-        je		Lint64
-        cmp		ecx, typelib_TypeClass_UNSIGNED_HYPER
-          je		Lint64
-        jmp		Lcleanup // no simple type
-Lint8:
-        mov		byte ptr [ebx], al
-        jmp		Lcleanup
-Lint16:
-        mov		word ptr [ebx], ax
-        jmp		Lcleanup
-Lfloat:
-        fstp	dword ptr [ebx]
-        jmp		Lcleanup
-Ldouble:
-        fstp	qword ptr [ebx]
-        jmp		Lcleanup
-Lint64:
-        mov		dword ptr [ebx], eax
-        mov		dword ptr [ebx+4], edx
-        jmp		Lcleanup
-Lint32:
-        mov		dword ptr [ebx], eax
-        jmp		Lcleanup
-Lcleanup:
-        // cleanup stack (obsolete though because of function)
-        mov		eax, nStackLongs
-        shl		eax, 2			// sizeof(sal_Int32) == 4
-        add		eax, 4			// this ptr
-        add		esp, eax
+        fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
+        for ( unsigned int i = 0; i < nGPR; ++i )
+            fprintf( stderr, "0x%lx, ", pGPR[i] );
+        fprintf( stderr, "\nFPR's (%d): ", nFPR );
+        for ( unsigned int i = 0; i < nFPR; ++i )
+            fprintf( stderr, "%f, ", pFPR[i] );
+        fprintf( stderr, "\nStack (%d): ", nStack );
+        for ( unsigned int i = 0; i < nStack; ++i )
+            fprintf( stderr, "0x%lx, ", pStack[i] );
+        fprintf( stderr, "\n" );
     }
+
+    callVirtualMethod( pAdjustedThisPtr, nVtableIndex,
+                       pReturn, pReturnTypeRef->eTypeClass,
+                       pStack, nStack,
+                       pGPR,
+                       pFPR);
 }
 
+#define callVirtualMethod callVirtualMethodwrapper
+
+#endif
+
 //==================================================================================================
 static void cpp_call(
     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
@@ -156,16 +102,33 @@ static void cpp_call(
     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) throw ()
 {
     // max space for: [complex ret ptr], values|ptr ...
-    char * pCppStack		= (char *)alloca( sizeof(sal_Int32) + (nParams * sizeof(sal_Int64)) );
-    char * pCppStackStart	= pCppStack;
+    // (but will be used less - some of the values will be in pGPR and pFPR)
+    sal_uInt64 *pStack = (sal_uInt64 *) alloca( (nParams + 3) * sizeof(sal_uInt64) );
+    sal_uInt64 *pStackStart = pStack;
+
+    // Parameters to be passed in registers stored here
+    sal_uInt64 pGPR[4];
+    sal_uInt32 nGPR = 0;
+    double pFPR[4];
+    sal_uInt32 nFPR = 0;
+
+    if (nParams > 20)
+    {
+
+    }
+
+
+    char * pCppStack        = (char *)alloca( sizeof(sal_Int64) + (nParams * sizeof(sal_Int64)) );
+    char * pCppStackStart   = pCppStack;
     
-    // return
+    // Return
     typelib_TypeDescription * pReturnTypeDescr = 0;
     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
     
     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
     
+    bool bSimpleReturn = true;
     if (pReturnTypeDescr)
     {
         if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
@@ -186,15 +149,15 @@ static void cpp_call(
 
     // stack space
 
-    OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
+    OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" );
     // args
-    void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
+    void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
     // indizes of values this have to be converted (interface conversion cpp<=>uno)
     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
     // type descriptions for reconversions
     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
     
-    sal_Int32 nTempIndizes   = 0;
+    sal_Int32 nTempIndizes = 0;
     
     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
     {
@@ -214,7 +177,7 @@ static void cpp_call(
             case typelib_TypeClass_HYPER:
             case typelib_TypeClass_UNSIGNED_HYPER:
             case typelib_TypeClass_DOUBLE:
-                pCppStack += sizeof(sal_Int32); // extra long
+                pCppStack += sizeof(sal_Int64); // extra qword
                 break;
             default:
                 break;
@@ -254,7 +217,7 @@ static void cpp_call(
                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
             }
         }
-        pCppStack += sizeof(sal_Int32); // standard parameter length
+        pCppStack += sizeof(sal_Int64); // standard parameter length
     }
 
     __try
@@ -264,8 +227,8 @@ static void cpp_call(
             reinterpret_cast< void ** >(pThis->getCppI()) + aVtableSlot.offset,
             aVtableSlot.index,
             pCppReturn, pReturnTypeDescr->eTypeClass,
-            (sal_Int32 *)pCppStackStart,
-            (pCppStack - pCppStackStart) / sizeof(sal_Int32) );
+            (sal_Int64 *)pCppStackStart,
+            (pCppStack - pCppStackStart) / sizeof(sal_Int64) );
     }
     __except (CPPU_CURRENT_NAMESPACE::mscx_filterCppException(
                   GetExceptionInformation(),
@@ -376,8 +339,8 @@ void unoInterfaceProxyDispatch(
             typelib_MethodParameter aParam;
             aParam.pTypeRef =
                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
-            aParam.bIn		= sal_True;
-            aParam.bOut		= sal_False;
+            aParam.bIn      = sal_True;
+            aParam.bOut     = sal_False;
             
             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );


More information about the Libreoffice-commits mailing list