xref: /AOO41X/main/bridges/source/cpp_uno/s5abi_macosx_x86-64/cpp2uno.cxx (revision 67a794bc92a1e8ffd80bf2fdc9bf74ed09144659)
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