From dce434e245a25a28a2bcd4aae8a40dd3bb3c2f63 Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Tue, 27 Apr 2010 11:17:28 +0100 Subject: armeabi02: #i105359# fix arm-eabi uno bridge, fix exception handling, and fix struct returning rules --- bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S | 38 +++++++++ bridges/source/cpp_uno/gcc3_linux_arm/armhelper.s | 22 ----- bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx | 30 +++---- bridges/source/cpp_uno/gcc3_linux_arm/except.cxx | 6 +- bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk | 2 +- bridges/source/cpp_uno/gcc3_linux_arm/share.hxx | 7 ++ bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx | 99 ++++++++++++++++------- 7 files changed, 133 insertions(+), 71 deletions(-) create mode 100644 bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S delete mode 100644 bridges/source/cpp_uno/gcc3_linux_arm/armhelper.s (limited to 'bridges') diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S new file mode 100644 index 000000000000..8db287174680 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S @@ -0,0 +1,38 @@ +@ ARM support code for OpenOffice C++/UNO bridging +@ +@ Written by Peter Naulls +@ Modified by Caolan McNamara +@ Fixed by Michael Casadevall + +#ifdef __ARM_EABI__ +# define UNWIND +#else +# define UNWIND @ +#endif + + .file "armhelper.s" + .text + .align 4 + .global privateSnippetExecutor + .type privateSnippetExecutor, %function +privateSnippetExecutor: + UNWIND .fnstart @ start of unwinder entry + + stmfd sp!, {r0-r3} @ follow other parameters on stack + UNWIND .pad #16 @ throw this data away on exception + mov r0, ip @ r0 points to functionoffset/vtable + mov r1, sp @ r1 points to this and params + @ (see cppuno.cxx:codeSnippet()) + stmfd sp!, {r4,lr} @ save return address + @ (r4 pushed to preserve stack alignment) + UNWIND .save {r4,lr} @ restore these regs on exception + + bl cpp_vtable_call(PLT) + + add sp, sp, #4 @ no need to restore r4 (we didn't touch it) + ldr pc, [sp], #20 @ return, discarding function arguments + + UNWIND .fnend @ end of unwinder entry + + .size privateSnippetExecutor, . - privateSnippetExecutor + .section .note.GNU-stack,"",%progbits diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.s b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.s deleted file mode 100644 index 8fd1a38e4f51..000000000000 --- a/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.s +++ /dev/null @@ -1,22 +0,0 @@ -@ ARM support code for OpenOffice C++/UNO bridging -@ -@ Written by Peter Naulls -@ Modified by Caolan McNamara - .file "armhelper.s" - .text - .align 4 - .global privateSnippetExecutor - .type privateSnippetExecutor, %function -privateSnippetExecutor: - stmfd sp!, {r0-r3} @ follow other parameters on stack - mov r0, ip @ r0 points to functionoffset/vtable - mov ip, sp @ fix up the ip - stmfd sp!, {fp,ip,lr,pc} @ 8 x 4 => stack remains 8 aligned - sub fp, ip, #4 @ set frame pointer - - add r1, sp, #16 @ r1 points to this and params - bl cpp_vtable_call(PLT) - - add sp, sp, #32 @ restore stack - ldr fp, [sp, #-32] @ restore frame pointer - ldr pc, [sp, #-24] @ return diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx index 98c213a53a83..54239945df19 100644 --- a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx @@ -76,10 +76,8 @@ namespace if (pReturnTypeDescr) { - if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) - { + if (!arm::return_in_hidden_param(pReturnTypeRef)) pUnoReturn = pRegisterReturn; // direct way for simple types - } else // complex return via ptr (pCppReturn) { pCppReturn = *(void **)pCppStack; @@ -422,9 +420,9 @@ namespace const int codeSnippetSize = 20; unsigned char *codeSnippet(unsigned char* code, sal_Int32 functionIndex, - sal_Int32 vtableOffset, bool simple_ret_type ) + sal_Int32 vtableOffset, bool bHasHiddenParam) { - if (!simple_ret_type) + if (bHasHiddenParam) functionIndex |= 0x80000000; unsigned long * p = (unsigned long *)code; @@ -478,24 +476,25 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( switch (member->eTypeClass) { case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + typelib_InterfaceAttributeTypeDescription *pAttrTD = + reinterpret_cast( member ); + // Getter: (s++)->fn = code + writetoexecdiff; code = codeSnippet( code, functionOffset++, vtableOffset, - bridges::cpp_uno::shared::isSimpleType( - reinterpret_cast< - typelib_InterfaceAttributeTypeDescription * >( - member)->pAttributeTypeRef)); + arm::return_in_hidden_param( pAttrTD->pAttributeTypeRef )); + // Setter: - if (!reinterpret_cast< - typelib_InterfaceAttributeTypeDescription * >( - member)->bReadOnly) + if (!pAttrTD->bReadOnly) { (s++)->fn = code + writetoexecdiff; code = codeSnippet( - code, functionOffset++, vtableOffset, true); + code, functionOffset++, vtableOffset, false); } break; + } case typelib_TypeClass_INTERFACE_METHOD: { (s++)->fn = code + writetoexecdiff; @@ -504,11 +503,8 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(member); - bool issimple = bridges::cpp_uno::shared::isSimpleType( - pMethodTD->pReturnTypeRef); - code = codeSnippet(code, functionOffset++, vtableOffset, - issimple); + arm::return_in_hidden_param(pMethodTD->pReturnTypeRef)); break; } default: diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/except.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/except.cxx index df717fe1f279..ec1e671a72ba 100644 --- a/bridges/source/cpp_uno/gcc3_linux_arm/except.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_arm/except.cxx @@ -162,8 +162,8 @@ namespace CPPU_CURRENT_NAMESPACE else { // try to lookup the symbol in the generated rtti map - t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) ); - if (iFind == m_generatedRttis.end()) + t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) ); + if (iFind2 == m_generatedRttis.end()) { // we must generate it ! // symbol and rtti-name is nearly identical, @@ -192,7 +192,7 @@ namespace CPPU_CURRENT_NAMESPACE } else // taking already generated rtti { - rtti = iFind->second; + rtti = iFind2->second; } } } diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk b/bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk index 44c557795510..0900ec11f41f 100644 --- a/bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk +++ b/bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk @@ -80,5 +80,5 @@ SHL1STDLIBS= \ .INCLUDE : target.mk -$(SLO)$/%.obj: %.s +$(SLO)$/%.obj: %.S $(CXX) -c -o $(SLO)$/$(@:b).o $< -fPIC ; touch $@ diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx b/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx index cfe220abaf17..fb72c360fd45 100644 --- a/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx +++ b/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx @@ -89,5 +89,12 @@ namespace CPPU_CURRENT_NAMESPACE void fillUnoException( __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); } + +namespace arm +{ + enum armlimits { MAX_GPR_REGS = 4 }; + bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); +} + #endif /* vi:set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx index 154ae52027bb..8d40be39b5ab 100644 --- a/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx @@ -105,17 +105,58 @@ using namespace ::com::sun::star::uno; namespace arm { - enum armlimits { MAX_GPR_REGS = 4 }; + bool is_complex_struct(const typelib_TypeDescription * type) + { + const typelib_CompoundTypeDescription * p + = reinterpret_cast< const typelib_CompoundTypeDescription * >(type); + for (sal_Int32 i = 0; i < p->nMembers; ++i) + { + if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT || + p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * t = 0; + TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]); + bool b = is_complex_struct(t); + TYPELIB_DANGER_RELEASE(t); + if (b) { + return true; + } + } + else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass)) + return true; + } + if (p->pBaseTypeDescription != 0) + return is_complex_struct(&p->pBaseTypeDescription->aBase); + return false; + } + + bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) + { + if (bridges::cpp_uno::shared::isSimpleType(pTypeRef)) + return false; + else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); + + //A Composite Type not larger than 4 bytes is returned in r0 + bool bRet = pTypeDescr->nSize > 4 || is_complex_struct(pTypeDescr); + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return bRet; + } + return true; + } } -void MapReturn(long r0, long r1, typelib_TypeClass eReturnType, void *pRegisterReturn) +void MapReturn(long r0, long r1, typelib_TypeDescriptionReference * pReturnType, void *pRegisterReturn) { #if !defined(__ARM_EABI__) && !defined(__SOFTFP__) register float fret asm("f0"); register double dret asm("f0"); #endif - switch( eReturnType ) + switch( pReturnType->eTypeClass ) { case typelib_TypeClass_HYPER: case typelib_TypeClass_UNSIGNED_HYPER: @@ -149,6 +190,13 @@ void MapReturn(long r0, long r1, typelib_TypeClass eReturnType, void *pRegisterR *(double*)pRegisterReturn = dret; #endif break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + if (!arm::return_in_hidden_param(pReturnType)) + ((long*)pRegisterReturn)[0] = r0; + break; + } default: break; } @@ -162,7 +210,7 @@ void callVirtualMethod( void * pThis, sal_Int32 nVtableIndex, void * pRegisterReturn, - typelib_TypeClass eReturnType, + typelib_TypeDescriptionReference * pReturnType, sal_uInt32 *pStack, sal_uInt32 nStack, sal_uInt32 *pGPR, @@ -172,7 +220,7 @@ void callVirtualMethod( void * pThis, sal_Int32 nVtableIndex, void * pRegisterReturn, - typelib_TypeClass eReturnType, + typelib_TypeDescriptionReference * pReturnType, sal_uInt32 *pStack, sal_uInt32 nStack, sal_uInt32 *pGPR, @@ -201,23 +249,10 @@ void callVirtualMethod( typedef void (*FunctionCall )( sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32); FunctionCall pFunc = (FunctionCall)pMethod; - // fill registers - __asm__ __volatile__ ( - "ldr r0, [%0, #0]\n\t" - "ldr r1, [%0, #4]\n\t" - "ldr r2, [%0, #8]\n\t" - "ldr r3, [%0, #12]\n\t" - : : "r" (pGPR) - : "r0", "r1", "r2", "r3" - ); - - // tell gcc that r0 to r3 are not available to it - register sal_uInt32 r0 asm("r0"); - register sal_uInt32 r1 asm("r1"); - register sal_uInt32 r2 asm("r2"); - register sal_uInt32 r3 asm("r3"); - - (*pFunc)(r0, r1, r2, r3); + (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3]); + + sal_uInt32 r0; + sal_uInt32 r1; // get return value __asm__ __volatile__ ( @@ -225,7 +260,7 @@ void callVirtualMethod( "mov %1, r1\n\t" : "=r" (r0), "=r" (r1) : ); - MapReturn(r0, r1, eReturnType, pRegisterReturn); + MapReturn(r0, r1, pReturnType, pRegisterReturn); } } @@ -312,14 +347,14 @@ static void cpp_call( void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion bool bOverFlow = false; - + bool bSimpleReturn = true; if (pReturnTypeDescr) { + if (arm::return_in_hidden_param( pReturnTypeRef ) ) + bSimpleReturn = false; - if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) - { + if (bSimpleReturn) pCppReturn = pUnoReturn; // direct way for simple types - } else { // complex return via ptr @@ -390,6 +425,8 @@ static void cpp_call( case typelib_TypeClass_DOUBLE: INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow ); break; + default: + break; } // no longer needed TYPELIB_DANGER_RELEASE( pParamTypeDescr ); @@ -431,7 +468,7 @@ static void cpp_call( { callVirtualMethod( pAdjustedThisPtr, aVtableSlot.index, - pCppReturn, pReturnTypeDescr->eTypeClass, + pCppReturn, pReturnTypeRef, pStackStart, (pStack - pStackStart), pGPR, nGPR); @@ -504,15 +541,19 @@ void unoInterfaceProxyDispatch( // is my surrogate bridges::cpp_uno::shared::UnoInterfaceProxy * pThis = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); +#if OSL_DEBUG_LEVEL > 0 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; +#endif switch (pMemberDescr->eTypeClass) { case typelib_TypeClass_INTERFACE_ATTRIBUTE: { +#if OSL_DEBUG_LEVEL > 0 // determine vtable call index sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif VtableSlot aVtableSlot( getVtableSlot( @@ -557,9 +598,11 @@ void unoInterfaceProxyDispatch( } case typelib_TypeClass_INTERFACE_METHOD: { +#if OSL_DEBUG_LEVEL > 0 // determine vtable call index sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); +#endif VtableSlot aVtableSlot( getVtableSlot( -- cgit From 867721d3e825be238785847a703c211d0e61d0ab Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Tue, 4 May 2010 14:33:17 +0100 Subject: armeabi02: #i105359# fix arm-eabi uno bridge --- bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S | 2 +- bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx | 24 ++++++++++++++++++++++- bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx | 20 ++++++++----------- 3 files changed, 32 insertions(+), 14 deletions(-) (limited to 'bridges') diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S index 8db287174680..d5faf15eed6f 100644 --- a/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S +++ b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S @@ -2,7 +2,7 @@ @ @ Written by Peter Naulls @ Modified by Caolan McNamara -@ Fixed by Michael Casadevall +@ Fixed by Michael Casadevall #ifdef __ARM_EABI__ # define UNWIND diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx index 54239945df19..0e801ab4433e 100644 --- a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx @@ -408,8 +408,30 @@ extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset, void **pCallStack ) { sal_Int64 nRegReturn; - cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, + typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, &nRegReturn ); + + switch( aType ) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + nRegReturn = (unsigned long)(*(unsigned char *)&nRegReturn); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_SHORT: + nRegReturn = (unsigned long)(*(unsigned short *)&nRegReturn); + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_LONG: + nRegReturn = (unsigned long)(*(unsigned int *)&nRegReturn); + break; + case typelib_TypeClass_VOID: + default: + break; + } + return nRegReturn; } diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx index 8d40be39b5ab..be67ed8fd830 100644 --- a/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx @@ -149,7 +149,7 @@ namespace arm } } -void MapReturn(long r0, long r1, typelib_TypeDescriptionReference * pReturnType, void *pRegisterReturn) +void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* pRegisterReturn) { #if !defined(__ARM_EABI__) && !defined(__SOFTFP__) register float fret asm("f0"); @@ -160,32 +160,28 @@ void MapReturn(long r0, long r1, typelib_TypeDescriptionReference * pReturnType, { case typelib_TypeClass_HYPER: case typelib_TypeClass_UNSIGNED_HYPER: - ((long*)pRegisterReturn)[1] = r1; + pRegisterReturn[1] = r1; case typelib_TypeClass_LONG: case typelib_TypeClass_UNSIGNED_LONG: case typelib_TypeClass_ENUM: - ((long*)pRegisterReturn)[0] = r0; - break; case typelib_TypeClass_CHAR: case typelib_TypeClass_SHORT: case typelib_TypeClass_UNSIGNED_SHORT: - *(unsigned short*)pRegisterReturn = (unsigned short)r0; - break; case typelib_TypeClass_BOOLEAN: case typelib_TypeClass_BYTE: - *(unsigned char*)pRegisterReturn = (unsigned char)r0; + pRegisterReturn[0] = r0; break; case typelib_TypeClass_FLOAT: #if defined(__ARM_EABI__) || defined(__SOFTFP__) - ((long*)pRegisterReturn)[0] = r0; + pRegisterReturn[0] = r0; #else *(float*)pRegisterReturn = fret; #endif break; case typelib_TypeClass_DOUBLE: #if defined(__ARM_EABI__) || defined(__SOFTFP__) - ((long*)pRegisterReturn)[1] = r1; - ((long*)pRegisterReturn)[0] = r0; + pRegisterReturn[1] = r1; + pRegisterReturn[0] = r0; #else *(double*)pRegisterReturn = dret; #endif @@ -194,7 +190,7 @@ void MapReturn(long r0, long r1, typelib_TypeDescriptionReference * pReturnType, case typelib_TypeClass_EXCEPTION: { if (!arm::return_in_hidden_param(pReturnType)) - ((long*)pRegisterReturn)[0] = r0; + pRegisterReturn[0] = r0; break; } default: @@ -260,7 +256,7 @@ void callVirtualMethod( "mov %1, r1\n\t" : "=r" (r0), "=r" (r1) : ); - MapReturn(r0, r1, pReturnType, pRegisterReturn); + MapReturn(r0, r1, pReturnType, (sal_uInt32*)pRegisterReturn); } } -- cgit