LibreOffice Module bridges (master)  1
gcc3_linux_m68k/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 <malloc.h>
21 #include <rtl/alloc.h>
22 
23 #include <com/sun/star/uno/genfunc.hxx>
24 #include <com/sun/star/uno/Exception.hpp>
25 #include "com/sun/star/uno/RuntimeException.hpp"
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 void MapReturn(long d0, long d1, typelib_TypeClass eReturnType, long *pRegisterReturn)
44 {
45  register float fret asm("fp0");
46  register double dret asm("fp0");
47 
48  switch( eReturnType )
49  {
50  case typelib_TypeClass_HYPER:
51  case typelib_TypeClass_UNSIGNED_HYPER:
52  pRegisterReturn[1] = d1;
53  case typelib_TypeClass_LONG:
54  case typelib_TypeClass_UNSIGNED_LONG:
55  case typelib_TypeClass_ENUM:
56  case typelib_TypeClass_CHAR:
57  case typelib_TypeClass_SHORT:
58  case typelib_TypeClass_UNSIGNED_SHORT:
59  case typelib_TypeClass_BOOLEAN:
60  case typelib_TypeClass_BYTE:
61  pRegisterReturn[0] = d0;
62  break;
63  case typelib_TypeClass_FLOAT:
64  *(float*)pRegisterReturn = fret;
65  break;
66  case typelib_TypeClass_DOUBLE:
67  *(double*)pRegisterReturn = dret;
68  break;
69  default:
70  break;
71  }
72 }
73 
74 namespace
75 {
76 
78  void * pThis,
79  sal_Int32 nVtableIndex,
80  void * pRegisterReturn,
81  typelib_TypeClass eReturnType,
82  sal_uInt32 *pStack,
83  sal_uInt32 nStack) __attribute__((noinline));
84 
86  void * pThis,
87  sal_Int32 nVtableIndex,
88  void * pRegisterReturn,
89  typelib_TypeClass eReturnType,
90  sal_uInt32 *pStack,
91  sal_uInt32 nStack)
92 {
93  // never called
94  if (! pThis)
95  CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
96 
97  if ( nStack )
98  {
99  // m68k stack is either 2 or 4 bytes aligned, doesn't really matter as
100  // we deal in 4 byte units anyway
101  sal_uInt32 nStackBytes = nStack * sizeof(sal_uInt32);
102  sal_uInt32 *stack = (sal_uInt32 *) __builtin_alloca( nStackBytes );
103  memcpy( stack, pStack, nStackBytes );
104  }
105 
106 #if OSL_DEBUG_LEVEL > 2
107  // Let's figure out what is really going on here
108  {
109  fprintf( stderr, "\nStack (%d): ", nStack );
110  for ( unsigned int i = 0; i < nStack; ++i )
111  fprintf( stderr, "0x%lx, ", pStack[i] );
112  fprintf( stderr, "\n" );
113  fprintf( stderr, "pRegisterReturn is %p\n", pRegisterReturn);
114  }
115 #endif
116 
117  sal_uInt32 pMethod = *((sal_uInt32*)pThis);
118  pMethod += 4 * nVtableIndex;
119  pMethod = *((sal_uInt32 *)pMethod);
120 
121  typedef long (*FunctionCall )();
122  FunctionCall pFunc = (FunctionCall)pMethod;
123 
124  //stick the return area into r8 for big struct returning
125  asm volatile("movel %0,%%a1" : : "m"(pRegisterReturn) : );
126 
127  long d0 = (*pFunc)();
128 
129  register long d1 asm("d1");
130 
131  MapReturn(d0, d1, eReturnType, (long*)pRegisterReturn);
132 }
133 }
134 
135 #define INSERT_INT32( pSV, pDS )\
136  *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
137 
138 #define INSERT_INT64( pSV, pDS )\
139  INSERT_INT32( pSV, pDS ) \
140  INSERT_INT32( ((sal_uInt32*)pSV)+1, pDS )
141 
142 #define INSERT_FLOAT( pSV, pDS ) \
143  INSERT_INT32( pSV, pDS )
144 
145 #define INSERT_DOUBLE( pSV, pDS ) \
146  INSERT_INT64( pSV, pDS )
147 
148 #define INSERT_INT16( pSV, pDS ) \
149  *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
150 
151 #define INSERT_INT8( pSV, pDS ) \
152  *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
153 
154 namespace {
155 
156 static void cpp_call(
159  typelib_TypeDescriptionReference * pReturnTypeRef,
160  sal_Int32 nParams, typelib_MethodParameter * pParams,
161  void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
162 {
163 
164  // max space for: [complex ret ptr], values|ptr ...
165  sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca(
166  sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
167  sal_uInt32 * pStackStart = pStack;
168 
169  // return
170  typelib_TypeDescription * pReturnTypeDescr = 0;
171  TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
172  assert(pReturnTypeDescr);
173 
174  void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
175 
176  if (pReturnTypeDescr)
177  {
178 
179  if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
180  {
181  pCppReturn = pUnoReturn; // direct way for simple types
182  }
183  else
184  {
185  // complex return via ptr
186  pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
187  ? __builtin_alloca( pReturnTypeDescr->nSize )
188  : pUnoReturn); // direct way
189 
190 // INSERT_INT32( &pCppReturn, pStack );
191  }
192  }
193  // push this
194  void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
195  + aVtableSlot.offset;
196  INSERT_INT32( &pAdjustedThisPtr, pStack );
197 
198  // stack space
199  static_assert(sizeof(void *) == sizeof(sal_Int32), "### unexpected size!");
200  // args
201  void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
202  // indices of values this have to be converted (interface conversion cpp<=>uno)
203  sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams);
204  // type descriptions for reconversions
205  typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
206 
207  sal_Int32 nTempIndices = 0;
208 
209  for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
210  {
211  const typelib_MethodParameter & rParam = pParams[nPos];
212  typelib_TypeDescription * pParamTypeDescr = 0;
213  TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
214 
215  if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
216  {
217 // uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
218  uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
219  pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
220 
221  switch (pParamTypeDescr->eTypeClass)
222  {
223  case typelib_TypeClass_HYPER:
224  case typelib_TypeClass_UNSIGNED_HYPER:
225 #if OSL_DEBUG_LEVEL > 2
226  fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]);
227 #endif
228  INSERT_INT64( pCppArgs[nPos], pStack );
229  break;
230  case typelib_TypeClass_LONG:
231  case typelib_TypeClass_UNSIGNED_LONG:
232  case typelib_TypeClass_ENUM:
233 #if OSL_DEBUG_LEVEL > 2
234  fprintf(stderr, "long is %x\n", pCppArgs[nPos]);
235 #endif
236  INSERT_INT32( pCppArgs[nPos], pStack );
237  break;
238  case typelib_TypeClass_SHORT:
239  case typelib_TypeClass_CHAR:
240  case typelib_TypeClass_UNSIGNED_SHORT:
241  INSERT_INT16( pCppArgs[nPos], pStack );
242  break;
243  case typelib_TypeClass_BOOLEAN:
244  case typelib_TypeClass_BYTE:
245  INSERT_INT8( pCppArgs[nPos], pStack );
246  break;
247  case typelib_TypeClass_FLOAT:
248  INSERT_FLOAT( pCppArgs[nPos], pStack );
249  break;
250  case typelib_TypeClass_DOUBLE:
251  INSERT_DOUBLE( pCppArgs[nPos], pStack );
252  break;
253  }
254  // no longer needed
255  TYPELIB_DANGER_RELEASE( pParamTypeDescr );
256  }
257  else // ptr to complex value | ref
258  {
259  if (! rParam.bIn) // is pure out
260  {
261  // cpp out is constructed mem, uno out is not!
263  pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
264  pParamTypeDescr );
265  pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
266  // will be released at reconversion
267  ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
268  }
269  // is in/inout
270  else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
271  {
273  pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
274  pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
275 
276  pTempIndices[nTempIndices] = nPos; // has to be reconverted
277  // will be released at reconversion
278  ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
279  }
280  else // direct way
281  {
282  pCppArgs[nPos] = pUnoArgs[nPos];
283  // no longer needed
284  TYPELIB_DANGER_RELEASE( pParamTypeDescr );
285  }
286  INSERT_INT32( &(pCppArgs[nPos]), pStack );
287  }
288  }
289 
290  try
291  {
292  try {
294  pAdjustedThisPtr, aVtableSlot.index,
295  pCppReturn, pReturnTypeDescr->eTypeClass,
296  pStackStart,
297  (pStack - pStackStart));
298  } catch (css::uno::Exception &) {
299  throw;
300  } catch (std::exception & e) {
301  throw css::uno::RuntimeException(
302  "C++ code threw " + o3tl::runtimeToOUString(typeid(e).name()) + ": "
303  + o3tl::runtimeToOUString(e.what()));
304  } catch (...) {
305  throw css::uno::RuntimeException("C++ code threw unknown exception");
306  }
307 
308  // NO exception occurred...
309  *ppUnoExc = 0;
310 
311  // reconvert temporary params
312  for ( ; nTempIndices--; )
313  {
314  sal_Int32 nIndex = pTempIndices[nTempIndices];
315  typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
316 
317  if (pParams[nIndex].bIn)
318  {
319  if (pParams[nIndex].bOut) // inout
320  {
321  uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
322  uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
323  pThis->getBridge()->getCpp2Uno() );
324  }
325  }
326  else // pure out
327  {
328  uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
329  pThis->getBridge()->getCpp2Uno() );
330  }
331  // destroy temp cpp param => cpp: every param was constructed
332  uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
333 
334  TYPELIB_DANGER_RELEASE( pParamTypeDescr );
335  }
336  // return value
337  if (pCppReturn && pUnoReturn != pCppReturn)
338  {
339  uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
340  pThis->getBridge()->getCpp2Uno() );
341  uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
342  }
343  }
344  catch (...)
345  {
346  // fill uno exception
348 
349  // temporary params
350  for ( ; nTempIndices--; )
351  {
352  sal_Int32 nIndex = pTempIndices[nTempIndices];
353  // destroy temp cpp param => cpp: every param was constructed
354  uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
355  TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
356  }
357 
358  // return type
359  if (pReturnTypeDescr)
360  TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
361  }
362 }
363 }
364 
365 namespace bridges::cpp_uno::shared {
366 
368  uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
369  void * pReturn, void * pArgs[], uno_Any ** ppException )
370 {
371  // is my surrogate
373  = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
374  typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
375 
376  switch (pMemberDescr->eTypeClass)
377  {
378  case typelib_TypeClass_INTERFACE_ATTRIBUTE:
379  {
380  // determine vtable call index
381  sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
382  assert(nMemberPos < pTypeDescr->nAllMembers);
383 
384  VtableSlot aVtableSlot(
386  reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>
387  (pMemberDescr)));
388 
389  if (pReturn)
390  {
391  // dependent dispatch
392  cpp_call(
393  pThis, aVtableSlot,
394  ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
395  0, 0, // no params
396  pReturn, pArgs, ppException );
397  }
398  else
399  {
400  // is SET
401  typelib_MethodParameter aParam;
402  aParam.pTypeRef =
403  ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
404  aParam.bIn = sal_True;
405  aParam.bOut = sal_False;
406 
407  typelib_TypeDescriptionReference * pReturnTypeRef = 0;
408  OUString aVoidName("void");
410  &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
411 
412  // dependent dispatch
413  aVtableSlot.index += 1;
414  cpp_call(
415  pThis, aVtableSlot, // get, then set method
416  pReturnTypeRef,
417  1, &aParam,
418  pReturn, pArgs, ppException );
419 
421  }
422 
423  break;
424  }
425  case typelib_TypeClass_INTERFACE_METHOD:
426  {
427  // determine vtable call index
428  sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
429  assert(nMemberPos < pTypeDescr->nAllMembers);
430 
431  VtableSlot aVtableSlot(
433  reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>
434  (pMemberDescr)));
435 
436  switch (aVtableSlot.index)
437  {
438  // standard calls
439  case 1: // acquire uno interface
440  (*pUnoI->acquire)( pUnoI );
441  *ppException = 0;
442  break;
443  case 2: // release uno interface
444  (*pUnoI->release)( pUnoI );
445  *ppException = 0;
446  break;
447  case 0: // queryInterface() opt
448  {
449  typelib_TypeDescription * pTD = 0;
450  TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
451  if (pTD)
452  {
453  uno_Interface * pInterface = 0;
454  (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
455  pThis->getBridge()->getUnoEnv(),
456  (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
457 
458  if (pInterface)
459  {
460  ::uno_any_construct(
461  reinterpret_cast< uno_Any * >( pReturn ),
462  &pInterface, pTD, 0 );
463  (*pInterface->release)( pInterface );
464  TYPELIB_DANGER_RELEASE( pTD );
465  *ppException = 0;
466  break;
467  }
468  TYPELIB_DANGER_RELEASE( pTD );
469  }
470  } // else perform queryInterface()
471  default:
472  // dependent dispatch
473  cpp_call(
474  pThis, aVtableSlot,
475  ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
476  ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
477  ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
478  pReturn, pArgs, ppException );
479  }
480  break;
481  }
482  default:
483  {
484  ::com::sun::star::uno::RuntimeException aExc(
485  "illegal member type description!",
487 
488  Type const & rExcType = cppu::UnoType<decltype(aExc)>::get();
489  // binary identical null reference
490  ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
491  }
492  }
493 }
494 
495 }
496 
497 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
sal_Int32 nIndex
void MapReturn(long d0, long d1, typelib_TypeClass eReturnType, long *pRegisterReturn)
#define INSERT_INT64(pSV, pDS)
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
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)
unsigned _Unwind_Word __attribute__((__mode__(__word__)))
Definition: unwind-cxx.h:45
sal_Int32 offset
The offset of the vtable.
Definition: vtables.hxx:68
int i
typelib_InterfaceTypeDescription * pTypeDescr
void SAL_CALL uno_constructData(void *pMem, typelib_TypeDescription *pTypeDescr) SAL_THROW_EXTERN_C()
#define INSERT_FLOAT(pSV, pDS)
#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_INT16(pSV, pDS)
struct _typelib_TypeDescription typelib_TypeDescription
Definition: msvc/except.hxx:52
uno_Mapping * getCpp2Uno()
Definition: bridge.hxx:72
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 INSERT_INT8(pSV, pDS)
#define sal_False
void dummy_can_throw_anything(char const *)
#define INSERT_INT32(pSV, pDS)
com::sun::star::uno::XInterface * getCppI()
sal_uInt16 nPos
#define INSERT_DOUBLE(pSV, pDS)
char const * name