10bd9e244Spfg /**************************************************************
20bd9e244Spfg  *
30bd9e244Spfg  * Licensed to the Apache Software Foundation (ASF) under one
40bd9e244Spfg  * or more contributor license agreements.  See the NOTICE file
50bd9e244Spfg  * distributed with this work for additional information
60bd9e244Spfg  * regarding copyright ownership.  The ASF licenses this file
70bd9e244Spfg  * to you under the Apache License, Version 2.0 (the
80bd9e244Spfg  * "License"); you may not use this file except in compliance
90bd9e244Spfg  * with the License.  You may obtain a copy of the License at
100bd9e244Spfg  *
110bd9e244Spfg  *   http://www.apache.org/licenses/LICENSE-2.0
120bd9e244Spfg  *
130bd9e244Spfg  * Unless required by applicable law or agreed to in writing,
140bd9e244Spfg  * software distributed under the License is distributed on an
150bd9e244Spfg  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
160bd9e244Spfg  * KIND, either express or implied.  See the License for the
170bd9e244Spfg  * specific language governing permissions and limitations
180bd9e244Spfg  * under the License.
190bd9e244Spfg  *
200bd9e244Spfg  *************************************************************/
210bd9e244Spfg 
220bd9e244Spfg 
230bd9e244Spfg 
24*08797115Spfg #include <stdlib.h>
250bd9e244Spfg #include <rtl/alloc.h>
260bd9e244Spfg 
270bd9e244Spfg #include <com/sun/star/uno/genfunc.hxx>
280bd9e244Spfg #include "com/sun/star/uno/RuntimeException.hpp"
290bd9e244Spfg #include <uno/data.h>
300bd9e244Spfg 
310bd9e244Spfg #include <bridges/cpp_uno/shared/bridge.hxx>
320bd9e244Spfg #include <bridges/cpp_uno/shared/types.hxx>
330bd9e244Spfg #include <bridges/cpp_uno/shared/unointerfaceproxy.hxx>
340bd9e244Spfg #include <bridges/cpp_uno/shared/vtables.hxx>
350bd9e244Spfg 
360bd9e244Spfg #include "share.hxx"
370bd9e244Spfg 
380bd9e244Spfg #include <stdio.h>
390bd9e244Spfg #include <string.h>
400bd9e244Spfg 
410bd9e244Spfg /*
420bd9e244Spfg  * Based on http://gcc.gnu.org/PR41443
430bd9e244Spfg  * References to __SOFTFP__ are incorrect for EABI; the __SOFTFP__ code
440bd9e244Spfg  * should be used for *soft-float ABI* whether or not VFP is enabled,
450bd9e244Spfg  * and __SOFTFP__ does specifically mean soft-float not soft-float ABI.
460bd9e244Spfg  *
470bd9e244Spfg  * Changing the conditionals to __SOFTFP__ || __ARM_EABI__ then
480bd9e244Spfg  * -mfloat-abi=softfp should work.  -mfloat-abi=hard won't; that would
490bd9e244Spfg  * need both a new macro to identify the hard-VFP ABI.
500bd9e244Spfg  */
510bd9e244Spfg #if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
520bd9e244Spfg #error Not Implemented
530bd9e244Spfg 
540bd9e244Spfg /*
550bd9e244Spfg  some possibly handy code to detect that we have VFP registers
560bd9e244Spfg  */
570bd9e244Spfg 
580bd9e244Spfg #include <sys/types.h>
590bd9e244Spfg #include <sys/stat.h>
600bd9e244Spfg #include <fcntl.h>
610bd9e244Spfg #include <unistd.h>
620bd9e244Spfg #include <elf.h>
630bd9e244Spfg 
640bd9e244Spfg #define HWCAP_ARM_VFP 64
650bd9e244Spfg 
hasVFP(void)660bd9e244Spfg int hasVFP(void)
670bd9e244Spfg {
680bd9e244Spfg     int fd = open ("/proc/self/auxv", O_RDONLY);
690bd9e244Spfg     if (fd == -1)
700bd9e244Spfg         return -1;
710bd9e244Spfg 
720bd9e244Spfg     int ret = -1;
730bd9e244Spfg 
740bd9e244Spfg     Elf32_auxv_t buf[128];
750bd9e244Spfg     ssize_t n;
760bd9e244Spfg     while ((ret == -1) && ((n = read(fd, buf, sizeof (buf))) > 0))
770bd9e244Spfg     {
780bd9e244Spfg         for (int i = 0; i < 128; ++i)
790bd9e244Spfg         {
800bd9e244Spfg 	    if (buf[i].a_type == AT_HWCAP)
810bd9e244Spfg 	    {
820bd9e244Spfg                 ret = (buf[i].a_un.a_val & HWCAP_ARM_VFP) ? true : false;
830bd9e244Spfg                 break;
840bd9e244Spfg 	    }
850bd9e244Spfg             else if (buf[i].a_type == AT_NULL)
860bd9e244Spfg             {
870bd9e244Spfg                 ret = -2;
880bd9e244Spfg                 break;
890bd9e244Spfg             }
900bd9e244Spfg         }
910bd9e244Spfg     }
920bd9e244Spfg 
930bd9e244Spfg     close (fd);
940bd9e244Spfg     return ret;
950bd9e244Spfg }
960bd9e244Spfg 
970bd9e244Spfg #endif
980bd9e244Spfg 
990bd9e244Spfg using namespace ::rtl;
1000bd9e244Spfg using namespace ::com::sun::star::uno;
1010bd9e244Spfg 
1020bd9e244Spfg namespace arm
1030bd9e244Spfg {
is_complex_struct(const typelib_TypeDescription * type)1040bd9e244Spfg     bool is_complex_struct(const typelib_TypeDescription * type)
1050bd9e244Spfg     {
1060bd9e244Spfg         const typelib_CompoundTypeDescription * p
1070bd9e244Spfg             = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
1080bd9e244Spfg         for (sal_Int32 i = 0; i < p->nMembers; ++i)
1090bd9e244Spfg         {
1100bd9e244Spfg             if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
1110bd9e244Spfg                 p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
1120bd9e244Spfg             {
1130bd9e244Spfg                 typelib_TypeDescription * t = 0;
1140bd9e244Spfg                 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
1150bd9e244Spfg                 bool b = is_complex_struct(t);
1160bd9e244Spfg                 TYPELIB_DANGER_RELEASE(t);
1170bd9e244Spfg                 if (b) {
1180bd9e244Spfg                     return true;
1190bd9e244Spfg                 }
1200bd9e244Spfg             }
1210bd9e244Spfg             else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
1220bd9e244Spfg                 return true;
1230bd9e244Spfg         }
1240bd9e244Spfg         if (p->pBaseTypeDescription != 0)
1250bd9e244Spfg             return is_complex_struct(&p->pBaseTypeDescription->aBase);
1260bd9e244Spfg         return false;
1270bd9e244Spfg     }
1280bd9e244Spfg 
return_in_hidden_param(typelib_TypeDescriptionReference * pTypeRef)1290bd9e244Spfg     bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
1300bd9e244Spfg     {
1310bd9e244Spfg         if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
1320bd9e244Spfg             return false;
1330bd9e244Spfg         else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
1340bd9e244Spfg         {
1350bd9e244Spfg             typelib_TypeDescription * pTypeDescr = 0;
1360bd9e244Spfg             TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
1370bd9e244Spfg 
1380bd9e244Spfg             //A Composite Type not larger than 4 bytes is returned in r0
1390bd9e244Spfg             bool bRet = pTypeDescr->nSize > 4 || is_complex_struct(pTypeDescr);
1400bd9e244Spfg 
1410bd9e244Spfg             TYPELIB_DANGER_RELEASE( pTypeDescr );
1420bd9e244Spfg             return bRet;
1430bd9e244Spfg         }
1440bd9e244Spfg         return true;
1450bd9e244Spfg     }
1460bd9e244Spfg }
1470bd9e244Spfg 
MapReturn(sal_uInt32 r0,sal_uInt32 r1,typelib_TypeDescriptionReference * pReturnType,sal_uInt32 * pRegisterReturn)1480bd9e244Spfg void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* pRegisterReturn)
1490bd9e244Spfg {
1500bd9e244Spfg #if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
1510bd9e244Spfg     register float fret asm("f0");
1520bd9e244Spfg     register double dret asm("f0");
1530bd9e244Spfg #endif
1540bd9e244Spfg 
1550bd9e244Spfg     switch( pReturnType->eTypeClass )
1560bd9e244Spfg     {
1570bd9e244Spfg         case typelib_TypeClass_HYPER:
1580bd9e244Spfg         case typelib_TypeClass_UNSIGNED_HYPER:
1590bd9e244Spfg             pRegisterReturn[1] = r1;
1600bd9e244Spfg         case typelib_TypeClass_LONG:
1610bd9e244Spfg         case typelib_TypeClass_UNSIGNED_LONG:
1620bd9e244Spfg         case typelib_TypeClass_ENUM:
1630bd9e244Spfg         case typelib_TypeClass_CHAR:
1640bd9e244Spfg         case typelib_TypeClass_SHORT:
1650bd9e244Spfg         case typelib_TypeClass_UNSIGNED_SHORT:
1660bd9e244Spfg         case typelib_TypeClass_BOOLEAN:
1670bd9e244Spfg         case typelib_TypeClass_BYTE:
1680bd9e244Spfg             pRegisterReturn[0] = r0;
1690bd9e244Spfg             break;
1700bd9e244Spfg         case typelib_TypeClass_FLOAT:
1710bd9e244Spfg #if defined(__ARM_EABI__) || defined(__SOFTFP__)
1720bd9e244Spfg             pRegisterReturn[0] = r0;
1730bd9e244Spfg #else
1740bd9e244Spfg             *(float*)pRegisterReturn = fret;
1750bd9e244Spfg #endif
1760bd9e244Spfg 	    break;
1770bd9e244Spfg         case typelib_TypeClass_DOUBLE:
1780bd9e244Spfg #if defined(__ARM_EABI__) || defined(__SOFTFP__)
1790bd9e244Spfg             pRegisterReturn[1] = r1;
1800bd9e244Spfg             pRegisterReturn[0] = r0;
1810bd9e244Spfg #else
1820bd9e244Spfg             *(double*)pRegisterReturn = dret;
1830bd9e244Spfg #endif
1840bd9e244Spfg             break;
1850bd9e244Spfg         case typelib_TypeClass_STRUCT:
1860bd9e244Spfg         case typelib_TypeClass_EXCEPTION:
1870bd9e244Spfg         {
1880bd9e244Spfg             if (!arm::return_in_hidden_param(pReturnType))
1890bd9e244Spfg                 pRegisterReturn[0] = r0;
1900bd9e244Spfg             break;
1910bd9e244Spfg         }
1920bd9e244Spfg         default:
1930bd9e244Spfg             break;
1940bd9e244Spfg     }
1950bd9e244Spfg }
1960bd9e244Spfg 
1970bd9e244Spfg namespace
1980bd9e244Spfg {
1990bd9e244Spfg //================================================================
2000bd9e244Spfg 
2010bd9e244Spfg void callVirtualMethod(
2020bd9e244Spfg     void * pThis,
2030bd9e244Spfg     sal_Int32 nVtableIndex,
2040bd9e244Spfg     void * pRegisterReturn,
2050bd9e244Spfg     typelib_TypeDescriptionReference * pReturnType,
2060bd9e244Spfg     sal_uInt32 *pStack,
2070bd9e244Spfg     sal_uInt32 nStack,
2080bd9e244Spfg     sal_uInt32 *pGPR,
2090bd9e244Spfg     sal_uInt32 nGPR) __attribute__((noinline));
2100bd9e244Spfg 
callVirtualMethod(void * pThis,sal_Int32 nVtableIndex,void * pRegisterReturn,typelib_TypeDescriptionReference * pReturnType,sal_uInt32 * pStack,sal_uInt32 nStack,sal_uInt32 * pGPR,sal_uInt32 nGPR)2110bd9e244Spfg void callVirtualMethod(
2120bd9e244Spfg     void * pThis,
2130bd9e244Spfg     sal_Int32 nVtableIndex,
2140bd9e244Spfg     void * pRegisterReturn,
2150bd9e244Spfg     typelib_TypeDescriptionReference * pReturnType,
2160bd9e244Spfg     sal_uInt32 *pStack,
2170bd9e244Spfg     sal_uInt32 nStack,
2180bd9e244Spfg     sal_uInt32 *pGPR,
2190bd9e244Spfg     sal_uInt32 nGPR)
2200bd9e244Spfg {
2210bd9e244Spfg     // never called
2220bd9e244Spfg     if (! pThis)
2230bd9e244Spfg         CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
2240bd9e244Spfg 
2250bd9e244Spfg     if ( nStack )
2260bd9e244Spfg     {
2270bd9e244Spfg         // 8-bytes aligned
2280bd9e244Spfg         sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 8;
2290bd9e244Spfg         sal_uInt32 *stack = (sal_uInt32 *) __builtin_alloca( nStackBytes );
2300bd9e244Spfg         memcpy( stack, pStack, nStackBytes );
2310bd9e244Spfg     }
2320bd9e244Spfg 
2330bd9e244Spfg     // Should not happen, but...
2340bd9e244Spfg     if ( nGPR > arm::MAX_GPR_REGS )
2350bd9e244Spfg         nGPR = arm::MAX_GPR_REGS;
2360bd9e244Spfg 
2370bd9e244Spfg     sal_uInt32 pMethod = *((sal_uInt32*)pThis);
2380bd9e244Spfg     pMethod += 4 * nVtableIndex;
2390bd9e244Spfg     pMethod = *((sal_uInt32 *)pMethod);
2400bd9e244Spfg 
2410bd9e244Spfg     typedef void (*FunctionCall )( sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32);
2420bd9e244Spfg     FunctionCall pFunc = (FunctionCall)pMethod;
2430bd9e244Spfg 
2440bd9e244Spfg     (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3]);
2450bd9e244Spfg 
2460bd9e244Spfg     sal_uInt32 r0;
2470bd9e244Spfg     sal_uInt32 r1;
2480bd9e244Spfg 
2490bd9e244Spfg     // get return value
2500bd9e244Spfg     __asm__ __volatile__ (
2510bd9e244Spfg         "mov %0, r0\n\t"
2520bd9e244Spfg         "mov %1, r1\n\t"
2530bd9e244Spfg         : "=r" (r0), "=r" (r1) : );
2540bd9e244Spfg 
2550bd9e244Spfg     MapReturn(r0, r1, pReturnType, (sal_uInt32*)pRegisterReturn);
2560bd9e244Spfg }
2570bd9e244Spfg }
2580bd9e244Spfg 
2590bd9e244Spfg #define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow ) \
2600bd9e244Spfg         if ( nr < arm::MAX_GPR_REGS ) \
2610bd9e244Spfg                 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
2620bd9e244Spfg         else \
2630bd9e244Spfg                 bOverFlow = true; \
2640bd9e244Spfg         if (bOverFlow) \
2650bd9e244Spfg                 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
2660bd9e244Spfg 
2670bd9e244Spfg #ifdef __ARM_EABI__
2680bd9e244Spfg #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
2690bd9e244Spfg         if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \
2700bd9e244Spfg         { \
2710bd9e244Spfg             	++nr; \
2720bd9e244Spfg         } \
2730bd9e244Spfg         if ( nr < arm::MAX_GPR_REGS ) \
2740bd9e244Spfg         { \
2750bd9e244Spfg                 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
2760bd9e244Spfg                 pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
2770bd9e244Spfg         } \
2780bd9e244Spfg         else \
2790bd9e244Spfg                 bOverFlow = true; \
2800bd9e244Spfg         if (bOverFlow) \
2810bd9e244Spfg 	{ \
2820bd9e244Spfg 		if ( (pDS - pStart) % 2) \
2830bd9e244Spfg                 { \
2840bd9e244Spfg                 	++pDS; \
2850bd9e244Spfg                 } \
2860bd9e244Spfg                 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \
2870bd9e244Spfg                 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \
2880bd9e244Spfg 	}
2890bd9e244Spfg #else
2900bd9e244Spfg #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
2910bd9e244Spfg         INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow) \
2920bd9e244Spfg         INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS, bOverflow)
2930bd9e244Spfg #endif
2940bd9e244Spfg 
2950bd9e244Spfg #define INSERT_FLOAT( pSV, nr, pFPR, pDS, bOverflow ) \
2960bd9e244Spfg         INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow)
2970bd9e244Spfg 
2980bd9e244Spfg #define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart, bOverflow ) \
2990bd9e244Spfg         INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow )
3000bd9e244Spfg 
3010bd9e244Spfg #define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \
3020bd9e244Spfg         if ( nr < arm::MAX_GPR_REGS ) \
3030bd9e244Spfg                 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
3040bd9e244Spfg         else \
3050bd9e244Spfg                 bOverFlow = true; \
3060bd9e244Spfg         if (bOverFlow) \
3070bd9e244Spfg                 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
3080bd9e244Spfg 
3090bd9e244Spfg #define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \
3100bd9e244Spfg         if ( nr < arm::MAX_GPR_REGS ) \
3110bd9e244Spfg                 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
3120bd9e244Spfg         else \
3130bd9e244Spfg                 bOverFlow = true; \
3140bd9e244Spfg         if (bOverFlow) \
3150bd9e244Spfg                 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
3160bd9e244Spfg 
3170bd9e244Spfg namespace {
3180bd9e244Spfg //=======================================================================
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)3190bd9e244Spfg static void cpp_call(
3200bd9e244Spfg     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
3210bd9e244Spfg     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
3220bd9e244Spfg     typelib_TypeDescriptionReference * pReturnTypeRef,
3230bd9e244Spfg     sal_Int32 nParams, typelib_MethodParameter * pParams,
3240bd9e244Spfg     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
3250bd9e244Spfg {
3260bd9e244Spfg     // max space for: [complex ret ptr], values|ptr ...
3270bd9e244Spfg     sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca(
3280bd9e244Spfg         sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
3290bd9e244Spfg     sal_uInt32 * pStackStart = pStack;
3300bd9e244Spfg 
3310bd9e244Spfg     sal_uInt32 pGPR[arm::MAX_GPR_REGS];
3320bd9e244Spfg     sal_uInt32 nGPR = 0;
3330bd9e244Spfg 
3340bd9e244Spfg     // return
3350bd9e244Spfg     typelib_TypeDescription * pReturnTypeDescr = 0;
3360bd9e244Spfg     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
3370bd9e244Spfg     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
3380bd9e244Spfg 
3390bd9e244Spfg     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
3400bd9e244Spfg 
3410bd9e244Spfg     bool bOverFlow = false;
3420bd9e244Spfg     bool bSimpleReturn = true;
3430bd9e244Spfg     if (pReturnTypeDescr)
3440bd9e244Spfg     {
3450bd9e244Spfg         if (arm::return_in_hidden_param( pReturnTypeRef ) )
3460bd9e244Spfg             bSimpleReturn = false;
3470bd9e244Spfg 
3480bd9e244Spfg         if (bSimpleReturn)
3490bd9e244Spfg             pCppReturn = pUnoReturn; // direct way for simple types
3500bd9e244Spfg         else
3510bd9e244Spfg         {
3520bd9e244Spfg             // complex return via ptr
3530bd9e244Spfg             pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
3540bd9e244Spfg                     ? __builtin_alloca( pReturnTypeDescr->nSize )
3550bd9e244Spfg                     : pUnoReturn); // direct way
3560bd9e244Spfg 
3570bd9e244Spfg             INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack, bOverFlow );
3580bd9e244Spfg         }
3590bd9e244Spfg     }
3600bd9e244Spfg     // push this
3610bd9e244Spfg     void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
3620bd9e244Spfg         + aVtableSlot.offset;
3630bd9e244Spfg     INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow );
3640bd9e244Spfg 
3650bd9e244Spfg     // stack space
3660bd9e244Spfg     OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
3670bd9e244Spfg     // args
3680bd9e244Spfg     void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
3690bd9e244Spfg     // indizes of values this have to be converted (interface conversion cpp<=>uno)
3700bd9e244Spfg     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
3710bd9e244Spfg     // type descriptions for reconversions
3720bd9e244Spfg     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
3730bd9e244Spfg 
3740bd9e244Spfg     sal_Int32 nTempIndizes   = 0;
3750bd9e244Spfg 
3760bd9e244Spfg     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
3770bd9e244Spfg     {
3780bd9e244Spfg         const typelib_MethodParameter & rParam = pParams[nPos];
3790bd9e244Spfg         typelib_TypeDescription * pParamTypeDescr = 0;
3800bd9e244Spfg         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
3810bd9e244Spfg 
3820bd9e244Spfg         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
3830bd9e244Spfg         {
3840bd9e244Spfg //            uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
3850bd9e244Spfg             uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
3860bd9e244Spfg                 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
3870bd9e244Spfg 
3880bd9e244Spfg             switch (pParamTypeDescr->eTypeClass)
3890bd9e244Spfg             {
3900bd9e244Spfg             case typelib_TypeClass_HYPER:
3910bd9e244Spfg             case typelib_TypeClass_UNSIGNED_HYPER:
3920bd9e244Spfg #ifdef CMC_DEBUG
3930bd9e244Spfg 			    fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]);
3940bd9e244Spfg #endif
3950bd9e244Spfg                 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow );
3960bd9e244Spfg                 break;
3970bd9e244Spfg             case typelib_TypeClass_LONG:
3980bd9e244Spfg             case typelib_TypeClass_UNSIGNED_LONG:
3990bd9e244Spfg             case typelib_TypeClass_ENUM:
4000bd9e244Spfg #ifdef CMC_DEBUG
4010bd9e244Spfg 			    fprintf(stderr, "long is %x\n", pCppArgs[nPos]);
4020bd9e244Spfg #endif
4030bd9e244Spfg                 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
4040bd9e244Spfg                 break;
4050bd9e244Spfg             case typelib_TypeClass_SHORT:
4060bd9e244Spfg             case typelib_TypeClass_CHAR:
4070bd9e244Spfg             case typelib_TypeClass_UNSIGNED_SHORT:
4080bd9e244Spfg                 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
4090bd9e244Spfg                 break;
4100bd9e244Spfg             case typelib_TypeClass_BOOLEAN:
4110bd9e244Spfg             case typelib_TypeClass_BYTE:
4120bd9e244Spfg                 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
4130bd9e244Spfg                 break;
4140bd9e244Spfg             case typelib_TypeClass_FLOAT:
4150bd9e244Spfg                 INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
4160bd9e244Spfg 			    break;
4170bd9e244Spfg             case typelib_TypeClass_DOUBLE:
4180bd9e244Spfg                 INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow );
4190bd9e244Spfg                 break;
4200bd9e244Spfg             default:
4210bd9e244Spfg                 break;
4220bd9e244Spfg             }
4230bd9e244Spfg             // no longer needed
4240bd9e244Spfg             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
4250bd9e244Spfg         }
4260bd9e244Spfg         else // ptr to complex value | ref
4270bd9e244Spfg         {
4280bd9e244Spfg             if (! rParam.bIn) // is pure out
4290bd9e244Spfg             {
4300bd9e244Spfg                 // cpp out is constructed mem, uno out is not!
4310bd9e244Spfg                 uno_constructData(
4320bd9e244Spfg                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
4330bd9e244Spfg                     pParamTypeDescr );
4340bd9e244Spfg                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
4350bd9e244Spfg                 // will be released at reconversion
4360bd9e244Spfg                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
4370bd9e244Spfg             }
4380bd9e244Spfg             // is in/inout
4390bd9e244Spfg             else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
4400bd9e244Spfg             {
4410bd9e244Spfg                 uno_copyAndConvertData(
4420bd9e244Spfg                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
4430bd9e244Spfg                     pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
4440bd9e244Spfg 
4450bd9e244Spfg                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
4460bd9e244Spfg                 // will be released at reconversion
4470bd9e244Spfg                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
4480bd9e244Spfg             }
4490bd9e244Spfg             else // direct way
4500bd9e244Spfg             {
4510bd9e244Spfg                 pCppArgs[nPos] = pUnoArgs[nPos];
4520bd9e244Spfg                 // no longer needed
4530bd9e244Spfg                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
4540bd9e244Spfg             }
4550bd9e244Spfg             INSERT_INT32( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow );
4560bd9e244Spfg         }
4570bd9e244Spfg     }
4580bd9e244Spfg 
4590bd9e244Spfg     try
4600bd9e244Spfg     {
4610bd9e244Spfg         callVirtualMethod(
4620bd9e244Spfg             pAdjustedThisPtr, aVtableSlot.index,
4630bd9e244Spfg             pCppReturn, pReturnTypeRef,
4640bd9e244Spfg             pStackStart,
4650bd9e244Spfg             (pStack - pStackStart),
4660bd9e244Spfg             pGPR, nGPR);
4670bd9e244Spfg 
4680bd9e244Spfg         // NO exception occurred...
4690bd9e244Spfg         *ppUnoExc = 0;
4700bd9e244Spfg 
4710bd9e244Spfg         // reconvert temporary params
4720bd9e244Spfg         for ( ; nTempIndizes--; )
4730bd9e244Spfg         {
4740bd9e244Spfg             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
4750bd9e244Spfg             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
4760bd9e244Spfg 
4770bd9e244Spfg             if (pParams[nIndex].bIn)
4780bd9e244Spfg             {
4790bd9e244Spfg                 if (pParams[nIndex].bOut) // inout
4800bd9e244Spfg                 {
4810bd9e244Spfg                     uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
4820bd9e244Spfg                     uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
4830bd9e244Spfg                                             pThis->getBridge()->getCpp2Uno() );
4840bd9e244Spfg                 }
4850bd9e244Spfg             }
4860bd9e244Spfg             else // pure out
4870bd9e244Spfg             {
4880bd9e244Spfg                 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
4890bd9e244Spfg                                         pThis->getBridge()->getCpp2Uno() );
4900bd9e244Spfg             }
4910bd9e244Spfg             // destroy temp cpp param => cpp: every param was constructed
4920bd9e244Spfg             uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
4930bd9e244Spfg 
4940bd9e244Spfg             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
4950bd9e244Spfg         }
4960bd9e244Spfg         // return value
4970bd9e244Spfg         if (pCppReturn && pUnoReturn != pCppReturn)
4980bd9e244Spfg         {
4990bd9e244Spfg             uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
5000bd9e244Spfg                                     pThis->getBridge()->getCpp2Uno() );
5010bd9e244Spfg             uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
5020bd9e244Spfg         }
5030bd9e244Spfg     }
5040bd9e244Spfg     catch (...)
5050bd9e244Spfg     {
5060bd9e244Spfg //        __asm__ __volatile__ ("sub sp, sp, #2048\n");
5070bd9e244Spfg 
5080bd9e244Spfg         // fill uno exception
5090bd9e244Spfg         fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
5100bd9e244Spfg 
5110bd9e244Spfg         // temporary params
5120bd9e244Spfg         for ( ; nTempIndizes--; )
5130bd9e244Spfg         {
5140bd9e244Spfg             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
5150bd9e244Spfg             // destroy temp cpp param => cpp: every param was constructed
5160bd9e244Spfg             uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
5170bd9e244Spfg             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
5180bd9e244Spfg         }
5190bd9e244Spfg 
5200bd9e244Spfg         // return type
5210bd9e244Spfg         if (pReturnTypeDescr)
5220bd9e244Spfg             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
5230bd9e244Spfg     }
5240bd9e244Spfg }
5250bd9e244Spfg }
5260bd9e244Spfg 
5270bd9e244Spfg namespace bridges { namespace cpp_uno { namespace shared {
5280bd9e244Spfg 
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)5290bd9e244Spfg void unoInterfaceProxyDispatch(
5300bd9e244Spfg     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
5310bd9e244Spfg     void * pReturn, void * pArgs[], uno_Any ** ppException )
5320bd9e244Spfg {
5330bd9e244Spfg     // is my surrogate
5340bd9e244Spfg     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
5350bd9e244Spfg           = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
5360bd9e244Spfg #if OSL_DEBUG_LEVEL > 0
5370bd9e244Spfg     typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
5380bd9e244Spfg #endif
5390bd9e244Spfg 
5400bd9e244Spfg     switch (pMemberDescr->eTypeClass)
5410bd9e244Spfg     {
5420bd9e244Spfg     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
5430bd9e244Spfg     {
5440bd9e244Spfg #if OSL_DEBUG_LEVEL > 0
5450bd9e244Spfg         // determine vtable call index
5460bd9e244Spfg         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
5470bd9e244Spfg         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
5480bd9e244Spfg #endif
5490bd9e244Spfg 
5500bd9e244Spfg         VtableSlot aVtableSlot(
5510bd9e244Spfg             getVtableSlot(
5520bd9e244Spfg             reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>
5530bd9e244Spfg               (pMemberDescr)));
5540bd9e244Spfg 
5550bd9e244Spfg         if (pReturn)
5560bd9e244Spfg         {
5570bd9e244Spfg             // dependent dispatch
5580bd9e244Spfg             cpp_call(
5590bd9e244Spfg                 pThis, aVtableSlot,
5600bd9e244Spfg                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
5610bd9e244Spfg                 0, 0, // no params
5620bd9e244Spfg                 pReturn, pArgs, ppException );
5630bd9e244Spfg         }
5640bd9e244Spfg         else
5650bd9e244Spfg         {
5660bd9e244Spfg             // is SET
5670bd9e244Spfg             typelib_MethodParameter aParam;
5680bd9e244Spfg             aParam.pTypeRef =
5690bd9e244Spfg                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
5700bd9e244Spfg             aParam.bIn      = sal_True;
5710bd9e244Spfg             aParam.bOut     = sal_False;
5720bd9e244Spfg 
5730bd9e244Spfg             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
5740bd9e244Spfg             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
5750bd9e244Spfg             typelib_typedescriptionreference_new(
5760bd9e244Spfg                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
5770bd9e244Spfg 
5780bd9e244Spfg             // dependent dispatch
5790bd9e244Spfg             aVtableSlot.index += 1;
5800bd9e244Spfg             cpp_call(
5810bd9e244Spfg                 pThis, aVtableSlot, // get, then set method
5820bd9e244Spfg                 pReturnTypeRef,
5830bd9e244Spfg                 1, &aParam,
5840bd9e244Spfg                 pReturn, pArgs, ppException );
5850bd9e244Spfg 
5860bd9e244Spfg             typelib_typedescriptionreference_release( pReturnTypeRef );
5870bd9e244Spfg         }
5880bd9e244Spfg 
5890bd9e244Spfg         break;
5900bd9e244Spfg     }
5910bd9e244Spfg     case typelib_TypeClass_INTERFACE_METHOD:
5920bd9e244Spfg     {
5930bd9e244Spfg #if OSL_DEBUG_LEVEL > 0
5940bd9e244Spfg         // determine vtable call index
5950bd9e244Spfg         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
5960bd9e244Spfg         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
5970bd9e244Spfg #endif
5980bd9e244Spfg 
5990bd9e244Spfg         VtableSlot aVtableSlot(
6000bd9e244Spfg             getVtableSlot(
6010bd9e244Spfg             reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>
6020bd9e244Spfg               (pMemberDescr)));
6030bd9e244Spfg 
6040bd9e244Spfg         switch (aVtableSlot.index)
6050bd9e244Spfg         {
6060bd9e244Spfg             // standard calls
6070bd9e244Spfg         case 1: // acquire uno interface
6080bd9e244Spfg             (*pUnoI->acquire)( pUnoI );
6090bd9e244Spfg             *ppException = 0;
6100bd9e244Spfg             break;
6110bd9e244Spfg         case 2: // release uno interface
6120bd9e244Spfg             (*pUnoI->release)( pUnoI );
6130bd9e244Spfg             *ppException = 0;
6140bd9e244Spfg             break;
6150bd9e244Spfg         case 0: // queryInterface() opt
6160bd9e244Spfg         {
6170bd9e244Spfg             typelib_TypeDescription * pTD = 0;
6180bd9e244Spfg             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
6190bd9e244Spfg             if (pTD)
6200bd9e244Spfg             {
6210bd9e244Spfg                 uno_Interface * pInterface = 0;
6220bd9e244Spfg                 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
6230bd9e244Spfg                     pThis->getBridge()->getUnoEnv(),
6240bd9e244Spfg                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
6250bd9e244Spfg 
6260bd9e244Spfg                 if (pInterface)
6270bd9e244Spfg                 {
6280bd9e244Spfg                     ::uno_any_construct(
6290bd9e244Spfg                         reinterpret_cast< uno_Any * >( pReturn ),
6300bd9e244Spfg                         &pInterface, pTD, 0 );
6310bd9e244Spfg                     (*pInterface->release)( pInterface );
6320bd9e244Spfg                     TYPELIB_DANGER_RELEASE( pTD );
6330bd9e244Spfg                     *ppException = 0;
6340bd9e244Spfg                     break;
6350bd9e244Spfg                 }
6360bd9e244Spfg                 TYPELIB_DANGER_RELEASE( pTD );
6370bd9e244Spfg             }
6380bd9e244Spfg         } // else perform queryInterface()
6390bd9e244Spfg         default:
6400bd9e244Spfg             // dependent dispatch
6410bd9e244Spfg             cpp_call(
6420bd9e244Spfg                 pThis, aVtableSlot,
6430bd9e244Spfg                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
6440bd9e244Spfg                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
6450bd9e244Spfg                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
6460bd9e244Spfg                 pReturn, pArgs, ppException );
6470bd9e244Spfg         }
6480bd9e244Spfg         break;
6490bd9e244Spfg     }
6500bd9e244Spfg     default:
6510bd9e244Spfg     {
6520bd9e244Spfg         ::com::sun::star::uno::RuntimeException aExc(
6530bd9e244Spfg             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
6540bd9e244Spfg             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
6550bd9e244Spfg 
6560bd9e244Spfg         Type const & rExcType = ::getCppuType( &aExc );
6570bd9e244Spfg         // binary identical null reference
6580bd9e244Spfg         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
6590bd9e244Spfg     }
6600bd9e244Spfg     }
6610bd9e244Spfg }
6620bd9e244Spfg 
6630bd9e244Spfg } } }
6640bd9e244Spfg 
6650bd9e244Spfg /* vi:set tabstop=4 shiftwidth=4 expandtab: */
666