Kaydet (Commit) 928c8c80 authored tarafından Tor Lillqvist's avatar Tor Lillqvist

iOS arm64 C++/UNO bridge WIP

Change-Id: I5eb994e4a48b043f463940d1c34ad7a9459b83cd
üst c8b62432
...@@ -20,9 +20,7 @@ ...@@ -20,9 +20,7 @@
#ifdef __arm64 #ifdef __arm64
// For iOS devices (64-bit ARM). Originally a copy of // For iOS devices (64-bit ARM). Originally a copy of
// ../gcc3_linux_arm/cpp2uno.cxx with some cleanups and necessary // ../gcc3_linux_arm/cpp2uno.cxx.
// changes: No dynamic code generation as that is prohibited for apps
// in the App Store. Instead we use a set of pre-generated snippets.
// No attempts at factoring out the large amounts of more or less // 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 // common code in this, cpp2uno-arm.cxx and cpp2uno-i386.cxx have been
...@@ -49,23 +47,19 @@ using namespace ::com::sun::star::uno; ...@@ -49,23 +47,19 @@ using namespace ::com::sun::star::uno;
namespace namespace
{ {
static typelib_TypeClass cpp2uno_call( static typelib_TypeClass cpp2uno_call(
bridges::cpp_uno::shared::CppInterfaceProxy* pThis, bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
const typelib_TypeDescription * pMemberTypeDescr, const typelib_TypeDescription * pMemberTypeDescr,
typelib_TypeDescriptionReference * pReturnTypeRef, typelib_TypeDescriptionReference * pReturnTypeRef,
sal_Int32 nParams, typelib_MethodParameter * pParams, sal_Int32 nParams,
typelib_MethodParameter * pParams,
void ** pCallStack, void ** pCallStack,
sal_Int64 * pRegisterReturn /* space for register return */ ) 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 * pTopStack = (char *)(pCallStack + 0);
char * pCppStack = pTopStack; char * pCppStack = pTopStack;
#ifdef __ARM_PCS_VFP
int dc = 0;
char * pFloatArgs = (char *)(pCppStack - 64);
#endif
// return // return
typelib_TypeDescription * pReturnTypeDescr = 0; typelib_TypeDescription * pReturnTypeDescr = 0;
if (pReturnTypeRef) if (pReturnTypeRef)
...@@ -77,7 +71,7 @@ namespace ...@@ -77,7 +71,7 @@ namespace
if (pReturnTypeDescr) if (pReturnTypeDescr)
{ {
if (!arm::return_in_hidden_param(pReturnTypeRef)) if (!arm::return_in_x8(pReturnTypeRef))
pUnoReturn = pRegisterReturn; // direct way for simple types pUnoReturn = pRegisterReturn; // direct way for simple types
else // complex return via ptr (pCppReturn) else // complex return via ptr (pCppReturn)
{ {
...@@ -99,14 +93,14 @@ namespace ...@@ -99,14 +93,14 @@ namespace
// Indices of values this have to be converted (interface conversion // Indices of values this have to be converted (interface conversion
// cpp<=>uno) // cpp<=>uno)
sal_Int32 * pTempIndices = (sal_Int32 *)alloca( sizeof(sal_Int32) * nParams); int * pTempIndices = (sal_Int32 *)alloca( sizeof(int) * nParams);
// Type descriptions for reconversions // Type descriptions for reconversions
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(typelib_TypeDescription *) * nParams); 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]; const typelib_MethodParameter & rParam = pParams[nPos];
typelib_TypeDescription * pParamTypeDescr = 0; typelib_TypeDescription * pParamTypeDescr = 0;
...@@ -221,7 +215,7 @@ namespace ...@@ -221,7 +215,7 @@ namespace
// destruct temporary in/inout params // destruct temporary in/inout params
for ( ; nTempIndices--; ) for ( ; nTempIndices--; )
{ {
sal_Int32 nIndex = pTempIndices[nTempIndices]; int nIndex = pTempIndices[nTempIndices];
if (pParams[nIndex].bIn) // is in/inout => was constructed if (pParams[nIndex].bIn) // is in/inout => was constructed
uno_destructData( pUnoArgs[nIndex], uno_destructData( pUnoArgs[nIndex],
...@@ -241,7 +235,7 @@ namespace ...@@ -241,7 +235,7 @@ namespace
// temporary params // temporary params
for ( ; nTempIndices--; ) for ( ; nTempIndices--; )
{ {
sal_Int32 nIndex = pTempIndices[nTempIndices]; int nIndex = pTempIndices[nTempIndices];
typelib_TypeDescription * pParamTypeDescr = typelib_TypeDescription * pParamTypeDescr =
ppTempParamTypeDescr[nTempIndices]; ppTempParamTypeDescr[nTempIndices];
...@@ -285,25 +279,15 @@ namespace ...@@ -285,25 +279,15 @@ namespace
//===================================================================== //=====================================================================
static typelib_TypeClass cpp_mediate( static typelib_TypeClass cpp_mediate( sal_Int32 nFunctionIndex,
sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, sal_Int32 nVtableOffset,
void ** pCallStack, void ** pCallStack,
sal_Int64 * pRegisterReturn /* space for register return */ ) sal_Int64 * pRegisterReturn )
{ {
OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); // pCallStack: x8, ret *, this, params
// pCallStack: [ret *], this, params
// _this_ ptr is patched cppu_XInterfaceProxy object // _this_ ptr is patched cppu_XInterfaceProxy object
void *pThis; nFunctionIndex &= 0x7fffffff;
if( nFunctionIndex & 0x80000000 ) void *pThis = pCallStack[2];
{
nFunctionIndex &= 0x7fffffff;
pThis = pCallStack[1];
}
else
{
pThis = pCallStack[0];
}
pThis = static_cast< char * >(pThis) - nVtableOffset; pThis = static_cast< char * >(pThis) - nVtableOffset;
bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
...@@ -427,12 +411,11 @@ namespace ...@@ -427,12 +411,11 @@ namespace
* (called by asm snippets) * (called by asm snippets)
*/ */
extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset, extern "C" sal_Int64 cpp_vtable_call( sal_Int32 *pFunctionAndOffset,
void **pCallStack ) void **pCallStack )
{ {
sal_Int64 nRegReturn; sal_Int64 nRegReturn;
typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, &nRegReturn );
&nRegReturn );
switch( aType ) switch( aType )
{ {
...@@ -461,7 +444,7 @@ extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset, ...@@ -461,7 +444,7 @@ extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset,
namespace namespace
{ {
unsigned char *codeSnippet(sal_Int32 functionIndex, unsigned char *codeSnippet(sal_Int32 functionIndex,
sal_Int32 vtableOffset, bool bHasHiddenParam) sal_Int32 vtableOffset, bool bReturnThroughX8)
{ {
assert(functionIndex < nFunIndexes); assert(functionIndex < nFunIndexes);
if (!(functionIndex < nFunIndexes)) if (!(functionIndex < nFunIndexes))
...@@ -472,14 +455,14 @@ namespace ...@@ -472,14 +455,14 @@ namespace
return NULL; return NULL;
// The codeSnippets table is indexed by functionIndex, // 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]; unsigned char *result = ((unsigned char *) &codeSnippets) + codeSnippets[index];
SAL_INFO( "bridges.ios", SAL_INFO( "bridges.ios",
"codeSnippet: [" << "codeSnippet: [" <<
functionIndex << "," << vtableOffset << "," << bHasHiddenParam << "]=" << functionIndex << "," << vtableOffset << "," << bReturnThroughX8 << "]=" <<
(void *) result); (void *) result);
return result; return result;
...@@ -532,7 +515,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( ...@@ -532,7 +515,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
// Getter: // Getter:
(s++)->fn = codeSnippet( (s++)->fn = codeSnippet(
functionOffset++, vtableOffset, functionOffset++, vtableOffset,
arm::return_in_hidden_param( pAttrTD->pAttributeTypeRef )); arm::return_in_x8( pAttrTD->pAttributeTypeRef ));
// Setter: // Setter:
if (!pAttrTD->bReadOnly) if (!pAttrTD->bReadOnly)
...@@ -549,7 +532,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( ...@@ -549,7 +532,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
typelib_InterfaceMethodTypeDescription * >(member); typelib_InterfaceMethodTypeDescription * >(member);
(s++)->fn = codeSnippet(functionOffset++, vtableOffset, (s++)->fn = codeSnippet(functionOffset++, vtableOffset,
arm::return_in_hidden_param(pMethodTD->pReturnTypeRef)); arm::return_in_x8(pMethodTD->pReturnTypeRef));
break; break;
} }
default: default:
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 . * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/ */
#include <dlfcn.h> #include <dlfcn.h>
#include <cxxabi.h> #include <cxxabi.h>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
......
...@@ -39,10 +39,10 @@ printf (".text\n"); ...@@ -39,10 +39,10 @@ printf (".text\n");
printf ("#if defined(__arm) || defined(__arm64)\n"); printf ("#if defined(__arm) || defined(__arm64)\n");
printf ("\n"); printf ("\n");
printf ("// Each codeSnippetX function stores into ip/x15 an address and branches to _privateSnippetExecutor\n"); printf ("// Each codeSnippetX function stores into ip (arm64: 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 address is that following the branch instruction, containing two 32-bit ints:\n");
printf ("// - the function index, as such and with the 0x80000000 bit set\n"); printf ("// - the function index, as such or with the 0x80000000 bit set\n");
printf ("// (to indicate a hidden parameter for returning large values)\n"); printf ("// (to indicate that a hidden parameter (arm64: x8) is used for returning large values)\n");
printf ("// - the vtable offset\n"); printf ("// - the vtable offset\n");
printf ("\n"); printf ("\n");
......
...@@ -35,7 +35,7 @@ _privateSnippetExecutor: ...@@ -35,7 +35,7 @@ _privateSnippetExecutor:
mov r0, ip // r0 points to functionoffset/vtable mov r0, ip // r0 points to functionoffset/vtable
mov r1, sp // r1 points to this and params mov r1, sp // r1 points to this and params
// (see cpp2uno.cxx:codeSnippet()) // (see cpp2uno.cxx:codeSnippet())
stmfd sp!, {r4,lr} // save return address stmfd sp!, {r4, lr} // save return address
// (r4 pushed to preserve stack alignment) // (r4 pushed to preserve stack alignment)
bl _cpp_vtable_call bl _cpp_vtable_call
...@@ -49,9 +49,20 @@ _privateSnippetExecutor: ...@@ -49,9 +49,20 @@ _privateSnippetExecutor:
_privateSnippetExecutor: _privateSnippetExecutor:
// Not done yet, intentionally crash for now... stp x6, x7, [sp, #-16]!
mov x15, #0 stp x4, x5, [sp, #-16]!
ldr x15, [x15] 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 #else
.text .text
......
...@@ -47,8 +47,18 @@ namespace CPPU_CURRENT_NAMESPACE ...@@ -47,8 +47,18 @@ namespace CPPU_CURRENT_NAMESPACE
namespace arm namespace arm
{ {
enum armlimits { MAX_GPR_REGS = 4, MAX_FPR_REGS = 8 }; enum armlimits {
bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); #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: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -32,46 +32,23 @@ using namespace ::com::sun::star::uno; ...@@ -32,46 +32,23 @@ using namespace ::com::sun::star::uno;
namespace arm namespace arm
{ {
bool is_complex_struct(const typelib_TypeDescription * type) bool is_hfa_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)
{ {
const typelib_CompoundTypeDescription * p const typelib_CompoundTypeDescription * p
= reinterpret_cast< const typelib_CompoundTypeDescription * >(type); = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
if (p->nMembers >= 4)
return false;
for (sal_Int32 i = 0; i < p->nMembers; ++i) for (sal_Int32 i = 0; i < p->nMembers; ++i)
{ {
if (p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT && if ((p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT &&
p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE) p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE) ||
p->ppTypeRefs[i]->eTypeClass != p->ppTypeRefs[0]->eTypeClass)
return false; return false;
} }
return true; 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)) if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
return false; return false;
...@@ -81,15 +58,10 @@ namespace arm ...@@ -81,15 +58,10 @@ namespace arm
TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
// A Composite Type not larger than 16 bytes is returned in x0, x1 // 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;
bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
#ifdef __ARM_PCS_VFP if (is_hfa_struct(pTypeDescr))
// 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))
bRet = false; bRet = false;
#endif
TYPELIB_DANGER_RELEASE( pTypeDescr ); TYPELIB_DANGER_RELEASE( pTypeDescr );
return bRet; return bRet;
...@@ -98,174 +70,131 @@ namespace arm ...@@ -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 ) switch( pReturnType->eTypeClass )
{ {
case typelib_TypeClass_HYPER: case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER: case typelib_TypeClass_UNSIGNED_HYPER:
pRegisterReturn[1] = r1; pRegisterReturn[1] = x1;
case typelib_TypeClass_LONG: // fallthrough
case typelib_TypeClass_UNSIGNED_LONG: case typelib_TypeClass_LONG:
case typelib_TypeClass_ENUM: case typelib_TypeClass_UNSIGNED_LONG:
case typelib_TypeClass_CHAR: case typelib_TypeClass_ENUM:
case typelib_TypeClass_SHORT: case typelib_TypeClass_CHAR:
case typelib_TypeClass_UNSIGNED_SHORT: case typelib_TypeClass_SHORT:
case typelib_TypeClass_BOOLEAN: case typelib_TypeClass_UNSIGNED_SHORT:
case typelib_TypeClass_BYTE: case typelib_TypeClass_BOOLEAN:
pRegisterReturn[0] = r0; case typelib_TypeClass_BYTE:
break; pRegisterReturn[0] = x0;
case typelib_TypeClass_FLOAT: break;
#if !defined(__ARM_PCS_VFP) && (defined(__ARM_EABI__) || defined(__SOFTFP__) || defined(IOS)) case typelib_TypeClass_FLOAT:
pRegisterReturn[0] = r0; register float fret asm("s0");
#else
register float fret asm("s0");
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized" #pragma GCC diagnostic ignored "-Wuninitialized"
*(float*)pRegisterReturn = fret; *(float*)pRegisterReturn = fret;
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif break;
break; case typelib_TypeClass_DOUBLE:
case typelib_TypeClass_DOUBLE: register double dret asm("d0");
#if !defined(__ARM_PCS_VFP) && (defined(__ARM_EABI__) || defined(__SOFTFP__) || defined(IOS))
pRegisterReturn[1] = r1;
pRegisterReturn[0] = r0;
#else
register double dret asm("d0");
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized" #pragma GCC diagnostic ignored "-Wuninitialized"
*(double*)pRegisterReturn = dret; *(double*)pRegisterReturn = dret;
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif break;
break; case typelib_TypeClass_STRUCT:
case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION:
case typelib_TypeClass_EXCEPTION: if (!arm::return_in_x8(pReturnType))
{ {
if (!arm::return_in_hidden_param(pReturnType)) pRegisterReturn[0] = x0;
pRegisterReturn[0] = r0; pRegisterReturn[1] = x1;
break;
} }
default: break;
break; default:
break;
} }
} }
namespace 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 callVirtualMethod(
void * pThis, void *pThis,
sal_Int32 nVtableIndex, sal_Int32 nVtableIndex,
void * pRegisterReturn, void *pRegisterReturn,
typelib_TypeDescriptionReference * pReturnType, typelib_TypeDescriptionReference *pReturnType,
sal_uInt32 *pStack, sal_uInt64 *pStack,
sal_uInt32 nStack, int nStack,
sal_uInt32 *pGPR, sal_uInt64 *pGPR,
sal_uInt32 nGPR, int nGPR,
double *pFPR) double *pFPR,
int nFPR)
{ {
abort(); // arm64 code not yet implemented // never called
if (! pThis)
(void) pThis; CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
(void) nVtableIndex;
(void) pRegisterReturn; if ( nStack )
(void) pReturnType; {
(void) pStack; // 16-bytes aligned
(void) nStack; sal_uInt32 nStackBytes = ( ( nStack + 3 ) >> 2 ) * 16;
(void) pGPR; sal_uInt32 *stack = (sal_uInt32 *) alloca( nStackBytes );
(void) nGPR; memcpy( stack, pStack, nStackBytes );
(void) pFPR; }
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 ) \ if ( nr < arm::MAX_GPR_REGS ) \
pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
else \ else \
*pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
#ifdef __ARM_EABI__ #define INSERT_INT32( pSV, nr, pGPR, pDS ) \
#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) \
if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \
{ \
++nr; \
} \
if ( nr < arm::MAX_GPR_REGS ) \ if ( nr < arm::MAX_GPR_REGS ) \
{ \
pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
} \
else \ else \
{ \ *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
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
#define INSERT_INT16( pSV, nr, pGPR, pDS ) \ #define INSERT_INT16( pSV, nr, pGPR, pDS ) \
if ( nr < arm::MAX_GPR_REGS ) \ if ( nr < arm::MAX_GPR_REGS ) \
...@@ -279,8 +208,16 @@ void callVirtualMethod( ...@@ -279,8 +208,16 @@ void callVirtualMethod(
else \ else \
*pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); *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 { namespace {
//=======================================================================
static void cpp_call( static void cpp_call(
bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
bridges::cpp_uno::shared::VtableSlot aVtableSlot, bridges::cpp_uno::shared::VtableSlot aVtableSlot,
...@@ -288,21 +225,16 @@ static void cpp_call( ...@@ -288,21 +225,16 @@ static void cpp_call(
sal_Int32 nParams, typelib_MethodParameter * pParams, sal_Int32 nParams, typelib_MethodParameter * pParams,
void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
{ {
// max space for: [complex ret ptr], values|ptr ... // max space for: values|ptr ...
sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca( sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+2) * sizeof(sal_Int64) );
sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) ); sal_uInt64 * pStackStart = pStack;
sal_uInt32 * pStackStart = pStack;
sal_uInt32 pGPR[arm::MAX_GPR_REGS]; sal_uInt64 pGPR[arm::MAX_GPR_REGS];
sal_uInt32 nGPR = 0; 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]; double pFPR[arm::MAX_FPR_REGS];
#ifdef __ARM_PCS_VFP int nFPR = 0;
sal_uInt32 nDR = 0;
float *pSPR = reinterpret_cast< float *>(&pFPR);
sal_uInt32 nSR = 0;
#endif
// return // return
typelib_TypeDescription * pReturnTypeDescr = 0; typelib_TypeDescription * pReturnTypeDescr = 0;
...@@ -311,22 +243,16 @@ static void cpp_call( ...@@ -311,22 +243,16 @@ static void cpp_call(
void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
bool bSimpleReturn = true;
if (pReturnTypeDescr) if (pReturnTypeDescr)
{ {
if (arm::return_in_hidden_param( pReturnTypeRef ) ) if (!arm::return_in_x8( pReturnTypeRef ) )
bSimpleReturn = false;
if (bSimpleReturn)
pCppReturn = pUnoReturn; // direct way for simple types pCppReturn = pUnoReturn; // direct way for simple types
else else
{ {
// complex return via ptr // complex return via x8
pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
? __builtin_alloca( pReturnTypeDescr->nSize ) ? alloca( pReturnTypeDescr->nSize )
: pUnoReturn); // direct way : pUnoReturn); // direct way
INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack );
} }
} }
// push this // push this
...@@ -335,15 +261,16 @@ static void cpp_call( ...@@ -335,15 +261,16 @@ static void cpp_call(
INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack ); INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack );
// stack space // stack space
OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
// args // 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) // 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 // 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 ) for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
{ {
...@@ -353,7 +280,6 @@ static void cpp_call( ...@@ -353,7 +280,6 @@ static void cpp_call(
if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
{ {
// uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos], uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
pParamTypeDescr, pThis->getBridge()->getUno2Cpp() ); pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
...@@ -361,17 +287,11 @@ static void cpp_call( ...@@ -361,17 +287,11 @@ static void cpp_call(
{ {
case typelib_TypeClass_HYPER: case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER: case typelib_TypeClass_UNSIGNED_HYPER:
INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
SAL_INFO( "bridges.ios", "hyper is " << pCppArgs[nPos] );
INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart );
break; break;
case typelib_TypeClass_LONG: case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG: case typelib_TypeClass_UNSIGNED_LONG:
case typelib_TypeClass_ENUM: case typelib_TypeClass_ENUM:
SAL_INFO( "bridges.ios", "long is " << pCppArgs[nPos] );
INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack ); INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
break; break;
case typelib_TypeClass_SHORT: case typelib_TypeClass_SHORT:
...@@ -384,10 +304,10 @@ static void cpp_call( ...@@ -384,10 +304,10 @@ static void cpp_call(
INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack ); INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
break; break;
case typelib_TypeClass_FLOAT: case typelib_TypeClass_FLOAT:
INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack ); INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, pStack );
break; break;
case typelib_TypeClass_DOUBLE: case typelib_TypeClass_DOUBLE:
INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart ); INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
break; break;
default: default:
break; break;
...@@ -436,7 +356,7 @@ static void cpp_call( ...@@ -436,7 +356,7 @@ static void cpp_call(
pStackStart, pStackStart,
(pStack - pStackStart), (pStack - pStackStart),
pGPR, nGPR, pGPR, nGPR,
pFPR); pFPR, nFPR);
// NO exception occurred... // NO exception occurred...
*ppUnoExc = 0; *ppUnoExc = 0;
...@@ -476,8 +396,6 @@ static void cpp_call( ...@@ -476,8 +396,6 @@ static void cpp_call(
} }
catch (...) catch (...)
{ {
// __asm__ __volatile__ ("sub sp, sp, #2048\n");
// fill uno exception // fill uno exception
CPPU_CURRENT_NAMESPACE::fillUnoException( abi::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); CPPU_CURRENT_NAMESPACE::fillUnoException( abi::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment