1*9c15e1abSPedro Giffuni /*
2*9c15e1abSPedro Giffuni * Licensed to the Apache Software Foundation (ASF) under one
3*9c15e1abSPedro Giffuni * or more contributor license agreements. See the NOTICE file
4*9c15e1abSPedro Giffuni * distributed with this work for additional information
5*9c15e1abSPedro Giffuni * regarding copyright ownership. The ASF licenses this file
6*9c15e1abSPedro Giffuni * to you under the Apache License, Version 2.0 (the
7*9c15e1abSPedro Giffuni * "License"); you may not use this file except in compliance
8*9c15e1abSPedro Giffuni * with the License. You may obtain a copy of the License at
9*9c15e1abSPedro Giffuni *
10*9c15e1abSPedro Giffuni * http://www.apache.org/licenses/LICENSE-2.0
11*9c15e1abSPedro Giffuni *
12*9c15e1abSPedro Giffuni * Unless required by applicable law or agreed to in writing,
13*9c15e1abSPedro Giffuni * software distributed under the License is distributed on an
14*9c15e1abSPedro Giffuni * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*9c15e1abSPedro Giffuni * KIND, either express or implied. See the License for the
16*9c15e1abSPedro Giffuni * specific language governing permissions and limitations
17*9c15e1abSPedro Giffuni * under the License.
18*9c15e1abSPedro Giffuni */
19*9c15e1abSPedro Giffuni
20*9c15e1abSPedro Giffuni
21*9c15e1abSPedro Giffuni // MARKER(update_precomp.py): autogen include statement, do not remove
22*9c15e1abSPedro Giffuni #include "precompiled_bridges.hxx"
23*9c15e1abSPedro Giffuni
24*9c15e1abSPedro Giffuni #include <stdio.h>
25*9c15e1abSPedro Giffuni #include <stdlib.h>
26*9c15e1abSPedro Giffuni #include <hash_map>
27*9c15e1abSPedro Giffuni
28*9c15e1abSPedro Giffuni #include <rtl/alloc.h>
29*9c15e1abSPedro Giffuni #include <osl/mutex.hxx>
30*9c15e1abSPedro Giffuni
31*9c15e1abSPedro Giffuni #include <com/sun/star/uno/genfunc.hxx>
32*9c15e1abSPedro Giffuni #include "com/sun/star/uno/RuntimeException.hpp"
33*9c15e1abSPedro Giffuni #include <uno/data.h>
34*9c15e1abSPedro Giffuni #include <typelib/typedescription.hxx>
35*9c15e1abSPedro Giffuni
36*9c15e1abSPedro Giffuni #include "bridges/cpp_uno/shared/bridge.hxx"
37*9c15e1abSPedro Giffuni #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
38*9c15e1abSPedro Giffuni #include "bridges/cpp_uno/shared/types.hxx"
39*9c15e1abSPedro Giffuni #include "bridges/cpp_uno/shared/vtablefactory.hxx"
40*9c15e1abSPedro Giffuni
41*9c15e1abSPedro Giffuni #include "abi.hxx"
42*9c15e1abSPedro Giffuni #include "share.hxx"
43*9c15e1abSPedro Giffuni
44*9c15e1abSPedro Giffuni using namespace ::osl;
45*9c15e1abSPedro Giffuni using namespace ::rtl;
46*9c15e1abSPedro Giffuni using namespace ::com::sun::star::uno;
47*9c15e1abSPedro Giffuni
48*9c15e1abSPedro Giffuni //==================================================================================================
49*9c15e1abSPedro Giffuni
50*9c15e1abSPedro Giffuni // Perform the UNO call
51*9c15e1abSPedro Giffuni //
52*9c15e1abSPedro Giffuni // We must convert the parameters stored in gpreg, fpreg and ovrflw to UNO
53*9c15e1abSPedro Giffuni // arguments and call pThis->getUnoI()->pDispatcher.
54*9c15e1abSPedro Giffuni //
55*9c15e1abSPedro Giffuni // gpreg: this, [gpr params x0..x7] (the indirect-result ptr is x8, separate)
56*9c15e1abSPedro Giffuni // fpreg: [fpr params d0..d7]
57*9c15e1abSPedro Giffuni // ovrflw: [gpr or fpr params (properly aligned)]
58*9c15e1abSPedro Giffuni //
59*9c15e1abSPedro Giffuni // On AArch64 a structure bigger than 16 bytes is returned via the buffer
60*9c15e1abSPedro Giffuni // addressed by x8 (pIndirectReturn); 'this' is always x0 = gpreg[0].
61*9c15e1abSPedro Giffuni // Simple types are returned in x0,x1 (int) or d0,d1 (fp); HFAs in d0..d3;
62*9c15e1abSPedro Giffuni // non-HFA structures <= 16 bytes in x0,x1.
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,unsigned char * ovrflw,void * pIndirectReturn,sal_uInt64 * pRegisterReturn)63*9c15e1abSPedro Giffuni static typelib_TypeClass cpp2uno_call(
64*9c15e1abSPedro Giffuni bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
65*9c15e1abSPedro Giffuni const typelib_TypeDescription * pMemberTypeDescr,
66*9c15e1abSPedro Giffuni typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
67*9c15e1abSPedro Giffuni sal_Int32 nParams, typelib_MethodParameter * pParams,
68*9c15e1abSPedro Giffuni void ** gpreg, void ** fpreg, unsigned char * ovrflw,
69*9c15e1abSPedro Giffuni void * pIndirectReturn, // AArch64 x8 indirect-result pointer (0 if none)
70*9c15e1abSPedro Giffuni sal_uInt64 * pRegisterReturn /* space for register return */ )
71*9c15e1abSPedro Giffuni {
72*9c15e1abSPedro Giffuni unsigned int nr_gpr = 0; //number of gpr registers used
73*9c15e1abSPedro Giffuni unsigned int nr_fpr = 0; //number of fpr registers used
74*9c15e1abSPedro Giffuni sal_uInt32 stackOffset = 0;
75*9c15e1abSPedro Giffuni
76*9c15e1abSPedro Giffuni // return
77*9c15e1abSPedro Giffuni typelib_TypeDescription * pReturnTypeDescr = 0;
78*9c15e1abSPedro Giffuni if (pReturnTypeRef)
79*9c15e1abSPedro Giffuni TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
80*9c15e1abSPedro Giffuni
81*9c15e1abSPedro Giffuni void * pUnoReturn = 0;
82*9c15e1abSPedro Giffuni void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
83*9c15e1abSPedro Giffuni
84*9c15e1abSPedro Giffuni if ( pReturnTypeDescr )
85*9c15e1abSPedro Giffuni {
86*9c15e1abSPedro Giffuni if ( aarch64::return_in_hidden_param( pReturnTypeRef ) )
87*9c15e1abSPedro Giffuni {
88*9c15e1abSPedro Giffuni // AArch64: the indirect-result pointer arrives in x8, NOT in the
89*9c15e1abSPedro Giffuni // first general-purpose argument register (unlike x86-64 SysV).
90*9c15e1abSPedro Giffuni // So we take it from pIndirectReturn and do NOT consume a gpreg
91*9c15e1abSPedro Giffuni // slot here; 'this' still occupies gpreg[0] below.
92*9c15e1abSPedro Giffuni pCppReturn = pIndirectReturn;
93*9c15e1abSPedro Giffuni
94*9c15e1abSPedro Giffuni pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
95*9c15e1abSPedro Giffuni ? alloca( pReturnTypeDescr->nSize )
96*9c15e1abSPedro Giffuni : pCppReturn ); // direct way
97*9c15e1abSPedro Giffuni }
98*9c15e1abSPedro Giffuni else
99*9c15e1abSPedro Giffuni pUnoReturn = pRegisterReturn; // direct way for simple types
100*9c15e1abSPedro Giffuni }
101*9c15e1abSPedro Giffuni
102*9c15e1abSPedro Giffuni // pop this (x0)
103*9c15e1abSPedro Giffuni gpreg++;
104*9c15e1abSPedro Giffuni nr_gpr++;
105*9c15e1abSPedro Giffuni
106*9c15e1abSPedro Giffuni // stack space
107*9c15e1abSPedro Giffuni // parameters
108*9c15e1abSPedro Giffuni void ** pUnoArgs = reinterpret_cast<void **>(alloca( 4 * sizeof(void *) * nParams ));
109*9c15e1abSPedro Giffuni void ** pCppArgs = pUnoArgs + nParams;
110*9c15e1abSPedro Giffuni // indices of values this have to be converted (interface conversion cpp<=>uno)
111*9c15e1abSPedro Giffuni sal_Int32 * pTempIndizes = reinterpret_cast<sal_Int32 *>(pUnoArgs + (2 * nParams));
112*9c15e1abSPedro Giffuni // type descriptions for reconversions
113*9c15e1abSPedro Giffuni typelib_TypeDescription ** ppTempParamTypeDescr = reinterpret_cast<typelib_TypeDescription **>(pUnoArgs + (3 * nParams));
114*9c15e1abSPedro Giffuni
115*9c15e1abSPedro Giffuni sal_Int32 nTempIndizes = 0;
116*9c15e1abSPedro Giffuni
117*9c15e1abSPedro Giffuni for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
118*9c15e1abSPedro Giffuni {
119*9c15e1abSPedro Giffuni const typelib_MethodParameter & rParam = pParams[nPos];
120*9c15e1abSPedro Giffuni
121*9c15e1abSPedro Giffuni int nUsedGPR = 0;
122*9c15e1abSPedro Giffuni int nUsedFPR = 0;
123*9c15e1abSPedro Giffuni if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
124*9c15e1abSPedro Giffuni {
125*9c15e1abSPedro Giffuni // A simple UNO type occupies exactly one register, GPR or FPR.
126*9c15e1abSPedro Giffuni if ( rParam.pTypeRef->eTypeClass == typelib_TypeClass_FLOAT ||
127*9c15e1abSPedro Giffuni rParam.pTypeRef->eTypeClass == typelib_TypeClass_DOUBLE )
128*9c15e1abSPedro Giffuni {
129*9c15e1abSPedro Giffuni nUsedFPR = 1; nUsedGPR = 0;
130*9c15e1abSPedro Giffuni }
131*9c15e1abSPedro Giffuni else
132*9c15e1abSPedro Giffuni {
133*9c15e1abSPedro Giffuni nUsedFPR = 0; nUsedGPR = 1;
134*9c15e1abSPedro Giffuni }
135*9c15e1abSPedro Giffuni
136*9c15e1abSPedro Giffuni OSL_ASSERT( ( nUsedFPR == 1 && nUsedGPR == 0 ) || ( nUsedFPR == 0 && nUsedGPR == 1 ) );
137*9c15e1abSPedro Giffuni
138*9c15e1abSPedro Giffuni if ( nUsedFPR == 1 )
139*9c15e1abSPedro Giffuni {
140*9c15e1abSPedro Giffuni if ( nr_fpr < aarch64::MAX_FPR_REGS )
141*9c15e1abSPedro Giffuni {
142*9c15e1abSPedro Giffuni pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
143*9c15e1abSPedro Giffuni nr_fpr++;
144*9c15e1abSPedro Giffuni }
145*9c15e1abSPedro Giffuni else
146*9c15e1abSPedro Giffuni {
147*9c15e1abSPedro Giffuni stackOffset = aarch64::align_stack_offset(
148*9c15e1abSPedro Giffuni stackOffset, rParam.pTypeRef );
149*9c15e1abSPedro Giffuni pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw + stackOffset;
150*9c15e1abSPedro Giffuni stackOffset += aarch64::stack_size( rParam.pTypeRef );
151*9c15e1abSPedro Giffuni }
152*9c15e1abSPedro Giffuni }
153*9c15e1abSPedro Giffuni else if ( nUsedGPR == 1 )
154*9c15e1abSPedro Giffuni {
155*9c15e1abSPedro Giffuni if ( nr_gpr < aarch64::MAX_GPR_REGS )
156*9c15e1abSPedro Giffuni {
157*9c15e1abSPedro Giffuni pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
158*9c15e1abSPedro Giffuni nr_gpr++;
159*9c15e1abSPedro Giffuni }
160*9c15e1abSPedro Giffuni else
161*9c15e1abSPedro Giffuni {
162*9c15e1abSPedro Giffuni stackOffset = aarch64::align_stack_offset(
163*9c15e1abSPedro Giffuni stackOffset, rParam.pTypeRef );
164*9c15e1abSPedro Giffuni pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw + stackOffset;
165*9c15e1abSPedro Giffuni stackOffset += aarch64::stack_size( rParam.pTypeRef );
166*9c15e1abSPedro Giffuni }
167*9c15e1abSPedro Giffuni }
168*9c15e1abSPedro Giffuni }
169*9c15e1abSPedro Giffuni else // struct <= 16 bytes || ptr to complex value || ref
170*9c15e1abSPedro Giffuni {
171*9c15e1abSPedro Giffuni typelib_TypeDescription * pParamTypeDescr = 0;
172*9c15e1abSPedro Giffuni TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
173*9c15e1abSPedro Giffuni
174*9c15e1abSPedro Giffuni void *pCppStack = 0;
175*9c15e1abSPedro Giffuni if ( nr_gpr < aarch64::MAX_GPR_REGS )
176*9c15e1abSPedro Giffuni {
177*9c15e1abSPedro Giffuni pCppArgs[nPos] = pCppStack = *gpreg++;
178*9c15e1abSPedro Giffuni nr_gpr++;
179*9c15e1abSPedro Giffuni }
180*9c15e1abSPedro Giffuni else
181*9c15e1abSPedro Giffuni {
182*9c15e1abSPedro Giffuni stackOffset = (stackOffset + sizeof(void *) - 1) &
183*9c15e1abSPedro Giffuni ~(sizeof(void *) - 1);
184*9c15e1abSPedro Giffuni pCppArgs[nPos] = pCppStack =
185*9c15e1abSPedro Giffuni *reinterpret_cast<void **>( ovrflw + stackOffset );
186*9c15e1abSPedro Giffuni stackOffset += sizeof(void *);
187*9c15e1abSPedro Giffuni }
188*9c15e1abSPedro Giffuni
189*9c15e1abSPedro Giffuni if (! rParam.bIn) // is pure out
190*9c15e1abSPedro Giffuni {
191*9c15e1abSPedro Giffuni // uno out is unconstructed mem!
192*9c15e1abSPedro Giffuni pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
193*9c15e1abSPedro Giffuni pTempIndizes[nTempIndizes] = nPos;
194*9c15e1abSPedro Giffuni // will be released at reconversion
195*9c15e1abSPedro Giffuni ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
196*9c15e1abSPedro Giffuni }
197*9c15e1abSPedro Giffuni else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
198*9c15e1abSPedro Giffuni {
199*9c15e1abSPedro Giffuni uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
200*9c15e1abSPedro Giffuni pCppStack, pParamTypeDescr,
201*9c15e1abSPedro Giffuni pThis->getBridge()->getCpp2Uno() );
202*9c15e1abSPedro Giffuni pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
203*9c15e1abSPedro Giffuni // will be released at reconversion
204*9c15e1abSPedro Giffuni ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
205*9c15e1abSPedro Giffuni }
206*9c15e1abSPedro Giffuni
207*9c15e1abSPedro Giffuni if ( pCppStack )
208*9c15e1abSPedro Giffuni {
209*9c15e1abSPedro Giffuni if ( pParamTypeDescr->eTypeClass == typelib_TypeClass_STRUCT ||
210*9c15e1abSPedro Giffuni pParamTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION )
211*9c15e1abSPedro Giffuni {
212*9c15e1abSPedro Giffuni // struct in registers/stack: copy it to a temporary if
213*9c15e1abSPedro Giffuni // it needs conversion
214*9c15e1abSPedro Giffuni if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) )
215*9c15e1abSPedro Giffuni {
216*9c15e1abSPedro Giffuni // already handled above
217*9c15e1abSPedro Giffuni }
218*9c15e1abSPedro Giffuni else
219*9c15e1abSPedro Giffuni pUnoArgs[nPos] = pCppStack;
220*9c15e1abSPedro Giffuni }
221*9c15e1abSPedro Giffuni }
222*9c15e1abSPedro Giffuni if ( pParamTypeDescr )
223*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pParamTypeDescr );
224*9c15e1abSPedro Giffuni }
225*9c15e1abSPedro Giffuni }
226*9c15e1abSPedro Giffuni
227*9c15e1abSPedro Giffuni // ExceptionHolder
228*9c15e1abSPedro Giffuni uno_Any aUnoExc; // Any will be constructed by callee
229*9c15e1abSPedro Giffuni uno_Any * pUnoExc = &aUnoExc;
230*9c15e1abSPedro Giffuni
231*9c15e1abSPedro Giffuni // invoke uno dispatch call
232*9c15e1abSPedro Giffuni (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
233*9c15e1abSPedro Giffuni
234*9c15e1abSPedro Giffuni // in case an exception occurred...
235*9c15e1abSPedro Giffuni if ( pUnoExc )
236*9c15e1abSPedro Giffuni {
237*9c15e1abSPedro Giffuni // destruct temporary in/inout params
238*9c15e1abSPedro Giffuni for ( ; nTempIndizes--; )
239*9c15e1abSPedro Giffuni {
240*9c15e1abSPedro Giffuni sal_Int32 nIndex = pTempIndizes[nTempIndizes];
241*9c15e1abSPedro Giffuni
242*9c15e1abSPedro Giffuni if (pParams[nIndex].bIn) // is in/inout => was constructed
243*9c15e1abSPedro Giffuni uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
244*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
245*9c15e1abSPedro Giffuni }
246*9c15e1abSPedro Giffuni if (pReturnTypeDescr)
247*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
248*9c15e1abSPedro Giffuni
249*9c15e1abSPedro Giffuni CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
250*9c15e1abSPedro Giffuni // is here for dummy
251*9c15e1abSPedro Giffuni return typelib_TypeClass_VOID;
252*9c15e1abSPedro Giffuni }
253*9c15e1abSPedro Giffuni else // else no exception occurred...
254*9c15e1abSPedro Giffuni {
255*9c15e1abSPedro Giffuni // temporary params
256*9c15e1abSPedro Giffuni for ( ; nTempIndizes--; )
257*9c15e1abSPedro Giffuni {
258*9c15e1abSPedro Giffuni sal_Int32 nIndex = pTempIndizes[nTempIndizes];
259*9c15e1abSPedro Giffuni typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
260*9c15e1abSPedro Giffuni
261*9c15e1abSPedro Giffuni if ( pParams[nIndex].bOut ) // inout/out
262*9c15e1abSPedro Giffuni {
263*9c15e1abSPedro Giffuni // convert and assign
264*9c15e1abSPedro Giffuni uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
265*9c15e1abSPedro Giffuni uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
266*9c15e1abSPedro Giffuni pThis->getBridge()->getUno2Cpp() );
267*9c15e1abSPedro Giffuni }
268*9c15e1abSPedro Giffuni // destroy temp uno param
269*9c15e1abSPedro Giffuni uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
270*9c15e1abSPedro Giffuni
271*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pParamTypeDescr );
272*9c15e1abSPedro Giffuni }
273*9c15e1abSPedro Giffuni // return
274*9c15e1abSPedro Giffuni if ( pCppReturn ) // has complex return
275*9c15e1abSPedro Giffuni {
276*9c15e1abSPedro Giffuni if ( pUnoReturn != pCppReturn ) // needs reconversion
277*9c15e1abSPedro Giffuni {
278*9c15e1abSPedro Giffuni uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
279*9c15e1abSPedro Giffuni pThis->getBridge()->getUno2Cpp() );
280*9c15e1abSPedro Giffuni // destroy temp uno return
281*9c15e1abSPedro Giffuni uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
282*9c15e1abSPedro Giffuni }
283*9c15e1abSPedro Giffuni // complex return ptr is set to return reg
284*9c15e1abSPedro Giffuni *reinterpret_cast<void **>(pRegisterReturn) = pCppReturn;
285*9c15e1abSPedro Giffuni }
286*9c15e1abSPedro Giffuni if ( pReturnTypeDescr )
287*9c15e1abSPedro Giffuni {
288*9c15e1abSPedro Giffuni typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
289*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
290*9c15e1abSPedro Giffuni return eRet;
291*9c15e1abSPedro Giffuni }
292*9c15e1abSPedro Giffuni else
293*9c15e1abSPedro Giffuni return typelib_TypeClass_VOID;
294*9c15e1abSPedro Giffuni }
295*9c15e1abSPedro Giffuni }
296*9c15e1abSPedro Giffuni
297*9c15e1abSPedro Giffuni
298*9c15e1abSPedro Giffuni //==================================================================================================
cpp_vtable_call(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** gpreg,void ** fpreg,unsigned char * ovrflw,void * pIndirectReturn,sal_uInt64 * pRegisterReturn)299*9c15e1abSPedro Giffuni extern "C" sal_uInt32 cpp_vtable_call(
300*9c15e1abSPedro Giffuni sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
301*9c15e1abSPedro Giffuni void ** gpreg, void ** fpreg, unsigned char * ovrflw,
302*9c15e1abSPedro Giffuni void * pIndirectReturn, // AArch64 x8 indirect-result pointer (0 if none)
303*9c15e1abSPedro Giffuni sal_uInt64 * pRegisterReturn /* space for register return */ )
304*9c15e1abSPedro Giffuni {
305*9c15e1abSPedro Giffuni // gpreg: this, [other gpr params x0..x7]
306*9c15e1abSPedro Giffuni // fpreg: [fpr params d0..d7]
307*9c15e1abSPedro Giffuni // ovrflw: [gpr or fpr params (properly aligned)]
308*9c15e1abSPedro Giffuni // pIndirectReturn: x8 (the hidden return buffer), when bit 0x80000000 set.
309*9c15e1abSPedro Giffuni //
310*9c15e1abSPedro Giffuni // On AArch64 'this' is ALWAYS x0 = gpreg[0]; the hidden return pointer is
311*9c15e1abSPedro Giffuni // the separate x8 register, not a displaced first GPR (unlike x86-64 SysV
312*9c15e1abSPedro Giffuni // where it occupied gpreg[0] and 'this' moved to gpreg[1]).
313*9c15e1abSPedro Giffuni if ( nFunctionIndex & 0x80000000 )
314*9c15e1abSPedro Giffuni nFunctionIndex &= 0x7fffffff;
315*9c15e1abSPedro Giffuni
316*9c15e1abSPedro Giffuni void * pThis = gpreg[0];
317*9c15e1abSPedro Giffuni pThis = static_cast<char *>( pThis ) - nVtableOffset;
318*9c15e1abSPedro Giffuni
319*9c15e1abSPedro Giffuni bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
320*9c15e1abSPedro Giffuni bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
321*9c15e1abSPedro Giffuni
322*9c15e1abSPedro Giffuni typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
323*9c15e1abSPedro Giffuni
324*9c15e1abSPedro Giffuni OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
325*9c15e1abSPedro Giffuni if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
326*9c15e1abSPedro Giffuni {
327*9c15e1abSPedro Giffuni throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
328*9c15e1abSPedro Giffuni reinterpret_cast<XInterface *>( pCppI ) );
329*9c15e1abSPedro Giffuni }
330*9c15e1abSPedro Giffuni
331*9c15e1abSPedro Giffuni // determine called method
332*9c15e1abSPedro Giffuni sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
333*9c15e1abSPedro Giffuni OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
334*9c15e1abSPedro Giffuni
335*9c15e1abSPedro Giffuni TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
336*9c15e1abSPedro Giffuni
337*9c15e1abSPedro Giffuni sal_uInt32 eRet;
338*9c15e1abSPedro Giffuni switch ( aMemberDescr.get()->eTypeClass )
339*9c15e1abSPedro Giffuni {
340*9c15e1abSPedro Giffuni case typelib_TypeClass_INTERFACE_ATTRIBUTE:
341*9c15e1abSPedro Giffuni {
342*9c15e1abSPedro Giffuni typelib_TypeDescriptionReference *pAttrTypeRef =
343*9c15e1abSPedro Giffuni reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
344*9c15e1abSPedro Giffuni
345*9c15e1abSPedro Giffuni if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
346*9c15e1abSPedro Giffuni {
347*9c15e1abSPedro Giffuni // is GET method
348*9c15e1abSPedro Giffuni eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
349*9c15e1abSPedro Giffuni 0, 0, // no params
350*9c15e1abSPedro Giffuni gpreg, fpreg, ovrflw, pIndirectReturn, pRegisterReturn );
351*9c15e1abSPedro Giffuni eRet = aarch64::get_return_kind( pAttrTypeRef );
352*9c15e1abSPedro Giffuni }
353*9c15e1abSPedro Giffuni else
354*9c15e1abSPedro Giffuni {
355*9c15e1abSPedro Giffuni // is SET method
356*9c15e1abSPedro Giffuni typelib_MethodParameter aParam;
357*9c15e1abSPedro Giffuni aParam.pTypeRef = pAttrTypeRef;
358*9c15e1abSPedro Giffuni aParam.bIn = sal_True;
359*9c15e1abSPedro Giffuni aParam.bOut = sal_False;
360*9c15e1abSPedro Giffuni
361*9c15e1abSPedro Giffuni eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
362*9c15e1abSPedro Giffuni 0, // indicates void return
363*9c15e1abSPedro Giffuni 1, &aParam,
364*9c15e1abSPedro Giffuni gpreg, fpreg, ovrflw, pIndirectReturn, pRegisterReturn );
365*9c15e1abSPedro Giffuni }
366*9c15e1abSPedro Giffuni break;
367*9c15e1abSPedro Giffuni }
368*9c15e1abSPedro Giffuni case typelib_TypeClass_INTERFACE_METHOD:
369*9c15e1abSPedro Giffuni {
370*9c15e1abSPedro Giffuni // is METHOD
371*9c15e1abSPedro Giffuni switch ( nFunctionIndex )
372*9c15e1abSPedro Giffuni {
373*9c15e1abSPedro Giffuni case 1: // acquire()
374*9c15e1abSPedro Giffuni pCppI->acquireProxy(); // non virtual call!
375*9c15e1abSPedro Giffuni eRet = typelib_TypeClass_VOID;
376*9c15e1abSPedro Giffuni break;
377*9c15e1abSPedro Giffuni case 2: // release()
378*9c15e1abSPedro Giffuni pCppI->releaseProxy(); // non virtual call!
379*9c15e1abSPedro Giffuni eRet = typelib_TypeClass_VOID;
380*9c15e1abSPedro Giffuni break;
381*9c15e1abSPedro Giffuni case 0: // queryInterface() opt
382*9c15e1abSPedro Giffuni {
383*9c15e1abSPedro Giffuni // queryInterface([in] type) returns an Any (> 16 bytes),
384*9c15e1abSPedro Giffuni // so on AArch64 the result buffer is x8 (pIndirectReturn),
385*9c15e1abSPedro Giffuni // 'this' is gpreg[0], and the type argument is the first
386*9c15e1abSPedro Giffuni // real parameter, gpreg[1].
387*9c15e1abSPedro Giffuni typelib_TypeDescription * pTD = 0;
388*9c15e1abSPedro Giffuni TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( gpreg[1] )->getTypeLibType() );
389*9c15e1abSPedro Giffuni if ( pTD )
390*9c15e1abSPedro Giffuni {
391*9c15e1abSPedro Giffuni XInterface * pInterface = 0;
392*9c15e1abSPedro Giffuni (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
393*9c15e1abSPedro Giffuni ( pCppI->getBridge()->getCppEnv(),
394*9c15e1abSPedro Giffuni reinterpret_cast<void **>(&pInterface),
395*9c15e1abSPedro Giffuni pCppI->getOid().pData,
396*9c15e1abSPedro Giffuni reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
397*9c15e1abSPedro Giffuni
398*9c15e1abSPedro Giffuni if ( pInterface )
399*9c15e1abSPedro Giffuni {
400*9c15e1abSPedro Giffuni ::uno_any_construct( reinterpret_cast<uno_Any *>( pIndirectReturn ),
401*9c15e1abSPedro Giffuni &pInterface, pTD, cpp_acquire );
402*9c15e1abSPedro Giffuni
403*9c15e1abSPedro Giffuni pInterface->release();
404*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pTD );
405*9c15e1abSPedro Giffuni
406*9c15e1abSPedro Giffuni reinterpret_cast<void **>( pRegisterReturn )[0] = pIndirectReturn;
407*9c15e1abSPedro Giffuni eRet = typelib_TypeClass_ANY;
408*9c15e1abSPedro Giffuni break;
409*9c15e1abSPedro Giffuni }
410*9c15e1abSPedro Giffuni TYPELIB_DANGER_RELEASE( pTD );
411*9c15e1abSPedro Giffuni }
412*9c15e1abSPedro Giffuni } // else perform queryInterface()
413*9c15e1abSPedro Giffuni default:
414*9c15e1abSPedro Giffuni {
415*9c15e1abSPedro Giffuni typelib_InterfaceMethodTypeDescription *pMethodTD =
416*9c15e1abSPedro Giffuni reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
417*9c15e1abSPedro Giffuni
418*9c15e1abSPedro Giffuni eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
419*9c15e1abSPedro Giffuni pMethodTD->pReturnTypeRef,
420*9c15e1abSPedro Giffuni pMethodTD->nParams,
421*9c15e1abSPedro Giffuni pMethodTD->pParams,
422*9c15e1abSPedro Giffuni gpreg, fpreg, ovrflw, pIndirectReturn, pRegisterReturn );
423*9c15e1abSPedro Giffuni eRet = aarch64::get_return_kind( pMethodTD->pReturnTypeRef );
424*9c15e1abSPedro Giffuni }
425*9c15e1abSPedro Giffuni }
426*9c15e1abSPedro Giffuni break;
427*9c15e1abSPedro Giffuni }
428*9c15e1abSPedro Giffuni default:
429*9c15e1abSPedro Giffuni {
430*9c15e1abSPedro Giffuni throw RuntimeException( OUString::createFromAscii("no member description found!"),
431*9c15e1abSPedro Giffuni reinterpret_cast<XInterface *>( pCppI ) );
432*9c15e1abSPedro Giffuni // is here for dummy
433*9c15e1abSPedro Giffuni eRet = typelib_TypeClass_VOID;
434*9c15e1abSPedro Giffuni }
435*9c15e1abSPedro Giffuni }
436*9c15e1abSPedro Giffuni
437*9c15e1abSPedro Giffuni return eRet;
438*9c15e1abSPedro Giffuni }
439