[Libreoffice-commits] core.git: Branch 'aoo/trunk' - 2 commits - bridges/Library_cpp_uno.mk bridges/source qadevOOo/makefile.mk solenv/gbuild

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Sat Jan 26 03:07:57 UTC 2019


 bridges/Library_cpp_uno.mk                           |   21 
 bridges/source/cpp_uno/msvc_win64_x86-64/abi.cxx     |   90 ++
 bridges/source/cpp_uno/msvc_win64_x86-64/abi.hxx     |   46 +
 bridges/source/cpp_uno/msvc_win64_x86-64/call.asm    |  249 +++++++
 bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno.cxx |  592 ++++++++++++++++
 bridges/source/cpp_uno/msvc_win64_x86-64/dllinit.cxx |   54 +
 bridges/source/cpp_uno/msvc_win64_x86-64/except.cxx  |  663 +++++++++++++++++++
 bridges/source/cpp_uno/msvc_win64_x86-64/mscx.hxx    |   53 +
 bridges/source/cpp_uno/msvc_win64_x86-64/uno2cpp.cxx |  365 ++++++++++
 qadevOOo/makefile.mk                                 |    2 
 solenv/gbuild/platform/windows.mk                    |    5 
 11 files changed, 2139 insertions(+), 1 deletion(-)

New commits:
commit 7c094e8e0f0e5e9aa2951207e831160e12031e12
Author:     Damjan Jovanovic <damjan at apache.org>
AuthorDate: Sat Jan 26 01:17:44 2019 +0000
Commit:     Damjan Jovanovic <damjan at apache.org>
CommitDate: Sat Jan 26 01:17:44 2019 +0000

    Fix building with Java 9, which doesn't support "-source 1.5" any more.
    
    Our baseline is Java 7 anyway.
    
    Patch by: me

diff --git a/qadevOOo/makefile.mk b/qadevOOo/makefile.mk
index 98322c699639..2e19a2493676 100644
--- a/qadevOOo/makefile.mk
+++ b/qadevOOo/makefile.mk
@@ -37,7 +37,7 @@ TST:
 
 .IF "$(SOLAR_JAVA)"=="TRUE"	
 .IF "$(ANT_HOME)"!="NO_ANT_HOME"
-ANT_FLAGS+=-Dbuild.source=1.5
+ANT_FLAGS+=-Dbuild.source=1.6
 .IF "$(L10N_framework)"==""
 ALLTAR: ANTBUILD
 .ENDIF
commit 372333a4072053843b2be7521dc393e744422ad9
Author:     Damjan Jovanovic <damjan at apache.org>
AuthorDate: Sat Jan 26 01:15:17 2019 +0000
Commit:     Damjan Jovanovic <damjan at apache.org>
CommitDate: Sat Jan 26 01:15:17 2019 +0000

    Add a preliminary Windows AMD64 UNO-C++ bridge.
    
    Largely based on a mixture of the Linux64 and Win32 bridges,
    with significant AMD64 assembly language also used, it was
    challenging to develop but luckily not too long.
    
    Some links and stacks/register diagrams have been left
    in the code for easy reference.
    
    It compiles and links, but how well it works remains to be tested. At
    least it's no longer holding up the Win64 port. The exception handling
    is the least certain, although stack alignments for the assembly language
    could also have issues.
    
    Also patched gbuild to use the 64 bit MASM for building assembly language
    files on Win64.
    
    Patch by: me

diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk
index e4c214a4bb1a..cec9f012e38d 100644
--- a/bridges/Library_cpp_uno.mk
+++ b/bridges/Library_cpp_uno.mk
@@ -608,6 +608,27 @@ $(eval $(call gb_Library_add_defs,$(COMNAME)_uno,\
 ))
 endif
 
+#########################################################
+else ifeq ($(OS)-$(CPUNAME)-$(COMNAME),WNT-X86_64-mscx)
+#########################################################
+
+$(eval $(call gb_Library_add_exception_objects,$(COMNAME)_uno,\
+	bridges/source/cpp_uno/msvc_win64_x86-64/abi \
+	bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno \
+	bridges/source/cpp_uno/msvc_win64_x86-64/dllinit \
+	bridges/source/cpp_uno/msvc_win64_x86-64/except \
+	bridges/source/cpp_uno/msvc_win64_x86-64/uno2cpp \
+))
+
+$(eval $(call gb_LinkTarget_set_cxx_optimization, \
+	bridges/source/cpp_uno/msvc_win64_x86-64/except \
+, $(gb_COMPILERNOOPTFLAGS) \
+))
+
+$(eval $(call gb_Library_add_asmobjects,$(COMNAME)_uno,\
+	bridges/source/cpp_uno/msvc_win64_x86-64/call \
+))
+
 #####################################
 else
 #####################################
diff --git a/bridges/source/cpp_uno/msvc_win64_x86-64/abi.cxx b/bridges/source/cpp_uno/msvc_win64_x86-64/abi.cxx
new file mode 100644
index 000000000000..a909bdde9c41
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win64_x86-64/abi.cxx
@@ -0,0 +1,90 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#include "abi.hxx"
+
+#include <rtl/ustring.hxx>
+
+using namespace x86_64;
+
+bool x86_64::return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
+{
+    switch ( pTypeRef->eTypeClass )
+    {
+        case typelib_TypeClass_VOID:
+            return false;
+        case typelib_TypeClass_CHAR:
+        case typelib_TypeClass_BOOLEAN:
+        case typelib_TypeClass_BYTE:
+        case typelib_TypeClass_SHORT:
+        case typelib_TypeClass_UNSIGNED_SHORT:
+        case typelib_TypeClass_LONG:
+        case typelib_TypeClass_UNSIGNED_LONG:
+        case typelib_TypeClass_HYPER:
+        case typelib_TypeClass_UNSIGNED_HYPER:
+        case typelib_TypeClass_ENUM:
+            return false;
+        case typelib_TypeClass_FLOAT:
+            return false;
+        case typelib_TypeClass_DOUBLE:
+            return false;
+        case typelib_TypeClass_STRING:
+        case typelib_TypeClass_TYPE:
+        case typelib_TypeClass_ANY:
+        case typelib_TypeClass_TYPEDEF:
+        case typelib_TypeClass_UNION:
+        case typelib_TypeClass_SEQUENCE:
+        case typelib_TypeClass_ARRAY:
+        case typelib_TypeClass_INTERFACE:
+            return true;
+        case typelib_TypeClass_STRUCT:
+        case typelib_TypeClass_EXCEPTION:
+            {
+                typelib_TypeDescription * pTypeDescr = 0;
+                TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
+
+                /* If the struct is larger than 8 bytes, pass it on the stack.  */
+                if ( pTypeDescr->nSize > 8 )
+                {
+                    TYPELIB_DANGER_RELEASE( pTypeDescr );
+                    return false;
+                }
+                else
+                {
+                    TYPELIB_DANGER_RELEASE( pTypeDescr );
+                    return true;
+                }
+            }
+
+        default:
+#if OSL_DEBUG_LEVEL > 1
+            OSL_TRACE( "Unhandled case: pType->eTypeClass == %d\n", pTypeRef->eTypeClass );
+#endif
+            OSL_ASSERT(0);
+    }
+    return 0; /* Never reached.  */
+}
+
diff --git a/bridges/source/cpp_uno/msvc_win64_x86-64/abi.hxx b/bridges/source/cpp_uno/msvc_win64_x86-64/abi.hxx
new file mode 100644
index 000000000000..c65a254f99e0
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win64_x86-64/abi.hxx
@@ -0,0 +1,46 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+
+
+#ifndef _BRIDGES_CPP_UNO_X86_64_ABI_HXX_
+#define _BRIDGES_CPP_UNO_X86_64_ABI_HXX_
+
+// This is an implementation of the Win64 (x64) ABI.
+
+#include <typelib/typedescription.hxx>
+
+namespace x86_64
+{
+
+const sal_uInt32 MAX_REGS = 4;
+
+/** Does function that returns this type use a hidden parameter, or registers?
+
+ The value can be returned either in a hidden 1st parameter (which is a
+ pointer to a structure allocated by the caller), or in registers (rax, rdx
+ for the integers, xmm0, xmm1 for the floating point numbers).
+*/
+bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef );
+
+} // namespace x86_64
+
+#endif // _BRIDGES_CPP_UNO_X86_64_ABI_HXX_
diff --git a/bridges/source/cpp_uno/msvc_win64_x86-64/call.asm b/bridges/source/cpp_uno/msvc_win64_x86-64/call.asm
new file mode 100644
index 000000000000..4e5cd0c326e5
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win64_x86-64/call.asm
@@ -0,0 +1,249 @@
+;
+; Licensed to the Apache Software Foundation (ASF) under one
+; or more contributor license agreements.  See the NOTICE file
+; distributed with this work for additional information
+; regarding copyright ownership.  The ASF licenses this file
+; to you under the Apache License, Version 2.0 (the
+; "License"); you may not use this file except in compliance
+; with the License.  You may obtain a copy of the License at
+; 
+;   http://www.apache.org/licenses/LICENSE-2.0
+; 
+; Unless required by applicable law or agreed to in writing,
+; software distributed under the License is distributed on an
+; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+; KIND, either express or implied.  See the License for the
+; specific language governing permissions and limitations
+; under the License.
+; 
+
+
+typelib_TypeClass_VOID equ 0
+typelib_TypeClass_CHAR equ 1
+typelib_TypeClass_BOOLEAN equ 2
+typelib_TypeClass_BYTE equ 3
+typelib_TypeClass_SHORT equ 4
+typelib_TypeClass_UNSIGNED_SHORT equ 5
+typelib_TypeClass_LONG equ 6
+typelib_TypeClass_UNSIGNED_LONG equ 7
+typelib_TypeClass_HYPER equ 8
+typelib_TypeClass_UNSIGNED_HYPER equ 9
+typelib_TypeClass_FLOAT equ 10
+typelib_TypeClass_DOUBLE equ 11
+typelib_TypeClass_ENUM equ 15
+
+EXTERN cpp_vtable_call: PROC
+
+.CODE
+
+;
+;               | ...                        |
+;               +----------------------------+
+;               | argument 4                 |
+; rbp+48 rsp+40 +----------------------------+ -------
+;               | argument 3, r9/xmm3 home   | ^ shadow
+; rbp+40 rsp+32 +----------------------------+ | space,
+;               | argument 2, r8/xmm2 home   | | guaranteed to be present but uninitialized,
+; rbp+32 rsp+24 +----------------------------+ | we have to copy
+;               | argument 1, rdx/xmm1 home  | | the first 4 parameters there from the registers,
+; rbp+24 rsp+16 +----------------------------+ | to form the continuous array of arguments.
+;               | argument 0, rcx/xmm0 home  | v
+; rbp+16 rsp+08 +----------------------------+ -------
+;               | return address             |
+; rbp+08 rsp--> +----------------------------+
+;               | old rbp                    |
+; rbp---------> +----------------------------+
+;               | pRegisterReturn memory     |
+; rbp-08 -----> +----------------------------+
+;               |                            |
+; rbp-16 -----> +----------------------------+ -------
+;               |                            | ^
+; rbp-24 -----> +----------------------------+ | shadow space
+;               |                            | | for cpp_vtable_call
+; rbp-32 -----> +----------------------------+ |
+;               |                            | |
+; rbp-40 -----> +----------------------------+ |
+;               |                            | v
+; rbp-48 -----> +----------------------------+ -------
+;
+; rax = functionIndex
+; r10 = vtableOffset
+; r11 = &privateSnippetExecutor
+;
+
+privateSnippetExecutor PROC FRAME
+
+	push	rbp
+	mov	rbp, rsp
+	sub	rsp, 48
+	.ALLOCSTACK(48)
+	.ENDPROLOG
+
+	; 4th param: sal_uInt64 *pRegisterReturn 
+	lea r9, -8[rbp]
+
+	; 3rd param: sal_Int32 nVtableOffset
+	mov r8, r10
+
+	; 2nd param: sal_Int32 nFunctionIndex
+	mov rdx, rax
+
+	; 1st param: void ** pCallStack
+	lea rcx, 8[rbp]
+
+	call cpp_vtable_call
+
+	; Integers would return in RAX and floats in XMM0, but both are free for us to clobber,
+	; and the caller knows where to look:
+	mov rax, -8[rbp]
+	movsd xmm0, qword ptr -8[rbp]
+
+	leave
+	ret
+
+privateSnippetExecutor ENDP
+
+
+;
+;               | ...                                         |
+; rbp+64 -----> +---------------------------------------------+
+;               | sal_uInt32 nStack                           |
+; rbp+56 -----> +---------------------------------------------+
+;               | sal_uInt64 *pStack                          |
+; rbp+48 -----> +---------------------------------------------+ -------
+;               | typelib_TypeClass eReturnTypeClass, r9 home | ^ shadow
+; rbp+40 -----> +---------------------------------------------+ | space,
+;               | void *pRegisterReturn,              r8 home | | guaranteed to be present but uninitialized,
+; rbp+32 -----> +---------------------------------------------+ | we have to copy
+;               | sal_Int32 nVtableIndex,            rdx home | | the first 4 parameters there from the registers,
+; rbp+24 -----> +---------------------------------------------+ | to form the continuous array of arguments.
+;               | void* pAdjustedThisPtr,            rcx home | v
+; rbp+16 -----> +---------------------------------------------+ -------
+;               | return address                              |
+; rbp+08 -----> +---------------------------------------------+
+;               | old rbp                                     |
+; rbp --------> +---------------------------------------------+ <---- 16 byte boundary
+;               | (possible 16 byte alignment placeholder)    |
+; rbp-08 -----> +---------------------------------------------+
+;               | (stack for virtual method)                  |
+;               | ...                                         |
+;               | (shadow space for virtual method)           |
+; rsp --------> +---------------------------------------------+ <---- 16 byte boundary
+
+callVirtualMethod PROC FRAME
+
+	push rbp
+	mov rbp, rsp
+	.ENDPROLOG
+
+	; Save our register arguments to the shadow space:
+	mov 16[rbp], rcx
+	mov 24[rbp], rdx
+	mov 32[rbp], r8
+	mov 40[rbp], r9
+
+	; We must maintain the stack aligned to a 16 byte boundary:
+	mov eax, 56[rbp]
+	cmp rax, 0
+	je stackIsEmpty
+	mov r11, rax
+	test rax,1
+	jz stackSizeEven
+	sub rsp, 8
+stackSizeEven:
+	mov r10, 48[rbp]
+	shl rax, 3        ; nStack is in units of sal_uInt64, and sizeof(sal_uInt64) == 8
+	add rax, r10
+
+copyStack:
+	sub rax, 8
+	push [rax]
+	dec r11
+	jne copyStack
+
+	; First 4 args are passed in registers. Floating point args needs to be
+	; in floating point registers, but those are free for us to clobber
+	; anyway, and the callee knows where to look, so put each arg in both
+	; its general purpose and its floating point register:
+	mov rcx, [rsp]
+	movsd xmm0, qword ptr [rsp]
+	mov rdx, 8[rsp]
+	movsd xmm1, qword ptr 8[rsp]
+	mov r8, 16[rsp]
+	movsd xmm2, qword ptr 16[rsp]
+	mov r9, 24[rsp]
+	movsd xmm3, qword ptr 24[rsp]
+	jmp callMethod
+
+stackIsEmpty:
+	sub rsp, 32       ; we still need shadow space
+	
+callMethod:
+	; Find the method pointer
+	mov rax, 16[rbp]
+	mov r10, [rax]    ; pointer to vtable
+	mov r11d, 24[rbp]
+	shl r11, 3        ; sizeof(void*) == 8
+	add r10, r11
+	call qword ptr [r10]
+
+	mov r10d, 40[rbp]
+	cmp r10, typelib_TypeClass_VOID
+	je cleanup
+	cmp r10, typelib_TypeClass_LONG
+	je Lint32
+	cmp r10, typelib_TypeClass_UNSIGNED_LONG
+	je Lint32
+	cmp r10, typelib_TypeClass_ENUM
+	je Lint32
+	cmp r10, typelib_TypeClass_BOOLEAN
+	je Lint8
+	cmp r10, typelib_TypeClass_BYTE
+	je Lint8
+	cmp r10, typelib_TypeClass_CHAR
+	je Lint16
+	cmp r10, typelib_TypeClass_SHORT
+	je Lint16
+	cmp r10, typelib_TypeClass_UNSIGNED_SHORT
+	je Lint16
+	cmp r10, typelib_TypeClass_FLOAT
+	je Lfloat
+	cmp r10, typelib_TypeClass_DOUBLE
+	je Lfloat
+	cmp r10, typelib_TypeClass_HYPER
+	je Lint64
+	cmp r10, typelib_TypeClass_UNSIGNED_HYPER
+	je Lint64
+
+	; https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017
+	; "The same pointer must be returned by the callee in RAX."
+	jmp Lint64
+
+Lint64:
+	mov 32[rbp], rax
+	jmp cleanup
+
+Lint32:
+	mov 32[rbp], eax
+	jmp cleanup
+
+Lint16:
+	mov 32[rbp], ax
+	jmp cleanup
+
+Lint8:
+	mov 32[rbp], al
+	jmp cleanup
+
+Lfloat:
+	movsd qword ptr 32[rbp], xmm0
+	jmp cleanup
+
+cleanup:
+	leave
+	ret
+
+callVirtualMethod ENDP
+
+
+END
diff --git a/bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno.cxx
new file mode 100644
index 000000000000..184b0c735450
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win64_x86-64/cpp2uno.cxx
@@ -0,0 +1,592 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#include <malloc.h>
+
+#include <com/sun/star/uno/genfunc.hxx>
+#include <uno/data.h>
+#include <typelib/typedescription.hxx>
+
+#include "bridges/cpp_uno/shared/bridge.hxx"
+#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
+#include "bridges/cpp_uno/shared/types.hxx"
+#include "bridges/cpp_uno/shared/vtablefactory.hxx"
+
+#include "abi.hxx"
+#include "mscx.hxx"
+
+using namespace ::rtl;
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+
+//==================================================================================================
+
+// Perform the UNO call
+//
+// We must convert the paramaters stored in pCallStack to UNO
+// arguments and call pThis->getUnoI()->pDispatcher.
+//
+// pCallStack:  ret addr, this, [ret *], [params]
+//
+// [ret *] is present when we are returning a structure bigger than 8 bytes
+// Simple types are returned in rax, or xmm0 (fp).
+// Similarly structures <= 8 bytes are in rax, xmm0 as necessary.
+static inline typelib_TypeClass cpp2uno_call(
+    bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
+    const typelib_TypeDescription * pMemberTypeDescr,
+    typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
+    sal_Int32 nParams, typelib_MethodParameter * pParams,
+    void ** pCallStack,
+    sal_uInt64 * pRegisterReturn /* space for register return */ )
+{
+    // return
+    typelib_TypeDescription * pReturnTypeDescr = 0;
+    if (pReturnTypeRef)
+        TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
+
+    void * pUnoReturn = 0;
+    void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
+
+    if ( pReturnTypeDescr )
+    {
+        if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
+        {
+            // complex return via ptr (pCppReturn)
+            pCppReturn = pCallStack[2];
+            ++pCallStack;
+
+            pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
+                           ? alloca( pReturnTypeDescr->nSize )
+                           : pCppReturn ); // direct way
+        }
+        else
+            pUnoReturn = pRegisterReturn; // direct way for simple types
+    }
+
+    // skip to first argument
+    pCallStack += 2;
+
+    // stack space
+    // parameters
+    void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
+    void ** pCppArgs = pUnoArgs + nParams;
+    // indices of values this have to be converted (interface conversion cpp<=>uno)
+    sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
+    // type descriptions for reconversions
+    typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
+
+    sal_Int32 nTempIndizes = 0;
+
+    for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+    {
+        const typelib_MethodParameter & rParam = pParams[nPos];
+        typelib_TypeDescription * pParamTypeDescr = 0;
+        TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
+
+        if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value
+        {
+            pCppArgs[nPos] = pUnoArgs[nPos] = pCallStack++;
+            // no longer needed
+            TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+        }
+        else // ptr to complex value || ref
+        {
+            void *pCppStack;
+            pCppArgs[nPos] = pCppStack = *pCallStack++;
+
+            if (! rParam.bIn) // is pure out
+            {
+                // uno out is unconstructed mem!
+                pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
+                pTempIndizes[nTempIndizes] = nPos;
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
+            }
+            else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
+            {
+                uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
+                                        pCppStack, pParamTypeDescr,
+                                        pThis->getBridge()->getCpp2Uno() );
+                pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
+            }
+            else // direct way
+            {
+                pUnoArgs[nPos] = pCppStack;
+                // no longer needed
+                TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+            }
+        }
+    }
+
+    // ExceptionHolder
+    uno_Any aUnoExc; // Any will be constructed by callee
+    uno_Any * pUnoExc = &aUnoExc;
+
+    // invoke uno dispatch call
+    (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
+
+    // in case an exception occurred...
+    if ( pUnoExc )
+    {
+        // destruct temporary in/inout params
+        for ( ; nTempIndizes--; )
+        {
+            sal_Int32 nIndex = pTempIndizes[nTempIndizes];
+
+            if (pParams[nIndex].bIn) // is in/inout => was constructed
+                uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
+            TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
+        }
+        if (pReturnTypeDescr)
+            TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+
+        CPPU_CURRENT_NAMESPACE::mscx_raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
+        // is here for dummy
+        return typelib_TypeClass_VOID;
+    }
+    else // else no exception occurred...
+    {
+        // temporary params
+        for ( ; nTempIndizes--; )
+        {
+            sal_Int32 nIndex = pTempIndizes[nTempIndizes];
+            typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
+
+            if ( pParams[nIndex].bOut ) // inout/out
+            {
+                // convert and assign
+                uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
+                uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
+                                        pThis->getBridge()->getUno2Cpp() );
+            }
+            // destroy temp uno param
+            uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
+
+            TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+        }
+        // return
+        if ( pCppReturn ) // has complex return
+        {
+            if ( pUnoReturn != pCppReturn ) // needs reconversion
+            {
+                uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
+                                        pThis->getBridge()->getUno2Cpp() );
+                // destroy temp uno return
+                uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
+            }
+            // complex return ptr is set to rax
+            *(void **)pRegisterReturn = pCppReturn;
+        }
+        if ( pReturnTypeDescr )
+        {
+            typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
+            TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+            return eRet;
+        }
+        else
+            return typelib_TypeClass_VOID;
+    }
+}
+
+
+//==================================================================================================
+extern "C" typelib_TypeClass cpp_vtable_call(
+    void ** pCallStack, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
+    sal_uInt64 * pRegisterReturn /* space for register return */ )
+{
+    // pCallStack: ret adr, this, [ret *], params
+    void * pThis = static_cast< char * >(pCallStack[1]) - nVtableOffset;
+
+    bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
+        bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
+
+    typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
+
+    OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
+    if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
+    {
+        throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
+                                reinterpret_cast<XInterface *>( pCppI ) );
+    }
+
+    // determine called method
+    sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
+    OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
+
+    TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
+
+    typelib_TypeClass eRet;
+    switch ( aMemberDescr.get()->eTypeClass )
+    {
+        case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+        {
+            typelib_TypeDescriptionReference *pAttrTypeRef =
+                reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
+
+            if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
+            {
+                // is GET method
+                eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
+                        0, 0, // no params
+                        pCallStack, pRegisterReturn );
+            }
+            else
+            {
+                // is SET method
+                typelib_MethodParameter aParam;
+                aParam.pTypeRef = pAttrTypeRef;
+                aParam.bIn      = sal_True;
+                aParam.bOut     = sal_False;
+
+                eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
+                        0, // indicates void return
+                        1, &aParam,
+                        pCallStack, pRegisterReturn );
+            }
+            break;
+        }
+        case typelib_TypeClass_INTERFACE_METHOD:
+        {
+            // is METHOD
+            switch ( nFunctionIndex )
+            {
+                // standard XInterface vtable calls
+                case 1: // acquire()
+                    pCppI->acquireProxy(); // non virtual call!
+                    eRet = typelib_TypeClass_VOID;
+                    break;
+                case 2: // release()
+                    pCppI->releaseProxy(); // non virtual call!
+                    eRet = typelib_TypeClass_VOID;
+                    break;
+                case 0: // queryInterface() opt
+                {
+                    typelib_TypeDescription * pTD = 0;
+                    TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( pCallStack[3] )->getTypeLibType() );
+                    if ( pTD )
+                    {
+                        XInterface * pInterface = 0;
+                        (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
+                            ( pCppI->getBridge()->getCppEnv(),
+                              (void **)&pInterface,
+                              pCppI->getOid().pData,
+                              reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
+
+                        if ( pInterface )
+                        {
+                            ::uno_any_construct( reinterpret_cast<uno_Any *>( pCallStack[1] ),
+                                                 &pInterface, pTD, cpp_acquire );
+
+                            pInterface->release();
+                            TYPELIB_DANGER_RELEASE( pTD );
+
+                            reinterpret_cast<void **>( pRegisterReturn )[0] = pCallStack[1];
+                            eRet = typelib_TypeClass_ANY;
+                            break;
+                        }
+                        TYPELIB_DANGER_RELEASE( pTD );
+                    }
+                } // else perform queryInterface()
+                default:
+                {
+                    typelib_InterfaceMethodTypeDescription *pMethodTD =
+                        reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
+
+                    eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
+                                         pMethodTD->pReturnTypeRef,
+                                         pMethodTD->nParams,
+                                         pMethodTD->pParams,
+                                         pCallStack, pRegisterReturn );
+                }
+            }
+            break;
+        }
+        default:
+        {
+            throw RuntimeException( OUString::createFromAscii("no member description found!"),
+                                    reinterpret_cast<XInterface *>( pCppI ) );
+            // is here for dummy
+            eRet = typelib_TypeClass_VOID;
+        }
+    }
+
+    return eRet;
+}
+
+//==================================================================================================
+extern "C" void privateSnippetExecutor( ... );
+
+int const codeSnippetSize = 44;
+
+unsigned char * codeSnippet(
+    unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, bool isArgFloat[4])
+{
+    unsigned char * p = code;
+
+
+    //
+    //         | ...                        |
+    //         +----------------------------+
+    //         | argument 4                 |
+    //  rsp+40 +----------------------------+ -------
+    //         | argument 3, r9/xmm3 home   | ^ shadow
+    //  rsp+32 +----------------------------+ | space,
+    //         | argument 2, r8/xmm2 home   | | guaranteed to be present but uninitialized,
+    //  rsp+24 +----------------------------+ | we have to copy
+    //         | argument 1, rdx/xmm1 home  | | the first 4 parameters there from the registers,
+    //  rsp+16 +----------------------------+ | to form the continuous array of arguments.
+    //         | argument 0, rcx/xmm0 home  | v
+    //  rsp+08 +----------------------------+ -------
+    //         | return address             |
+    //  rsp--> +----------------------------+
+    //
+    //
+
+    if (isArgFloat[0])
+    {
+        // movsd QWORD[rsp+8], XMM0
+        *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08;
+    }
+    else
+    {
+        // mov QWORD[rsp+8], rcx
+        *p++ = 0x48; *p++ = 0x49; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x08;
+    }
+
+    if (isArgFloat[1])
+    {
+        // movsd QWORD[rsp+16], XMM1
+        *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x10;
+    }
+    else
+    {
+        // mov QWORD[rsp+16], rdx
+        *p++ = 0x48; *p++ = 0x49; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10;
+    }
+
+    if (isArgFloat[2])
+    {
+        // movsd QWORD[rsp+24], XMM2
+        *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18;
+    }
+    else
+    {
+        // mov QWORD[rsp+24], r8
+        *p++ = 0x4c; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18;
+    }
+
+    if (isArgFloat[3])
+    {
+        // movsd QWORD[rsp+32], XMM3
+        *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x5c; *p++ = 0x24; *p++ = 0x20;
+    }
+    else
+    {
+        // mov QWORD[rsp+32], r9
+        *p++ = 0x4c; *p++ = 0x89; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x20;
+    }
+
+    // mov rax, functionIndex
+    *p++ = 0xb8;
+    *p++ = functionIndex & 0xff;
+    *p++ = (functionIndex >> 8) & 0xff;
+    *p++ = (functionIndex >> 16) & 0xff;
+    *p++ = (functionIndex >> 24) & 0xff;
+
+    // mov r10, vtableOffset
+    *p++ = 0x41;
+    *p++ = 0xba;
+    *p++ = vtableOffset & 0xff;
+    *p++ = (vtableOffset >> 8) & 0xff;
+    *p++ = (vtableOffset >> 16) & 0xff;
+    *p++ = (vtableOffset >> 24) & 0xff;
+
+    // mov r11, privateSnippetExecutor
+    *p++ = 0x49;
+    *p++ = 0xbb;
+    *p++ = ((sal_uIntPtr)(&privateSnippetExecutor)) & 0xff;
+    *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 8) & 0xff;
+    *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 16) & 0xff;
+    *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 24) & 0xff;
+    *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 32) & 0xff;
+    *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 40) & 0xff;
+    *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 48) & 0xff;
+    *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 56) & 0xff;
+
+    // jmp r11
+    *p++ = 0x49;
+    *p++ = 0xff;
+    *p++ = 0xe3;
+
+    OSL_ASSERT(p - code <= codeSnippetSize);
+    return code + codeSnippetSize;
+}
+
+}
+
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+
+bridges::cpp_uno::shared::VtableFactory::Slot *
+bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
+{
+    return static_cast< Slot * >(block) + 1;
+}
+
+sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
+    sal_Int32 slotCount)
+{
+    return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
+}
+
+bridges::cpp_uno::shared::VtableFactory::Slot *
+bridges::cpp_uno::shared::VtableFactory::initializeBlock(
+    void * block, sal_Int32 slotCount)
+{
+    struct RttiCompleteObjectLocator {
+        sal_uInt32 signature;
+        sal_uInt32 offset;    // offset of vtable in objects of the class
+        sal_uInt32 cdOffset;  // constructor displacement offset
+        // On AMD64, these 2 are offsets from the module's base address (when signature == 0):
+        sal_uInt32 typeDescriptorAddress;
+        sal_uInt32 classDescriptorAddress;
+        sal_uInt32 objectBase; // ignored when signature == 0
+
+        RttiCompleteObjectLocator(): signature(0), offset(0), cdOffset(0)
+        {
+            type_info *typeInfo = CPPU_CURRENT_NAMESPACE::mscx_getRTTI(
+                     rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+                                       "com.sun.star.uno.XInterface")));
+            HMODULE thisDLLBase;
+            GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)&bridges::cpp_uno::shared::VtableFactory::initializeBlock, &thisDLLBase);
+            typeDescriptorAddress = (sal_uInt32) (((char*)typeInfo) - (char*)thisDLLBase);
+            classDescriptorAddress = 0;
+            objectBase = 0;
+        }
+    };
+    static RttiCompleteObjectLocator rtti;
+
+    Slot * slots = mapBlockToVtable(block);
+    slots[-1].fn = &rtti;
+    return slots + slotCount;
+}
+
+static void findFirst4Win64ArgumentTypes(
+    typelib_MethodParameter *pParams, sal_Int32 nParams,
+    typelib_TypeDescriptionReference *pReturnType, bool isArgFloat[4])
+{
+    sal_uInt32 index = 0;
+
+    isArgFloat[0] = isArgFloat[1] = isArgFloat[2] = isArgFloat[3] = false;
+
+    // C++ "this" pointer:
+    ++index;
+
+    // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017
+    // "Otherwise the caller assumes the responsibility of allocating memory
+    // and passing a pointer for the return value as the first argument.
+    // Subsequent arguments are then shifted one argument to the right.
+    // The same pointer must be returned by the callee in RAX."
+    if ( pReturnType && x86_64::return_in_hidden_param( pReturnType ) )
+        ++index;
+
+    for (int param = 0; param < nParams; param++)
+    {
+        if (index >= 4)
+            break;
+
+        typelib_TypeDescription *pParamTypeDescr = 0;
+
+        TYPELIB_DANGER_GET( &pParamTypeDescr, pParams[param].pTypeRef );
+        OSL_ASSERT( pParamTypeDescr );
+
+        isArgFloat[index++] = !pParams[param].bOut &&
+            (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT ||
+            pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE);
+
+        TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+    }
+}
+
+unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
+    Slot ** slots, unsigned char * code,
+    typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset,
+    sal_Int32 functionCount, sal_Int32 vtableOffset)
+{
+    (*slots) -= functionCount;
+    Slot * s = *slots;
+    for (sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos) {
+        typelib_TypeDescription * pTD = 0;
+
+        TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
+        OSL_ASSERT( pTD );
+
+        bool isArgFloat[4];
+        if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
+        {
+            typelib_InterfaceAttributeTypeDescription *pAttrTD =
+                reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
+
+            // get method
+            findFirst4Win64ArgumentTypes(0, 0, pAttrTD->pAttributeTypeRef, isArgFloat);
+            (s++)->fn = code;
+            code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
+
+            if ( ! pAttrTD->bReadOnly )
+            {
+                // set method
+                typelib_MethodParameter aParam;
+                aParam.pTypeRef = pAttrTD->pAttributeTypeRef;
+                aParam.bIn      = sal_True;
+                aParam.bOut     = sal_False;
+                findFirst4Win64ArgumentTypes(&aParam, 1, 0, isArgFloat);
+                (s++)->fn = code;
+                code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
+            }
+        }
+        else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
+        {
+            typelib_InterfaceMethodTypeDescription *pMethodTD =
+                reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
+            findFirst4Win64ArgumentTypes(pMethodTD->pParams, pMethodTD->nParams,
+                pMethodTD->pReturnTypeRef, isArgFloat);
+            (s++)->fn = code;
+            code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
+        }
+        else
+            OSL_ASSERT( false );
+
+        TYPELIB_DANGER_RELEASE( pTD );
+    }
+    return code;
+}
+
+void bridges::cpp_uno::shared::VtableFactory::flushCode(
+    unsigned char const *, unsigned char const *)
+{}
diff --git a/bridges/source/cpp_uno/msvc_win64_x86-64/dllinit.cxx b/bridges/source/cpp_uno/msvc_win64_x86-64/dllinit.cxx
new file mode 100644
index 000000000000..6d88b4a4e9ce
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win64_x86-64/dllinit.cxx
@@ -0,0 +1,54 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+
+#pragma warning(push,1) // disable warnings within system headers
+#include <windows.h>
+#pragma warning(pop)
+
+
+void dso_init(void);
+void dso_exit(void);
+
+
+extern "C" BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpvReserved)
+{
+    switch(dwReason) {
+    case DLL_PROCESS_ATTACH:
+        DisableThreadLibraryCalls(hModule);
+
+        dso_init();
+        break;
+
+    case DLL_PROCESS_DETACH:
+        if (!lpvReserved)
+            dso_exit();
+        break;
+    }
+
+    return TRUE;
+}
diff --git a/bridges/source/cpp_uno/msvc_win64_x86-64/except.cxx b/bridges/source/cpp_uno/msvc_win64_x86-64/except.cxx
new file mode 100644
index 000000000000..c38515e77836
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win64_x86-64/except.cxx
@@ -0,0 +1,663 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#pragma warning( disable : 4237 )
+#include <hash_map>
+#include <sal/config.h>
+#include <malloc.h>
+#include <typeinfo.h>
+#include <signal.h>
+
+#include "rtl/alloc.h"
+#include "rtl/strbuf.hxx"
+#include "rtl/ustrbuf.hxx"
+
+#include "com/sun/star/uno/Any.hxx"
+
+#include "mscx.hxx"
+
+
+#pragma pack(push, 8)
+
+using namespace ::com::sun::star::uno;
+using namespace ::std;
+using namespace ::osl;
+using namespace ::rtl;
+
+namespace CPPU_CURRENT_NAMESPACE
+{
+
+//==================================================================================================
+static inline OUString toUNOname( OUString const & rRTTIname ) throw ()
+{
+    OUStringBuffer aRet( 64 );
+    OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz at yyy@xxx@@
+    sal_Int32 nPos = aStr.getLength();
+    while (nPos > 0)
+    {
+        sal_Int32 n = aStr.lastIndexOf( '@', nPos );
+        aRet.append( aStr.copy( n +1, nPos -n -1 ) );
+        if (n >= 0)
+        {
+            aRet.append( (sal_Unicode)'.' );
+        }
+        nPos = n;
+    }
+    return aRet.makeStringAndClear();
+}
+//==================================================================================================
+static inline OUString toRTTIname( OUString const & rUNOname ) throw ()
+{
+    OUStringBuffer aRet( 64 );
+    aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM(".?AV") ); // class ".?AV"; struct ".?AU"
+    sal_Int32 nPos = rUNOname.getLength();
+    while (nPos > 0)
+    {
+        sal_Int32 n = rUNOname.lastIndexOf( '.', nPos );
+        aRet.append( rUNOname.copy( n +1, nPos -n -1 ) );
+        aRet.append( (sal_Unicode)'@' );
+        nPos = n;
+    }
+    aRet.append( (sal_Unicode)'@' );
+    return aRet.makeStringAndClear();
+}
+
+
+//##################################################################################################
+//#### RTTI simulation #############################################################################
+//##################################################################################################
+
+
+typedef hash_map< OUString, void *, OUStringHash, equal_to< OUString > > t_string2PtrMap;
+
+//==================================================================================================
+class RTTInfos
+{
+    Mutex               _aMutex;
+    t_string2PtrMap     _allRTTI;
+
+    static OUString toRawName( OUString const & rUNOname ) throw ();
+public:
+    type_info * getRTTI( OUString const & rUNOname ) throw ();
+
+    RTTInfos();
+    ~RTTInfos();
+};
+
+//==================================================================================================
+class __type_info
+{
+    friend type_info * RTTInfos::getRTTI( OUString const & ) throw ();
+    friend int mscx_filterCppException(
+        LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * );
+
+public:
+    virtual ~__type_info() throw ();
+
+    inline __type_info( void * m_vtable, const char * m_d_name ) throw ()
+        : _m_vtable( m_vtable )
+        , _m_name( NULL )
+        { ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked
+
+    size_t length() const
+    {
+        return sizeof(__type_info) + strlen(_m_d_name);
+    }
+
+private:
+    void * _m_vtable;
+    char * _m_name;     // cached copy of unmangled name, NULL initially
+    char _m_d_name[1];  // mangled name
+};
+//__________________________________________________________________________________________________
+__type_info::~__type_info() throw ()
+{
+}
+//__________________________________________________________________________________________________
+type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw ()
+{
+    // a must be
+    OSL_ENSURE( sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!" );
+
+    MutexGuard aGuard( _aMutex );
+    t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) );
+
+    // check if type is already available
+    if (iFind == _allRTTI.end())
+    {
+        // insert new type_info
+        OString aRawName( OUStringToOString( toRTTIname( rUNOname ), RTL_TEXTENCODING_ASCII_US ) );
+        __type_info * pRTTI = new( ::rtl_allocateMemory( sizeof(__type_info) + aRawName.getLength() ) )
+            __type_info( NULL, aRawName.getStr() );
+
+        // put into map
+        pair< t_string2PtrMap::iterator, bool > insertion(
+            _allRTTI.insert( t_string2PtrMap::value_type( rUNOname, pRTTI ) ) );
+        OSL_ENSURE( insertion.second, "### rtti insertion failed?!" );
+
+        return (type_info *)pRTTI;
+    }
+    else
+    {
+        return (type_info *)iFind->second;
+    }
+}
+//__________________________________________________________________________________________________
+RTTInfos::RTTInfos() throw ()
+{
+}
+//__________________________________________________________________________________________________
+RTTInfos::~RTTInfos() throw ()
+{
+#if OSL_DEBUG_LEVEL > 1
+    OSL_TRACE( "> freeing generated RTTI infos... <\n" );
+#endif
+
+    MutexGuard aGuard( _aMutex );
+    for ( t_string2PtrMap::const_iterator iPos( _allRTTI.begin() );
+          iPos != _allRTTI.end(); ++iPos )
+    {
+        __type_info * pType = (__type_info *)iPos->second;
+        pType->~__type_info(); // obsolete, but good style...
+        ::rtl_freeMemory( pType );
+    }
+}
+
+
+//##################################################################################################
+//#### Exception raising ###########################################################################
+//##################################################################################################
+
+
+//==================================================================================================
+static void * __copyConstruct( void * pExcThis, void * pSource, typelib_TypeDescription *pTypeDescr )
+    throw ()
+{
+    ::uno_copyData( pExcThis, pSource, pTypeDescr, cpp_acquire );
+    return pExcThis;
+}
+//==================================================================================================
+static void * __destruct( void * pExcThis, typelib_TypeDescription *pTypeDescr )
+    throw ()
+{
+    ::uno_destructData( pExcThis, pTypeDescr, cpp_release );
+    return pExcThis;
+}
+
+//==================================================================================================
+
+int const codeSnippetSize = 32;
+
+void copyConstructCodeSnippet( unsigned char * code, typelib_TypeDescription * pTypeDescr )
+    throw ()
+{
+    unsigned char * p = code;
+
+    // mov r8, pTypeDescr
+    *p++ = 0x49;
+    *p++ = 0xb8;
+    *p++ = ((sal_uIntPtr)(pTypeDescr)) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 8) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 16) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 24) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 32) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 40) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 48) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 56) & 0xff;
+
+    // mov r9, __copyConstruct
+    *p++ = 0x49;
+    *p++ = 0xb9;
+    *p++ = ((sal_uIntPtr)(&__copyConstruct)) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 8) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 16) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 24) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 32) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 40) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 48) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__copyConstruct)) >> 56) & 0xff;
+
+    // jmp r9
+    *p++ = 0x41;
+    *p++ = 0xff;
+    *p++ = 0xe1;
+
+    OSL_ASSERT(p - code <= codeSnippetSize);
+}
+
+//==================================================================================================
+void destructCodeSnippet( unsigned char * code, typelib_TypeDescription * pTypeDescr )
+    throw ()
+{
+    unsigned char * p = code;
+
+    // mov rdx, pTypeDescr
+    *p++ = 0x48;
+    *p++ = 0xba;
+    *p++ = ((sal_uIntPtr)(pTypeDescr)) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 8) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 16) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 24) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 32) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 40) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 48) & 0xff;
+    *p++ = (((sal_uIntPtr)(pTypeDescr)) >> 56) & 0xff;
+
+    // mov r9, __destruct
+    *p++ = 0x49;
+    *p++ = 0xb9;
+    *p++ = ((sal_uIntPtr)(&__destruct)) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__destruct)) >> 8) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__destruct)) >> 16) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__destruct)) >> 24) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__destruct)) >> 32) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__destruct)) >> 40) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__destruct)) >> 48) & 0xff;
+    *p++ = (((sal_uIntPtr)(&__destruct)) >> 56) & 0xff;
+
+    // jmp r9
+    *p++ = 0x41;
+    *p++ = 0xff;
+    *p++ = 0xe1;
+
+    OSL_ASSERT(p - code <= codeSnippetSize);
+}
+
+//==================================================================================================
+static size_t align16(size_t size)
+{
+    return ((size + 15) >> 4) << 4;
+}
+
+//==================================================================================================
+// Known as "catchabletype" in https://github.com/icestudent/ontl/blob/master/ntl/nt/exception.hxx
+struct ExceptionType
+{
+    sal_Int32           _n0;
+    sal_uInt32          _pTypeInfo;    // type_info *, RVA on Win64
+    sal_Int32           _n1, _n2, _n3; // pointer to member descriptor, 12 bytes.
+    sal_uInt32          _n4;
+    sal_uInt32          _pCopyCtor;    // RVA on Win64
+    sal_Int32           _n5;
+
+    static void initialize( unsigned char *p, sal_uInt32 typeInfoRVA, typelib_TypeDescription * pTypeDescr, sal_uInt32 copyConstructorRVA ) throw ()
+    {
+        ExceptionType *e = (ExceptionType*)p;
+        e->_n0 = 0;
+        e->_pTypeInfo = typeInfoRVA;
+        e->_n1 = 0;
+        e->_n2 = -1;
+        e->_n3 = 0;
+        e->_n4 = pTypeDescr->nSize;
+        e->_pCopyCtor = copyConstructorRVA;
+        e->_n5 = 0;
+    }
+};
+
+//==================================================================================================
+// Known as "throwinfo" in https://github.com/icestudent/ontl/blob/master/ntl/nt/exception.hxx
+struct RaiseInfo
+{
+    // Microsoft's fields:
+    sal_uInt32          _n0;
+    sal_uInt32          _pDtor; // RVA on Win64
+    sal_uInt32          _n2;
+    sal_uInt32          _types; // void *, RVA on Win64
+
+    // Our additional fields:
+    typelib_TypeDescription * pTypeDescr;
+    unsigned char       *baseAddress; // The RVAs are relative to this field
+
+    RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
+    ~RaiseInfo() throw ();
+};
+//__________________________________________________________________________________________________
+RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
+    : _n0( 0 )
+    , _n2( 0 )
+{
+    // a must be
+    OSL_ENSURE( sizeof(sal_Int32) == sizeof(ExceptionType *), "### pointer size differs from sal_Int32!" );
+
+    ::typelib_typedescription_acquire( pTypeDescr );
+    this->pTypeDescr = pTypeDescr;
+
+    typelib_CompoundTypeDescription * pCompTypeDescr;
+
+    size_t bytesNeeded = codeSnippetSize; // destructCodeSnippet for _pDtor
+    sal_uInt32 typeCount = 0;
+    for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
+          pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
+    {
+        ++typeCount;
+        bytesNeeded += align16( sizeof( ExceptionType ) );
+        __type_info *typeInfo = (__type_info*) mscx_getRTTI( ((typelib_TypeDescription *)pCompTypeDescr)->pTypeName );
+        bytesNeeded += align16( typeInfo->length() );
+        bytesNeeded += codeSnippetSize; // copyConstructCodeSnippet for its _pCopyCtor
+    }
+    // type info count accompanied by RVAs of type info ptrs: type, base type, base base type, ...
+    bytesNeeded += align16( sizeof( sal_uInt32 ) + (typeCount * sizeof( sal_uInt32 )) );
+
+    unsigned char *p = (unsigned char*) ::rtl_allocateMemory( bytesNeeded );
+    DWORD old_protect;
+#if OSL_DEBUG_LEVEL > 0
+    BOOL success =
+#endif
+    VirtualProtect( p, bytesNeeded, PAGE_EXECUTE_READWRITE, &old_protect );
+    OSL_ENSURE( success, "VirtualProtect() failed!" );
+    baseAddress = p;
+
+    destructCodeSnippet( p, pTypeDescr );
+    _pDtor = (sal_uInt32)(p - baseAddress);
+    p += codeSnippetSize;
+
+    sal_uInt32 *types = (sal_uInt32*)p;
+    _types = (sal_uInt32)(p - baseAddress);
+    p += align16( sizeof( sal_uInt32 ) + (typeCount * sizeof( sal_uInt32 )) );
+    types[0] = typeCount;
+    int next = 1;
+    for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr;
+          pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
+    {
+        __type_info *typeInfo = (__type_info*) mscx_getRTTI( ((typelib_TypeDescription *)pCompTypeDescr)->pTypeName );
+        memcpy(p, typeInfo, typeInfo->length() );
+        sal_uInt32 typeInfoRVA = (sal_uInt32)(p - baseAddress);
+        p += align16( typeInfo->length() );
+
+        copyConstructCodeSnippet( p, (typelib_TypeDescription *)pCompTypeDescr );
+        sal_uInt32 copyConstructorRVA = (sal_uInt32)(p - baseAddress);
+        p += codeSnippetSize;
+
+        ExceptionType::initialize( p, typeInfoRVA, (typelib_TypeDescription *)pCompTypeDescr, copyConstructorRVA );
+        types[next++] = (sal_uInt32)(p - baseAddress);
+        p += align16( sizeof(ExceptionType) );
+    }
+
+    OSL_ASSERT(p - baseAddress <= bytesNeeded);
+}
+//__________________________________________________________________________________________________
+RaiseInfo::~RaiseInfo() throw ()
+{
+    ::rtl_freeMemory( baseAddress );
+    ::typelib_typedescription_release( pTypeDescr );
+}
+
+//==================================================================================================
+class ExceptionInfos
+{
+    Mutex           _aMutex;
+    t_string2PtrMap _allRaiseInfos;
+
+public:
+    static RaiseInfo * getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ();
+
+    ExceptionInfos() throw ();
+    ~ExceptionInfos() throw ();
+};
+//__________________________________________________________________________________________________
+ExceptionInfos::ExceptionInfos() throw ()
+{
+}
+//__________________________________________________________________________________________________
+ExceptionInfos::~ExceptionInfos() throw ()
+{
+#if OSL_DEBUG_LEVEL > 1
+    OSL_TRACE( "> freeing exception infos... <\n" );
+#endif
+
+    MutexGuard aGuard( _aMutex );
+    for ( t_string2PtrMap::const_iterator iPos( _allRaiseInfos.begin() );
+          iPos != _allRaiseInfos.end(); ++iPos )
+    {
+        delete (RaiseInfo *)iPos->second;
+    }
+}
+//__________________________________________________________________________________________________
+RaiseInfo * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw ()
+{
+    static ExceptionInfos * s_pInfos = 0;
+    if (! s_pInfos)
+    {
+        MutexGuard aGuard( Mutex::getGlobalMutex() );
+        if (! s_pInfos)
+        {
+#ifdef LEAK_STATIC_DATA
+            s_pInfos = new ExceptionInfos();
+#else
+            static ExceptionInfos s_allExceptionInfos;
+            s_pInfos = &s_allExceptionInfos;
+#endif
+        }
+    }
+
+    OSL_ASSERT( pTypeDescr &&
+                (pTypeDescr->eTypeClass == typelib_TypeClass_STRUCT ||
+                 pTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION) );
+
+    void * pRaiseInfo;
+
+    OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTypeDescr->pTypeName );
+    MutexGuard aGuard( s_pInfos->_aMutex );
+    t_string2PtrMap::const_iterator const iFind(
+        s_pInfos->_allRaiseInfos.find( rTypeName ) );
+    if (iFind == s_pInfos->_allRaiseInfos.end())
+    {
+        pRaiseInfo = new RaiseInfo( pTypeDescr );
+        // put into map
+        pair< t_string2PtrMap::iterator, bool > insertion(
+            s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, pRaiseInfo ) ) );
+        OSL_ENSURE( insertion.second, "### raise info insertion failed?!" );
+    }
+    else
+    {
+        // reuse existing info
+        pRaiseInfo = iFind->second;
+    }
+
+    return (RaiseInfo*) pRaiseInfo;
+}
+
+
+//##################################################################################################
+//#### exported ####################################################################################
+//##################################################################################################
+
+
+//##################################################################################################
+type_info * mscx_getRTTI( OUString const & rUNOname )
+{
+    static RTTInfos * s_pRTTIs = 0;
+    if (! s_pRTTIs)
+    {
+        MutexGuard aGuard( Mutex::getGlobalMutex() );
+        if (! s_pRTTIs)
+        {
+#ifdef LEAK_STATIC_DATA
+            s_pRTTIs = new RTTInfos();
+#else
+            static RTTInfos s_aRTTIs;
+            s_pRTTIs = &s_aRTTIs;
+#endif
+        }
+    }
+    return s_pRTTIs->getRTTI( rUNOname );
+}
+
+//##################################################################################################
+void mscx_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
+{
+    // no ctor/dtor in here: this leads to dtors called twice upon RaiseException()!
+    // thus this obj file will be compiled without opt, so no inling of
+    // ExceptionInfos::getRaiseInfo()
+
+    // construct cpp exception object
+    typelib_TypeDescription * pTypeDescr = 0;
+    TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
+
+    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!" );
+    RaiseInfo *raiseInfo = ExceptionInfos::getRaiseInfo( pTypeDescr );
+    ULONG_PTR arFilterArgs[4];
+    arFilterArgs[0] = MSVC_magic_number;
+    arFilterArgs[1] = (ULONG_PTR)pCppExc;
+    arFilterArgs[2] = (ULONG_PTR)raiseInfo;
+    arFilterArgs[3] = (ULONG_PTR)raiseInfo->baseAddress;
+
+    // destruct uno exception
+    ::uno_any_destruct( pUnoExc, 0 );
+    TYPELIB_DANGER_RELEASE( pTypeDescr );
+
+    // last point to release anything not affected by stack unwinding
+    RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 4, arFilterArgs );
+}
+
+//##############################################################################
+int mscx_filterCppException(
+    EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
+{
+    if (pPointers == 0)
+        return EXCEPTION_CONTINUE_SEARCH;
+    EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord;
+    // handle only C++ exceptions:
+    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:
+        pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >(
+            reinterpret_cast< char * >( __pxcptinfoptrs() ) +
+            // as long as we don't demand msvcr source as build prerequisite
+            // (->platform sdk), we have to code those offsets here.
+            //
+            // crt\src\mtdll.h:
+            // offsetof (_tiddata, _curexception) -
+            // offsetof (_tiddata, _tpxcptinfoptrs):
+            48
+            );
+    }
+    // rethrow: handle only C++ exceptions:
+    if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode)
+        return EXCEPTION_CONTINUE_SEARCH;
+
+    if (pRecord->NumberParameters == 4 &&
+//          pRecord->ExceptionInformation[ 0 ] == MSVC_magic_number &&
+        pRecord->ExceptionInformation[ 1 ] != 0 &&
+        pRecord->ExceptionInformation[ 2 ] != 0 &&
+        pRecord->ExceptionInformation[ 3 ] != 0)
+    {
+        unsigned char *baseAddress = (unsigned char*) pRecord->ExceptionInformation[ 3 ];
+        sal_uInt32 * types = (sal_uInt32*)(baseAddress + reinterpret_cast< RaiseInfo * >(
+            pRecord->ExceptionInformation[ 2 ] )->_types );
+        if (types != 0 && (sal_uInt32)(types[0]) > 0) // count
+        {
+            ExceptionType * pType = reinterpret_cast< ExceptionType * >(
+                baseAddress + types[ 1 ] );
+            if (pType != 0 && pType->_pTypeInfo != 0)
+            {
+                OUString aRTTIname(
+                    OStringToOUString(
+                        reinterpret_cast< __type_info * >(
+                            baseAddress + pType->_pTypeInfo )->_m_d_name,
+                        RTL_TEXTENCODING_ASCII_US ) );
+                OUString aUNOname( toUNOname( aRTTIname ) );
+
+                typelib_TypeDescription * pExcTypeDescr = 0;
+                typelib_typedescription_getByName(
+                    &pExcTypeDescr, aUNOname.pData );
+                if (pExcTypeDescr == 0)
+                {
+                    OUStringBuffer buf;
+                    buf.appendAscii(
+                        RTL_CONSTASCII_STRINGPARAM(
+                            "[mscx_uno bridge error] UNO type of "
+                            "C++ exception unknown: \"") );
+                    buf.append( aUNOname );
+                    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
+                                         "\", RTTI-name=\"") );
+                    buf.append( aRTTIname );
+                    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
+                    RuntimeException exc(
+                        buf.makeStringAndClear(), Reference< XInterface >() );
+                    uno_type_any_constructAndConvert(
+                        pUnoExc, &exc,
+                        ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
+#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
+                    // if (! rethrow):
+                    // though this unknown exception leaks now, no user-defined
+                    // exception is ever thrown through the binary C-UNO dispatcher
+                    // call stack.
+#endif
+                }
+                else
+                {
+                    // construct uno exception any
+                    uno_any_constructAndConvert(
+                        pUnoExc, (void *) pRecord->ExceptionInformation[1],
+                        pExcTypeDescr, pCpp2Uno );
+#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
+                    if (! rethrow)
+                    {
+                        uno_destructData(
+                            (void *) pRecord->ExceptionInformation[1],
+                            pExcTypeDescr, cpp_release );
+                    }
+#endif
+                    typelib_typedescription_release( pExcTypeDescr );
+                }
+
+                return EXCEPTION_EXECUTE_HANDLER;
+            }
+        }
+    }
+    // though this unknown exception leaks now, no user-defined exception
+    // is ever thrown through the binary C-UNO dispatcher call stack.
+    RuntimeException exc(
+        OUString( RTL_CONSTASCII_USTRINGPARAM(
+                      "[mscx_uno bridge error] unexpected "
+                      "C++ exception occurred!") ),
+        Reference< XInterface >() );
+    uno_type_any_constructAndConvert(
+        pUnoExc, &exc, ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno );
+    return EXCEPTION_EXECUTE_HANDLER;
+}
+
+}
+
+#pragma pack(pop)
+
diff --git a/bridges/source/cpp_uno/msvc_win64_x86-64/mscx.hxx b/bridges/source/cpp_uno/msvc_win64_x86-64/mscx.hxx
new file mode 100644
index 000000000000..d49ec35f842f
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win64_x86-64/mscx.hxx
@@ -0,0 +1,53 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+
+
+#pragma warning(push, 1)
+#include <windows.h>
+#pragma warning(pop)
+
+#include "rtl/ustring.hxx"
+
+
+class type_info;
+typedef struct _uno_Any uno_Any;
+typedef struct _uno_Mapping uno_Mapping;
+
+namespace CPPU_CURRENT_NAMESPACE
+{
+
+const DWORD MSVC_ExceptionCode = 0xe06d7363;
+const long MSVC_magic_number = 0x19930520L;
+
+//==============================================================================
+type_info * mscx_getRTTI( ::rtl::OUString const & rUNOname );
+
+//==============================================================================
+int mscx_filterCppException(
+    EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno );
+
+//==============================================================================
+void mscx_raiseException(
+    uno_Any * pUnoExc, uno_Mapping * pUno2Cpp );
+
+}
+
diff --git a/bridges/source/cpp_uno/msvc_win64_x86-64/uno2cpp.cxx b/bridges/source/cpp_uno/msvc_win64_x86-64/uno2cpp.cxx
new file mode 100644
index 000000000000..f7281620a136
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win64_x86-64/uno2cpp.cxx
@@ -0,0 +1,365 @@
+/**************************************************************
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#include <malloc.h>
+
+#include <com/sun/star/uno/genfunc.hxx>
+#include <uno/data.h>
+
+#include "bridges/cpp_uno/shared/bridge.hxx"
+#include "bridges/cpp_uno/shared/types.hxx"
+#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
+#include "bridges/cpp_uno/shared/vtables.hxx"
+
+#include "abi.hxx"
+#include "mscx.hxx"
+
+using namespace ::rtl;
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+
+//==================================================================================================
+extern "C" void callVirtualMethod(
+    void * pAdjustedThisPtr, sal_Int32 nVtableIndex,
+    void * pRegisterReturn, typelib_TypeClass eReturnTypeClass,
+    sal_uInt64 * pStackLongs, sal_uInt32 nStackLongs );
+
+//==================================================================================================
+static void cpp_call(
+    bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
+    bridges::cpp_uno::shared::VtableSlot aVtableSlot,
+    typelib_TypeDescriptionReference * pReturnTypeRef,
+    sal_Int32 nParams, typelib_MethodParameter * pParams,
+    void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) throw ()
+{
+    // max space for: [complex ret ptr], values|ptr ...
+    sal_uInt64 *pStack = (sal_uInt64 *)alloca( (nParams + 3) * sizeof(sal_uInt64) );
+    sal_uInt64 *pStackStart = pStack;
+
+    // Push "this" pointer
+    void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
+    *pStack++ = *(sal_uInt64*)&pAdjustedThisPtr;
+
+    // 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
+
+    if ( pReturnTypeDescr )
+    {
+        if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
+        {
+            // complex return via ptr
+            pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
+                         alloca( pReturnTypeDescr->nSize ) : pUnoReturn; // direct way
+            *pStack++ = *(sal_uInt64*)&pCppReturn;
+        }
+        else
+            pCppReturn = pUnoReturn; // direct way for simple types
+    }
+
+    // Args
+    void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
+    // Indices 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;
+
+    for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+    {
+        const typelib_MethodParameter & rParam = pParams[nPos];
+        typelib_TypeDescription * pParamTypeDescr = 0;
+        TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
+
+        if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
+        {
+            uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
+                                    pThis->getBridge()->getUno2Cpp() );
+
+            switch (pParamTypeDescr->eTypeClass)
+            {
+            case typelib_TypeClass_HYPER:
+            case typelib_TypeClass_UNSIGNED_HYPER:
+                *pStack++ = *(sal_uInt64*)&pCppArgs[nPos];
+                break;
+            case typelib_TypeClass_LONG:
+            case typelib_TypeClass_UNSIGNED_LONG:
+            case typelib_TypeClass_ENUM:
+                *pStack++ = *(sal_uInt32*)&pCppArgs[nPos];
+                break;
+            case typelib_TypeClass_SHORT:
+            case typelib_TypeClass_UNSIGNED_SHORT:
+            case typelib_TypeClass_CHAR:
+                *pStack++ = *(sal_uInt16*)&pCppArgs[nPos];
+                break;
+            case typelib_TypeClass_BOOLEAN:
+            case typelib_TypeClass_BYTE:
+                *pStack++ = *(sal_uInt8*)&pCppArgs[nPos];
+                break;
+            case typelib_TypeClass_FLOAT:
+            case typelib_TypeClass_DOUBLE:
+                *pStack++ = *(sal_uInt64*)&pCppArgs[nPos]; // verbatim!
+                break;
+            default:
+                break;
+            }
+            // no longer needed
+            TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+        }
+        else // ptr to complex value | ref
+        {
+            if (! rParam.bIn) // is pure out
+            {
+                // cpp out is constructed mem, uno out is not!
+                uno_constructData(
+                    pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
+                    pParamTypeDescr );
+                pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
+            }
+            // is in/inout
+            else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
+            {
+                uno_copyAndConvertData(
+                    pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
+                    pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
+
+                pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
+            }
+            else // direct way
+            {
+                pCppArgs[nPos] = pUnoArgs[nPos];
+                // no longer needed
+                TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+            }
+            *pStack++ = *(sal_uInt64*)&pCppArgs[nPos];
+        }
+    }
+
+    __try
+    {
+        // pCppI is mscx this pointer
+        callVirtualMethod(
+            pAdjustedThisPtr,
+            aVtableSlot.index,
+            pCppReturn, pReturnTypeDescr->eTypeClass,
+            pStackStart, (pStack - pStackStart) );
+    }
+    __except (CPPU_CURRENT_NAMESPACE::mscx_filterCppException(
+                  GetExceptionInformation(),
+                  *ppUnoExc, pThis->getBridge()->getCpp2Uno() ))
+   {
+        // *ppUnoExc was constructed by filter function
+        // temporary params
+        for ( ; nTempIndizes--; )
+        {
+            sal_Int32 nIndex = pTempIndizes[nTempIndizes];
+            // destroy temp cpp param => cpp: every param was constructed
+            uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
+            TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
+        }
+        // return type
+        if (pReturnTypeDescr)
+            TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+        // end here
+        return;
+    }
+
+    // NO exception occurred
+    *ppUnoExc = 0;
+
+    // reconvert temporary params
+    for ( ; nTempIndizes--; )
+    {
+        sal_Int32 nIndex = pTempIndizes[nTempIndizes];
+        typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
+
+        if (pParams[nIndex].bIn)
+        {
+            if (pParams[nIndex].bOut) // inout
+            {
+                uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
+                uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
+                                        pThis->getBridge()->getCpp2Uno() );
+            }
+        }
+        else // pure out
+        {
+            uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
+                                    pThis->getBridge()->getCpp2Uno() );
+        }
+        // destroy temp cpp param => cpp: every param was constructed
+        uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
+
+        TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+    }
+    // return value
+    if (pCppReturn && pUnoReturn != pCppReturn)
+    {
+        uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
+                                pThis->getBridge()->getCpp2Uno() );
+        uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
+    }
+    // return type
+    if (pReturnTypeDescr)
+        TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+}
+
+}
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+void unoInterfaceProxyDispatch(
+    uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
+    void * pReturn, void * pArgs[], uno_Any ** ppException )
+{
+    // is my surrogate
+    bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
+        = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
+
+    switch (pMemberDescr->eTypeClass)
+    {
+    case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+    {
+        VtableSlot aVtableSlot(
+            getVtableSlot(
+                reinterpret_cast<
+                    typelib_InterfaceAttributeTypeDescription const * >(
+                        pMemberDescr)));
+
+        if (pReturn)
+        {
+            // dependent dispatch
+            cpp_call(
+                pThis, aVtableSlot,
+                ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
+                0, 0, // no params
+                pReturn, pArgs, ppException );
+        }
+        else
+        {
+            // is SET
+            typelib_MethodParameter aParam;
+            aParam.pTypeRef =
+                ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
+            aParam.bIn      = sal_True;
+            aParam.bOut     = sal_False;
+
+            typelib_TypeDescriptionReference * pReturnTypeRef = 0;
+            OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
+            typelib_typedescriptionreference_new(
+                &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
+
+            // dependent dispatch
+            aVtableSlot.index += 1; // get, then set method
+            cpp_call(
+                pThis, aVtableSlot, // get, then set method
+                pReturnTypeRef,
+                1, &aParam,
+                pReturn, pArgs, ppException );
+
+            typelib_typedescriptionreference_release( pReturnTypeRef );
+        }
+
+        break;
+    }
+    case typelib_TypeClass_INTERFACE_METHOD:
+    {
+        VtableSlot aVtableSlot(
+            getVtableSlot(
+                reinterpret_cast<
+                    typelib_InterfaceMethodTypeDescription const * >(
+                        pMemberDescr)));
+
+        switch (aVtableSlot.index)
+        {
+            // standard calls
+        case 1: // acquire uno interface
+            (*pUnoI->acquire)( pUnoI );
+            *ppException = 0;
+            break;
+        case 2: // release uno interface
+            (*pUnoI->release)( pUnoI );
+            *ppException = 0;
+            break;
+        case 0: // queryInterface() opt
+        {
+            typelib_TypeDescription * pTD = 0;
+            TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
+            if (pTD)
+            {
+                uno_Interface * pInterface = 0;
+                (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
+                    pThis->getBridge()->getUnoEnv(),
+                    (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
+
+                if (pInterface)
+                {
+                    ::uno_any_construct(
+                        reinterpret_cast< uno_Any * >( pReturn ),
+                        &pInterface, pTD, 0 );
+                    (*pInterface->release)( pInterface );
+                    TYPELIB_DANGER_RELEASE( pTD );
+                    *ppException = 0;
+                    break;
+                }
+                TYPELIB_DANGER_RELEASE( pTD );
+            }
+        } // else perform queryInterface()
+        default:
+            // dependent dispatch
+            cpp_call(
+                pThis, aVtableSlot,
+                ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
+                ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
+                ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
+                pReturn, pArgs, ppException );
+        }
+        break;
+    }
+    default:
+    {
+        ::com::sun::star::uno::RuntimeException aExc(
+            OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
+            ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
+
+        Type const & rExcType = ::getCppuType( &aExc );
+        // binary identical null reference
+        ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
+    }
+    }
+}
+
+} } }
diff --git a/solenv/gbuild/platform/windows.mk b/solenv/gbuild/platform/windows.mk
index 50dc1baf0518..4377c576353b 100644
--- a/solenv/gbuild/platform/windows.mk
+++ b/solenv/gbuild/platform/windows.mk
@@ -28,7 +28,12 @@ COM := MSC
 gb_TMPDIR:=$(if $(TMPDIR),$(shell cygpath -m $(TMPDIR)),$(shell cygpath -m /tmp))
 gb_MKTEMP := mktemp --tmpdir=$(gb_TMPDIR) gbuild.XXXXXX
 
+ifeq ($(CPUNAME),INTEL)
 gb_AS := ml
+else ifeq ($(CPUNAME),X86_64)
+gb_AS := ml64
+endif
+
 gb_CC := cl
 gb_CXX := cl
 gb_LINK := link


More information about the Libreoffice-commits mailing list