diff options
author | Tor Lillqvist <tml@collabora.com> | 2013-12-20 23:57:06 +0200 |
---|---|---|
committer | Tor Lillqvist <tml@collabora.com> | 2013-12-21 18:57:09 +0200 |
commit | 928c8c800e2d6c17a768ea8fe2767a2ea68fba20 (patch) | |
tree | 32bec61fbef57eb2483cb4217b59e2f82d640e78 /bridges/source | |
parent | c8b624329caed68550fcb1fe197c8fa8107d079b (diff) |
iOS arm64 C++/UNO bridge WIP
Change-Id: I5eb994e4a48b043f463940d1c34ad7a9459b83cd
Diffstat (limited to 'bridges/source')
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm64.cxx | 69 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios_arm/except.cxx | 1 | ||||
-rwxr-xr-x | bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl | 8 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios_arm/helper.s | 19 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios_arm/share.hxx | 14 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm64.cxx | 354 |
6 files changed, 193 insertions, 272 deletions
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm64.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm64.cxx index 54441b87149b..1b68c1edbe8b 100644 --- a/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm64.cxx +++ b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm64.cxx @@ -20,9 +20,7 @@ #ifdef __arm64 // For iOS devices (64-bit ARM). Originally a copy of -// ../gcc3_linux_arm/cpp2uno.cxx with some cleanups and necessary -// changes: No dynamic code generation as that is prohibited for apps -// in the App Store. Instead we use a set of pre-generated snippets. +// ../gcc3_linux_arm/cpp2uno.cxx. // No attempts at factoring out the large amounts of more or less // common code in this, cpp2uno-arm.cxx and cpp2uno-i386.cxx have been @@ -49,23 +47,19 @@ using namespace ::com::sun::star::uno; namespace { - static typelib_TypeClass cpp2uno_call( bridges::cpp_uno::shared::CppInterfaceProxy* pThis, const typelib_TypeDescription * pMemberTypeDescr, typelib_TypeDescriptionReference * pReturnTypeRef, - sal_Int32 nParams, typelib_MethodParameter * pParams, + sal_Int32 nParams, + typelib_MethodParameter * pParams, void ** pCallStack, sal_Int64 * pRegisterReturn /* space for register return */ ) { - // pCallStack: ret, [return ptr], this, params + // pCallStack: x8, ret, [return ptr], this, params char * pTopStack = (char *)(pCallStack + 0); char * pCppStack = pTopStack; -#ifdef __ARM_PCS_VFP - int dc = 0; - char * pFloatArgs = (char *)(pCppStack - 64); -#endif // return typelib_TypeDescription * pReturnTypeDescr = 0; if (pReturnTypeRef) @@ -77,7 +71,7 @@ namespace if (pReturnTypeDescr) { - if (!arm::return_in_hidden_param(pReturnTypeRef)) + if (!arm::return_in_x8(pReturnTypeRef)) pUnoReturn = pRegisterReturn; // direct way for simple types else // complex return via ptr (pCppReturn) { @@ -99,14 +93,14 @@ namespace // Indices of values this have to be converted (interface conversion // cpp<=>uno) - sal_Int32 * pTempIndices = (sal_Int32 *)alloca( sizeof(sal_Int32) * nParams); + int * pTempIndices = (sal_Int32 *)alloca( sizeof(int) * nParams); // Type descriptions for reconversions typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(typelib_TypeDescription *) * nParams); - sal_Int32 nTempIndices = 0; + int nTempIndices = 0; - for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + for ( int nPos = 0; nPos < nParams; ++nPos ) { const typelib_MethodParameter & rParam = pParams[nPos]; typelib_TypeDescription * pParamTypeDescr = 0; @@ -221,7 +215,7 @@ namespace // destruct temporary in/inout params for ( ; nTempIndices--; ) { - sal_Int32 nIndex = pTempIndices[nTempIndices]; + int nIndex = pTempIndices[nTempIndices]; if (pParams[nIndex].bIn) // is in/inout => was constructed uno_destructData( pUnoArgs[nIndex], @@ -241,7 +235,7 @@ namespace // temporary params for ( ; nTempIndices--; ) { - sal_Int32 nIndex = pTempIndices[nTempIndices]; + int nIndex = pTempIndices[nTempIndices]; typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices]; @@ -285,25 +279,15 @@ namespace //===================================================================== - static typelib_TypeClass cpp_mediate( - sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, - void ** pCallStack, - sal_Int64 * pRegisterReturn /* space for register return */ ) + static typelib_TypeClass cpp_mediate( sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** pCallStack, + sal_Int64 * pRegisterReturn ) { - OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); - - // pCallStack: [ret *], this, params + // pCallStack: x8, ret *, this, params // _this_ ptr is patched cppu_XInterfaceProxy object - void *pThis; - if( nFunctionIndex & 0x80000000 ) - { - nFunctionIndex &= 0x7fffffff; - pThis = pCallStack[1]; - } - else - { - pThis = pCallStack[0]; - } + nFunctionIndex &= 0x7fffffff; + void *pThis = pCallStack[2]; pThis = static_cast< char * >(pThis) - nVtableOffset; bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = @@ -427,12 +411,11 @@ namespace * (called by asm snippets) */ -extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset, - void **pCallStack ) +extern "C" sal_Int64 cpp_vtable_call( sal_Int32 *pFunctionAndOffset, + void **pCallStack ) { sal_Int64 nRegReturn; - typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, - &nRegReturn ); + typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, &nRegReturn ); switch( aType ) { @@ -461,7 +444,7 @@ extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset, namespace { unsigned char *codeSnippet(sal_Int32 functionIndex, - sal_Int32 vtableOffset, bool bHasHiddenParam) + sal_Int32 vtableOffset, bool bReturnThroughX8) { assert(functionIndex < nFunIndexes); if (!(functionIndex < nFunIndexes)) @@ -472,14 +455,14 @@ namespace return NULL; // The codeSnippets table is indexed by functionIndex, - // vtableOffset, and the has-hidden-param flag + // vtableOffset, and the return-through-x8 flag - int index = functionIndex*nVtableOffsets*2 + vtableOffset*2 + bHasHiddenParam; + int index = functionIndex*nVtableOffsets*2 + vtableOffset*2 + bReturnThroughX8; unsigned char *result = ((unsigned char *) &codeSnippets) + codeSnippets[index]; SAL_INFO( "bridges.ios", "codeSnippet: [" << - functionIndex << "," << vtableOffset << "," << bHasHiddenParam << "]=" << + functionIndex << "," << vtableOffset << "," << bReturnThroughX8 << "]=" << (void *) result); return result; @@ -532,7 +515,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( // Getter: (s++)->fn = codeSnippet( functionOffset++, vtableOffset, - arm::return_in_hidden_param( pAttrTD->pAttributeTypeRef )); + arm::return_in_x8( pAttrTD->pAttributeTypeRef )); // Setter: if (!pAttrTD->bReadOnly) @@ -549,7 +532,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( typelib_InterfaceMethodTypeDescription * >(member); (s++)->fn = codeSnippet(functionOffset++, vtableOffset, - arm::return_in_hidden_param(pMethodTD->pReturnTypeRef)); + arm::return_in_x8(pMethodTD->pReturnTypeRef)); break; } default: diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx index e0232978b0a5..e21dce7aee60 100644 --- a/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx +++ b/bridges/source/cpp_uno/gcc3_ios_arm/except.cxx @@ -17,7 +17,6 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ - #include <dlfcn.h> #include <cxxabi.h> #include <boost/unordered_map.hpp> diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl b/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl index c89f2ed7bd4e..b6ffc079b105 100755 --- a/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl +++ b/bridges/source/cpp_uno/gcc3_ios_arm/generate-snippets.pl @@ -39,10 +39,10 @@ printf (".text\n"); printf ("#if defined(__arm) || defined(__arm64)\n"); printf ("\n"); -printf ("// Each codeSnippetX function stores into ip/x15 an address and branches to _privateSnippetExecutor\n"); -printf ("// The branch instruction is followed by two longs that ip/x15 points to:\n"); -printf ("// - the function index, as such and with the 0x80000000 bit set\n"); -printf ("// (to indicate a hidden parameter for returning large values)\n"); +printf ("// Each codeSnippetX function stores into ip (arm64: x15) an address and branches to _privateSnippetExecutor\n"); +printf ("// The address is that following the branch instruction, containing two 32-bit ints:\n"); +printf ("// - the function index, as such or with the 0x80000000 bit set\n"); +printf ("// (to indicate that a hidden parameter (arm64: x8) is used for returning large values)\n"); printf ("// - the vtable offset\n"); printf ("\n"); diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/helper.s b/bridges/source/cpp_uno/gcc3_ios_arm/helper.s index 27c7c04ed1fc..bf84f654df10 100644 --- a/bridges/source/cpp_uno/gcc3_ios_arm/helper.s +++ b/bridges/source/cpp_uno/gcc3_ios_arm/helper.s @@ -35,7 +35,7 @@ _privateSnippetExecutor: mov r0, ip // r0 points to functionoffset/vtable mov r1, sp // r1 points to this and params // (see cpp2uno.cxx:codeSnippet()) - stmfd sp!, {r4,lr} // save return address + stmfd sp!, {r4, lr} // save return address // (r4 pushed to preserve stack alignment) bl _cpp_vtable_call @@ -49,9 +49,20 @@ _privateSnippetExecutor: _privateSnippetExecutor: - // Not done yet, intentionally crash for now... - mov x15, #0 - ldr x15, [x15] + stp x6, x7, [sp, #-16]! + stp x4, x5, [sp, #-16]! + stp x2, x3, [sp, #-16]! + stp x0, x1, [sp, #-16]! + + mov x0, x15 + stp x8, lr, [sp, #-16]! + mov x1, sp + + bl _cpp_vtable_call + + ldp x8, lr, [sp, #0] + add sp, sp, #80 + ret lr #else .text diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx b/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx index 37ae457ab426..c719aa2b683a 100644 --- a/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx +++ b/bridges/source/cpp_uno/gcc3_ios_arm/share.hxx @@ -47,8 +47,18 @@ namespace CPPU_CURRENT_NAMESPACE namespace arm { - enum armlimits { MAX_GPR_REGS = 4, MAX_FPR_REGS = 8 }; - bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); + enum armlimits { +#if defined(__arm) + MAX_GPR_REGS = 4, + MAX_FPR_REGS = 8 +#elif defined(__arm64) + MAX_GPR_REGS = 8, + MAX_FPR_REGS = 8 +#else +#error wtf +#endif + }; + bool return_in_x8( typelib_TypeDescriptionReference *pTypeRef ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm64.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm64.cxx index 9b2c6762760c..e3c9e817313b 100644 --- a/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm64.cxx +++ b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm64.cxx @@ -32,46 +32,23 @@ using namespace ::com::sun::star::uno; namespace arm { - 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; - } - -#ifdef __ARM_PCS_VFP - bool is_float_only_struct(const typelib_TypeDescription * type) + bool is_hfa_struct(const typelib_TypeDescription * type) { const typelib_CompoundTypeDescription * p = reinterpret_cast< const typelib_CompoundTypeDescription * >(type); + if (p->nMembers >= 4) + return false; for (sal_Int32 i = 0; i < p->nMembers; ++i) { - if (p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT && - p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE) + if ((p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT && + p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE) || + p->ppTypeRefs[i]->eTypeClass != p->ppTypeRefs[0]->eTypeClass) return false; } return true; } -#endif - bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) + + bool return_in_x8( typelib_TypeDescriptionReference *pTypeRef ) { if (bridges::cpp_uno::shared::isSimpleType(pTypeRef)) return false; @@ -81,15 +58,10 @@ namespace arm TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); // A Composite Type not larger than 16 bytes is returned in x0, x1 - // FIXME: what about the "complex struct" thing, is that relevant at all? - bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr); + bool bRet = pTypeDescr->nSize > 16; -#ifdef __ARM_PCS_VFP - // In the VFP ABI, structs with only float/double values that fit in - // 16 bytes are returned in registers - if( pTypeDescr->nSize <= 16 && is_float_only_struct(pTypeDescr)) + if (is_hfa_struct(pTypeDescr)) bRet = false; -#endif TYPELIB_DANGER_RELEASE( pTypeDescr ); return bRet; @@ -98,174 +70,131 @@ namespace arm } } -void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* pRegisterReturn) +void MapReturn(sal_uInt64 x0, sal_uInt64 x1, typelib_TypeDescriptionReference *pReturnType, sal_uInt64 *pRegisterReturn) { switch( pReturnType->eTypeClass ) { - case typelib_TypeClass_HYPER: - case typelib_TypeClass_UNSIGNED_HYPER: - pRegisterReturn[1] = r1; - case typelib_TypeClass_LONG: - case typelib_TypeClass_UNSIGNED_LONG: - case typelib_TypeClass_ENUM: - case typelib_TypeClass_CHAR: - case typelib_TypeClass_SHORT: - case typelib_TypeClass_UNSIGNED_SHORT: - case typelib_TypeClass_BOOLEAN: - case typelib_TypeClass_BYTE: - pRegisterReturn[0] = r0; - break; - case typelib_TypeClass_FLOAT: -#if !defined(__ARM_PCS_VFP) && (defined(__ARM_EABI__) || defined(__SOFTFP__) || defined(IOS)) - pRegisterReturn[0] = r0; -#else - register float fret asm("s0"); + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + pRegisterReturn[1] = x1; + // fallthrough + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + pRegisterReturn[0] = x0; + break; + case typelib_TypeClass_FLOAT: + register float fret asm("s0"); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wuninitialized" - *(float*)pRegisterReturn = fret; + *(float*)pRegisterReturn = fret; #pragma GCC diagnostic pop -#endif - break; - case typelib_TypeClass_DOUBLE: -#if !defined(__ARM_PCS_VFP) && (defined(__ARM_EABI__) || defined(__SOFTFP__) || defined(IOS)) - pRegisterReturn[1] = r1; - pRegisterReturn[0] = r0; -#else - register double dret asm("d0"); + break; + case typelib_TypeClass_DOUBLE: + register double dret asm("d0"); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wuninitialized" - *(double*)pRegisterReturn = dret; + *(double*)pRegisterReturn = dret; #pragma GCC diagnostic pop -#endif - break; - case typelib_TypeClass_STRUCT: - case typelib_TypeClass_EXCEPTION: + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + if (!arm::return_in_x8(pReturnType)) { - if (!arm::return_in_hidden_param(pReturnType)) - pRegisterReturn[0] = r0; - break; + pRegisterReturn[0] = x0; + pRegisterReturn[1] = x1; } - default: - break; + break; + default: + break; } } namespace { -//================================================================ - -void callVirtualMethod( - void * pThis, - sal_Int32 nVtableIndex, - void * pRegisterReturn, - typelib_TypeDescriptionReference * pReturnType, - sal_uInt32 *pStack, - sal_uInt32 nStack, - sal_uInt32 *pGPR, - sal_uInt32 nGPR, - double *pFPR) __attribute__((noinline)); - void callVirtualMethod( - void * pThis, + void *pThis, sal_Int32 nVtableIndex, - void * pRegisterReturn, - typelib_TypeDescriptionReference * pReturnType, - sal_uInt32 *pStack, - sal_uInt32 nStack, - sal_uInt32 *pGPR, - sal_uInt32 nGPR, - double *pFPR) + void *pRegisterReturn, + typelib_TypeDescriptionReference *pReturnType, + sal_uInt64 *pStack, + int nStack, + sal_uInt64 *pGPR, + int nGPR, + double *pFPR, + int nFPR) { - abort(); // arm64 code not yet implemented - - (void) pThis; - (void) nVtableIndex; - (void) pRegisterReturn; - (void) pReturnType; - (void) pStack; - (void) nStack; - (void) pGPR; - (void) nGPR; - (void) pFPR; + // never called + if (! pThis) + CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + if ( nStack ) + { + // 16-bytes aligned + sal_uInt32 nStackBytes = ( ( nStack + 3 ) >> 2 ) * 16; + sal_uInt32 *stack = (sal_uInt32 *) alloca( nStackBytes ); + memcpy( stack, pStack, nStackBytes ); + } + + assert( nGPR <= arm::MAX_GPR_REGS ); + assert( nFPR <= arm::MAX_FPR_REGS ); + + sal_uInt64 pMethod = *((sal_uInt64*)pThis); + pMethod += 8 * nVtableIndex; + pMethod = *((sal_uInt64 *)pMethod); + + // For value returned in registers + sal_uInt64 x0; + sal_uInt64 x1; + + __asm__ __volatile__ + ( + " ldp x0, x1, %[pgpr_0]\n" + " ldp x2, x3, %[pgpr_2]\n" + " ldp x4, x5, %[pgpr_4]\n" + " ldp x6, x7, %[pgpr_6]\n" + " ldr x8, %[pregisterreturn]\n" + " ldp d0, d1, %[pfpr_0]\n" + " ldp d2, d3, %[pfpr_2]\n" + " ldp d4, d5, %[pfpr_4]\n" + " ldp d6, d7, %[pfpr_6]\n" + " blr %[pmethod]\n" + " str x0, %[x0]\n" + " str x1, %[x1]\n" + : [x0]"=m" (x0), [x1]"=m" (x1) + : [pgpr_0]"m" (pGPR[0]), + [pgpr_2]"m" (pGPR[2]), + [pgpr_4]"m" (pGPR[4]), + [pgpr_6]"m" (pGPR[6]), + [pregisterreturn]"m" (pRegisterReturn), + [pfpr_0]"m" (pFPR[0]), + [pfpr_2]"m" (pFPR[2]), + [pfpr_4]"m" (pFPR[4]), + [pfpr_6]"m" (pFPR[6]), + [pmethod]"r" (pMethod) + : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7" + ); + + MapReturn(x0, x1, pReturnType, (sal_uInt64 *) pRegisterReturn); } } -#define INSERT_INT32( pSV, nr, pGPR, pDS ) \ +#define INSERT_INT64( pSV, nr, pGPR, pDS ) \ if ( nr < arm::MAX_GPR_REGS ) \ - pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ else \ - *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); -#ifdef __ARM_EABI__ -#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) \ - if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \ - { \ - ++nr; \ - } \ +#define INSERT_INT32( pSV, nr, pGPR, pDS ) \ if ( nr < arm::MAX_GPR_REGS ) \ - { \ pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ - pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \ - } \ else \ - { \ - if ( (pDS - pStart) % 2) \ - { \ - ++pDS; \ - } \ - *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \ - *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \ - } -#else -#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) \ - INSERT_INT32( pSV, nr, pGPR, pDS ) \ - INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS ) -#endif - -#ifdef __ARM_PCS_VFP -// Since single and double arguments share the same register bank the filling of the -// registers is not always linear. Single values go to the first available single register, -// while doubles need to have an 8 byte alignment, so only go into double registers starting -// at every other single register. For ex a float, double, float sequence will fill registers -// s0, d1, and s1, actually corresponding to the linear order s0,s1, d1. -// -// These use the single/double register array and counters and ignore the pGPR argument -// nSR and nDR are the number of single and double precision registers that are no longer -// available -#define INSERT_FLOAT( pSV, nr, pGPR, pDS ) \ - if (nSR % 2 == 0) {\ - nSR = 2*nDR; \ - }\ - if ( nSR < arm::MAX_FPR_REGS*2 ) {\ - pSPR[nSR++] = *reinterpret_cast<float *>( pSV ); \ - if ((nSR % 2 == 1) && (nSR > 2*nDR)) {\ - nDR++; \ - }\ - }\ - else \ - {\ - *pDS++ = *reinterpret_cast<float *>( pSV );\ - } -#define INSERT_DOUBLE( pSV, nr, pGPR, pDS, pStart ) \ - if ( nDR < arm::MAX_FPR_REGS ) { \ - pFPR[nDR++] = *reinterpret_cast<double *>( pSV ); \ - }\ - else\ - {\ - if ( (pDS - pStart) % 2) \ - { \ - ++pDS; \ - } \ - *(double *)pDS = *reinterpret_cast<double *>( pSV );\ - pDS += 2;\ - } -#else -#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \ - INSERT_INT32( pSV, nr, pGPR, pDS ) - -#define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart ) \ - INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) -#endif + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); #define INSERT_INT16( pSV, nr, pGPR, pDS ) \ if ( nr < arm::MAX_GPR_REGS ) \ @@ -279,8 +208,16 @@ void callVirtualMethod( else \ *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); +#define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \ + if ( nr < arm::MAX_FPR_REGS ) \ + pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<double *>( pSV ); + +#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \ + INSERT_DOUBLE( pSV, nr, pGPR, pDS ) + namespace { -//======================================================================= static void cpp_call( bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, bridges::cpp_uno::shared::VtableSlot aVtableSlot, @@ -288,21 +225,16 @@ static void cpp_call( sal_Int32 nParams, typelib_MethodParameter * pParams, void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) { - // max space for: [complex ret ptr], values|ptr ... - sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca( - sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); - sal_uInt32 * pStackStart = pStack; + // max space for: values|ptr ... + sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+2) * sizeof(sal_Int64) ); + sal_uInt64 * pStackStart = pStack; - sal_uInt32 pGPR[arm::MAX_GPR_REGS]; - sal_uInt32 nGPR = 0; + sal_uInt64 pGPR[arm::MAX_GPR_REGS]; + int nGPR = 0; - // storage and counters for single and double precision VFP registers + // storage and counter for SIMD/FP registers double pFPR[arm::MAX_FPR_REGS]; -#ifdef __ARM_PCS_VFP - sal_uInt32 nDR = 0; - float *pSPR = reinterpret_cast< float *>(&pFPR); - sal_uInt32 nSR = 0; -#endif + int nFPR = 0; // return typelib_TypeDescription * pReturnTypeDescr = 0; @@ -311,22 +243,16 @@ static void cpp_call( void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion - bool bSimpleReturn = true; if (pReturnTypeDescr) { - if (arm::return_in_hidden_param( pReturnTypeRef ) ) - bSimpleReturn = false; - - if (bSimpleReturn) + if (!arm::return_in_x8( pReturnTypeRef ) ) pCppReturn = pUnoReturn; // direct way for simple types else { - // complex return via ptr + // complex return via x8 pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) - ? __builtin_alloca( pReturnTypeDescr->nSize ) + ? alloca( pReturnTypeDescr->nSize ) : pUnoReturn); // direct way - - INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack ); } } // push this @@ -335,15 +261,16 @@ static void cpp_call( INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack ); // stack space - OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); // args - void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams ); + // indices of values this have to be converted (interface conversion cpp<=>uno) - sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams); + int * pTempIndices = (int *)alloca( sizeof(int) * nParams ); + // type descriptions for reconversions - typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(void *) * nParams ); - sal_Int32 nTempIndices = 0; + sal_Int32 nTempIndices = 0; for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) { @@ -353,7 +280,6 @@ static void cpp_call( if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) { -// uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); @@ -361,17 +287,11 @@ static void cpp_call( { case typelib_TypeClass_HYPER: case typelib_TypeClass_UNSIGNED_HYPER: - - SAL_INFO( "bridges.ios", "hyper is " << pCppArgs[nPos] ); - - INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart ); + INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack ); break; case typelib_TypeClass_LONG: case typelib_TypeClass_UNSIGNED_LONG: case typelib_TypeClass_ENUM: - - SAL_INFO( "bridges.ios", "long is " << pCppArgs[nPos] ); - INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack ); break; case typelib_TypeClass_SHORT: @@ -384,10 +304,10 @@ static void cpp_call( INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack ); break; case typelib_TypeClass_FLOAT: - INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack ); + INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, pStack ); break; case typelib_TypeClass_DOUBLE: - INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart ); + INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack ); break; default: break; @@ -436,7 +356,7 @@ static void cpp_call( pStackStart, (pStack - pStackStart), pGPR, nGPR, - pFPR); + pFPR, nFPR); // NO exception occurred... *ppUnoExc = 0; @@ -476,8 +396,6 @@ static void cpp_call( } catch (...) { -// __asm__ __volatile__ ("sub sp, sp, #2048\n"); - // fill uno exception CPPU_CURRENT_NAMESPACE::fillUnoException( abi::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); |