LibreOffice Module bridges (master) 1
gcc3_aix_powerpc/uno2cpp.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sys/types.h>
21#include <sys/malloc.h>
22
23#include <com/sun/star/uno/Exception.hxx>
24#include <com/sun/star/uno/RuntimeException.hxx>
25#include <com/sun/star/uno/genfunc.hxx>
27#include <uno/data.h>
28
29#include "bridge.hxx"
30#include "types.hxx"
31#include "unointerfaceproxy.hxx"
32#include "vtables.hxx"
33
34#include "share.hxx"
35
36#include <exception>
37#include <stdio.h>
38#include <string.h>
39#include <typeinfo>
40
41using namespace ::com::sun::star::uno;
42
43namespace
44{
45
46void MapReturn(sal_uInt32 r3, sal_uInt32 r4, double dret, typelib_TypeClass eReturnType, void *pRegisterReturn)
47{
48 switch( eReturnType )
49 {
50 case typelib_TypeClass_HYPER:
51 case typelib_TypeClass_UNSIGNED_HYPER:
52 ((long*)pRegisterReturn)[1] = r4;
53 // fall through on purpose
54 case typelib_TypeClass_LONG:
55 case typelib_TypeClass_UNSIGNED_LONG:
56 case typelib_TypeClass_ENUM:
57 ((long*)pRegisterReturn)[0] = r3;
58 break;
59 case typelib_TypeClass_CHAR:
60 case typelib_TypeClass_SHORT:
61 case typelib_TypeClass_UNSIGNED_SHORT:
62 *(unsigned short*)pRegisterReturn = (unsigned short)r3;
63 break;
64 case typelib_TypeClass_BOOLEAN:
65 case typelib_TypeClass_BYTE:
66 *(unsigned char*)pRegisterReturn = (unsigned char)r3;
67 break;
68 case typelib_TypeClass_FLOAT:
69 *(float*)pRegisterReturn = (float)dret;
70 break;
71 case typelib_TypeClass_DOUBLE:
72 *(double*)pRegisterReturn = dret;
73 break;
74 default:
75 break;
76 }
77}
78
79#define DISPLACEMENT -2
80
81static void callVirtualMethod(
82 void * pThis,
83 sal_uInt32 nVtableIndex,
84 void * pRegisterReturn,
85 typelib_TypeClass eReturnType,
86 sal_uInt32 * pStack,
87 sal_uInt32 nStack,
88 double *pFPR,
89 sal_uInt32 nFPR)
90{
91 sal_uInt32 nStackWords = nStack;
92 if (nStackWords < ppc::MAX_GPR_REGS)
93 nStackWords = 0;
94 else
95 nStackWords-=ppc::MAX_GPR_REGS;
96 if (nStackWords)
97 nStackWords = ( nStackWords + 1) & ~1;
98 sal_uInt32 *stack = (sal_uInt32*)__builtin_alloca( nStackWords * sizeof(sal_uInt32) );
99 memcpy(stack+DISPLACEMENT, pStack+ppc::MAX_GPR_REGS, nStack * sizeof(sal_uInt32));
100
101 // Get pointer to method
102 sal_uInt32 pMethod = *((sal_uInt32 *)pThis);
103 pMethod += 4 * nVtableIndex;
104 pMethod = *((sal_uInt32 *)pMethod);
105
106 typedef void (* FunctionCall )( sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32 );
107 FunctionCall pFunc = (FunctionCall)pMethod;
108
109 register double d0 asm("fr1"); d0 = pFPR[0];
110 register double d1 asm("fr2"); d1 = pFPR[1];
111 register double d2 asm("fr3"); d2 = pFPR[2];
112 register double d3 asm("fr4"); d3 = pFPR[3];
113 register double d4 asm("fr5"); d4 = pFPR[4];
114 register double d5 asm("fr6"); d5 = pFPR[5];
115 register double d6 asm("fr7"); d6 = pFPR[6];
116 register double d7 asm("fr8"); d7 = pFPR[7];
117 register double d8 asm("fr9"); d8 = pFPR[8];
118 register double d9 asm("fr10"); d9 = pFPR[9];
119 register double d10 asm("fr11"); d10 = pFPR[10];
120 register double d11 asm("fr12"); d11 = pFPR[11];
121 register double d12 asm("fr13"); d12 = pFPR[12];
122
123 (*pFunc)(pStack[0], pStack[1], pStack[2], pStack[3], pStack[4], pStack[5], pStack[6], pStack[7]);
124
125 register sal_uInt32 r3 asm("r3");
126 register sal_uInt32 r4 asm("r4");
127 MapReturn(r3, r4, d0, eReturnType, pRegisterReturn);
128}
129
130#define INSERT_INT32(pSV, pDS) \
131{ \
132 *pDS++ = *reinterpret_cast<sal_uInt32 *>(pSV); \
133}
134
135#define INSERT_INT16(pSV, pDS) \
136{ \
137 *pDS++ = *reinterpret_cast<sal_uInt16 *>(pSV); \
138}
139
140#define INSERT_INT8(pSV, pDS) \
141{ \
142 *pDS++ = *reinterpret_cast<sal_uInt8 *>(pSV); \
143}
144
145#define INSERT_FLOAT(pSV, nr, pFPR, pDS) \
146{ \
147 if (nr < ppc::MAX_SSE_REGS) \
148 { \
149 sal_uInt32 *pDouble = (sal_uInt32 *)&(pFPR[nr++]); \
150 pDouble[0] = *reinterpret_cast<sal_uInt32 *>(pSV); \
151 } \
152 *pDS++ = *reinterpret_cast<sal_uInt32 *>(pSV); \
153}
154
155#define INSERT_DOUBLE(pSV, nr, pFPR, pDS) \
156{ \
157 if (nr < ppc::MAX_SSE_REGS) \
158 { \
159 pFPR[nr++] = *reinterpret_cast<double *>(pSV); \
160 } \
161 *pDS++ = reinterpret_cast<sal_uInt32 *>(pSV)[1]; \
162 *pDS++ = reinterpret_cast<sal_uInt32 *>(pSV)[0]; \
163}
164
165#define INSERT_INT64(pSV, pDS) \
166{ \
167 INSERT_INT32(pSV, pDS) \
168 INSERT_INT32(((sal_uInt32*)pSV)+1, pDS) \
169}
170
171static void cpp_call(
174 typelib_TypeDescriptionReference * pReturnTypeRef,
175 sal_Int32 nParams, typelib_MethodParameter * pParams,
176 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
177{
178 // max space for: [complex ret ptr], values|ptr ...
179 sal_uInt32 * pStack = (sal_uInt32*)__builtin_alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
180 sal_uInt32 * pStackStart = pStack;
181
182 double pFPR[ppc::MAX_SSE_REGS];
183 sal_uInt32 nFPR = 0;
184
185 // return
186 typelib_TypeDescription * pReturnTypeDescr = 0;
187 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
188 assert(pReturnTypeDescr && "### expected return type description!");
189
190 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
191
192 if (pReturnTypeDescr)
193 {
194 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
195 {
196 pCppReturn = pUnoReturn; // direct way for simple types
197 }
198 else
199 {
200 // complex return via ptr
201 pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
202 ? __builtin_alloca( pReturnTypeDescr->nSize )
203 : pUnoReturn); // direct way
204 INSERT_INT32(&pCppReturn, pStack);
205 }
206 }
207 // push this
208 void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + aVtableSlot.offset;
209 INSERT_INT32(&pAdjustedThisPtr, pStack);
210
211 // stack space
212 static_assert( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
213 // args
214 void ** pCppArgs = (void **)__builtin_alloca( 3 * sizeof(void *) * nParams );
215 // indices of values this have to be converted (interface conversion cpp<=>uno)
216 sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams);
217 // type descriptions for reconversions
218 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
219
220 sal_Int32 nTempIndices = 0;
221
222 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
223 {
224 const typelib_MethodParameter & rParam = pParams[nPos];
225 typelib_TypeDescription * pParamTypeDescr = 0;
226 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
227
228 if (!rParam.bOut
229 && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
230 {
231 uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], pParamTypeDescr,
232 pThis->getBridge()->getUno2Cpp() );
233
234 switch (pParamTypeDescr->eTypeClass)
235 {
236 case typelib_TypeClass_LONG:
237 case typelib_TypeClass_UNSIGNED_LONG:
238 case typelib_TypeClass_ENUM:
239 INSERT_INT32(pCppArgs[nPos], pStack);
240 break;
241 case typelib_TypeClass_SHORT:
242 case typelib_TypeClass_CHAR:
243 case typelib_TypeClass_UNSIGNED_SHORT:
244 INSERT_INT16(pCppArgs[nPos], pStack);
245 break;
246 case typelib_TypeClass_BOOLEAN:
247 case typelib_TypeClass_BYTE:
248 INSERT_INT8(pCppArgs[nPos], pStack);
249 break;
250 case typelib_TypeClass_FLOAT:
251 INSERT_FLOAT(pCppArgs[nPos], nFPR, pFPR, pStack);
252 break;
253 case typelib_TypeClass_DOUBLE:
254 INSERT_DOUBLE(pCppArgs[nPos], nFPR, pFPR, pStack);
255 break;
256 case typelib_TypeClass_HYPER:
257 case typelib_TypeClass_UNSIGNED_HYPER:
258 INSERT_INT64(pCppArgs[nPos], pStack);
259 break;
260 default:
261 break;
262 }
263
264 // no longer needed
265 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
266 }
267 else // ptr to complex value | ref
268 {
269 if (! rParam.bIn) // is pure out
270 {
271 // cpp out is constructed mem, uno out is not!
273 pCppArgs[nPos] = __builtin_alloca( pParamTypeDescr->nSize ),
274 pParamTypeDescr );
275 pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
276 // will be released at reconversion
277 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
278 }
279 // is in/inout
280 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
281 {
283 pCppArgs[nPos] = __builtin_alloca( pParamTypeDescr->nSize ),
284 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
285
286 pTempIndices[nTempIndices] = nPos; // has to be reconverted
287 // will be released at reconversion
288 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
289 }
290 else // direct way
291 {
292 pCppArgs[nPos] = pUnoArgs[nPos];
293 // no longer needed
294 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
295 }
296 INSERT_INT32(&(pCppArgs[nPos]), pStack);
297 }
298 }
299
300 try
301 {
302 assert( !( (pCppStack - pCppStackStart ) & 3) && "UNALIGNED STACK !!! (Please DO panic)" );
303 try {
305 pAdjustedThisPtr, aVtableSlot.index,
306 pCppReturn, pReturnTypeDescr->eTypeClass,
307 pStackStart, (pStack - pStackStart), pFPR, nFPR );
308 } catch (css::uno::Exception &) {
309 throw;
310 } catch (std::exception & e) {
311 throw css::uno::RuntimeException(
312 "C++ code threw " + o3tl::runtimeToOUString(typeid(e).name()) + ": "
313 + o3tl::runtimeToOUString(e.what()));
314 } catch (...) {
315 throw css::uno::RuntimeException("C++ code threw unknown exception");
316 }
317 // NO exception occurred...
318 *ppUnoExc = 0;
319
320 // reconvert temporary params
321 for ( ; nTempIndices--; )
322 {
323 sal_Int32 nIndex = pTempIndices[nTempIndices];
324 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
325
326 if (pParams[nIndex].bIn)
327 {
328 if (pParams[nIndex].bOut) // inout
329 {
330 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
331 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
332 pThis->getBridge()->getCpp2Uno() );
333 }
334 }
335 else // pure out
336 {
337 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
338 pThis->getBridge()->getCpp2Uno() );
339 }
340 // destroy temp cpp param => cpp: every param was constructed
341 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
342
343 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
344 }
345 // return value
346 if (pCppReturn && pUnoReturn != pCppReturn)
347 {
348 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
349 pThis->getBridge()->getCpp2Uno() );
350 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
351 }
352 }
353 catch (...)
354 {
355 // fill uno exception
357
358 // temporary params
359 for ( ; nTempIndices--; )
360 {
361 sal_Int32 nIndex = pTempIndices[nTempIndices];
362 // destroy temp cpp param => cpp: every param was constructed
363 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
364 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
365 }
366 // return type
367 if (pReturnTypeDescr)
368 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
369 }
370}
371
372}
373
375
377 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
378 void * pReturn, void * pArgs[], uno_Any ** ppException )
379{
380 // is my surrogate
382 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * > (pUnoI);
383 // typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
384
385 switch (pMemberDescr->eTypeClass)
386 {
387 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
388 {
389
390 VtableSlot aVtableSlot(
392 reinterpret_cast<
393 typelib_InterfaceAttributeTypeDescription const * >(
394 pMemberDescr)));
395
396 if (pReturn)
397 {
398 // dependent dispatch
399 cpp_call(
400 pThis, aVtableSlot,
401 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
402 0, 0, // no params
403 pReturn, pArgs, ppException );
404 }
405 else
406 {
407 // is SET
408 typelib_MethodParameter aParam;
409 aParam.pTypeRef =
410 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
411 aParam.bIn = sal_True;
412 aParam.bOut = sal_False;
413
414 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
415 OUString aVoidName("void");
417 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
418
419 // dependent dispatch
420 aVtableSlot.index += 1; //get then set method
421 cpp_call(
422 pThis, aVtableSlot,
423 pReturnTypeRef,
424 1, &aParam,
425 pReturn, pArgs, ppException );
426
428 }
429
430 break;
431 }
432 case typelib_TypeClass_INTERFACE_METHOD:
433 {
434
435 VtableSlot aVtableSlot(
437 reinterpret_cast<
438 typelib_InterfaceMethodTypeDescription const * >(
439 pMemberDescr)));
440 switch (aVtableSlot.index)
441 {
442 // standard calls
443 case 1: // acquire uno interface
444 (*pUnoI->acquire)( pUnoI );
445 *ppException = 0;
446 break;
447 case 2: // release uno interface
448 (*pUnoI->release)( pUnoI );
449 *ppException = 0;
450 break;
451 case 0: // queryInterface() opt
452 {
453 typelib_TypeDescription * pTD = 0;
454 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
455 if (pTD)
456 {
457 uno_Interface * pInterface = 0;
458 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
459 pThis->pBridge->getUnoEnv(),
460 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
461
462 if (pInterface)
463 {
464 ::uno_any_construct(
465 reinterpret_cast< uno_Any * >( pReturn ),
466 &pInterface, pTD, 0 );
467 (*pInterface->release)( pInterface );
468 TYPELIB_DANGER_RELEASE( pTD );
469 *ppException = 0;
470 break;
471 }
472 TYPELIB_DANGER_RELEASE( pTD );
473 }
474 } // else perform queryInterface()
475 default:
476 // dependent dispatch
477 cpp_call(
478 pThis, aVtableSlot,
479 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
480 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
481 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
482 pReturn, pArgs, ppException );
483 }
484 break;
485 }
486 default:
487 {
488 ::com::sun::star::uno::RuntimeException aExc(
489 "illegal member type description!",
491
492 Type const & rExcType = cppu::UnoType<decltype(aExc)>::get();
493 // binary identical null reference
494 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
495 }
496 }
497}
498
499}
500
501/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
uno_Mapping * getUno2Cpp()
Definition: bridge.hxx:73
uno_ExtEnvironment * getUnoEnv()
Definition: bridge.hxx:70
uno_Mapping * getCpp2Uno()
Definition: bridge.hxx:72
A uno proxy wrapping a cpp interface.
com::sun::star::uno::XInterface * getCppI()
void SAL_CALL uno_destructData(void *pValue, typelib_TypeDescription *pTypeDescr, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
void SAL_CALL uno_constructData(void *pMem, typelib_TypeDescription *pTypeDescr) SAL_THROW_EXTERN_C()
void SAL_CALL uno_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
#define DISPLACEMENT
#define INSERT_INT64(pSV, pDS)
#define INSERT_FLOAT(pSV, nr, pFPR, pDS)
#define INSERT_DOUBLE(pSV, nr, pFPR, pDS)
#define INSERT_INT8(pSV, pDS)
#define INSERT_INT16(pSV, pDS)
#define INSERT_INT32(pSV, pDS)
char const * name
void MapReturn(long r0, typelib_TypeClass eTypeClass, sal_uInt64 *pRegisterReturn)
void callVirtualMethod(void *pThis, sal_uInt32 nVtableIndex, void *pRegisterReturn, typelib_TypeDescription *pReturnTypeDescr, bool bRegisterReturn, sal_uInt32 *pStack, sal_uInt32 nStack, sal_uInt32 *pGPR, double *pFPR) __attribute__((noinline))
static void cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy *pThis, bridges::cpp_uno::shared::VtableSlot aVtableSlot, typelib_TypeDescriptionReference *pReturnTypeRef, sal_Int32 nParams, typelib_MethodParameter *pParams, void *pUnoReturn, void *pUnoArgs[], uno_Any **ppUnoExc)
sal_Int32 nIndex
sal_uInt16 nPos
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:52
struct _uno_Any uno_Any
Definition: msvc/except.hxx:31
void fillUnoException(uno_Any *pExc, uno_Mapping *pCpp2Uno)
void unoInterfaceProxyDispatch(uno_Interface *pUnoI, const typelib_TypeDescription *pMemberDescr, void *pReturn, void *pArgs[], uno_Any **ppException)
VtableSlot getVtableSlot(typelib_InterfaceAttributeTypeDescription const *ifcMember)
Calculates the vtable slot associated with an interface attribute member.
Definition: vtables.cxx:132
bool isSimpleType(typelib_TypeClass typeClass)
Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, UNSIGNED SHORT,...
Definition: types.cxx:28
bool relatesToInterfaceType(typelib_TypeDescription const *type)
Determines whether a type relates to an interface type (is itself an interface type,...
Definition: types.cxx:41
Type
OUString runtimeToOUString(char const *runtimeString)
Represents a vtable slot of a C++ class.
Definition: vtables.hxx:60
sal_Int32 index
The index within the vtable.
Definition: vtables.hxx:76
sal_Int32 offset
The offset of the vtable.
Definition: vtables.hxx:68
void SAL_CALL typelib_typedescriptionreference_new(typelib_TypeDescriptionReference **ppTDR, typelib_TypeClass eTypeClass, rtl_uString *pTypeName) SAL_THROW_EXTERN_C()
void SAL_CALL typelib_typedescriptionreference_release(typelib_TypeDescriptionReference *pRef) SAL_THROW_EXTERN_C()
#define sal_True
#define sal_False