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