merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / cpp_uno / gcc3_linux_sparc / cpp2uno.cxx
blob3292116b0be870f4406b1677fd2181dc2bfd7633
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: cpp2uno.cxx,v $
10 * $Revision: 1.14 $
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"
33 #include <com/sun/star/uno/genfunc.hxx>
34 #include <typelib/typedescription.hxx>
35 #include <uno/data.h>
36 #include "bridges/cpp_uno/shared/bridge.hxx"
37 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
38 #include "bridges/cpp_uno/shared/types.hxx"
39 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
40 #include "share.hxx"
42 using namespace com::sun::star::uno;
44 namespace
46 //==================================================================================================
47 static typelib_TypeClass cpp2uno_call(
48 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
49 const typelib_TypeDescription * pMemberTypeDescr,
50 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
51 sal_Int32 nParams, typelib_MethodParameter * pParams,
52 void ** pCallStack,
53 sal_Int64 * pRegisterReturn /* space for register return */ )
55 // pCallStack: [ret ptr], this, params
56 char * pCppStack = (char *)pCallStack;
58 // return
59 typelib_TypeDescription * pReturnTypeDescr = 0;
60 if (pReturnTypeRef)
61 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
63 void * pUnoReturn = 0;
64 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
66 if (pReturnTypeDescr)
68 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
69 pUnoReturn = pRegisterReturn; // direct way for simple types
70 else // complex return via ptr (pCppReturn)
72 pCppReturn = *(void**)pCppStack;
73 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
74 pReturnTypeDescr )
75 ? alloca( pReturnTypeDescr->nSize )
76 : pCppReturn); // direct way
77 pCppStack += sizeof( void* );
80 // pop this
81 pCppStack += sizeof( void* );
83 // stack space
84 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
85 // parameters
86 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
87 void ** pCppArgs = pUnoArgs + nParams;
88 // indizes of values this have to be converted (interface conversion cpp<=>uno)
89 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
90 // type descriptions for reconversions
91 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
93 sal_Int32 nTempIndizes = 0;
95 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
97 const typelib_MethodParameter & rParam = pParams[nPos];
98 typelib_TypeDescription * pParamTypeDescr = 0;
99 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
101 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value
103 pCppArgs[nPos] = pUnoArgs[nPos] = CPPU_CURRENT_NAMESPACE::adjustPointer(pCppStack, pParamTypeDescr);
104 switch (pParamTypeDescr->eTypeClass)
106 case typelib_TypeClass_HYPER:
107 case typelib_TypeClass_UNSIGNED_HYPER:
108 case typelib_TypeClass_DOUBLE:
110 if ((reinterpret_cast< long >(pCppStack) & 7) != 0)
112 OSL_ASSERT( sizeof (double) == sizeof (sal_Int64) );
113 void * pDest = alloca( sizeof (sal_Int64) );
114 *reinterpret_cast< sal_Int32 * >(pDest) =
115 *reinterpret_cast< sal_Int32 const * >(pCppStack);
116 *(reinterpret_cast< sal_Int32 * >(pDest) + 1) =
117 *(reinterpret_cast< sal_Int32 const * >(pCppStack) + 1);
118 pCppArgs[nPos] = pUnoArgs[nPos] = pDest;
120 pCppStack += sizeof (sal_Int32); // extra long
121 break;
122 default:
123 break;
126 // no longer needed
127 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
129 else // ptr to complex value | ref
131 pCppArgs[nPos] = *(void **)pCppStack;
133 if (! rParam.bIn) // is pure out
135 // uno out is unconstructed mem!
136 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
137 pTempIndizes[nTempIndizes] = nPos;
138 // will be released at reconversion
139 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
141 // is in/inout
142 else if (bridges::cpp_uno::shared::relatesToInterfaceType(
143 pParamTypeDescr ))
145 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
146 *(void **)pCppStack, pParamTypeDescr,
147 pThis->getBridge()->getCpp2Uno() );
148 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
149 // will be released at reconversion
150 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
152 else // direct way
154 pUnoArgs[nPos] = *(void **)pCppStack;
155 // no longer needed
156 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
159 pCppStack += sizeof(sal_Int32); // standard parameter length
162 // ExceptionHolder
163 uno_Any aUnoExc; // Any will be constructed by callee
164 uno_Any * pUnoExc = &aUnoExc;
166 // invoke uno dispatch call
167 (*pThis->getUnoI()->pDispatcher)(pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
169 // in case an exception occured...
170 if (pUnoExc)
172 // destruct temporary in/inout params
173 for ( ; nTempIndizes--; )
175 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
177 if (pParams[nIndex].bIn) // is in/inout => was constructed
178 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
179 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
181 if (pReturnTypeDescr)
182 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
183 CPPU_CURRENT_NAMESPACE::raiseException(&aUnoExc, pThis->getBridge()->getUno2Cpp() );
184 // has to destruct the any
185 // is here for dummy
186 return typelib_TypeClass_VOID;
188 else // else no exception occured...
190 // temporary params
191 for ( ; nTempIndizes--; )
193 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
194 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
196 if (pParams[nIndex].bOut) // inout/out
198 // convert and assign
199 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
200 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
201 pThis->getBridge()->getUno2Cpp() );
203 // destroy temp uno param
204 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
206 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
208 // return
209 if (pCppReturn) // has complex return
211 if (pUnoReturn != pCppReturn) // needs reconversion
213 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
214 pThis->getBridge()->getUno2Cpp() );
215 // destroy temp uno return
216 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
218 // complex return ptr is set to eax
219 *(void **)pRegisterReturn = pCppReturn;
221 if (pReturnTypeDescr)
223 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
224 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
225 return eRet;
227 else
228 return typelib_TypeClass_VOID;
233 //==================================================================================================
234 static typelib_TypeClass cpp_mediate(
235 sal_Int32 nFunctionIndex,
236 sal_Int32 nVtableOffset,
237 void ** pCallStack,
238 sal_Int64 * pRegisterReturn /* space for register return */ )
240 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
242 // pCallStack: this, params
243 // eventual [ret*] lies at pCallStack -1
244 // so count down pCallStack by one to keep it simple
245 // pCallStack: this, params
246 // eventual [ret*] lies at pCallStack -1
247 // so count down pCallStack by one to keep it simple
248 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
249 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
250 static_cast< char * >(*pCallStack) - nVtableOffset);
251 if ((nFunctionIndex & 0x80000000) != 0) {
252 nFunctionIndex &= 0x7FFFFFFF;
253 --pCallStack;
256 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
258 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
259 "### illegal vtable index!" );
260 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
262 throw RuntimeException( rtl::OUString::createFromAscii("illegal vtable index!"), (XInterface *)pCppI );
265 // determine called method
266 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
267 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
269 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
271 #if defined BRIDGES_DEBUG
272 OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
273 fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
274 #endif
276 typelib_TypeClass eRet;
277 switch (aMemberDescr.get()->eTypeClass)
279 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
281 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
283 // is GET method
284 eRet = cpp2uno_call(
285 pCppI, aMemberDescr.get(),
286 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
287 0, 0, // no params
288 pCallStack, pRegisterReturn );
290 else
292 // is SET method
293 typelib_MethodParameter aParam;
294 aParam.pTypeRef =
295 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
296 aParam.bIn = sal_True;
297 aParam.bOut = sal_False;
299 eRet = cpp2uno_call(
300 pCppI, aMemberDescr.get(),
301 0, // indicates void return
302 1, &aParam,
303 pCallStack, pRegisterReturn );
305 break;
307 case typelib_TypeClass_INTERFACE_METHOD:
309 // is METHOD
310 switch (nFunctionIndex)
312 case 1: // acquire()
313 pCppI->acquireProxy(); // non virtual call!
314 eRet = typelib_TypeClass_VOID;
315 break;
316 case 2: // release()
317 pCppI->releaseProxy(); // non virtual call!
318 eRet = typelib_TypeClass_VOID;
319 break;
320 case 0: // queryInterface() opt
322 typelib_TypeDescription * pTD = 0;
323 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[2] )->getTypeLibType() );
324 if (pTD)
326 XInterface * pInterface = 0;
327 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
328 pCppI->getBridge()->getCppEnv(),
329 (void **)&pInterface, pCppI->getOid().pData, (typelib_InterfaceTypeDescription *)pTD );
331 if (pInterface)
333 ::uno_any_construct(
334 reinterpret_cast< uno_Any * >( pCallStack[0] ),
335 &pInterface, pTD, cpp_acquire );
336 pInterface->release();
337 TYPELIB_DANGER_RELEASE( pTD );
338 *(void **)pRegisterReturn = pCallStack[0];
339 eRet = typelib_TypeClass_ANY;
340 break;
342 TYPELIB_DANGER_RELEASE( pTD );
344 } // else perform queryInterface()
345 default:
346 eRet = cpp2uno_call(
347 pCppI, aMemberDescr.get(),
348 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
349 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
350 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
351 pCallStack, pRegisterReturn );
353 break;
355 default:
357 throw RuntimeException(rtl::OUString::createFromAscii("no member description found!"), (XInterface *)pCppI );
358 // is here for dummy
359 eRet = typelib_TypeClass_VOID;
362 return eRet;
367 //==================================================================================================
369 * is called on incoming vtable calls
370 * (called by asm snippets)
372 static void cpp_vtable_call()
374 sal_Int64 nRegReturn;
375 int nFunctionIndex;
376 void** pCallStack;
377 int vTableOffset;
379 void * pRegReturn = &nRegReturn;
381 __asm__( "st %%i0, %0\n\t"
382 "st %%i1, %1\n\t"
383 "st %%i2, %2\n\t"
384 : : "m"(nFunctionIndex), "m"(pCallStack), "m"(vTableOffset) );
386 // fprintf(stderr,"cpp_mediate nFunctionIndex=%x\n",nFunctionIndex);
387 // fflush(stderr);
389 sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
390 typelib_TypeClass aType =
391 cpp_mediate( nFunctionIndex, vTableOffset, pCallStack+17, (sal_Int64*)&nRegReturn );
393 switch( aType )
395 case typelib_TypeClass_BOOLEAN:
396 case typelib_TypeClass_BYTE:
397 __asm__( "ld %0, %%l0\n\t"
398 "ldsb [%%l0], %%i0\n"
399 : : "m"(pRegReturn) );
400 break;
401 case typelib_TypeClass_CHAR:
402 case typelib_TypeClass_SHORT:
403 case typelib_TypeClass_UNSIGNED_SHORT:
404 __asm__( "ld %0, %%l0\n\t"
405 "ldsh [%%l0], %%i0\n"
406 : : "m"(pRegReturn) );
407 break;
408 case typelib_TypeClass_HYPER:
409 case typelib_TypeClass_UNSIGNED_HYPER:
410 __asm__( "ld %0, %%l0\n\t"
411 "ld [%%l0], %%i0\n\t"
412 "add %%l0, 4, %%l0\n\t"
413 "ld [%%l0], %%i1\n\t"
414 : : "m"(pRegReturn) );
416 break;
417 case typelib_TypeClass_FLOAT:
418 __asm__( "ld %0, %%l0\n\t"
419 "ld [%%l0], %%f0\n"
420 : : "m"(pRegReturn) );
421 break;
422 case typelib_TypeClass_DOUBLE:
423 __asm__( "ld %0, %%l0\n\t"
424 "ldd [%%l0], %%f0\n"
425 : : "m"(pRegReturn) );
426 break;
427 case typelib_TypeClass_VOID:
428 break;
429 default:
430 __asm__( "ld %0, %%l0\n\t"
431 "ld [%%l0], %%i0\n"
432 : : "m"(pRegReturn) );
433 break;
436 if( bComplex )
438 __asm__( "add %i7, 4, %i7\n\t" );
439 // after call to complex return valued funcion there is an unimp instruction
443 //__________________________________________________________________________________________________
445 int const codeSnippetSize = 56;
446 unsigned char * codeSnippet(
447 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
448 bool simpleRetType)
450 sal_uInt32 index = functionIndex;
451 if (!simpleRetType) {
452 index |= 0x80000000;
454 unsigned int * p = reinterpret_cast< unsigned int * >(code);
455 OSL_ASSERT(sizeof (unsigned int) == 4);
456 // st %o0, [%sp+68]:
457 *p++ = 0xD023A044;
458 // st %o1, [%sp+72]:
459 *p++ = 0xD223A048;
460 // st %o2, [%sp+76]:
461 *p++ = 0xD423A04C;
462 // st %o3, [%sp+80]:
463 *p++ = 0xD623A050;
464 // st %o4, [%sp+84]:
465 *p++ = 0xD823A054;
466 // st %o5, [%sp+88]:
467 *p++ = 0xDA23A058;
468 // sethi %hi(index), %o0:
469 *p++ = 0x11000000 | (index >> 10);
470 // or %o0, %lo(index), %o0:
471 *p++ = 0x90122000 | (index & 0x3FF);
472 // sethi %hi(vtableOffset), %o2:
473 *p++ = 0x15000000 | (vtableOffset >> 10);
474 // or %o2, %lo(vtableOffset), %o2:
475 *p++ = 0x9412A000 | (vtableOffset & 0x3FF);
476 // sethi %hi(cpp_vtable_call), %o3:
477 *p++ = 0x17000000 | (reinterpret_cast< unsigned int >(cpp_vtable_call) >> 10);
478 // or %o3, %lo(cpp_vtable_call), %o3:
479 *p++ = 0x9612E000 | (reinterpret_cast< unsigned int >(cpp_vtable_call) & 0x3FF);
480 // jmpl %o3, %g0:
481 *p++ = 0x81C2C000;
482 // mov %sp, %o1:
483 *p++ = 0x9210000E;
484 OSL_ASSERT(
485 reinterpret_cast< unsigned char * >(p) - code <= codeSnippetSize);
486 return code + codeSnippetSize;
489 } //end of namespace
491 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
493 bridges::cpp_uno::shared::VtableFactory::Slot *
494 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
496 return static_cast< Slot * >(block) + 2;
499 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
500 sal_Int32 slotCount)
502 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
505 bridges::cpp_uno::shared::VtableFactory::Slot *
506 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
507 void * block, sal_Int32 slotCount)
509 Slot * slots = mapBlockToVtable(block);
510 slots[-2].fn = 0; //null
511 slots[-1].fn = 0; //destructor
512 return slots + slotCount;
515 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
516 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
517 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
518 sal_Int32 functionCount, sal_Int32 vTableOffset)
520 (*slots) -= functionCount;
521 Slot * s = *slots;
522 for (sal_Int32 i = 0; i < type->nMembers; ++i) {
523 typelib_TypeDescription * member = 0;
524 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
525 OSL_ASSERT(member != 0);
526 switch (member->eTypeClass) {
527 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
528 // Getter:
529 (s++)->fn = code + writetoexecdiff;
530 code = codeSnippet(
531 code, functionOffset++, vTableOffset,
532 bridges::cpp_uno::shared::isSimpleType(
533 reinterpret_cast<
534 typelib_InterfaceAttributeTypeDescription * >(
535 member)->pAttributeTypeRef));
536 // Setter:
537 if (!reinterpret_cast<
538 typelib_InterfaceAttributeTypeDescription * >(
539 member)->bReadOnly)
541 (s++)->fn = code + writetoexecdiff;
542 code = codeSnippet(code, functionOffset++, vTableOffset, true);
544 break;
546 case typelib_TypeClass_INTERFACE_METHOD:
547 (s++)->fn = code + writetoexecdiff;
548 code = codeSnippet(
549 code, functionOffset++, vTableOffset,
550 bridges::cpp_uno::shared::isSimpleType(
551 reinterpret_cast<
552 typelib_InterfaceMethodTypeDescription * >(
553 member)->pReturnTypeRef));
554 break;
556 default:
557 OSL_ASSERT(false);
558 break;
560 TYPELIB_DANGER_RELEASE(member);
562 return code;
565 // use flush code from cc50_solaris_sparc
567 extern "C" void doFlushCode(unsigned long address, unsigned long count);
569 void bridges::cpp_uno::shared::VtableFactory::flushCode(
570 unsigned char const * begin, unsigned char const * end)
572 unsigned long n = end - begin;
573 if (n != 0) {
574 unsigned long adr = reinterpret_cast< unsigned long >(begin);
575 unsigned long off = adr & 7;
576 doFlushCode(adr - off, (n + off + 7) >> 3);