cid#1636693 COPY_INSTEAD_OF_MOVE
[LibreOffice.git] / bridges / source / cpp_uno / gcc3_linux_hppa / uno2cpp.cxx
blob43e9aabac8b15c7a1e552b65ce6c28004d4a09a6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <malloc.h>
21 #include <rtl/alloc.h>
23 #include <com/sun/star/uno/genfunc.hxx>
24 #include <com/sun/star/uno/Exception.hpp>
25 #include "com/sun/star/uno/RuntimeException.hpp"
26 #include <o3tl/runtimetooustring.hxx>
27 #include <uno/data.h>
29 #include <bridge.hxx>
30 #include <types.hxx>
31 #include <unointerfaceproxy.hxx>
32 #include <vtables.hxx>
34 #include "share.hxx"
36 #include <exception>
37 #include <stdio.h>
38 #include <string.h>
39 #include <typeinfo>
41 using namespace ::com::sun::star::uno;
43 void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
44 void * pRegisterReturn, typelib_TypeDescription *pReturnTypeDescr, bool bRegisterReturn,
45 sal_uInt32 *pStack, sal_uInt32 nStack, sal_uInt32 *pGPR, double *pFPR);
47 #define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow )\
48 if (nr < hppa::MAX_WORDS_IN_REGS) \
49 { \
50 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
51 } \
52 else \
53 bOverflow = true; \
54 if (bOverflow) \
55 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
57 #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow )\
58 if ( (nr < hppa::MAX_WORDS_IN_REGS) && (nr % 2) ) \
59 { \
60 ++nr; \
61 } \
62 if ( nr < hppa::MAX_WORDS_IN_REGS ) \
63 { \
64 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
65 pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
66 } \
67 else \
68 bOverflow = true; \
69 if ( bOverflow ) \
70 { \
71 if ( (pDS - pStart) % 2) \
72 ++pDS; \
73 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \
74 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \
77 #define INSERT_FLOAT( pSV, nr, pFPR, pDS, bOverflow ) \
78 if (nr < hppa::MAX_WORDS_IN_REGS) \
79 { \
80 sal_uInt32 *pDouble = (sal_uInt32 *)&(pFPR[nr++]); \
81 pDouble[0] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
82 } \
83 else \
84 bOverflow = true; \
85 if (bOverflow) \
86 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
88 #define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart, bOverflow ) \
89 if ( (nr < hppa::MAX_WORDS_IN_REGS) && (nr % 2) ) \
90 { \
91 ++nr; \
92 } \
93 if ( nr < hppa::MAX_WORDS_IN_REGS ) \
94 { \
95 sal_uInt32 *pDouble = (sal_uInt32 *)&(pFPR[nr+1]); \
96 pDouble[0] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
97 pDouble[1] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
98 nr+=2; \
99 } \
100 else \
101 bOverflow = true; \
102 if ( bOverflow ) \
104 if ( (pDS - pStart) % 2) \
105 ++pDS; \
106 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \
107 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \
110 #define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \
111 if ( nr < hppa::MAX_WORDS_IN_REGS ) \
112 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
113 else \
114 bOverflow = true; \
115 if (bOverflow) \
116 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
118 #define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \
119 if ( nr < hppa::MAX_WORDS_IN_REGS ) \
120 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
121 else \
122 bOverflow = true; \
123 if (bOverflow) \
124 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
126 namespace hppa
128 bool is_complex_struct(const typelib_TypeDescription * type)
130 const typelib_CompoundTypeDescription * p
131 = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
132 for (sal_Int32 i = 0; i < p->nMembers; ++i)
134 if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
135 p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
137 typelib_TypeDescription * t = 0;
138 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
139 bool b = is_complex_struct(t);
140 TYPELIB_DANGER_RELEASE(t);
141 if (b) {
142 return true;
145 else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
146 return true;
148 if (p->pBaseTypeDescription != 0)
149 return is_complex_struct(&p->pBaseTypeDescription->aBase);
150 return false;
153 bool isRegisterReturn( typelib_TypeDescriptionReference *pTypeRef )
155 if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
156 return true;
157 else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
159 typelib_TypeDescription * pTypeDescr = 0;
160 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
162 /* If the struct is larger than 8 bytes, then there is a buffer at r8 to stick the return value into */
163 bool bRet = pTypeDescr->nSize <= 8 && !is_complex_struct(pTypeDescr);
165 TYPELIB_DANGER_RELEASE( pTypeDescr );
166 return bRet;
168 return false;
173 namespace {
175 static void cpp_call(
176 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
177 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
178 typelib_TypeDescriptionReference * pReturnTypeRef,
179 sal_Int32 nParams, typelib_MethodParameter * pParams,
180 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
182 // max space for: [complex ret ptr], values|ptr ...
183 sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca(
184 sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
185 sal_uInt32 * pStackStart = pStack;
187 sal_uInt32 pGPR[hppa::MAX_GPR_REGS];
188 double pFPR[hppa::MAX_SSE_REGS];
189 sal_uInt32 nRegs=0;
191 // return
192 typelib_TypeDescription * pReturnTypeDescr = 0;
193 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
194 assert(pReturnTypeDescr);
196 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
197 bool bOverflow = false;
198 bool bRegisterReturn = true;
200 if (pReturnTypeDescr)
203 bRegisterReturn = hppa::isRegisterReturn(pReturnTypeRef);
204 if (bRegisterReturn)
205 pCppReturn = pUnoReturn; // direct way for simple types
206 else
208 // complex return via ptr
209 pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
210 ? __builtin_alloca( pReturnTypeDescr->nSize )
211 : pUnoReturn); // direct way
214 // push this
215 void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
216 + aVtableSlot.offset;
217 INSERT_INT32( &pAdjustedThisPtr, nRegs, pGPR, pStack, bOverflow );
219 // stack space
220 static_assert(sizeof(void *) == sizeof(sal_Int32), "### unexpected size!");
221 // args
222 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
223 // indices of values this have to be converted (interface conversion cpp<=>uno)
224 sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams);
225 // type descriptions for reconversions
226 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
228 sal_Int32 nTempIndices = 0;
230 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
232 const typelib_MethodParameter & rParam = pParams[nPos];
233 typelib_TypeDescription * pParamTypeDescr = 0;
234 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
236 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
238 uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
239 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
241 switch (pParamTypeDescr->eTypeClass)
243 case typelib_TypeClass_HYPER:
244 case typelib_TypeClass_UNSIGNED_HYPER:
245 #if OSL_DEBUG_LEVEL > 2
246 fprintf(stderr, "hyper is %llx\n", *((long long*)pCppArgs[nPos]));
247 #endif
248 INSERT_INT64( pCppArgs[nPos], nRegs, pGPR, pStack, pStackStart, bOverflow );
249 break;
250 case typelib_TypeClass_LONG:
251 case typelib_TypeClass_UNSIGNED_LONG:
252 case typelib_TypeClass_ENUM:
253 #if OSL_DEBUG_LEVEL > 2
254 fprintf(stderr, "long is %x\n", pCppArgs[nPos]);
255 #endif
256 INSERT_INT32( pCppArgs[nPos], nRegs, pGPR, pStack, bOverflow );
257 break;
258 case typelib_TypeClass_SHORT:
259 case typelib_TypeClass_CHAR:
260 case typelib_TypeClass_UNSIGNED_SHORT:
261 INSERT_INT16( pCppArgs[nPos], nRegs, pGPR, pStack, bOverflow );
262 break;
263 case typelib_TypeClass_BOOLEAN:
264 case typelib_TypeClass_BYTE:
265 INSERT_INT8( pCppArgs[nPos], nRegs, pGPR, pStack, bOverflow );
266 break;
267 case typelib_TypeClass_FLOAT:
268 INSERT_FLOAT( pCppArgs[nPos], nRegs, pFPR, pStack, bOverflow );
269 break;
270 case typelib_TypeClass_DOUBLE:
271 INSERT_DOUBLE( pCppArgs[nPos], nRegs, pFPR, pStack, pStackStart, bOverflow );
272 break;
273 default:
274 break;
276 // no longer needed
277 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
279 else // ptr to complex value | ref
281 if (! rParam.bIn) // is pure out
283 // cpp out is constructed mem, uno out is not!
284 uno_constructData(
285 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
286 pParamTypeDescr );
287 pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
288 // will be released at reconversion
289 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
291 // is in/inout
292 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
294 uno_copyAndConvertData(
295 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
296 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
298 pTempIndices[nTempIndices] = nPos; // has to be reconverted
299 // will be released at reconversion
300 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
302 else // direct way
304 pCppArgs[nPos] = pUnoArgs[nPos];
305 // no longer needed
306 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
308 INSERT_INT32( &(pCppArgs[nPos]), nRegs, pGPR, pStack, bOverflow );
314 try {
315 callVirtualMethod(
316 pAdjustedThisPtr, aVtableSlot.index,
317 pCppReturn, pReturnTypeDescr, bRegisterReturn,
318 pStackStart,
319 (pStack - pStackStart), pGPR, pFPR);
320 } catch (css::uno::Exception &) {
321 throw;
322 } catch (std::exception & e) {
323 throw css::uno::RuntimeException(
324 "C++ code threw " + o3tl::runtimeToOUString(typeid(e).name()) + ": "
325 + o3tl::runtimeToOUString(e.what()));
326 } catch (...) {
327 throw css::uno::RuntimeException("C++ code threw unknown exception");
330 // NO exception occurred...
331 *ppUnoExc = 0;
333 // reconvert temporary params
334 for ( ; nTempIndices--; )
336 sal_Int32 nIndex = pTempIndices[nTempIndices];
337 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
339 if (pParams[nIndex].bIn)
341 if (pParams[nIndex].bOut) // inout
343 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
344 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
345 pThis->getBridge()->getCpp2Uno() );
348 else // pure out
350 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
351 pThis->getBridge()->getCpp2Uno() );
353 // destroy temp cpp param => cpp: every param was constructed
354 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
356 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
358 // return value
359 if (pCppReturn && pUnoReturn != pCppReturn)
361 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
362 pThis->getBridge()->getCpp2Uno() );
363 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
366 catch (...)
368 // fill uno exception
369 CPPU_CURRENT_NAMESPACE::fillUnoException(*ppUnoExc, pThis->getBridge()->getCpp2Uno());
371 // temporary params
372 for ( ; nTempIndices--; )
374 sal_Int32 nIndex = pTempIndices[nTempIndices];
375 // destroy temp cpp param => cpp: every param was constructed
376 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
377 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
380 // return type
381 if (pReturnTypeDescr)
382 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
387 namespace bridges::cpp_uno::shared {
389 void unoInterfaceProxyDispatch(
390 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
391 void * pReturn, void * pArgs[], uno_Any ** ppException )
393 // is my surrogate
394 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
395 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
396 #if OSL_DEBUG_LEVEL > 0
397 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
398 #endif
400 switch (pMemberDescr->eTypeClass)
402 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
404 #if OSL_DEBUG_LEVEL > 0
405 // determine vtable call index
406 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
407 assert(nMemberPos < pTypeDescr->nAllMembers);
408 #endif
410 VtableSlot aVtableSlot(
411 getVtableSlot(
412 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>
413 (pMemberDescr)));
415 if (pReturn)
417 // dependent dispatch
418 cpp_call(
419 pThis, aVtableSlot,
420 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
421 0, 0, // no params
422 pReturn, pArgs, ppException );
424 else
426 // is SET
427 typelib_MethodParameter aParam;
428 aParam.pTypeRef =
429 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
430 aParam.bIn = sal_True;
431 aParam.bOut = sal_False;
433 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
434 OUString aVoidName("void");
435 typelib_typedescriptionreference_new(
436 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
438 // dependent dispatch
439 aVtableSlot.index += 1;
440 cpp_call(
441 pThis, aVtableSlot, // get, then set method
442 pReturnTypeRef,
443 1, &aParam,
444 pReturn, pArgs, ppException );
446 typelib_typedescriptionreference_release( pReturnTypeRef );
449 break;
451 case typelib_TypeClass_INTERFACE_METHOD:
453 #if OSL_DEBUG_LEVEL > 0
454 // determine vtable call index
455 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
456 assert(nMemberPos < pTypeDescr->nAllMembers);
457 #endif
459 VtableSlot aVtableSlot(
460 getVtableSlot(
461 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>
462 (pMemberDescr)));
464 switch (aVtableSlot.index)
466 // standard calls
467 case 1: // acquire uno interface
468 (*pUnoI->acquire)( pUnoI );
469 *ppException = 0;
470 break;
471 case 2: // release uno interface
472 (*pUnoI->release)( pUnoI );
473 *ppException = 0;
474 break;
475 case 0: // queryInterface() opt
477 typelib_TypeDescription * pTD = 0;
478 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
479 if (pTD)
481 uno_Interface * pInterface = 0;
482 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
483 pThis->getBridge()->getUnoEnv(),
484 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
486 if (pInterface)
488 ::uno_any_construct(
489 reinterpret_cast< uno_Any * >( pReturn ),
490 &pInterface, pTD, 0 );
491 (*pInterface->release)( pInterface );
492 TYPELIB_DANGER_RELEASE( pTD );
493 *ppException = 0;
494 break;
497 TYPELIB_DANGER_RELEASE( pTD );
499 } // else perform queryInterface()
500 default:
501 // dependent dispatch
502 cpp_call(
503 pThis, aVtableSlot,
504 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
505 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
506 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
507 pReturn, pArgs, ppException );
509 break;
511 default:
513 ::com::sun::star::uno::RuntimeException aExc(
514 "illegal member type description!",
515 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
517 Type const & rExcType = cppu::UnoType<decltype(aExc)>::get();
518 // binary identical null reference
519 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
526 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */