xref: /AOO42X/main/bridges/source/cpp_uno/s5abi_macosx_x86-64/cpp2uno.cxx (revision 3f67767c7707462d7983dbfa8c2155d6be2b0fd1)
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