16d1ed1ddSHerbert Dürr /**************************************************************
26d1ed1ddSHerbert Dürr *
36d1ed1ddSHerbert Dürr * Licensed to the Apache Software Foundation (ASF) under one
46d1ed1ddSHerbert Dürr * or more contributor license agreements. See the NOTICE file
56d1ed1ddSHerbert Dürr * distributed with this work for additional information
66d1ed1ddSHerbert Dürr * regarding copyright ownership. The ASF licenses this file
76d1ed1ddSHerbert Dürr * to you under the Apache License, Version 2.0 (the
86d1ed1ddSHerbert Dürr * "License"); you may not use this file except in compliance
96d1ed1ddSHerbert Dürr * with the License. You may obtain a copy of the License at
106d1ed1ddSHerbert Dürr *
116d1ed1ddSHerbert Dürr * http://www.apache.org/licenses/LICENSE-2.0
126d1ed1ddSHerbert Dürr *
136d1ed1ddSHerbert Dürr * Unless required by applicable law or agreed to in writing,
146d1ed1ddSHerbert Dürr * software distributed under the License is distributed on an
156d1ed1ddSHerbert Dürr * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
166d1ed1ddSHerbert Dürr * KIND, either express or implied. See the License for the
176d1ed1ddSHerbert Dürr * specific language governing permissions and limitations
186d1ed1ddSHerbert Dürr * under the License.
196d1ed1ddSHerbert Dürr *
206d1ed1ddSHerbert Dürr *************************************************************/
216d1ed1ddSHerbert Dürr
226d1ed1ddSHerbert Dürr
236d1ed1ddSHerbert Dürr
246d1ed1ddSHerbert Dürr // MARKER(update_precomp.py): autogen include statement, do not remove
256d1ed1ddSHerbert Dürr #include "precompiled_bridges.hxx"
266d1ed1ddSHerbert Dürr
276d1ed1ddSHerbert Dürr #include <stdio.h>
286d1ed1ddSHerbert Dürr #include <stdlib.h>
296d1ed1ddSHerbert Dürr #include <hash_map>
306d1ed1ddSHerbert Dürr
316d1ed1ddSHerbert Dürr #include <rtl/alloc.h>
326d1ed1ddSHerbert Dürr #include <osl/mutex.hxx>
336d1ed1ddSHerbert Dürr
346d1ed1ddSHerbert Dürr #include <com/sun/star/uno/genfunc.hxx>
356d1ed1ddSHerbert Dürr #include "com/sun/star/uno/RuntimeException.hpp"
366d1ed1ddSHerbert Dürr #include <uno/data.h>
376d1ed1ddSHerbert Dürr #include <typelib/typedescription.hxx>
386d1ed1ddSHerbert Dürr
396d1ed1ddSHerbert Dürr #include "bridges/cpp_uno/shared/bridge.hxx"
406d1ed1ddSHerbert Dürr #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
416d1ed1ddSHerbert Dürr #include "bridges/cpp_uno/shared/types.hxx"
426d1ed1ddSHerbert Dürr #include "bridges/cpp_uno/shared/vtablefactory.hxx"
436d1ed1ddSHerbert Dürr
446d1ed1ddSHerbert Dürr #include "abi.hxx"
456d1ed1ddSHerbert Dürr #include "share.hxx"
466d1ed1ddSHerbert Dürr
476d1ed1ddSHerbert Dürr using namespace ::osl;
486d1ed1ddSHerbert Dürr using namespace ::rtl;
496d1ed1ddSHerbert Dürr using namespace ::com::sun::star::uno;
506d1ed1ddSHerbert Dürr
516d1ed1ddSHerbert Dürr //==================================================================================================
526d1ed1ddSHerbert Dürr
536d1ed1ddSHerbert Dürr // Perform the UNO call
546d1ed1ddSHerbert Dürr //
556d1ed1ddSHerbert Dürr // We must convert the paramaters stored in gpreg, fpreg and ovrflw to UNO
566d1ed1ddSHerbert Dürr // arguments and call pThis->getUnoI()->pDispatcher.
576d1ed1ddSHerbert Dürr //
586d1ed1ddSHerbert Dürr // gpreg: [ret *], this, [gpr params]
596d1ed1ddSHerbert Dürr // fpreg: [fpr params]
606d1ed1ddSHerbert Dürr // ovrflw: [gpr or fpr params (properly aligned)]
616d1ed1ddSHerbert Dürr //
626d1ed1ddSHerbert Dürr // [ret *] is present when we are returning a structure bigger than 16 bytes
636d1ed1ddSHerbert Dürr // Simple types are returned in rax, rdx (int), or xmm0, xmm1 (fp).
646d1ed1ddSHerbert 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)656d1ed1ddSHerbert Dürr static typelib_TypeClass cpp2uno_call(
666d1ed1ddSHerbert Dürr bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
676d1ed1ddSHerbert Dürr const typelib_TypeDescription * pMemberTypeDescr,
686d1ed1ddSHerbert Dürr typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
696d1ed1ddSHerbert Dürr sal_Int32 nParams, typelib_MethodParameter * pParams,
706d1ed1ddSHerbert Dürr void ** gpreg, void ** fpreg, void ** ovrflw,
716d1ed1ddSHerbert Dürr sal_uInt64 * pRegisterReturn /* space for register return */ )
726d1ed1ddSHerbert Dürr {
736d1ed1ddSHerbert Dürr unsigned int nr_gpr = 0; //number of gpr registers used
746d1ed1ddSHerbert Dürr unsigned int nr_fpr = 0; //number of fpr registers used
756d1ed1ddSHerbert Dürr
766d1ed1ddSHerbert Dürr // return
776d1ed1ddSHerbert Dürr typelib_TypeDescription * pReturnTypeDescr = 0;
786d1ed1ddSHerbert Dürr if (pReturnTypeRef)
796d1ed1ddSHerbert Dürr TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
806d1ed1ddSHerbert Dürr
816d1ed1ddSHerbert Dürr void * pUnoReturn = 0;
826d1ed1ddSHerbert Dürr void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
836d1ed1ddSHerbert Dürr
846d1ed1ddSHerbert Dürr if ( pReturnTypeDescr )
856d1ed1ddSHerbert Dürr {
866d1ed1ddSHerbert Dürr if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
876d1ed1ddSHerbert Dürr {
886d1ed1ddSHerbert Dürr pCppReturn = *gpreg++;
896d1ed1ddSHerbert Dürr nr_gpr++;
906d1ed1ddSHerbert Dürr
916d1ed1ddSHerbert Dürr pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
926d1ed1ddSHerbert Dürr ? alloca( pReturnTypeDescr->nSize )
936d1ed1ddSHerbert Dürr : pCppReturn ); // direct way
946d1ed1ddSHerbert Dürr }
956d1ed1ddSHerbert Dürr else
966d1ed1ddSHerbert Dürr pUnoReturn = pRegisterReturn; // direct way for simple types
976d1ed1ddSHerbert Dürr }
986d1ed1ddSHerbert Dürr
996d1ed1ddSHerbert Dürr // pop this
1006d1ed1ddSHerbert Dürr gpreg++;
1016d1ed1ddSHerbert Dürr nr_gpr++;
1026d1ed1ddSHerbert Dürr
1036d1ed1ddSHerbert Dürr // stack space
1046d1ed1ddSHerbert Dürr // parameters
105*67a794bcSJim Jagielski void ** pUnoArgs = reinterpret_cast<void **>(alloca( 4 * sizeof(void *) * nParams ));
1066d1ed1ddSHerbert Dürr void ** pCppArgs = pUnoArgs + nParams;
1076d1ed1ddSHerbert Dürr // indizes of values this have to be converted (interface conversion cpp<=>uno)
108*67a794bcSJim Jagielski sal_Int32 * pTempIndizes = reinterpret_cast<sal_Int32 *>(pUnoArgs + (2 * nParams));
1096d1ed1ddSHerbert Dürr // type descriptions for reconversions
110*67a794bcSJim Jagielski typelib_TypeDescription ** ppTempParamTypeDescr = reinterpret_cast<typelib_TypeDescription **>(pUnoArgs + (3 * nParams));
1116d1ed1ddSHerbert Dürr
1126d1ed1ddSHerbert Dürr sal_Int32 nTempIndizes = 0;
1136d1ed1ddSHerbert Dürr
1146d1ed1ddSHerbert Dürr for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
1156d1ed1ddSHerbert Dürr {
1166d1ed1ddSHerbert Dürr const typelib_MethodParameter & rParam = pParams[nPos];
1176d1ed1ddSHerbert Dürr
1186d1ed1ddSHerbert Dürr int nUsedGPR = 0;
1196d1ed1ddSHerbert Dürr int nUsedSSE = 0;
120*67a794bcSJim Jagielski bool bFitsRegisters = x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE );
1216d1ed1ddSHerbert Dürr if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
1226d1ed1ddSHerbert Dürr {
1236d1ed1ddSHerbert Dürr // Simple types must fit exactly one register on x86_64
1246d1ed1ddSHerbert Dürr OSL_ASSERT( bFitsRegisters && ( ( nUsedSSE == 1 && nUsedGPR == 0 ) || ( nUsedSSE == 0 && nUsedGPR == 1 ) ) );
1256d1ed1ddSHerbert Dürr
1266d1ed1ddSHerbert Dürr if ( nUsedSSE == 1 )
1276d1ed1ddSHerbert Dürr {
1286d1ed1ddSHerbert Dürr if ( nr_fpr < x86_64::MAX_SSE_REGS )
1296d1ed1ddSHerbert Dürr {
1306d1ed1ddSHerbert Dürr pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
1316d1ed1ddSHerbert Dürr nr_fpr++;
1326d1ed1ddSHerbert Dürr }
1336d1ed1ddSHerbert Dürr else
1346d1ed1ddSHerbert Dürr pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
1356d1ed1ddSHerbert Dürr }
1366d1ed1ddSHerbert Dürr else if ( nUsedGPR == 1 )
1376d1ed1ddSHerbert Dürr {
1386d1ed1ddSHerbert Dürr if ( nr_gpr < x86_64::MAX_GPR_REGS )
1396d1ed1ddSHerbert Dürr {
1406d1ed1ddSHerbert Dürr pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
1416d1ed1ddSHerbert Dürr nr_gpr++;
1426d1ed1ddSHerbert Dürr }
1436d1ed1ddSHerbert Dürr else
1446d1ed1ddSHerbert Dürr pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
1456d1ed1ddSHerbert Dürr }
1466d1ed1ddSHerbert Dürr }
1476d1ed1ddSHerbert Dürr else // struct <= 16 bytes || ptr to complex value || ref
1486d1ed1ddSHerbert Dürr {
1496d1ed1ddSHerbert Dürr typelib_TypeDescription * pParamTypeDescr = 0;
1506d1ed1ddSHerbert Dürr TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
1516d1ed1ddSHerbert Dürr
1526d1ed1ddSHerbert Dürr void *pCppStack;
1536d1ed1ddSHerbert Dürr if ( nr_gpr < x86_64::MAX_GPR_REGS )
1546d1ed1ddSHerbert Dürr {
1556d1ed1ddSHerbert Dürr pCppArgs[nPos] = pCppStack = *gpreg++;
1566d1ed1ddSHerbert Dürr nr_gpr++;
1576d1ed1ddSHerbert Dürr }
1586d1ed1ddSHerbert Dürr else
1596d1ed1ddSHerbert Dürr pCppArgs[nPos] = pCppStack = *ovrflw++;
1606d1ed1ddSHerbert Dürr
1616d1ed1ddSHerbert Dürr if (! rParam.bIn) // is pure out
1626d1ed1ddSHerbert Dürr {
1636d1ed1ddSHerbert Dürr // uno out is unconstructed mem!
1646d1ed1ddSHerbert Dürr pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
1656d1ed1ddSHerbert Dürr pTempIndizes[nTempIndizes] = nPos;
1666d1ed1ddSHerbert Dürr // will be released at reconversion
1676d1ed1ddSHerbert Dürr ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
1686d1ed1ddSHerbert Dürr }
1696d1ed1ddSHerbert Dürr else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
1706d1ed1ddSHerbert Dürr {
1716d1ed1ddSHerbert Dürr uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
1726d1ed1ddSHerbert Dürr pCppStack, pParamTypeDescr,
1736d1ed1ddSHerbert Dürr pThis->getBridge()->getCpp2Uno() );
1746d1ed1ddSHerbert Dürr pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
1756d1ed1ddSHerbert Dürr // will be released at reconversion
1766d1ed1ddSHerbert Dürr ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
1776d1ed1ddSHerbert Dürr }
1786d1ed1ddSHerbert Dürr else // direct way
1796d1ed1ddSHerbert Dürr {
1806d1ed1ddSHerbert Dürr pUnoArgs[nPos] = pCppStack;
1816d1ed1ddSHerbert Dürr // no longer needed
1826d1ed1ddSHerbert Dürr TYPELIB_DANGER_RELEASE( pParamTypeDescr );
1836d1ed1ddSHerbert Dürr }
1846d1ed1ddSHerbert Dürr }
1856d1ed1ddSHerbert Dürr }
1866d1ed1ddSHerbert Dürr
1876d1ed1ddSHerbert Dürr // ExceptionHolder
1886d1ed1ddSHerbert Dürr uno_Any aUnoExc; // Any will be constructed by callee
1896d1ed1ddSHerbert Dürr uno_Any * pUnoExc = &aUnoExc;
1906d1ed1ddSHerbert Dürr
1916d1ed1ddSHerbert Dürr // invoke uno dispatch call
1926d1ed1ddSHerbert Dürr (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
1936d1ed1ddSHerbert Dürr
194*67a794bcSJim Jagielski // in case an exception occurred...
1956d1ed1ddSHerbert Dürr if ( pUnoExc )
1966d1ed1ddSHerbert Dürr {
1976d1ed1ddSHerbert Dürr // destruct temporary in/inout params
1986d1ed1ddSHerbert Dürr for ( ; nTempIndizes--; )
1996d1ed1ddSHerbert Dürr {
2006d1ed1ddSHerbert Dürr sal_Int32 nIndex = pTempIndizes[nTempIndizes];
2016d1ed1ddSHerbert Dürr
2026d1ed1ddSHerbert Dürr if (pParams[nIndex].bIn) // is in/inout => was constructed
2036d1ed1ddSHerbert Dürr uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
2046d1ed1ddSHerbert Dürr TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
2056d1ed1ddSHerbert Dürr }
2066d1ed1ddSHerbert Dürr if (pReturnTypeDescr)
2076d1ed1ddSHerbert Dürr TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
2086d1ed1ddSHerbert Dürr
2096d1ed1ddSHerbert Dürr CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
2106d1ed1ddSHerbert Dürr // is here for dummy
2116d1ed1ddSHerbert Dürr return typelib_TypeClass_VOID;
2126d1ed1ddSHerbert Dürr }
213*67a794bcSJim Jagielski else // else no exception occurred...
2146d1ed1ddSHerbert Dürr {
2156d1ed1ddSHerbert Dürr // temporary params
2166d1ed1ddSHerbert Dürr for ( ; nTempIndizes--; )
2176d1ed1ddSHerbert Dürr {
2186d1ed1ddSHerbert Dürr sal_Int32 nIndex = pTempIndizes[nTempIndizes];
2196d1ed1ddSHerbert Dürr typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
2206d1ed1ddSHerbert Dürr
2216d1ed1ddSHerbert Dürr if ( pParams[nIndex].bOut ) // inout/out
2226d1ed1ddSHerbert Dürr {
2236d1ed1ddSHerbert Dürr // convert and assign
2246d1ed1ddSHerbert Dürr uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
2256d1ed1ddSHerbert Dürr uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
2266d1ed1ddSHerbert Dürr pThis->getBridge()->getUno2Cpp() );
2276d1ed1ddSHerbert Dürr }
2286d1ed1ddSHerbert Dürr // destroy temp uno param
2296d1ed1ddSHerbert Dürr uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
2306d1ed1ddSHerbert Dürr
2316d1ed1ddSHerbert Dürr TYPELIB_DANGER_RELEASE( pParamTypeDescr );
2326d1ed1ddSHerbert Dürr }
2336d1ed1ddSHerbert Dürr // return
2346d1ed1ddSHerbert Dürr if ( pCppReturn ) // has complex return
2356d1ed1ddSHerbert Dürr {
2366d1ed1ddSHerbert Dürr if ( pUnoReturn != pCppReturn ) // needs reconversion
2376d1ed1ddSHerbert Dürr {
2386d1ed1ddSHerbert Dürr uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
2396d1ed1ddSHerbert Dürr pThis->getBridge()->getUno2Cpp() );
2406d1ed1ddSHerbert Dürr // destroy temp uno return
2416d1ed1ddSHerbert Dürr uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
2426d1ed1ddSHerbert Dürr }
2436d1ed1ddSHerbert Dürr // complex return ptr is set to return reg
244*67a794bcSJim Jagielski *reinterpret_cast<void **>(pRegisterReturn) = pCppReturn;
2456d1ed1ddSHerbert Dürr }
2466d1ed1ddSHerbert Dürr if ( pReturnTypeDescr )
2476d1ed1ddSHerbert Dürr {
2486d1ed1ddSHerbert Dürr typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
2496d1ed1ddSHerbert Dürr TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
2506d1ed1ddSHerbert Dürr return eRet;
2516d1ed1ddSHerbert Dürr }
2526d1ed1ddSHerbert Dürr else
2536d1ed1ddSHerbert Dürr return typelib_TypeClass_VOID;
2546d1ed1ddSHerbert Dürr }
2556d1ed1ddSHerbert Dürr }
2566d1ed1ddSHerbert Dürr
2576d1ed1ddSHerbert Dürr
2586d1ed1ddSHerbert Dürr //==================================================================================================
cpp_vtable_call(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** gpreg,void ** fpreg,void ** ovrflw,sal_uInt64 * pRegisterReturn)2596d1ed1ddSHerbert Dürr extern "C" typelib_TypeClass cpp_vtable_call(
2606d1ed1ddSHerbert Dürr sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
2616d1ed1ddSHerbert Dürr void ** gpreg, void ** fpreg, void ** ovrflw,
2626d1ed1ddSHerbert Dürr sal_uInt64 * pRegisterReturn /* space for register return */ )
2636d1ed1ddSHerbert Dürr {
2646d1ed1ddSHerbert Dürr // gpreg: [ret *], this, [other gpr params]
2656d1ed1ddSHerbert Dürr // fpreg: [fpr params]
2666d1ed1ddSHerbert Dürr // ovrflw: [gpr or fpr params (properly aligned)]
2676d1ed1ddSHerbert Dürr void * pThis;
2686d1ed1ddSHerbert Dürr if ( nFunctionIndex & 0x80000000 )
2696d1ed1ddSHerbert Dürr {
2706d1ed1ddSHerbert Dürr nFunctionIndex &= 0x7fffffff;
2716d1ed1ddSHerbert Dürr pThis = gpreg[1];
2726d1ed1ddSHerbert Dürr }
2736d1ed1ddSHerbert Dürr else
2746d1ed1ddSHerbert Dürr {
2756d1ed1ddSHerbert Dürr pThis = gpreg[0];
2766d1ed1ddSHerbert Dürr }
2776d1ed1ddSHerbert Dürr pThis = static_cast<char *>( pThis ) - nVtableOffset;
2786d1ed1ddSHerbert Dürr
2796d1ed1ddSHerbert Dürr bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
2806d1ed1ddSHerbert Dürr bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
2816d1ed1ddSHerbert Dürr
2826d1ed1ddSHerbert Dürr typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
2836d1ed1ddSHerbert Dürr
2846d1ed1ddSHerbert Dürr OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
2856d1ed1ddSHerbert Dürr if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
2866d1ed1ddSHerbert Dürr {
2876d1ed1ddSHerbert Dürr throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
2886d1ed1ddSHerbert Dürr reinterpret_cast<XInterface *>( pCppI ) );
2896d1ed1ddSHerbert Dürr }
2906d1ed1ddSHerbert Dürr
2916d1ed1ddSHerbert Dürr // determine called method
2926d1ed1ddSHerbert Dürr sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
2936d1ed1ddSHerbert Dürr OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
2946d1ed1ddSHerbert Dürr
2956d1ed1ddSHerbert Dürr TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
2966d1ed1ddSHerbert Dürr
2976d1ed1ddSHerbert Dürr typelib_TypeClass eRet;
2986d1ed1ddSHerbert Dürr switch ( aMemberDescr.get()->eTypeClass )
2996d1ed1ddSHerbert Dürr {
3006d1ed1ddSHerbert Dürr case typelib_TypeClass_INTERFACE_ATTRIBUTE:
3016d1ed1ddSHerbert Dürr {
3026d1ed1ddSHerbert Dürr typelib_TypeDescriptionReference *pAttrTypeRef =
3036d1ed1ddSHerbert Dürr reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
3046d1ed1ddSHerbert Dürr
3056d1ed1ddSHerbert Dürr if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
3066d1ed1ddSHerbert Dürr {
3076d1ed1ddSHerbert Dürr // is GET method
3086d1ed1ddSHerbert Dürr eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
3096d1ed1ddSHerbert Dürr 0, 0, // no params
3106d1ed1ddSHerbert Dürr gpreg, fpreg, ovrflw, pRegisterReturn );
3116d1ed1ddSHerbert Dürr }
3126d1ed1ddSHerbert Dürr else
3136d1ed1ddSHerbert Dürr {
3146d1ed1ddSHerbert Dürr // is SET method
3156d1ed1ddSHerbert Dürr typelib_MethodParameter aParam;
3166d1ed1ddSHerbert Dürr aParam.pTypeRef = pAttrTypeRef;
3176d1ed1ddSHerbert Dürr aParam.bIn = sal_True;
3186d1ed1ddSHerbert Dürr aParam.bOut = sal_False;
3196d1ed1ddSHerbert Dürr
3206d1ed1ddSHerbert Dürr eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
3216d1ed1ddSHerbert Dürr 0, // indicates void return
3226d1ed1ddSHerbert Dürr 1, &aParam,
3236d1ed1ddSHerbert Dürr gpreg, fpreg, ovrflw, pRegisterReturn );
3246d1ed1ddSHerbert Dürr }
3256d1ed1ddSHerbert Dürr break;
3266d1ed1ddSHerbert Dürr }
3276d1ed1ddSHerbert Dürr case typelib_TypeClass_INTERFACE_METHOD:
3286d1ed1ddSHerbert Dürr {
3296d1ed1ddSHerbert Dürr // is METHOD
3306d1ed1ddSHerbert Dürr switch ( nFunctionIndex )
3316d1ed1ddSHerbert Dürr {
3326d1ed1ddSHerbert Dürr case 1: // acquire()
3336d1ed1ddSHerbert Dürr pCppI->acquireProxy(); // non virtual call!
3346d1ed1ddSHerbert Dürr eRet = typelib_TypeClass_VOID;
3356d1ed1ddSHerbert Dürr break;
3366d1ed1ddSHerbert Dürr case 2: // release()
3376d1ed1ddSHerbert Dürr pCppI->releaseProxy(); // non virtual call!
3386d1ed1ddSHerbert Dürr eRet = typelib_TypeClass_VOID;
3396d1ed1ddSHerbert Dürr break;
3406d1ed1ddSHerbert Dürr case 0: // queryInterface() opt
3416d1ed1ddSHerbert Dürr {
3426d1ed1ddSHerbert Dürr typelib_TypeDescription * pTD = 0;
3436d1ed1ddSHerbert Dürr TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[2] )->getTypeLibType() );
3446d1ed1ddSHerbert Dürr if ( pTD )
3456d1ed1ddSHerbert Dürr {
3466d1ed1ddSHerbert Dürr XInterface * pInterface = 0;
3476d1ed1ddSHerbert Dürr (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
3486d1ed1ddSHerbert Dürr ( pCppI->getBridge()->getCppEnv(),
349*67a794bcSJim Jagielski reinterpret_cast<void **>(&pInterface),
3506d1ed1ddSHerbert Dürr pCppI->getOid().pData,
3516d1ed1ddSHerbert Dürr reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
3526d1ed1ddSHerbert Dürr
3536d1ed1ddSHerbert Dürr if ( pInterface )
3546d1ed1ddSHerbert Dürr {
3556d1ed1ddSHerbert Dürr ::uno_any_construct( reinterpret_cast<uno_Any *>( gpreg[0] ),
3566d1ed1ddSHerbert Dürr &pInterface, pTD, cpp_acquire );
3576d1ed1ddSHerbert Dürr
3586d1ed1ddSHerbert Dürr pInterface->release();
3596d1ed1ddSHerbert Dürr TYPELIB_DANGER_RELEASE( pTD );
3606d1ed1ddSHerbert Dürr
3616d1ed1ddSHerbert Dürr reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0];
3626d1ed1ddSHerbert Dürr eRet = typelib_TypeClass_ANY;
3636d1ed1ddSHerbert Dürr break;
3646d1ed1ddSHerbert Dürr }
3656d1ed1ddSHerbert Dürr TYPELIB_DANGER_RELEASE( pTD );
3666d1ed1ddSHerbert Dürr }
3676d1ed1ddSHerbert Dürr } // else perform queryInterface()
3686d1ed1ddSHerbert Dürr default:
3696d1ed1ddSHerbert Dürr {
3706d1ed1ddSHerbert Dürr typelib_InterfaceMethodTypeDescription *pMethodTD =
3716d1ed1ddSHerbert Dürr reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
3726d1ed1ddSHerbert Dürr
3736d1ed1ddSHerbert Dürr eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
3746d1ed1ddSHerbert Dürr pMethodTD->pReturnTypeRef,
3756d1ed1ddSHerbert Dürr pMethodTD->nParams,
3766d1ed1ddSHerbert Dürr pMethodTD->pParams,
3776d1ed1ddSHerbert Dürr gpreg, fpreg, ovrflw, pRegisterReturn );
3786d1ed1ddSHerbert Dürr }
3796d1ed1ddSHerbert Dürr }
3806d1ed1ddSHerbert Dürr break;
3816d1ed1ddSHerbert Dürr }
3826d1ed1ddSHerbert Dürr default:
3836d1ed1ddSHerbert Dürr {
3846d1ed1ddSHerbert Dürr throw RuntimeException( OUString::createFromAscii("no member description found!"),
3856d1ed1ddSHerbert Dürr reinterpret_cast<XInterface *>( pCppI ) );
3866d1ed1ddSHerbert Dürr // is here for dummy
3876d1ed1ddSHerbert Dürr eRet = typelib_TypeClass_VOID;
3886d1ed1ddSHerbert Dürr }
3896d1ed1ddSHerbert Dürr }
3906d1ed1ddSHerbert Dürr
3916d1ed1ddSHerbert Dürr return eRet;
3926d1ed1ddSHerbert Dürr }
3936d1ed1ddSHerbert Dürr
3946d1ed1ddSHerbert Dürr //==================================================================================================
privateSnippetExecutor(void)3956d1ed1ddSHerbert Dürr extern "C" void privateSnippetExecutor( void )
3966d1ed1ddSHerbert Dürr {
3976d1ed1ddSHerbert Dürr asm volatile (
398*67a794bcSJim Jagielski " subq $160, %rsp\n"
399*67a794bcSJim Jagielski " movq %r10, -152(%rbp)\n" // Save (nVtableOffset << 32) + nFunctionIndex
4006d1ed1ddSHerbert Dürr
401*67a794bcSJim Jagielski " movq %rdi, -112(%rbp)\n" // Save GP registers
402*67a794bcSJim Jagielski " movq %rsi, -104(%rbp)\n"
403*67a794bcSJim Jagielski " movq %rdx, -96(%rbp)\n"
404*67a794bcSJim Jagielski " movq %rcx, -88(%rbp)\n"
405*67a794bcSJim Jagielski " movq %r8 , -80(%rbp)\n"
406*67a794bcSJim Jagielski " movq %r9 , -72(%rbp)\n"
4076d1ed1ddSHerbert Dürr
408*67a794bcSJim Jagielski " movsd %xmm0, -64(%rbp)\n" // Save FP registers
409*67a794bcSJim Jagielski " movsd %xmm1, -56(%rbp)\n"
410*67a794bcSJim Jagielski " movsd %xmm2, -48(%rbp)\n"
411*67a794bcSJim Jagielski " movsd %xmm3, -40(%rbp)\n"
412*67a794bcSJim Jagielski " movsd %xmm4, -32(%rbp)\n"
413*67a794bcSJim Jagielski " movsd %xmm5, -24(%rbp)\n"
414*67a794bcSJim Jagielski " movsd %xmm6, -16(%rbp)\n"
415*67a794bcSJim Jagielski " movsd %xmm7, -8(%rbp)\n"
4166d1ed1ddSHerbert Dürr
417*67a794bcSJim Jagielski " leaq -144(%rbp), %r9\n" // 6th param: sal_uInt64* pRegisterReturn
418*67a794bcSJim Jagielski " leaq 16(%rbp), %r8\n" // 5rd param: void** ovrflw
419*67a794bcSJim Jagielski " leaq -64(%rbp), %rcx\n" // 4th param: void** fpreg
420*67a794bcSJim Jagielski " leaq -112(%rbp), %rdx\n" // 3rd param: void** gpreg
421*67a794bcSJim Jagielski " movl -148(%rbp), %esi\n" // 2nd param: sal_int32 nVtableOffset
422*67a794bcSJim Jagielski " movl -152(%rbp), %edi\n" // 1st param: sal_int32 nFunctionIndex
4236d1ed1ddSHerbert Dürr
424*67a794bcSJim Jagielski " call _cpp_vtable_call\n"
4256d1ed1ddSHerbert Dürr
426*67a794bcSJim Jagielski " cmp $10, %rax\n" // typelib_TypeClass_FLOAT
427*67a794bcSJim Jagielski " je .Lfloat\n"
428*67a794bcSJim Jagielski " cmp $11, %rax\n" // typelib_TypeClass_DOUBLE
429*67a794bcSJim Jagielski " je .Lfloat\n"
4306d1ed1ddSHerbert Dürr
431*67a794bcSJim Jagielski " movq -144(%rbp), %rax\n" // Return value (int case)
432*67a794bcSJim Jagielski " movq -136(%rbp), %rdx\n" // Return value (int case)
433*67a794bcSJim Jagielski " movq -144(%rbp), %xmm0\n" // Return value (int case)
434*67a794bcSJim Jagielski " movq -136(%rbp), %xmm1\n" // Return value (int case)
4356d1ed1ddSHerbert Dürr " jmp .Lfinish\n"
436*67a794bcSJim Jagielski ".Lfloat:\n"
437*67a794bcSJim Jagielski " movlpd -144(%rbp), %xmm0\n" // Return value (float/double case)
438*67a794bcSJim Jagielski ".Lfinish:\n"
439*67a794bcSJim Jagielski " addq $160, %rsp\n"
440*67a794bcSJim Jagielski );
4416d1ed1ddSHerbert Dürr }
442*67a794bcSJim Jagielski const int codeSnippetSize = 24;
4436d1ed1ddSHerbert Dürr
4446d1ed1ddSHerbert Dürr // Generate a trampoline that redirects method calls to
4456d1ed1ddSHerbert Dürr // privateSnippetExecutor().
4466d1ed1ddSHerbert Dürr //
447*67a794bcSJim Jagielski // privateSnippetExecutor() saves all the registers that are used for
448*67a794bcSJim Jagielski // parameter passing on x86_64, and calls the cpp_vtable_call().
449*67a794bcSJim Jagielski // When it returns, privateSnippetExecutor() sets the return value.
450*67a794bcSJim Jagielski //
4516d1ed1ddSHerbert Dürr // Note: The code snippet we build here must not create a stack frame,
4526d1ed1ddSHerbert Dürr // otherwise the UNO exceptions stop working thanks to non-existing
4536d1ed1ddSHerbert Dürr // unwinding info.
codeSnippet(unsigned char * code,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,bool bHasHiddenParam)4546d1ed1ddSHerbert Dürr unsigned char * codeSnippet( unsigned char * code,
4556d1ed1ddSHerbert Dürr sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
4566d1ed1ddSHerbert Dürr bool bHasHiddenParam ) SAL_THROW( () )
4576d1ed1ddSHerbert Dürr {
458*67a794bcSJim Jagielski sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>( nVtableOffset ) << 32 ) | static_cast<sal_uInt64>( nFunctionIndex );
4596d1ed1ddSHerbert Dürr
4606d1ed1ddSHerbert Dürr if ( bHasHiddenParam )
4616d1ed1ddSHerbert Dürr nOffsetAndIndex |= 0x80000000;
4626d1ed1ddSHerbert Dürr
4636d1ed1ddSHerbert Dürr // movq $<nOffsetAndIndex>, %r10
4646d1ed1ddSHerbert Dürr *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49;
4656d1ed1ddSHerbert Dürr *reinterpret_cast<sal_uInt64 *>( code + 2 ) = nOffsetAndIndex;
4666d1ed1ddSHerbert Dürr
4676d1ed1ddSHerbert Dürr // movq $<address of the privateSnippetExecutor>, %r11
4686d1ed1ddSHerbert Dürr *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49;
4696d1ed1ddSHerbert Dürr *reinterpret_cast<sal_uInt64 *>( code + 12 ) = reinterpret_cast<sal_uInt64>( privateSnippetExecutor );
4706d1ed1ddSHerbert Dürr
4716d1ed1ddSHerbert Dürr // jmpq *%r11
4726d1ed1ddSHerbert Dürr *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
4736d1ed1ddSHerbert Dürr
4746d1ed1ddSHerbert Dürr return code + codeSnippetSize;
4756d1ed1ddSHerbert Dürr }
4766d1ed1ddSHerbert Dürr
4776d1ed1ddSHerbert Dürr //==================================================================================================
4786d1ed1ddSHerbert Dürr struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
4796d1ed1ddSHerbert Dürr
4806d1ed1ddSHerbert Dürr bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)4816d1ed1ddSHerbert Dürr bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
4826d1ed1ddSHerbert Dürr {
4836d1ed1ddSHerbert Dürr return static_cast< Slot * >(block) + 2;
4846d1ed1ddSHerbert Dürr }
4856d1ed1ddSHerbert Dürr
4866d1ed1ddSHerbert Dürr //==================================================================================================
getBlockSize(sal_Int32 slotCount)4876d1ed1ddSHerbert Dürr sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
4886d1ed1ddSHerbert Dürr sal_Int32 slotCount)
4896d1ed1ddSHerbert Dürr {
4906d1ed1ddSHerbert Dürr return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
4916d1ed1ddSHerbert Dürr }
4926d1ed1ddSHerbert Dürr
4936d1ed1ddSHerbert Dürr //==================================================================================================
4946d1ed1ddSHerbert Dürr bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)4956d1ed1ddSHerbert Dürr bridges::cpp_uno::shared::VtableFactory::initializeBlock(
4966d1ed1ddSHerbert Dürr void * block, sal_Int32 slotCount)
4976d1ed1ddSHerbert Dürr {
4986d1ed1ddSHerbert Dürr Slot * slots = mapBlockToVtable(block);
4996d1ed1ddSHerbert Dürr slots[-2].fn = 0;
5006d1ed1ddSHerbert Dürr slots[-1].fn = 0;
5016d1ed1ddSHerbert Dürr return slots + slotCount;
5026d1ed1ddSHerbert Dürr }
5036d1ed1ddSHerbert Dürr
5046d1ed1ddSHerbert Dürr //==================================================================================================
5056d1ed1ddSHerbert Dürr
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 nFunctionOffset,sal_Int32 functionCount,sal_Int32 nVtableOffset)5066d1ed1ddSHerbert Dürr unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
5076d1ed1ddSHerbert Dürr Slot ** slots, unsigned char * code, /*sal_PtrDiff writetoexecdiff,*/
5086d1ed1ddSHerbert Dürr typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
5096d1ed1ddSHerbert Dürr sal_Int32 functionCount, sal_Int32 nVtableOffset )
5106d1ed1ddSHerbert Dürr {
511*67a794bcSJim Jagielski const sal_PtrDiff writetoexecdiff = 0;
5126d1ed1ddSHerbert Dürr (*slots) -= functionCount;
5136d1ed1ddSHerbert Dürr Slot * s = *slots;
5146d1ed1ddSHerbert Dürr for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
5156d1ed1ddSHerbert Dürr {
5166d1ed1ddSHerbert Dürr typelib_TypeDescription * pTD = 0;
5176d1ed1ddSHerbert Dürr
5186d1ed1ddSHerbert Dürr TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
5196d1ed1ddSHerbert Dürr OSL_ASSERT( pTD );
5206d1ed1ddSHerbert Dürr
5216d1ed1ddSHerbert Dürr if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
5226d1ed1ddSHerbert Dürr {
5236d1ed1ddSHerbert Dürr typelib_InterfaceAttributeTypeDescription *pAttrTD =
5246d1ed1ddSHerbert Dürr reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
5256d1ed1ddSHerbert Dürr
5266d1ed1ddSHerbert Dürr // get method
5276d1ed1ddSHerbert Dürr (s++)->fn = code + writetoexecdiff;
5286d1ed1ddSHerbert Dürr code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
5296d1ed1ddSHerbert Dürr x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
5306d1ed1ddSHerbert Dürr
5316d1ed1ddSHerbert Dürr if ( ! pAttrTD->bReadOnly )
5326d1ed1ddSHerbert Dürr {
5336d1ed1ddSHerbert Dürr // set method
5346d1ed1ddSHerbert Dürr (s++)->fn = code + writetoexecdiff;
5356d1ed1ddSHerbert Dürr code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
5366d1ed1ddSHerbert Dürr }
5376d1ed1ddSHerbert Dürr }
5386d1ed1ddSHerbert Dürr else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
5396d1ed1ddSHerbert Dürr {
5406d1ed1ddSHerbert Dürr typelib_InterfaceMethodTypeDescription *pMethodTD =
5416d1ed1ddSHerbert Dürr reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
5426d1ed1ddSHerbert Dürr
5436d1ed1ddSHerbert Dürr (s++)->fn = code + writetoexecdiff;
5446d1ed1ddSHerbert Dürr code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
5456d1ed1ddSHerbert Dürr x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
5466d1ed1ddSHerbert Dürr }
5476d1ed1ddSHerbert Dürr else
5486d1ed1ddSHerbert Dürr OSL_ASSERT( false );
5496d1ed1ddSHerbert Dürr
5506d1ed1ddSHerbert Dürr TYPELIB_DANGER_RELEASE( pTD );
5516d1ed1ddSHerbert Dürr }
5526d1ed1ddSHerbert Dürr return code;
5536d1ed1ddSHerbert Dürr }
5546d1ed1ddSHerbert Dürr
5556d1ed1ddSHerbert Dürr //==================================================================================================
flushCode(unsigned char const *,unsigned char const *)5566d1ed1ddSHerbert Dürr void bridges::cpp_uno::shared::VtableFactory::flushCode(
5576d1ed1ddSHerbert Dürr unsigned char const *, unsigned char const * )
5586d1ed1ddSHerbert Dürr {
5596d1ed1ddSHerbert Dürr }
560