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: */
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