Bump for 3.6-28
[LibreOffice.git] / bridges / source / cpp_uno / gcc3_solaris_intel / cpp2uno.cxx
blob0c73b56758430e3fda2d89b5b6b06cd5faad9cae
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 <sal/alloca.h>
31 #include <strings.h>
33 #include <com/sun/star/uno/genfunc.hxx>
34 #include "com/sun/star/uno/RuntimeException.hpp"
35 #include <uno/data.h>
36 #include <typelib/typedescription.hxx>
38 #include "bridges/cpp_uno/shared/bridge.hxx"
39 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
40 #include "bridges/cpp_uno/shared/types.hxx"
41 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
43 #include "share.hxx"
45 using namespace ::com::sun::star::uno;
47 namespace
50 //==================================================================================================
51 static typelib_TypeClass cpp2uno_call(
52 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
53 const typelib_TypeDescription * pMemberTypeDescr,
54 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
55 sal_Int32 nParams, typelib_MethodParameter * pParams,
56 void ** pCallStack,
57 sal_Int64 * pRegisterReturn /* space for register return */ )
59 // pCallStack: ret, [return ptr], this, params
60 char * pCppStack = (char *)(pCallStack +1);
62 // return
63 typelib_TypeDescription * pReturnTypeDescr = 0;
64 if (pReturnTypeRef)
65 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
67 void * pUnoReturn = 0;
68 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
70 if (pReturnTypeDescr)
72 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
74 pUnoReturn = pRegisterReturn; // direct way for simple types
76 else // complex return via ptr (pCppReturn)
78 pCppReturn = *(void **)pCppStack;
79 pCppStack += sizeof(void *);
81 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
82 pReturnTypeDescr )
83 ? alloca( pReturnTypeDescr->nSize )
84 : pCppReturn); // direct way
87 // pop this
88 pCppStack += sizeof( void* );
90 // stack space
91 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
92 // parameters
93 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
94 void ** pCppArgs = pUnoArgs + nParams;
95 // indizes of values this have to be converted (interface conversion cpp<=>uno)
96 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
97 // type descriptions for reconversions
98 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
100 sal_Int32 nTempIndizes = 0;
102 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
104 const typelib_MethodParameter & rParam = pParams[nPos];
105 typelib_TypeDescription * pParamTypeDescr = 0;
106 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
108 if (!rParam.bOut
109 && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
110 // value
112 pCppArgs[nPos] = pCppStack;
113 pUnoArgs[nPos] = pCppStack;
114 switch (pParamTypeDescr->eTypeClass)
116 case typelib_TypeClass_HYPER:
117 case typelib_TypeClass_UNSIGNED_HYPER:
118 case typelib_TypeClass_DOUBLE:
119 pCppStack += sizeof(sal_Int32); // extra long
121 // no longer needed
122 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
124 else // ptr to complex value | ref
126 pCppArgs[nPos] = *(void **)pCppStack;
128 if (! rParam.bIn) // is pure out
130 // uno out is unconstructed mem!
131 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
132 pTempIndizes[nTempIndizes] = nPos;
133 // will be released at reconversion
134 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
136 // is in/inout
137 else if (bridges::cpp_uno::shared::relatesToInterfaceType(
138 pParamTypeDescr ))
140 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
141 *(void **)pCppStack, pParamTypeDescr,
142 pThis->getBridge()->getCpp2Uno() );
143 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
144 // will be released at reconversion
145 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
147 else // direct way
149 pUnoArgs[nPos] = *(void **)pCppStack;
150 // no longer needed
151 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
154 pCppStack += sizeof(sal_Int32); // standard parameter length
157 // ExceptionHolder
158 uno_Any aUnoExc; // Any will be constructed by callee
159 uno_Any * pUnoExc = &aUnoExc;
161 // invoke uno dispatch call
162 (*pThis->getUnoI()->pDispatcher)(
163 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
165 // in case an exception occurred...
166 if (pUnoExc)
168 // destruct temporary in/inout params
169 for ( ; nTempIndizes--; )
171 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
173 if (pParams[nIndex].bIn) // is in/inout => was constructed
174 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
175 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
177 if (pReturnTypeDescr)
178 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
180 CPPU_CURRENT_NAMESPACE::raiseException(
181 &aUnoExc, pThis->getBridge()->getUno2Cpp() );
182 // has to destruct the any
183 // is here for dummy
184 return typelib_TypeClass_VOID;
186 else // else no exception occurred...
188 // temporary params
189 for ( ; nTempIndizes--; )
191 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
192 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
194 if (pParams[nIndex].bOut) // inout/out
196 // convert and assign
197 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
198 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
199 pThis->getBridge()->getUno2Cpp() );
201 // destroy temp uno param
202 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
204 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
206 // return
207 if (pCppReturn) // has complex return
209 if (pUnoReturn != pCppReturn) // needs reconversion
211 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
212 pThis->getBridge()->getUno2Cpp() );
213 // destroy temp uno return
214 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
216 // complex return ptr is set to eax
217 *(void **)pRegisterReturn = pCppReturn;
219 if (pReturnTypeDescr)
221 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
222 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
223 return eRet;
225 else
226 return typelib_TypeClass_VOID;
231 //==================================================================================================
232 static typelib_TypeClass cpp_mediate(
233 sal_Int32 nFunctionIndex,
234 sal_Int32 nVtableOffset,
235 void ** pCallStack,
236 sal_Int64 * pRegisterReturn /* space for register return */ )
238 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
240 // pCallStack: ret adr, [ret *], this, params
241 void * pThis;
242 if( nFunctionIndex & 0x80000000 )
244 nFunctionIndex &= 0x7fffffff;
245 pThis = pCallStack[2];
247 else
249 pThis = pCallStack[1];
251 pThis = static_cast< char * >(pThis) - nVtableOffset;
252 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
253 = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
254 pThis);
256 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
258 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
259 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
261 throw RuntimeException(
262 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal vtable index!" )),
263 (XInterface *)pThis );
266 // determine called method
267 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
268 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
270 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
272 typelib_TypeClass eRet;
273 switch (aMemberDescr.get()->eTypeClass)
275 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
277 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
279 // is GET method
280 eRet = cpp2uno_call(
281 pCppI, aMemberDescr.get(),
282 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
283 0, 0, // no params
284 pCallStack, pRegisterReturn );
286 else
288 // is SET method
289 typelib_MethodParameter aParam;
290 aParam.pTypeRef =
291 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
292 aParam.bIn = sal_True;
293 aParam.bOut = sal_False;
295 eRet = cpp2uno_call(
296 pCppI, aMemberDescr.get(),
297 0, // indicates void return
298 1, &aParam,
299 pCallStack, pRegisterReturn );
301 break;
303 case typelib_TypeClass_INTERFACE_METHOD:
305 // is METHOD
306 switch (nFunctionIndex)
308 case 1: // acquire()
309 pCppI->acquireProxy(); // non virtual call!
310 eRet = typelib_TypeClass_VOID;
311 break;
312 case 2: // release()
313 pCppI->releaseProxy(); // non virtual call!
314 eRet = typelib_TypeClass_VOID;
315 break;
316 case 0: // queryInterface() opt
318 typelib_TypeDescription * pTD = 0;
319 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() );
320 if (pTD)
322 XInterface * pInterface = 0;
323 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
324 pCppI->getBridge()->getCppEnv(),
325 (void **)&pInterface, pCppI->getOid().pData,
326 (typelib_InterfaceTypeDescription *)pTD );
328 if (pInterface)
330 ::uno_any_construct(
331 reinterpret_cast< uno_Any * >( pCallStack[1] ),
332 &pInterface, pTD, cpp_acquire );
333 pInterface->release();
334 TYPELIB_DANGER_RELEASE( pTD );
335 *(void **)pRegisterReturn = pCallStack[1];
336 eRet = typelib_TypeClass_ANY;
337 break;
339 TYPELIB_DANGER_RELEASE( pTD );
341 } // else perform queryInterface()
342 default:
343 eRet = cpp2uno_call(
344 pCppI, aMemberDescr.get(),
345 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
346 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
347 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
348 pCallStack, pRegisterReturn );
350 break;
352 default:
354 throw RuntimeException(
355 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )),
356 (XInterface *)pThis );
360 return eRet;
363 //==================================================================================================
365 * is called on incoming vtable calls
366 * (called by asm snippets)
368 static void cpp_vtable_call(
369 int nFunctionIndex, int nVtableOffset, void** pCallStack )
370 __attribute__((regparm(3)));
372 void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** pCallStack )
374 volatile long nRegReturn[2];
375 typelib_TypeClass aType = cpp_mediate(
376 nFunctionIndex, nVtableOffset, pCallStack, (sal_Int64*)nRegReturn );
378 switch( aType )
380 case typelib_TypeClass_HYPER:
381 case typelib_TypeClass_UNSIGNED_HYPER:
382 __asm__( "movl %1, %%edx\n\t"
383 "movl %0, %%eax\n"
384 : : "m"(nRegReturn[0]), "m"(nRegReturn[1]) );
385 break;
386 case typelib_TypeClass_FLOAT:
387 __asm__( "flds %0\n\t"
388 "fstp %%st(0)\n\t"
389 "flds %0\n"
390 : : "m"(*(float *)nRegReturn) );
391 break;
392 case typelib_TypeClass_DOUBLE:
393 __asm__( "fldl %0\n\t"
394 "fstp %%st(0)\n\t"
395 "fldl %0\n"
396 : : "m"(*(double *)nRegReturn) );
397 break;
398 // case typelib_TypeClass_UNSIGNED_SHORT:
399 // case typelib_TypeClass_SHORT:
400 // __asm__( "movswl %0, %%eax\n"
401 // : : "m"(nRegReturn) );
402 // break;
403 default:
404 __asm__( "movl %0, %%eax\n"
405 : : "m"(nRegReturn[0]) );
406 break;
411 //==================================================================================================
412 int const codeSnippetSize = 20;
414 unsigned char * codeSnippet(
415 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
416 bool simpleRetType)
418 if (!simpleRetType) {
419 functionIndex |= 0x80000000;
421 unsigned char * p = code;
422 OSL_ASSERT(sizeof (sal_Int32) == 4);
423 // mov function_index, %eax:
424 *p++ = 0xB8;
425 *reinterpret_cast< sal_Int32 * >(p) = functionIndex;
426 p += sizeof (sal_Int32);
427 // mov vtable_offset, %edx:
428 *p++ = 0xBA;
429 *reinterpret_cast< sal_Int32 * >(p) = vtableOffset;
430 p += sizeof (sal_Int32);
431 // mov %esp, %ecx:
432 *p++ = 0x89;
433 *p++ = 0xE1;
434 // jmp cpp_vtable_call:
435 *p++ = 0xE9;
436 *reinterpret_cast< sal_Int32 * >(p)
437 = ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int32);
438 p += sizeof (sal_Int32);
439 OSL_ASSERT(p - code <= codeSnippetSize);
440 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,
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) {
477 typelib_TypeDescription * member = 0;
478 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
479 OSL_ASSERT(member != 0);
480 switch (member->eTypeClass) {
481 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
482 // Getter:
483 (s++)->fn = code;
484 code = codeSnippet(
485 code, functionOffset++, vtableOffset,
486 bridges::cpp_uno::shared::isSimpleType(
487 reinterpret_cast<
488 typelib_InterfaceAttributeTypeDescription * >(
489 member)->pAttributeTypeRef));
490 // Setter:
491 if (!reinterpret_cast<
492 typelib_InterfaceAttributeTypeDescription * >(
493 member)->bReadOnly)
495 (s++)->fn = code;
496 code = codeSnippet(code, functionOffset++, vtableOffset, true);
498 break;
500 case typelib_TypeClass_INTERFACE_METHOD:
501 (s++)->fn = code;
502 code = codeSnippet(
503 code, functionOffset++, vtableOffset,
504 bridges::cpp_uno::shared::isSimpleType(
505 reinterpret_cast<
506 typelib_InterfaceMethodTypeDescription * >(
507 member)->pReturnTypeRef));
508 break;
510 default:
511 OSL_ASSERT(false);
512 break;
514 TYPELIB_DANGER_RELEASE(member);
516 return code;
519 void bridges::cpp_uno::shared::VtableFactory::flushCode(
520 unsigned char const *, unsigned char const *)
523 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */