Bump for 3.6-28
[LibreOffice.git] / bridges / source / cpp_uno / mingw_intel / cpp2uno.cxx
blob39693b871efab1311c9f4317981e3072ab495318
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 <uno/data.h>
33 #include <typelib/typedescription.hxx>
34 #include <sal/alloca.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"
41 #include "share.hxx"
42 #include "smallstruct.hxx"
44 using namespace ::com::sun::star::uno;
46 namespace
49 //==================================================================================================
50 void cpp2uno_call(
51 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
52 const typelib_TypeDescription * pMemberTypeDescr,
53 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
54 sal_Int32 nParams, typelib_MethodParameter * pParams,
55 void ** pCallStack,
56 void * pReturnValue )
58 // pCallStack: ret, [return ptr], this, params
59 char * pCppStack = (char *)(pCallStack +1);
61 // return
62 typelib_TypeDescription * pReturnTypeDescr = 0;
63 if (pReturnTypeRef)
64 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
66 void * pUnoReturn = 0;
67 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
69 if (pReturnTypeDescr)
71 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
73 pUnoReturn = pReturnValue; // direct way for simple types
75 else // complex return via ptr (pCppReturn)
77 if (!bridges::cpp_uno::shared::isSmallStruct(pReturnTypeDescr)) {
78 pCppReturn = *(void **)pCppStack;
79 pCppStack += sizeof(void *);
81 else {
82 pCppReturn = pReturnValue;
85 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
86 pReturnTypeDescr )
87 ? alloca( pReturnTypeDescr->nSize )
88 : pCppReturn); // direct way
91 // pop this
92 pCppStack += sizeof( void* );
94 // stack space
95 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
96 // parameters
97 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
98 void ** pCppArgs = pUnoArgs + nParams;
99 // indizes of values this have to be converted (interface conversion cpp<=>uno)
100 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
101 // type descriptions for reconversions
102 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
104 sal_Int32 nTempIndizes = 0;
106 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
108 const typelib_MethodParameter & rParam = pParams[nPos];
109 typelib_TypeDescription * pParamTypeDescr = 0;
110 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
112 if (!rParam.bOut
113 && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
114 // value
116 pCppArgs[nPos] = pCppStack;
117 pUnoArgs[nPos] = pCppStack;
118 switch (pParamTypeDescr->eTypeClass)
120 case typelib_TypeClass_HYPER:
121 case typelib_TypeClass_UNSIGNED_HYPER:
122 case typelib_TypeClass_DOUBLE:
123 pCppStack += sizeof(sal_Int32); // extra long
124 break;
125 default:
126 break;
128 // no longer needed
129 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
131 else // ptr to complex value | ref
133 pCppArgs[nPos] = *(void **)pCppStack;
135 if (! rParam.bIn) // is pure out
137 // uno out is unconstructed mem!
138 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
139 pTempIndizes[nTempIndizes] = nPos;
140 // will be released at reconversion
141 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
143 // is in/inout
144 else if (bridges::cpp_uno::shared::relatesToInterfaceType(
145 pParamTypeDescr ))
147 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
148 *(void **)pCppStack, pParamTypeDescr,
149 pThis->getBridge()->getCpp2Uno() );
150 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
151 // will be released at reconversion
152 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
154 else // direct way
156 pUnoArgs[nPos] = *(void **)pCppStack;
157 // no longer needed
158 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
161 pCppStack += sizeof(sal_Int32); // standard parameter length
164 // ExceptionHolder
165 uno_Any aUnoExc; // Any will be constructed by callee
166 uno_Any * pUnoExc = &aUnoExc;
168 // invoke uno dispatch call
169 (*pThis->getUnoI()->pDispatcher)(
170 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
172 // in case an exception occurred...
173 if (pUnoExc)
175 // destruct temporary in/inout params
176 for ( ; nTempIndizes--; )
178 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
180 if (pParams[nIndex].bIn) // is in/inout => was constructed
181 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
182 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
184 if (pReturnTypeDescr)
185 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
187 CPPU_CURRENT_NAMESPACE::raiseException(
188 &aUnoExc, pThis->getBridge()->getUno2Cpp() );
189 // has to destruct the any
191 else // else no exception occurred...
193 // temporary params
194 for ( ; nTempIndizes--; )
196 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
197 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
199 if (pParams[nIndex].bOut) // inout/out
201 // convert and assign
202 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
203 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
204 pThis->getBridge()->getUno2Cpp() );
206 // destroy temp uno param
207 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
209 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
211 // return
212 if (pCppReturn) // has complex return
214 if (pUnoReturn != pCppReturn) // needs reconversion
216 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
217 pThis->getBridge()->getUno2Cpp() );
218 // destroy temp uno return
219 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
221 if (pReturnValue != pCppReturn)
222 // complex return ptr is set to eax
223 *static_cast< void ** >(pReturnValue) = pCppReturn;
225 if (pReturnTypeDescr)
227 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
233 //==================================================================================================
234 extern "C" void cpp_vtable_call(
235 int nFunctionIndex, int nVtableOffset, void** pCallStack,
236 void * pReturnValue )
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 switch (aMemberDescr.get()->eTypeClass)
274 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
276 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
278 // is GET method
279 cpp2uno_call(
280 pCppI, aMemberDescr.get(),
281 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
282 0, 0, // no params
283 pCallStack, pReturnValue );
285 else
287 // is SET method
288 typelib_MethodParameter aParam;
289 aParam.pTypeRef =
290 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
291 aParam.bIn = sal_True;
292 aParam.bOut = sal_False;
294 cpp2uno_call(
295 pCppI, aMemberDescr.get(),
296 0, // indicates void return
297 1, &aParam,
298 pCallStack, pReturnValue );
300 break;
302 case typelib_TypeClass_INTERFACE_METHOD:
304 // is METHOD
305 switch (nFunctionIndex)
307 case 1: // acquire()
308 pCppI->acquireProxy(); // non virtual call!
309 break;
310 case 2: // release()
311 pCppI->releaseProxy(); // non virtual call!
312 break;
313 case 0: // queryInterface() opt
315 typelib_TypeDescription * pTD = 0;
316 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() );
317 if (pTD)
319 XInterface * pInterface = 0;
320 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
321 pCppI->getBridge()->getCppEnv(),
322 (void **)&pInterface, pCppI->getOid().pData,
323 (typelib_InterfaceTypeDescription *)pTD );
325 if (pInterface)
327 ::uno_any_construct(
328 reinterpret_cast< uno_Any * >( pCallStack[1] ),
329 &pInterface, pTD, cpp_acquire );
330 pInterface->release();
331 TYPELIB_DANGER_RELEASE( pTD );
332 *static_cast< void ** >(pReturnValue) = pCallStack[1];
333 break;
335 TYPELIB_DANGER_RELEASE( pTD );
337 } // else perform queryInterface()
338 default:
339 cpp2uno_call(
340 pCppI, aMemberDescr.get(),
341 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
342 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
343 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
344 pCallStack, pReturnValue );
346 break;
348 default:
350 throw RuntimeException(
351 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no member description found!" )),
352 (XInterface *)pThis );
357 //==================================================================================================
358 extern "C" void privateSnippetExecutorGeneral();
359 extern "C" void privateSnippetExecutorVoid();
360 extern "C" void privateSnippetExecutorHyper();
361 extern "C" void privateSnippetExecutorFloat();
362 extern "C" void privateSnippetExecutorDouble();
363 extern "C" void privateSnippetExecutorClass();
364 extern "C" typedef void (*PrivateSnippetExecutor)();
366 int const codeSnippetSize = 16;
368 unsigned char * codeSnippet(
369 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
370 typelib_TypeDescriptionReference * returnType)
372 typelib_TypeDescription * returnTypeDescr = 0;
373 if (returnType)
374 TYPELIB_DANGER_GET( &returnTypeDescr, returnType );
376 typelib_TypeClass returnTypeClass = returnType ? returnType->eTypeClass : typelib_TypeClass_VOID;
377 if (!bridges::cpp_uno::shared::isSimpleType(returnTypeClass) &&
378 !bridges::cpp_uno::shared::isSmallStruct(returnTypeDescr)) {
379 functionIndex |= 0x80000000;
381 PrivateSnippetExecutor exec = privateSnippetExecutorGeneral;
382 switch (returnTypeClass) {
383 case typelib_TypeClass_VOID:
384 exec = privateSnippetExecutorVoid;
385 break;
386 case typelib_TypeClass_HYPER:
387 case typelib_TypeClass_UNSIGNED_HYPER:
388 exec = privateSnippetExecutorHyper;
389 break;
390 case typelib_TypeClass_FLOAT:
391 exec = privateSnippetExecutorFloat;
392 break;
393 case typelib_TypeClass_DOUBLE:
394 exec = privateSnippetExecutorDouble;
395 break;
396 case typelib_TypeClass_STRUCT:
397 if (bridges::cpp_uno::shared::isSmallStruct(returnTypeDescr)) {
398 if (returnType->pType->nSize <= 4) {
399 exec = privateSnippetExecutorGeneral;
401 else if (returnType->pType->nSize <= 8) {
402 exec = privateSnippetExecutorHyper;
405 else {
406 exec = privateSnippetExecutorClass;
408 break;
409 case typelib_TypeClass_STRING:
410 case typelib_TypeClass_TYPE:
411 case typelib_TypeClass_ANY:
412 case typelib_TypeClass_SEQUENCE:
413 case typelib_TypeClass_INTERFACE:
414 exec = privateSnippetExecutorClass;
415 break;
416 default:
417 exec = privateSnippetExecutorGeneral;
418 break;
420 if (returnType)
421 TYPELIB_DANGER_RELEASE( returnTypeDescr );
422 unsigned char * p = code;
423 OSL_ASSERT(sizeof (sal_Int32) == 4);
424 // mov function_index, %eax:
425 *p++ = 0xB8;
426 *reinterpret_cast< sal_Int32 * >(p) = functionIndex;
427 p += sizeof (sal_Int32);
428 // mov vtable_offset, %edx:
429 *p++ = 0xBA;
430 *reinterpret_cast< sal_Int32 * >(p) = vtableOffset;
431 p += sizeof (sal_Int32);
432 // jmp privateSnippetExecutor:
433 *p++ = 0xE9;
434 *reinterpret_cast< sal_Int32 * >(p)
435 = ((unsigned char *) exec) - p - sizeof (sal_Int32);
436 p += sizeof (sal_Int32);
437 OSL_ASSERT(p - code <= codeSnippetSize);
438 return code + codeSnippetSize;
443 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
445 bridges::cpp_uno::shared::VtableFactory::Slot *
446 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
448 return static_cast< Slot * >(block) + 2;
451 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
452 sal_Int32 slotCount)
454 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
457 bridges::cpp_uno::shared::VtableFactory::Slot *
458 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
459 void * block, sal_Int32 slotCount)
461 Slot * slots = mapBlockToVtable(block);
462 slots[-2].fn = 0;
463 slots[-1].fn = 0;
464 return slots + slotCount;
467 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
468 Slot ** slots, unsigned char * code,
469 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
470 sal_Int32 functionCount, sal_Int32 vtableOffset)
472 (*slots) -= functionCount;
473 Slot * s = *slots;
474 for (sal_Int32 i = 0; i < type->nMembers; ++i) {
475 typelib_TypeDescription * member = 0;
476 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
477 OSL_ASSERT(member != 0);
478 switch (member->eTypeClass) {
479 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
480 // Getter:
481 (s++)->fn = code;
482 code = codeSnippet(
483 code, functionOffset++, vtableOffset,
484 reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
485 member)->pAttributeTypeRef);
486 // Setter:
487 if (!reinterpret_cast<
488 typelib_InterfaceAttributeTypeDescription * >(
489 member)->bReadOnly)
491 (s++)->fn = code;
492 code = codeSnippet(
493 code, functionOffset++, vtableOffset,
494 NULL);
496 break;
498 case typelib_TypeClass_INTERFACE_METHOD:
499 (s++)->fn = code;
500 code = codeSnippet(
501 code, functionOffset++, vtableOffset,
502 reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
503 member)->pReturnTypeRef);
504 break;
506 default:
507 OSL_ASSERT(false);
508 break;
510 TYPELIB_DANGER_RELEASE(member);
512 return code;
515 void bridges::cpp_uno::shared::VtableFactory::flushCode(
516 unsigned char const *, unsigned char const *)
519 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */