1b682cb18SJim Jagielski /**************************************************************
2b682cb18SJim Jagielski *
3b682cb18SJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4b682cb18SJim Jagielski * or more contributor license agreements. See the NOTICE file
5b682cb18SJim Jagielski * distributed with this work for additional information
6b682cb18SJim Jagielski * regarding copyright ownership. The ASF licenses this file
7b682cb18SJim Jagielski * to you under the Apache License, Version 2.0 (the
8b682cb18SJim Jagielski * "License"); you may not use this file except in compliance
9b682cb18SJim Jagielski * with the License. You may obtain a copy of the License at
10b682cb18SJim Jagielski *
11b682cb18SJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12b682cb18SJim Jagielski *
13b682cb18SJim Jagielski * Unless required by applicable law or agreed to in writing,
14b682cb18SJim Jagielski * software distributed under the License is distributed on an
15b682cb18SJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b682cb18SJim Jagielski * KIND, either express or implied. See the License for the
17b682cb18SJim Jagielski * specific language governing permissions and limitations
18b682cb18SJim Jagielski * under the License.
19b682cb18SJim Jagielski *
20b682cb18SJim Jagielski *************************************************************/
21b682cb18SJim Jagielski
22b682cb18SJim Jagielski
23b682cb18SJim Jagielski
24b682cb18SJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25b682cb18SJim Jagielski #include "precompiled_bridges.hxx"
26b682cb18SJim Jagielski
27b682cb18SJim Jagielski #include <stdio.h>
28b682cb18SJim Jagielski #include <stdlib.h>
29b682cb18SJim Jagielski #include <hash_map>
30b682cb18SJim Jagielski
31b682cb18SJim Jagielski #include <rtl/alloc.h>
32b682cb18SJim Jagielski #include <osl/mutex.hxx>
33b682cb18SJim Jagielski
34b682cb18SJim Jagielski #include <com/sun/star/uno/genfunc.hxx>
35b682cb18SJim Jagielski #include "com/sun/star/uno/RuntimeException.hpp"
36b682cb18SJim Jagielski #include <uno/data.h>
37b682cb18SJim Jagielski #include <typelib/typedescription.hxx>
38b682cb18SJim Jagielski
39b682cb18SJim Jagielski #include "bridges/cpp_uno/shared/bridge.hxx"
40b682cb18SJim Jagielski #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
41b682cb18SJim Jagielski #include "bridges/cpp_uno/shared/types.hxx"
42b682cb18SJim Jagielski #include "bridges/cpp_uno/shared/vtablefactory.hxx"
43b682cb18SJim Jagielski
44b682cb18SJim Jagielski #include "abi.hxx"
45b682cb18SJim Jagielski #include "share.hxx"
46b682cb18SJim Jagielski
47b682cb18SJim Jagielski using namespace ::osl;
48b682cb18SJim Jagielski using namespace ::rtl;
49b682cb18SJim Jagielski using namespace ::com::sun::star::uno;
50b682cb18SJim Jagielski
51b682cb18SJim Jagielski //==================================================================================================
52b682cb18SJim Jagielski
53b682cb18SJim Jagielski // Perform the UNO call
54b682cb18SJim Jagielski //
55*76a54f96SJohn Bampton // We must convert the parameters stored in gpreg, fpreg and ovrflw to UNO
56b682cb18SJim Jagielski // arguments and call pThis->getUnoI()->pDispatcher.
57b682cb18SJim Jagielski //
58b682cb18SJim Jagielski // gpreg: [ret *], this, [gpr params]
59b682cb18SJim Jagielski // fpreg: [fpr params]
60b682cb18SJim Jagielski // ovrflw: [gpr or fpr params (properly aligned)]
61b682cb18SJim Jagielski //
62b682cb18SJim Jagielski // [ret *] is present when we are returning a structure bigger than 16 bytes
63b682cb18SJim Jagielski // Simple types are returned in rax, rdx (int), or xmm0, xmm1 (fp).
64b682cb18SJim 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)65b682cb18SJim Jagielski static typelib_TypeClass cpp2uno_call(
66b682cb18SJim Jagielski bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
67b682cb18SJim Jagielski const typelib_TypeDescription * pMemberTypeDescr,
68b682cb18SJim Jagielski typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
69b682cb18SJim Jagielski sal_Int32 nParams, typelib_MethodParameter * pParams,
70b682cb18SJim Jagielski void ** gpreg, void ** fpreg, void ** ovrflw,
71b682cb18SJim Jagielski sal_uInt64 * pRegisterReturn /* space for register return */ )
72b682cb18SJim Jagielski {
73b682cb18SJim Jagielski unsigned int nr_gpr = 0; //number of gpr registers used
74b682cb18SJim Jagielski unsigned int nr_fpr = 0; //number of fpr registers used
75b682cb18SJim Jagielski
76b682cb18SJim Jagielski // return
77b682cb18SJim Jagielski typelib_TypeDescription * pReturnTypeDescr = 0;
78b682cb18SJim Jagielski if (pReturnTypeRef)
79b682cb18SJim Jagielski TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
80b682cb18SJim Jagielski
81b682cb18SJim Jagielski void * pUnoReturn = 0;
82b682cb18SJim Jagielski void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
83b682cb18SJim Jagielski
84b682cb18SJim Jagielski if ( pReturnTypeDescr )
85b682cb18SJim Jagielski {
86b682cb18SJim Jagielski if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
87b682cb18SJim Jagielski {
88b682cb18SJim Jagielski pCppReturn = *gpreg++;
89b682cb18SJim Jagielski nr_gpr++;
90b682cb18SJim Jagielski
91b682cb18SJim Jagielski pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
92b682cb18SJim Jagielski ? alloca( pReturnTypeDescr->nSize )
93b682cb18SJim Jagielski : pCppReturn ); // direct way
94b682cb18SJim Jagielski }
95b682cb18SJim Jagielski else
96b682cb18SJim Jagielski pUnoReturn = pRegisterReturn; // direct way for simple types
97b682cb18SJim Jagielski }
98b682cb18SJim Jagielski
99b682cb18SJim Jagielski // pop this
100b682cb18SJim Jagielski gpreg++;
101b682cb18SJim Jagielski nr_gpr++;
102b682cb18SJim Jagielski
103b682cb18SJim Jagielski // stack space
104b682cb18SJim Jagielski // parameters
105dfec5905SJim Jagielski void ** pUnoArgs = reinterpret_cast<void **>(alloca( 4 * sizeof(void *) * nParams ));
106b682cb18SJim Jagielski void ** pCppArgs = pUnoArgs + nParams;
107b682cb18SJim Jagielski // indizes of values this have to be converted (interface conversion cpp<=>uno)
108b682cb18SJim Jagielski sal_Int32 * pTempIndizes = reinterpret_cast<sal_Int32 *>(pUnoArgs + (2 * nParams));
109b682cb18SJim Jagielski // type descriptions for reconversions
110b682cb18SJim Jagielski typelib_TypeDescription ** ppTempParamTypeDescr = reinterpret_cast<typelib_TypeDescription **>(pUnoArgs + (3 * nParams));
111b682cb18SJim Jagielski
112b682cb18SJim Jagielski sal_Int32 nTempIndizes = 0;
113b682cb18SJim Jagielski
114b682cb18SJim Jagielski for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
115b682cb18SJim Jagielski {
116b682cb18SJim Jagielski const typelib_MethodParameter & rParam = pParams[nPos];
117b682cb18SJim Jagielski
118b682cb18SJim Jagielski int nUsedGPR = 0;
119b682cb18SJim Jagielski int nUsedSSE = 0;
120b682cb18SJim Jagielski bool bFitsRegisters = x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE );
121b682cb18SJim Jagielski if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
122b682cb18SJim Jagielski {
123b682cb18SJim Jagielski // Simple types must fit exactly one register on x86_64
124b682cb18SJim Jagielski OSL_ASSERT( bFitsRegisters && ( ( nUsedSSE == 1 && nUsedGPR == 0 ) || ( nUsedSSE == 0 && nUsedGPR == 1 ) ) );
125b682cb18SJim Jagielski
126b682cb18SJim Jagielski if ( nUsedSSE == 1 )
127b682cb18SJim Jagielski {
128b682cb18SJim Jagielski if ( nr_fpr < x86_64::MAX_SSE_REGS )
129b682cb18SJim Jagielski {
130b682cb18SJim Jagielski pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
131b682cb18SJim Jagielski nr_fpr++;
132b682cb18SJim Jagielski }
133b682cb18SJim Jagielski else
134b682cb18SJim Jagielski pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
135b682cb18SJim Jagielski }
136b682cb18SJim Jagielski else if ( nUsedGPR == 1 )
137b682cb18SJim Jagielski {
138b682cb18SJim Jagielski if ( nr_gpr < x86_64::MAX_GPR_REGS )
139b682cb18SJim Jagielski {
140b682cb18SJim Jagielski pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
141b682cb18SJim Jagielski nr_gpr++;
142b682cb18SJim Jagielski }
143b682cb18SJim Jagielski else
144b682cb18SJim Jagielski pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
145b682cb18SJim Jagielski }
146b682cb18SJim Jagielski }
147b682cb18SJim Jagielski else // struct <= 16 bytes || ptr to complex value || ref
148b682cb18SJim Jagielski {
149b682cb18SJim Jagielski typelib_TypeDescription * pParamTypeDescr = 0;
150b682cb18SJim Jagielski TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
151b682cb18SJim Jagielski
152b682cb18SJim Jagielski void *pCppStack;
153b682cb18SJim Jagielski if ( nr_gpr < x86_64::MAX_GPR_REGS )
154b682cb18SJim Jagielski {
155b682cb18SJim Jagielski pCppArgs[nPos] = pCppStack = *gpreg++;
156b682cb18SJim Jagielski nr_gpr++;
157b682cb18SJim Jagielski }
158b682cb18SJim Jagielski else
159b682cb18SJim Jagielski pCppArgs[nPos] = pCppStack = *ovrflw++;
160b682cb18SJim Jagielski
161b682cb18SJim Jagielski if (! rParam.bIn) // is pure out
162b682cb18SJim Jagielski {
163b682cb18SJim Jagielski // uno out is unconstructed mem!
164b682cb18SJim Jagielski pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
165b682cb18SJim Jagielski pTempIndizes[nTempIndizes] = nPos;
166b682cb18SJim Jagielski // will be released at reconversion
167b682cb18SJim Jagielski ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
168b682cb18SJim Jagielski }
169b682cb18SJim Jagielski else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
170b682cb18SJim Jagielski {
171b682cb18SJim Jagielski uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
172b682cb18SJim Jagielski pCppStack, pParamTypeDescr,
173b682cb18SJim Jagielski pThis->getBridge()->getCpp2Uno() );
174b682cb18SJim Jagielski pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
175b682cb18SJim Jagielski // will be released at reconversion
176b682cb18SJim Jagielski ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
177b682cb18SJim Jagielski }
178b682cb18SJim Jagielski else // direct way
179b682cb18SJim Jagielski {
180b682cb18SJim Jagielski pUnoArgs[nPos] = pCppStack;
181b682cb18SJim Jagielski // no longer needed
182b682cb18SJim Jagielski TYPELIB_DANGER_RELEASE( pParamTypeDescr );
183b682cb18SJim Jagielski }
184b682cb18SJim Jagielski }
185b682cb18SJim Jagielski }
186b682cb18SJim Jagielski
187b682cb18SJim Jagielski // ExceptionHolder
188b682cb18SJim Jagielski uno_Any aUnoExc; // Any will be constructed by callee
189b682cb18SJim Jagielski uno_Any * pUnoExc = &aUnoExc;
190b682cb18SJim Jagielski
191b682cb18SJim Jagielski // invoke uno dispatch call
192b682cb18SJim Jagielski (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
193b682cb18SJim Jagielski
194b682cb18SJim Jagielski // in case an exception occurred...
195b682cb18SJim Jagielski if ( pUnoExc )
196b682cb18SJim Jagielski {
197b682cb18SJim Jagielski // destruct temporary in/inout params
198b682cb18SJim Jagielski for ( ; nTempIndizes--; )
199b682cb18SJim Jagielski {
200b682cb18SJim Jagielski sal_Int32 nIndex = pTempIndizes[nTempIndizes];
201b682cb18SJim Jagielski
202b682cb18SJim Jagielski if (pParams[nIndex].bIn) // is in/inout => was constructed
203b682cb18SJim Jagielski uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
204b682cb18SJim Jagielski TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
205b682cb18SJim Jagielski }
206b682cb18SJim Jagielski if (pReturnTypeDescr)
207b682cb18SJim Jagielski TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
208b682cb18SJim Jagielski
209b682cb18SJim Jagielski CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
210b682cb18SJim Jagielski // is here for dummy
211b682cb18SJim Jagielski return typelib_TypeClass_VOID;
212b682cb18SJim Jagielski }
213b682cb18SJim Jagielski else // else no exception occurred...
214b682cb18SJim Jagielski {
215b682cb18SJim Jagielski // temporary params
216b682cb18SJim Jagielski for ( ; nTempIndizes--; )
217b682cb18SJim Jagielski {
218b682cb18SJim Jagielski sal_Int32 nIndex = pTempIndizes[nTempIndizes];
219b682cb18SJim Jagielski typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
220b682cb18SJim Jagielski
221b682cb18SJim Jagielski if ( pParams[nIndex].bOut ) // inout/out
222b682cb18SJim Jagielski {
223b682cb18SJim Jagielski // convert and assign
224b682cb18SJim Jagielski uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
225b682cb18SJim Jagielski uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
226b682cb18SJim Jagielski pThis->getBridge()->getUno2Cpp() );
227b682cb18SJim Jagielski }
228b682cb18SJim Jagielski // destroy temp uno param
229b682cb18SJim Jagielski uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
230b682cb18SJim Jagielski
231b682cb18SJim Jagielski TYPELIB_DANGER_RELEASE( pParamTypeDescr );
232b682cb18SJim Jagielski }
233b682cb18SJim Jagielski // return
234b682cb18SJim Jagielski if ( pCppReturn ) // has complex return
235b682cb18SJim Jagielski {
236b682cb18SJim Jagielski if ( pUnoReturn != pCppReturn ) // needs reconversion
237b682cb18SJim Jagielski {
238b682cb18SJim Jagielski uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
239b682cb18SJim Jagielski pThis->getBridge()->getUno2Cpp() );
240b682cb18SJim Jagielski // destroy temp uno return
241b682cb18SJim Jagielski uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
242b682cb18SJim Jagielski }
243b682cb18SJim Jagielski // complex return ptr is set to return reg
244b682cb18SJim Jagielski *reinterpret_cast<void **>(pRegisterReturn) = pCppReturn;
245b682cb18SJim Jagielski }
246b682cb18SJim Jagielski if ( pReturnTypeDescr )
247b682cb18SJim Jagielski {
248b682cb18SJim Jagielski typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
249b682cb18SJim Jagielski TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
250b682cb18SJim Jagielski return eRet;
251b682cb18SJim Jagielski }
252b682cb18SJim Jagielski else
253b682cb18SJim Jagielski return typelib_TypeClass_VOID;
254b682cb18SJim Jagielski }
255b682cb18SJim Jagielski }
256b682cb18SJim Jagielski
257b682cb18SJim Jagielski
258b682cb18SJim Jagielski //==================================================================================================
cpp_vtable_call(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** gpreg,void ** fpreg,void ** ovrflw,sal_uInt64 * pRegisterReturn)259b682cb18SJim Jagielski extern "C" typelib_TypeClass cpp_vtable_call(
260b682cb18SJim Jagielski sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
261b682cb18SJim Jagielski void ** gpreg, void ** fpreg, void ** ovrflw,
262b682cb18SJim Jagielski sal_uInt64 * pRegisterReturn /* space for register return */ )
263b682cb18SJim Jagielski {
264b682cb18SJim Jagielski // gpreg: [ret *], this, [other gpr params]
265b682cb18SJim Jagielski // fpreg: [fpr params]
266b682cb18SJim Jagielski // ovrflw: [gpr or fpr params (properly aligned)]
267b682cb18SJim Jagielski void * pThis;
268b682cb18SJim Jagielski if ( nFunctionIndex & 0x80000000 )
269b682cb18SJim Jagielski {
270b682cb18SJim Jagielski nFunctionIndex &= 0x7fffffff;
271b682cb18SJim Jagielski pThis = gpreg[1];
272b682cb18SJim Jagielski }
273b682cb18SJim Jagielski else
274b682cb18SJim Jagielski {
275b682cb18SJim Jagielski pThis = gpreg[0];
276b682cb18SJim Jagielski }
277b682cb18SJim Jagielski pThis = static_cast<char *>( pThis ) - nVtableOffset;
278b682cb18SJim Jagielski
279b682cb18SJim Jagielski bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
280b682cb18SJim Jagielski bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
281b682cb18SJim Jagielski
282b682cb18SJim Jagielski typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
283b682cb18SJim Jagielski
284b682cb18SJim Jagielski OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
285b682cb18SJim Jagielski if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
286b682cb18SJim Jagielski {
287b682cb18SJim Jagielski throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
288b682cb18SJim Jagielski reinterpret_cast<XInterface *>( pCppI ) );
289b682cb18SJim Jagielski }
290b682cb18SJim Jagielski
291b682cb18SJim Jagielski // determine called method
292b682cb18SJim Jagielski sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
293b682cb18SJim Jagielski OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
294b682cb18SJim Jagielski
295b682cb18SJim Jagielski TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
296b682cb18SJim Jagielski
297b682cb18SJim Jagielski typelib_TypeClass eRet;
298b682cb18SJim Jagielski switch ( aMemberDescr.get()->eTypeClass )
299b682cb18SJim Jagielski {
300b682cb18SJim Jagielski case typelib_TypeClass_INTERFACE_ATTRIBUTE:
301b682cb18SJim Jagielski {
302b682cb18SJim Jagielski typelib_TypeDescriptionReference *pAttrTypeRef =
303b682cb18SJim Jagielski reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
304b682cb18SJim Jagielski
305b682cb18SJim Jagielski if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
306b682cb18SJim Jagielski {
307b682cb18SJim Jagielski // is GET method
308b682cb18SJim Jagielski eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
309b682cb18SJim Jagielski 0, 0, // no params
310b682cb18SJim Jagielski gpreg, fpreg, ovrflw, pRegisterReturn );
311b682cb18SJim Jagielski }
312b682cb18SJim Jagielski else
313b682cb18SJim Jagielski {
314b682cb18SJim Jagielski // is SET method
315b682cb18SJim Jagielski typelib_MethodParameter aParam;
316b682cb18SJim Jagielski aParam.pTypeRef = pAttrTypeRef;
317b682cb18SJim Jagielski aParam.bIn = sal_True;
318b682cb18SJim Jagielski aParam.bOut = sal_False;
319b682cb18SJim Jagielski
320b682cb18SJim Jagielski eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
321b682cb18SJim Jagielski 0, // indicates void return
322b682cb18SJim Jagielski 1, &aParam,
323b682cb18SJim Jagielski gpreg, fpreg, ovrflw, pRegisterReturn );
324b682cb18SJim Jagielski }
325b682cb18SJim Jagielski break;
326b682cb18SJim Jagielski }
327b682cb18SJim Jagielski case typelib_TypeClass_INTERFACE_METHOD:
328b682cb18SJim Jagielski {
329b682cb18SJim Jagielski // is METHOD
330b682cb18SJim Jagielski switch ( nFunctionIndex )
331b682cb18SJim Jagielski {
332b682cb18SJim Jagielski case 1: // acquire()
333b682cb18SJim Jagielski pCppI->acquireProxy(); // non virtual call!
334b682cb18SJim Jagielski eRet = typelib_TypeClass_VOID;
335b682cb18SJim Jagielski break;
336b682cb18SJim Jagielski case 2: // release()
337b682cb18SJim Jagielski pCppI->releaseProxy(); // non virtual call!
338b682cb18SJim Jagielski eRet = typelib_TypeClass_VOID;
339b682cb18SJim Jagielski break;
340b682cb18SJim Jagielski case 0: // queryInterface() opt
341b682cb18SJim Jagielski {
342b682cb18SJim Jagielski typelib_TypeDescription * pTD = 0;
343dfec5905SJim Jagielski TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[2] )->getTypeLibType() );
344b682cb18SJim Jagielski if ( pTD )
345b682cb18SJim Jagielski {
346b682cb18SJim Jagielski XInterface * pInterface = 0;
347b682cb18SJim Jagielski (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
348b682cb18SJim Jagielski ( pCppI->getBridge()->getCppEnv(),
349b682cb18SJim Jagielski reinterpret_cast<void **>(&pInterface),
350b682cb18SJim Jagielski pCppI->getOid().pData,
351b682cb18SJim Jagielski reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
352b682cb18SJim Jagielski
353b682cb18SJim Jagielski if ( pInterface )
354b682cb18SJim Jagielski {
355dfec5905SJim Jagielski ::uno_any_construct( reinterpret_cast<uno_Any *>( gpreg[0] ),
356b682cb18SJim Jagielski &pInterface, pTD, cpp_acquire );
357b682cb18SJim Jagielski
358b682cb18SJim Jagielski pInterface->release();
359b682cb18SJim Jagielski TYPELIB_DANGER_RELEASE( pTD );
360b682cb18SJim Jagielski
361b682cb18SJim Jagielski reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0];
362b682cb18SJim Jagielski eRet = typelib_TypeClass_ANY;
363b682cb18SJim Jagielski break;
364b682cb18SJim Jagielski }
365b682cb18SJim Jagielski TYPELIB_DANGER_RELEASE( pTD );
366b682cb18SJim Jagielski }
367b682cb18SJim Jagielski } // else perform queryInterface()
368b682cb18SJim Jagielski default:
369b682cb18SJim Jagielski {
370b682cb18SJim Jagielski typelib_InterfaceMethodTypeDescription *pMethodTD =
371b682cb18SJim Jagielski reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
372b682cb18SJim Jagielski
373b682cb18SJim Jagielski eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
374b682cb18SJim Jagielski pMethodTD->pReturnTypeRef,
375b682cb18SJim Jagielski pMethodTD->nParams,
376b682cb18SJim Jagielski pMethodTD->pParams,
377b682cb18SJim Jagielski gpreg, fpreg, ovrflw, pRegisterReturn );
378b682cb18SJim Jagielski }
379b682cb18SJim Jagielski }
380b682cb18SJim Jagielski break;
381b682cb18SJim Jagielski }
382b682cb18SJim Jagielski default:
383b682cb18SJim Jagielski {
384b682cb18SJim Jagielski throw RuntimeException( OUString::createFromAscii("no member description found!"),
385b682cb18SJim Jagielski reinterpret_cast<XInterface *>( pCppI ) );
386b682cb18SJim Jagielski // is here for dummy
387b682cb18SJim Jagielski eRet = typelib_TypeClass_VOID;
388b682cb18SJim Jagielski }
389b682cb18SJim Jagielski }
390b682cb18SJim Jagielski
391b682cb18SJim Jagielski return eRet;
392b682cb18SJim Jagielski }
393b682cb18SJim Jagielski
394b682cb18SJim Jagielski //==================================================================================================
privateSnippetExecutor(void)395dfec5905SJim Jagielski extern "C" void privateSnippetExecutor( void )
396b682cb18SJim Jagielski {
397b682cb18SJim Jagielski asm volatile (
39826c81592SJim Jagielski " .text\n"
39926c81592SJim Jagielski " .align 2\n"
40026c81592SJim Jagielski ".globl privateSnippetExecutor\n"
401b682cb18SJim Jagielski " subq $160, %rsp\n"
402b682cb18SJim Jagielski " movq %r10, -152(%rbp)\n" // Save (nVtableOffset << 32) + nFunctionIndex
403b682cb18SJim Jagielski
404b682cb18SJim Jagielski " movq %rdi, -112(%rbp)\n" // Save GP registers
405b682cb18SJim Jagielski " movq %rsi, -104(%rbp)\n"
406b682cb18SJim Jagielski " movq %rdx, -96(%rbp)\n"
407b682cb18SJim Jagielski " movq %rcx, -88(%rbp)\n"
408b682cb18SJim Jagielski " movq %r8 , -80(%rbp)\n"
409b682cb18SJim Jagielski " movq %r9 , -72(%rbp)\n"
410b682cb18SJim Jagielski
411b682cb18SJim Jagielski " movsd %xmm0, -64(%rbp)\n" // Save FP registers
412b682cb18SJim Jagielski " movsd %xmm1, -56(%rbp)\n"
413b682cb18SJim Jagielski " movsd %xmm2, -48(%rbp)\n"
414b682cb18SJim Jagielski " movsd %xmm3, -40(%rbp)\n"
415b682cb18SJim Jagielski " movsd %xmm4, -32(%rbp)\n"
416b682cb18SJim Jagielski " movsd %xmm5, -24(%rbp)\n"
417b682cb18SJim Jagielski " movsd %xmm6, -16(%rbp)\n"
418b682cb18SJim Jagielski " movsd %xmm7, -8(%rbp)\n"
419b682cb18SJim Jagielski
420b682cb18SJim Jagielski " leaq -144(%rbp), %r9\n" // 6th param: sal_uInt64* pRegisterReturn
421b682cb18SJim Jagielski " leaq 16(%rbp), %r8\n" // 5rd param: void** ovrflw
422b682cb18SJim Jagielski " leaq -64(%rbp), %rcx\n" // 4th param: void** fpreg
423b682cb18SJim Jagielski " leaq -112(%rbp), %rdx\n" // 3rd param: void** gpreg
424b682cb18SJim Jagielski " movl -148(%rbp), %esi\n" // 2nd param: sal_int32 nVtableOffset
425b682cb18SJim Jagielski " movl -152(%rbp), %edi\n" // 1st param: sal_int32 nFunctionIndex
426b682cb18SJim Jagielski
427b682cb18SJim Jagielski " call _cpp_vtable_call\n"
428b682cb18SJim Jagielski
429b682cb18SJim Jagielski " cmp $10, %rax\n" // typelib_TypeClass_FLOAT
430b682cb18SJim Jagielski " je .Lfloat\n"
431b682cb18SJim Jagielski " cmp $11, %rax\n" // typelib_TypeClass_DOUBLE
432b682cb18SJim Jagielski " je .Lfloat\n"
433b682cb18SJim Jagielski
434b682cb18SJim Jagielski " movq -144(%rbp), %rax\n" // Return value (int case)
435b682cb18SJim Jagielski " movq -136(%rbp), %rdx\n" // Return value (int case)
436b682cb18SJim Jagielski " movq -144(%rbp), %xmm0\n" // Return value (int case)
437b682cb18SJim Jagielski " movq -136(%rbp), %xmm1\n" // Return value (int case)
438b682cb18SJim Jagielski " jmp .Lfinish\n"
439b682cb18SJim Jagielski ".Lfloat:\n"
440b682cb18SJim Jagielski " movlpd -144(%rbp), %xmm0\n" // Return value (float/double case)
441b682cb18SJim Jagielski ".Lfinish:\n"
442b682cb18SJim Jagielski " addq $160, %rsp\n"
443b682cb18SJim Jagielski );
444b682cb18SJim Jagielski }
445b682cb18SJim Jagielski const int codeSnippetSize = 24;
446b682cb18SJim Jagielski
447b682cb18SJim Jagielski // Generate a trampoline that redirects method calls to
448b682cb18SJim Jagielski // privateSnippetExecutor().
449b682cb18SJim Jagielski //
450b682cb18SJim Jagielski // privateSnippetExecutor() saves all the registers that are used for
451b682cb18SJim Jagielski // parameter passing on x86_64, and calls the cpp_vtable_call().
452b682cb18SJim Jagielski // When it returns, privateSnippetExecutor() sets the return value.
453b682cb18SJim Jagielski //
454b682cb18SJim Jagielski // Note: The code snippet we build here must not create a stack frame,
455b682cb18SJim Jagielski // otherwise the UNO exceptions stop working thanks to non-existing
456b682cb18SJim Jagielski // unwinding info.
codeSnippet(unsigned char * code,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,bool bHasHiddenParam)457b682cb18SJim Jagielski unsigned char * codeSnippet( unsigned char * code,
458b682cb18SJim Jagielski sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
459b682cb18SJim Jagielski bool bHasHiddenParam ) SAL_THROW( () )
460b682cb18SJim Jagielski {
461b682cb18SJim Jagielski sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>( nVtableOffset ) << 32 ) | static_cast<sal_uInt64>( nFunctionIndex );
462b682cb18SJim Jagielski
463b682cb18SJim Jagielski if ( bHasHiddenParam )
464b682cb18SJim Jagielski nOffsetAndIndex |= 0x80000000;
465b682cb18SJim Jagielski
466b682cb18SJim Jagielski // movq $<nOffsetAndIndex>, %r10
467b682cb18SJim Jagielski *reinterpret_cast<sal_uInt16 *>( code ) = 0xba49;
468dfec5905SJim Jagielski *reinterpret_cast<sal_uInt64 *>( code + 2 ) = nOffsetAndIndex;
469b682cb18SJim Jagielski
470b682cb18SJim Jagielski // movq $<address of the privateSnippetExecutor>, %r11
471b682cb18SJim Jagielski *reinterpret_cast<sal_uInt16 *>( code + 10 ) = 0xbb49;
472dfec5905SJim Jagielski *reinterpret_cast<sal_uInt64 *>( code + 12 ) = reinterpret_cast<sal_uInt64>( privateSnippetExecutor );
473b682cb18SJim Jagielski
474b682cb18SJim Jagielski // jmpq *%r11
475b682cb18SJim Jagielski *reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
476b682cb18SJim Jagielski
477b682cb18SJim Jagielski return code + codeSnippetSize;
478b682cb18SJim Jagielski }
479b682cb18SJim Jagielski
480b682cb18SJim Jagielski //==================================================================================================
481b682cb18SJim Jagielski struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
482b682cb18SJim Jagielski
483b682cb18SJim Jagielski bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)484b682cb18SJim Jagielski bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
485b682cb18SJim Jagielski {
486b682cb18SJim Jagielski return static_cast< Slot * >(block) + 2;
487b682cb18SJim Jagielski }
488b682cb18SJim Jagielski
489b682cb18SJim Jagielski //==================================================================================================
getBlockSize(sal_Int32 slotCount)490b682cb18SJim Jagielski sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
491b682cb18SJim Jagielski sal_Int32 slotCount)
492b682cb18SJim Jagielski {
493b682cb18SJim Jagielski return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
494b682cb18SJim Jagielski }
495b682cb18SJim Jagielski
496b682cb18SJim Jagielski //==================================================================================================
497b682cb18SJim Jagielski bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)498b682cb18SJim Jagielski bridges::cpp_uno::shared::VtableFactory::initializeBlock(
499b682cb18SJim Jagielski void * block, sal_Int32 slotCount)
500b682cb18SJim Jagielski {
501b682cb18SJim Jagielski Slot * slots = mapBlockToVtable(block);
502b682cb18SJim Jagielski slots[-2].fn = 0;
503b682cb18SJim Jagielski slots[-1].fn = 0;
504b682cb18SJim Jagielski return slots + slotCount;
505b682cb18SJim Jagielski }
506b682cb18SJim Jagielski
507b682cb18SJim Jagielski //==================================================================================================
508b682cb18SJim Jagielski
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 nFunctionOffset,sal_Int32 functionCount,sal_Int32 nVtableOffset)509b682cb18SJim Jagielski unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
510b682cb18SJim Jagielski Slot ** slots, unsigned char * code, /*sal_PtrDiff writetoexecdiff,*/
511b682cb18SJim Jagielski typelib_InterfaceTypeDescription const * type, sal_Int32 nFunctionOffset,
512b682cb18SJim Jagielski sal_Int32 functionCount, sal_Int32 nVtableOffset )
513b682cb18SJim Jagielski {
514b682cb18SJim Jagielski const sal_PtrDiff writetoexecdiff = 0;
515b682cb18SJim Jagielski (*slots) -= functionCount;
516b682cb18SJim Jagielski Slot * s = *slots;
517b682cb18SJim Jagielski for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
518b682cb18SJim Jagielski {
519b682cb18SJim Jagielski typelib_TypeDescription * pTD = 0;
520b682cb18SJim Jagielski
521b682cb18SJim Jagielski TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
522b682cb18SJim Jagielski OSL_ASSERT( pTD );
523b682cb18SJim Jagielski
524b682cb18SJim Jagielski if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
525b682cb18SJim Jagielski {
526b682cb18SJim Jagielski typelib_InterfaceAttributeTypeDescription *pAttrTD =
527b682cb18SJim Jagielski reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
528b682cb18SJim Jagielski
529b682cb18SJim Jagielski // get method
530b682cb18SJim Jagielski (s++)->fn = code + writetoexecdiff;
531b682cb18SJim Jagielski code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
532b682cb18SJim Jagielski x86_64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
533b682cb18SJim Jagielski
534b682cb18SJim Jagielski if ( ! pAttrTD->bReadOnly )
535b682cb18SJim Jagielski {
536b682cb18SJim Jagielski // set method
537b682cb18SJim Jagielski (s++)->fn = code + writetoexecdiff;
538b682cb18SJim Jagielski code = codeSnippet( code, nFunctionOffset++, nVtableOffset, false );
539b682cb18SJim Jagielski }
540b682cb18SJim Jagielski }
541b682cb18SJim Jagielski else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
542b682cb18SJim Jagielski {
543b682cb18SJim Jagielski typelib_InterfaceMethodTypeDescription *pMethodTD =
544b682cb18SJim Jagielski reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
545b682cb18SJim Jagielski
546b682cb18SJim Jagielski (s++)->fn = code + writetoexecdiff;
547b682cb18SJim Jagielski code = codeSnippet( code, nFunctionOffset++, nVtableOffset,
548b682cb18SJim Jagielski x86_64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
549b682cb18SJim Jagielski }
550b682cb18SJim Jagielski else
551b682cb18SJim Jagielski OSL_ASSERT( false );
552b682cb18SJim Jagielski
553b682cb18SJim Jagielski TYPELIB_DANGER_RELEASE( pTD );
554b682cb18SJim Jagielski }
555b682cb18SJim Jagielski return code;
556b682cb18SJim Jagielski }
557b682cb18SJim Jagielski
558b682cb18SJim Jagielski //==================================================================================================
flushCode(unsigned char const *,unsigned char const *)559b682cb18SJim Jagielski void bridges::cpp_uno::shared::VtableFactory::flushCode(
560b682cb18SJim Jagielski unsigned char const *, unsigned char const * )
561b682cb18SJim Jagielski {
562b682cb18SJim Jagielski }
563