12755751fSHerbert Dürr /**************************************************************
22755751fSHerbert Dürr *
32755751fSHerbert Dürr * Licensed to the Apache Software Foundation (ASF) under one
42755751fSHerbert Dürr * or more contributor license agreements. See the NOTICE file
52755751fSHerbert Dürr * distributed with this work for additional information
62755751fSHerbert Dürr * regarding copyright ownership. The ASF licenses this file
72755751fSHerbert Dürr * to you under the Apache License, Version 2.0 (the
82755751fSHerbert Dürr * "License"); you may not use this file except in compliance
92755751fSHerbert Dürr * with the License. You may obtain a copy of the License at
102755751fSHerbert Dürr *
112755751fSHerbert Dürr * http://www.apache.org/licenses/LICENSE-2.0
122755751fSHerbert Dürr *
132755751fSHerbert Dürr * Unless required by applicable law or agreed to in writing,
142755751fSHerbert Dürr * software distributed under the License is distributed on an
152755751fSHerbert Dürr * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
162755751fSHerbert Dürr * KIND, either express or implied. See the License for the
172755751fSHerbert Dürr * specific language governing permissions and limitations
182755751fSHerbert Dürr * under the License.
192755751fSHerbert Dürr *
202755751fSHerbert Dürr *************************************************************/
212755751fSHerbert Dürr
222755751fSHerbert Dürr
232755751fSHerbert Dürr
242755751fSHerbert Dürr // MARKER(update_precomp.py): autogen include statement, do not remove
252755751fSHerbert Dürr #include "precompiled_bridges.hxx"
262755751fSHerbert Dürr
272755751fSHerbert Dürr #include <stdio.h>
282755751fSHerbert Dürr #include <stdlib.h>
292755751fSHerbert Dürr #include <hash_map>
302755751fSHerbert Dürr
312755751fSHerbert Dürr #include <rtl/alloc.h>
322755751fSHerbert Dürr #include <osl/mutex.hxx>
332755751fSHerbert Dürr
342755751fSHerbert Dürr #include <com/sun/star/uno/genfunc.hxx>
352755751fSHerbert Dürr #include "com/sun/star/uno/RuntimeException.hpp"
362755751fSHerbert Dürr #include <uno/data.h>
372755751fSHerbert Dürr #include <typelib/typedescription.hxx>
382755751fSHerbert Dürr
392755751fSHerbert Dürr #include "bridges/cpp_uno/shared/bridge.hxx"
402755751fSHerbert Dürr #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
412755751fSHerbert Dürr #include "bridges/cpp_uno/shared/types.hxx"
422755751fSHerbert Dürr #include "bridges/cpp_uno/shared/vtablefactory.hxx"
432755751fSHerbert Dürr
442755751fSHerbert Dürr #include "abi.hxx"
452755751fSHerbert Dürr #include "share.hxx"
462755751fSHerbert Dürr
472755751fSHerbert Dürr using namespace ::osl;
482755751fSHerbert Dürr using namespace ::rtl;
492755751fSHerbert Dürr using namespace ::com::sun::star::uno;
502755751fSHerbert Dürr
512755751fSHerbert Dürr //==================================================================================================
522755751fSHerbert Dürr
532755751fSHerbert Dürr // Perform the UNO call
542755751fSHerbert Dürr //
552755751fSHerbert Dürr // We must convert the paramaters stored in gpreg, fpreg and ovrflw to UNO
562755751fSHerbert Dürr // arguments and call pThis->getUnoI()->pDispatcher.
572755751fSHerbert Dürr //
582755751fSHerbert Dürr // gpreg: [ret *], this, [gpr params]
592755751fSHerbert Dürr // fpreg: [fpr params]
602755751fSHerbert Dürr // ovrflw: [gpr or fpr params (properly aligned)]
612755751fSHerbert Dürr //
622755751fSHerbert Dürr // [ret *] is present when we are returning a structure bigger than 16 bytes
632755751fSHerbert Dürr // Simple types are returned in rax, rdx (int), or xmm0, xmm1 (fp).
642755751fSHerbert Dürr // Similarly structures <= 16 bytes are in rax, rdx, xmm0, xmm1 as necessary.
cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy * pThis,const typelib_TypeDescription * pMemberTypeDescr,typelib_TypeDescriptionReference * pReturnTypeRef,sal_Int32 nParams,typelib_MethodParameter * pParams,void ** gpreg,void ** fpreg,void ** ovrflw,sal_uInt64 * pRegisterReturn)652755751fSHerbert Dürr static typelib_TypeClass cpp2uno_call(
662755751fSHerbert Dürr bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
672755751fSHerbert Dürr const typelib_TypeDescription * pMemberTypeDescr,
682755751fSHerbert Dürr typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
692755751fSHerbert Dürr sal_Int32 nParams, typelib_MethodParameter * pParams,
702755751fSHerbert Dürr void ** gpreg, void ** fpreg, void ** ovrflw,
712755751fSHerbert Dürr sal_uInt64 * pRegisterReturn /* space for register return */ )
722755751fSHerbert Dürr {
732755751fSHerbert Dürr unsigned int nr_gpr = 0; //number of gpr registers used
742755751fSHerbert Dürr unsigned int nr_fpr = 0; //number of fpr registers used
752755751fSHerbert Dürr
762755751fSHerbert Dürr // return
772755751fSHerbert Dürr typelib_TypeDescription * pReturnTypeDescr = 0;
782755751fSHerbert Dürr if (pReturnTypeRef)
792755751fSHerbert Dürr TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
802755751fSHerbert Dürr
812755751fSHerbert Dürr void * pUnoReturn = 0;
822755751fSHerbert Dürr void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
832755751fSHerbert Dürr
842755751fSHerbert Dürr if ( pReturnTypeDescr )
852755751fSHerbert Dürr {
862755751fSHerbert Dürr if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
872755751fSHerbert Dürr {
882755751fSHerbert Dürr pCppReturn = *gpreg++;
892755751fSHerbert Dürr nr_gpr++;
902755751fSHerbert Dürr
912755751fSHerbert Dürr pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
922755751fSHerbert Dürr ? alloca( pReturnTypeDescr->nSize )
932755751fSHerbert Dürr : pCppReturn ); // direct way
942755751fSHerbert Dürr }
952755751fSHerbert Dürr else
962755751fSHerbert Dürr pUnoReturn = pRegisterReturn; // direct way for simple types
972755751fSHerbert Dürr }
982755751fSHerbert Dürr
992755751fSHerbert Dürr // pop this
1002755751fSHerbert Dürr gpreg++;
1012755751fSHerbert Dürr nr_gpr++;
1022755751fSHerbert Dürr
1032755751fSHerbert Dürr // stack space
1042755751fSHerbert Dürr // parameters
105ecf1c5e9SJim Jagielski void ** pUnoArgs = reinterpret_cast<void **>(alloca( 4 * sizeof(void *) * nParams ));
1062755751fSHerbert Dürr void ** pCppArgs = pUnoArgs + nParams;
1072755751fSHerbert Dürr // indizes of values this have to be converted (interface conversion cpp<=>uno)
1085212c076SJim Jagielski sal_Int32 * pTempIndizes = reinterpret_cast<sal_Int32 *>(pUnoArgs + (2 * nParams));
1092755751fSHerbert Dürr // type descriptions for reconversions
1105212c076SJim Jagielski typelib_TypeDescription ** ppTempParamTypeDescr = reinterpret_cast<typelib_TypeDescription **>(pUnoArgs + (3 * nParams));
1112755751fSHerbert Dürr
1122755751fSHerbert Dürr sal_Int32 nTempIndizes = 0;
1132755751fSHerbert Dürr
1142755751fSHerbert Dürr for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
1152755751fSHerbert Dürr {
1162755751fSHerbert Dürr const typelib_MethodParameter & rParam = pParams[nPos];
1172755751fSHerbert Dürr
1182755751fSHerbert Dürr int nUsedGPR = 0;
1192755751fSHerbert Dürr int nUsedSSE = 0;
1208c988601SJim Jagielski bool bFitsRegisters = x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE );
1212755751fSHerbert Dürr if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
1222755751fSHerbert Dürr {
1232755751fSHerbert Dürr // Simple types must fit exactly one register on x86_64
1242755751fSHerbert Dürr OSL_ASSERT( bFitsRegisters && ( ( nUsedSSE == 1 && nUsedGPR == 0 ) || ( nUsedSSE == 0 && nUsedGPR == 1 ) ) );
1252755751fSHerbert Dürr
1262755751fSHerbert Dürr if ( nUsedSSE == 1 )
1272755751fSHerbert Dürr {
1282755751fSHerbert Dürr if ( nr_fpr < x86_64::MAX_SSE_REGS )
1292755751fSHerbert Dürr {
1302755751fSHerbert Dürr pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
1312755751fSHerbert Dürr nr_fpr++;
1322755751fSHerbert Dürr }
1332755751fSHerbert Dürr else
1342755751fSHerbert Dürr pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
1352755751fSHerbert Dürr }
1362755751fSHerbert Dürr else if ( nUsedGPR == 1 )
1372755751fSHerbert Dürr {
1382755751fSHerbert Dürr if ( nr_gpr < x86_64::MAX_GPR_REGS )
1392755751fSHerbert Dürr {
1402755751fSHerbert Dürr pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
1412755751fSHerbert Dürr nr_gpr++;
1422755751fSHerbert Dürr }
1432755751fSHerbert Dürr else
1442755751fSHerbert Dürr pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
1452755751fSHerbert Dürr }
1462755751fSHerbert Dürr }
1472755751fSHerbert Dürr else // struct <= 16 bytes || ptr to complex value || ref
1482755751fSHerbert Dürr {
1492755751fSHerbert Dürr typelib_TypeDescription * pParamTypeDescr = 0;
1502755751fSHerbert Dürr TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
1512755751fSHerbert Dürr
1522755751fSHerbert Dürr void *pCppStack;
1532755751fSHerbert Dürr if ( nr_gpr < x86_64::MAX_GPR_REGS )
1542755751fSHerbert Dürr {
1552755751fSHerbert Dürr pCppArgs[nPos] = pCppStack = *gpreg++;
1562755751fSHerbert Dürr nr_gpr++;
1572755751fSHerbert Dürr }
1582755751fSHerbert Dürr else
1592755751fSHerbert Dürr pCppArgs[nPos] = pCppStack = *ovrflw++;
1602755751fSHerbert Dürr
1612755751fSHerbert Dürr if (! rParam.bIn) // is pure out
1622755751fSHerbert Dürr {
1632755751fSHerbert Dürr // uno out is unconstructed mem!
1642755751fSHerbert Dürr pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
1652755751fSHerbert Dürr pTempIndizes[nTempIndizes] = nPos;
1662755751fSHerbert Dürr // will be released at reconversion
1672755751fSHerbert Dürr ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
1682755751fSHerbert Dürr }
1692755751fSHerbert Dürr else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
1702755751fSHerbert Dürr {
1712755751fSHerbert Dürr uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
1722755751fSHerbert Dürr pCppStack, pParamTypeDescr,
1732755751fSHerbert Dürr pThis->getBridge()->getCpp2Uno() );
1742755751fSHerbert Dürr pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
1752755751fSHerbert Dürr // will be released at reconversion
1762755751fSHerbert Dürr ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
1772755751fSHerbert Dürr }
1782755751fSHerbert Dürr else // direct way
1792755751fSHerbert Dürr {
1802755751fSHerbert Dürr pUnoArgs[nPos] = pCppStack;
1812755751fSHerbert Dürr // no longer needed
1822755751fSHerbert Dürr TYPELIB_DANGER_RELEASE( pParamTypeDescr );
1832755751fSHerbert Dürr }
1842755751fSHerbert Dürr }
1852755751fSHerbert Dürr }
1862755751fSHerbert Dürr
1872755751fSHerbert Dürr // ExceptionHolder
1882755751fSHerbert Dürr uno_Any aUnoExc; // Any will be constructed by callee
1892755751fSHerbert Dürr uno_Any * pUnoExc = &aUnoExc;
1902755751fSHerbert Dürr
1912755751fSHerbert Dürr // invoke uno dispatch call
1922755751fSHerbert Dürr (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
1932755751fSHerbert Dürr
19407a3d7f1SPedro Giffuni // in case an exception occurred...
1952755751fSHerbert Dürr if ( pUnoExc )
1962755751fSHerbert Dürr {
1972755751fSHerbert Dürr // destruct temporary in/inout params
1982755751fSHerbert Dürr for ( ; nTempIndizes--; )
1992755751fSHerbert Dürr {
2002755751fSHerbert Dürr sal_Int32 nIndex = pTempIndizes[nTempIndizes];
2012755751fSHerbert Dürr
2022755751fSHerbert Dürr if (pParams[nIndex].bIn) // is in/inout => was constructed
2032755751fSHerbert Dürr uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
2042755751fSHerbert Dürr TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
2052755751fSHerbert Dürr }
2062755751fSHerbert Dürr if (pReturnTypeDescr)
2072755751fSHerbert Dürr TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
2082755751fSHerbert Dürr
2092755751fSHerbert Dürr CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
2102755751fSHerbert Dürr // is here for dummy
2112755751fSHerbert Dürr return typelib_TypeClass_VOID;
2122755751fSHerbert Dürr }
21307a3d7f1SPedro Giffuni else // else no exception occurred...
2142755751fSHerbert Dürr {
2152755751fSHerbert Dürr // temporary params
2162755751fSHerbert Dürr for ( ; nTempIndizes--; )
2172755751fSHerbert Dürr {
2182755751fSHerbert Dürr sal_Int32 nIndex = pTempIndizes[nTempIndizes];
2192755751fSHerbert Dürr typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
2202755751fSHerbert Dürr
2212755751fSHerbert Dürr if ( pParams[nIndex].bOut ) // inout/out
2222755751fSHerbert Dürr {
2232755751fSHerbert Dürr // convert and assign
2242755751fSHerbert Dürr uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
2252755751fSHerbert Dürr uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
2262755751fSHerbert Dürr pThis->getBridge()->getUno2Cpp() );
2272755751fSHerbert Dürr }
2282755751fSHerbert Dürr // destroy temp uno param
2292755751fSHerbert Dürr uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
2302755751fSHerbert Dürr
2312755751fSHerbert Dürr TYPELIB_DANGER_RELEASE( pParamTypeDescr );
2322755751fSHerbert Dürr }
2332755751fSHerbert Dürr // return
2342755751fSHerbert Dürr if ( pCppReturn ) // has complex return
2352755751fSHerbert Dürr {
2362755751fSHerbert Dürr if ( pUnoReturn != pCppReturn ) // needs reconversion
2372755751fSHerbert Dürr {
2382755751fSHerbert Dürr uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
2392755751fSHerbert Dürr pThis->getBridge()->getUno2Cpp() );
2402755751fSHerbert Dürr // destroy temp uno return
2412755751fSHerbert Dürr uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
2422755751fSHerbert Dürr }
2432755751fSHerbert Dürr // complex return ptr is set to return reg
2445212c076SJim Jagielski *reinterpret_cast<void **>(pRegisterReturn) = pCppReturn;
2452755751fSHerbert Dürr }
2462755751fSHerbert Dürr if ( pReturnTypeDescr )
2472755751fSHerbert Dürr {
2482755751fSHerbert Dürr typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
2492755751fSHerbert Dürr TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
2502755751fSHerbert Dürr return eRet;
2512755751fSHerbert Dürr }
2522755751fSHerbert Dürr else
2532755751fSHerbert Dürr return typelib_TypeClass_VOID;
2542755751fSHerbert Dürr }
2552755751fSHerbert Dürr }
2562755751fSHerbert Dürr
2572755751fSHerbert Dürr
2582755751fSHerbert Dürr //==================================================================================================
cpp_vtable_call(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** gpreg,void ** fpreg,void ** ovrflw,sal_uInt64 * pRegisterReturn)2592755751fSHerbert Dürr extern "C" typelib_TypeClass cpp_vtable_call(
2602755751fSHerbert Dürr sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
2612755751fSHerbert Dürr void ** gpreg, void ** fpreg, void ** ovrflw,
2622755751fSHerbert Dürr sal_uInt64 * pRegisterReturn /* space for register return */ )
2632755751fSHerbert Dürr {
2642755751fSHerbert Dürr // gpreg: [ret *], this, [other gpr params]
2652755751fSHerbert Dürr // fpreg: [fpr params]
2662755751fSHerbert Dürr // ovrflw: [gpr or fpr params (properly aligned)]
2672755751fSHerbert Dürr void * pThis;
2682755751fSHerbert Dürr if ( nFunctionIndex & 0x80000000 )
2692755751fSHerbert Dürr {
2702755751fSHerbert Dürr nFunctionIndex &= 0x7fffffff;
2712755751fSHerbert Dürr pThis = gpreg[1];
2722755751fSHerbert Dürr }
2732755751fSHerbert Dürr else
2742755751fSHerbert Dürr {
2752755751fSHerbert Dürr pThis = gpreg[0];
2762755751fSHerbert Dürr }
2772755751fSHerbert Dürr pThis = static_cast<char *>( pThis ) - nVtableOffset;
2782755751fSHerbert Dürr
2792755751fSHerbert Dürr bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
2802755751fSHerbert Dürr bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
2812755751fSHerbert Dürr
2822755751fSHerbert Dürr typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
2832755751fSHerbert Dürr
2842755751fSHerbert Dürr OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
2852755751fSHerbert Dürr if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
2862755751fSHerbert Dürr {
2872755751fSHerbert Dürr throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
2882755751fSHerbert Dürr reinterpret_cast<XInterface *>( pCppI ) );
2892755751fSHerbert Dürr }
2902755751fSHerbert Dürr
2912755751fSHerbert Dürr // determine called method
2922755751fSHerbert Dürr sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
2932755751fSHerbert Dürr OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
2942755751fSHerbert Dürr
2952755751fSHerbert Dürr TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
2962755751fSHerbert Dürr
2972755751fSHerbert Dürr typelib_TypeClass eRet;
2982755751fSHerbert Dürr switch ( aMemberDescr.get()->eTypeClass )
2992755751fSHerbert Dürr {
3002755751fSHerbert Dürr case typelib_TypeClass_INTERFACE_ATTRIBUTE:
3012755751fSHerbert Dürr {
3022755751fSHerbert Dürr typelib_TypeDescriptionReference *pAttrTypeRef =
3032755751fSHerbert Dürr reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
3042755751fSHerbert Dürr
3052755751fSHerbert Dürr if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
3062755751fSHerbert Dürr {
3072755751fSHerbert Dürr // is GET method
3082755751fSHerbert Dürr eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
3092755751fSHerbert Dürr 0, 0, // no params
3102755751fSHerbert Dürr gpreg, fpreg, ovrflw, pRegisterReturn );
3112755751fSHerbert Dürr }
3122755751fSHerbert Dürr else
3132755751fSHerbert Dürr {
3142755751fSHerbert Dürr // is SET method
3152755751fSHerbert Dürr typelib_MethodParameter aParam;
3162755751fSHerbert Dürr aParam.pTypeRef = pAttrTypeRef;
3172755751fSHerbert Dürr aParam.bIn = sal_True;
3182755751fSHerbert Dürr aParam.bOut = sal_False;
3192755751fSHerbert Dürr
3202755751fSHerbert Dürr eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
3212755751fSHerbert Dürr 0, // indicates void return
3222755751fSHerbert Dürr 1, &aParam,
3232755751fSHerbert Dürr gpreg, fpreg, ovrflw, pRegisterReturn );
3242755751fSHerbert Dürr }
3252755751fSHerbert Dürr break;
3262755751fSHerbert Dürr }
3272755751fSHerbert Dürr case typelib_TypeClass_INTERFACE_METHOD:
3282755751fSHerbert Dürr {
3292755751fSHerbert Dürr // is METHOD
3302755751fSHerbert Dürr switch ( nFunctionIndex )
3312755751fSHerbert Dürr {
3322755751fSHerbert Dürr case 1: // acquire()
3332755751fSHerbert Dürr pCppI->acquireProxy(); // non virtual call!
3342755751fSHerbert Dürr eRet = typelib_TypeClass_VOID;
3352755751fSHerbert Dürr break;
3362755751fSHerbert Dürr case 2: // release()
3372755751fSHerbert Dürr pCppI->releaseProxy(); // non virtual call!
3382755751fSHerbert Dürr eRet = typelib_TypeClass_VOID;
3392755751fSHerbert Dürr break;
3402755751fSHerbert Dürr case 0: // queryInterface() opt
3412755751fSHerbert Dürr {
3422755751fSHerbert Dürr typelib_TypeDescription * pTD = 0;
343ecf1c5e9SJim Jagielski TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[2] )->getTypeLibType() );
3442755751fSHerbert Dürr if ( pTD )
3452755751fSHerbert Dürr {
3462755751fSHerbert Dürr XInterface * pInterface = 0;
3472755751fSHerbert Dürr (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
3482755751fSHerbert Dürr ( pCppI->getBridge()->getCppEnv(),
3495212c076SJim Jagielski reinterpret_cast<void **>(&pInterface),
3502755751fSHerbert Dürr pCppI->getOid().pData,
3512755751fSHerbert Dürr reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
3522755751fSHerbert Dürr
3532755751fSHerbert Dürr if ( pInterface )
3542755751fSHerbert Dürr {
355ecf1c5e9SJim Jagielski ::uno_any_construct( reinterpret_cast<uno_Any *>( gpreg[0] ),
3562755751fSHerbert Dürr &pInterface, pTD, cpp_acquire );
3572755751fSHerbert Dürr
3582755751fSHerbert Dürr pInterface->release();
3592755751fSHerbert Dürr TYPELIB_DANGER_RELEASE( pTD );
3602755751fSHerbert Dürr
3612755751fSHerbert Dürr reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0];
3622755751fSHerbert Dürr eRet = typelib_TypeClass_ANY;
3632755751fSHerbert Dürr break;
3642755751fSHerbert Dürr }
3652755751fSHerbert Dürr TYPELIB_DANGER_RELEASE( pTD );
3662755751fSHerbert Dürr }
3672755751fSHerbert Dürr } // else perform queryInterface()
3682755751fSHerbert Dürr default:
3692755751fSHerbert Dürr {
3702755751fSHerbert Dürr typelib_InterfaceMethodTypeDescription *pMethodTD =
3712755751fSHerbert Dürr reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
3722755751fSHerbert Dürr
3732755751fSHerbert Dürr eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
3742755751fSHerbert Dürr pMethodTD->pReturnTypeRef,
3752755751fSHerbert Dürr pMethodTD->nParams,
3762755751fSHerbert Dürr pMethodTD->pParams,
3772755751fSHerbert Dürr gpreg, fpreg, ovrflw, pRegisterReturn );
3782755751fSHerbert Dürr }
3792755751fSHerbert Dürr }
3802755751fSHerbert Dürr break;
3812755751fSHerbert Dürr }
3822755751fSHerbert Dürr default:
3832755751fSHerbert Dürr {
3842755751fSHerbert Dürr throw RuntimeException( OUString::createFromAscii("no member description found!"),
3852755751fSHerbert Dürr reinterpret_cast<XInterface *>( pCppI ) );
3862755751fSHerbert Dürr // is here for dummy
3872755751fSHerbert Dürr eRet = typelib_TypeClass_VOID;
3882755751fSHerbert Dürr }
3892755751fSHerbert Dürr }
3902755751fSHerbert Dürr
3912755751fSHerbert Dürr return eRet;
3922755751fSHerbert Dürr }
3932755751fSHerbert Dürr
3942755751fSHerbert Dürr //==================================================================================================
privateSnippetExecutor(void)395ecf1c5e9SJim Jagielski extern "C" void privateSnippetExecutor( void )
39693a81769SJim Jagielski {
39725f868f2SJim Jagielski asm volatile (
398*3187fb04SJim Jagielski " .text\n"
399*3187fb04SJim Jagielski " .align 2\n"
400*3187fb04SJim Jagielski ".globl privateSnippetExecutor\n"
40125f868f2SJim Jagielski " subq $160, %rsp\n"
40225f868f2SJim Jagielski " movq %r10, -152(%rbp)\n" // Save (nVtableOffset << 32) + nFunctionIndex
40325f868f2SJim Jagielski
40425f868f2SJim Jagielski " movq %rdi, -112(%rbp)\n" // Save GP registers
40525f868f2SJim Jagielski " movq %rsi, -104(%rbp)\n"
40625f868f2SJim Jagielski " movq %rdx, -96(%rbp)\n"
40725f868f2SJim Jagielski " movq %rcx, -88(%rbp)\n"
40825f868f2SJim Jagielski " movq %r8 , -80(%rbp)\n"
40925f868f2SJim Jagielski " movq %r9 , -72(%rbp)\n"
41025f868f2SJim Jagielski
41125f868f2SJim Jagielski " movsd %xmm0, -64(%rbp)\n" // Save FP registers
41225f868f2SJim Jagielski " movsd %xmm1, -56(%rbp)\n"
41325f868f2SJim Jagielski " movsd %xmm2, -48(%rbp)\n"
41425f868f2SJim Jagielski " movsd %xmm3, -40(%rbp)\n"
41525f868f2SJim Jagielski " movsd %xmm4, -32(%rbp)\n"
41625f868f2SJim Jagielski " movsd %xmm5, -24(%rbp)\n"
41725f868f2SJim Jagielski " movsd %xmm6, -16(%rbp)\n"
41825f868f2SJim Jagielski " movsd %xmm7, -8(%rbp)\n"
41925f868f2SJim Jagielski
42025f868f2SJim Jagielski " leaq -144(%rbp), %r9\n" // 6th param: sal_uInt64* pRegisterReturn
42125f868f2SJim Jagielski " leaq 16(%rbp), %r8\n" // 5rd param: void** ovrflw
42225f868f2SJim Jagielski " leaq -64(%rbp), %rcx\n" // 4th param: void** fpreg
42325f868f2SJim Jagielski " leaq -112(%rbp), %rdx\n" // 3rd param: void** gpreg
42425f868f2SJim Jagielski " movl -148(%rbp), %esi\n" // 2nd param: sal_int32 nVtableOffset
42525f868f2SJim Jagielski " movl -152(%rbp), %edi\n" // 1st param: sal_int32 nFunctionIndex
42625f868f2SJim Jagielski
42725f868f2SJim Jagielski " call _cpp_vtable_call\n"
42825f868f2SJim Jagielski
42925f868f2SJim Jagielski " cmp $10, %rax\n" // typelib_TypeClass_FLOAT
43025f868f2SJim Jagielski " je .Lfloat\n"
43125f868f2SJim Jagielski " cmp $11, %rax\n" // typelib_TypeClass_DOUBLE
43225f868f2SJim Jagielski " je .Lfloat\n"
43325f868f2SJim Jagielski
43425f868f2SJim Jagielski " movq -144(%rbp), %rax\n" // Return value (int case)
43525f868f2SJim Jagielski " movq -136(%rbp), %rdx\n" // Return value (int case)
43625f868f2SJim Jagielski " movq -144(%rbp), %xmm0\n" // Return value (int case)
43725f868f2SJim Jagielski " movq -136(%rbp), %xmm1\n" // Return value (int case)
43825f868f2SJim Jagielski " jmp .Lfinish\n"
43925f868f2SJim Jagielski ".Lfloat:\n"
44025f868f2SJim Jagielski " movlpd -144(%rbp), %xmm0\n" // Return value (float/double case)
44125f868f2SJim Jagielski ".Lfinish:\n"
44225f868f2SJim Jagielski " addq $160, %rsp\n"
44325f868f2SJim Jagielski );
44493a81769SJim Jagielski }
44537f4cb17SJim Jagielski const int codeSnippetSize = 24;
4462755751fSHerbert Dürr
4472755751fSHerbert Dürr // Generate a trampoline that redirects method calls to
4482755751fSHerbert Dürr // privateSnippetExecutor().
4492755751fSHerbert Dürr //
45037f4cb17SJim Jagielski // privateSnippetExecutor() saves all the registers that are used for
45137f4cb17SJim Jagielski // parameter passing on x86_64, and calls the cpp_vtable_call().
45237f4cb17SJim Jagielski // When it returns, privateSnippetExecutor() sets the return value.
45337f4cb17SJim Jagielski //
4542755751fSHerbert Dürr // Note: The code snippet we build here must not create a stack frame,
4552755751fSHerbert Dürr // otherwise the UNO exceptions stop working thanks to non-existing
4562755751fSHerbert Dürr // unwinding info.
codeSnippet(unsigned char * code,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,bool bHasHiddenParam)4572755751fSHerbert Dürr unsigned char * codeSnippet( unsigned char * code,
4582755751fSHerbert Dürr sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
4592755751fSHerbert Dürr bool bHasHiddenParam ) SAL_THROW( () )
4602755751fSHerbert Dürr {
4615212c076SJim Jagielski sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>( nVtableOffset ) << 32 ) | static_cast<sal_uInt64>( nFunctionIndex );
4622755751fSHerbert Dürr
4632755751fSHerbert Dürr if ( bHasHiddenParam )
4642755751fSHerbert Dürr nOffsetAndIndex |= 0x80000000;
4652755751fSHerbert Dürr
4662755751fSHerbert Dürr // movq $<nOffsetAndIndex>, %r10
4679c072909SJim Jagielski *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49;
468ecf1c5e9SJim Jagielski *reinterpret_cast<sal_uInt64 *>( code + 2 ) = nOffsetAndIndex;
4692755751fSHerbert Dürr
4702755751fSHerbert Dürr // movq $<address of the privateSnippetExecutor>, %r11
4719c072909SJim Jagielski *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49;
472ecf1c5e9SJim Jagielski *reinterpret_cast<sal_uInt64 *>( code + 12 ) = reinterpret_cast<sal_uInt64>( privateSnippetExecutor );
4732755751fSHerbert Dürr
4742755751fSHerbert Dürr // jmpq *%r11
4752755751fSHerbert Dürr *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
4762755751fSHerbert Dürr
4772755751fSHerbert Dürr return code + codeSnippetSize;
4782755751fSHerbert Dürr }
4792755751fSHerbert Dürr
4802755751fSHerbert Dürr //==================================================================================================
4812755751fSHerbert Dürr struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
4822755751fSHerbert Dürr
4832755751fSHerbert Dürr bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)4842755751fSHerbert Dürr bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
4852755751fSHerbert Dürr {
4862755751fSHerbert Dürr return static_cast< Slot * >(block) + 2;
4872755751fSHerbert Dürr }
4882755751fSHerbert Dürr
4892755751fSHerbert Dürr //==================================================================================================
getBlockSize(sal_Int32 slotCount)4902755751fSHerbert Dürr sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
4912755751fSHerbert Dürr sal_Int32 slotCount)
4922755751fSHerbert Dürr {
4932755751fSHerbert Dürr return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
4942755751fSHerbert Dürr }
4952755751fSHerbert Dürr
4962755751fSHerbert Dürr //==================================================================================================
4972755751fSHerbert Dürr bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)4982755751fSHerbert Dürr bridges::cpp_uno::shared::VtableFactory::initializeBlock(
4992755751fSHerbert Dürr void * block, sal_Int32 slotCount)
5002755751fSHerbert Dürr {
5012755751fSHerbert Dürr Slot * slots = mapBlockToVtable(block);
5022755751fSHerbert Dürr slots[-2].fn = 0;
5032755751fSHerbert Dürr slots[-1].fn = 0;
5042755751fSHerbert Dürr return slots + slotCount;
5052755751fSHerbert Dürr }
5062755751fSHerbert Dürr
5072755751fSHerbert Dürr //==================================================================================================
5082755751fSHerbert Dürr
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 nFunctionOffset,sal_Int32 functionCount,sal_Int32 nVtableOffset)5092755751fSHerbert Dürr unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
510831244c9SJim Jagielski Slot ** slots, unsigned char * code, /*sal_PtrDiff writetoexecdiff,*/
5112755751fSHerbert Dürr typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
5122755751fSHerbert Dürr sal_Int32 functionCount, sal_Int32 nVtableOffset )
5132755751fSHerbert Dürr {
514831244c9SJim Jagielski const sal_PtrDiff writetoexecdiff = 0;
5152755751fSHerbert Dürr (*slots) -= functionCount;
5162755751fSHerbert Dürr Slot * s = *slots;
5172755751fSHerbert Dürr for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
5182755751fSHerbert Dürr {
5192755751fSHerbert Dürr typelib_TypeDescription * pTD = 0;
5202755751fSHerbert Dürr
5212755751fSHerbert Dürr TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
5222755751fSHerbert Dürr OSL_ASSERT( pTD );
5232755751fSHerbert Dürr
5242755751fSHerbert Dürr if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
5252755751fSHerbert Dürr {
5262755751fSHerbert Dürr typelib_InterfaceAttributeTypeDescription *pAttrTD =
5272755751fSHerbert Dürr reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
5282755751fSHerbert Dürr
5292755751fSHerbert Dürr // get method
5302755751fSHerbert Dürr (s++)->fn = code + writetoexecdiff;
5312755751fSHerbert Dürr code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
5322755751fSHerbert Dürr x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
5332755751fSHerbert Dürr
5342755751fSHerbert Dürr if ( ! pAttrTD->bReadOnly )
5352755751fSHerbert Dürr {
5362755751fSHerbert Dürr // set method
5372755751fSHerbert Dürr (s++)->fn = code + writetoexecdiff;
5382755751fSHerbert Dürr code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
5392755751fSHerbert Dürr }
5402755751fSHerbert Dürr }
5412755751fSHerbert Dürr else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
5422755751fSHerbert Dürr {
5432755751fSHerbert Dürr typelib_InterfaceMethodTypeDescription *pMethodTD =
5442755751fSHerbert Dürr reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
5452755751fSHerbert Dürr
5462755751fSHerbert Dürr (s++)->fn = code + writetoexecdiff;
5472755751fSHerbert Dürr code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
5482755751fSHerbert Dürr x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
5492755751fSHerbert Dürr }
5502755751fSHerbert Dürr else
5512755751fSHerbert Dürr OSL_ASSERT( false );
5522755751fSHerbert Dürr
5532755751fSHerbert Dürr TYPELIB_DANGER_RELEASE( pTD );
5542755751fSHerbert Dürr }
5552755751fSHerbert Dürr return code;
5562755751fSHerbert Dürr }
5572755751fSHerbert Dürr
5582755751fSHerbert Dürr //==================================================================================================
flushCode(unsigned char const *,unsigned char const *)5592755751fSHerbert Dürr void bridges::cpp_uno::shared::VtableFactory::flushCode(
5602755751fSHerbert Dürr unsigned char const *, unsigned char const * )
5612755751fSHerbert Dürr {
5622755751fSHerbert Dürr }
563