xref: /trunk/main/bridges/source/cpp_uno/s5abi_macosx_x86-64/cpp2uno.cxx (revision 76a54f96102e7418655edaf8bd6c0402a622d359)
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