Update ooo320-m1
[ooovba.git] / bridges / source / cpp_uno / gcc3_freebsd_x86-64 / uno2cpp.cxx
blob593a3e930d2f4f1c860b2804f480bb029711361e
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 $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_bridges.hxx"
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <rtl/alloc.h>
39 #include <com/sun/star/uno/genfunc.hxx>
40 #include "com/sun/star/uno/RuntimeException.hpp"
41 #include <uno/data.h>
43 #include <bridges/cpp_uno/shared/bridge.hxx>
44 #include <bridges/cpp_uno/shared/types.hxx>
45 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
46 #include "bridges/cpp_uno/shared/vtables.hxx"
48 #include "abi.hxx"
49 #include "share.hxx"
51 using namespace ::rtl;
52 using namespace ::com::sun::star::uno;
54 //==================================================================================================
55 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
56 void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn,
57 sal_uInt64 *pStack, sal_uInt32 nStack,
58 sal_uInt64 *pGPR, sal_uInt32 nGPR,
59 double *pFPR, sal_uInt32 nFPR) __attribute__((noinline));
61 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
62 void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn,
63 sal_uInt64 *pStack, sal_uInt32 nStack,
64 sal_uInt64 *pGPR, sal_uInt32 nGPR,
65 double *pFPR, sal_uInt32 nFPR)
67 #if OSL_DEBUG_LEVEL > 1
68 // Let's figure out what is really going on here
70 fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
71 for ( int i = 0; i < nGPR; ++i )
72 fprintf( stderr, "0x%lx, ", pGPR[i] );
73 fprintf( stderr, "\nFPR's (%d): ", nFPR );
74 for ( int i = 0; i < nFPR; ++i )
75 fprintf( stderr, "%f, ", pFPR[i] );
76 fprintf( stderr, "\nStack (%d): ", nStack );
77 for ( int i = 0; i < nStack; ++i )
78 fprintf( stderr, "0x%lx, ", pStack[i] );
79 fprintf( stderr, "\n" );
81 #endif
83 // The call instruction within the asm section of callVirtualMethod may throw
84 // exceptions. So that the compiler handles this correctly, it is important
85 // that (a) callVirtualMethod might call dummy_can_throw_anything (although this
86 // never happens at runtime), which in turn can throw exceptions, and (b)
87 // callVirtualMethod is not inlined at its call site (so that any exceptions are
88 // caught which are thrown from the instruction calling callVirtualMethod):
89 if ( !pThis )
90 CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something
92 // Should not happen, but...
93 if ( nFPR > x86_64::MAX_SSE_REGS )
94 nFPR = x86_64::MAX_SSE_REGS;
95 if ( nGPR > x86_64::MAX_GPR_REGS )
96 nGPR = x86_64::MAX_GPR_REGS;
98 // Get pointer to method
99 sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
100 pMethod += 8 * nVtableIndex;
101 pMethod = *((sal_uInt64 *)pMethod);
103 // Load parameters to stack, if necessary
104 if ( nStack )
106 // 16-bytes aligned
107 sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 16;
108 sal_uInt64 *pCallStack = (sal_uInt64 *) __builtin_alloca( nStackBytes );
109 memcpy( pCallStack, pStack, nStackBytes );
112 // Return values
113 sal_uInt64 rax;
114 sal_uInt64 rdx;
115 double xmm0;
117 asm volatile (
119 // Fill the xmm registers
120 "movq %2, %%rax\n\t"
122 "movsd (%%rax), %%xmm0\n\t"
123 "movsd 8(%%rax), %%xmm1\n\t"
124 "movsd 16(%%rax), %%xmm2\n\t"
125 "movsd 24(%%rax), %%xmm3\n\t"
126 "movsd 32(%%rax), %%xmm4\n\t"
127 "movsd 40(%%rax), %%xmm5\n\t"
128 "movsd 48(%%rax), %%xmm6\n\t"
129 "movsd 56(%%rax), %%xmm7\n\t"
131 // Fill the general purpose registers
132 "movq %1, %%rax\n\t"
134 "movq (%%rax), %%rdi\n\t"
135 "movq 8(%%rax), %%rsi\n\t"
136 "movq 16(%%rax), %%rdx\n\t"
137 "movq 24(%%rax), %%rcx\n\t"
138 "movq 32(%%rax), %%r8\n\t"
139 "movq 40(%%rax), %%r9\n\t"
141 // Perform the call
142 "movq %0, %%r11\n\t"
143 "movq %3, %%rax\n\t"
144 "call *%%r11\n\t"
146 // Fill the return values
147 "movq %%rax, %4\n\t"
148 "movq %%rdx, %5\n\t"
149 "movsd %%xmm0, %6\n\t"
151 : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR ),
152 "m" ( rax ), "m" ( rdx ), "m" ( xmm0 )
153 : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11"
156 switch (pReturnTypeDescr->eTypeClass)
158 case typelib_TypeClass_HYPER:
159 case typelib_TypeClass_UNSIGNED_HYPER:
160 *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = rax;
161 break;
162 case typelib_TypeClass_LONG:
163 case typelib_TypeClass_UNSIGNED_LONG:
164 case typelib_TypeClass_ENUM:
165 *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &rax );
166 break;
167 case typelib_TypeClass_CHAR:
168 case typelib_TypeClass_SHORT:
169 case typelib_TypeClass_UNSIGNED_SHORT:
170 *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &rax );
171 break;
172 case typelib_TypeClass_BOOLEAN:
173 case typelib_TypeClass_BYTE:
174 *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &rax );
175 break;
176 case typelib_TypeClass_FLOAT:
177 case typelib_TypeClass_DOUBLE:
178 *reinterpret_cast<double *>( pRegisterReturn ) = xmm0;
179 break;
180 default:
182 sal_Int32 const nRetSize = pReturnTypeDescr->nSize;
183 if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
185 if (nRetSize > 8)
186 static_cast<sal_uInt64 *>(pRegisterReturn)[1] = rdx;
187 static_cast<sal_uInt64 *>(pRegisterReturn)[0] = rax;
189 break;
194 //==================================================================================================
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]
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!
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 );
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 );
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 );
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 );
234 //==================================================================================================
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 )
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;
248 sal_uInt64 pGPR[x86_64::MAX_GPR_REGS];
249 sal_uInt32 nGPR = 0;
251 double pFPR[x86_64::MAX_SSE_REGS];
252 sal_uInt32 nFPR = 0;
254 // Return
255 typelib_TypeDescription * pReturnTypeDescr = 0;
256 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
257 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
259 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below)
261 bool bSimpleReturn = true;
262 if ( pReturnTypeDescr )
264 if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
265 bSimpleReturn = false;
267 if ( bSimpleReturn )
268 pCppReturn = pUnoReturn; // direct way for simple types
269 else
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 );
278 // Push "this" pointer
279 void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
280 INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
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));
289 sal_Int32 nTempIndizes = 0;
291 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
293 const typelib_MethodParameter & rParam = pParams[nPos];
294 typelib_TypeDescription * pParamTypeDescr = 0;
295 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
297 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
299 uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
300 pThis->getBridge()->getUno2Cpp() );
302 switch (pParamTypeDescr->eTypeClass)
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;
328 // no longer needed
329 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
331 else // ptr to complex value | ref
333 if (! rParam.bIn) // is pure out
335 // cpp out is constructed mem, uno out is not!
336 uno_constructData(
337 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
338 pParamTypeDescr );
339 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
340 // will be released at reconversion
341 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
343 // is in/inout
344 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
346 uno_copyAndConvertData(
347 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
348 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
350 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
351 // will be released at reconversion
352 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
354 else // direct way
356 pCppArgs[nPos] = pUnoArgs[nPos];
357 // no longer needed
358 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
360 INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
366 callVirtualMethod(
367 pAdjustedThisPtr, aVtableSlot.index,
368 pCppReturn, pReturnTypeDescr, bSimpleReturn,
369 pStackStart, ( pStack - pStackStart ),
370 pGPR, nGPR,
371 pFPR, nFPR );
372 // NO exception occured...
373 *ppUnoExc = 0;
375 // reconvert temporary params
376 for ( ; nTempIndizes--; )
378 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
379 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
381 if (pParams[nIndex].bIn)
383 if (pParams[nIndex].bOut) // inout
385 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
386 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
387 pThis->getBridge()->getCpp2Uno() );
390 else // pure out
392 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
393 pThis->getBridge()->getCpp2Uno() );
395 // destroy temp cpp param => cpp: every param was constructed
396 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
398 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
400 // return value
401 if (pCppReturn && pUnoReturn != pCppReturn)
403 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
404 pThis->getBridge()->getCpp2Uno() );
405 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
408 catch (...)
410 // fill uno exception
411 fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
413 // temporary params
414 for ( ; nTempIndizes--; )
416 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
417 // destroy temp cpp param => cpp: every param was constructed
418 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
419 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
421 // return type
422 if (pReturnTypeDescr)
423 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
427 //==================================================================================================
429 namespace bridges { namespace cpp_uno { namespace shared {
431 void unoInterfaceProxyDispatch(
432 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
433 void * pReturn, void * pArgs[], uno_Any ** ppException )
435 // is my surrogate
436 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
437 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
438 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
440 switch (pMemberDescr->eTypeClass)
442 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
444 // determine vtable call index
445 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
446 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
448 VtableSlot aVtableSlot(
449 getVtableSlot(
450 reinterpret_cast<
451 typelib_InterfaceAttributeTypeDescription const * >(
452 pMemberDescr)));
454 if (pReturn)
456 // dependent dispatch
457 cpp_call(
458 pThis, aVtableSlot,
459 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
460 0, 0, // no params
461 pReturn, pArgs, ppException );
463 else
465 // is SET
466 typelib_MethodParameter aParam;
467 aParam.pTypeRef =
468 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
469 aParam.bIn = sal_True;
470 aParam.bOut = sal_False;
472 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
473 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
474 typelib_typedescriptionreference_new(
475 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
477 // dependent dispatch
478 aVtableSlot.index += 1; // get, then set method
479 cpp_call(
480 pThis, aVtableSlot, // get, then set method
481 pReturnTypeRef,
482 1, &aParam,
483 pReturn, pArgs, ppException );
485 typelib_typedescriptionreference_release( pReturnTypeRef );
488 break;
490 case typelib_TypeClass_INTERFACE_METHOD:
492 // determine vtable call index
493 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
494 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
496 VtableSlot aVtableSlot(
497 getVtableSlot(
498 reinterpret_cast<
499 typelib_InterfaceMethodTypeDescription const * >(
500 pMemberDescr)));
502 switch (aVtableSlot.index)
504 // standard calls
505 case 1: // acquire uno interface
506 (*pUnoI->acquire)( pUnoI );
507 *ppException = 0;
508 break;
509 case 2: // release uno interface
510 (*pUnoI->release)( pUnoI );
511 *ppException = 0;
512 break;
513 case 0: // queryInterface() opt
515 typelib_TypeDescription * pTD = 0;
516 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
517 if (pTD)
519 uno_Interface * pInterface = 0;
520 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
521 pThis->getBridge()->getUnoEnv(),
522 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
524 if (pInterface)
526 ::uno_any_construct(
527 reinterpret_cast< uno_Any * >( pReturn ),
528 &pInterface, pTD, 0 );
529 (*pInterface->release)( pInterface );
530 TYPELIB_DANGER_RELEASE( pTD );
531 *ppException = 0;
532 break;
534 TYPELIB_DANGER_RELEASE( pTD );
536 } // else perform queryInterface()
537 default:
538 // dependent dispatch
539 cpp_call(
540 pThis, aVtableSlot,
541 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
542 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
543 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
544 pReturn, pArgs, ppException );
546 break;
548 default:
550 ::com::sun::star::uno::RuntimeException aExc(
551 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
552 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
554 Type const & rExcType = ::getCppuType( &aExc );
555 // binary identical null reference
556 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
561 } } }