xref: /trunk/main/bridges/source/cpp_uno/gcc3_freebsd_powerpc64/uno2cpp.cxx (revision 31bbceb0f9d64c0c2c3b22a794a1666c1f33396e)
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 <stdlib.h>
28 
29 #include <exception>
30 #include <malloc.h>
31 #include <typeinfo>
32 
33 #include <com/sun/star/uno/Exception.hpp>
34 #include <com/sun/star/uno/RuntimeException.hpp>
35 #include <com/sun/star/uno/genfunc.hxx>
36 #include <uno/data.h>
37 
38 #include "bridges/cpp_uno/shared/bridge.hxx"
39 #include "bridges/cpp_uno/shared/types.hxx"
40 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
41 #include "bridges/cpp_uno/shared/vtables.hxx"
42 
43 #include "share.hxx"
44 
45 #include <stdio.h>
46 #include <string.h>
47 
48 
49 using namespace ::rtl;
50 using namespace ::com::sun::star::uno;
51 #ifdef __GLIBCXX__
52 using CPPU_CURRENT_NAMESPACE::__cxa_exception;
53 using CPPU_CURRENT_NAMESPACE::__cxa_get_globals;
54 #else
55 using __cxxabiv1::__cxa_exception;
56 using __cxxabiv1::__cxa_current_primary_exception;
57 using __cxxabiv1::__cxa_decrement_exception_refcount;
58 #endif
59 
60 namespace ppc64
61 {
62 #if defined(_CALL_ELF) && _CALL_ELF == 2
63     bool is_complex_struct(const typelib_TypeDescription * type)
64     {
65         const typelib_CompoundTypeDescription * p
66             = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
67         for (sal_Int32 i = 0; i < p->nMembers; ++i)
68         {
69             if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
70                 p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
71             {
72                 typelib_TypeDescription * t = 0;
73                 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
74                 bool b = is_complex_struct(t);
75                 TYPELIB_DANGER_RELEASE(t);
76                 if (b) {
77                     return true;
78                 }
79             }
80             else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
81                 return true;
82         }
83         if (p->pBaseTypeDescription != 0)
84             return is_complex_struct(&p->pBaseTypeDescription->aBase);
85         return false;
86     }
87 #endif
88 
89     bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
90     {
91         if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
92             return false;
93 #if defined(_CALL_ELF) && _CALL_ELF == 2
94         else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
95         {
96             typelib_TypeDescription * pTypeDescr = 0;
97             TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
98 
99             //A Composite Type not larger than 16 bytes is returned in up to two GPRs
100             bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
101 
102             TYPELIB_DANGER_RELEASE( pTypeDescr );
103             return bRet;
104         }
105 #endif
106         return true;
107     }
108 }
109 
110 extern "C" void MapReturn(long r3, long r4, double dret, typelib_TypeDescriptionReference* pReturnType, void *pRegisterReturn)
111 {
112     switch (pReturnType->eTypeClass)
113     {
114     case typelib_TypeClass_HYPER:
115     case typelib_TypeClass_UNSIGNED_HYPER:
116             *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = r3;
117             break;
118     case typelib_TypeClass_LONG:
119     case typelib_TypeClass_UNSIGNED_LONG:
120     case typelib_TypeClass_ENUM:
121             *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = r3;
122             break;
123     case typelib_TypeClass_CHAR:
124     case typelib_TypeClass_SHORT:
125     case typelib_TypeClass_UNSIGNED_SHORT:
126             *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = (unsigned short)r3;
127             break;
128     case typelib_TypeClass_BOOLEAN:
129     case typelib_TypeClass_BYTE:
130             *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = (unsigned char)r3;
131             break;
132     case typelib_TypeClass_FLOAT:
133             *reinterpret_cast<float *>( pRegisterReturn ) = dret;
134         break;
135     case typelib_TypeClass_DOUBLE:
136             *reinterpret_cast<double *>( pRegisterReturn ) = dret;
137             break;
138 #if defined(_CALL_ELF) && _CALL_ELF == 2
139     case typelib_TypeClass_STRUCT:
140     case typelib_TypeClass_EXCEPTION:
141             if (!ppc64::return_in_hidden_param(pReturnType))
142             {
143                 sal_uInt64 *pRegisters = reinterpret_cast<sal_uInt64*>(pRegisterReturn);
144                 pRegisters[0] = r3;
145                 if (pReturnType->pType->nSize > 8)
146                     pRegisters[1] = r4;
147             }
148 #else
149     (void)r4;
150 #endif
151     default:
152             break;
153     }
154 }
155 
156 namespace
157 {
158 //==================================================================================================
159 extern "C" void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
160     void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr,
161         sal_uInt64 *pStack, sal_uInt32 nStack,
162         sal_uInt64 *pGPR, sal_uInt32 nGPR,
163         double *pFPR, sal_uInt32 nFPR);
164 
165 #if 0
166 {
167     // Stack, if used, must be 16-bytes aligned
168     if ( nStack )
169         nStack = ( nStack + 1 ) & ~1;
170 
171     // Should not happen, but...
172     if ( nFPR > ppc64::MAX_SSE_REGS )
173         nFPR = ppc64::MAX_SSE_REGS;
174     if ( nGPR > ppc64::MAX_GPR_REGS )
175         nGPR = ppc64::MAX_GPR_REGS;
176 
177 #ifdef CMC_DEBUG
178         // Let's figure out what is really going on here
179         {
180                 fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
181                 for ( sal_uInt32 i = 0; i < nGPR; ++i )
182                         fprintf( stderr, "0x%lx, ", pGPR[i] );
183                 fprintf( stderr, "\nFPR's (%d): ", nFPR );
184                 for ( sal_uInt32 i = 0; i < nFPR; ++i )
185                         fprintf( stderr, "0x%lx (%lf), ", (sal_Int64)pFPR[i], pFPR[i] );
186                 fprintf( stderr, "\nStack (%d): ", nStack );
187                 for ( sal_uInt32 i = 0; i < nStack; ++i )
188                         fprintf( stderr, "0x%lx, ", pStack[i] );
189                 fprintf( stderr, "\n" );
190         }
191 #endif
192 
193     // Load parameters to stack, if necessary
194     sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 );
195     memcpy( stack, pStack, nStack * 8 );
196 
197     // Get pointer to method
198     sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
199     pMethod += 8 * nVtableIndex;
200     pMethod = *((sal_uInt64 *)pMethod);
201 
202 #if defined(_CALL_ELF) && _CALL_ELF == 2
203     typedef void (* FunctionCall )(...);
204 #else
205     typedef void (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 );
206 #endif
207     FunctionCall pFunc = (FunctionCall)pMethod;
208 
209     volatile double dret;
210 
211     //  fill registers
212     __asm__ __volatile__ (
213                 "lfd  1,  0(%0)\n\t"
214                 "lfd  2,  8(%0)\n\t"
215                 "lfd  3, 16(%0)\n\t"
216                 "lfd  4, 24(%0)\n\t"
217                 "lfd  5, 32(%0)\n\t"
218                 "lfd  6, 40(%0)\n\t"
219                 "lfd  7, 48(%0)\n\t"
220                 "lfd  8, 56(%0)\n\t"
221                 "lfd  9, 64(%0)\n\t"
222                 "lfd 10, 72(%0)\n\t"
223                 "lfd 11, 80(%0)\n\t"
224                 "lfd 12, 88(%0)\n\t"
225                 "lfd 13, 96(%0)\n\t"
226                 : : "r" (pFPR)
227               : "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", "fr8", "fr9",
228                 "fr10", "fr11", "fr12", "fr13"
229     );
230 
231     // tell gcc that r3 to r11 are not available to it for doing the TOC and exception munge on the func call
232     register sal_uInt64 r3 asm("r3");
233     register sal_uInt64 r4 asm("r4");
234 
235     (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3], pGPR[4], pGPR[5], pGPR[6], pGPR[7]);
236 
237     // get return value
238     __asm__ __volatile__ (
239                 "mr     %1,     3\n\t"
240                 "mr     %2,     4\n\t"
241                 "fmr    %0,     1\n\t"
242                 : "=f" (dret), "=r" (r3), "=r" (r4) : );
243 
244     MapReturn(r3, r4, dret, reinterpret_cast<typelib_TypeDescriptionReference *>(pReturnTypeDescr), pRegisterReturn);
245 }
246 #endif
247 
248 // Macros for easier insertion of values to registers or stack
249 // pSV - pointer to the source
250 // nr - order of the value [will be increased if stored to register]
251 // pFPR, pGPR - pointer to the registers
252 // pDS - pointer to the stack [will be increased if stored here]
253 
254 // The value in %xmm register is already prepared to be retrieved as a float,
255 // thus we treat float and double the same
256 #define INSERT_FLOAT( pSV, nr, pFPR, nGPR, pDS, bOverFlow ) \
257         if ( nGPR < ppc64::MAX_GPR_REGS ) \
258                 ++nGPR;                   \
259         if ( nr < ppc64::MAX_SSE_REGS )   \
260                 pFPR[nr++] = *reinterpret_cast<float *>( pSV ); \
261         else \
262             bOverFlow = true; \
263         if (bOverFlow) \
264                 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
265 
266 #define INSERT_DOUBLE( pSV, nr, pFPR, nGPR, pDS, bOverFlow ) \
267         if ( nGPR < ppc64::MAX_GPR_REGS ) \
268                 ++nGPR;                   \
269         if ( nr < ppc64::MAX_SSE_REGS )   \
270                 pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
271         else \
272             bOverFlow = true; \
273         if (bOverFlow) \
274                 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
275 
276 #define INSERT_INT64( pSV, nr, pGPR, pDS, bOverFlow ) \
277         if ( nr < ppc64::MAX_GPR_REGS ) \
278                 pGPR[nr++] = *reinterpret_cast<sal_Int64 *>( pSV ); \
279         else \
280         bOverFlow = true; \
281     if (bOverFlow) \
282                 *pDS++ = *reinterpret_cast<sal_Int64 *>( pSV );
283 
284 #define INSERT_UINT64( pSV, nr, pGPR, pDS, bOverFlow ) \
285         if ( nr < ppc64::MAX_GPR_REGS ) \
286                 pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
287         else \
288         bOverFlow = true; \
289     if (bOverFlow) \
290                 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
291 
292 #define INSERT_INT32( pSV, nr, pGPR, pDS, bOverFlow ) \
293         if ( nr < ppc64::MAX_GPR_REGS ) \
294                 pGPR[nr++] = *reinterpret_cast<sal_Int32 *>( pSV ); \
295         else \
296                 bOverFlow = true; \
297         if (bOverFlow) \
298                 *pDS++ = *reinterpret_cast<sal_Int32 *>( pSV );
299 
300 #define INSERT_UINT32( pSV, nr, pGPR, pDS, bOverFlow ) \
301         if ( nr < ppc64::MAX_GPR_REGS ) \
302                 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
303         else \
304                 bOverFlow = true; \
305         if (bOverFlow) \
306                 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
307 
308 #define INSERT_INT16( pSV, nr, pGPR, pDS, bOverFlow ) \
309         if ( nr < ppc64::MAX_GPR_REGS ) \
310                 pGPR[nr++] = *reinterpret_cast<sal_Int16 *>( pSV ); \
311         else \
312                 bOverFlow = true; \
313         if (bOverFlow) \
314                 *pDS++ = *reinterpret_cast<sal_Int16 *>( pSV );
315 
316 #define INSERT_UINT16( pSV, nr, pGPR, pDS, bOverFlow ) \
317         if ( nr < ppc64::MAX_GPR_REGS ) \
318                 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
319         else \
320                 bOverFlow = true; \
321         if (bOverFlow) \
322                 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
323 
324 #define INSERT_INT8( pSV, nr, pGPR, pDS, bOverFlow ) \
325         if ( nr < ppc64::MAX_GPR_REGS ) \
326                 pGPR[nr++] = *reinterpret_cast<sal_Int8 *>( pSV ); \
327         else \
328                 bOverFlow = true; \
329         if (bOverFlow) \
330                 *pDS++ = *reinterpret_cast<sal_Int8 *>( pSV );
331 
332 #define INSERT_UINT8( pSV, nr, pGPR, pDS, bOverFlow ) \
333         if ( nr < ppc64::MAX_GPR_REGS ) \
334                 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
335         else \
336                 bOverFlow = true; \
337         if (bOverFlow) \
338                 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
339 
340 //==================================================================================================
341 static void cpp_call(
342     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
343     bridges::cpp_uno::shared::VtableSlot  aVtableSlot,
344     typelib_TypeDescriptionReference * pReturnTypeRef,
345     sal_Int32 nParams, typelib_MethodParameter * pParams,
346     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
347 {
348     // max space for: [complex ret ptr], values|ptr ...
349     sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+3) * sizeof(sal_Int64) );
350     sal_uInt64 * pStackStart = pStack;
351 
352     sal_uInt64 pGPR[ppc64::MAX_GPR_REGS];
353     sal_uInt32 nGPR = 0;
354 
355     double pFPR[ppc64::MAX_SSE_REGS];
356     sal_uInt32 nFPR = 0;
357 
358     // return
359     typelib_TypeDescription * pReturnTypeDescr = 0;
360     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
361     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
362 
363     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
364 
365         bool bOverFlow = false;
366 
367     if (pReturnTypeDescr)
368     {
369 #ifdef CMC_DEBUG
370         fprintf(stderr, "return type is %d\n", pReturnTypeDescr->eTypeClass);
371 #endif
372         if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
373         {
374             pCppReturn = pUnoReturn; // direct way for simple types
375 #ifdef CMC_DEBUG
376             fprintf(stderr, "simple return\n");
377 #endif
378         }
379         else
380         {
381             // complex return via ptr
382             pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
383                    ? alloca( pReturnTypeDescr->nSize ) : pUnoReturn);
384 #ifdef CMC_DEBUG
385             fprintf(stderr, "pCppReturn/pUnoReturn is %lx/%lx", pCppReturn, pUnoReturn);
386 #endif
387             INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack, bOverFlow );
388         }
389     }
390     // push "this" pointer
391         void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
392 #ifdef CMC_DEBUG
393     fprintf(stderr, "this pointer is %p\n", pAdjustedThisPtr);
394 #endif
395     INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow );
396 
397         // Args
398         void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
399     // indizes of values this have to be converted (interface conversion cpp<=>uno)
400     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
401     // type descriptions for reconversions
402     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
403 
404     sal_Int32 nTempIndizes   = 0;
405 
406 #ifdef CMC_DEBUG
407     fprintf(stderr, "n params is %d\n", nParams);
408 #endif
409 
410     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
411     {
412         const typelib_MethodParameter & rParam = pParams[nPos];
413         typelib_TypeDescription * pParamTypeDescr = 0;
414         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
415 
416 #ifdef CMC_DEBUG
417         fprintf(stderr, "param %d is %d %d %d\n", nPos, rParam.bOut, bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ),
418             pParamTypeDescr->eTypeClass);
419 #endif
420 
421         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
422         {
423 //          uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
424             uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], pParamTypeDescr,
425                                     pThis->getBridge()->getUno2Cpp() );
426                 switch (pParamTypeDescr->eTypeClass)
427                         {
428                         case typelib_TypeClass_HYPER:
429                         case typelib_TypeClass_UNSIGNED_HYPER:
430 #ifdef CMC_DEBUG
431                 fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]);
432 #endif
433                                 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
434                                 break;
435                         case typelib_TypeClass_LONG:
436                         case typelib_TypeClass_UNSIGNED_LONG:
437                         case typelib_TypeClass_ENUM:
438 #ifdef CMC_DEBUG
439                 fprintf(stderr, "long is %x\n", pCppArgs[nPos]);
440 #endif
441                                 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
442                                 break;
443                         case typelib_TypeClass_SHORT:
444                                 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
445                                 break;
446                         case typelib_TypeClass_CHAR:
447                         case typelib_TypeClass_UNSIGNED_SHORT:
448                                 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
449                                 break;
450                         case typelib_TypeClass_BOOLEAN:
451                                 INSERT_UINT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
452                                 break;
453                         case typelib_TypeClass_BYTE:
454                                 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
455                                 break;
456                         case typelib_TypeClass_FLOAT:
457                                 INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, nGPR, pStack, bOverFlow );
458                                 break;
459                         case typelib_TypeClass_DOUBLE:
460                                 INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, nGPR, pStack, bOverFlow );
461                                 break;
462                         }
463 
464                         // no longer needed
465                         TYPELIB_DANGER_RELEASE( pParamTypeDescr );
466 
467         }
468         else // ptr to complex value | ref
469         {
470 #ifdef CMC_DEBUG
471             fprintf(stderr, "complex type again %d\n", rParam.bIn);
472 #endif
473                         if (! rParam.bIn) // is pure out
474                         {
475 #ifdef CMC_DEBUG
476                 fprintf(stderr, "complex size is %d\n", pParamTypeDescr->nSize );
477 #endif
478                                 // cpp out is constructed mem, uno out is not!
479                                 uno_constructData(
480                                         pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
481                                         pParamTypeDescr );
482                                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
483                                 // will be released at reconversion
484                                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
485                         }
486                         // is in/inout
487                         else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
488                         {
489 #ifdef CMC_DEBUG
490                 fprintf(stderr, "this one\n");
491 #endif
492                                 uno_copyAndConvertData(
493                                         pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
494                                         pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
495 
496                                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
497                                 // will be released at reconversion
498                                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
499                         }
500                         else // direct way
501                         {
502 #ifdef CMC_DEBUG
503                 fprintf(stderr, "that one, passing %lx through\n", pUnoArgs[nPos]);
504 #endif
505                                 pCppArgs[nPos] = pUnoArgs[nPos];
506                                 // no longer needed
507                                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
508                         }
509                         INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow );
510         }
511     }
512 
513     try
514     {
515                callVirtualMethod(
516                         pAdjustedThisPtr, aVtableSlot.index,
517                         pCppReturn, pReturnTypeDescr,
518                         pStackStart, ( pStack - pStackStart ),
519                         pGPR, nGPR,
520                         pFPR, nFPR );
521         // NO exception occurred...
522         *ppUnoExc = 0;
523 
524         // reconvert temporary params
525         for ( ; nTempIndizes--; )
526         {
527             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
528             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
529 
530             if (pParams[nIndex].bIn)
531             {
532                 if (pParams[nIndex].bOut) // inout
533                 {
534                     uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
535                     uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
536                                             pThis->getBridge()->getCpp2Uno() );
537                 }
538             }
539             else // pure out
540             {
541                 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
542                                         pThis->getBridge()->getCpp2Uno() );
543             }
544             // destroy temp cpp param => cpp: every param was constructed
545             uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
546 
547             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
548         }
549         // return value
550         if (pCppReturn && pUnoReturn != pCppReturn)
551         {
552             uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
553                                     pThis->getBridge()->getCpp2Uno() );
554             uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
555         }
556     }
557     catch (...)
558     {
559         __cxa_exception *header;
560 #ifdef __GLIBCXX__
561         header = __cxa_get_globals()->caughtExceptions;
562 #else
563         header = reinterpret_cast<__cxa_exception *>( __cxa_current_primary_exception() );
564         if (header) {
565             __cxa_decrement_exception_refcount( header );
566             header--;
567         }
568 #endif
569         // fill uno exception
570         CPPU_CURRENT_NAMESPACE::fillUnoException( header, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
571 
572         // temporary params
573         for ( ; nTempIndizes--; )
574         {
575             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
576             // destroy temp cpp param => cpp: every param was constructed
577             uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
578             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
579         }
580         // return type
581         if (pReturnTypeDescr)
582             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
583     }
584 }
585 
586 }
587 
588 namespace bridges { namespace cpp_uno { namespace shared {
589 
590 void unoInterfaceProxyDispatch(
591     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
592     void * pReturn, void * pArgs[], uno_Any ** ppException )
593 {
594     // is my surrogate
595         ::bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
596             = static_cast< ::bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI);
597     typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
598 
599     switch (pMemberDescr->eTypeClass)
600     {
601     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
602     {
603 
604         ::bridges::cpp_uno::shared::VtableSlot aVtableSlot(
605             ::bridges::cpp_uno::shared::getVtableSlot(
606                 reinterpret_cast<
607                     typelib_InterfaceAttributeTypeDescription const * >(
608                         pMemberDescr)));
609 
610         if (pReturn)
611         {
612             // dependent dispatch
613             cpp_call(
614                 pThis, aVtableSlot,
615                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
616                 0, 0, // no params
617                 pReturn, pArgs, ppException );
618         }
619         else
620         {
621             // is SET
622             typelib_MethodParameter aParam;
623             aParam.pTypeRef =
624                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
625             aParam.bIn      = sal_True;
626             aParam.bOut     = sal_False;
627 
628             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
629             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
630             typelib_typedescriptionreference_new(
631                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
632 
633             // dependent dispatch
634                         aVtableSlot.index += 1; //get then set method
635             cpp_call(
636                 pThis, aVtableSlot,
637                 pReturnTypeRef,
638                 1, &aParam,
639                 pReturn, pArgs, ppException );
640 
641             typelib_typedescriptionreference_release( pReturnTypeRef );
642         }
643 
644         break;
645     }
646     case typelib_TypeClass_INTERFACE_METHOD:
647     {
648 
649         ::bridges::cpp_uno::shared::VtableSlot aVtableSlot(
650             ::bridges::cpp_uno::shared::getVtableSlot(
651                 reinterpret_cast<
652                     typelib_InterfaceMethodTypeDescription const * >(
653                         pMemberDescr)));
654         switch (aVtableSlot.index)
655         {
656             // standard calls
657         case 1: // acquire uno interface
658             (*pUnoI->acquire)( pUnoI );
659             *ppException = 0;
660             break;
661         case 2: // release uno interface
662             (*pUnoI->release)( pUnoI );
663             *ppException = 0;
664             break;
665         case 0: // queryInterface() opt
666         {
667             typelib_TypeDescription * pTD = 0;
668             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
669             if (pTD)
670             {
671                 uno_Interface * pInterface = 0;
672                 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
673                     pThis->pBridge->getUnoEnv(),
674                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
675 
676                 if (pInterface)
677                 {
678                     ::uno_any_construct(
679                         reinterpret_cast< uno_Any * >( pReturn ),
680                         &pInterface, pTD, 0 );
681                     (*pInterface->release)( pInterface );
682                     TYPELIB_DANGER_RELEASE( pTD );
683                     *ppException = 0;
684                     break;
685                 }
686                 TYPELIB_DANGER_RELEASE( pTD );
687             }
688         } // else perform queryInterface()
689         default:
690             // dependent dispatch
691             cpp_call(
692                 pThis, aVtableSlot,
693                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
694                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
695                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
696                 pReturn, pArgs, ppException );
697         }
698         break;
699     }
700     default:
701     {
702         ::com::sun::star::uno::RuntimeException aExc(
703             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
704             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
705 
706         Type const & rExcType = ::getCppuType( &aExc );
707         // binary identical null reference
708         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
709     }
710     }
711 }
712 
713 } } }
714