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