bump product version to 6.3.0.0.beta1
[LibreOffice.git] / bridges / source / cpp_uno / gcc3_linux_m68k / uno2cpp.cxx
blobdbe7896d1ceb6ae3137c7f56d43b9101529464b1
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 MapReturn(long d0, long d1, typelib_TypeClass eReturnType, long *pRegisterReturn)
45 register float fret asm("fp0");
46 register double dret asm("fp0");
48 switch( eReturnType )
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;
74 namespace
77 void callVirtualMethod(
78 void * pThis,
79 sal_Int32 nVtableIndex,
80 void * pRegisterReturn,
81 typelib_TypeClass eReturnType,
82 sal_uInt32 *pStack,
83 sal_uInt32 nStack) __attribute__((noinline));
85 void callVirtualMethod(
86 void * pThis,
87 sal_Int32 nVtableIndex,
88 void * pRegisterReturn,
89 typelib_TypeClass eReturnType,
90 sal_uInt32 *pStack,
91 sal_uInt32 nStack)
93 // never called
94 if (! pThis)
95 CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
97 if ( nStack )
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 );
106 #if OSL_DEBUG_LEVEL > 2
107 // Let's figure out what is really going on here
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);
115 #endif
117 sal_uInt32 pMethod = *((sal_uInt32*)pThis);
118 pMethod += 4 * nVtableIndex;
119 pMethod = *((sal_uInt32 *)pMethod);
121 typedef long (*FunctionCall )();
122 FunctionCall pFunc = (FunctionCall)pMethod;
124 //stick the return area into r8 for big struct returning
125 asm volatile("movel %0,%%a1" : : "m"(pRegisterReturn) : );
127 long d0 = (*pFunc)();
129 register long d1 asm("d1");
131 MapReturn(d0, d1, eReturnType, (long*)pRegisterReturn);
135 #define INSERT_INT32( pSV, pDS )\
136 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
138 #define INSERT_INT64( pSV, pDS )\
139 INSERT_INT32( pSV, pDS ) \
140 INSERT_INT32( ((sal_uInt32*)pSV)+1, pDS )
142 #define INSERT_FLOAT( pSV, pDS ) \
143 INSERT_INT32( pSV, pDS )
145 #define INSERT_DOUBLE( pSV, pDS ) \
146 INSERT_INT64( pSV, pDS )
148 #define INSERT_INT16( pSV, pDS ) \
149 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
151 #define INSERT_INT8( pSV, pDS ) \
152 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
154 namespace {
156 static void cpp_call(
157 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
158 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
159 typelib_TypeDescriptionReference * pReturnTypeRef,
160 sal_Int32 nParams, typelib_MethodParameter * pParams,
161 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
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;
169 // return
170 typelib_TypeDescription * pReturnTypeDescr = 0;
171 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
172 assert(pReturnTypeDescr);
174 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
176 if (pReturnTypeDescr)
179 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
181 pCppReturn = pUnoReturn; // direct way for simple types
183 else
185 // complex return via ptr
186 pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
187 ? __builtin_alloca( pReturnTypeDescr->nSize )
188 : pUnoReturn); // direct way
190 // INSERT_INT32( &pCppReturn, pStack );
193 // push this
194 void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
195 + aVtableSlot.offset;
196 INSERT_INT32( &pAdjustedThisPtr, pStack );
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));
207 sal_Int32 nTempIndices = 0;
209 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
211 const typelib_MethodParameter & rParam = pParams[nPos];
212 typelib_TypeDescription * pParamTypeDescr = 0;
213 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
215 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
217 // uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
218 uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
219 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
221 switch (pParamTypeDescr->eTypeClass)
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;
254 // no longer needed
255 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
257 else // ptr to complex value | ref
259 if (! rParam.bIn) // is pure out
261 // cpp out is constructed mem, uno out is not!
262 uno_constructData(
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;
269 // is in/inout
270 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
272 uno_copyAndConvertData(
273 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
274 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
276 pTempIndices[nTempIndices] = nPos; // has to be reconverted
277 // will be released at reconversion
278 ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
280 else // direct way
282 pCppArgs[nPos] = pUnoArgs[nPos];
283 // no longer needed
284 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
286 INSERT_INT32( &(pCppArgs[nPos]), pStack );
292 try {
293 callVirtualMethod(
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");
308 // NO exception occurred...
309 *ppUnoExc = 0;
311 // reconvert temporary params
312 for ( ; nTempIndices--; )
314 sal_Int32 nIndex = pTempIndices[nTempIndices];
315 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
317 if (pParams[nIndex].bIn)
319 if (pParams[nIndex].bOut) // inout
321 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
322 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
323 pThis->getBridge()->getCpp2Uno() );
326 else // pure out
328 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
329 pThis->getBridge()->getCpp2Uno() );
331 // destroy temp cpp param => cpp: every param was constructed
332 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
334 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
336 // return value
337 if (pCppReturn && pUnoReturn != pCppReturn)
339 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
340 pThis->getBridge()->getCpp2Uno() );
341 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
344 catch (...)
346 // fill uno exception
347 CPPU_CURRENT_NAMESPACE::fillUnoException(*ppUnoExc, pThis->getBridge()->getCpp2Uno());
349 // temporary params
350 for ( ; nTempIndices--; )
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] );
358 // return type
359 if (pReturnTypeDescr)
360 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
365 namespace bridges { namespace cpp_uno { namespace shared {
367 void unoInterfaceProxyDispatch(
368 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
369 void * pReturn, void * pArgs[], uno_Any ** ppException )
371 // is my surrogate
372 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
373 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
374 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
376 switch (pMemberDescr->eTypeClass)
378 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
380 // determine vtable call index
381 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
382 assert(nMemberPos < pTypeDescr->nAllMembers);
384 VtableSlot aVtableSlot(
385 getVtableSlot(
386 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>
387 (pMemberDescr)));
389 if (pReturn)
391 // dependent dispatch
392 cpp_call(
393 pThis, aVtableSlot,
394 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
395 0, 0, // no params
396 pReturn, pArgs, ppException );
398 else
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;
407 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
408 OUString aVoidName("void");
409 typelib_typedescriptionreference_new(
410 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
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 );
420 typelib_typedescriptionreference_release( pReturnTypeRef );
423 break;
425 case typelib_TypeClass_INTERFACE_METHOD:
427 // determine vtable call index
428 sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
429 assert(nMemberPos < pTypeDescr->nAllMembers);
431 VtableSlot aVtableSlot(
432 getVtableSlot(
433 reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>
434 (pMemberDescr)));
436 switch (aVtableSlot.index)
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
449 typelib_TypeDescription * pTD = 0;
450 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
451 if (pTD)
453 uno_Interface * pInterface = 0;
454 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
455 pThis->getBridge()->getUnoEnv(),
456 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
458 if (pInterface)
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;
468 TYPELIB_DANGER_RELEASE( pTD );
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 );
480 break;
482 default:
484 ::com::sun::star::uno::RuntimeException aExc(
485 "illegal member type description!",
486 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
488 Type const & rExcType = cppu::UnoType<decltype(aExc)>::get();
489 // binary identical null reference
490 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
495 } } }
497 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */