xref: /trunk/main/bridges/source/cpp_uno/gcc3_freebsd_x86-64/uno2cpp.cxx (revision 61dff127b6698e0bae836c8aedd6ec62111483d1)
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 <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <rtl/alloc.h>
31 
32 #include <com/sun/star/uno/genfunc.hxx>
33 #include "com/sun/star/uno/RuntimeException.hpp"
34 #include <uno/data.h>
35 
36 #include <bridges/cpp_uno/shared/bridge.hxx>
37 #include <bridges/cpp_uno/shared/types.hxx>
38 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
39 #include "bridges/cpp_uno/shared/vtables.hxx"
40 
41 #include "abi.hxx"
42 #include "share.hxx"
43 
44 using namespace ::rtl;
45 using namespace ::com::sun::star::uno;
46 
47 //==================================================================================================
48 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
49                               void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
50                               sal_uInt64 *pStack, sal_uInt32 nStack,
51                               sal_uInt64 *pGPR, sal_uInt32 nGPR,
52                               double *pFPR, sal_uInt32 nFPR) __attribute__((noinline));
53 
54 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
55                               void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
56                               sal_uInt64 *pStack, sal_uInt32 nStack,
57                               sal_uInt64 *pGPR, sal_uInt32 nGPR,
58                               double *pFPR, sal_uInt32 nFPR)
59 {
60 #if OSL_DEBUG_LEVEL > 1
61     // Let's figure out what is really going on here
62     {
63         fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
64         for ( unsigned int i = 0; i < nGPR; ++i )
65             fprintf( stderr, "0x%lx, ", pGPR[i] );
66         fprintf( stderr, "\nFPR's (%d): ", nFPR );
67         for ( unsigned int i = 0; i < nFPR; ++i )
68             fprintf( stderr, "%f, ", pFPR[i] );
69         fprintf( stderr, "\nStack (%d): ", nStack );
70         for ( unsigned int i = 0; i < nStack; ++i )
71             fprintf( stderr, "0x%lx, ", pStack[i] );
72         fprintf( stderr, "\n" );
73     }
74 #endif
75 
76     // The call instruction within the asm section of callVirtualMethod may throw
77     // exceptions.  So that the compiler handles this correctly, it is important
78     // that (a) callVirtualMethod might call dummy_can_throw_anything (although this
79     // never happens at runtime), which in turn can throw exceptions, and (b)
80     // callVirtualMethod is not inlined at its call site (so that any exceptions are
81     // caught which are thrown from the instruction calling callVirtualMethod):
82     if ( !pThis )
83         CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something
84 
85     // Should not happen, but...
86     if ( nFPR > x86_64::MAX_SSE_REGS )
87         nFPR = x86_64::MAX_SSE_REGS;
88     if ( nGPR > x86_64::MAX_GPR_REGS )
89         nGPR = x86_64::MAX_GPR_REGS;
90 
91     // Get pointer to method
92     sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
93     pMethod += 8 * nVtableIndex;
94     pMethod = *((sal_uInt64 *)pMethod);
95 
96     // Load parameters to stack, if necessary
97     if ( nStack )
98     {
99         // 16-bytes aligned
100         sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 16;
101         sal_uInt64 *pCallStack = (sal_uInt64 *) __builtin_alloca( nStackBytes );
102         memcpy( pCallStack, pStack, nStackBytes );
103     }
104 
105     // Return values
106     sal_uInt64 rax;
107     sal_uInt64 rdx;
108     double xmm0;
109     double xmm1;
110 
111     asm volatile (
112 
113         // Fill the xmm registers
114         "movq %2, %%rax\n\t"
115 
116         "movsd   (%%rax), %%xmm0\n\t"
117         "movsd  8(%%rax), %%xmm1\n\t"
118         "movsd 16(%%rax), %%xmm2\n\t"
119         "movsd 24(%%rax), %%xmm3\n\t"
120         "movsd 32(%%rax), %%xmm4\n\t"
121         "movsd 40(%%rax), %%xmm5\n\t"
122         "movsd 48(%%rax), %%xmm6\n\t"
123         "movsd 56(%%rax), %%xmm7\n\t"
124 
125         // Fill the general purpose registers
126         "movq %1, %%rax\n\t"
127 
128         "movq    (%%rax), %%rdi\n\t"
129         "movq   8(%%rax), %%rsi\n\t"
130         "movq  16(%%rax), %%rdx\n\t"
131         "movq  24(%%rax), %%rcx\n\t"
132         "movq  32(%%rax), %%r8\n\t"
133         "movq  40(%%rax), %%r9\n\t"
134 
135         // Perform the call
136         "movq %0, %%r11\n\t"
137         "movq %3, %%rax\n\t"
138         "call *%%r11\n\t"
139 
140         // Fill the return values
141         "movq   %%rax, %4\n\t"
142         "movq   %%rdx, %5\n\t"
143         "movsd %%xmm0, %6\n\t"
144         "movsd %%xmm1, %7\n\t"
145         :
146         : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR ),
147           "m" ( rax ), "m" ( rdx ), "m" ( xmm0 ), "m" ( xmm1 )
148         : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11"
149     );
150 
151     switch (pReturnTypeRef->eTypeClass)
152     {
153     case typelib_TypeClass_HYPER:
154     case typelib_TypeClass_UNSIGNED_HYPER:
155         *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = rax;
156         break;
157     case typelib_TypeClass_LONG:
158     case typelib_TypeClass_UNSIGNED_LONG:
159     case typelib_TypeClass_ENUM:
160         *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &rax );
161         break;
162     case typelib_TypeClass_CHAR:
163     case typelib_TypeClass_SHORT:
164     case typelib_TypeClass_UNSIGNED_SHORT:
165         *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &rax );
166         break;
167     case typelib_TypeClass_BOOLEAN:
168     case typelib_TypeClass_BYTE:
169         *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &rax );
170         break;
171     case typelib_TypeClass_FLOAT:
172     case typelib_TypeClass_DOUBLE:
173         *reinterpret_cast<double *>( pRegisterReturn ) = xmm0;
174         break;
175     default:
176         {
177             sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
178             if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
179             {
180                 sal_uInt64 longs[2];
181                 longs[0] = rax;
182                 longs[1] = rdx;
183 
184                 double doubles[2];
185                 doubles[0] = xmm0;
186                 doubles[1] = xmm1;
187                 x86_64::fill_struct( pReturnTypeRef, &longs[0], &doubles[0], pRegisterReturn);
188             }
189             break;
190         }
191     }
192 }
193 
194 //==================================================================================================
195 
196 // Macros for easier insertion of values to registers or stack
197 // pSV - pointer to the source
198 // nr - order of the value [will be increased if stored to register]
199 // pFPR, pGPR - pointer to the registers
200 // pDS - pointer to the stack [will be increased if stored here]
201 
202 // The value in %xmm register is already prepared to be retrieved as a float,
203 // thus we treat float and double the same
204 #define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \
205     if ( nr < x86_64::MAX_SSE_REGS ) \
206         pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
207     else \
208         *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
209 
210 #define INSERT_INT64( pSV, nr, pGPR, pDS ) \
211     if ( nr < x86_64::MAX_GPR_REGS ) \
212         pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
213     else \
214         *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
215 
216 #define INSERT_INT32( pSV, nr, pGPR, pDS ) \
217     if ( nr < x86_64::MAX_GPR_REGS ) \
218         pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
219     else \
220         *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
221 
222 #define INSERT_INT16( pSV, nr, pGPR, pDS ) \
223     if ( nr < x86_64::MAX_GPR_REGS ) \
224         pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
225     else \
226         *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
227 
228 #define INSERT_INT8( pSV, nr, pGPR, pDS ) \
229     if ( nr < x86_64::MAX_GPR_REGS ) \
230         pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
231     else \
232         *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
233 
234 //==================================================================================================
235 
236 static void cpp_call(
237     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
238     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
239     typelib_TypeDescriptionReference * pReturnTypeRef,
240     sal_Int32 nParams, typelib_MethodParameter * pParams,
241     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
242 {
243     // Maxium space for [complex ret ptr], values | ptr ...
244     // (but will be used less - some of the values will be in pGPR and pFPR)
245     sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) );
246     sal_uInt64 *pStackStart = pStack;
247 
248     sal_uInt64 pGPR[x86_64::MAX_GPR_REGS];
249     sal_uInt32 nGPR = 0;
250 
251     double pFPR[x86_64::MAX_SSE_REGS];
252     sal_uInt32 nFPR = 0;
253 
254     // Return
255     typelib_TypeDescription * pReturnTypeDescr = 0;
256     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
257     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
258 
259     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below)
260 
261     bool bSimpleReturn = true;
262     if ( pReturnTypeDescr )
263     {
264         if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
265             bSimpleReturn = false;
266 
267         if ( bSimpleReturn )
268             pCppReturn = pUnoReturn; // direct way for simple types
269         else
270         {
271             // complex return via ptr
272             pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
273                          __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
274             INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack );
275         }
276     }
277 
278     // Push "this" pointer
279     void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
280     INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
281 
282     // Args
283     void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
284     // Indizes of values this have to be converted (interface conversion cpp<=>uno)
285     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
286     // Type descriptions for reconversions
287     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
288 
289     sal_Int32 nTempIndizes = 0;
290 
291     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
292     {
293         const typelib_MethodParameter & rParam = pParams[nPos];
294         typelib_TypeDescription * pParamTypeDescr = 0;
295         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
296 
297         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
298         {
299             uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
300                                     pThis->getBridge()->getUno2Cpp() );
301 
302             switch (pParamTypeDescr->eTypeClass)
303             {
304             case typelib_TypeClass_HYPER:
305             case typelib_TypeClass_UNSIGNED_HYPER:
306                 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
307                 break;
308             case typelib_TypeClass_LONG:
309             case typelib_TypeClass_UNSIGNED_LONG:
310             case typelib_TypeClass_ENUM:
311                 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
312                 break;
313             case typelib_TypeClass_SHORT:
314             case typelib_TypeClass_CHAR:
315             case typelib_TypeClass_UNSIGNED_SHORT:
316                 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
317                 break;
318             case typelib_TypeClass_BOOLEAN:
319             case typelib_TypeClass_BYTE:
320                 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
321                 break;
322             case typelib_TypeClass_FLOAT:
323             case typelib_TypeClass_DOUBLE:
324                 INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
325                 break;
326             default:
327                 break;
328             }
329 
330             // no longer needed
331             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
332         }
333         else // ptr to complex value | ref
334         {
335             if (! rParam.bIn) // is pure out
336             {
337                 // cpp out is constructed mem, uno out is not!
338                 uno_constructData(
339                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
340                     pParamTypeDescr );
341                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
342                 // will be released at reconversion
343                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
344             }
345             // is in/inout
346             else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
347             {
348                 uno_copyAndConvertData(
349                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
350                     pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
351 
352                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
353                 // will be released at reconversion
354                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
355             }
356             else // direct way
357             {
358                 pCppArgs[nPos] = pUnoArgs[nPos];
359                 // no longer needed
360                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
361             }
362             INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
363         }
364     }
365 
366     try
367     {
368         callVirtualMethod(
369             pAdjustedThisPtr, aVtableSlot.index,
370             pCppReturn, pReturnTypeRef, bSimpleReturn,
371             pStackStart, ( pStack - pStackStart ),
372             pGPR, nGPR,
373             pFPR, nFPR );
374         // NO exception occured...
375         *ppUnoExc = 0;
376 
377         // reconvert temporary params
378         for ( ; nTempIndizes--; )
379         {
380             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
381             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
382 
383             if (pParams[nIndex].bIn)
384             {
385                 if (pParams[nIndex].bOut) // inout
386                 {
387                     uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
388                     uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
389                                             pThis->getBridge()->getCpp2Uno() );
390                 }
391             }
392             else // pure out
393             {
394                 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
395                                         pThis->getBridge()->getCpp2Uno() );
396             }
397             // destroy temp cpp param => cpp: every param was constructed
398             uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
399 
400             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
401         }
402         // return value
403         if (pCppReturn && pUnoReturn != pCppReturn)
404         {
405             uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
406                                     pThis->getBridge()->getCpp2Uno() );
407             uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
408         }
409     }
410     catch (...)
411     {
412         // fill uno exception
413         fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
414 
415         // temporary params
416         for ( ; nTempIndizes--; )
417         {
418             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
419             // destroy temp cpp param => cpp: every param was constructed
420             uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
421             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
422         }
423         // return type
424         if (pReturnTypeDescr)
425             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
426     }
427 }
428 
429 //==================================================================================================
430 
431 namespace bridges { namespace cpp_uno { namespace shared {
432 
433 void unoInterfaceProxyDispatch(
434     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
435     void * pReturn, void * pArgs[], uno_Any ** ppException )
436 {
437     // is my surrogate
438     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
439         = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
440 #if OSL_DEBUG_LEVEL > 0
441     typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
442 #endif
443 
444     switch (pMemberDescr->eTypeClass)
445     {
446     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
447     {
448 #if OSL_DEBUG_LEVEL > 0
449         // determine vtable call index
450         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
451         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
452 #endif
453         VtableSlot aVtableSlot(
454                 getVtableSlot(
455                     reinterpret_cast<
456                     typelib_InterfaceAttributeTypeDescription const * >(
457                         pMemberDescr)));
458 
459         if (pReturn)
460         {
461             // dependent dispatch
462             cpp_call(
463                 pThis, aVtableSlot,
464                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
465                 0, 0, // no params
466                 pReturn, pArgs, ppException );
467         }
468         else
469         {
470             // is SET
471             typelib_MethodParameter aParam;
472             aParam.pTypeRef =
473                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
474             aParam.bIn      = sal_True;
475             aParam.bOut     = sal_False;
476 
477             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
478             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
479             typelib_typedescriptionreference_new(
480                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
481 
482             // dependent dispatch
483             aVtableSlot.index += 1; // get, then set method
484             cpp_call(
485                 pThis, aVtableSlot, // get, then set method
486                 pReturnTypeRef,
487                 1, &aParam,
488                 pReturn, pArgs, ppException );
489 
490             typelib_typedescriptionreference_release( pReturnTypeRef );
491         }
492 
493         break;
494     }
495     case typelib_TypeClass_INTERFACE_METHOD:
496     {
497 #if OSL_DEBUG_LEVEL > 0
498         // determine vtable call index
499         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
500         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
501 #endif
502         VtableSlot aVtableSlot(
503                 getVtableSlot(
504                     reinterpret_cast<
505                     typelib_InterfaceMethodTypeDescription const * >(
506                         pMemberDescr)));
507 
508         switch (aVtableSlot.index)
509         {
510             // standard calls
511         case 1: // acquire uno interface
512             (*pUnoI->acquire)( pUnoI );
513             *ppException = 0;
514             break;
515         case 2: // release uno interface
516             (*pUnoI->release)( pUnoI );
517             *ppException = 0;
518             break;
519         case 0: // queryInterface() opt
520         {
521             typelib_TypeDescription * pTD = 0;
522             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
523             if (pTD)
524             {
525                 uno_Interface * pInterface = 0;
526                 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
527                     pThis->getBridge()->getUnoEnv(),
528                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
529 
530                 if (pInterface)
531                 {
532                     ::uno_any_construct(
533                         reinterpret_cast< uno_Any * >( pReturn ),
534                         &pInterface, pTD, 0 );
535                     (*pInterface->release)( pInterface );
536                     TYPELIB_DANGER_RELEASE( pTD );
537                     *ppException = 0;
538                     break;
539                 }
540                 TYPELIB_DANGER_RELEASE( pTD );
541             }
542         } // else perform queryInterface()
543         default:
544             // dependent dispatch
545             cpp_call(
546                 pThis, aVtableSlot,
547                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
548                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
549                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
550                 pReturn, pArgs, ppException );
551         }
552         break;
553     }
554     default:
555     {
556         ::com::sun::star::uno::RuntimeException aExc(
557             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
558             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
559 
560         Type const & rExcType = ::getCppuType( &aExc );
561         // binary identical null reference
562         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
563     }
564     }
565 }
566 
567 } } }
568