merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / cpp_uno / gcc3_linux_arm / cpp2uno.cxx
blobab71329fc6a2037e6b26347bcad1ac796414f355
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.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 #include <malloc.h>
32 #include <hash_map>
34 #include <rtl/alloc.h>
35 #include <osl/mutex.hxx>
37 #include <com/sun/star/uno/genfunc.hxx>
38 #include "com/sun/star/uno/RuntimeException.hpp"
39 #include <uno/data.h>
40 #include <typelib/typedescription.hxx>
42 #include "bridges/cpp_uno/shared/bridge.hxx"
43 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
44 #include "bridges/cpp_uno/shared/types.hxx"
45 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
47 #include "share.hxx"
49 #include <dlfcn.h>
52 using namespace ::osl;
53 using namespace ::rtl;
54 using namespace ::com::sun::star::uno;
56 namespace
59 static typelib_TypeClass cpp2uno_call(
60 bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
61 const typelib_TypeDescription * pMemberTypeDescr,
62 typelib_TypeDescriptionReference * pReturnTypeRef,
63 sal_Int32 nParams, typelib_MethodParameter * pParams,
64 void ** pCallStack,
65 sal_Int64 * pRegisterReturn /* space for register return */ )
67 // pCallStack: ret, [return ptr], this, params
68 char * pTopStack = (char *)(pCallStack + 0);
69 char * pCppStack = pTopStack;
71 // return
72 typelib_TypeDescription * pReturnTypeDescr = 0;
73 if (pReturnTypeRef)
74 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
76 void * pUnoReturn = 0;
77 // complex return ptr: if != 0 && != pUnoReturn, reconversion need
78 void * pCppReturn = 0;
80 if (pReturnTypeDescr)
82 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
84 pUnoReturn = pRegisterReturn; // direct way for simple types
86 else // complex return via ptr (pCppReturn)
88 pCppReturn = *(void **)pCppStack;
89 pCppStack += sizeof(void *);
91 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
92 pReturnTypeDescr )
93 ? alloca( pReturnTypeDescr->nSize )
94 : pCppReturn); // direct way
97 // pop this
98 pCppStack += sizeof( void* );
100 // stack space
101 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32),
102 "### unexpected size!" );
103 // parameters
104 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
105 void ** pCppArgs = pUnoArgs + nParams;
106 // indizes of values this have to be converted (interface conversion
107 // cpp<=>uno)
108 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
109 // type descriptions for reconversions
110 typelib_TypeDescription ** ppTempParamTypeDescr =
111 (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
113 sal_Int32 nTempIndizes = 0;
115 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
117 const typelib_MethodParameter & rParam = pParams[nPos];
118 typelib_TypeDescription * pParamTypeDescr = 0;
119 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
121 if (!rParam.bOut &&
122 bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
124 #ifdef __ARM_EABI__
125 switch (pParamTypeDescr->eTypeClass)
127 case typelib_TypeClass_HYPER:
128 case typelib_TypeClass_UNSIGNED_HYPER:
129 case typelib_TypeClass_DOUBLE:
130 if ((pCppStack - pTopStack) % 8) pCppStack+=sizeof(sal_Int32); //align to 8
131 break;
132 default:
133 break;
135 #endif
137 pCppArgs[nPos] = pCppStack;
138 pUnoArgs[nPos] = pCppStack;
139 switch (pParamTypeDescr->eTypeClass)
141 case typelib_TypeClass_HYPER:
142 case typelib_TypeClass_UNSIGNED_HYPER:
143 case typelib_TypeClass_DOUBLE:
144 pCppStack += sizeof(sal_Int32); // extra long
145 break;
146 default:
147 break;
149 // no longer needed
150 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
152 else // ptr to complex value | ref
154 pCppArgs[nPos] = *(void **)pCppStack;
156 if (! rParam.bIn) // is pure out
158 // uno out is unconstructed mem!
159 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
160 pTempIndizes[nTempIndizes] = nPos;
161 // will be released at reconversion
162 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
164 // is in/inout
165 else if (bridges::cpp_uno::shared::relatesToInterfaceType(
166 pParamTypeDescr ))
168 uno_copyAndConvertData( pUnoArgs[nPos] =
169 alloca( pParamTypeDescr->nSize ),
170 *(void **)pCppStack, pParamTypeDescr,
171 pThis->getBridge()->getCpp2Uno() );
172 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
173 // will be released at reconversion
174 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
176 else // direct way
178 pUnoArgs[nPos] = *(void **)pCppStack;
179 // no longer needed
180 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
183 pCppStack += sizeof(sal_Int32); // standard parameter length
186 // ExceptionHolder
187 uno_Any aUnoExc; // Any will be constructed by callee
188 uno_Any * pUnoExc = &aUnoExc;
190 // invoke uno dispatch call
191 (*pThis->getUnoI()->pDispatcher)(
192 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
194 // in case an exception occured...
195 if (pUnoExc)
197 // destruct temporary in/inout params
198 for ( ; nTempIndizes--; )
200 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
202 if (pParams[nIndex].bIn) // is in/inout => was constructed
203 uno_destructData( pUnoArgs[nIndex],
204 ppTempParamTypeDescr[nTempIndizes], 0 );
205 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
207 if (pReturnTypeDescr)
208 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
210 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc,
211 pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
212 // is here for dummy
213 return typelib_TypeClass_VOID;
215 else // else no exception occured...
217 // temporary params
218 for ( ; nTempIndizes--; )
220 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
221 typelib_TypeDescription * pParamTypeDescr =
222 ppTempParamTypeDescr[nTempIndizes];
224 if (pParams[nIndex].bOut) // inout/out
226 // convert and assign
227 uno_destructData( pCppArgs[nIndex], pParamTypeDescr,
228 cpp_release );
229 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex],
230 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
232 // destroy temp uno param
233 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
235 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
237 // return
238 if (pCppReturn) // has complex return
240 if (pUnoReturn != pCppReturn) // needs reconversion
242 uno_copyAndConvertData( pCppReturn, pUnoReturn,
243 pReturnTypeDescr, pThis->getBridge()->getUno2Cpp() );
244 // destroy temp uno return
245 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
247 // complex return ptr is set to eax
248 *(void **)pRegisterReturn = pCppReturn;
250 if (pReturnTypeDescr)
252 typelib_TypeClass eRet =
253 (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
254 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
255 return eRet;
257 else
258 return typelib_TypeClass_VOID;
263 //=====================================================================
264 static typelib_TypeClass cpp_mediate(
265 sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
266 void ** pCallStack,
267 sal_Int64 * pRegisterReturn /* space for register return */ )
269 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
271 // pCallStack: [ret *], this, params
272 // _this_ ptr is patched cppu_XInterfaceProxy object
273 void *pThis;
274 if( nFunctionIndex & 0x80000000 )
276 nFunctionIndex &= 0x7fffffff;
277 pThis = pCallStack[1];
279 else
281 pThis = pCallStack[0];
284 pThis = static_cast< char * >(pThis) - nVtableOffset;
285 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
286 bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
287 pThis);
289 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
291 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
292 "### illegal vtable index!" );
293 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
295 throw RuntimeException(
296 OUString::createFromAscii("illegal vtable index!"),
297 (XInterface *)pCppI );
300 // determine called method
301 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
302 "### illegal vtable index!" );
303 sal_Int32 nMemberPos =
304 pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
305 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers,
306 "### illegal member index!" );
308 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
310 typelib_TypeClass eRet;
311 switch (aMemberDescr.get()->eTypeClass)
313 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
315 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] ==
316 nFunctionIndex)
318 // is GET method
319 eRet = cpp2uno_call(
320 pCppI, aMemberDescr.get(),
321 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
322 0, 0, // no params
323 pCallStack, pRegisterReturn );
325 else
327 // is SET method
328 typelib_MethodParameter aParam;
329 aParam.pTypeRef =
330 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
331 aParam.bIn = sal_True;
332 aParam.bOut = sal_False;
334 eRet = cpp2uno_call(
335 pCppI, aMemberDescr.get(),
336 0, // indicates void return
337 1, &aParam,
338 pCallStack, pRegisterReturn );
340 break;
342 case typelib_TypeClass_INTERFACE_METHOD:
344 // is METHOD
345 switch (nFunctionIndex)
347 case 1: // acquire()
348 pCppI->acquireProxy(); // non virtual call!
349 eRet = typelib_TypeClass_VOID;
350 break;
351 case 2: // release()
352 pCppI->releaseProxy(); // non virtual call!
353 eRet = typelib_TypeClass_VOID;
354 break;
355 case 0: // queryInterface() opt
357 typelib_TypeDescription * pTD = 0;
358 TYPELIB_DANGER_GET(&pTD,
359 reinterpret_cast<Type *>(pCallStack[2])->getTypeLibType());
360 if (pTD)
362 XInterface * pInterface = 0;
363 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
364 pCppI->getBridge()->getCppEnv(),
365 (void **)&pInterface, pCppI->getOid().pData,
366 (typelib_InterfaceTypeDescription *)pTD );
368 if (pInterface)
370 ::uno_any_construct(
371 reinterpret_cast< uno_Any * >( pCallStack[0] ),
372 &pInterface, pTD, cpp_acquire );
373 pInterface->release();
374 TYPELIB_DANGER_RELEASE( pTD );
375 *(void **)pRegisterReturn = pCallStack[0];
376 eRet = typelib_TypeClass_ANY;
377 break;
379 TYPELIB_DANGER_RELEASE( pTD );
381 } // else perform queryInterface()
382 default:
383 eRet = cpp2uno_call(
384 pCppI, aMemberDescr.get(),
385 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
386 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
387 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
388 pCallStack, pRegisterReturn );
390 break;
392 default:
394 throw RuntimeException(
395 OUString::createFromAscii("no member description found!"),
396 (XInterface *)pCppI );
397 // is here for dummy
398 eRet = typelib_TypeClass_VOID;
402 return eRet;
406 //=======================================================================
408 * is called on incoming vtable calls
409 * (called by asm snippets)
412 extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset,
413 void **pCallStack )
415 sal_Int64 nRegReturn;
416 cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack,
417 &nRegReturn );
418 return nRegReturn;
421 extern "C" void privateSnippetExecutor(void);
423 namespace
425 const int codeSnippetSize = 20;
427 unsigned char *codeSnippet(unsigned char* code, sal_Int32 functionIndex,
428 sal_Int32 vtableOffset, bool simple_ret_type )
430 if (!simple_ret_type)
431 functionIndex |= 0x80000000;
433 unsigned long * p = (unsigned long *)code;
435 *p++ = 0xE1A0C00F;
436 *p++ = 0xE59FF004;
437 *p++ = (unsigned long)functionIndex;
438 *p++ = (unsigned long)vtableOffset;
439 *p++ = (unsigned long)privateSnippetExecutor;
441 return code + codeSnippetSize;
445 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
447 bridges::cpp_uno::shared::VtableFactory::Slot *
448 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
450 return static_cast< Slot * >(block) + 2;
453 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
454 sal_Int32 slotCount)
456 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
459 bridges::cpp_uno::shared::VtableFactory::Slot *
460 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
461 void * block, sal_Int32 slotCount)
463 Slot * slots = mapBlockToVtable(block);
464 slots[-2].fn = 0;
465 slots[-1].fn = 0;
466 return slots + slotCount;
469 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
470 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
471 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
472 sal_Int32 functionCount, sal_Int32 vtableOffset)
474 (*slots) -= functionCount;
475 Slot * s = *slots;
476 for (sal_Int32 i = 0; i < type->nMembers; ++i)
478 typelib_TypeDescription * member = 0;
479 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
480 OSL_ASSERT(member != 0);
481 switch (member->eTypeClass)
483 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
484 // Getter:
485 (s++)->fn = code + writetoexecdiff;
486 code = codeSnippet(
487 code, functionOffset++, vtableOffset,
488 bridges::cpp_uno::shared::isSimpleType(
489 reinterpret_cast<
490 typelib_InterfaceAttributeTypeDescription * >(
491 member)->pAttributeTypeRef));
492 // Setter:
493 if (!reinterpret_cast<
494 typelib_InterfaceAttributeTypeDescription * >(
495 member)->bReadOnly)
497 (s++)->fn = code + writetoexecdiff;
498 code = codeSnippet(
499 code, functionOffset++, vtableOffset, true);
501 break;
502 case typelib_TypeClass_INTERFACE_METHOD:
504 (s++)->fn = code + writetoexecdiff;
506 typelib_InterfaceMethodTypeDescription *pMethodTD =
507 reinterpret_cast<
508 typelib_InterfaceMethodTypeDescription * >(member);
510 bool issimple = bridges::cpp_uno::shared::isSimpleType(
511 pMethodTD->pReturnTypeRef);
513 code = codeSnippet(code, functionOffset++, vtableOffset,
514 issimple);
515 break;
517 default:
518 OSL_ASSERT(false);
519 break;
521 TYPELIB_DANGER_RELEASE(member);
523 return code;
526 void bridges::cpp_uno::shared::VtableFactory::flushCode(
527 unsigned char const *beg, unsigned char const *end)
529 static void (*clear_cache)(unsigned char const*, unsigned char const*)
530 = (void (*)(unsigned char const*, unsigned char const*))
531 dlsym(RTLD_DEFAULT, "__clear_cache");
532 (*clear_cache)(beg, end);
535 /* vi:set tabstop=4 shiftwidth=4 expandtab: */