xref: /AOO42X/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx (revision cd15cd7435a5992ecd53f36ec66392bf63f53df1)
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