summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
authorCaolán McNamara <cmc@openoffice.org>2010-05-26 13:23:31 +0100
committerCaolán McNamara <cmc@openoffice.org>2010-05-26 13:23:31 +0100
commit33d87c934fe3fe330efa730d97ffeef2a8f854c7 (patch)
tree609cbb0b931bbf400a1c06ddf1a1d21c403fe280 /bridges
parent8829f8979787c370af363ffba6027f4807e00cf8 (diff)
parent478b93c2222402c14b4f68467b065e55b247bbc9 (diff)
cmcfixes75: merge with DEV300 m79
Diffstat (limited to 'bridges')
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S38
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_arm/armhelper.s22
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx54
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_arm/except.cxx6
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_arm/makefile.mk2
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_arm/share.hxx7
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx113
7 files changed, 161 insertions, 81 deletions
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 000000000..d5faf15ee
--- /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 <peter@chocky.org>
+@ Modified by Caolan McNamara <caolanm@redhat.com>
+@ Fixed by Michael Casadevall <mcasadevall@kubuntu.org>
+
+#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 8fd1a38e4..000000000
--- 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 <peter@chocky.org>
-@ Modified by Caolan McNamara <caolanm@redhat.com>
- .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 ab79cac70..f7b95522e 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;
@@ -410,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;
}
@@ -422,9 +442,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 +498,25 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
switch (member->eTypeClass)
{
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ typelib_InterfaceAttributeTypeDescription *pAttrTD =
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( 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 +525,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 ba5ab6a55..2cfe251cd 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 44c557795..0900ec11f 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 b47d48fbf..57ebcadce 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 982531e52..358271f2e 100644
--- a/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx
@@ -105,50 +105,94 @@ 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(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* 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:
- ((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
break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ if (!arm::return_in_hidden_param(pReturnType))
+ pRegisterReturn[0] = r0;
+ break;
+ }
default:
break;
}
@@ -162,7 +206,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 +216,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 +245,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 +256,7 @@ void callVirtualMethod(
"mov %1, r1\n\t"
: "=r" (r0), "=r" (r1) : );
- MapReturn(r0, r1, eReturnType, pRegisterReturn);
+ MapReturn(r0, r1, pReturnType, (sal_uInt32*)pRegisterReturn);
}
}
@@ -312,14 +343,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 +421,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 +464,7 @@ static void cpp_call(
{
callVirtualMethod(
pAdjustedThisPtr, aVtableSlot.index,
- pCppReturn, pReturnTypeDescr->eTypeClass,
+ pCppReturn, pReturnTypeRef,
pStackStart,
(pStack - pStackStart),
pGPR, nGPR);
@@ -504,15 +537,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 +594,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(