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*44db7cb5SPedro Giffuni #include <stdlib.h>
250bd9e244Spfg #include <hash_map>
260bd9e244Spfg
270bd9e244Spfg #include <rtl/alloc.h>
280bd9e244Spfg #include <osl/mutex.hxx>
290bd9e244Spfg
300bd9e244Spfg #include <com/sun/star/uno/genfunc.hxx>
310bd9e244Spfg #include "com/sun/star/uno/RuntimeException.hpp"
320bd9e244Spfg #include <uno/data.h>
330bd9e244Spfg #include <typelib/typedescription.hxx>
340bd9e244Spfg
350bd9e244Spfg #include "bridges/cpp_uno/shared/bridge.hxx"
360bd9e244Spfg #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
370bd9e244Spfg #include "bridges/cpp_uno/shared/types.hxx"
380bd9e244Spfg #include "bridges/cpp_uno/shared/vtablefactory.hxx"
390bd9e244Spfg
400bd9e244Spfg #include "share.hxx"
410bd9e244Spfg
420bd9e244Spfg #include <dlfcn.h>
430bd9e244Spfg
440bd9e244Spfg
450bd9e244Spfg using namespace ::osl;
460bd9e244Spfg using namespace ::rtl;
470bd9e244Spfg using namespace ::com::sun::star::uno;
480bd9e244Spfg
490bd9e244Spfg namespace
500bd9e244Spfg {
510bd9e244Spfg
cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy * pThis,const typelib_TypeDescription * pMemberTypeDescr,typelib_TypeDescriptionReference * pReturnTypeRef,sal_Int32 nParams,typelib_MethodParameter * pParams,void ** pCallStack,sal_Int64 * pRegisterReturn)520bd9e244Spfg static typelib_TypeClass cpp2uno_call(
530bd9e244Spfg bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
540bd9e244Spfg const typelib_TypeDescription * pMemberTypeDescr,
550bd9e244Spfg typelib_TypeDescriptionReference * pReturnTypeRef,
560bd9e244Spfg sal_Int32 nParams, typelib_MethodParameter * pParams,
570bd9e244Spfg void ** pCallStack,
580bd9e244Spfg sal_Int64 * pRegisterReturn /* space for register return */ )
590bd9e244Spfg {
600bd9e244Spfg // pCallStack: ret, [return ptr], this, params
610bd9e244Spfg char * pTopStack = (char *)(pCallStack + 0);
620bd9e244Spfg char * pCppStack = pTopStack;
630bd9e244Spfg
640bd9e244Spfg // return
650bd9e244Spfg typelib_TypeDescription * pReturnTypeDescr = 0;
660bd9e244Spfg if (pReturnTypeRef)
670bd9e244Spfg TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
680bd9e244Spfg
690bd9e244Spfg void * pUnoReturn = 0;
700bd9e244Spfg // complex return ptr: if != 0 && != pUnoReturn, reconversion need
710bd9e244Spfg void * pCppReturn = 0;
720bd9e244Spfg
730bd9e244Spfg if (pReturnTypeDescr)
740bd9e244Spfg {
750bd9e244Spfg if (!arm::return_in_hidden_param(pReturnTypeRef))
760bd9e244Spfg pUnoReturn = pRegisterReturn; // direct way for simple types
770bd9e244Spfg else // complex return via ptr (pCppReturn)
780bd9e244Spfg {
790bd9e244Spfg pCppReturn = *(void **)pCppStack;
800bd9e244Spfg pCppStack += sizeof(void *);
810bd9e244Spfg
820bd9e244Spfg pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
830bd9e244Spfg pReturnTypeDescr )
840bd9e244Spfg ? alloca( pReturnTypeDescr->nSize )
850bd9e244Spfg : pCppReturn); // direct way
860bd9e244Spfg }
870bd9e244Spfg }
880bd9e244Spfg // pop this
890bd9e244Spfg pCppStack += sizeof( void* );
900bd9e244Spfg
910bd9e244Spfg // stack space
920bd9e244Spfg OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32),
930bd9e244Spfg "### unexpected size!" );
940bd9e244Spfg // parameters
950bd9e244Spfg void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
960bd9e244Spfg void ** pCppArgs = pUnoArgs + nParams;
970bd9e244Spfg // indizes of values this have to be converted (interface conversion
980bd9e244Spfg // cpp<=>uno)
990bd9e244Spfg sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
1000bd9e244Spfg // type descriptions for reconversions
1010bd9e244Spfg typelib_TypeDescription ** ppTempParamTypeDescr =
1020bd9e244Spfg (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
1030bd9e244Spfg
1040bd9e244Spfg sal_Int32 nTempIndizes = 0;
1050bd9e244Spfg
1060bd9e244Spfg for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
1070bd9e244Spfg {
1080bd9e244Spfg const typelib_MethodParameter & rParam = pParams[nPos];
1090bd9e244Spfg typelib_TypeDescription * pParamTypeDescr = 0;
1100bd9e244Spfg TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
1110bd9e244Spfg
1120bd9e244Spfg if (!rParam.bOut &&
1130bd9e244Spfg bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
1140bd9e244Spfg {
1150bd9e244Spfg #ifdef __ARM_EABI__
1160bd9e244Spfg switch (pParamTypeDescr->eTypeClass)
1170bd9e244Spfg {
1180bd9e244Spfg case typelib_TypeClass_HYPER:
1190bd9e244Spfg case typelib_TypeClass_UNSIGNED_HYPER:
1200bd9e244Spfg case typelib_TypeClass_DOUBLE:
1210bd9e244Spfg if ((pCppStack - pTopStack) % 8) pCppStack+=sizeof(sal_Int32); //align to 8
1220bd9e244Spfg break;
1230bd9e244Spfg default:
1240bd9e244Spfg break;
1250bd9e244Spfg }
1260bd9e244Spfg #endif
1270bd9e244Spfg
1280bd9e244Spfg pCppArgs[nPos] = pCppStack;
1290bd9e244Spfg pUnoArgs[nPos] = pCppStack;
1300bd9e244Spfg switch (pParamTypeDescr->eTypeClass)
1310bd9e244Spfg {
1320bd9e244Spfg case typelib_TypeClass_HYPER:
1330bd9e244Spfg case typelib_TypeClass_UNSIGNED_HYPER:
1340bd9e244Spfg case typelib_TypeClass_DOUBLE:
1350bd9e244Spfg pCppStack += sizeof(sal_Int32); // extra long
1360bd9e244Spfg break;
1370bd9e244Spfg default:
1380bd9e244Spfg break;
1390bd9e244Spfg }
1400bd9e244Spfg // no longer needed
1410bd9e244Spfg TYPELIB_DANGER_RELEASE( pParamTypeDescr );
1420bd9e244Spfg }
1430bd9e244Spfg else // ptr to complex value | ref
1440bd9e244Spfg {
1450bd9e244Spfg pCppArgs[nPos] = *(void **)pCppStack;
1460bd9e244Spfg
1470bd9e244Spfg if (! rParam.bIn) // is pure out
1480bd9e244Spfg {
1490bd9e244Spfg // uno out is unconstructed mem!
1500bd9e244Spfg pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
1510bd9e244Spfg pTempIndizes[nTempIndizes] = nPos;
1520bd9e244Spfg // will be released at reconversion
1530bd9e244Spfg ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
1540bd9e244Spfg }
1550bd9e244Spfg // is in/inout
1560bd9e244Spfg else if (bridges::cpp_uno::shared::relatesToInterfaceType(
1570bd9e244Spfg pParamTypeDescr ))
1580bd9e244Spfg {
1590bd9e244Spfg uno_copyAndConvertData( pUnoArgs[nPos] =
1600bd9e244Spfg alloca( pParamTypeDescr->nSize ),
1610bd9e244Spfg *(void **)pCppStack, pParamTypeDescr,
1620bd9e244Spfg pThis->getBridge()->getCpp2Uno() );
1630bd9e244Spfg pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
1640bd9e244Spfg // will be released at reconversion
1650bd9e244Spfg ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
1660bd9e244Spfg }
1670bd9e244Spfg else // direct way
1680bd9e244Spfg {
1690bd9e244Spfg pUnoArgs[nPos] = *(void **)pCppStack;
1700bd9e244Spfg // no longer needed
1710bd9e244Spfg TYPELIB_DANGER_RELEASE( pParamTypeDescr );
1720bd9e244Spfg }
1730bd9e244Spfg }
1740bd9e244Spfg pCppStack += sizeof(sal_Int32); // standard parameter length
1750bd9e244Spfg }
1760bd9e244Spfg
1770bd9e244Spfg // ExceptionHolder
1780bd9e244Spfg uno_Any aUnoExc; // Any will be constructed by callee
1790bd9e244Spfg uno_Any * pUnoExc = &aUnoExc;
1800bd9e244Spfg
1810bd9e244Spfg // invoke uno dispatch call
1820bd9e244Spfg (*pThis->getUnoI()->pDispatcher)(
1830bd9e244Spfg pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
1840bd9e244Spfg
1850bd9e244Spfg // in case an exception occurred...
1860bd9e244Spfg if (pUnoExc)
1870bd9e244Spfg {
1880bd9e244Spfg // destruct temporary in/inout params
1890bd9e244Spfg for ( ; nTempIndizes--; )
1900bd9e244Spfg {
1910bd9e244Spfg sal_Int32 nIndex = pTempIndizes[nTempIndizes];
1920bd9e244Spfg
1930bd9e244Spfg if (pParams[nIndex].bIn) // is in/inout => was constructed
1940bd9e244Spfg uno_destructData( pUnoArgs[nIndex],
1950bd9e244Spfg ppTempParamTypeDescr[nTempIndizes], 0 );
1960bd9e244Spfg TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
1970bd9e244Spfg }
1980bd9e244Spfg if (pReturnTypeDescr)
1990bd9e244Spfg TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
2000bd9e244Spfg
2010bd9e244Spfg CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc,
2020bd9e244Spfg pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
2030bd9e244Spfg // is here for dummy
2040bd9e244Spfg return typelib_TypeClass_VOID;
2050bd9e244Spfg }
2060bd9e244Spfg else // else no exception occurred...
2070bd9e244Spfg {
2080bd9e244Spfg // temporary params
2090bd9e244Spfg for ( ; nTempIndizes--; )
2100bd9e244Spfg {
2110bd9e244Spfg sal_Int32 nIndex = pTempIndizes[nTempIndizes];
2120bd9e244Spfg typelib_TypeDescription * pParamTypeDescr =
2130bd9e244Spfg ppTempParamTypeDescr[nTempIndizes];
2140bd9e244Spfg
2150bd9e244Spfg if (pParams[nIndex].bOut) // inout/out
2160bd9e244Spfg {
2170bd9e244Spfg // convert and assign
2180bd9e244Spfg uno_destructData( pCppArgs[nIndex], pParamTypeDescr,
2190bd9e244Spfg cpp_release );
2200bd9e244Spfg uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex],
2210bd9e244Spfg pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
2220bd9e244Spfg }
2230bd9e244Spfg // destroy temp uno param
2240bd9e244Spfg uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
2250bd9e244Spfg
2260bd9e244Spfg TYPELIB_DANGER_RELEASE( pParamTypeDescr );
2270bd9e244Spfg }
2280bd9e244Spfg // return
2290bd9e244Spfg if (pCppReturn) // has complex return
2300bd9e244Spfg {
2310bd9e244Spfg if (pUnoReturn != pCppReturn) // needs reconversion
2320bd9e244Spfg {
2330bd9e244Spfg uno_copyAndConvertData( pCppReturn, pUnoReturn,
2340bd9e244Spfg pReturnTypeDescr, pThis->getBridge()->getUno2Cpp() );
2350bd9e244Spfg // destroy temp uno return
2360bd9e244Spfg uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
2370bd9e244Spfg }
2380bd9e244Spfg // complex return ptr is set to eax
2390bd9e244Spfg *(void **)pRegisterReturn = pCppReturn;
2400bd9e244Spfg }
2410bd9e244Spfg if (pReturnTypeDescr)
2420bd9e244Spfg {
2430bd9e244Spfg typelib_TypeClass eRet =
2440bd9e244Spfg (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
2450bd9e244Spfg TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
2460bd9e244Spfg return eRet;
2470bd9e244Spfg }
2480bd9e244Spfg else
2490bd9e244Spfg return typelib_TypeClass_VOID;
2500bd9e244Spfg }
2510bd9e244Spfg }
2520bd9e244Spfg
2530bd9e244Spfg
2540bd9e244Spfg //=====================================================================
cpp_mediate(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** pCallStack,sal_Int64 * pRegisterReturn)2550bd9e244Spfg static typelib_TypeClass cpp_mediate(
2560bd9e244Spfg sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
2570bd9e244Spfg void ** pCallStack,
2580bd9e244Spfg sal_Int64 * pRegisterReturn /* space for register return */ )
2590bd9e244Spfg {
2600bd9e244Spfg OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
2610bd9e244Spfg
2620bd9e244Spfg // pCallStack: [ret *], this, params
2630bd9e244Spfg // _this_ ptr is patched cppu_XInterfaceProxy object
2640bd9e244Spfg void *pThis;
2650bd9e244Spfg if( nFunctionIndex & 0x80000000 )
2660bd9e244Spfg {
2670bd9e244Spfg nFunctionIndex &= 0x7fffffff;
2680bd9e244Spfg pThis = pCallStack[1];
2690bd9e244Spfg }
2700bd9e244Spfg else
2710bd9e244Spfg {
2720bd9e244Spfg pThis = pCallStack[0];
2730bd9e244Spfg }
2740bd9e244Spfg
2750bd9e244Spfg pThis = static_cast< char * >(pThis) - nVtableOffset;
2760bd9e244Spfg bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
2770bd9e244Spfg bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
2780bd9e244Spfg pThis);
2790bd9e244Spfg
2800bd9e244Spfg typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
2810bd9e244Spfg
2820bd9e244Spfg OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
2830bd9e244Spfg "### illegal vtable index!" );
2840bd9e244Spfg if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
2850bd9e244Spfg {
2860bd9e244Spfg throw RuntimeException(
2870bd9e244Spfg OUString::createFromAscii("illegal vtable index!"),
2880bd9e244Spfg (XInterface *)pCppI );
2890bd9e244Spfg }
2900bd9e244Spfg
2910bd9e244Spfg // determine called method
2920bd9e244Spfg OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
2930bd9e244Spfg "### illegal vtable index!" );
2940bd9e244Spfg sal_Int32 nMemberPos =
2950bd9e244Spfg pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
2960bd9e244Spfg OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers,
2970bd9e244Spfg "### illegal member index!" );
2980bd9e244Spfg
2990bd9e244Spfg TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
3000bd9e244Spfg
3010bd9e244Spfg typelib_TypeClass eRet;
3020bd9e244Spfg switch (aMemberDescr.get()->eTypeClass)
3030bd9e244Spfg {
3040bd9e244Spfg case typelib_TypeClass_INTERFACE_ATTRIBUTE:
3050bd9e244Spfg {
3060bd9e244Spfg if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] ==
3070bd9e244Spfg nFunctionIndex)
3080bd9e244Spfg {
3090bd9e244Spfg // is GET method
3100bd9e244Spfg eRet = cpp2uno_call(
3110bd9e244Spfg pCppI, aMemberDescr.get(),
3120bd9e244Spfg ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
3130bd9e244Spfg 0, 0, // no params
3140bd9e244Spfg pCallStack, pRegisterReturn );
3150bd9e244Spfg }
3160bd9e244Spfg else
3170bd9e244Spfg {
3180bd9e244Spfg // is SET method
3190bd9e244Spfg typelib_MethodParameter aParam;
3200bd9e244Spfg aParam.pTypeRef =
3210bd9e244Spfg ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
3220bd9e244Spfg aParam.bIn = sal_True;
3230bd9e244Spfg aParam.bOut = sal_False;
3240bd9e244Spfg
3250bd9e244Spfg eRet = cpp2uno_call(
3260bd9e244Spfg pCppI, aMemberDescr.get(),
3270bd9e244Spfg 0, // indicates void return
3280bd9e244Spfg 1, &aParam,
3290bd9e244Spfg pCallStack, pRegisterReturn );
3300bd9e244Spfg }
3310bd9e244Spfg break;
3320bd9e244Spfg }
3330bd9e244Spfg case typelib_TypeClass_INTERFACE_METHOD:
3340bd9e244Spfg {
3350bd9e244Spfg // is METHOD
3360bd9e244Spfg switch (nFunctionIndex)
3370bd9e244Spfg {
3380bd9e244Spfg case 1: // acquire()
3390bd9e244Spfg pCppI->acquireProxy(); // non virtual call!
3400bd9e244Spfg eRet = typelib_TypeClass_VOID;
3410bd9e244Spfg break;
3420bd9e244Spfg case 2: // release()
3430bd9e244Spfg pCppI->releaseProxy(); // non virtual call!
3440bd9e244Spfg eRet = typelib_TypeClass_VOID;
3450bd9e244Spfg break;
3460bd9e244Spfg case 0: // queryInterface() opt
3470bd9e244Spfg {
3480bd9e244Spfg typelib_TypeDescription * pTD = 0;
3490bd9e244Spfg TYPELIB_DANGER_GET(&pTD,
3500bd9e244Spfg reinterpret_cast<Type *>(pCallStack[2])->getTypeLibType());
3510bd9e244Spfg if (pTD)
3520bd9e244Spfg {
3530bd9e244Spfg XInterface * pInterface = 0;
3540bd9e244Spfg (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
3550bd9e244Spfg pCppI->getBridge()->getCppEnv(),
3560bd9e244Spfg (void **)&pInterface, pCppI->getOid().pData,
3570bd9e244Spfg (typelib_InterfaceTypeDescription *)pTD );
3580bd9e244Spfg
3590bd9e244Spfg if (pInterface)
3600bd9e244Spfg {
3610bd9e244Spfg ::uno_any_construct(
3620bd9e244Spfg reinterpret_cast< uno_Any * >( pCallStack[0] ),
3630bd9e244Spfg &pInterface, pTD, cpp_acquire );
3640bd9e244Spfg pInterface->release();
3650bd9e244Spfg TYPELIB_DANGER_RELEASE( pTD );
3660bd9e244Spfg *(void **)pRegisterReturn = pCallStack[0];
3670bd9e244Spfg eRet = typelib_TypeClass_ANY;
3680bd9e244Spfg break;
3690bd9e244Spfg }
3700bd9e244Spfg TYPELIB_DANGER_RELEASE( pTD );
3710bd9e244Spfg }
3720bd9e244Spfg } // else perform queryInterface()
3730bd9e244Spfg default:
3740bd9e244Spfg eRet = cpp2uno_call(
3750bd9e244Spfg pCppI, aMemberDescr.get(),
3760bd9e244Spfg ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
3770bd9e244Spfg ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
3780bd9e244Spfg ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
3790bd9e244Spfg pCallStack, pRegisterReturn );
3800bd9e244Spfg }
3810bd9e244Spfg break;
3820bd9e244Spfg }
3830bd9e244Spfg default:
3840bd9e244Spfg {
3850bd9e244Spfg throw RuntimeException(
3860bd9e244Spfg OUString::createFromAscii("no member description found!"),
3870bd9e244Spfg (XInterface *)pCppI );
3880bd9e244Spfg // is here for dummy
3890bd9e244Spfg eRet = typelib_TypeClass_VOID;
3900bd9e244Spfg }
3910bd9e244Spfg }
3920bd9e244Spfg
3930bd9e244Spfg return eRet;
3940bd9e244Spfg }
3950bd9e244Spfg }
3960bd9e244Spfg
3970bd9e244Spfg //=======================================================================
3980bd9e244Spfg /**
3990bd9e244Spfg * is called on incoming vtable calls
4000bd9e244Spfg * (called by asm snippets)
4010bd9e244Spfg */
4020bd9e244Spfg
cpp_vtable_call(long * pFunctionAndOffset,void ** pCallStack)4030bd9e244Spfg extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset,
4040bd9e244Spfg void **pCallStack )
4050bd9e244Spfg {
4060bd9e244Spfg sal_Int64 nRegReturn;
4070bd9e244Spfg typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack,
4080bd9e244Spfg &nRegReturn );
4090bd9e244Spfg
4100bd9e244Spfg switch( aType )
4110bd9e244Spfg {
4120bd9e244Spfg case typelib_TypeClass_BOOLEAN:
4130bd9e244Spfg case typelib_TypeClass_BYTE:
4140bd9e244Spfg nRegReturn = (unsigned long)(*(unsigned char *)&nRegReturn);
4150bd9e244Spfg break;
4160bd9e244Spfg case typelib_TypeClass_CHAR:
4170bd9e244Spfg case typelib_TypeClass_UNSIGNED_SHORT:
4180bd9e244Spfg case typelib_TypeClass_SHORT:
4190bd9e244Spfg nRegReturn = (unsigned long)(*(unsigned short *)&nRegReturn);
4200bd9e244Spfg break;
4210bd9e244Spfg case typelib_TypeClass_ENUM:
4220bd9e244Spfg case typelib_TypeClass_UNSIGNED_LONG:
4230bd9e244Spfg case typelib_TypeClass_LONG:
4240bd9e244Spfg nRegReturn = (unsigned long)(*(unsigned int *)&nRegReturn);
4250bd9e244Spfg break;
4260bd9e244Spfg case typelib_TypeClass_VOID:
4270bd9e244Spfg default:
4280bd9e244Spfg break;
4290bd9e244Spfg }
4300bd9e244Spfg
4310bd9e244Spfg return nRegReturn;
4320bd9e244Spfg }
4330bd9e244Spfg
4340bd9e244Spfg extern "C" void privateSnippetExecutor(void);
4350bd9e244Spfg
4360bd9e244Spfg namespace
4370bd9e244Spfg {
4380bd9e244Spfg const int codeSnippetSize = 20;
4390bd9e244Spfg
codeSnippet(unsigned char * code,sal_Int32 functionIndex,sal_Int32 vtableOffset,bool bHasHiddenParam)4400bd9e244Spfg unsigned char *codeSnippet(unsigned char* code, sal_Int32 functionIndex,
4410bd9e244Spfg sal_Int32 vtableOffset, bool bHasHiddenParam)
4420bd9e244Spfg {
4430bd9e244Spfg if (bHasHiddenParam)
4440bd9e244Spfg functionIndex |= 0x80000000;
4450bd9e244Spfg
4460bd9e244Spfg unsigned long * p = (unsigned long *)code;
4470bd9e244Spfg
4480bd9e244Spfg *p++ = 0xE1A0C00F;
4490bd9e244Spfg *p++ = 0xE59FF004;
4500bd9e244Spfg *p++ = (unsigned long)functionIndex;
4510bd9e244Spfg *p++ = (unsigned long)vtableOffset;
4520bd9e244Spfg *p++ = (unsigned long)privateSnippetExecutor;
4530bd9e244Spfg
4540bd9e244Spfg return code + codeSnippetSize;
4550bd9e244Spfg }
4560bd9e244Spfg }
4570bd9e244Spfg
4580bd9e244Spfg struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
4590bd9e244Spfg
4600bd9e244Spfg bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)4610bd9e244Spfg bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
4620bd9e244Spfg {
4630bd9e244Spfg return static_cast< Slot * >(block) + 2;
4640bd9e244Spfg }
4650bd9e244Spfg
getBlockSize(sal_Int32 slotCount)4660bd9e244Spfg sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
4670bd9e244Spfg sal_Int32 slotCount)
4680bd9e244Spfg {
4690bd9e244Spfg return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
4700bd9e244Spfg }
4710bd9e244Spfg
4720bd9e244Spfg bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)4730bd9e244Spfg bridges::cpp_uno::shared::VtableFactory::initializeBlock(
4740bd9e244Spfg void * block, sal_Int32 slotCount)
4750bd9e244Spfg {
4760bd9e244Spfg Slot * slots = mapBlockToVtable(block);
4770bd9e244Spfg slots[-2].fn = 0;
4780bd9e244Spfg slots[-1].fn = 0;
4790bd9e244Spfg return slots + slotCount;
4800bd9e244Spfg }
4810bd9e244Spfg
addLocalFunctions(Slot ** slots,unsigned char * code,sal_PtrDiff writetoexecdiff,typelib_InterfaceTypeDescription const * type,sal_Int32 functionOffset,sal_Int32 functionCount,sal_Int32 vtableOffset)4820bd9e244Spfg unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
4830bd9e244Spfg Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
4840bd9e244Spfg typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
4850bd9e244Spfg sal_Int32 functionCount, sal_Int32 vtableOffset)
4860bd9e244Spfg {
4870bd9e244Spfg (*slots) -= functionCount;
4880bd9e244Spfg Slot * s = *slots;
4890bd9e244Spfg for (sal_Int32 i = 0; i < type->nMembers; ++i)
4900bd9e244Spfg {
4910bd9e244Spfg typelib_TypeDescription * member = 0;
4920bd9e244Spfg TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
4930bd9e244Spfg OSL_ASSERT(member != 0);
4940bd9e244Spfg switch (member->eTypeClass)
4950bd9e244Spfg {
4960bd9e244Spfg case typelib_TypeClass_INTERFACE_ATTRIBUTE:
4970bd9e244Spfg {
4980bd9e244Spfg typelib_InterfaceAttributeTypeDescription *pAttrTD =
4990bd9e244Spfg reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member );
5000bd9e244Spfg
5010bd9e244Spfg // Getter:
5020bd9e244Spfg (s++)->fn = code + writetoexecdiff;
5030bd9e244Spfg code = codeSnippet(
5040bd9e244Spfg code, functionOffset++, vtableOffset,
5050bd9e244Spfg arm::return_in_hidden_param( pAttrTD->pAttributeTypeRef ));
5060bd9e244Spfg
5070bd9e244Spfg // Setter:
5080bd9e244Spfg if (!pAttrTD->bReadOnly)
5090bd9e244Spfg {
5100bd9e244Spfg (s++)->fn = code + writetoexecdiff;
5110bd9e244Spfg code = codeSnippet(
5120bd9e244Spfg code, functionOffset++, vtableOffset, false);
5130bd9e244Spfg }
5140bd9e244Spfg break;
5150bd9e244Spfg }
5160bd9e244Spfg case typelib_TypeClass_INTERFACE_METHOD:
5170bd9e244Spfg {
5180bd9e244Spfg (s++)->fn = code + writetoexecdiff;
5190bd9e244Spfg
5200bd9e244Spfg typelib_InterfaceMethodTypeDescription *pMethodTD =
5210bd9e244Spfg reinterpret_cast<
5220bd9e244Spfg typelib_InterfaceMethodTypeDescription * >(member);
5230bd9e244Spfg
5240bd9e244Spfg code = codeSnippet(code, functionOffset++, vtableOffset,
5250bd9e244Spfg arm::return_in_hidden_param(pMethodTD->pReturnTypeRef));
5260bd9e244Spfg break;
5270bd9e244Spfg }
5280bd9e244Spfg default:
5290bd9e244Spfg OSL_ASSERT(false);
5300bd9e244Spfg break;
5310bd9e244Spfg }
5320bd9e244Spfg TYPELIB_DANGER_RELEASE(member);
5330bd9e244Spfg }
5340bd9e244Spfg return code;
5350bd9e244Spfg }
5360bd9e244Spfg
flushCode(unsigned char const * beg,unsigned char const * end)5370bd9e244Spfg void bridges::cpp_uno::shared::VtableFactory::flushCode(
5380bd9e244Spfg unsigned char const *beg, unsigned char const *end)
5390bd9e244Spfg {
5400bd9e244Spfg static void (*clear_cache)(unsigned char const*, unsigned char const*)
5410bd9e244Spfg = (void (*)(unsigned char const*, unsigned char const*))
5420bd9e244Spfg dlsym(RTLD_DEFAULT, "__clear_cache");
5430bd9e244Spfg (*clear_cache)(beg, end);
5440bd9e244Spfg }
5450bd9e244Spfg
5460bd9e244Spfg /* vi:set tabstop=4 shiftwidth=4 expandtab: */
547