merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / cpp_uno / gcc3_linux_s390x / uno2cpp.cxx
blob36d178c61ea03d6a9174ce1445d2e5a4927c9cc2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: uno2cpp.cxx,v $
11 * $Revision: 1.3 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_bridges.hxx"
35 #include <malloc.h>
37 #include <com/sun/star/uno/genfunc.hxx>
38 #include <uno/data.h>
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"
45 #include "share.hxx"
47 #include <stdio.h>
48 #include <string.h>
51 using namespace ::rtl;
52 using namespace ::com::sun::star::uno;
54 void MapReturn(long r2, double f0, typelib_TypeClass eTypeClass, sal_uInt64* pRegisterReturn)
56 #ifdef CMC_DEBUG
57 fprintf(stderr,"Mapping Return with %lx %ld %f\n", r2, r2, f0);
58 #endif
59 switch (eTypeClass)
61 case typelib_TypeClass_HYPER:
62 case typelib_TypeClass_UNSIGNED_HYPER:
63 case typelib_TypeClass_LONG:
64 case typelib_TypeClass_UNSIGNED_LONG:
65 case typelib_TypeClass_ENUM:
66 *pRegisterReturn = r2;
67 break;
68 case typelib_TypeClass_CHAR:
69 case typelib_TypeClass_SHORT:
70 case typelib_TypeClass_UNSIGNED_SHORT:
71 *pRegisterReturn = (unsigned short)r2;
72 break;
73 case typelib_TypeClass_BOOLEAN:
74 case typelib_TypeClass_BYTE:
75 *pRegisterReturn = (unsigned char)r2;
76 break;
77 case typelib_TypeClass_FLOAT:
78 *reinterpret_cast<float *>( pRegisterReturn ) = f0;
79 break;
80 case typelib_TypeClass_DOUBLE:
81 *reinterpret_cast<double *>( pRegisterReturn ) = f0;
82 break;
83 default:
84 break;
86 #ifdef CMC_DEBUG
87 fprintf(stderr, "end of MapReturn with %x\n", pRegisterReturn ? *pRegisterReturn : 0);
88 #endif
91 #define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \
92 { \
93 float tmp = *reinterpret_cast<float *>( pSV ); \
94 if ( nr < s390x::MAX_SSE_REGS ) \
95 { \
96 pFPR[nr++] = *reinterpret_cast<float *>( pSV ); \
97 } \
98 else \
99 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); \
102 #define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \
103 if ( nr < s390x::MAX_SSE_REGS ) \
104 pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
105 else \
106 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
108 #define INSERT_INT64( pSV, nr, pGPR, pDS ) \
109 if ( nr < s390x::MAX_GPR_REGS ) \
110 pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
111 else \
112 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
114 #define INSERT_INT32( pSV, nr, pGPR, pDS ) \
115 if ( nr < s390x::MAX_GPR_REGS ) \
116 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
117 else \
118 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
120 #define INSERT_INT16( pSV, nr, pGPR, pDS ) \
121 if ( nr < s390x::MAX_GPR_REGS ) \
122 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
123 else \
124 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
126 #define INSERT_INT8( pSV, nr, pGPR, pDS ) \
127 if ( nr < s390x::MAX_GPR_REGS ) \
128 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
129 else \
130 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
132 namespace
134 //==================================================================================================
135 void callVirtualMethod(
136 void * pThis, sal_Int32 nVtableIndex,
137 void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr,
138 sal_uInt64 *pStack, sal_uInt32 nStack,
139 sal_uInt64 *pGPR, sal_uInt32 nGPR,
140 double *pFPR, sal_uInt32 nFPR)
142 // Should not happen, but...
143 if ( nFPR > s390x::MAX_SSE_REGS )
144 nFPR = s390x::MAX_SSE_REGS;
145 if ( nGPR > s390x::MAX_GPR_REGS )
146 nGPR = s390x::MAX_GPR_REGS;
148 #ifdef CMC_DEBUG
149 // Let's figure out what is really going on here
151 fprintf( stderr, "= nStack is %d\n", nStack );
152 fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
153 for ( unsigned int i = 0; i < nGPR; ++i )
154 fprintf( stderr, "0x%lx, ", pGPR[i] );
155 fprintf( stderr, "\nFPR's (%d): ", nFPR );
156 for ( unsigned int i = 0; i < nFPR; ++i )
157 fprintf( stderr, "0x%lx (%f), ", pFPR[i], pFPR[i] );
158 fprintf( stderr, "\nStack (%d): ", nStack );
159 for ( unsigned int i = 0; i < nStack; ++i )
160 fprintf( stderr, "0x%lx, ", pStack[i] );
161 fprintf( stderr, "\n" );
162 fprintf( stderr, "pRegisterReturn is %p\n", pRegisterReturn);
164 #endif
166 // Load parameters to stack, if necessary
167 // Stack, if used, must be 8-bytes aligned
168 sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 );
169 memcpy( stack, pStack, nStack * 8 );
171 // To get pointer to method
172 // a) get the address of the vtable
173 sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
174 // b) get the address from the vtable entry at offset
175 pMethod += 8 * nVtableIndex;
176 pMethod = *((sal_uInt64 *)pMethod);
178 typedef void (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 );
179 FunctionCall pFunc = (FunctionCall)pMethod;
181 switch (nFPR) //deliberate fall through
183 case 4:
184 asm volatile("ld 6,%0" :: "m"(pFPR[3]) : "16");
185 case 3:
186 asm volatile("ld 4,%0" :: "m"(pFPR[2]) : "16");
187 case 2:
188 asm volatile("ld 2,%0" :: "m"(pFPR[1]) : "16");
189 case 1:
190 asm volatile("ld 0,%0" :: "m"(pFPR[0]) : "16");
191 default:
192 break;
195 volatile long r2;
196 volatile double f0;
198 (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3], pGPR[4]);
200 __asm__ __volatile__ (
201 "lgr %0,2\n\t"
202 "ldr %1,0\n\t"
203 : "=r" (r2), "=f" (f0)
207 MapReturn(r2, f0, pReturnTypeDescr->eTypeClass, (sal_uInt64*)pRegisterReturn);
211 //============================================================================
212 static void cpp_call(
213 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
214 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
215 typelib_TypeDescriptionReference * pReturnTypeRef,
216 sal_Int32 nParams, typelib_MethodParameter * pParams,
217 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
219 // max space for: [complex ret ptr], values|ptr ...
220 sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+3) * sizeof(sal_Int64) );
221 sal_uInt64 * pStackStart = pStack;
223 sal_uInt64 pGPR[s390x::MAX_GPR_REGS];
224 sal_uInt32 nGPR = 0;
226 double pFPR[s390x::MAX_SSE_REGS];
227 sal_uInt32 nFPR = 0;
229 // return
230 typelib_TypeDescription * pReturnTypeDescr = 0;
231 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
232 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
234 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
236 if (pReturnTypeDescr)
238 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
240 pCppReturn = pUnoReturn; // direct way for simple types
242 else
244 // complex return via ptr
245 pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
246 ? alloca( pReturnTypeDescr->nSize )
247 : pUnoReturn); // direct way
248 INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack );
251 // push "this" pointer
252 void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
254 INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
256 // stack space
257 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int64), "### unexpected size!" );
258 // args
259 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
260 // indizes of values this have to be converted (interface conversion cpp<=>uno)
261 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
262 // type descriptions for reconversions
263 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
265 sal_Int32 nTempIndizes = 0;
267 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
269 const typelib_MethodParameter & rParam = pParams[nPos];
270 typelib_TypeDescription * pParamTypeDescr = 0;
271 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
273 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
275 uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
276 pThis->getBridge()->getUno2Cpp() );
278 switch (pParamTypeDescr->eTypeClass)
280 case typelib_TypeClass_HYPER:
281 case typelib_TypeClass_UNSIGNED_HYPER:
282 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
283 break;
284 case typelib_TypeClass_LONG:
285 case typelib_TypeClass_UNSIGNED_LONG:
286 case typelib_TypeClass_ENUM:
287 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
288 break;
289 case typelib_TypeClass_SHORT:
290 case typelib_TypeClass_CHAR:
291 case typelib_TypeClass_UNSIGNED_SHORT:
292 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
293 break;
294 case typelib_TypeClass_BOOLEAN:
295 case typelib_TypeClass_BYTE:
296 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
297 break;
298 case typelib_TypeClass_FLOAT:
299 INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, pStack );
300 break;
301 case typelib_TypeClass_DOUBLE:
302 INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
303 break;
304 default:
305 break;
308 // no longer needed
309 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
311 else // ptr to complex value | ref
313 if (! rParam.bIn) // is pure out
315 // cpp out is constructed mem, uno out is not!
316 uno_constructData(
317 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
318 pParamTypeDescr );
319 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
320 // will be released at reconversion
321 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
323 // is in/inout
324 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
326 uno_copyAndConvertData(
327 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
328 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
330 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
331 // will be released at reconversion
332 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
334 else // direct way
336 pCppArgs[nPos] = pUnoArgs[nPos];
337 // no longer needed
338 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
340 INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
346 callVirtualMethod(
347 pAdjustedThisPtr, aVtableSlot.index,
348 pCppReturn, pReturnTypeDescr,
349 pStackStart, (pStack - pStackStart),
350 pGPR, nGPR,
351 pFPR, nFPR );
352 // NO exception occured...
353 *ppUnoExc = 0;
355 // reconvert temporary params
356 for ( ; nTempIndizes--; )
358 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
359 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
361 if (pParams[nIndex].bIn)
363 if (pParams[nIndex].bOut) // inout
365 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
366 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
367 pThis->getBridge()->getCpp2Uno() );
370 else // pure out
372 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
373 pThis->getBridge()->getCpp2Uno() );
375 // destroy temp cpp param => cpp: every param was constructed
376 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
378 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
380 // return value
381 if (pCppReturn && pUnoReturn != pCppReturn)
383 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
384 pThis->getBridge()->getCpp2Uno() );
385 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
388 catch (...)
390 // fill uno exception
391 fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions,
392 *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
395 // temporary params
396 for ( ; nTempIndizes--; )
398 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
399 // destroy temp cpp param => cpp: every param was constructed
400 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
401 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
403 // return type
404 if (pReturnTypeDescr)
405 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
410 namespace bridges { namespace cpp_uno { namespace shared {
412 void unoInterfaceProxyDispatch(
413 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
414 void * pReturn, void * pArgs[], uno_Any ** ppException )
416 #ifdef CMC_DEBUG
417 fprintf(stderr, "unoInterfaceProxyDispatch\n");
418 #endif
421 // is my surrogate
422 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
423 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI);
424 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
426 switch (pMemberDescr->eTypeClass)
428 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
431 VtableSlot aVtableSlot(
432 getVtableSlot(
433 reinterpret_cast<
434 typelib_InterfaceAttributeTypeDescription const * >(
435 pMemberDescr)));
437 if (pReturn)
439 // dependent dispatch
440 cpp_call(
441 pThis, aVtableSlot,
442 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
443 0, 0, // no params
444 pReturn, pArgs, ppException );
446 else
448 // is SET
449 typelib_MethodParameter aParam;
450 aParam.pTypeRef =
451 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
452 aParam.bIn = sal_True;
453 aParam.bOut = sal_False;
455 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
456 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
457 typelib_typedescriptionreference_new(
458 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
460 // dependent dispatch
461 aVtableSlot.index += 1; //get then set method
462 cpp_call(
463 pThis, aVtableSlot,
464 pReturnTypeRef,
465 1, &aParam,
466 pReturn, pArgs, ppException );
468 typelib_typedescriptionreference_release( pReturnTypeRef );
471 break;
473 case typelib_TypeClass_INTERFACE_METHOD:
476 VtableSlot aVtableSlot(
477 getVtableSlot(
478 reinterpret_cast<
479 typelib_InterfaceMethodTypeDescription const * >(
480 pMemberDescr)));
481 switch (aVtableSlot.index)
483 // standard calls
484 case 1: // acquire uno interface
485 (*pUnoI->acquire)( pUnoI );
486 *ppException = 0;
487 break;
488 case 2: // release uno interface
489 (*pUnoI->release)( pUnoI );
490 *ppException = 0;
491 break;
492 case 0: // queryInterface() opt
494 typelib_TypeDescription * pTD = 0;
495 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
496 if (pTD)
498 uno_Interface * pInterface = 0;
499 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
500 pThis->pBridge->getUnoEnv(),
501 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
503 if (pInterface)
505 ::uno_any_construct(
506 reinterpret_cast< uno_Any * >( pReturn ),
507 &pInterface, pTD, 0 );
508 (*pInterface->release)( pInterface );
509 TYPELIB_DANGER_RELEASE( pTD );
510 *ppException = 0;
511 break;
513 TYPELIB_DANGER_RELEASE( pTD );
515 } // else perform queryInterface()
516 default:
517 // dependent dispatch
518 cpp_call(
519 pThis, aVtableSlot,
520 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
521 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
522 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
523 pReturn, pArgs, ppException );
525 break;
527 default:
529 ::com::sun::star::uno::RuntimeException aExc(
530 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
531 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
533 Type const & rExcType = ::getCppuType( &aExc );
534 // binary identical null reference
535 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
540 } } }
541 /* vi:set tabstop=4 shiftwidth=4 expandtab: */