17a46fbe4Spfg /**************************************************************
27a46fbe4Spfg  *
37a46fbe4Spfg  * Licensed to the Apache Software Foundation (ASF) under one
47a46fbe4Spfg  * or more contributor license agreements.  See the NOTICE file
57a46fbe4Spfg  * distributed with this work for additional information
67a46fbe4Spfg  * regarding copyright ownership.  The ASF licenses this file
77a46fbe4Spfg  * to you under the Apache License, Version 2.0 (the
87a46fbe4Spfg  * "License"); you may not use this file except in compliance
97a46fbe4Spfg  * with the License.  You may obtain a copy of the License at
107a46fbe4Spfg  *
117a46fbe4Spfg  *   http://www.apache.org/licenses/LICENSE-2.0
127a46fbe4Spfg  *
137a46fbe4Spfg  * Unless required by applicable law or agreed to in writing,
147a46fbe4Spfg  * software distributed under the License is distributed on an
157a46fbe4Spfg  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
167a46fbe4Spfg  * KIND, either express or implied.  See the License for the
177a46fbe4Spfg  * specific language governing permissions and limitations
187a46fbe4Spfg  * under the License.
197a46fbe4Spfg  *
207a46fbe4Spfg  *************************************************************/
217a46fbe4Spfg 
227a46fbe4Spfg 
237a46fbe4Spfg 
24*7ddd8e27Spfg #include <stdlib.h>
257a46fbe4Spfg #include <rtl/alloc.h>
267a46fbe4Spfg 
277a46fbe4Spfg #include <com/sun/star/uno/genfunc.hxx>
287a46fbe4Spfg #include "com/sun/star/uno/RuntimeException.hpp"
297a46fbe4Spfg #include <uno/data.h>
307a46fbe4Spfg 
317a46fbe4Spfg #include <bridges/cpp_uno/shared/bridge.hxx>
327a46fbe4Spfg #include <bridges/cpp_uno/shared/types.hxx>
337a46fbe4Spfg #include <bridges/cpp_uno/shared/unointerfaceproxy.hxx>
347a46fbe4Spfg #include <bridges/cpp_uno/shared/vtables.hxx>
357a46fbe4Spfg 
367a46fbe4Spfg #include "share.hxx"
377a46fbe4Spfg 
387a46fbe4Spfg #include <stdio.h>
397a46fbe4Spfg #include <string.h>
407a46fbe4Spfg 
417a46fbe4Spfg /*
427a46fbe4Spfg  * Based on http://gcc.gnu.org/PR41443
437a46fbe4Spfg  * References to __SOFTFP__ are incorrect for EABI; the __SOFTFP__ code
447a46fbe4Spfg  * should be used for *soft-float ABI* whether or not VFP is enabled,
457a46fbe4Spfg  * and __SOFTFP__ does specifically mean soft-float not soft-float ABI.
467a46fbe4Spfg  *
477a46fbe4Spfg  * Changing the conditionals to __SOFTFP__ || __ARM_EABI__ then
487a46fbe4Spfg  * -mfloat-abi=softfp should work.  -mfloat-abi=hard won't; that would
497a46fbe4Spfg  * need both a new macro to identify the hard-VFP ABI.
507a46fbe4Spfg  */
517a46fbe4Spfg #if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
527a46fbe4Spfg #error Not Implemented
537a46fbe4Spfg 
547a46fbe4Spfg /*
557a46fbe4Spfg  some possibly handy code to detect that we have VFP registers
567a46fbe4Spfg  */
577a46fbe4Spfg 
587a46fbe4Spfg #include <sys/types.h>
597a46fbe4Spfg #include <sys/stat.h>
607a46fbe4Spfg #include <fcntl.h>
617a46fbe4Spfg #include <unistd.h>
627a46fbe4Spfg #include <elf.h>
637a46fbe4Spfg 
647a46fbe4Spfg #define HWCAP_ARM_VFP 64
657a46fbe4Spfg 
hasVFP(void)667a46fbe4Spfg int hasVFP(void)
677a46fbe4Spfg {
687a46fbe4Spfg     int fd = open ("/proc/self/auxv", O_RDONLY);
697a46fbe4Spfg     if (fd == -1)
707a46fbe4Spfg         return -1;
717a46fbe4Spfg 
727a46fbe4Spfg     int ret = -1;
737a46fbe4Spfg 
747a46fbe4Spfg     Elf32_auxv_t buf[128];
757a46fbe4Spfg     ssize_t n;
767a46fbe4Spfg     while ((ret == -1) && ((n = read(fd, buf, sizeof (buf))) > 0))
777a46fbe4Spfg     {
787a46fbe4Spfg         for (int i = 0; i < 128; ++i)
797a46fbe4Spfg         {
807a46fbe4Spfg 	    if (buf[i].a_type == AT_HWCAP)
817a46fbe4Spfg 	    {
827a46fbe4Spfg                 ret = (buf[i].a_un.a_val & HWCAP_ARM_VFP) ? true : false;
837a46fbe4Spfg                 break;
847a46fbe4Spfg 	    }
857a46fbe4Spfg             else if (buf[i].a_type == AT_NULL)
867a46fbe4Spfg             {
877a46fbe4Spfg                 ret = -2;
887a46fbe4Spfg                 break;
897a46fbe4Spfg             }
907a46fbe4Spfg         }
917a46fbe4Spfg     }
927a46fbe4Spfg 
937a46fbe4Spfg     close (fd);
947a46fbe4Spfg     return ret;
957a46fbe4Spfg }
967a46fbe4Spfg 
977a46fbe4Spfg #endif
987a46fbe4Spfg 
997a46fbe4Spfg using namespace ::rtl;
1007a46fbe4Spfg using namespace ::com::sun::star::uno;
1017a46fbe4Spfg 
1027a46fbe4Spfg namespace arm
1037a46fbe4Spfg {
is_complex_struct(const typelib_TypeDescription * type)1047a46fbe4Spfg     bool is_complex_struct(const typelib_TypeDescription * type)
1057a46fbe4Spfg     {
1067a46fbe4Spfg         const typelib_CompoundTypeDescription * p
1077a46fbe4Spfg             = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
1087a46fbe4Spfg         for (sal_Int32 i = 0; i < p->nMembers; ++i)
1097a46fbe4Spfg         {
1107a46fbe4Spfg             if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
1117a46fbe4Spfg                 p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
1127a46fbe4Spfg             {
1137a46fbe4Spfg                 typelib_TypeDescription * t = 0;
1147a46fbe4Spfg                 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
1157a46fbe4Spfg                 bool b = is_complex_struct(t);
1167a46fbe4Spfg                 TYPELIB_DANGER_RELEASE(t);
1177a46fbe4Spfg                 if (b) {
1187a46fbe4Spfg                     return true;
1197a46fbe4Spfg                 }
1207a46fbe4Spfg             }
1217a46fbe4Spfg             else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
1227a46fbe4Spfg                 return true;
1237a46fbe4Spfg         }
1247a46fbe4Spfg         if (p->pBaseTypeDescription != 0)
1257a46fbe4Spfg             return is_complex_struct(&p->pBaseTypeDescription->aBase);
1267a46fbe4Spfg         return false;
1277a46fbe4Spfg     }
1287a46fbe4Spfg 
return_in_hidden_param(typelib_TypeDescriptionReference * pTypeRef)1297a46fbe4Spfg     bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
1307a46fbe4Spfg     {
1317a46fbe4Spfg         if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
1327a46fbe4Spfg             return false;
1337a46fbe4Spfg         else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
1347a46fbe4Spfg         {
1357a46fbe4Spfg             typelib_TypeDescription * pTypeDescr = 0;
1367a46fbe4Spfg             TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
1377a46fbe4Spfg 
1387a46fbe4Spfg             //A Composite Type not larger than 4 bytes is returned in r0
1397a46fbe4Spfg             bool bRet = pTypeDescr->nSize > 4 || is_complex_struct(pTypeDescr);
1407a46fbe4Spfg 
1417a46fbe4Spfg             TYPELIB_DANGER_RELEASE( pTypeDescr );
1427a46fbe4Spfg             return bRet;
1437a46fbe4Spfg         }
1447a46fbe4Spfg         return true;
1457a46fbe4Spfg     }
1467a46fbe4Spfg }
1477a46fbe4Spfg 
MapReturn(sal_uInt32 r0,sal_uInt32 r1,typelib_TypeDescriptionReference * pReturnType,sal_uInt32 * pRegisterReturn)1487a46fbe4Spfg void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* pRegisterReturn)
1497a46fbe4Spfg {
1507a46fbe4Spfg #if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
1517a46fbe4Spfg     register float fret asm("f0");
1527a46fbe4Spfg     register double dret asm("f0");
1537a46fbe4Spfg #endif
1547a46fbe4Spfg 
1557a46fbe4Spfg     switch( pReturnType->eTypeClass )
1567a46fbe4Spfg     {
1577a46fbe4Spfg         case typelib_TypeClass_HYPER:
1587a46fbe4Spfg         case typelib_TypeClass_UNSIGNED_HYPER:
1597a46fbe4Spfg             pRegisterReturn[1] = r1;
1607a46fbe4Spfg         case typelib_TypeClass_LONG:
1617a46fbe4Spfg         case typelib_TypeClass_UNSIGNED_LONG:
1627a46fbe4Spfg         case typelib_TypeClass_ENUM:
1637a46fbe4Spfg         case typelib_TypeClass_CHAR:
1647a46fbe4Spfg         case typelib_TypeClass_SHORT:
1657a46fbe4Spfg         case typelib_TypeClass_UNSIGNED_SHORT:
1667a46fbe4Spfg         case typelib_TypeClass_BOOLEAN:
1677a46fbe4Spfg         case typelib_TypeClass_BYTE:
1687a46fbe4Spfg             pRegisterReturn[0] = r0;
1697a46fbe4Spfg             break;
1707a46fbe4Spfg         case typelib_TypeClass_FLOAT:
1717a46fbe4Spfg #if defined(__ARM_EABI__) || defined(__SOFTFP__)
1727a46fbe4Spfg             pRegisterReturn[0] = r0;
1737a46fbe4Spfg #else
1747a46fbe4Spfg             *(float*)pRegisterReturn = fret;
1757a46fbe4Spfg #endif
1767a46fbe4Spfg 	    break;
1777a46fbe4Spfg         case typelib_TypeClass_DOUBLE:
1787a46fbe4Spfg #if defined(__ARM_EABI__) || defined(__SOFTFP__)
1797a46fbe4Spfg             pRegisterReturn[1] = r1;
1807a46fbe4Spfg             pRegisterReturn[0] = r0;
1817a46fbe4Spfg #else
1827a46fbe4Spfg             *(double*)pRegisterReturn = dret;
1837a46fbe4Spfg #endif
1847a46fbe4Spfg             break;
1857a46fbe4Spfg         case typelib_TypeClass_STRUCT:
1867a46fbe4Spfg         case typelib_TypeClass_EXCEPTION:
1877a46fbe4Spfg         {
1887a46fbe4Spfg             if (!arm::return_in_hidden_param(pReturnType))
1897a46fbe4Spfg                 pRegisterReturn[0] = r0;
1907a46fbe4Spfg             break;
1917a46fbe4Spfg         }
1927a46fbe4Spfg         default:
1937a46fbe4Spfg             break;
1947a46fbe4Spfg     }
1957a46fbe4Spfg }
1967a46fbe4Spfg 
1977a46fbe4Spfg namespace
1987a46fbe4Spfg {
1997a46fbe4Spfg //================================================================
2007a46fbe4Spfg 
2017a46fbe4Spfg void callVirtualMethod(
2027a46fbe4Spfg     void * pThis,
2037a46fbe4Spfg     sal_Int32 nVtableIndex,
2047a46fbe4Spfg     void * pRegisterReturn,
2057a46fbe4Spfg     typelib_TypeDescriptionReference * pReturnType,
2067a46fbe4Spfg     sal_uInt32 *pStack,
2077a46fbe4Spfg     sal_uInt32 nStack,
2087a46fbe4Spfg     sal_uInt32 *pGPR,
2097a46fbe4Spfg     sal_uInt32 nGPR) __attribute__((noinline));
2107a46fbe4Spfg 
callVirtualMethod(void * pThis,sal_Int32 nVtableIndex,void * pRegisterReturn,typelib_TypeDescriptionReference * pReturnType,sal_uInt32 * pStack,sal_uInt32 nStack,sal_uInt32 * pGPR,sal_uInt32 nGPR)2117a46fbe4Spfg void callVirtualMethod(
2127a46fbe4Spfg     void * pThis,
2137a46fbe4Spfg     sal_Int32 nVtableIndex,
2147a46fbe4Spfg     void * pRegisterReturn,
2157a46fbe4Spfg     typelib_TypeDescriptionReference * pReturnType,
2167a46fbe4Spfg     sal_uInt32 *pStack,
2177a46fbe4Spfg     sal_uInt32 nStack,
2187a46fbe4Spfg     sal_uInt32 *pGPR,
2197a46fbe4Spfg     sal_uInt32 nGPR)
2207a46fbe4Spfg {
2217a46fbe4Spfg     // never called
2227a46fbe4Spfg     if (! pThis)
2237a46fbe4Spfg         CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
2247a46fbe4Spfg 
2257a46fbe4Spfg     if ( nStack )
2267a46fbe4Spfg     {
2277a46fbe4Spfg         // 8-bytes aligned
2287a46fbe4Spfg         sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 8;
2297a46fbe4Spfg         sal_uInt32 *stack = (sal_uInt32 *) __builtin_alloca( nStackBytes );
2307a46fbe4Spfg         memcpy( stack, pStack, nStackBytes );
2317a46fbe4Spfg     }
2327a46fbe4Spfg 
2337a46fbe4Spfg     // Should not happen, but...
2347a46fbe4Spfg     if ( nGPR > arm::MAX_GPR_REGS )
2357a46fbe4Spfg         nGPR = arm::MAX_GPR_REGS;
2367a46fbe4Spfg 
2377a46fbe4Spfg     sal_uInt32 pMethod = *((sal_uInt32*)pThis);
2387a46fbe4Spfg     pMethod += 4 * nVtableIndex;
2397a46fbe4Spfg     pMethod = *((sal_uInt32 *)pMethod);
2407a46fbe4Spfg 
2417a46fbe4Spfg     typedef void (*FunctionCall )( sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32);
2427a46fbe4Spfg     FunctionCall pFunc = (FunctionCall)pMethod;
2437a46fbe4Spfg 
2447a46fbe4Spfg     (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3]);
2457a46fbe4Spfg 
2467a46fbe4Spfg     sal_uInt32 r0;
2477a46fbe4Spfg     sal_uInt32 r1;
2487a46fbe4Spfg 
2497a46fbe4Spfg     // get return value
2507a46fbe4Spfg     __asm__ __volatile__ (
2517a46fbe4Spfg         "mov %0, r0\n\t"
2527a46fbe4Spfg         "mov %1, r1\n\t"
2537a46fbe4Spfg         : "=r" (r0), "=r" (r1) : );
2547a46fbe4Spfg 
2557a46fbe4Spfg     MapReturn(r0, r1, pReturnType, (sal_uInt32*)pRegisterReturn);
2567a46fbe4Spfg }
2577a46fbe4Spfg }
2587a46fbe4Spfg 
2597a46fbe4Spfg #define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow ) \
2607a46fbe4Spfg         if ( nr < arm::MAX_GPR_REGS ) \
2617a46fbe4Spfg                 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
2627a46fbe4Spfg         else \
2637a46fbe4Spfg                 bOverFlow = true; \
2647a46fbe4Spfg         if (bOverFlow) \
2657a46fbe4Spfg                 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
2667a46fbe4Spfg 
2677a46fbe4Spfg #ifdef __ARM_EABI__
2687a46fbe4Spfg #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
2697a46fbe4Spfg         if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \
2707a46fbe4Spfg         { \
2717a46fbe4Spfg             	++nr; \
2727a46fbe4Spfg         } \
2737a46fbe4Spfg         if ( nr < arm::MAX_GPR_REGS ) \
2747a46fbe4Spfg         { \
2757a46fbe4Spfg                 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
2767a46fbe4Spfg                 pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
2777a46fbe4Spfg         } \
2787a46fbe4Spfg         else \
2797a46fbe4Spfg                 bOverFlow = true; \
2807a46fbe4Spfg         if (bOverFlow) \
2817a46fbe4Spfg 	{ \
2827a46fbe4Spfg 		if ( (pDS - pStart) % 2) \
2837a46fbe4Spfg                 { \
2847a46fbe4Spfg                 	++pDS; \
2857a46fbe4Spfg                 } \
2867a46fbe4Spfg                 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \
2877a46fbe4Spfg                 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \
2887a46fbe4Spfg 	}
2897a46fbe4Spfg #else
2907a46fbe4Spfg #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
2917a46fbe4Spfg         INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow) \
2927a46fbe4Spfg         INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS, bOverflow)
2937a46fbe4Spfg #endif
2947a46fbe4Spfg 
2957a46fbe4Spfg #define INSERT_FLOAT( pSV, nr, pFPR, pDS, bOverflow ) \
2967a46fbe4Spfg         INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow)
2977a46fbe4Spfg 
2987a46fbe4Spfg #define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart, bOverflow ) \
2997a46fbe4Spfg         INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow )
3007a46fbe4Spfg 
3017a46fbe4Spfg #define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \
3027a46fbe4Spfg         if ( nr < arm::MAX_GPR_REGS ) \
3037a46fbe4Spfg                 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
3047a46fbe4Spfg         else \
3057a46fbe4Spfg                 bOverFlow = true; \
3067a46fbe4Spfg         if (bOverFlow) \
3077a46fbe4Spfg                 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
3087a46fbe4Spfg 
3097a46fbe4Spfg #define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \
3107a46fbe4Spfg         if ( nr < arm::MAX_GPR_REGS ) \
3117a46fbe4Spfg                 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
3127a46fbe4Spfg         else \
3137a46fbe4Spfg                 bOverFlow = true; \
3147a46fbe4Spfg         if (bOverFlow) \
3157a46fbe4Spfg                 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
3167a46fbe4Spfg 
3177a46fbe4Spfg namespace {
3187a46fbe4Spfg //=======================================================================
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)3197a46fbe4Spfg static void cpp_call(
3207a46fbe4Spfg     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
3217a46fbe4Spfg     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
3227a46fbe4Spfg     typelib_TypeDescriptionReference * pReturnTypeRef,
3237a46fbe4Spfg     sal_Int32 nParams, typelib_MethodParameter * pParams,
3247a46fbe4Spfg     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
3257a46fbe4Spfg {
3267a46fbe4Spfg     // max space for: [complex ret ptr], values|ptr ...
3277a46fbe4Spfg     sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca(
3287a46fbe4Spfg         sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
3297a46fbe4Spfg     sal_uInt32 * pStackStart = pStack;
3307a46fbe4Spfg 
3317a46fbe4Spfg     sal_uInt32 pGPR[arm::MAX_GPR_REGS];
3327a46fbe4Spfg     sal_uInt32 nGPR = 0;
3337a46fbe4Spfg 
3347a46fbe4Spfg     // return
3357a46fbe4Spfg     typelib_TypeDescription * pReturnTypeDescr = 0;
3367a46fbe4Spfg     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
3377a46fbe4Spfg     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
3387a46fbe4Spfg 
3397a46fbe4Spfg     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
3407a46fbe4Spfg 
3417a46fbe4Spfg     bool bOverFlow = false;
3427a46fbe4Spfg     bool bSimpleReturn = true;
3437a46fbe4Spfg     if (pReturnTypeDescr)
3447a46fbe4Spfg     {
3457a46fbe4Spfg         if (arm::return_in_hidden_param( pReturnTypeRef ) )
3467a46fbe4Spfg             bSimpleReturn = false;
3477a46fbe4Spfg 
3487a46fbe4Spfg         if (bSimpleReturn)
3497a46fbe4Spfg             pCppReturn = pUnoReturn; // direct way for simple types
3507a46fbe4Spfg         else
3517a46fbe4Spfg         {
3527a46fbe4Spfg             // complex return via ptr
3537a46fbe4Spfg             pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
3547a46fbe4Spfg                     ? __builtin_alloca( pReturnTypeDescr->nSize )
3557a46fbe4Spfg                     : pUnoReturn); // direct way
3567a46fbe4Spfg 
3577a46fbe4Spfg             INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack, bOverFlow );
3587a46fbe4Spfg         }
3597a46fbe4Spfg     }
3607a46fbe4Spfg     // push this
3617a46fbe4Spfg     void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
3627a46fbe4Spfg         + aVtableSlot.offset;
3637a46fbe4Spfg     INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow );
3647a46fbe4Spfg 
3657a46fbe4Spfg     // stack space
3667a46fbe4Spfg     OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
3677a46fbe4Spfg     // args
3687a46fbe4Spfg     void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
3697a46fbe4Spfg     // indizes of values this have to be converted (interface conversion cpp<=>uno)
3707a46fbe4Spfg     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
3717a46fbe4Spfg     // type descriptions for reconversions
3727a46fbe4Spfg     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
3737a46fbe4Spfg 
3747a46fbe4Spfg     sal_Int32 nTempIndizes   = 0;
3757a46fbe4Spfg 
3767a46fbe4Spfg     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
3777a46fbe4Spfg     {
3787a46fbe4Spfg         const typelib_MethodParameter & rParam = pParams[nPos];
3797a46fbe4Spfg         typelib_TypeDescription * pParamTypeDescr = 0;
3807a46fbe4Spfg         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
3817a46fbe4Spfg 
3827a46fbe4Spfg         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
3837a46fbe4Spfg         {
3847a46fbe4Spfg //            uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
3857a46fbe4Spfg             uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
3867a46fbe4Spfg                 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
3877a46fbe4Spfg 
3887a46fbe4Spfg             switch (pParamTypeDescr->eTypeClass)
3897a46fbe4Spfg             {
3907a46fbe4Spfg             case typelib_TypeClass_HYPER:
3917a46fbe4Spfg             case typelib_TypeClass_UNSIGNED_HYPER:
3927a46fbe4Spfg #ifdef CMC_DEBUG
3937a46fbe4Spfg 			    fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]);
3947a46fbe4Spfg #endif
3957a46fbe4Spfg                 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow );
3967a46fbe4Spfg                 break;
3977a46fbe4Spfg             case typelib_TypeClass_LONG:
3987a46fbe4Spfg             case typelib_TypeClass_UNSIGNED_LONG:
3997a46fbe4Spfg             case typelib_TypeClass_ENUM:
4007a46fbe4Spfg #ifdef CMC_DEBUG
4017a46fbe4Spfg 			    fprintf(stderr, "long is %x\n", pCppArgs[nPos]);
4027a46fbe4Spfg #endif
4037a46fbe4Spfg                 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
4047a46fbe4Spfg                 break;
4057a46fbe4Spfg             case typelib_TypeClass_SHORT:
4067a46fbe4Spfg             case typelib_TypeClass_CHAR:
4077a46fbe4Spfg             case typelib_TypeClass_UNSIGNED_SHORT:
4087a46fbe4Spfg                 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
4097a46fbe4Spfg                 break;
4107a46fbe4Spfg             case typelib_TypeClass_BOOLEAN:
4117a46fbe4Spfg             case typelib_TypeClass_BYTE:
4127a46fbe4Spfg                 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
4137a46fbe4Spfg                 break;
4147a46fbe4Spfg             case typelib_TypeClass_FLOAT:
4157a46fbe4Spfg                 INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
4167a46fbe4Spfg 			    break;
4177a46fbe4Spfg             case typelib_TypeClass_DOUBLE:
4187a46fbe4Spfg                 INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow );
4197a46fbe4Spfg                 break;
4207a46fbe4Spfg             default:
4217a46fbe4Spfg                 break;
4227a46fbe4Spfg             }
4237a46fbe4Spfg             // no longer needed
4247a46fbe4Spfg             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
4257a46fbe4Spfg         }
4267a46fbe4Spfg         else // ptr to complex value | ref
4277a46fbe4Spfg         {
4287a46fbe4Spfg             if (! rParam.bIn) // is pure out
4297a46fbe4Spfg             {
4307a46fbe4Spfg                 // cpp out is constructed mem, uno out is not!
4317a46fbe4Spfg                 uno_constructData(
4327a46fbe4Spfg                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
4337a46fbe4Spfg                     pParamTypeDescr );
4347a46fbe4Spfg                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
4357a46fbe4Spfg                 // will be released at reconversion
4367a46fbe4Spfg                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
4377a46fbe4Spfg             }
4387a46fbe4Spfg             // is in/inout
4397a46fbe4Spfg             else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
4407a46fbe4Spfg             {
4417a46fbe4Spfg                 uno_copyAndConvertData(
4427a46fbe4Spfg                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
4437a46fbe4Spfg                     pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
4447a46fbe4Spfg 
4457a46fbe4Spfg                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
4467a46fbe4Spfg                 // will be released at reconversion
4477a46fbe4Spfg                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
4487a46fbe4Spfg             }
4497a46fbe4Spfg             else // direct way
4507a46fbe4Spfg             {
4517a46fbe4Spfg                 pCppArgs[nPos] = pUnoArgs[nPos];
4527a46fbe4Spfg                 // no longer needed
4537a46fbe4Spfg                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
4547a46fbe4Spfg             }
4557a46fbe4Spfg             INSERT_INT32( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow );
4567a46fbe4Spfg         }
4577a46fbe4Spfg     }
4587a46fbe4Spfg 
4597a46fbe4Spfg     try
4607a46fbe4Spfg     {
4617a46fbe4Spfg         callVirtualMethod(
4627a46fbe4Spfg             pAdjustedThisPtr, aVtableSlot.index,
4637a46fbe4Spfg             pCppReturn, pReturnTypeRef,
4647a46fbe4Spfg             pStackStart,
4657a46fbe4Spfg             (pStack - pStackStart),
4667a46fbe4Spfg             pGPR, nGPR);
4677a46fbe4Spfg 
4687a46fbe4Spfg         // NO exception occurred...
4697a46fbe4Spfg         *ppUnoExc = 0;
4707a46fbe4Spfg 
4717a46fbe4Spfg         // reconvert temporary params
4727a46fbe4Spfg         for ( ; nTempIndizes--; )
4737a46fbe4Spfg         {
4747a46fbe4Spfg             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
4757a46fbe4Spfg             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
4767a46fbe4Spfg 
4777a46fbe4Spfg             if (pParams[nIndex].bIn)
4787a46fbe4Spfg             {
4797a46fbe4Spfg                 if (pParams[nIndex].bOut) // inout
4807a46fbe4Spfg                 {
4817a46fbe4Spfg                     uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
4827a46fbe4Spfg                     uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
4837a46fbe4Spfg                                             pThis->getBridge()->getCpp2Uno() );
4847a46fbe4Spfg                 }
4857a46fbe4Spfg             }
4867a46fbe4Spfg             else // pure out
4877a46fbe4Spfg             {
4887a46fbe4Spfg                 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
4897a46fbe4Spfg                                         pThis->getBridge()->getCpp2Uno() );
4907a46fbe4Spfg             }
4917a46fbe4Spfg             // destroy temp cpp param => cpp: every param was constructed
4927a46fbe4Spfg             uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
4937a46fbe4Spfg 
4947a46fbe4Spfg             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
4957a46fbe4Spfg         }
4967a46fbe4Spfg         // return value
4977a46fbe4Spfg         if (pCppReturn && pUnoReturn != pCppReturn)
4987a46fbe4Spfg         {
4997a46fbe4Spfg             uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
5007a46fbe4Spfg                                     pThis->getBridge()->getCpp2Uno() );
5017a46fbe4Spfg             uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
5027a46fbe4Spfg         }
5037a46fbe4Spfg     }
5047a46fbe4Spfg     catch (...)
5057a46fbe4Spfg     {
5067a46fbe4Spfg //        __asm__ __volatile__ ("sub sp, sp, #2048\n");
5077a46fbe4Spfg 
5087a46fbe4Spfg         // fill uno exception
5097a46fbe4Spfg         fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
5107a46fbe4Spfg 
5117a46fbe4Spfg         // temporary params
5127a46fbe4Spfg         for ( ; nTempIndizes--; )
5137a46fbe4Spfg         {
5147a46fbe4Spfg             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
5157a46fbe4Spfg             // destroy temp cpp param => cpp: every param was constructed
5167a46fbe4Spfg             uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
5177a46fbe4Spfg             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
5187a46fbe4Spfg         }
5197a46fbe4Spfg 
5207a46fbe4Spfg         // return type
5217a46fbe4Spfg         if (pReturnTypeDescr)
5227a46fbe4Spfg             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
5237a46fbe4Spfg     }
5247a46fbe4Spfg }
5257a46fbe4Spfg }
5267a46fbe4Spfg 
5277a46fbe4Spfg namespace bridges { namespace cpp_uno { namespace shared {
5287a46fbe4Spfg 
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)5297a46fbe4Spfg void unoInterfaceProxyDispatch(
5307a46fbe4Spfg     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
5317a46fbe4Spfg     void * pReturn, void * pArgs[], uno_Any ** ppException )
5327a46fbe4Spfg {
5337a46fbe4Spfg     // is my surrogate
5347a46fbe4Spfg     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
5357a46fbe4Spfg           = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
5367a46fbe4Spfg #if OSL_DEBUG_LEVEL > 0
5377a46fbe4Spfg     typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
5387a46fbe4Spfg #endif
5397a46fbe4Spfg 
5407a46fbe4Spfg     switch (pMemberDescr->eTypeClass)
5417a46fbe4Spfg     {
5427a46fbe4Spfg     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
5437a46fbe4Spfg     {
5447a46fbe4Spfg #if OSL_DEBUG_LEVEL > 0
5457a46fbe4Spfg         // determine vtable call index
5467a46fbe4Spfg         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
5477a46fbe4Spfg         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
5487a46fbe4Spfg #endif
5497a46fbe4Spfg 
5507a46fbe4Spfg         VtableSlot aVtableSlot(
5517a46fbe4Spfg             getVtableSlot(
5527a46fbe4Spfg             reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>
5537a46fbe4Spfg               (pMemberDescr)));
5547a46fbe4Spfg 
5557a46fbe4Spfg         if (pReturn)
5567a46fbe4Spfg         {
5577a46fbe4Spfg             // dependent dispatch
5587a46fbe4Spfg             cpp_call(
5597a46fbe4Spfg                 pThis, aVtableSlot,
5607a46fbe4Spfg                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
5617a46fbe4Spfg                 0, 0, // no params
5627a46fbe4Spfg                 pReturn, pArgs, ppException );
5637a46fbe4Spfg         }
5647a46fbe4Spfg         else
5657a46fbe4Spfg         {
5667a46fbe4Spfg             // is SET
5677a46fbe4Spfg             typelib_MethodParameter aParam;
5687a46fbe4Spfg             aParam.pTypeRef =
5697a46fbe4Spfg                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
5707a46fbe4Spfg             aParam.bIn      = sal_True;
5717a46fbe4Spfg             aParam.bOut     = sal_False;
5727a46fbe4Spfg 
5737a46fbe4Spfg             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
5747a46fbe4Spfg             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
5757a46fbe4Spfg             typelib_typedescriptionreference_new(
5767a46fbe4Spfg                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
5777a46fbe4Spfg 
5787a46fbe4Spfg             // dependent dispatch
5797a46fbe4Spfg             aVtableSlot.index += 1;
5807a46fbe4Spfg             cpp_call(
5817a46fbe4Spfg                 pThis, aVtableSlot, // get, then set method
5827a46fbe4Spfg                 pReturnTypeRef,
5837a46fbe4Spfg                 1, &aParam,
5847a46fbe4Spfg                 pReturn, pArgs, ppException );
5857a46fbe4Spfg 
5867a46fbe4Spfg             typelib_typedescriptionreference_release( pReturnTypeRef );
5877a46fbe4Spfg         }
5887a46fbe4Spfg 
5897a46fbe4Spfg         break;
5907a46fbe4Spfg     }
5917a46fbe4Spfg     case typelib_TypeClass_INTERFACE_METHOD:
5927a46fbe4Spfg     {
5937a46fbe4Spfg #if OSL_DEBUG_LEVEL > 0
5947a46fbe4Spfg         // determine vtable call index
5957a46fbe4Spfg         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
5967a46fbe4Spfg         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
5977a46fbe4Spfg #endif
5987a46fbe4Spfg 
5997a46fbe4Spfg         VtableSlot aVtableSlot(
6007a46fbe4Spfg             getVtableSlot(
6017a46fbe4Spfg             reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>
6027a46fbe4Spfg               (pMemberDescr)));
6037a46fbe4Spfg 
6047a46fbe4Spfg         switch (aVtableSlot.index)
6057a46fbe4Spfg         {
6067a46fbe4Spfg             // standard calls
6077a46fbe4Spfg         case 1: // acquire uno interface
6087a46fbe4Spfg             (*pUnoI->acquire)( pUnoI );
6097a46fbe4Spfg             *ppException = 0;
6107a46fbe4Spfg             break;
6117a46fbe4Spfg         case 2: // release uno interface
6127a46fbe4Spfg             (*pUnoI->release)( pUnoI );
6137a46fbe4Spfg             *ppException = 0;
6147a46fbe4Spfg             break;
6157a46fbe4Spfg         case 0: // queryInterface() opt
6167a46fbe4Spfg         {
6177a46fbe4Spfg             typelib_TypeDescription * pTD = 0;
6187a46fbe4Spfg             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
6197a46fbe4Spfg             if (pTD)
6207a46fbe4Spfg             {
6217a46fbe4Spfg                 uno_Interface * pInterface = 0;
6227a46fbe4Spfg                 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
6237a46fbe4Spfg                     pThis->getBridge()->getUnoEnv(),
6247a46fbe4Spfg                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
6257a46fbe4Spfg 
6267a46fbe4Spfg                 if (pInterface)
6277a46fbe4Spfg                 {
6287a46fbe4Spfg                     ::uno_any_construct(
6297a46fbe4Spfg                         reinterpret_cast< uno_Any * >( pReturn ),
6307a46fbe4Spfg                         &pInterface, pTD, 0 );
6317a46fbe4Spfg                     (*pInterface->release)( pInterface );
6327a46fbe4Spfg                     TYPELIB_DANGER_RELEASE( pTD );
6337a46fbe4Spfg                     *ppException = 0;
6347a46fbe4Spfg                     break;
6357a46fbe4Spfg                 }
6367a46fbe4Spfg                 TYPELIB_DANGER_RELEASE( pTD );
6377a46fbe4Spfg             }
6387a46fbe4Spfg         } // else perform queryInterface()
6397a46fbe4Spfg         default:
6407a46fbe4Spfg             // dependent dispatch
6417a46fbe4Spfg             cpp_call(
6427a46fbe4Spfg                 pThis, aVtableSlot,
6437a46fbe4Spfg                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
6447a46fbe4Spfg                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
6457a46fbe4Spfg                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
6467a46fbe4Spfg                 pReturn, pArgs, ppException );
6477a46fbe4Spfg         }
6487a46fbe4Spfg         break;
6497a46fbe4Spfg     }
6507a46fbe4Spfg     default:
6517a46fbe4Spfg     {
6527a46fbe4Spfg         ::com::sun::star::uno::RuntimeException aExc(
6537a46fbe4Spfg             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
6547a46fbe4Spfg             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
6557a46fbe4Spfg 
6567a46fbe4Spfg         Type const & rExcType = ::getCppuType( &aExc );
6577a46fbe4Spfg         // binary identical null reference
6587a46fbe4Spfg         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
6597a46fbe4Spfg     }
6607a46fbe4Spfg     }
6617a46fbe4Spfg }
6627a46fbe4Spfg 
6637a46fbe4Spfg } } }
6647a46fbe4Spfg 
6657a46fbe4Spfg /* vi:set tabstop=4 shiftwidth=4 expandtab: */
666