1*cd15cd74SJim Jagielski /**************************************************************
2*cd15cd74SJim Jagielski *
3*cd15cd74SJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*cd15cd74SJim Jagielski * or more contributor license agreements. See the NOTICE file
5*cd15cd74SJim Jagielski * distributed with this work for additional information
6*cd15cd74SJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*cd15cd74SJim Jagielski * to you under the Apache License, Version 2.0 (the
8*cd15cd74SJim Jagielski * "License"); you may not use this file except in compliance
9*cd15cd74SJim Jagielski * with the License. You may obtain a copy of the License at
10*cd15cd74SJim Jagielski *
11*cd15cd74SJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*cd15cd74SJim Jagielski *
13*cd15cd74SJim Jagielski * Unless required by applicable law or agreed to in writing,
14*cd15cd74SJim Jagielski * software distributed under the License is distributed on an
15*cd15cd74SJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*cd15cd74SJim Jagielski * KIND, either express or implied. See the License for the
17*cd15cd74SJim Jagielski * specific language governing permissions and limitations
18*cd15cd74SJim Jagielski * under the License.
19*cd15cd74SJim Jagielski *
20*cd15cd74SJim Jagielski *************************************************************/
21*cd15cd74SJim Jagielski
22*cd15cd74SJim Jagielski
23*cd15cd74SJim Jagielski
24*cd15cd74SJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*cd15cd74SJim Jagielski #include "precompiled_bridges.hxx"
26*cd15cd74SJim Jagielski
27*cd15cd74SJim Jagielski #include <exception>
28*cd15cd74SJim Jagielski #include <typeinfo>
29*cd15cd74SJim Jagielski #include <stdio.h>
30*cd15cd74SJim Jagielski #include <stdlib.h>
31*cd15cd74SJim Jagielski #include <string.h>
32*cd15cd74SJim Jagielski
33*cd15cd74SJim Jagielski #include "rtl/alloc.h"
34*cd15cd74SJim Jagielski #include "rtl/ustrbuf.hxx"
35*cd15cd74SJim Jagielski
36*cd15cd74SJim Jagielski #include <com/sun/star/uno/genfunc.hxx>
37*cd15cd74SJim Jagielski #include "com/sun/star/uno/RuntimeException.hpp"
38*cd15cd74SJim Jagielski #include <uno/data.h>
39*cd15cd74SJim Jagielski
40*cd15cd74SJim Jagielski #include <bridges/cpp_uno/shared/bridge.hxx>
41*cd15cd74SJim Jagielski #include <bridges/cpp_uno/shared/types.hxx>
42*cd15cd74SJim Jagielski #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
43*cd15cd74SJim Jagielski #include "bridges/cpp_uno/shared/vtables.hxx"
44*cd15cd74SJim Jagielski
45*cd15cd74SJim Jagielski #include "abi.hxx"
46*cd15cd74SJim Jagielski #include "share.hxx"
47*cd15cd74SJim Jagielski
48*cd15cd74SJim Jagielski using namespace ::rtl;
49*cd15cd74SJim Jagielski using namespace ::com::sun::star::uno;
50*cd15cd74SJim Jagielski
51*cd15cd74SJim Jagielski //==================================================================================================
52*cd15cd74SJim Jagielski
53*cd15cd74SJim Jagielski // The AArch64 outgoing-call trampoline, implemented in call.s. It loads the
54*cd15cd74SJim Jagielski // argument registers from the caller-prepared arrays, copies overflow args to
55*cd15cd74SJim Jagielski // the outgoing stack, performs the indirect call, and returns x0/x1 and d0..d3.
56*cd15cd74SJim Jagielski extern "C" void callVirtualFunction(
57*cd15cd74SJim Jagielski sal_uInt64 pFunction, sal_uInt64 pIndirectRet,
58*cd15cd74SJim Jagielski sal_uInt64 *pGPR, double *pFPR,
59*cd15cd74SJim Jagielski sal_uInt64 *pStack, sal_uInt32 nStackWords,
60*cd15cd74SJim Jagielski sal_uInt64 *pGPRReturn, double *pFPRReturn );
61*cd15cd74SJim Jagielski
62*cd15cd74SJim Jagielski static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
63*cd15cd74SJim Jagielski void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
64*cd15cd74SJim Jagielski void * pIndirectReturn,
65*cd15cd74SJim Jagielski sal_uInt64 *pStack, sal_uInt32 nStack,
66*cd15cd74SJim Jagielski sal_uInt64 *pGPR, sal_uInt32 nGPR,
67*cd15cd74SJim Jagielski double *pFPR, sal_uInt32 nFPR) __attribute__((noinline));
68*cd15cd74SJim Jagielski
callVirtualMethod(void * pThis,sal_uInt32 nVtableIndex,void * pRegisterReturn,typelib_TypeDescriptionReference * pReturnTypeRef,bool bSimpleReturn,void * pIndirectReturn,sal_uInt64 * pStack,sal_uInt32 nStack,sal_uInt64 * pGPR,sal_uInt32 nGPR,double * pFPR,sal_uInt32 nFPR)69*cd15cd74SJim Jagielski static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
70*cd15cd74SJim Jagielski void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
71*cd15cd74SJim Jagielski void * pIndirectReturn,
72*cd15cd74SJim Jagielski sal_uInt64 *pStack, sal_uInt32 nStack,
73*cd15cd74SJim Jagielski sal_uInt64 *pGPR, sal_uInt32 nGPR,
74*cd15cd74SJim Jagielski double *pFPR, sal_uInt32 nFPR)
75*cd15cd74SJim Jagielski {
76*cd15cd74SJim Jagielski #if OSL_DEBUG_LEVEL > 1
77*cd15cd74SJim Jagielski // Let's figure out what is really going on here
78*cd15cd74SJim Jagielski {
79*cd15cd74SJim Jagielski fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
80*cd15cd74SJim Jagielski for ( unsigned int i = 0; i < nGPR; ++i )
81*cd15cd74SJim Jagielski fprintf( stderr, "0x%lx, ", pGPR[i] );
82*cd15cd74SJim Jagielski fprintf( stderr, "\nFPR's (%d): ", nFPR );
83*cd15cd74SJim Jagielski for ( unsigned int i = 0; i < nFPR; ++i )
84*cd15cd74SJim Jagielski fprintf( stderr, "%f, ", pFPR[i] );
85*cd15cd74SJim Jagielski fprintf( stderr, "\nStack (%d): ", nStack );
86*cd15cd74SJim Jagielski for ( unsigned int i = 0; i < nStack; ++i )
87*cd15cd74SJim Jagielski fprintf( stderr, "0x%lx, ", pStack[i] );
88*cd15cd74SJim Jagielski fprintf( stderr, "\n" );
89*cd15cd74SJim Jagielski }
90*cd15cd74SJim Jagielski #endif
91*cd15cd74SJim Jagielski
92*cd15cd74SJim Jagielski // The call instruction within callVirtualFunction may throw exceptions. So
93*cd15cd74SJim Jagielski // that the compiler handles this correctly, it is important that (a)
94*cd15cd74SJim Jagielski // callVirtualMethod might call dummy_can_throw_anything (although this never
95*cd15cd74SJim Jagielski // happens at runtime), which in turn can throw exceptions, and (b)
96*cd15cd74SJim Jagielski // callVirtualMethod is not inlined at its call site (so that any exceptions
97*cd15cd74SJim Jagielski // thrown across the call are caught):
98*cd15cd74SJim Jagielski if ( !pThis )
99*cd15cd74SJim Jagielski CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something
100*cd15cd74SJim Jagielski
101*cd15cd74SJim Jagielski // Should not happen, but...
102*cd15cd74SJim Jagielski if ( nFPR > aarch64::MAX_FPR_REGS )
103*cd15cd74SJim Jagielski nFPR = aarch64::MAX_FPR_REGS;
104*cd15cd74SJim Jagielski if ( nGPR > aarch64::MAX_GPR_REGS )
105*cd15cd74SJim Jagielski nGPR = aarch64::MAX_GPR_REGS;
106*cd15cd74SJim Jagielski
107*cd15cd74SJim Jagielski // Get pointer to the C++ virtual method from the vtable.
108*cd15cd74SJim Jagielski sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
109*cd15cd74SJim Jagielski pMethod += 8 * nVtableIndex;
110*cd15cd74SJim Jagielski pMethod = *((sal_uInt64 *)pMethod);
111*cd15cd74SJim Jagielski
112*cd15cd74SJim Jagielski // Return register save areas: x0,x1 and d0..d3 (HFA up to 4 elements).
113*cd15cd74SJim Jagielski sal_uInt64 gpReturn[2] = { 0, 0 };
114*cd15cd74SJim Jagielski double fpReturn[4] = { 0, 0, 0, 0 };
115*cd15cd74SJim Jagielski
116*cd15cd74SJim Jagielski // Ensure the GPR/FPR arrays are the full register width even if fewer were
117*cd15cd74SJim Jagielski // filled (the trampoline always loads all 8 of each).
118*cd15cd74SJim Jagielski sal_uInt64 gpr[aarch64::MAX_GPR_REGS];
119*cd15cd74SJim Jagielski double fpr[aarch64::MAX_FPR_REGS];
120*cd15cd74SJim Jagielski for ( sal_uInt32 i = 0; i < aarch64::MAX_GPR_REGS; ++i )
121*cd15cd74SJim Jagielski gpr[i] = ( i < nGPR ) ? pGPR[i] : 0;
122*cd15cd74SJim Jagielski for ( sal_uInt32 i = 0; i < aarch64::MAX_FPR_REGS; ++i )
123*cd15cd74SJim Jagielski fpr[i] = ( i < nFPR ) ? pFPR[i] : 0;
124*cd15cd74SJim Jagielski
125*cd15cd74SJim Jagielski callVirtualFunction(
126*cd15cd74SJim Jagielski pMethod,
127*cd15cd74SJim Jagielski reinterpret_cast<sal_uInt64>( pIndirectReturn ), // x8, 0 if none
128*cd15cd74SJim Jagielski gpr, fpr,
129*cd15cd74SJim Jagielski pStack, nStack,
130*cd15cd74SJim Jagielski gpReturn, fpReturn );
131*cd15cd74SJim Jagielski
132*cd15cd74SJim Jagielski switch (pReturnTypeRef->eTypeClass)
133*cd15cd74SJim Jagielski {
134*cd15cd74SJim Jagielski case typelib_TypeClass_HYPER:
135*cd15cd74SJim Jagielski case typelib_TypeClass_UNSIGNED_HYPER:
136*cd15cd74SJim Jagielski *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = gpReturn[0];
137*cd15cd74SJim Jagielski break;
138*cd15cd74SJim Jagielski case typelib_TypeClass_LONG:
139*cd15cd74SJim Jagielski case typelib_TypeClass_UNSIGNED_LONG:
140*cd15cd74SJim Jagielski case typelib_TypeClass_ENUM:
141*cd15cd74SJim Jagielski *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &gpReturn[0] );
142*cd15cd74SJim Jagielski break;
143*cd15cd74SJim Jagielski case typelib_TypeClass_CHAR:
144*cd15cd74SJim Jagielski case typelib_TypeClass_SHORT:
145*cd15cd74SJim Jagielski case typelib_TypeClass_UNSIGNED_SHORT:
146*cd15cd74SJim Jagielski *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &gpReturn[0] );
147*cd15cd74SJim Jagielski break;
148*cd15cd74SJim Jagielski case typelib_TypeClass_BOOLEAN:
149*cd15cd74SJim Jagielski case typelib_TypeClass_BYTE:
150*cd15cd74SJim Jagielski *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &gpReturn[0] );
151*cd15cd74SJim Jagielski break;
152*cd15cd74SJim Jagielski case typelib_TypeClass_FLOAT:
153*cd15cd74SJim Jagielski case typelib_TypeClass_DOUBLE:
154*cd15cd74SJim Jagielski *reinterpret_cast<double *>( pRegisterReturn ) = fpReturn[0];
155*cd15cd74SJim Jagielski break;
156*cd15cd74SJim Jagielski default:
157*cd15cd74SJim Jagielski {
158*cd15cd74SJim Jagielski sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
159*cd15cd74SJim Jagielski if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
160*cd15cd74SJim Jagielski {
161*cd15cd74SJim Jagielski // Register-returned aggregate: an HFA arrives in d0..d3, a
162*cd15cd74SJim Jagielski // non-HFA <= 16 bytes in x0,x1. fill_struct picks the right one.
163*cd15cd74SJim Jagielski aarch64::fill_struct( pReturnTypeRef, &gpReturn[0], &fpReturn[0], pRegisterReturn);
164*cd15cd74SJim Jagielski }
165*cd15cd74SJim Jagielski break;
166*cd15cd74SJim Jagielski }
167*cd15cd74SJim Jagielski }
168*cd15cd74SJim Jagielski }
169*cd15cd74SJim Jagielski
170*cd15cd74SJim Jagielski //==================================================================================================
171*cd15cd74SJim Jagielski
172*cd15cd74SJim Jagielski // Macros for easier insertion of values to registers or stack
173*cd15cd74SJim Jagielski // pSV - pointer to the source
174*cd15cd74SJim Jagielski // nr - order of the value [will be increased if stored to register]
175*cd15cd74SJim Jagielski // pFPR, pGPR - pointer to the registers
176*cd15cd74SJim Jagielski // pDS - pointer to the stack [will be increased if stored here]
177*cd15cd74SJim Jagielski
178*cd15cd74SJim Jagielski // The pFPR slot holds the value to be loaded into a v register; the trampoline
179*cd15cd74SJim Jagielski // loads it with LDR d<n>, so float and double are stored the same way here.
180*cd15cd74SJim Jagielski #define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \
181*cd15cd74SJim Jagielski if ( nr < aarch64::MAX_FPR_REGS ) \
182*cd15cd74SJim Jagielski pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
183*cd15cd74SJim Jagielski else \
184*cd15cd74SJim Jagielski *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
185*cd15cd74SJim Jagielski
186*cd15cd74SJim Jagielski #define INSERT_INT64( pSV, nr, pGPR, pDS ) \
187*cd15cd74SJim Jagielski if ( nr < aarch64::MAX_GPR_REGS ) \
188*cd15cd74SJim Jagielski pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
189*cd15cd74SJim Jagielski else \
190*cd15cd74SJim Jagielski *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
191*cd15cd74SJim Jagielski
192*cd15cd74SJim Jagielski #define INSERT_INT32( pSV, nr, pGPR, pDS ) \
193*cd15cd74SJim Jagielski if ( nr < aarch64::MAX_GPR_REGS ) \
194*cd15cd74SJim Jagielski pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
195*cd15cd74SJim Jagielski else \
196*cd15cd74SJim Jagielski *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
197*cd15cd74SJim Jagielski
198*cd15cd74SJim Jagielski #define INSERT_INT16( pSV, nr, pGPR, pDS ) \
199*cd15cd74SJim Jagielski if ( nr < aarch64::MAX_GPR_REGS ) \
200*cd15cd74SJim Jagielski pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
201*cd15cd74SJim Jagielski else \
202*cd15cd74SJim Jagielski *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
203*cd15cd74SJim Jagielski
204*cd15cd74SJim Jagielski #define INSERT_INT8( pSV, nr, pGPR, pDS ) \
205*cd15cd74SJim Jagielski if ( nr < aarch64::MAX_GPR_REGS ) \
206*cd15cd74SJim Jagielski pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
207*cd15cd74SJim Jagielski else \
208*cd15cd74SJim Jagielski *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
209*cd15cd74SJim Jagielski
210*cd15cd74SJim Jagielski //==================================================================================================
211*cd15cd74SJim Jagielski
212*cd15cd74SJim Jagielski namespace {
213*cd15cd74SJim Jagielski
appendCString(OUStringBuffer & buffer,char const * text)214*cd15cd74SJim Jagielski void appendCString(OUStringBuffer & buffer, char const * text) {
215*cd15cd74SJim Jagielski if (text != 0) {
216*cd15cd74SJim Jagielski buffer.append(
217*cd15cd74SJim Jagielski OStringToOUString(OString(text), RTL_TEXTENCODING_ISO_8859_1));
218*cd15cd74SJim Jagielski // use 8859-1 to avoid conversion failure
219*cd15cd74SJim Jagielski }
220*cd15cd74SJim Jagielski }
221*cd15cd74SJim Jagielski
222*cd15cd74SJim Jagielski }
223*cd15cd74SJim Jagielski
cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,bridges::cpp_uno::shared::VtableSlot aVtableSlot,typelib_TypeDescriptionReference * pReturnTypeRef,sal_Int32 nParams,typelib_MethodParameter * pParams,void * pUnoReturn,void * pUnoArgs[],uno_Any ** ppUnoExc)224*cd15cd74SJim Jagielski static void cpp_call(
225*cd15cd74SJim Jagielski bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
226*cd15cd74SJim Jagielski bridges::cpp_uno::shared::VtableSlot aVtableSlot,
227*cd15cd74SJim Jagielski typelib_TypeDescriptionReference * pReturnTypeRef,
228*cd15cd74SJim Jagielski sal_Int32 nParams, typelib_MethodParameter * pParams,
229*cd15cd74SJim Jagielski void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
230*cd15cd74SJim Jagielski {
231*cd15cd74SJim Jagielski // Maxium space for [complex ret ptr], values | ptr ...
232*cd15cd74SJim Jagielski // (but will be used less - some of the values will be in pGPR and pFPR)
233*cd15cd74SJim Jagielski sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) );
234*cd15cd74SJim Jagielski sal_uInt64 *pStackStart = pStack;
235*cd15cd74SJim Jagielski
236*cd15cd74SJim Jagielski sal_uInt64 pGPR[aarch64::MAX_GPR_REGS];
237*cd15cd74SJim Jagielski sal_uInt32 nGPR = 0;
238*cd15cd74SJim Jagielski
239*cd15cd74SJim Jagielski double pFPR[aarch64::MAX_FPR_REGS];
240*cd15cd74SJim Jagielski sal_uInt32 nFPR = 0;
241*cd15cd74SJim Jagielski
242*cd15cd74SJim Jagielski // Return
243*cd15cd74SJim Jagielski typelib_TypeDescription * pReturnTypeDescr = 0;
244*cd15cd74SJim Jagielski TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
245*cd15cd74SJim Jagielski OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
246*cd15cd74SJim Jagielski
247*cd15cd74SJim Jagielski void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below)
248*cd15cd74SJim Jagielski
249*cd15cd74SJim Jagielski // Indirect-result pointer. On AArch64 this is passed in the dedicated x8
250*cd15cd74SJim Jagielski // register, NOT as the first general-purpose argument (unlike x86-64 SysV).
251*cd15cd74SJim Jagielski // So we do NOT insert it into pGPR here; it is threaded to the trampoline
252*cd15cd74SJim Jagielski // separately as pIndirectReturn.
253*cd15cd74SJim Jagielski void * pIndirectReturn = 0;
254*cd15cd74SJim Jagielski
255*cd15cd74SJim Jagielski bool bSimpleReturn = true;
256*cd15cd74SJim Jagielski if ( pReturnTypeDescr )
257*cd15cd74SJim Jagielski {
258*cd15cd74SJim Jagielski if ( aarch64::return_in_hidden_param( pReturnTypeRef ) )
259*cd15cd74SJim Jagielski bSimpleReturn = false;
260*cd15cd74SJim Jagielski
261*cd15cd74SJim Jagielski if ( bSimpleReturn )
262*cd15cd74SJim Jagielski pCppReturn = pUnoReturn; // direct way for simple types
263*cd15cd74SJim Jagielski else
264*cd15cd74SJim Jagielski {
265*cd15cd74SJim Jagielski // complex return via the x8 indirect-result buffer
266*cd15cd74SJim Jagielski pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
267*cd15cd74SJim Jagielski __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
268*cd15cd74SJim Jagielski pIndirectReturn = pCppReturn;
269*cd15cd74SJim Jagielski }
270*cd15cd74SJim Jagielski }
271*cd15cd74SJim Jagielski
272*cd15cd74SJim Jagielski // Push "this" pointer
273*cd15cd74SJim Jagielski void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
274*cd15cd74SJim Jagielski INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
275*cd15cd74SJim Jagielski
276*cd15cd74SJim Jagielski // Args
277*cd15cd74SJim Jagielski void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
278*cd15cd74SJim Jagielski // Indizes of values this have to be converted (interface conversion cpp<=>uno)
279*cd15cd74SJim Jagielski sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
280*cd15cd74SJim Jagielski // Type descriptions for reconversions
281*cd15cd74SJim Jagielski typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
282*cd15cd74SJim Jagielski
283*cd15cd74SJim Jagielski sal_Int32 nTempIndizes = 0;
284*cd15cd74SJim Jagielski
285*cd15cd74SJim Jagielski for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
286*cd15cd74SJim Jagielski {
287*cd15cd74SJim Jagielski const typelib_MethodParameter & rParam = pParams[nPos];
288*cd15cd74SJim Jagielski typelib_TypeDescription * pParamTypeDescr = 0;
289*cd15cd74SJim Jagielski TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
290*cd15cd74SJim Jagielski
291*cd15cd74SJim Jagielski if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
292*cd15cd74SJim Jagielski {
293*cd15cd74SJim Jagielski uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
294*cd15cd74SJim Jagielski pThis->getBridge()->getUno2Cpp() );
295*cd15cd74SJim Jagielski
296*cd15cd74SJim Jagielski switch (pParamTypeDescr->eTypeClass)
297*cd15cd74SJim Jagielski {
298*cd15cd74SJim Jagielski case typelib_TypeClass_HYPER:
299*cd15cd74SJim Jagielski case typelib_TypeClass_UNSIGNED_HYPER:
300*cd15cd74SJim Jagielski INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
301*cd15cd74SJim Jagielski break;
302*cd15cd74SJim Jagielski case typelib_TypeClass_LONG:
303*cd15cd74SJim Jagielski case typelib_TypeClass_UNSIGNED_LONG:
304*cd15cd74SJim Jagielski case typelib_TypeClass_ENUM:
305*cd15cd74SJim Jagielski INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
306*cd15cd74SJim Jagielski break;
307*cd15cd74SJim Jagielski case typelib_TypeClass_SHORT:
308*cd15cd74SJim Jagielski case typelib_TypeClass_CHAR:
309*cd15cd74SJim Jagielski case typelib_TypeClass_UNSIGNED_SHORT:
310*cd15cd74SJim Jagielski INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
311*cd15cd74SJim Jagielski break;
312*cd15cd74SJim Jagielski case typelib_TypeClass_BOOLEAN:
313*cd15cd74SJim Jagielski case typelib_TypeClass_BYTE:
314*cd15cd74SJim Jagielski INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
315*cd15cd74SJim Jagielski break;
316*cd15cd74SJim Jagielski case typelib_TypeClass_FLOAT:
317*cd15cd74SJim Jagielski case typelib_TypeClass_DOUBLE:
318*cd15cd74SJim Jagielski INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
319*cd15cd74SJim Jagielski break;
320*cd15cd74SJim Jagielski default:
321*cd15cd74SJim Jagielski break;
322*cd15cd74SJim Jagielski }
323*cd15cd74SJim Jagielski
324*cd15cd74SJim Jagielski // no longer needed
325*cd15cd74SJim Jagielski TYPELIB_DANGER_RELEASE( pParamTypeDescr );
326*cd15cd74SJim Jagielski }
327*cd15cd74SJim Jagielski else // ptr to complex value | ref
328*cd15cd74SJim Jagielski {
329*cd15cd74SJim Jagielski if (! rParam.bIn) // is pure out
330*cd15cd74SJim Jagielski {
331*cd15cd74SJim Jagielski // cpp out is constructed mem, uno out is not!
332*cd15cd74SJim Jagielski uno_constructData(
333*cd15cd74SJim Jagielski pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
334*cd15cd74SJim Jagielski pParamTypeDescr );
335*cd15cd74SJim Jagielski pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
336*cd15cd74SJim Jagielski // will be released at reconversion
337*cd15cd74SJim Jagielski ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
338*cd15cd74SJim Jagielski }
339*cd15cd74SJim Jagielski // is in/inout
340*cd15cd74SJim Jagielski else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
341*cd15cd74SJim Jagielski {
342*cd15cd74SJim Jagielski uno_copyAndConvertData(
343*cd15cd74SJim Jagielski pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
344*cd15cd74SJim Jagielski pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
345*cd15cd74SJim Jagielski
346*cd15cd74SJim Jagielski pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
347*cd15cd74SJim Jagielski // will be released at reconversion
348*cd15cd74SJim Jagielski ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
349*cd15cd74SJim Jagielski }
350*cd15cd74SJim Jagielski else // direct way
351*cd15cd74SJim Jagielski {
352*cd15cd74SJim Jagielski pCppArgs[nPos] = pUnoArgs[nPos];
353*cd15cd74SJim Jagielski // no longer needed
354*cd15cd74SJim Jagielski TYPELIB_DANGER_RELEASE( pParamTypeDescr );
355*cd15cd74SJim Jagielski }
356*cd15cd74SJim Jagielski INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
357*cd15cd74SJim Jagielski }
358*cd15cd74SJim Jagielski }
359*cd15cd74SJim Jagielski
360*cd15cd74SJim Jagielski try
361*cd15cd74SJim Jagielski {
362*cd15cd74SJim Jagielski try {
363*cd15cd74SJim Jagielski callVirtualMethod(
364*cd15cd74SJim Jagielski pAdjustedThisPtr, aVtableSlot.index,
365*cd15cd74SJim Jagielski pCppReturn, pReturnTypeRef, bSimpleReturn,
366*cd15cd74SJim Jagielski pIndirectReturn,
367*cd15cd74SJim Jagielski pStackStart, ( pStack - pStackStart ),
368*cd15cd74SJim Jagielski pGPR, nGPR,
369*cd15cd74SJim Jagielski pFPR, nFPR );
370*cd15cd74SJim Jagielski } catch (Exception &) {
371*cd15cd74SJim Jagielski throw;
372*cd15cd74SJim Jagielski } catch (std::exception & e) {
373*cd15cd74SJim Jagielski OUStringBuffer buf;
374*cd15cd74SJim Jagielski buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("C++ code threw "));
375*cd15cd74SJim Jagielski appendCString(buf, typeid(e).name());
376*cd15cd74SJim Jagielski buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": "));
377*cd15cd74SJim Jagielski appendCString(buf, e.what());
378*cd15cd74SJim Jagielski throw RuntimeException(
379*cd15cd74SJim Jagielski buf.makeStringAndClear(), Reference< XInterface >());
380*cd15cd74SJim Jagielski } catch (...) {
381*cd15cd74SJim Jagielski throw RuntimeException(
382*cd15cd74SJim Jagielski OUString(
383*cd15cd74SJim Jagielski RTL_CONSTASCII_USTRINGPARAM(
384*cd15cd74SJim Jagielski "C++ code threw unknown exception")),
385*cd15cd74SJim Jagielski Reference< XInterface >());
386*cd15cd74SJim Jagielski }
387*cd15cd74SJim Jagielski
388*cd15cd74SJim Jagielski // NO exception occurred...
389*cd15cd74SJim Jagielski *ppUnoExc = 0;
390*cd15cd74SJim Jagielski
391*cd15cd74SJim Jagielski // reconvert temporary params
392*cd15cd74SJim Jagielski for ( ; nTempIndizes--; )
393*cd15cd74SJim Jagielski {
394*cd15cd74SJim Jagielski sal_Int32 nIndex = pTempIndizes[nTempIndizes];
395*cd15cd74SJim Jagielski typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
396*cd15cd74SJim Jagielski
397*cd15cd74SJim Jagielski if (pParams[nIndex].bIn)
398*cd15cd74SJim Jagielski {
399*cd15cd74SJim Jagielski if (pParams[nIndex].bOut) // inout
400*cd15cd74SJim Jagielski {
401*cd15cd74SJim Jagielski uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
402*cd15cd74SJim Jagielski uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
403*cd15cd74SJim Jagielski pThis->getBridge()->getCpp2Uno() );
404*cd15cd74SJim Jagielski }
405*cd15cd74SJim Jagielski }
406*cd15cd74SJim Jagielski else // pure out
407*cd15cd74SJim Jagielski {
408*cd15cd74SJim Jagielski uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
409*cd15cd74SJim Jagielski pThis->getBridge()->getCpp2Uno() );
410*cd15cd74SJim Jagielski }
411*cd15cd74SJim Jagielski // destroy temp cpp param => cpp: every param was constructed
412*cd15cd74SJim Jagielski uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
413*cd15cd74SJim Jagielski
414*cd15cd74SJim Jagielski TYPELIB_DANGER_RELEASE( pParamTypeDescr );
415*cd15cd74SJim Jagielski }
416*cd15cd74SJim Jagielski // return value
417*cd15cd74SJim Jagielski if (pCppReturn && pUnoReturn != pCppReturn)
418*cd15cd74SJim Jagielski {
419*cd15cd74SJim Jagielski uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
420*cd15cd74SJim Jagielski pThis->getBridge()->getCpp2Uno() );
421*cd15cd74SJim Jagielski uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
422*cd15cd74SJim Jagielski }
423*cd15cd74SJim Jagielski }
424*cd15cd74SJim Jagielski catch (...)
425*cd15cd74SJim Jagielski {
426*cd15cd74SJim Jagielski // fill uno exception
427*cd15cd74SJim Jagielski fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
428*cd15cd74SJim Jagielski
429*cd15cd74SJim Jagielski // temporary params
430*cd15cd74SJim Jagielski for ( ; nTempIndizes--; )
431*cd15cd74SJim Jagielski {
432*cd15cd74SJim Jagielski sal_Int32 nIndex = pTempIndizes[nTempIndizes];
433*cd15cd74SJim Jagielski // destroy temp cpp param => cpp: every param was constructed
434*cd15cd74SJim Jagielski uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
435*cd15cd74SJim Jagielski TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
436*cd15cd74SJim Jagielski }
437*cd15cd74SJim Jagielski // return type
438*cd15cd74SJim Jagielski if (pReturnTypeDescr)
439*cd15cd74SJim Jagielski TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
440*cd15cd74SJim Jagielski }
441*cd15cd74SJim Jagielski }
442*cd15cd74SJim Jagielski
443*cd15cd74SJim Jagielski //==================================================================================================
444*cd15cd74SJim Jagielski
445*cd15cd74SJim Jagielski namespace bridges { namespace cpp_uno { namespace shared {
446*cd15cd74SJim Jagielski
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)447*cd15cd74SJim Jagielski void unoInterfaceProxyDispatch(
448*cd15cd74SJim Jagielski uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
449*cd15cd74SJim Jagielski void * pReturn, void * pArgs[], uno_Any ** ppException )
450*cd15cd74SJim Jagielski {
451*cd15cd74SJim Jagielski // is my surrogate
452*cd15cd74SJim Jagielski bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
453*cd15cd74SJim Jagielski = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
454*cd15cd74SJim Jagielski #if OSL_DEBUG_LEVEL > 0
455*cd15cd74SJim Jagielski typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
456*cd15cd74SJim Jagielski #endif
457*cd15cd74SJim Jagielski
458*cd15cd74SJim Jagielski switch (pMemberDescr->eTypeClass)
459*cd15cd74SJim Jagielski {
460*cd15cd74SJim Jagielski case typelib_TypeClass_INTERFACE_ATTRIBUTE:
461*cd15cd74SJim Jagielski {
462*cd15cd74SJim Jagielski #if OSL_DEBUG_LEVEL > 0
463*cd15cd74SJim Jagielski // determine vtable call index
464*cd15cd74SJim Jagielski sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
465*cd15cd74SJim Jagielski OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
466*cd15cd74SJim Jagielski #endif
467*cd15cd74SJim Jagielski VtableSlot aVtableSlot(
468*cd15cd74SJim Jagielski getVtableSlot(
469*cd15cd74SJim Jagielski reinterpret_cast<
470*cd15cd74SJim Jagielski typelib_InterfaceAttributeTypeDescription const * >(
471*cd15cd74SJim Jagielski pMemberDescr)));
472*cd15cd74SJim Jagielski
473*cd15cd74SJim Jagielski if (pReturn)
474*cd15cd74SJim Jagielski {
475*cd15cd74SJim Jagielski // dependent dispatch
476*cd15cd74SJim Jagielski cpp_call(
477*cd15cd74SJim Jagielski pThis, aVtableSlot,
478*cd15cd74SJim Jagielski ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
479*cd15cd74SJim Jagielski 0, 0, // no params
480*cd15cd74SJim Jagielski pReturn, pArgs, ppException );
481*cd15cd74SJim Jagielski }
482*cd15cd74SJim Jagielski else
483*cd15cd74SJim Jagielski {
484*cd15cd74SJim Jagielski // is SET
485*cd15cd74SJim Jagielski typelib_MethodParameter aParam;
486*cd15cd74SJim Jagielski aParam.pTypeRef =
487*cd15cd74SJim Jagielski ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
488*cd15cd74SJim Jagielski aParam.bIn = sal_True;
489*cd15cd74SJim Jagielski aParam.bOut = sal_False;
490*cd15cd74SJim Jagielski
491*cd15cd74SJim Jagielski typelib_TypeDescriptionReference * pReturnTypeRef = 0;
492*cd15cd74SJim Jagielski OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
493*cd15cd74SJim Jagielski typelib_typedescriptionreference_new(
494*cd15cd74SJim Jagielski &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
495*cd15cd74SJim Jagielski
496*cd15cd74SJim Jagielski // dependent dispatch
497*cd15cd74SJim Jagielski aVtableSlot.index += 1; // get, then set method
498*cd15cd74SJim Jagielski cpp_call(
499*cd15cd74SJim Jagielski pThis, aVtableSlot, // get, then set method
500*cd15cd74SJim Jagielski pReturnTypeRef,
501*cd15cd74SJim Jagielski 1, &aParam,
502*cd15cd74SJim Jagielski pReturn, pArgs, ppException );
503*cd15cd74SJim Jagielski
504*cd15cd74SJim Jagielski typelib_typedescriptionreference_release( pReturnTypeRef );
505*cd15cd74SJim Jagielski }
506*cd15cd74SJim Jagielski
507*cd15cd74SJim Jagielski break;
508*cd15cd74SJim Jagielski }
509*cd15cd74SJim Jagielski case typelib_TypeClass_INTERFACE_METHOD:
510*cd15cd74SJim Jagielski {
511*cd15cd74SJim Jagielski #if OSL_DEBUG_LEVEL > 0
512*cd15cd74SJim Jagielski // determine vtable call index
513*cd15cd74SJim Jagielski sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
514*cd15cd74SJim Jagielski OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
515*cd15cd74SJim Jagielski #endif
516*cd15cd74SJim Jagielski VtableSlot aVtableSlot(
517*cd15cd74SJim Jagielski getVtableSlot(
518*cd15cd74SJim Jagielski reinterpret_cast<
519*cd15cd74SJim Jagielski typelib_InterfaceMethodTypeDescription const * >(
520*cd15cd74SJim Jagielski pMemberDescr)));
521*cd15cd74SJim Jagielski
522*cd15cd74SJim Jagielski switch (aVtableSlot.index)
523*cd15cd74SJim Jagielski {
524*cd15cd74SJim Jagielski // standard calls
525*cd15cd74SJim Jagielski case 1: // acquire uno interface
526*cd15cd74SJim Jagielski (*pUnoI->acquire)( pUnoI );
527*cd15cd74SJim Jagielski *ppException = 0;
528*cd15cd74SJim Jagielski break;
529*cd15cd74SJim Jagielski case 2: // release uno interface
530*cd15cd74SJim Jagielski (*pUnoI->release)( pUnoI );
531*cd15cd74SJim Jagielski *ppException = 0;
532*cd15cd74SJim Jagielski break;
533*cd15cd74SJim Jagielski case 0: // queryInterface() opt
534*cd15cd74SJim Jagielski {
535*cd15cd74SJim Jagielski typelib_TypeDescription * pTD = 0;
536*cd15cd74SJim Jagielski TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
537*cd15cd74SJim Jagielski if (pTD)
538*cd15cd74SJim Jagielski {
539*cd15cd74SJim Jagielski uno_Interface * pInterface = 0;
540*cd15cd74SJim Jagielski (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
541*cd15cd74SJim Jagielski pThis->getBridge()->getUnoEnv(),
542*cd15cd74SJim Jagielski (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
543*cd15cd74SJim Jagielski
544*cd15cd74SJim Jagielski if (pInterface)
545*cd15cd74SJim Jagielski {
546*cd15cd74SJim Jagielski ::uno_any_construct(
547*cd15cd74SJim Jagielski reinterpret_cast< uno_Any * >( pReturn ),
548*cd15cd74SJim Jagielski &pInterface, pTD, 0 );
549*cd15cd74SJim Jagielski (*pInterface->release)( pInterface );
550*cd15cd74SJim Jagielski TYPELIB_DANGER_RELEASE( pTD );
551*cd15cd74SJim Jagielski *ppException = 0;
552*cd15cd74SJim Jagielski break;
553*cd15cd74SJim Jagielski }
554*cd15cd74SJim Jagielski TYPELIB_DANGER_RELEASE( pTD );
555*cd15cd74SJim Jagielski }
556*cd15cd74SJim Jagielski } // else perform queryInterface()
557*cd15cd74SJim Jagielski default:
558*cd15cd74SJim Jagielski // dependent dispatch
559*cd15cd74SJim Jagielski cpp_call(
560*cd15cd74SJim Jagielski pThis, aVtableSlot,
561*cd15cd74SJim Jagielski ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
562*cd15cd74SJim Jagielski ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
563*cd15cd74SJim Jagielski ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
564*cd15cd74SJim Jagielski pReturn, pArgs, ppException );
565*cd15cd74SJim Jagielski }
566*cd15cd74SJim Jagielski break;
567*cd15cd74SJim Jagielski }
568*cd15cd74SJim Jagielski default:
569*cd15cd74SJim Jagielski {
570*cd15cd74SJim Jagielski ::com::sun::star::uno::RuntimeException aExc(
571*cd15cd74SJim Jagielski OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
572*cd15cd74SJim Jagielski ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
573*cd15cd74SJim Jagielski
574*cd15cd74SJim Jagielski Type const & rExcType = ::getCppuType( &aExc );
575*cd15cd74SJim Jagielski // binary identical null reference
576*cd15cd74SJim Jagielski ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
577*cd15cd74SJim Jagielski }
578*cd15cd74SJim Jagielski }
579*cd15cd74SJim Jagielski }
580*cd15cd74SJim Jagielski
581*cd15cd74SJim Jagielski } } }
582