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 
41 using namespace ::com::sun::star::uno;
42 
43 namespace
44 {
45 
46 void 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 
81 static 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 
171 static 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: */
Type
sal_Int32 nIndex
void SAL_CALL uno_destructData(void *pValue, typelib_TypeDescription *pTypeDescr, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
Represents a vtable slot of a C++ class.
Definition: vtables.hxx:59
void fillUnoException(uno_Any *pExc, uno_Mapping *pCpp2Uno)
bool isSimpleType(typelib_TypeClass typeClass)
Determines whether a type is a "simple" type (VOID, BOOLEAN, BYTE, SHORT, UNSIGNED SHORT...
Definition: types.cxx:28
#define INSERT_INT32(pSV, pDS)
sal_Int32 index
The index within the vtable.
Definition: vtables.hxx:76
A uno proxy wrapping a cpp interface.
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))
bool relatesToInterfaceType(typelib_TypeDescription const *type)
Determines whether a type relates to an interface type (is itself an interface type, or might contain entities of interface type).
Definition: types.cxx:41
void unoInterfaceProxyDispatch(uno_Interface *pUnoI, const typelib_TypeDescription *pMemberDescr, void *pReturn, void *pArgs[], uno_Any **ppException)
uno_ExtEnvironment * getUnoEnv()
Definition: bridge.hxx:70
struct _uno_Any uno_Any
Definition: msvc/except.hxx:31
uno_Mapping * getUno2Cpp()
Definition: bridge.hxx:73
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)
#define INSERT_INT8(pSV, pDS)
sal_Int32 offset
The offset of the vtable.
Definition: vtables.hxx:68
#define DISPLACEMENT
void SAL_CALL uno_constructData(void *pMem, typelib_TypeDescription *pTypeDescr) SAL_THROW_EXTERN_C()
#define sal_True
void SAL_CALL uno_copyAndConvertData(void *pDest, void *pSource, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping) SAL_THROW_EXTERN_C()
void SAL_CALL typelib_typedescriptionreference_release(typelib_TypeDescriptionReference *pRef) SAL_THROW_EXTERN_C()
#define INSERT_INT64(pSV, pDS)
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:52
uno_Mapping * getCpp2Uno()
Definition: bridge.hxx:72
void MapReturn(long r0, typelib_TypeClass eTypeClass, sal_uInt64 *pRegisterReturn)
VtableSlot getVtableSlot(typelib_InterfaceAttributeTypeDescription const *ifcMember)
Calculates the vtable slot associated with an interface attribute member.
Definition: vtables.cxx:132
void SAL_CALL typelib_typedescriptionreference_new(typelib_TypeDescriptionReference **ppTDR, typelib_TypeClass eTypeClass, rtl_uString *pTypeName) SAL_THROW_EXTERN_C()
OUString runtimeToOUString(char const *runtimeString)
#define sal_False
#define INSERT_FLOAT(pSV, nr, pFPR, pDS)
#define INSERT_INT16(pSV, pDS)
#define INSERT_DOUBLE(pSV, nr, pFPR, pDS)
com::sun::star::uno::XInterface * getCppI()
sal_uInt16 nPos
char const * name
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo