Bump for 3.6-28
[LibreOffice.git] / bridges / source / cpp_uno / gcc3_ios_arm / cpp2uno.cxx
blob9e6fba0dfc50704a7d71126b13539d524797342b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <com/sun/star/uno/genfunc.hxx>
31 #include "com/sun/star/uno/RuntimeException.hpp"
32 #include "com/sun/star/uno/Sequence.hxx"
33 #include <uno/data.h>
34 #include <typelib/typedescription.hxx>
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"
41 #include "share.hxx"
43 #include "boost/static_assert.hpp"
44 #include <stdio.h>
46 using namespace ::com::sun::star::uno;
48 namespace
51 //==================================================================================================
52 void cpp2uno_call(
53 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
54 const typelib_TypeDescription * pMemberTypeDescr,
55 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
56 sal_Int32 nParams, typelib_MethodParameter * pParams,
57 void ** pCallStack,
58 void * pReturnValue )
60 // pCallStack: ret, [return ptr], this, params
61 char * pCppStack = (char *)(pCallStack +1);
63 // return
64 typelib_TypeDescription * pReturnTypeDescr = 0;
65 if (pReturnTypeRef)
66 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
68 void * pUnoReturn = 0;
69 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
71 if (pReturnTypeDescr)
73 // xxx todo: test PolyStructy<STRUCT<long>> foo()
74 if (
75 #ifdef __arm
76 !arm::return_in_hidden_param(pReturnTypeRef)
77 #else
78 CPPU_CURRENT_NAMESPACE::isSimpleReturnType( pReturnTypeDescr )
79 #endif
82 pUnoReturn = pReturnValue; // direct way for simple types
84 else // complex return via ptr (pCppReturn)
86 pCppReturn = *(void **)pCppStack;
87 pCppStack += sizeof(void *);
88 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
89 pReturnTypeDescr )
90 ? alloca( pReturnTypeDescr->nSize )
91 : pCppReturn); // direct way
94 // pop this
95 pCppStack += sizeof( void* );
97 // stack space
98 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
99 // parameters
100 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
101 void ** pCppArgs = pUnoArgs + nParams;
102 // indizes of values this have to be converted (interface conversion cpp<=>uno)
103 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
104 // type descriptions for reconversions
105 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
107 sal_Int32 nTempIndizes = 0;
109 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
111 const typelib_MethodParameter & rParam = pParams[nPos];
112 typelib_TypeDescription * pParamTypeDescr = 0;
113 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
115 if (!rParam.bOut
116 && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
117 // value
119 pCppArgs[nPos] = pCppStack;
120 pUnoArgs[nPos] = pCppStack;
121 switch (pParamTypeDescr->eTypeClass)
123 case typelib_TypeClass_HYPER:
124 case typelib_TypeClass_UNSIGNED_HYPER:
125 case typelib_TypeClass_DOUBLE:
126 pCppStack += sizeof(sal_Int32); // extra long
127 default:
128 break;
130 // no longer needed
131 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
133 else // ptr to complex value | ref
135 pCppArgs[nPos] = *(void **)pCppStack;
137 if (! rParam.bIn) // is pure out
139 // uno out is unconstructed mem!
140 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
141 pTempIndizes[nTempIndizes] = nPos;
142 // will be released at reconversion
143 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
145 // is in/inout
146 else if (bridges::cpp_uno::shared::relatesToInterfaceType(
147 pParamTypeDescr ))
149 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
150 *(void **)pCppStack, pParamTypeDescr,
151 pThis->getBridge()->getCpp2Uno() );
152 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
153 // will be released at reconversion
154 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
156 else // direct way
158 pUnoArgs[nPos] = *(void **)pCppStack;
159 // no longer needed
160 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
163 pCppStack += sizeof(sal_Int32); // standard parameter length
166 // ExceptionHolder
167 uno_Any aUnoExc; // Any will be constructed by callee
168 uno_Any * pUnoExc = &aUnoExc;
170 // invoke uno dispatch call
171 (*pThis->getUnoI()->pDispatcher)(
172 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
174 // in case an exception occurred...
175 if (pUnoExc)
177 // destruct temporary in/inout params
178 for ( ; nTempIndizes--; )
180 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
182 if (pParams[nIndex].bIn) // is in/inout => was constructed
183 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
184 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
186 if (pReturnTypeDescr)
187 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
189 CPPU_CURRENT_NAMESPACE::raiseException(
190 &aUnoExc, pThis->getBridge()->getUno2Cpp() );
191 // has to destruct the any
193 else // else no exception occurred...
195 // temporary params
196 for ( ; nTempIndizes--; )
198 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
199 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
201 if (pParams[nIndex].bOut) // inout/out
203 // convert and assign
204 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
205 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
206 pThis->getBridge()->getUno2Cpp() );
208 // destroy temp uno param
209 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
211 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
213 // return
214 if (pCppReturn) // has complex return
216 if (pUnoReturn != pCppReturn) // needs reconversion
218 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
219 pThis->getBridge()->getUno2Cpp() );
220 // destroy temp uno return
221 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
223 if (pReturnValue != pCppReturn) {
224 // complex return ptr is set to eax if return value
225 // is not transferred via eax[/edx]:
226 *static_cast< void ** >(pReturnValue) = pCppReturn;
229 if (pReturnTypeDescr)
231 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
237 //==================================================================================================
238 extern "C" void cpp_vtable_call(
239 int nFunctionIndex, int nVtableOffset, void** pCallStack,
240 void * pReturnValue )
242 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
244 // pCallStack: ret adr, [ret *], this, params
245 void * pThis;
246 if( nFunctionIndex & 0x80000000 )
248 nFunctionIndex &= 0x7fffffff;
249 pThis = pCallStack[2];
251 else
253 pThis = pCallStack[1];
255 pThis = static_cast< char * >(pThis) - nVtableOffset;
256 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
257 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
258 pThis);
259 #if OSL_DEBUG_LEVEL > 1
260 fprintf( stderr, "%p %p %p pThis=%p, pCppI=%p, function index=%d, vtable offset=%d\n", pCallStack[0], pCallStack[1], pCallStack[2], pThis, pCppI, nFunctionIndex, nVtableOffset );
261 #endif
262 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
263 #if OSL_DEBUG_LEVEL > 1
264 fprintf( stderr, "name=%s\n", rtl::OUStringToOString(pTypeDescr->aBase.pTypeName, RTL_TEXTENCODING_UTF8).getStr() );
265 #endif
266 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
267 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
269 throw RuntimeException(
270 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )),
271 (XInterface *)pThis );
274 // determine called method
275 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
276 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
278 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
279 #if OSL_DEBUG_LEVEL > 1
280 fprintf(stderr, "calling %s\n", rtl::OUStringToOString(aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_UTF8).getStr());
281 #endif
282 switch (aMemberDescr.get()->eTypeClass)
284 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
286 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
288 // is GET method
289 cpp2uno_call(
290 pCppI, aMemberDescr.get(),
291 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
292 0, 0, // no params
293 pCallStack, pReturnValue );
295 else
297 // is SET method
298 typelib_MethodParameter aParam;
299 aParam.pTypeRef =
300 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
301 aParam.bIn = sal_True;
302 aParam.bOut = sal_False;
304 cpp2uno_call(
305 pCppI, aMemberDescr.get(),
306 0, // indicates void return
307 1, &aParam,
308 pCallStack, pReturnValue );
310 break;
312 case typelib_TypeClass_INTERFACE_METHOD:
314 // is METHOD
315 switch (nFunctionIndex)
317 case 1: // acquire()
318 pCppI->acquireProxy(); // non virtual call!
319 break;
320 case 2: // release()
321 pCppI->releaseProxy(); // non virtual call!
322 break;
323 case 0: // queryInterface() opt
325 typelib_TypeDescription * pTD = 0;
326 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() );
327 if (pTD)
329 XInterface * pInterface = 0;
330 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
331 pCppI->getBridge()->getCppEnv(),
332 (void **)&pInterface, pCppI->getOid().pData,
333 (typelib_InterfaceTypeDescription *)pTD );
335 if (pInterface)
337 ::uno_any_construct(
338 reinterpret_cast< uno_Any * >( pCallStack[1] ),
339 &pInterface, pTD, cpp_acquire );
340 pInterface->release();
341 TYPELIB_DANGER_RELEASE( pTD );
342 *static_cast< void ** >(pReturnValue) = pCallStack[1];
343 break;
345 TYPELIB_DANGER_RELEASE( pTD );
347 } // else perform queryInterface()
348 default:
349 cpp2uno_call(
350 pCppI, aMemberDescr.get(),
351 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
352 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
353 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
354 pCallStack, pReturnValue );
356 break;
358 default:
360 throw RuntimeException(
361 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )),
362 (XInterface *)pThis );
367 //==================================================================================================
368 extern "C" {
369 extern int nFunIndexes, nVtableOffsets;
370 extern int codeSnippets[];
373 unsigned char * codeSnippet(
374 sal_Int32 functionIndex, sal_Int32 vtableOffset,
375 #ifdef __arm
376 bool bHasHiddenParam
377 #else
378 typelib_TypeDescriptionReference * pReturnTypeRef
379 #endif
382 OSL_ASSERT(functionIndex < nFunIndexes);
383 if (!(functionIndex < nFunIndexes))
384 return NULL;
386 OSL_ASSERT(vtableOffset < nVtableOffsets);
387 if (!(vtableOffset < nVtableOffsets))
388 return NULL;
390 #ifdef __arm
391 return ((unsigned char *) &codeSnippets) + codeSnippets[functionIndex*nVtableOffsets*2 + vtableOffset*2 + bHasHiddenParam];
392 #else
393 enum { General, Void, Hyper, Float, Double, Class } exec;
394 bool bHasHiddenParam = false;
395 if (pReturnTypeRef == 0) {
396 exec = Void;
398 else {
399 switch (pReturnTypeRef->eTypeClass) {
400 case typelib_TypeClass_VOID:
401 exec = Void;
402 break;
403 case typelib_TypeClass_HYPER:
404 case typelib_TypeClass_UNSIGNED_HYPER:
405 exec = Hyper;
406 break;
407 case typelib_TypeClass_FLOAT:
408 exec = Float;
409 break;
410 case typelib_TypeClass_DOUBLE:
411 exec = Double;
412 break;
413 case typelib_TypeClass_STRUCT:
414 case typelib_TypeClass_EXCEPTION: {
415 typelib_TypeDescription * pReturnTypeDescr = 0;
416 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
417 bool const bSimpleReturnStruct =
418 CPPU_CURRENT_NAMESPACE::isSimpleReturnType(pReturnTypeDescr);
419 sal_Int32 const nRetSize = pReturnTypeDescr->nSize;
420 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
421 if (bSimpleReturnStruct && nRetSize <= 8) {
422 exec = General; // fills eax
423 if (nRetSize > 4)
424 exec = Hyper; // fills eax/edx
425 break;
428 case typelib_TypeClass_STRING:
429 case typelib_TypeClass_TYPE:
430 case typelib_TypeClass_SEQUENCE:
431 case typelib_TypeClass_INTERFACE:
432 case typelib_TypeClass_ANY:
433 bHasHiddenParam = 1;
434 exec = Class;
435 break;
436 default:
437 exec = General;
438 break;
442 // The codeSnippets table is indexed by functionIndex, vtableOffset, exec and flag
444 fprintf(stderr, "Indexing codeSnippets with %ld [%ld,%ld,%d,%d]\n",
445 functionIndex*nVtableOffsets*6*2 + vtableOffset*6*2 + exec*2 + bHasHiddenParam,
446 functionIndex, vtableOffset, (int) exec, bHasHiddenParam);
447 return ((unsigned char *) &codeSnippets) + codeSnippets[functionIndex*nVtableOffsets*6*2 + vtableOffset*6*2 + exec*2 + bHasHiddenParam];
448 #endif
453 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
455 bridges::cpp_uno::shared::VtableFactory::Slot *
456 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
458 return static_cast< Slot * >(block) + 2;
461 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
462 sal_Int32 slotCount)
464 #ifdef __arm
466 #else
467 return (slotCount + 2) * sizeof (Slot);
468 #endif
471 bridges::cpp_uno::shared::VtableFactory::Slot *
472 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
473 void * block, sal_Int32 slotCount)
475 Slot * slots = mapBlockToVtable(block);
476 slots[-2].fn = 0;
477 slots[-1].fn = 0;
478 return slots + slotCount;
481 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
482 Slot ** slots, unsigned char * code,
483 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
484 sal_Int32 functionCount, sal_Int32 vtableOffset)
486 (*slots) -= functionCount;
487 Slot * s = *slots;
488 for (sal_Int32 i = 0; i < type->nMembers; ++i) {
489 typelib_TypeDescription * member = 0;
490 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
491 OSL_ASSERT(member != 0);
492 switch (member->eTypeClass) {
493 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
494 #ifdef __arm
495 typelib_InterfaceAttributeTypeDescription *pAttrTD =
496 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member );
497 #endif
498 // Getter:
499 (s++)->fn = codeSnippet(
500 functionOffset++, vtableOffset,
501 #ifdef __arm
502 arm::return_in_hidden_param( pAttrTD->pAttributeTypeRef )
503 #else
504 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
505 member)->pAttributeTypeRef
506 #endif
508 // Setter:
509 if (!reinterpret_cast<
510 typelib_InterfaceAttributeTypeDescription * >(
511 member)->bReadOnly)
513 (s++)->fn = codeSnippet(
514 functionOffset++, vtableOffset,
515 #ifdef __arm
516 false
517 #else
518 0 /* indicates VOID */
519 #endif
522 break;
524 case typelib_TypeClass_INTERFACE_METHOD:
525 #ifdef __arm
526 typelib_InterfaceMethodTypeDescription *pMethodTD =
527 reinterpret_cast<
528 typelib_InterfaceMethodTypeDescription * >(member);
529 #endif
530 (s++)->fn = codeSnippet(
531 functionOffset++, vtableOffset,
532 #ifdef __arm
533 arm::return_in_hidden_param(pMethodTD->pReturnTypeRef)
534 #else
535 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
536 member)->pReturnTypeRef
537 #endif
539 break;
541 default:
542 OSL_ASSERT(false);
543 break;
545 TYPELIB_DANGER_RELEASE(member);
547 return code;
550 void bridges::cpp_uno::shared::VtableFactory::flushCode(
551 unsigned char const *, unsigned char const *)
555 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */