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
41using namespace ::com::sun::star::uno;
42
43void 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
74namespace
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
154namespace {
155
156static 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
365namespace 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: */
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()
typelib_InterfaceTypeDescription * pTypeDescr
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()
char const * name
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))
#define INSERT_FLOAT(pSV, pDS)
#define INSERT_DOUBLE(pSV, pDS)
#define INSERT_INT64(pSV, pDS)
#define INSERT_INT8(pSV, pDS)
#define INSERT_INT16(pSV, pDS)
void MapReturn(long d0, long d1, typelib_TypeClass eReturnType, long *pRegisterReturn)
#define INSERT_INT32(pSV, pDS)
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:53
struct _uno_Any uno_Any
Definition: msvc/except.hxx:32
void dummy_can_throw_anything(char const *)
void fillUnoException(uno_Any *pUnoExc, uno_Mapping *pCpp2Uno)
void unoInterfaceProxyDispatch(uno_Interface *pUnoI, typelib_TypeDescription const *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
int i
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
unsigned _Unwind_Word __attribute__((__mode__(__word__)))
Definition: unwind-cxx.h:45