Update ooo320-m1
[ooovba.git] / bridges / source / cpp_uno / gcc3_solaris_intel / cpp2uno.cxx
blob4466220aec444cc1402a6d5be0adb411b855aa11
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.8 $
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 <sal/alloca.h>
36 #include <com/sun/star/uno/genfunc.hxx>
37 #include "com/sun/star/uno/RuntimeException.hpp"
38 #include <uno/data.h>
39 #include <typelib/typedescription.hxx>
41 #include "bridges/cpp_uno/shared/bridge.hxx"
42 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
43 #include "bridges/cpp_uno/shared/types.hxx"
44 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
46 #include "share.hxx"
48 using namespace ::com::sun::star::uno;
50 namespace
53 //==================================================================================================
54 static typelib_TypeClass cpp2uno_call(
55 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
56 const typelib_TypeDescription * pMemberTypeDescr,
57 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
58 sal_Int32 nParams, typelib_MethodParameter * pParams,
59 void ** pCallStack,
60 sal_Int64 * pRegisterReturn /* space for register return */ )
62 // pCallStack: ret, [return ptr], this, params
63 char * pCppStack = (char *)(pCallStack +1);
65 // return
66 typelib_TypeDescription * pReturnTypeDescr = 0;
67 if (pReturnTypeRef)
68 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
70 void * pUnoReturn = 0;
71 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
73 if (pReturnTypeDescr)
75 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
77 pUnoReturn = pRegisterReturn; // direct way for simple types
79 else // complex return via ptr (pCppReturn)
81 pCppReturn = *(void **)pCppStack;
82 pCppStack += sizeof(void *);
84 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
85 pReturnTypeDescr )
86 ? alloca( pReturnTypeDescr->nSize )
87 : pCppReturn); // direct way
90 // pop this
91 pCppStack += sizeof( void* );
93 // stack space
94 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
95 // parameters
96 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
97 void ** pCppArgs = pUnoArgs + nParams;
98 // indizes of values this have to be converted (interface conversion cpp<=>uno)
99 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
100 // type descriptions for reconversions
101 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
103 sal_Int32 nTempIndizes = 0;
105 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
107 const typelib_MethodParameter & rParam = pParams[nPos];
108 typelib_TypeDescription * pParamTypeDescr = 0;
109 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
111 if (!rParam.bOut
112 && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
113 // value
115 pCppArgs[nPos] = pCppStack;
116 pUnoArgs[nPos] = pCppStack;
117 switch (pParamTypeDescr->eTypeClass)
119 case typelib_TypeClass_HYPER:
120 case typelib_TypeClass_UNSIGNED_HYPER:
121 case typelib_TypeClass_DOUBLE:
122 pCppStack += sizeof(sal_Int32); // extra long
124 // no longer needed
125 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
127 else // ptr to complex value | ref
129 pCppArgs[nPos] = *(void **)pCppStack;
131 if (! rParam.bIn) // is pure out
133 // uno out is unconstructed mem!
134 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
135 pTempIndizes[nTempIndizes] = nPos;
136 // will be released at reconversion
137 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
139 // is in/inout
140 else if (bridges::cpp_uno::shared::relatesToInterfaceType(
141 pParamTypeDescr ))
143 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
144 *(void **)pCppStack, pParamTypeDescr,
145 pThis->getBridge()->getCpp2Uno() );
146 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
147 // will be released at reconversion
148 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
150 else // direct way
152 pUnoArgs[nPos] = *(void **)pCppStack;
153 // no longer needed
154 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
157 pCppStack += sizeof(sal_Int32); // standard parameter length
160 // ExceptionHolder
161 uno_Any aUnoExc; // Any will be constructed by callee
162 uno_Any * pUnoExc = &aUnoExc;
164 // invoke uno dispatch call
165 (*pThis->getUnoI()->pDispatcher)(
166 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
168 // in case an exception occured...
169 if (pUnoExc)
171 // destruct temporary in/inout params
172 for ( ; nTempIndizes--; )
174 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
176 if (pParams[nIndex].bIn) // is in/inout => was constructed
177 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
178 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
180 if (pReturnTypeDescr)
181 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
183 CPPU_CURRENT_NAMESPACE::raiseException(
184 &aUnoExc, pThis->getBridge()->getUno2Cpp() );
185 // has to destruct the any
186 // is here for dummy
187 return typelib_TypeClass_VOID;
189 else // else no exception occured...
191 // temporary params
192 for ( ; nTempIndizes--; )
194 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
195 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
197 if (pParams[nIndex].bOut) // inout/out
199 // convert and assign
200 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
201 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
202 pThis->getBridge()->getUno2Cpp() );
204 // destroy temp uno param
205 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
207 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
209 // return
210 if (pCppReturn) // has complex return
212 if (pUnoReturn != pCppReturn) // needs reconversion
214 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
215 pThis->getBridge()->getUno2Cpp() );
216 // destroy temp uno return
217 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
219 // complex return ptr is set to eax
220 *(void **)pRegisterReturn = pCppReturn;
222 if (pReturnTypeDescr)
224 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
225 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
226 return eRet;
228 else
229 return typelib_TypeClass_VOID;
234 //==================================================================================================
235 static typelib_TypeClass cpp_mediate(
236 sal_Int32 nFunctionIndex,
237 sal_Int32 nVtableOffset,
238 void ** pCallStack,
239 sal_Int64 * pRegisterReturn /* space for register return */ )
241 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
243 // pCallStack: ret adr, [ret *], this, params
244 void * pThis;
245 if( nFunctionIndex & 0x80000000 )
247 nFunctionIndex &= 0x7fffffff;
248 pThis = pCallStack[2];
250 else
252 pThis = pCallStack[1];
254 pThis = static_cast< char * >(pThis) - nVtableOffset;
255 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
256 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
257 pThis);
259 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
261 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
262 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
264 throw RuntimeException(
265 rtl::OUString::createFromAscii("illegal vtable index!"),
266 (XInterface *)pThis );
269 // determine called method
270 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
271 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
273 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
275 typelib_TypeClass eRet;
276 switch (aMemberDescr.get()->eTypeClass)
278 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
280 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
282 // is GET method
283 eRet = cpp2uno_call(
284 pCppI, aMemberDescr.get(),
285 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
286 0, 0, // no params
287 pCallStack, pRegisterReturn );
289 else
291 // is SET method
292 typelib_MethodParameter aParam;
293 aParam.pTypeRef =
294 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
295 aParam.bIn = sal_True;
296 aParam.bOut = sal_False;
298 eRet = cpp2uno_call(
299 pCppI, aMemberDescr.get(),
300 0, // indicates void return
301 1, &aParam,
302 pCallStack, pRegisterReturn );
304 break;
306 case typelib_TypeClass_INTERFACE_METHOD:
308 // is METHOD
309 switch (nFunctionIndex)
311 case 1: // acquire()
312 pCppI->acquireProxy(); // non virtual call!
313 eRet = typelib_TypeClass_VOID;
314 break;
315 case 2: // release()
316 pCppI->releaseProxy(); // non virtual call!
317 eRet = typelib_TypeClass_VOID;
318 break;
319 case 0: // queryInterface() opt
321 typelib_TypeDescription * pTD = 0;
322 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() );
323 if (pTD)
325 XInterface * pInterface = 0;
326 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
327 pCppI->getBridge()->getCppEnv(),
328 (void **)&pInterface, pCppI->getOid().pData,
329 (typelib_InterfaceTypeDescription *)pTD );
331 if (pInterface)
333 ::uno_any_construct(
334 reinterpret_cast< uno_Any * >( pCallStack[1] ),
335 &pInterface, pTD, cpp_acquire );
336 pInterface->release();
337 TYPELIB_DANGER_RELEASE( pTD );
338 *(void **)pRegisterReturn = pCallStack[1];
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(
358 rtl::OUString::createFromAscii("no member description found!"),
359 (XInterface *)pThis );
360 // is here for dummy
361 eRet = typelib_TypeClass_VOID;
365 return eRet;
368 //==================================================================================================
370 * is called on incoming vtable calls
371 * (called by asm snippets)
373 static void cpp_vtable_call(
374 int nFunctionIndex, int nVtableOffset, void** pCallStack )
375 __attribute__((regparm(3)));
377 void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** pCallStack )
379 volatile long nRegReturn[2];
380 typelib_TypeClass aType = cpp_mediate(
381 nFunctionIndex, nVtableOffset, pCallStack, (sal_Int64*)nRegReturn );
383 switch( aType )
385 case typelib_TypeClass_HYPER:
386 case typelib_TypeClass_UNSIGNED_HYPER:
387 __asm__( "movl %1, %%edx\n\t"
388 "movl %0, %%eax\n"
389 : : "m"(nRegReturn[0]), "m"(nRegReturn[1]) );
390 break;
391 case typelib_TypeClass_FLOAT:
392 __asm__( "flds %0\n\t"
393 "fstp %%st(0)\n\t"
394 "flds %0\n"
395 : : "m"(*(float *)nRegReturn) );
396 break;
397 case typelib_TypeClass_DOUBLE:
398 __asm__( "fldl %0\n\t"
399 "fstp %%st(0)\n\t"
400 "fldl %0\n"
401 : : "m"(*(double *)nRegReturn) );
402 break;
403 // case typelib_TypeClass_UNSIGNED_SHORT:
404 // case typelib_TypeClass_SHORT:
405 // __asm__( "movswl %0, %%eax\n"
406 // : : "m"(nRegReturn) );
407 // break;
408 default:
409 __asm__( "movl %0, %%eax\n"
410 : : "m"(nRegReturn[0]) );
411 break;
416 //==================================================================================================
417 int const codeSnippetSize = 20;
419 unsigned char * codeSnippet(
420 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
421 bool simpleRetType)
423 if (!simpleRetType) {
424 functionIndex |= 0x80000000;
426 unsigned char * p = code;
427 OSL_ASSERT(sizeof (sal_Int32) == 4);
428 // mov function_index, %eax:
429 *p++ = 0xB8;
430 *reinterpret_cast< sal_Int32 * >(p) = functionIndex;
431 p += sizeof (sal_Int32);
432 // mov vtable_offset, %edx:
433 *p++ = 0xBA;
434 *reinterpret_cast< sal_Int32 * >(p) = vtableOffset;
435 p += sizeof (sal_Int32);
436 // mov %esp, %ecx:
437 *p++ = 0x89;
438 *p++ = 0xE1;
439 // jmp cpp_vtable_call:
440 *p++ = 0xE9;
441 *reinterpret_cast< sal_Int32 * >(p)
442 = ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int32);
443 p += sizeof (sal_Int32);
444 OSL_ASSERT(p - code <= codeSnippetSize);
445 return code + codeSnippetSize;
450 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
452 bridges::cpp_uno::shared::VtableFactory::Slot *
453 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
455 return static_cast< Slot * >(block) + 2;
458 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
459 sal_Int32 slotCount)
461 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
464 bridges::cpp_uno::shared::VtableFactory::Slot *
465 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
466 void * block, sal_Int32 slotCount)
468 Slot * slots = mapBlockToVtable(block);
469 slots[-2].fn = 0;
470 slots[-1].fn = 0;
471 return slots + slotCount;
474 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
475 Slot ** slots, unsigned char * code,
476 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
477 sal_Int32 functionCount, sal_Int32 vtableOffset)
479 (*slots) -= functionCount;
480 Slot * s = *slots;
481 for (sal_Int32 i = 0; i < type->nMembers; ++i) {
482 typelib_TypeDescription * member = 0;
483 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
484 OSL_ASSERT(member != 0);
485 switch (member->eTypeClass) {
486 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
487 // Getter:
488 (s++)->fn = code;
489 code = codeSnippet(
490 code, functionOffset++, vtableOffset,
491 bridges::cpp_uno::shared::isSimpleType(
492 reinterpret_cast<
493 typelib_InterfaceAttributeTypeDescription * >(
494 member)->pAttributeTypeRef));
495 // Setter:
496 if (!reinterpret_cast<
497 typelib_InterfaceAttributeTypeDescription * >(
498 member)->bReadOnly)
500 (s++)->fn = code;
501 code = codeSnippet(code, functionOffset++, vtableOffset, true);
503 break;
505 case typelib_TypeClass_INTERFACE_METHOD:
506 (s++)->fn = code;
507 code = codeSnippet(
508 code, functionOffset++, vtableOffset,
509 bridges::cpp_uno::shared::isSimpleType(
510 reinterpret_cast<
511 typelib_InterfaceMethodTypeDescription * >(
512 member)->pReturnTypeRef));
513 break;
515 default:
516 OSL_ASSERT(false);
517 break;
519 TYPELIB_DANGER_RELEASE(member);
521 return code;
524 void bridges::cpp_uno::shared::VtableFactory::flushCode(
525 unsigned char const *, unsigned char const *)