12755751fSHerbert Dürr /**************************************************************
22755751fSHerbert Dürr  *
32755751fSHerbert Dürr  * Licensed to the Apache Software Foundation (ASF) under one
42755751fSHerbert Dürr  * or more contributor license agreements.  See the NOTICE file
52755751fSHerbert Dürr  * distributed with this work for additional information
62755751fSHerbert Dürr  * regarding copyright ownership.  The ASF licenses this file
72755751fSHerbert Dürr  * to you under the Apache License, Version 2.0 (the
82755751fSHerbert Dürr  * "License"); you may not use this file except in compliance
92755751fSHerbert Dürr  * with the License.  You may obtain a copy of the License at
102755751fSHerbert Dürr  *
112755751fSHerbert Dürr  *   http://www.apache.org/licenses/LICENSE-2.0
122755751fSHerbert Dürr  *
132755751fSHerbert Dürr  * Unless required by applicable law or agreed to in writing,
142755751fSHerbert Dürr  * software distributed under the License is distributed on an
152755751fSHerbert Dürr  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
162755751fSHerbert Dürr  * KIND, either express or implied.  See the License for the
172755751fSHerbert Dürr  * specific language governing permissions and limitations
182755751fSHerbert Dürr  * under the License.
192755751fSHerbert Dürr  *
202755751fSHerbert Dürr  *************************************************************/
212755751fSHerbert Dürr 
222755751fSHerbert Dürr 
232755751fSHerbert Dürr 
242755751fSHerbert Dürr // MARKER(update_precomp.py): autogen include statement, do not remove
252755751fSHerbert Dürr #include "precompiled_bridges.hxx"
262755751fSHerbert Dürr 
272755751fSHerbert Dürr #include <exception>
282755751fSHerbert Dürr #include <typeinfo>
292755751fSHerbert Dürr #include <stdio.h>
302755751fSHerbert Dürr #include <stdlib.h>
312755751fSHerbert Dürr #include <string.h>
322755751fSHerbert Dürr 
332755751fSHerbert Dürr #include "rtl/alloc.h"
342755751fSHerbert Dürr #include "rtl/ustrbuf.hxx"
352755751fSHerbert Dürr 
362755751fSHerbert Dürr #include <com/sun/star/uno/genfunc.hxx>
372755751fSHerbert Dürr #include "com/sun/star/uno/RuntimeException.hpp"
382755751fSHerbert Dürr #include <uno/data.h>
392755751fSHerbert Dürr 
402755751fSHerbert Dürr #include <bridges/cpp_uno/shared/bridge.hxx>
412755751fSHerbert Dürr #include <bridges/cpp_uno/shared/types.hxx>
422755751fSHerbert Dürr #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
432755751fSHerbert Dürr #include "bridges/cpp_uno/shared/vtables.hxx"
442755751fSHerbert Dürr 
452755751fSHerbert Dürr #include "abi.hxx"
462755751fSHerbert Dürr #include "share.hxx"
472755751fSHerbert Dürr 
482755751fSHerbert Dürr using namespace ::rtl;
492755751fSHerbert Dürr using namespace ::com::sun::star::uno;
502755751fSHerbert Dürr 
512755751fSHerbert Dürr //==================================================================================================
522755751fSHerbert Dürr static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
532755751fSHerbert Dürr                               void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
542755751fSHerbert Dürr                               sal_uInt64 *pStack, sal_uInt32 nStack,
552755751fSHerbert Dürr                               sal_uInt64 *pGPR, sal_uInt32 nGPR,
562755751fSHerbert Dürr                               double *pFPR, sal_uInt32 nFPR) __attribute__((noinline));
572755751fSHerbert Dürr 
callVirtualMethod(void * pThis,sal_uInt32 nVtableIndex,void * pRegisterReturn,typelib_TypeDescriptionReference * pReturnTypeRef,bool bSimpleReturn,sal_uInt64 * pStack,sal_uInt32 nStack,sal_uInt64 * pGPR,sal_uInt32 nGPR,double * pFPR,sal_uInt32 nFPR)582755751fSHerbert Dürr static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
592755751fSHerbert Dürr                               void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
602755751fSHerbert Dürr                               sal_uInt64 *pStack, sal_uInt32 nStack,
612755751fSHerbert Dürr                               sal_uInt64 *pGPR, sal_uInt32 nGPR,
622755751fSHerbert Dürr                               double *pFPR, sal_uInt32 nFPR)
632755751fSHerbert Dürr {
642755751fSHerbert Dürr #if OSL_DEBUG_LEVEL > 1
652755751fSHerbert Dürr     // Let's figure out what is really going on here
662755751fSHerbert Dürr     {
672755751fSHerbert Dürr         fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
682755751fSHerbert Dürr         for ( unsigned int i = 0; i < nGPR; ++i )
692755751fSHerbert Dürr             fprintf( stderr, "0x%lx, ", pGPR[i] );
702755751fSHerbert Dürr         fprintf( stderr, "\nFPR's (%d): ", nFPR );
712755751fSHerbert Dürr         for ( unsigned int i = 0; i < nFPR; ++i )
722755751fSHerbert Dürr             fprintf( stderr, "%f, ", pFPR[i] );
732755751fSHerbert Dürr         fprintf( stderr, "\nStack (%d): ", nStack );
742755751fSHerbert Dürr         for ( unsigned int i = 0; i < nStack; ++i )
752755751fSHerbert Dürr             fprintf( stderr, "0x%lx, ", pStack[i] );
762755751fSHerbert Dürr         fprintf( stderr, "\n" );
772755751fSHerbert Dürr     }
782755751fSHerbert Dürr #endif
792755751fSHerbert Dürr 
802755751fSHerbert Dürr     // The call instruction within the asm section of callVirtualMethod may throw
812755751fSHerbert Dürr     // exceptions.  So that the compiler handles this correctly, it is important
822755751fSHerbert Dürr     // that (a) callVirtualMethod might call dummy_can_throw_anything (although this
832755751fSHerbert Dürr     // never happens at runtime), which in turn can throw exceptions, and (b)
842755751fSHerbert Dürr     // callVirtualMethod is not inlined at its call site (so that any exceptions are
852755751fSHerbert Dürr     // caught which are thrown from the instruction calling callVirtualMethod):
862755751fSHerbert Dürr     if ( !pThis )
872755751fSHerbert Dürr         CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something
882755751fSHerbert Dürr 
892755751fSHerbert Dürr     // Should not happen, but...
902755751fSHerbert Dürr     if ( nFPR > x86_64::MAX_SSE_REGS )
912755751fSHerbert Dürr         nFPR = x86_64::MAX_SSE_REGS;
922755751fSHerbert Dürr     if ( nGPR > x86_64::MAX_GPR_REGS )
932755751fSHerbert Dürr         nGPR = x86_64::MAX_GPR_REGS;
942755751fSHerbert Dürr 
952755751fSHerbert Dürr     // Get pointer to method
962755751fSHerbert Dürr     sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
972755751fSHerbert Dürr     pMethod += 8 * nVtableIndex;
982755751fSHerbert Dürr     pMethod = *((sal_uInt64 *)pMethod);
992755751fSHerbert Dürr 
1002755751fSHerbert Dürr     // Load parameters to stack, if necessary
1013f6fbc83SHerbert Dürr     sal_uInt64* pCallStack = NULL;
1022755751fSHerbert Dürr     if ( nStack )
1032755751fSHerbert Dürr     {
1042755751fSHerbert Dürr         // 16-bytes aligned
1052755751fSHerbert Dürr         sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 16;
1063f6fbc83SHerbert Dürr         pCallStack = (sal_uInt64*) __builtin_alloca( nStackBytes );
1072755751fSHerbert Dürr         memcpy( pCallStack, pStack, nStackBytes );
1082755751fSHerbert Dürr     }
1092755751fSHerbert Dürr 
1102755751fSHerbert Dürr     // Return values
1112755751fSHerbert Dürr     sal_uInt64 rax;
1122755751fSHerbert Dürr     sal_uInt64 rdx;
1132755751fSHerbert Dürr     double xmm0;
1142755751fSHerbert Dürr     double xmm1;
1152755751fSHerbert Dürr 
1162755751fSHerbert Dürr     asm volatile (
1172755751fSHerbert Dürr         // Fill the xmm registers
1182755751fSHerbert Dürr         "movq %2, %%rax\n\t"
1192755751fSHerbert Dürr 
1202755751fSHerbert Dürr         "movsd   (%%rax), %%xmm0\n\t"
1212755751fSHerbert Dürr         "movsd  8(%%rax), %%xmm1\n\t"
1222755751fSHerbert Dürr         "movsd 16(%%rax), %%xmm2\n\t"
1232755751fSHerbert Dürr         "movsd 24(%%rax), %%xmm3\n\t"
1242755751fSHerbert Dürr         "movsd 32(%%rax), %%xmm4\n\t"
1252755751fSHerbert Dürr         "movsd 40(%%rax), %%xmm5\n\t"
1262755751fSHerbert Dürr         "movsd 48(%%rax), %%xmm6\n\t"
1272755751fSHerbert Dürr         "movsd 56(%%rax), %%xmm7\n\t"
1282755751fSHerbert Dürr 
1292755751fSHerbert Dürr         // Fill the general purpose registers
1302755751fSHerbert Dürr         "movq %1, %%rax\n\t"
1312755751fSHerbert Dürr 
1322755751fSHerbert Dürr         "movq    (%%rax), %%rdi\n\t"
1332755751fSHerbert Dürr         "movq   8(%%rax), %%rsi\n\t"
1342755751fSHerbert Dürr         "movq  16(%%rax), %%rdx\n\t"
1352755751fSHerbert Dürr         "movq  24(%%rax), %%rcx\n\t"
1362755751fSHerbert Dürr         "movq  32(%%rax), %%r8\n\t"
1372755751fSHerbert Dürr         "movq  40(%%rax), %%r9\n\t"
1382755751fSHerbert Dürr 
1392755751fSHerbert Dürr         // Perform the call
1402755751fSHerbert Dürr         "movq %0, %%r11\n\t"
1412755751fSHerbert Dürr         "movq %3, %%rax\n\t"
1422755751fSHerbert Dürr         "call *%%r11\n\t"
1432755751fSHerbert Dürr 
1442755751fSHerbert Dürr         // Fill the return values
1452755751fSHerbert Dürr         "movq   %%rax, %4\n\t"
1462755751fSHerbert Dürr         "movq   %%rdx, %5\n\t"
1472755751fSHerbert Dürr         "movsd %%xmm0, %6\n\t"
1482755751fSHerbert Dürr         "movsd %%xmm1, %7\n\t"
1492755751fSHerbert Dürr         :
1502755751fSHerbert Dürr         : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR ),
1513f6fbc83SHerbert Dürr           "m" ( rax ), "m" ( rdx ), "m" ( xmm0 ), "m" ( xmm1 ),
152*67a794bcSJim Jagielski           "m" (pCallStack) // dummy input to prevent the compiler from optimizing the alloca out
1533f6fbc83SHerbert Dürr         : "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9",
1543f6fbc83SHerbert Dürr           "r10", "r11", "r10", "r12", "r13", "r14", "r15", "rbx",
1553f6fbc83SHerbert Dürr           "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
1562755751fSHerbert Dürr     );
1572755751fSHerbert Dürr 
1582755751fSHerbert Dürr     switch (pReturnTypeRef->eTypeClass)
1592755751fSHerbert Dürr     {
1602755751fSHerbert Dürr     case typelib_TypeClass_HYPER:
1612755751fSHerbert Dürr     case typelib_TypeClass_UNSIGNED_HYPER:
1622755751fSHerbert Dürr         *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = rax;
1632755751fSHerbert Dürr         break;
1642755751fSHerbert Dürr     case typelib_TypeClass_LONG:
1652755751fSHerbert Dürr     case typelib_TypeClass_UNSIGNED_LONG:
1662755751fSHerbert Dürr     case typelib_TypeClass_ENUM:
1672755751fSHerbert Dürr         *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &rax );
1682755751fSHerbert Dürr         break;
1692755751fSHerbert Dürr     case typelib_TypeClass_CHAR:
1702755751fSHerbert Dürr     case typelib_TypeClass_SHORT:
1712755751fSHerbert Dürr     case typelib_TypeClass_UNSIGNED_SHORT:
1722755751fSHerbert Dürr         *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &rax );
1732755751fSHerbert Dürr         break;
1742755751fSHerbert Dürr     case typelib_TypeClass_BOOLEAN:
1752755751fSHerbert Dürr     case typelib_TypeClass_BYTE:
1762755751fSHerbert Dürr         *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &rax );
1772755751fSHerbert Dürr         break;
1782755751fSHerbert Dürr     case typelib_TypeClass_FLOAT:
1792755751fSHerbert Dürr     case typelib_TypeClass_DOUBLE:
1802755751fSHerbert Dürr         *reinterpret_cast<double *>( pRegisterReturn ) = xmm0;
1812755751fSHerbert Dürr         break;
1822755751fSHerbert Dürr     default:
1832755751fSHerbert Dürr         {
1842755751fSHerbert Dürr             sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
1852755751fSHerbert Dürr             if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
1862755751fSHerbert Dürr             {
1872755751fSHerbert Dürr                 sal_uInt64 longs[2];
1882755751fSHerbert Dürr                 longs[0] = rax;
1892755751fSHerbert Dürr                 longs[1] = rdx;
1902755751fSHerbert Dürr 
1912755751fSHerbert Dürr                 double doubles[2];
1922755751fSHerbert Dürr                 doubles[0] = xmm0;
1932755751fSHerbert Dürr                 doubles[1] = xmm1;
1942755751fSHerbert Dürr                 x86_64::fill_struct( pReturnTypeRef, &longs[0], &doubles[0], pRegisterReturn);
1952755751fSHerbert Dürr             }
1962755751fSHerbert Dürr             break;
1972755751fSHerbert Dürr         }
1982755751fSHerbert Dürr     }
1992755751fSHerbert Dürr }
2002755751fSHerbert Dürr 
2012755751fSHerbert Dürr //==================================================================================================
2022755751fSHerbert Dürr 
2032755751fSHerbert Dürr // Macros for easier insertion of values to registers or stack
2042755751fSHerbert Dürr // pSV - pointer to the source
2052755751fSHerbert Dürr // nr - order of the value [will be increased if stored to register]
2062755751fSHerbert Dürr // pFPR, pGPR - pointer to the registers
2072755751fSHerbert Dürr // pDS - pointer to the stack [will be increased if stored here]
2082755751fSHerbert Dürr 
2092755751fSHerbert Dürr // The value in %xmm register is already prepared to be retrieved as a float,
2102755751fSHerbert Dürr // thus we treat float and double the same
2112755751fSHerbert Dürr #define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \
2122755751fSHerbert Dürr 	if ( nr < x86_64::MAX_SSE_REGS ) \
2132755751fSHerbert Dürr 		pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
2142755751fSHerbert Dürr 	else \
2152755751fSHerbert Dürr 		*pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
2162755751fSHerbert Dürr 
2172755751fSHerbert Dürr #define INSERT_INT64( pSV, nr, pGPR, pDS ) \
2182755751fSHerbert Dürr 	if ( nr < x86_64::MAX_GPR_REGS ) \
2192755751fSHerbert Dürr 		pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
2202755751fSHerbert Dürr 	else \
2212755751fSHerbert Dürr 		*pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
2222755751fSHerbert Dürr 
2232755751fSHerbert Dürr #define INSERT_INT32( pSV, nr, pGPR, pDS ) \
2242755751fSHerbert Dürr 	if ( nr < x86_64::MAX_GPR_REGS ) \
2252755751fSHerbert Dürr 		pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
2262755751fSHerbert Dürr 	else \
2272755751fSHerbert Dürr 		*pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
2282755751fSHerbert Dürr 
2292755751fSHerbert Dürr #define INSERT_INT16( pSV, nr, pGPR, pDS ) \
2302755751fSHerbert Dürr 	if ( nr < x86_64::MAX_GPR_REGS ) \
2312755751fSHerbert Dürr 		pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
2322755751fSHerbert Dürr 	else \
2332755751fSHerbert Dürr 		*pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
2342755751fSHerbert Dürr 
2352755751fSHerbert Dürr #define INSERT_INT8( pSV, nr, pGPR, pDS ) \
2362755751fSHerbert Dürr 	if ( nr < x86_64::MAX_GPR_REGS ) \
2372755751fSHerbert Dürr 		pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
2382755751fSHerbert Dürr 	else \
2392755751fSHerbert Dürr 		*pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
2402755751fSHerbert Dürr 
2412755751fSHerbert Dürr //==================================================================================================
2422755751fSHerbert Dürr 
2432755751fSHerbert Dürr namespace {
2442755751fSHerbert Dürr 
appendCString(OUStringBuffer & buffer,char const * text)2452755751fSHerbert Dürr void appendCString(OUStringBuffer & buffer, char const * text) {
2462755751fSHerbert Dürr     if (text != 0) {
2472755751fSHerbert Dürr         buffer.append(
2482755751fSHerbert Dürr             OStringToOUString(OString(text), RTL_TEXTENCODING_ISO_8859_1));
2492755751fSHerbert Dürr             // use 8859-1 to avoid conversion failure
2502755751fSHerbert Dürr     }
2512755751fSHerbert Dürr }
2522755751fSHerbert Dürr 
2532755751fSHerbert Dürr }
2542755751fSHerbert Dürr 
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)2552755751fSHerbert Dürr static void cpp_call(
2562755751fSHerbert Dürr 	bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
2572755751fSHerbert Dürr 	bridges::cpp_uno::shared::VtableSlot aVtableSlot,
2582755751fSHerbert Dürr 	typelib_TypeDescriptionReference * pReturnTypeRef,
2592755751fSHerbert Dürr 	sal_Int32 nParams, typelib_MethodParameter * pParams,
2602755751fSHerbert Dürr 	void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
2612755751fSHerbert Dürr {
2622755751fSHerbert Dürr 	// Maxium space for [complex ret ptr], values | ptr ...
2632755751fSHerbert Dürr 	// (but will be used less - some of the values will be in pGPR and pFPR)
2642755751fSHerbert Dürr   	sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) );
2652755751fSHerbert Dürr   	sal_uInt64 *pStackStart = pStack;
2662755751fSHerbert Dürr 
2672755751fSHerbert Dürr 	sal_uInt64 pGPR[x86_64::MAX_GPR_REGS];
2682755751fSHerbert Dürr 	sal_uInt32 nGPR = 0;
2692755751fSHerbert Dürr 
2702755751fSHerbert Dürr 	double pFPR[x86_64::MAX_SSE_REGS];
2712755751fSHerbert Dürr 	sal_uInt32 nFPR = 0;
2722755751fSHerbert Dürr 
2732755751fSHerbert Dürr 	// Return
2742755751fSHerbert Dürr 	typelib_TypeDescription * pReturnTypeDescr = 0;
2752755751fSHerbert Dürr 	TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
2762755751fSHerbert Dürr 	OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
2772755751fSHerbert Dürr 
2782755751fSHerbert Dürr 	void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below)
2792755751fSHerbert Dürr 
2802755751fSHerbert Dürr 	bool bSimpleReturn = true;
2812755751fSHerbert Dürr 	if ( pReturnTypeDescr )
2822755751fSHerbert Dürr 	{
2832755751fSHerbert Dürr 		if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
2842755751fSHerbert Dürr 			bSimpleReturn = false;
2852755751fSHerbert Dürr 
2862755751fSHerbert Dürr 		if ( bSimpleReturn )
2872755751fSHerbert Dürr 			pCppReturn = pUnoReturn; // direct way for simple types
2882755751fSHerbert Dürr 		else
2892755751fSHerbert Dürr 		{
2902755751fSHerbert Dürr 			// complex return via ptr
2912755751fSHerbert Dürr 			pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
2922755751fSHerbert Dürr 						 __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
2932755751fSHerbert Dürr 			INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack );
2942755751fSHerbert Dürr 		}
2952755751fSHerbert Dürr 	}
2962755751fSHerbert Dürr 
2972755751fSHerbert Dürr 	// Push "this" pointer
2982755751fSHerbert Dürr 	void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
2992755751fSHerbert Dürr 	INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
3002755751fSHerbert Dürr 
3012755751fSHerbert Dürr 	// Args
3022755751fSHerbert Dürr 	void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
3032755751fSHerbert Dürr 	// Indizes of values this have to be converted (interface conversion cpp<=>uno)
3042755751fSHerbert Dürr 	sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
3052755751fSHerbert Dürr 	// Type descriptions for reconversions
3062755751fSHerbert Dürr 	typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
3072755751fSHerbert Dürr 
3082755751fSHerbert Dürr 	sal_Int32 nTempIndizes = 0;
3092755751fSHerbert Dürr 
3102755751fSHerbert Dürr 	for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
3112755751fSHerbert Dürr 	{
3122755751fSHerbert Dürr 		const typelib_MethodParameter & rParam = pParams[nPos];
3132755751fSHerbert Dürr 		typelib_TypeDescription * pParamTypeDescr = 0;
3142755751fSHerbert Dürr 		TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
3152755751fSHerbert Dürr 
3162755751fSHerbert Dürr 		if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
3172755751fSHerbert Dürr 		{
3182755751fSHerbert Dürr 			uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
3192755751fSHerbert Dürr 									pThis->getBridge()->getUno2Cpp() );
3202755751fSHerbert Dürr 
3212755751fSHerbert Dürr 			switch (pParamTypeDescr->eTypeClass)
3222755751fSHerbert Dürr 			{
3232755751fSHerbert Dürr 			case typelib_TypeClass_HYPER:
3242755751fSHerbert Dürr 			case typelib_TypeClass_UNSIGNED_HYPER:
3252755751fSHerbert Dürr 				INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
3262755751fSHerbert Dürr 				break;
3272755751fSHerbert Dürr 			case typelib_TypeClass_LONG:
3282755751fSHerbert Dürr 			case typelib_TypeClass_UNSIGNED_LONG:
3292755751fSHerbert Dürr 			case typelib_TypeClass_ENUM:
3302755751fSHerbert Dürr 				INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
3312755751fSHerbert Dürr 				break;
3322755751fSHerbert Dürr 			case typelib_TypeClass_SHORT:
3332755751fSHerbert Dürr 			case typelib_TypeClass_CHAR:
3342755751fSHerbert Dürr 			case typelib_TypeClass_UNSIGNED_SHORT:
3352755751fSHerbert Dürr 				INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
3362755751fSHerbert Dürr 				break;
3372755751fSHerbert Dürr 			case typelib_TypeClass_BOOLEAN:
3382755751fSHerbert Dürr 			case typelib_TypeClass_BYTE:
3392755751fSHerbert Dürr 				INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
3402755751fSHerbert Dürr 				break;
3412755751fSHerbert Dürr 			case typelib_TypeClass_FLOAT:
3422755751fSHerbert Dürr 			case typelib_TypeClass_DOUBLE:
3432755751fSHerbert Dürr 				INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
3442755751fSHerbert Dürr 				break;
3452755751fSHerbert Dürr 			default:
3462755751fSHerbert Dürr 				break;
3472755751fSHerbert Dürr 			}
3482755751fSHerbert Dürr 
3492755751fSHerbert Dürr 			// no longer needed
3502755751fSHerbert Dürr 			TYPELIB_DANGER_RELEASE( pParamTypeDescr );
3512755751fSHerbert Dürr 		}
3522755751fSHerbert Dürr 		else // ptr to complex value | ref
3532755751fSHerbert Dürr 		{
3542755751fSHerbert Dürr 			if (! rParam.bIn) // is pure out
3552755751fSHerbert Dürr 			{
3562755751fSHerbert Dürr 				// cpp out is constructed mem, uno out is not!
3572755751fSHerbert Dürr 				uno_constructData(
3582755751fSHerbert Dürr 					pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
3592755751fSHerbert Dürr 					pParamTypeDescr );
3602755751fSHerbert Dürr 				pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
3612755751fSHerbert Dürr 				// will be released at reconversion
3622755751fSHerbert Dürr 				ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
3632755751fSHerbert Dürr 			}
3642755751fSHerbert Dürr 			// is in/inout
3652755751fSHerbert Dürr 			else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
3662755751fSHerbert Dürr 			{
3672755751fSHerbert Dürr 				uno_copyAndConvertData(
3682755751fSHerbert Dürr 					pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
3692755751fSHerbert Dürr 					pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
3702755751fSHerbert Dürr 
3712755751fSHerbert Dürr 				pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
3722755751fSHerbert Dürr 				// will be released at reconversion
3732755751fSHerbert Dürr 				ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
3742755751fSHerbert Dürr 			}
3752755751fSHerbert Dürr 			else // direct way
3762755751fSHerbert Dürr 			{
3772755751fSHerbert Dürr 				pCppArgs[nPos] = pUnoArgs[nPos];
3782755751fSHerbert Dürr 				// no longer needed
3792755751fSHerbert Dürr 				TYPELIB_DANGER_RELEASE( pParamTypeDescr );
3802755751fSHerbert Dürr 			}
3812755751fSHerbert Dürr 			INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
3822755751fSHerbert Dürr 		}
3832755751fSHerbert Dürr 	}
3842755751fSHerbert Dürr 
3852755751fSHerbert Dürr 	try
3862755751fSHerbert Dürr 	{
3872755751fSHerbert Dürr         try {
3882755751fSHerbert Dürr             callVirtualMethod(
3892755751fSHerbert Dürr                 pAdjustedThisPtr, aVtableSlot.index,
3902755751fSHerbert Dürr                 pCppReturn, pReturnTypeRef, bSimpleReturn,
3912755751fSHerbert Dürr                 pStackStart, ( pStack - pStackStart ),
3922755751fSHerbert Dürr                 pGPR, nGPR,
3932755751fSHerbert Dürr                 pFPR, nFPR );
3942755751fSHerbert Dürr         } catch (Exception &) {
3952755751fSHerbert Dürr             throw;
3962755751fSHerbert Dürr         } catch (std::exception & e) {
3972755751fSHerbert Dürr             OUStringBuffer buf;
3982755751fSHerbert Dürr             buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("C++ code threw "));
3992755751fSHerbert Dürr             appendCString(buf, typeid(e).name());
4002755751fSHerbert Dürr             buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": "));
4012755751fSHerbert Dürr             appendCString(buf, e.what());
4022755751fSHerbert Dürr             throw RuntimeException(
4032755751fSHerbert Dürr                 buf.makeStringAndClear(), Reference< XInterface >());
4042755751fSHerbert Dürr         } catch (...) {
4052755751fSHerbert Dürr             throw RuntimeException(
4062755751fSHerbert Dürr                 OUString(
4072755751fSHerbert Dürr                     RTL_CONSTASCII_USTRINGPARAM(
4082755751fSHerbert Dürr                         "C++ code threw unknown exception")),
4092755751fSHerbert Dürr                 Reference< XInterface >());
4102755751fSHerbert Dürr         }
4112755751fSHerbert Dürr 
412*67a794bcSJim Jagielski 		// NO exception occurred...
4132755751fSHerbert Dürr 		*ppUnoExc = 0;
4142755751fSHerbert Dürr 
4152755751fSHerbert Dürr 		// reconvert temporary params
4162755751fSHerbert Dürr 		for ( ; nTempIndizes--; )
4172755751fSHerbert Dürr 		{
4182755751fSHerbert Dürr 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
4192755751fSHerbert Dürr 			typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
4202755751fSHerbert Dürr 
4212755751fSHerbert Dürr 			if (pParams[nIndex].bIn)
4222755751fSHerbert Dürr 			{
4232755751fSHerbert Dürr 				if (pParams[nIndex].bOut) // inout
4242755751fSHerbert Dürr 				{
4252755751fSHerbert Dürr 					uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
4262755751fSHerbert Dürr 					uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
4272755751fSHerbert Dürr 											pThis->getBridge()->getCpp2Uno() );
4282755751fSHerbert Dürr 				}
4292755751fSHerbert Dürr 			}
4302755751fSHerbert Dürr 			else // pure out
4312755751fSHerbert Dürr 			{
4322755751fSHerbert Dürr 				uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
4332755751fSHerbert Dürr 										pThis->getBridge()->getCpp2Uno() );
4342755751fSHerbert Dürr 			}
4352755751fSHerbert Dürr 			// destroy temp cpp param => cpp: every param was constructed
4362755751fSHerbert Dürr 			uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
4372755751fSHerbert Dürr 
4382755751fSHerbert Dürr 			TYPELIB_DANGER_RELEASE( pParamTypeDescr );
4392755751fSHerbert Dürr 		}
4402755751fSHerbert Dürr 		// return value
4412755751fSHerbert Dürr 		if (pCppReturn && pUnoReturn != pCppReturn)
4422755751fSHerbert Dürr 		{
4432755751fSHerbert Dürr 			uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
4442755751fSHerbert Dürr 									pThis->getBridge()->getCpp2Uno() );
4452755751fSHerbert Dürr 			uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
4462755751fSHerbert Dürr 		}
4472755751fSHerbert Dürr 	}
4482755751fSHerbert Dürr  	catch (...)
4492755751fSHerbert Dürr  	{
4502755751fSHerbert Dürr   		// fill uno exception
4512755751fSHerbert Dürr 		fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
4522755751fSHerbert Dürr 
4532755751fSHerbert Dürr 		// temporary params
4542755751fSHerbert Dürr 		for ( ; nTempIndizes--; )
4552755751fSHerbert Dürr 		{
4562755751fSHerbert Dürr 			sal_Int32 nIndex = pTempIndizes[nTempIndizes];
4572755751fSHerbert Dürr 			// destroy temp cpp param => cpp: every param was constructed
4582755751fSHerbert Dürr 			uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
4592755751fSHerbert Dürr 			TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
4602755751fSHerbert Dürr 		}
4612755751fSHerbert Dürr 		// return type
4622755751fSHerbert Dürr 		if (pReturnTypeDescr)
4632755751fSHerbert Dürr 			TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
4642755751fSHerbert Dürr 	}
4652755751fSHerbert Dürr }
4662755751fSHerbert Dürr 
4672755751fSHerbert Dürr //==================================================================================================
4682755751fSHerbert Dürr 
4692755751fSHerbert Dürr namespace bridges { namespace cpp_uno { namespace shared {
4702755751fSHerbert Dürr 
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)4712755751fSHerbert Dürr void unoInterfaceProxyDispatch(
4722755751fSHerbert Dürr 	uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
4732755751fSHerbert Dürr 	void * pReturn, void * pArgs[], uno_Any ** ppException )
4742755751fSHerbert Dürr {
4752755751fSHerbert Dürr 	// is my surrogate
4762755751fSHerbert Dürr 	bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
4772755751fSHerbert Dürr 		= static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
4782755751fSHerbert Dürr #if OSL_DEBUG_LEVEL > 0
4792755751fSHerbert Dürr 	typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
4802755751fSHerbert Dürr #endif
4812755751fSHerbert Dürr 
4822755751fSHerbert Dürr 	switch (pMemberDescr->eTypeClass)
4832755751fSHerbert Dürr 	{
4842755751fSHerbert Dürr 	case typelib_TypeClass_INTERFACE_ATTRIBUTE:
4852755751fSHerbert Dürr 	{
4862755751fSHerbert Dürr #if OSL_DEBUG_LEVEL > 0
4872755751fSHerbert Dürr 		// determine vtable call index
4882755751fSHerbert Dürr 		sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
4892755751fSHerbert Dürr 		OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
4902755751fSHerbert Dürr #endif
4912755751fSHerbert Dürr 		VtableSlot aVtableSlot(
4922755751fSHerbert Dürr 				getVtableSlot(
4932755751fSHerbert Dürr 					reinterpret_cast<
4942755751fSHerbert Dürr 					typelib_InterfaceAttributeTypeDescription const * >(
4952755751fSHerbert Dürr 						pMemberDescr)));
4962755751fSHerbert Dürr 
4972755751fSHerbert Dürr 		if (pReturn)
4982755751fSHerbert Dürr 		{
4992755751fSHerbert Dürr 			// dependent dispatch
5002755751fSHerbert Dürr 			cpp_call(
5012755751fSHerbert Dürr 				pThis, aVtableSlot,
5022755751fSHerbert Dürr 				((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
5032755751fSHerbert Dürr 				0, 0, // no params
5042755751fSHerbert Dürr 				pReturn, pArgs, ppException );
5052755751fSHerbert Dürr 		}
5062755751fSHerbert Dürr 		else
5072755751fSHerbert Dürr 		{
5082755751fSHerbert Dürr 			// is SET
5092755751fSHerbert Dürr 			typelib_MethodParameter aParam;
5102755751fSHerbert Dürr 			aParam.pTypeRef =
5112755751fSHerbert Dürr 				((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
5122755751fSHerbert Dürr 			aParam.bIn		= sal_True;
5132755751fSHerbert Dürr 			aParam.bOut		= sal_False;
5142755751fSHerbert Dürr 
5152755751fSHerbert Dürr 			typelib_TypeDescriptionReference * pReturnTypeRef = 0;
5162755751fSHerbert Dürr 			OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
5172755751fSHerbert Dürr 			typelib_typedescriptionreference_new(
5182755751fSHerbert Dürr 				&pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
5192755751fSHerbert Dürr 
5202755751fSHerbert Dürr 			// dependent dispatch
5212755751fSHerbert Dürr 			aVtableSlot.index += 1; // get, then set method
5222755751fSHerbert Dürr 			cpp_call(
5232755751fSHerbert Dürr 				pThis, aVtableSlot, // get, then set method
5242755751fSHerbert Dürr 				pReturnTypeRef,
5252755751fSHerbert Dürr 				1, &aParam,
5262755751fSHerbert Dürr 				pReturn, pArgs, ppException );
5272755751fSHerbert Dürr 
5282755751fSHerbert Dürr 			typelib_typedescriptionreference_release( pReturnTypeRef );
5292755751fSHerbert Dürr 		}
5302755751fSHerbert Dürr 
5312755751fSHerbert Dürr 		break;
5322755751fSHerbert Dürr 	}
5332755751fSHerbert Dürr 	case typelib_TypeClass_INTERFACE_METHOD:
5342755751fSHerbert Dürr 	{
5352755751fSHerbert Dürr #if OSL_DEBUG_LEVEL > 0
5362755751fSHerbert Dürr 		// determine vtable call index
5372755751fSHerbert Dürr 		sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
5382755751fSHerbert Dürr 		OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
5392755751fSHerbert Dürr #endif
5402755751fSHerbert Dürr 		VtableSlot aVtableSlot(
5412755751fSHerbert Dürr 				getVtableSlot(
5422755751fSHerbert Dürr 					reinterpret_cast<
5432755751fSHerbert Dürr 					typelib_InterfaceMethodTypeDescription const * >(
5442755751fSHerbert Dürr 						pMemberDescr)));
5452755751fSHerbert Dürr 
5462755751fSHerbert Dürr 		switch (aVtableSlot.index)
5472755751fSHerbert Dürr 		{
5482755751fSHerbert Dürr 			// standard calls
5492755751fSHerbert Dürr 		case 1: // acquire uno interface
5502755751fSHerbert Dürr 			(*pUnoI->acquire)( pUnoI );
5512755751fSHerbert Dürr 			*ppException = 0;
5522755751fSHerbert Dürr 			break;
5532755751fSHerbert Dürr 		case 2: // release uno interface
5542755751fSHerbert Dürr 			(*pUnoI->release)( pUnoI );
5552755751fSHerbert Dürr 			*ppException = 0;
5562755751fSHerbert Dürr 			break;
5572755751fSHerbert Dürr 		case 0: // queryInterface() opt
5582755751fSHerbert Dürr 		{
5592755751fSHerbert Dürr 			typelib_TypeDescription * pTD = 0;
5602755751fSHerbert Dürr 			TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
5612755751fSHerbert Dürr 			if (pTD)
5622755751fSHerbert Dürr 			{
5632755751fSHerbert Dürr                 uno_Interface * pInterface = 0;
5642755751fSHerbert Dürr                 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
5652755751fSHerbert Dürr                     pThis->getBridge()->getUnoEnv(),
5662755751fSHerbert Dürr                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
5672755751fSHerbert Dürr 
5682755751fSHerbert Dürr                 if (pInterface)
5692755751fSHerbert Dürr                 {
5702755751fSHerbert Dürr                     ::uno_any_construct(
5712755751fSHerbert Dürr                         reinterpret_cast< uno_Any * >( pReturn ),
5722755751fSHerbert Dürr                         &pInterface, pTD, 0 );
5732755751fSHerbert Dürr                     (*pInterface->release)( pInterface );
5742755751fSHerbert Dürr                     TYPELIB_DANGER_RELEASE( pTD );
5752755751fSHerbert Dürr                     *ppException = 0;
5762755751fSHerbert Dürr                     break;
5772755751fSHerbert Dürr                 }
5782755751fSHerbert Dürr                 TYPELIB_DANGER_RELEASE( pTD );
5792755751fSHerbert Dürr             }
5802755751fSHerbert Dürr 		} // else perform queryInterface()
5812755751fSHerbert Dürr 		default:
5822755751fSHerbert Dürr 			// dependent dispatch
5832755751fSHerbert Dürr 			cpp_call(
5842755751fSHerbert Dürr 				pThis, aVtableSlot,
5852755751fSHerbert Dürr 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
5862755751fSHerbert Dürr 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
5872755751fSHerbert Dürr 				((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
5882755751fSHerbert Dürr 				pReturn, pArgs, ppException );
5892755751fSHerbert Dürr 		}
5902755751fSHerbert Dürr 		break;
5912755751fSHerbert Dürr 	}
5922755751fSHerbert Dürr 	default:
5932755751fSHerbert Dürr 	{
5942755751fSHerbert Dürr 		::com::sun::star::uno::RuntimeException aExc(
5952755751fSHerbert Dürr 			OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
5962755751fSHerbert Dürr 			::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
5972755751fSHerbert Dürr 
5982755751fSHerbert Dürr 		Type const & rExcType = ::getCppuType( &aExc );
5992755751fSHerbert Dürr 		// binary identical null reference
6002755751fSHerbert Dürr 		::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
6012755751fSHerbert Dürr 	}
6022755751fSHerbert Dürr 	}
6032755751fSHerbert Dürr }
6042755751fSHerbert Dürr 
6052755751fSHerbert Dürr } } }
606