1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: uno2cpp.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 #include <rtl/alloc.h>
34 #include <com/sun/star/uno/genfunc.hxx>
35 #include "com/sun/star/uno/RuntimeException.hpp"
38 #include <bridges/cpp_uno/shared/bridge.hxx>
39 #include <bridges/cpp_uno/shared/types.hxx>
40 #include <bridges/cpp_uno/shared/unointerfaceproxy.hxx>
41 #include <bridges/cpp_uno/shared/vtables.hxx>
49 * Based on http://gcc.gnu.org/PR41443
50 * References to __SOFTFP__ are incorrect for EABI; the __SOFTFP__ code
51 * should be used for *soft-float ABI* whether or not VFP is enabled,
52 * and __SOFTFP__ does specifically mean soft-float not soft-float ABI.
54 * Changing the conditionals to __SOFTFP__ || __ARM_EABI__ then
55 * -mfloat-abi=softfp should work. -mfloat-abi=hard won't; that would
56 * need both a new macro to identify the hard-VFP ABI.
58 #if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
59 #error Not Implemented
62 some possibly handy code to detect that we have VFP registers
65 #include <sys/types.h>
71 #define HWCAP_ARM_VFP 64
75 int fd
= open ("/proc/self/auxv", O_RDONLY
);
81 Elf32_auxv_t buf
[128];
83 while ((ret
== -1) && ((n
= read(fd
, buf
, sizeof (buf
))) > 0))
85 for (int i
= 0; i
< 128; ++i
)
87 if (buf
[i
].a_type
== AT_HWCAP
)
89 ret
= (buf
[i
].a_un
.a_val
& HWCAP_ARM_VFP
) ? true : false;
92 else if (buf
[i
].a_type
== AT_NULL
)
106 using namespace ::rtl
;
107 using namespace ::com::sun::star::uno
;
111 enum armlimits
{ MAX_GPR_REGS
= 4 };
114 void MapReturn(long r0
, long r1
, typelib_TypeClass eReturnType
, void *pRegisterReturn
)
116 #if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
117 register float fret
asm("f0");
118 register double dret
asm("f0");
121 switch( eReturnType
)
123 case typelib_TypeClass_HYPER
:
124 case typelib_TypeClass_UNSIGNED_HYPER
:
125 ((long*)pRegisterReturn
)[1] = r1
;
126 case typelib_TypeClass_LONG
:
127 case typelib_TypeClass_UNSIGNED_LONG
:
128 case typelib_TypeClass_ENUM
:
129 ((long*)pRegisterReturn
)[0] = r0
;
131 case typelib_TypeClass_CHAR
:
132 case typelib_TypeClass_SHORT
:
133 case typelib_TypeClass_UNSIGNED_SHORT
:
134 *(unsigned short*)pRegisterReturn
= (unsigned short)r0
;
136 case typelib_TypeClass_BOOLEAN
:
137 case typelib_TypeClass_BYTE
:
138 *(unsigned char*)pRegisterReturn
= (unsigned char)r0
;
140 case typelib_TypeClass_FLOAT
:
141 #if defined(__ARM_EABI__) || defined(__SOFTFP__)
142 ((long*)pRegisterReturn
)[0] = r0
;
144 *(float*)pRegisterReturn
= fret
;
147 case typelib_TypeClass_DOUBLE
:
148 #if defined(__ARM_EABI__) || defined(__SOFTFP__)
149 ((long*)pRegisterReturn
)[1] = r1
;
150 ((long*)pRegisterReturn
)[0] = r0
;
152 *(double*)pRegisterReturn
= dret
;
162 //================================================================
164 void callVirtualMethod(
166 sal_Int32 nVtableIndex
,
167 void * pRegisterReturn
,
168 typelib_TypeClass eReturnType
,
172 sal_uInt32 nGPR
) __attribute__((noinline
));
174 void callVirtualMethod(
176 sal_Int32 nVtableIndex
,
177 void * pRegisterReturn
,
178 typelib_TypeClass eReturnType
,
186 CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
191 sal_uInt32 nStackBytes
= ( ( nStack
+ 1 ) >> 1 ) * 8;
192 sal_uInt32
*stack
= (sal_uInt32
*) __builtin_alloca( nStackBytes
);
193 memcpy( stack
, pStack
, nStackBytes
);
196 // Should not happen, but...
197 if ( nGPR
> arm::MAX_GPR_REGS
)
198 nGPR
= arm::MAX_GPR_REGS
;
200 sal_uInt32 pMethod
= *((sal_uInt32
*)pThis
);
201 pMethod
+= 4 * nVtableIndex
;
202 pMethod
= *((sal_uInt32
*)pMethod
);
204 typedef void (*FunctionCall
)( sal_uInt32
, sal_uInt32
, sal_uInt32
, sal_uInt32
);
205 FunctionCall pFunc
= (FunctionCall
)pMethod
;
208 __asm__
__volatile__ (
209 "ldr r0, [%0, #0]\n\t"
210 "ldr r1, [%0, #4]\n\t"
211 "ldr r2, [%0, #8]\n\t"
212 "ldr r3, [%0, #12]\n\t"
214 : "r0", "r1", "r2", "r3"
217 // tell gcc that r0 to r3 are not available to it
218 register sal_uInt32 r0
asm("r0");
219 register sal_uInt32 r1
asm("r1");
220 register sal_uInt32 r2
asm("r2");
221 register sal_uInt32 r3
asm("r3");
223 (*pFunc
)(r0
, r1
, r2
, r3
);
226 __asm__
__volatile__ (
229 : "=r" (r0
), "=r" (r1
) : );
231 MapReturn(r0
, r1
, eReturnType
, pRegisterReturn
);
235 #define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow ) \
236 if ( nr < arm::MAX_GPR_REGS ) \
237 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
241 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
244 #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
245 if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \
249 if ( nr < arm::MAX_GPR_REGS ) \
251 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
252 pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
258 if ( (pDS - pStart) % 2) \
262 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \
263 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \
266 #define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
267 INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow) \
268 INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS, bOverflow)
271 #define INSERT_FLOAT( pSV, nr, pFPR, pDS, bOverflow ) \
272 INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow)
274 #define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart, bOverflow ) \
275 INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow )
277 #define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \
278 if ( nr < arm::MAX_GPR_REGS ) \
279 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
283 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
285 #define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \
286 if ( nr < arm::MAX_GPR_REGS ) \
287 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
291 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
294 //=======================================================================
295 static void cpp_call(
296 bridges::cpp_uno::shared::UnoInterfaceProxy
* pThis
,
297 bridges::cpp_uno::shared::VtableSlot aVtableSlot
,
298 typelib_TypeDescriptionReference
* pReturnTypeRef
,
299 sal_Int32 nParams
, typelib_MethodParameter
* pParams
,
300 void * pUnoReturn
, void * pUnoArgs
[], uno_Any
** ppUnoExc
)
302 // max space for: [complex ret ptr], values|ptr ...
303 sal_uInt32
* pStack
= (sal_uInt32
*)__builtin_alloca(
304 sizeof(sal_Int32
) + ((nParams
+2) * sizeof(sal_Int64
)) );
305 sal_uInt32
* pStackStart
= pStack
;
307 sal_uInt32 pGPR
[arm::MAX_GPR_REGS
];
311 typelib_TypeDescription
* pReturnTypeDescr
= 0;
312 TYPELIB_DANGER_GET( &pReturnTypeDescr
, pReturnTypeRef
);
313 OSL_ENSURE( pReturnTypeDescr
, "### expected return type description!" );
315 void * pCppReturn
= 0; // if != 0 && != pUnoReturn, needs reconversion
317 bool bOverFlow
= false;
319 if (pReturnTypeDescr
)
322 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr
))
324 pCppReturn
= pUnoReturn
; // direct way for simple types
328 // complex return via ptr
329 pCppReturn
= (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr
)
330 ? __builtin_alloca( pReturnTypeDescr
->nSize
)
331 : pUnoReturn
); // direct way
333 INSERT_INT32( &pCppReturn
, nGPR
, pGPR
, pStack
, bOverFlow
);
337 void * pAdjustedThisPtr
= reinterpret_cast< void ** >(pThis
->getCppI())
338 + aVtableSlot
.offset
;
339 INSERT_INT32( &pAdjustedThisPtr
, nGPR
, pGPR
, pStack
, bOverFlow
);
342 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32
), "### unexpected size!" );
344 void ** pCppArgs
= (void **)alloca( 3 * sizeof(void *) * nParams
);
345 // indizes of values this have to be converted (interface conversion cpp<=>uno)
346 sal_Int32
* pTempIndizes
= (sal_Int32
*)(pCppArgs
+ nParams
);
347 // type descriptions for reconversions
348 typelib_TypeDescription
** ppTempParamTypeDescr
= (typelib_TypeDescription
**)(pCppArgs
+ (2 * nParams
));
350 sal_Int32 nTempIndizes
= 0;
352 for ( sal_Int32 nPos
= 0; nPos
< nParams
; ++nPos
)
354 const typelib_MethodParameter
& rParam
= pParams
[nPos
];
355 typelib_TypeDescription
* pParamTypeDescr
= 0;
356 TYPELIB_DANGER_GET( &pParamTypeDescr
, rParam
.pTypeRef
);
358 if (!rParam
.bOut
&& bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr
))
360 // uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
361 uno_copyAndConvertData( pCppArgs
[nPos
] = alloca(8), pUnoArgs
[nPos
],
362 pParamTypeDescr
, pThis
->getBridge()->getUno2Cpp() );
364 switch (pParamTypeDescr
->eTypeClass
)
366 case typelib_TypeClass_HYPER
:
367 case typelib_TypeClass_UNSIGNED_HYPER
:
369 fprintf(stderr
, "hyper is %lx\n", pCppArgs
[nPos
]);
371 INSERT_INT64( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
, pStackStart
, bOverFlow
);
373 case typelib_TypeClass_LONG
:
374 case typelib_TypeClass_UNSIGNED_LONG
:
375 case typelib_TypeClass_ENUM
:
377 fprintf(stderr
, "long is %x\n", pCppArgs
[nPos
]);
379 INSERT_INT32( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
, bOverFlow
);
381 case typelib_TypeClass_SHORT
:
382 case typelib_TypeClass_CHAR
:
383 case typelib_TypeClass_UNSIGNED_SHORT
:
384 INSERT_INT16( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
, bOverFlow
);
386 case typelib_TypeClass_BOOLEAN
:
387 case typelib_TypeClass_BYTE
:
388 INSERT_INT8( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
, bOverFlow
);
390 case typelib_TypeClass_FLOAT
:
391 INSERT_FLOAT( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
, bOverFlow
);
393 case typelib_TypeClass_DOUBLE
:
394 INSERT_DOUBLE( pCppArgs
[nPos
], nGPR
, pGPR
, pStack
, pStackStart
, bOverFlow
);
398 TYPELIB_DANGER_RELEASE( pParamTypeDescr
);
400 else // ptr to complex value | ref
402 if (! rParam
.bIn
) // is pure out
404 // cpp out is constructed mem, uno out is not!
406 pCppArgs
[nPos
] = alloca( pParamTypeDescr
->nSize
),
408 pTempIndizes
[nTempIndizes
] = nPos
; // default constructed for cpp call
409 // will be released at reconversion
410 ppTempParamTypeDescr
[nTempIndizes
++] = pParamTypeDescr
;
413 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr
))
415 uno_copyAndConvertData(
416 pCppArgs
[nPos
] = alloca( pParamTypeDescr
->nSize
),
417 pUnoArgs
[nPos
], pParamTypeDescr
, pThis
->getBridge()->getUno2Cpp() );
419 pTempIndizes
[nTempIndizes
] = nPos
; // has to be reconverted
420 // will be released at reconversion
421 ppTempParamTypeDescr
[nTempIndizes
++] = pParamTypeDescr
;
425 pCppArgs
[nPos
] = pUnoArgs
[nPos
];
427 TYPELIB_DANGER_RELEASE( pParamTypeDescr
);
429 INSERT_INT32( &(pCppArgs
[nPos
]), nGPR
, pGPR
, pStack
, bOverFlow
);
436 pAdjustedThisPtr
, aVtableSlot
.index
,
437 pCppReturn
, pReturnTypeDescr
->eTypeClass
,
439 (pStack
- pStackStart
),
442 // NO exception occured...
445 // reconvert temporary params
446 for ( ; nTempIndizes
--; )
448 sal_Int32 nIndex
= pTempIndizes
[nTempIndizes
];
449 typelib_TypeDescription
* pParamTypeDescr
= ppTempParamTypeDescr
[nTempIndizes
];
451 if (pParams
[nIndex
].bIn
)
453 if (pParams
[nIndex
].bOut
) // inout
455 uno_destructData( pUnoArgs
[nIndex
], pParamTypeDescr
, 0 ); // destroy uno value
456 uno_copyAndConvertData( pUnoArgs
[nIndex
], pCppArgs
[nIndex
], pParamTypeDescr
,
457 pThis
->getBridge()->getCpp2Uno() );
462 uno_copyAndConvertData( pUnoArgs
[nIndex
], pCppArgs
[nIndex
], pParamTypeDescr
,
463 pThis
->getBridge()->getCpp2Uno() );
465 // destroy temp cpp param => cpp: every param was constructed
466 uno_destructData( pCppArgs
[nIndex
], pParamTypeDescr
, cpp_release
);
468 TYPELIB_DANGER_RELEASE( pParamTypeDescr
);
471 if (pCppReturn
&& pUnoReturn
!= pCppReturn
)
473 uno_copyAndConvertData( pUnoReturn
, pCppReturn
, pReturnTypeDescr
,
474 pThis
->getBridge()->getCpp2Uno() );
475 uno_destructData( pCppReturn
, pReturnTypeDescr
, cpp_release
);
480 // __asm__ __volatile__ ("sub sp, sp, #2048\n");
482 // fill uno exception
483 fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions
, *ppUnoExc
, pThis
->getBridge()->getCpp2Uno() );
486 for ( ; nTempIndizes
--; )
488 sal_Int32 nIndex
= pTempIndizes
[nTempIndizes
];
489 // destroy temp cpp param => cpp: every param was constructed
490 uno_destructData( pCppArgs
[nIndex
], ppTempParamTypeDescr
[nTempIndizes
], cpp_release
);
491 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr
[nTempIndizes
] );
495 if (pReturnTypeDescr
)
496 TYPELIB_DANGER_RELEASE( pReturnTypeDescr
);
501 namespace bridges
{ namespace cpp_uno
{ namespace shared
{
503 void unoInterfaceProxyDispatch(
504 uno_Interface
* pUnoI
, const typelib_TypeDescription
* pMemberDescr
,
505 void * pReturn
, void * pArgs
[], uno_Any
** ppException
)
508 bridges::cpp_uno::shared::UnoInterfaceProxy
* pThis
509 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy
* >(pUnoI
);
510 typelib_InterfaceTypeDescription
* pTypeDescr
= pThis
->pTypeDescr
;
512 switch (pMemberDescr
->eTypeClass
)
514 case typelib_TypeClass_INTERFACE_ATTRIBUTE
:
516 // determine vtable call index
517 sal_Int32 nMemberPos
= ((typelib_InterfaceMemberTypeDescription
*)pMemberDescr
)->nPosition
;
518 OSL_ENSURE( nMemberPos
< pTypeDescr
->nAllMembers
, "### member pos out of range!" );
520 VtableSlot
aVtableSlot(
522 reinterpret_cast<typelib_InterfaceAttributeTypeDescription
const *>
527 // dependent dispatch
530 ((typelib_InterfaceAttributeTypeDescription
*)pMemberDescr
)->pAttributeTypeRef
,
532 pReturn
, pArgs
, ppException
);
537 typelib_MethodParameter aParam
;
539 ((typelib_InterfaceAttributeTypeDescription
*)pMemberDescr
)->pAttributeTypeRef
;
540 aParam
.bIn
= sal_True
;
541 aParam
.bOut
= sal_False
;
543 typelib_TypeDescriptionReference
* pReturnTypeRef
= 0;
544 OUString
aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
545 typelib_typedescriptionreference_new(
546 &pReturnTypeRef
, typelib_TypeClass_VOID
, aVoidName
.pData
);
548 // dependent dispatch
549 aVtableSlot
.index
+= 1;
551 pThis
, aVtableSlot
, // get, then set method
554 pReturn
, pArgs
, ppException
);
556 typelib_typedescriptionreference_release( pReturnTypeRef
);
561 case typelib_TypeClass_INTERFACE_METHOD
:
563 // determine vtable call index
564 sal_Int32 nMemberPos
= ((typelib_InterfaceMemberTypeDescription
*)pMemberDescr
)->nPosition
;
565 OSL_ENSURE( nMemberPos
< pTypeDescr
->nAllMembers
, "### member pos out of range!" );
567 VtableSlot
aVtableSlot(
569 reinterpret_cast<typelib_InterfaceMethodTypeDescription
const *>
572 switch (aVtableSlot
.index
)
575 case 1: // acquire uno interface
576 (*pUnoI
->acquire
)( pUnoI
);
579 case 2: // release uno interface
580 (*pUnoI
->release
)( pUnoI
);
583 case 0: // queryInterface() opt
585 typelib_TypeDescription
* pTD
= 0;
586 TYPELIB_DANGER_GET( &pTD
, reinterpret_cast< Type
* >( pArgs
[0] )->getTypeLibType() );
589 uno_Interface
* pInterface
= 0;
590 (*pThis
->getBridge()->getUnoEnv()->getRegisteredInterface
)(
591 pThis
->getBridge()->getUnoEnv(),
592 (void **)&pInterface
, pThis
->oid
.pData
, (typelib_InterfaceTypeDescription
*)pTD
);
597 reinterpret_cast< uno_Any
* >( pReturn
),
598 &pInterface
, pTD
, 0 );
599 (*pInterface
->release
)( pInterface
);
600 TYPELIB_DANGER_RELEASE( pTD
);
604 TYPELIB_DANGER_RELEASE( pTD
);
606 } // else perform queryInterface()
608 // dependent dispatch
611 ((typelib_InterfaceMethodTypeDescription
*)pMemberDescr
)->pReturnTypeRef
,
612 ((typelib_InterfaceMethodTypeDescription
*)pMemberDescr
)->nParams
,
613 ((typelib_InterfaceMethodTypeDescription
*)pMemberDescr
)->pParams
,
614 pReturn
, pArgs
, ppException
);
620 ::com::sun::star::uno::RuntimeException
aExc(
621 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
622 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>() );
624 Type
const & rExcType
= ::getCppuType( &aExc
);
625 // binary identical null reference
626 ::uno_type_any_construct( *ppException
, &aExc
, rExcType
.getTypeLibType(), 0 );
633 /* vi:set tabstop=4 shiftwidth=4 expandtab: */