1809f4227SJim Jagielski /**************************************************************
2809f4227SJim Jagielski *
3809f4227SJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4809f4227SJim Jagielski * or more contributor license agreements. See the NOTICE file
5809f4227SJim Jagielski * distributed with this work for additional information
6809f4227SJim Jagielski * regarding copyright ownership. The ASF licenses this file
7809f4227SJim Jagielski * to you under the Apache License, Version 2.0 (the
8809f4227SJim Jagielski * "License"); you may not use this file except in compliance
9809f4227SJim Jagielski * with the License. You may obtain a copy of the License at
10809f4227SJim Jagielski *
11809f4227SJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12809f4227SJim Jagielski *
13809f4227SJim Jagielski * Unless required by applicable law or agreed to in writing,
14809f4227SJim Jagielski * software distributed under the License is distributed on an
15809f4227SJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16809f4227SJim Jagielski * KIND, either express or implied. See the License for the
17809f4227SJim Jagielski * specific language governing permissions and limitations
18809f4227SJim Jagielski * under the License.
19809f4227SJim Jagielski *
20809f4227SJim Jagielski *************************************************************/
21809f4227SJim Jagielski
22809f4227SJim Jagielski
23809f4227SJim Jagielski
24809f4227SJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25809f4227SJim Jagielski #include "precompiled_bridges.hxx"
26809f4227SJim Jagielski
27809f4227SJim Jagielski #include <stdio.h>
28809f4227SJim Jagielski #include <stdlib.h>
29809f4227SJim Jagielski #include <hash_map>
30809f4227SJim Jagielski
31809f4227SJim Jagielski #include <rtl/alloc.h>
32809f4227SJim Jagielski #include <osl/mutex.hxx>
33809f4227SJim Jagielski
34809f4227SJim Jagielski #include <com/sun/star/uno/genfunc.hxx>
35809f4227SJim Jagielski #include "com/sun/star/uno/RuntimeException.hpp"
36809f4227SJim Jagielski #include <uno/data.h>
37809f4227SJim Jagielski #include <typelib/typedescription.hxx>
38809f4227SJim Jagielski
39809f4227SJim Jagielski #include "bridges/cpp_uno/shared/bridge.hxx"
40809f4227SJim Jagielski #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
41809f4227SJim Jagielski #include "bridges/cpp_uno/shared/types.hxx"
42809f4227SJim Jagielski #include "bridges/cpp_uno/shared/vtablefactory.hxx"
43809f4227SJim Jagielski
44809f4227SJim Jagielski #include "abi.hxx"
45809f4227SJim Jagielski #include "share.hxx"
46809f4227SJim Jagielski
47809f4227SJim Jagielski using namespace ::osl;
48809f4227SJim Jagielski using namespace ::rtl;
49809f4227SJim Jagielski using namespace ::com::sun::star::uno;
50809f4227SJim Jagielski
51809f4227SJim Jagielski //==================================================================================================
52809f4227SJim Jagielski
53809f4227SJim Jagielski // Perform the UNO call
54809f4227SJim Jagielski //
55*3f67767cSJohn Bampton // We must convert the parameters stored in gpreg, fpreg and ovrflw to UNO
56809f4227SJim Jagielski // arguments and call pThis->getUnoI()->pDispatcher.
57809f4227SJim Jagielski //
58809f4227SJim Jagielski // gpreg: [ret *], this, [gpr params]
59809f4227SJim Jagielski // fpreg: [fpr params]
60809f4227SJim Jagielski // ovrflw: [gpr or fpr params (properly aligned)]
61809f4227SJim Jagielski //
62809f4227SJim Jagielski // [ret *] is present when we are returning a structure bigger than 16 bytes
63809f4227SJim Jagielski // Simple types are returned in rax, rdx (int), or xmm0, xmm1 (fp).
64809f4227SJim Jagielski // 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)65809f4227SJim Jagielski static typelib_TypeClass cpp2uno_call(
66809f4227SJim Jagielski bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
67809f4227SJim Jagielski const typelib_TypeDescription * pMemberTypeDescr,
68809f4227SJim Jagielski typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
69809f4227SJim Jagielski sal_Int32 nParams, typelib_MethodParameter * pParams,
70809f4227SJim Jagielski void ** gpreg, void ** fpreg, void ** ovrflw,
71809f4227SJim Jagielski sal_uInt64 * pRegisterReturn /* space for register return */ )
72809f4227SJim Jagielski {
73809f4227SJim Jagielski unsigned int nr_gpr = 0; //number of gpr registers used
74809f4227SJim Jagielski unsigned int nr_fpr = 0; //number of fpr registers used
75809f4227SJim Jagielski
76809f4227SJim Jagielski // return
77809f4227SJim Jagielski typelib_TypeDescription * pReturnTypeDescr = 0;
78809f4227SJim Jagielski if (pReturnTypeRef)
79809f4227SJim Jagielski TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
80809f4227SJim Jagielski
81809f4227SJim Jagielski void * pUnoReturn = 0;
82809f4227SJim Jagielski void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
83809f4227SJim Jagielski
84809f4227SJim Jagielski if ( pReturnTypeDescr )
85809f4227SJim Jagielski {
86809f4227SJim Jagielski if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
87809f4227SJim Jagielski {
88809f4227SJim Jagielski pCppReturn = *gpreg++;
89809f4227SJim Jagielski nr_gpr++;
90809f4227SJim Jagielski
91809f4227SJim Jagielski pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
92809f4227SJim Jagielski ? alloca( pReturnTypeDescr->nSize )
93809f4227SJim Jagielski : pCppReturn ); // direct way
94809f4227SJim Jagielski }
95809f4227SJim Jagielski else
96809f4227SJim Jagielski pUnoReturn = pRegisterReturn; // direct way for simple types
97809f4227SJim Jagielski }
98809f4227SJim Jagielski
99809f4227SJim Jagielski // pop this
100809f4227SJim Jagielski gpreg++;
101809f4227SJim Jagielski nr_gpr++;
102809f4227SJim Jagielski
103809f4227SJim Jagielski // stack space
104809f4227SJim Jagielski // parameters
105ecf1c5e9SJim Jagielski void ** pUnoArgs = reinterpret_cast<void **>(alloca( 4 * sizeof(void *) * nParams ));
106809f4227SJim Jagielski void ** pCppArgs = pUnoArgs + nParams;
107809f4227SJim Jagielski // indizes of values this have to be converted (interface conversion cpp<=>uno)
108809f4227SJim Jagielski sal_Int32 * pTempIndizes = reinterpret_cast<sal_Int32 *>(pUnoArgs + (2 * nParams));
109809f4227SJim Jagielski // type descriptions for reconversions
110809f4227SJim Jagielski typelib_TypeDescription ** ppTempParamTypeDescr = reinterpret_cast<typelib_TypeDescription **>(pUnoArgs + (3 * nParams));
111809f4227SJim Jagielski
112809f4227SJim Jagielski sal_Int32 nTempIndizes = 0;
113809f4227SJim Jagielski
114809f4227SJim Jagielski for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
115809f4227SJim Jagielski {
116809f4227SJim Jagielski const typelib_MethodParameter & rParam = pParams[nPos];
117809f4227SJim Jagielski
118809f4227SJim Jagielski int nUsedGPR = 0;
119809f4227SJim Jagielski int nUsedSSE = 0;
120809f4227SJim Jagielski bool bFitsRegisters = x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE );
121809f4227SJim Jagielski if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
122809f4227SJim Jagielski {
123809f4227SJim Jagielski // Simple types must fit exactly one register on x86_64
124809f4227SJim Jagielski OSL_ASSERT( bFitsRegisters && ( ( nUsedSSE == 1 && nUsedGPR == 0 ) || ( nUsedSSE == 0 && nUsedGPR == 1 ) ) );
125809f4227SJim Jagielski
126809f4227SJim Jagielski if ( nUsedSSE == 1 )
127809f4227SJim Jagielski {
128809f4227SJim Jagielski if ( nr_fpr < x86_64::MAX_SSE_REGS )
129809f4227SJim Jagielski {
130809f4227SJim Jagielski pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
131809f4227SJim Jagielski nr_fpr++;
132809f4227SJim Jagielski }
133809f4227SJim Jagielski else
134809f4227SJim Jagielski pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
135809f4227SJim Jagielski }
136809f4227SJim Jagielski else if ( nUsedGPR == 1 )
137809f4227SJim Jagielski {
138809f4227SJim Jagielski if ( nr_gpr < x86_64::MAX_GPR_REGS )
139809f4227SJim Jagielski {
140809f4227SJim Jagielski pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
141809f4227SJim Jagielski nr_gpr++;
142809f4227SJim Jagielski }
143809f4227SJim Jagielski else
144809f4227SJim Jagielski pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
145809f4227SJim Jagielski }
146809f4227SJim Jagielski }
147809f4227SJim Jagielski else // struct <= 16 bytes || ptr to complex value || ref
148809f4227SJim Jagielski {
149809f4227SJim Jagielski typelib_TypeDescription * pParamTypeDescr = 0;
150809f4227SJim Jagielski TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
151809f4227SJim Jagielski
152809f4227SJim Jagielski void *pCppStack;
153809f4227SJim Jagielski if ( nr_gpr < x86_64::MAX_GPR_REGS )
154809f4227SJim Jagielski {
155809f4227SJim Jagielski pCppArgs[nPos] = pCppStack = *gpreg++;
156809f4227SJim Jagielski nr_gpr++;
157809f4227SJim Jagielski }
158809f4227SJim Jagielski else
159809f4227SJim Jagielski pCppArgs[nPos] = pCppStack = *ovrflw++;
160809f4227SJim Jagielski
161809f4227SJim Jagielski if (! rParam.bIn) // is pure out
162809f4227SJim Jagielski {
163809f4227SJim Jagielski // uno out is unconstructed mem!
164809f4227SJim Jagielski pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
165809f4227SJim Jagielski pTempIndizes[nTempIndizes] = nPos;
166809f4227SJim Jagielski // will be released at reconversion
167809f4227SJim Jagielski ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
168809f4227SJim Jagielski }
169809f4227SJim Jagielski else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
170809f4227SJim Jagielski {
171809f4227SJim Jagielski uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
172809f4227SJim Jagielski pCppStack, pParamTypeDescr,
173809f4227SJim Jagielski pThis->getBridge()->getCpp2Uno() );
174809f4227SJim Jagielski pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
175809f4227SJim Jagielski // will be released at reconversion
176809f4227SJim Jagielski ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
177809f4227SJim Jagielski }
178809f4227SJim Jagielski else // direct way
179809f4227SJim Jagielski {
180809f4227SJim Jagielski pUnoArgs[nPos] = pCppStack;
181809f4227SJim Jagielski // no longer needed
182809f4227SJim Jagielski TYPELIB_DANGER_RELEASE( pParamTypeDescr );
183809f4227SJim Jagielski }
184809f4227SJim Jagielski }
185809f4227SJim Jagielski }
186809f4227SJim Jagielski
187809f4227SJim Jagielski // ExceptionHolder
188809f4227SJim Jagielski uno_Any aUnoExc; // Any will be constructed by callee
189809f4227SJim Jagielski uno_Any * pUnoExc = &aUnoExc;
190809f4227SJim Jagielski
191809f4227SJim Jagielski // invoke uno dispatch call
192809f4227SJim Jagielski (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
193809f4227SJim Jagielski
194809f4227SJim Jagielski // in case an exception occurred...
195809f4227SJim Jagielski if ( pUnoExc )
196809f4227SJim Jagielski {
197809f4227SJim Jagielski // destruct temporary in/inout params
198809f4227SJim Jagielski for ( ; nTempIndizes--; )
199809f4227SJim Jagielski {
200809f4227SJim Jagielski sal_Int32 nIndex = pTempIndizes[nTempIndizes];
201809f4227SJim Jagielski
202809f4227SJim Jagielski if (pParams[nIndex].bIn) // is in/inout => was constructed
203809f4227SJim Jagielski uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
204809f4227SJim Jagielski TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
205809f4227SJim Jagielski }
206809f4227SJim Jagielski if (pReturnTypeDescr)
207809f4227SJim Jagielski TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
208809f4227SJim Jagielski
209809f4227SJim Jagielski CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
210809f4227SJim Jagielski // is here for dummy
211809f4227SJim Jagielski return typelib_TypeClass_VOID;
212809f4227SJim Jagielski }
213809f4227SJim Jagielski else // else no exception occurred...
214809f4227SJim Jagielski {
215809f4227SJim Jagielski // temporary params
216809f4227SJim Jagielski for ( ; nTempIndizes--; )
217809f4227SJim Jagielski {
218809f4227SJim Jagielski sal_Int32 nIndex = pTempIndizes[nTempIndizes];
219809f4227SJim Jagielski typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
220809f4227SJim Jagielski
221809f4227SJim Jagielski if ( pParams[nIndex].bOut ) // inout/out
222809f4227SJim Jagielski {
223809f4227SJim Jagielski // convert and assign
224809f4227SJim Jagielski uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
225809f4227SJim Jagielski uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
226809f4227SJim Jagielski pThis->getBridge()->getUno2Cpp() );
227809f4227SJim Jagielski }
228809f4227SJim Jagielski // destroy temp uno param
229809f4227SJim Jagielski uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
230809f4227SJim Jagielski
231809f4227SJim Jagielski TYPELIB_DANGER_RELEASE( pParamTypeDescr );
232809f4227SJim Jagielski }
233809f4227SJim Jagielski // return
234809f4227SJim Jagielski if ( pCppReturn ) // has complex return
235809f4227SJim Jagielski {
236809f4227SJim Jagielski if ( pUnoReturn != pCppReturn ) // needs reconversion
237809f4227SJim Jagielski {
238809f4227SJim Jagielski uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
239809f4227SJim Jagielski pThis->getBridge()->getUno2Cpp() );
240809f4227SJim Jagielski // destroy temp uno return
241809f4227SJim Jagielski uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
242809f4227SJim Jagielski }
243809f4227SJim Jagielski // complex return ptr is set to return reg
244809f4227SJim Jagielski *reinterpret_cast<void **>(pRegisterReturn) = pCppReturn;
245809f4227SJim Jagielski }
246809f4227SJim Jagielski if ( pReturnTypeDescr )
247809f4227SJim Jagielski {
248809f4227SJim Jagielski typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
249809f4227SJim Jagielski TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
250809f4227SJim Jagielski return eRet;
251809f4227SJim Jagielski }
252809f4227SJim Jagielski else
253809f4227SJim Jagielski return typelib_TypeClass_VOID;
254809f4227SJim Jagielski }
255809f4227SJim Jagielski }
256809f4227SJim Jagielski
257809f4227SJim Jagielski
258809f4227SJim Jagielski //==================================================================================================
cpp_vtable_call(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** gpreg,void ** fpreg,void ** ovrflw,sal_uInt64 * pRegisterReturn)259809f4227SJim Jagielski extern "C" typelib_TypeClass cpp_vtable_call(
260809f4227SJim Jagielski sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
261809f4227SJim Jagielski void ** gpreg, void ** fpreg, void ** ovrflw,
262809f4227SJim Jagielski sal_uInt64 * pRegisterReturn /* space for register return */ )
263809f4227SJim Jagielski {
264809f4227SJim Jagielski // gpreg: [ret *], this, [other gpr params]
265809f4227SJim Jagielski // fpreg: [fpr params]
266809f4227SJim Jagielski // ovrflw: [gpr or fpr params (properly aligned)]
267809f4227SJim Jagielski void * pThis;
268809f4227SJim Jagielski if ( nFunctionIndex & 0x80000000 )
269809f4227SJim Jagielski {
270809f4227SJim Jagielski nFunctionIndex &= 0x7fffffff;
271809f4227SJim Jagielski pThis = gpreg[1];
272809f4227SJim Jagielski }
273809f4227SJim Jagielski else
274809f4227SJim Jagielski {
275809f4227SJim Jagielski pThis = gpreg[0];
276809f4227SJim Jagielski }
277809f4227SJim Jagielski pThis = static_cast<char *>( pThis ) - nVtableOffset;
278809f4227SJim Jagielski
279809f4227SJim Jagielski bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
280809f4227SJim Jagielski bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
281809f4227SJim Jagielski
282809f4227SJim Jagielski typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
283809f4227SJim Jagielski
284809f4227SJim Jagielski OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
285809f4227SJim Jagielski if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
286809f4227SJim Jagielski {
287809f4227SJim Jagielski throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
288809f4227SJim Jagielski reinterpret_cast<XInterface *>( pCppI ) );
289809f4227SJim Jagielski }
290809f4227SJim Jagielski
291809f4227SJim Jagielski // determine called method
292809f4227SJim Jagielski sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
293809f4227SJim Jagielski OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
294809f4227SJim Jagielski
295809f4227SJim Jagielski TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
296809f4227SJim Jagielski
297809f4227SJim Jagielski typelib_TypeClass eRet;
298809f4227SJim Jagielski switch ( aMemberDescr.get()->eTypeClass )
299809f4227SJim Jagielski {
300809f4227SJim Jagielski case typelib_TypeClass_INTERFACE_ATTRIBUTE:
301809f4227SJim Jagielski {
302809f4227SJim Jagielski typelib_TypeDescriptionReference *pAttrTypeRef =
303809f4227SJim Jagielski reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
304809f4227SJim Jagielski
305809f4227SJim Jagielski if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
306809f4227SJim Jagielski {
307809f4227SJim Jagielski // is GET method
308809f4227SJim Jagielski eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
309809f4227SJim Jagielski 0, 0, // no params
310809f4227SJim Jagielski gpreg, fpreg, ovrflw, pRegisterReturn );
311809f4227SJim Jagielski }
312809f4227SJim Jagielski else
313809f4227SJim Jagielski {
314809f4227SJim Jagielski // is SET method
315809f4227SJim Jagielski typelib_MethodParameter aParam;
316809f4227SJim Jagielski aParam.pTypeRef = pAttrTypeRef;
317809f4227SJim Jagielski aParam.bIn = sal_True;
318809f4227SJim Jagielski aParam.bOut = sal_False;
319809f4227SJim Jagielski
320809f4227SJim Jagielski eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
321809f4227SJim Jagielski 0, // indicates void return
322809f4227SJim Jagielski 1, &aParam,
323809f4227SJim Jagielski gpreg, fpreg, ovrflw, pRegisterReturn );
324809f4227SJim Jagielski }
325809f4227SJim Jagielski break;
326809f4227SJim Jagielski }
327809f4227SJim Jagielski case typelib_TypeClass_INTERFACE_METHOD:
328809f4227SJim Jagielski {
329809f4227SJim Jagielski // is METHOD
330809f4227SJim Jagielski switch ( nFunctionIndex )
331809f4227SJim Jagielski {
332809f4227SJim Jagielski case 1: // acquire()
333809f4227SJim Jagielski pCppI->acquireProxy(); // non virtual call!
334809f4227SJim Jagielski eRet = typelib_TypeClass_VOID;
335809f4227SJim Jagielski break;
336809f4227SJim Jagielski case 2: // release()
337809f4227SJim Jagielski pCppI->releaseProxy(); // non virtual call!
338809f4227SJim Jagielski eRet = typelib_TypeClass_VOID;
339809f4227SJim Jagielski break;
340809f4227SJim Jagielski case 0: // queryInterface() opt
341809f4227SJim Jagielski {
342809f4227SJim Jagielski typelib_TypeDescription * pTD = 0;
343ecf1c5e9SJim Jagielski TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[2] )->getTypeLibType() );
344809f4227SJim Jagielski if ( pTD )
345809f4227SJim Jagielski {
346809f4227SJim Jagielski XInterface * pInterface = 0;
347809f4227SJim Jagielski (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
348809f4227SJim Jagielski ( pCppI->getBridge()->getCppEnv(),
349809f4227SJim Jagielski reinterpret_cast<void **>(&pInterface),
350809f4227SJim Jagielski pCppI->getOid().pData,
351809f4227SJim Jagielski reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
352809f4227SJim Jagielski
353809f4227SJim Jagielski if ( pInterface )
354809f4227SJim Jagielski {
355ecf1c5e9SJim Jagielski ::uno_any_construct( reinterpret_cast<uno_Any *>( gpreg[0] ),
356809f4227SJim Jagielski &pInterface, pTD, cpp_acquire );
357809f4227SJim Jagielski
358809f4227SJim Jagielski pInterface->release();
359809f4227SJim Jagielski TYPELIB_DANGER_RELEASE( pTD );
360809f4227SJim Jagielski
361809f4227SJim Jagielski reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0];
362809f4227SJim Jagielski eRet = typelib_TypeClass_ANY;
363809f4227SJim Jagielski break;
364809f4227SJim Jagielski }
365809f4227SJim Jagielski TYPELIB_DANGER_RELEASE( pTD );
366809f4227SJim Jagielski }
367809f4227SJim Jagielski } // else perform queryInterface()
368809f4227SJim Jagielski default:
369809f4227SJim Jagielski {
370809f4227SJim Jagielski typelib_InterfaceMethodTypeDescription *pMethodTD =
371809f4227SJim Jagielski reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
372809f4227SJim Jagielski
373809f4227SJim Jagielski eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
374809f4227SJim Jagielski pMethodTD->pReturnTypeRef,
375809f4227SJim Jagielski pMethodTD->nParams,
376809f4227SJim Jagielski pMethodTD->pParams,
377809f4227SJim Jagielski gpreg, fpreg, ovrflw, pRegisterReturn );
378809f4227SJim Jagielski }
379809f4227SJim Jagielski }
380809f4227SJim Jagielski break;
381809f4227SJim Jagielski }
382809f4227SJim Jagielski default:
383809f4227SJim Jagielski {
384809f4227SJim Jagielski throw RuntimeException( OUString::createFromAscii("no member description found!"),
385809f4227SJim Jagielski reinterpret_cast<XInterface *>( pCppI ) );
386809f4227SJim Jagielski // is here for dummy
387809f4227SJim Jagielski eRet = typelib_TypeClass_VOID;
388809f4227SJim Jagielski }
389809f4227SJim Jagielski }
390809f4227SJim Jagielski
391809f4227SJim Jagielski return eRet;
392809f4227SJim Jagielski }
393809f4227SJim Jagielski
394809f4227SJim Jagielski //==================================================================================================
privateSnippetExecutor(void)395ecf1c5e9SJim Jagielski extern "C" void privateSnippetExecutor( void )
396809f4227SJim Jagielski {
397809f4227SJim Jagielski asm volatile (
3983187fb04SJim Jagielski " .text\n"
3993187fb04SJim Jagielski " .align 2\n"
4003187fb04SJim Jagielski ".globl privateSnippetExecutor\n"
401809f4227SJim Jagielski " subq $160, %rsp\n"
402809f4227SJim Jagielski " movq %r10, -152(%rbp)\n" // Save (nVtableOffset << 32) + nFunctionIndex
403809f4227SJim Jagielski
404809f4227SJim Jagielski " movq %rdi, -112(%rbp)\n" // Save GP registers
405809f4227SJim Jagielski " movq %rsi, -104(%rbp)\n"
406809f4227SJim Jagielski " movq %rdx, -96(%rbp)\n"
407809f4227SJim Jagielski " movq %rcx, -88(%rbp)\n"
408809f4227SJim Jagielski " movq %r8 , -80(%rbp)\n"
409809f4227SJim Jagielski " movq %r9 , -72(%rbp)\n"
410809f4227SJim Jagielski
411809f4227SJim Jagielski " movsd %xmm0, -64(%rbp)\n" // Save FP registers
412809f4227SJim Jagielski " movsd %xmm1, -56(%rbp)\n"
413809f4227SJim Jagielski " movsd %xmm2, -48(%rbp)\n"
414809f4227SJim Jagielski " movsd %xmm3, -40(%rbp)\n"
415809f4227SJim Jagielski " movsd %xmm4, -32(%rbp)\n"
416809f4227SJim Jagielski " movsd %xmm5, -24(%rbp)\n"
417809f4227SJim Jagielski " movsd %xmm6, -16(%rbp)\n"
418809f4227SJim Jagielski " movsd %xmm7, -8(%rbp)\n"
419809f4227SJim Jagielski
420809f4227SJim Jagielski " leaq -144(%rbp), %r9\n" // 6th param: sal_uInt64* pRegisterReturn
421809f4227SJim Jagielski " leaq 16(%rbp), %r8\n" // 5rd param: void** ovrflw
422809f4227SJim Jagielski " leaq -64(%rbp), %rcx\n" // 4th param: void** fpreg
423809f4227SJim Jagielski " leaq -112(%rbp), %rdx\n" // 3rd param: void** gpreg
424809f4227SJim Jagielski " movl -148(%rbp), %esi\n" // 2nd param: sal_int32 nVtableOffset
425809f4227SJim Jagielski " movl -152(%rbp), %edi\n" // 1st param: sal_int32 nFunctionIndex
426809f4227SJim Jagielski
427809f4227SJim Jagielski " call _cpp_vtable_call\n"
428809f4227SJim Jagielski
429809f4227SJim Jagielski " cmp $10, %rax\n" // typelib_TypeClass_FLOAT
430809f4227SJim Jagielski " je .Lfloat\n"
431809f4227SJim Jagielski " cmp $11, %rax\n" // typelib_TypeClass_DOUBLE
432809f4227SJim Jagielski " je .Lfloat\n"
433809f4227SJim Jagielski
434809f4227SJim Jagielski " movq -144(%rbp), %rax\n" // Return value (int case)
435809f4227SJim Jagielski " movq -136(%rbp), %rdx\n" // Return value (int case)
436809f4227SJim Jagielski " movq -144(%rbp), %xmm0\n" // Return value (int case)
437809f4227SJim Jagielski " movq -136(%rbp), %xmm1\n" // Return value (int case)
438809f4227SJim Jagielski " jmp .Lfinish\n"
439809f4227SJim Jagielski ".Lfloat:\n"
440809f4227SJim Jagielski " movlpd -144(%rbp), %xmm0\n" // Return value (float/double case)
441809f4227SJim Jagielski ".Lfinish:\n"
442809f4227SJim Jagielski " addq $160, %rsp\n"
443809f4227SJim Jagielski );
444809f4227SJim Jagielski }
445809f4227SJim Jagielski const int codeSnippetSize = 24;
446809f4227SJim Jagielski
447809f4227SJim Jagielski // Generate a trampoline that redirects method calls to
448809f4227SJim Jagielski // privateSnippetExecutor().
449809f4227SJim Jagielski //
450809f4227SJim Jagielski // privateSnippetExecutor() saves all the registers that are used for
451809f4227SJim Jagielski // parameter passing on x86_64, and calls the cpp_vtable_call().
452809f4227SJim Jagielski // When it returns, privateSnippetExecutor() sets the return value.
453809f4227SJim Jagielski //
454809f4227SJim Jagielski // Note: The code snippet we build here must not create a stack frame,
455809f4227SJim Jagielski // otherwise the UNO exceptions stop working thanks to non-existing
456809f4227SJim Jagielski // unwinding info.
codeSnippet(unsigned char * code,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,bool bHasHiddenParam)457809f4227SJim Jagielski unsigned char * codeSnippet( unsigned char * code,
458809f4227SJim Jagielski sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
459809f4227SJim Jagielski bool bHasHiddenParam ) SAL_THROW( () )
460809f4227SJim Jagielski {
461809f4227SJim Jagielski sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>( nVtableOffset ) << 32 ) | static_cast<sal_uInt64>( nFunctionIndex );
462809f4227SJim Jagielski
463809f4227SJim Jagielski if ( bHasHiddenParam )
464809f4227SJim Jagielski nOffsetAndIndex |= 0x80000000;
465809f4227SJim Jagielski
466809f4227SJim Jagielski // movq $<nOffsetAndIndex>, %r10
467809f4227SJim Jagielski *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49;
468ecf1c5e9SJim Jagielski *reinterpret_cast<sal_uInt64 *>( code + 2 ) = nOffsetAndIndex;
469809f4227SJim Jagielski
470809f4227SJim Jagielski // movq $<address of the privateSnippetExecutor>, %r11
471809f4227SJim Jagielski *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49;
472ecf1c5e9SJim Jagielski *reinterpret_cast<sal_uInt64 *>( code + 12 ) = reinterpret_cast<sal_uInt64>( privateSnippetExecutor );
473809f4227SJim Jagielski
474809f4227SJim Jagielski // jmpq *%r11
475809f4227SJim Jagielski *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
476809f4227SJim Jagielski
477809f4227SJim Jagielski return code + codeSnippetSize;
478809f4227SJim Jagielski }
479809f4227SJim Jagielski
480809f4227SJim Jagielski //==================================================================================================
481809f4227SJim Jagielski struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
482809f4227SJim Jagielski
483809f4227SJim Jagielski bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)484809f4227SJim Jagielski bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
485809f4227SJim Jagielski {
486809f4227SJim Jagielski return static_cast< Slot * >(block) + 2;
487809f4227SJim Jagielski }
488809f4227SJim Jagielski
489809f4227SJim Jagielski //==================================================================================================
getBlockSize(sal_Int32 slotCount)490809f4227SJim Jagielski sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
491809f4227SJim Jagielski sal_Int32 slotCount)
492809f4227SJim Jagielski {
493809f4227SJim Jagielski return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
494809f4227SJim Jagielski }
495809f4227SJim Jagielski
496809f4227SJim Jagielski //==================================================================================================
497809f4227SJim Jagielski bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)498809f4227SJim Jagielski bridges::cpp_uno::shared::VtableFactory::initializeBlock(
499809f4227SJim Jagielski void * block, sal_Int32 slotCount)
500809f4227SJim Jagielski {
501809f4227SJim Jagielski Slot * slots = mapBlockToVtable(block);
502809f4227SJim Jagielski slots[-2].fn = 0;
503809f4227SJim Jagielski slots[-1].fn = 0;
504809f4227SJim Jagielski return slots + slotCount;
505809f4227SJim Jagielski }
506809f4227SJim Jagielski
507809f4227SJim Jagielski //==================================================================================================
508809f4227SJim Jagielski
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 nFunctionOffset,sal_Int32 functionCount,sal_Int32 nVtableOffset)509809f4227SJim Jagielski unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
510809f4227SJim Jagielski Slot ** slots, unsigned char * code, /*sal_PtrDiff writetoexecdiff,*/
511809f4227SJim Jagielski typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
512809f4227SJim Jagielski sal_Int32 functionCount, sal_Int32 nVtableOffset )
513809f4227SJim Jagielski {
514809f4227SJim Jagielski const sal_PtrDiff writetoexecdiff = 0;
515809f4227SJim Jagielski (*slots) -= functionCount;
516809f4227SJim Jagielski Slot * s = *slots;
517809f4227SJim Jagielski for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
518809f4227SJim Jagielski {
519809f4227SJim Jagielski typelib_TypeDescription * pTD = 0;
520809f4227SJim Jagielski
521809f4227SJim Jagielski TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
522809f4227SJim Jagielski OSL_ASSERT( pTD );
523809f4227SJim Jagielski
524809f4227SJim Jagielski if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
525809f4227SJim Jagielski {
526809f4227SJim Jagielski typelib_InterfaceAttributeTypeDescription *pAttrTD =
527809f4227SJim Jagielski reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
528809f4227SJim Jagielski
529809f4227SJim Jagielski // get method
530809f4227SJim Jagielski (s++)->fn = code + writetoexecdiff;
531809f4227SJim Jagielski code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
532809f4227SJim Jagielski x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
533809f4227SJim Jagielski
534809f4227SJim Jagielski if ( ! pAttrTD->bReadOnly )
535809f4227SJim Jagielski {
536809f4227SJim Jagielski // set method
537809f4227SJim Jagielski (s++)->fn = code + writetoexecdiff;
538809f4227SJim Jagielski code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
539809f4227SJim Jagielski }
540809f4227SJim Jagielski }
541809f4227SJim Jagielski else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
542809f4227SJim Jagielski {
543809f4227SJim Jagielski typelib_InterfaceMethodTypeDescription *pMethodTD =
544809f4227SJim Jagielski reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
545809f4227SJim Jagielski
546809f4227SJim Jagielski (s++)->fn = code + writetoexecdiff;
547809f4227SJim Jagielski code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
548809f4227SJim Jagielski x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
549809f4227SJim Jagielski }
550809f4227SJim Jagielski else
551809f4227SJim Jagielski OSL_ASSERT( false );
552809f4227SJim Jagielski
553809f4227SJim Jagielski TYPELIB_DANGER_RELEASE( pTD );
554809f4227SJim Jagielski }
555809f4227SJim Jagielski return code;
556809f4227SJim Jagielski }
557809f4227SJim Jagielski
558809f4227SJim Jagielski //==================================================================================================
flushCode(unsigned char const *,unsigned char const *)559809f4227SJim Jagielski void bridges::cpp_uno::shared::VtableFactory::flushCode(
560809f4227SJim Jagielski unsigned char const *, unsigned char const * )
561809f4227SJim Jagielski {
562809f4227SJim Jagielski }
563