So, checking this out on Robert's OpenBSD box and digging into MacOSX land it appears that Linux has different x86 struct returning rules than MacOSX and OpenBSD and I therefore assume all BSD derived OSes on x86 follow the same rules, especially as Robert says that FreeBSD have just hacked out the test in their platform builds.
So attached is my proposed change that would allow the testtools tests to run correctly during the build without being hacked out or disabled, which is rather important because if those tests fail it implies that the final LibreOffice has busted UNO and will fail in strange and wonderful ways. Apparently works fine on Linux x86 (though I typically build on x86_64). If this works for you guys, I'd then like to see if we could just use the same gcc3_linux_intel bridge for MacOSX as the next step. C.
diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx index 0e804ed..24818e6 100644 --- a/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_intel/cpp2uno.cxx @@ -68,7 +68,7 @@ void cpp2uno_call( if (pReturnTypeDescr) { - if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + if (x86::isSimpleReturnType( pReturnTypeDescr )) { pUnoReturn = pReturnValue; // direct way for simple types } @@ -359,15 +359,39 @@ extern "C" typedef void (*PrivateSnippetExecutor)(); int const codeSnippetSize = 16; +#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(MACOSX) +namespace +{ + PrivateSnippetExecutor returnsInRegister(typelib_TypeDescriptionReference * pReturnTypeRef) + { + //These archs apparently are returning small structs in registers, while Linux + //doesn't + PrivateSnippetExecutor exec=NULL; + + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + const bool bSimpleReturnStruct = x86::isSimpleReturnType(pReturnTypeDescr); + const sal_Int32 nRetSize = pReturnTypeDescr->nSize; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + if (bSimpleReturnStruct) + { + exec = privateSnippetExecutorGeneral; // fills eax + if (nRetSize > 4) + exec = privateSnippetExecutorHyper; // fills eax/edx + } + return exec; + } +} +#endif + unsigned char * codeSnippet( unsigned char * code, sal_PtrDiff writetoexecdiff, sal_Int32 functionIndex, sal_Int32 vtableOffset, - typelib_TypeClass returnTypeClass) + typelib_TypeDescriptionReference * pReturnTypeRef) { - if (!bridges::cpp_uno::shared::isSimpleType(returnTypeClass)) { - functionIndex |= 0x80000000; - } PrivateSnippetExecutor exec; - switch (returnTypeClass) { + typelib_TypeClass eReturnClass = pReturnTypeRef ? pReturnTypeRef->eTypeClass : typelib_TypeClass_VOID; + switch (eReturnClass) + { case typelib_TypeClass_VOID: exec = privateSnippetExecutorVoid; break; @@ -381,13 +405,24 @@ unsigned char * codeSnippet( case typelib_TypeClass_DOUBLE: exec = privateSnippetExecutorDouble; break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: +#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(MACOSX) + exec = returnsInRegister(pReturnTypeRef); + if (!exec) + { + exec = privateSnippetExecutorClass; + functionIndex |= 0x80000000; + } + break; +#endif case typelib_TypeClass_STRING: case typelib_TypeClass_TYPE: case typelib_TypeClass_ANY: case typelib_TypeClass_SEQUENCE: - case typelib_TypeClass_STRUCT: case typelib_TypeClass_INTERFACE: exec = privateSnippetExecutorClass; + functionIndex |= 0x80000000; break; default: exec = privateSnippetExecutorGeneral; @@ -455,7 +490,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( code = codeSnippet( code, writetoexecdiff, functionOffset++, vtableOffset, reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( - member)->pAttributeTypeRef->eTypeClass); + member)->pAttributeTypeRef); // Setter: if (!reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( @@ -464,7 +499,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( (s++)->fn = code + writetoexecdiff; code = codeSnippet( code, writetoexecdiff, functionOffset++, vtableOffset, - typelib_TypeClass_VOID); + NULL); } break; @@ -473,7 +508,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( code = codeSnippet( code, writetoexecdiff, functionOffset++, vtableOffset, reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( - member)->pReturnTypeRef->eTypeClass); + member)->pReturnTypeRef); break; default: diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/share.hxx b/bridges/source/cpp_uno/gcc3_linux_intel/share.hxx index e4a6b37..f7dc2f9 100644 --- a/bridges/source/cpp_uno/gcc3_linux_intel/share.hxx +++ b/bridges/source/cpp_uno/gcc3_linux_intel/share.hxx @@ -88,6 +88,12 @@ void raiseException( //================================================================================================== void fillUnoException( __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); + +} + +namespace x86 +{ + bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive = false); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_intel/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_intel/uno2cpp.cxx index e1180c7..6fd5c32 100644 --- a/bridges/source/cpp_uno/gcc3_linux_intel/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_intel/uno2cpp.cxx @@ -59,7 +59,7 @@ void callVirtualMethod( void * pAdjustedThisPtr, sal_Int32 nVtableIndex, void * pRegisterReturn, - typelib_TypeClass eReturnType, + typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, sal_Int32 * pStackLongs, sal_Int32 nStackLongs ) __attribute__((noinline)); @@ -67,7 +67,7 @@ void callVirtualMethod( void * pAdjustedThisPtr, sal_Int32 nVtableIndex, void * pRegisterReturn, - typelib_TypeClass eReturnType, + typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn, sal_Int32 * pStackLongs, sal_Int32 nStackLongs ) { @@ -120,8 +120,10 @@ void callVirtualMethod( : "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr), "m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr) : "eax", "edx" ); - switch( eReturnType ) + switch( pReturnTypeDescr->eTypeClass ) { + case typelib_TypeClass_VOID: + break; case typelib_TypeClass_HYPER: case typelib_TypeClass_UNSIGNED_HYPER: ((long*)pRegisterReturn)[1] = edx; @@ -146,7 +148,20 @@ void callVirtualMethod( asm ( "fstpl %0\n\t" : : "m"(*(char *)pRegisterReturn) ); break; default: + { +#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(MACOSX) + sal_Int32 const nRetSize = pReturnTypeDescr->nSize; + if (bSimpleReturn && nRetSize <= 8 && nRetSize > 0) + { + if (nRetSize > 4) + static_cast<long *>(pRegisterReturn)[1] = edx; + static_cast<long *>(pRegisterReturn)[0] = eax; + } +#else + (void)bSimpleReturn; +#endif break; + } } } @@ -169,10 +184,12 @@ static void cpp_call( OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + bool bSimpleReturn = true; if (pReturnTypeDescr) { - if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + bSimpleReturn = x86::isSimpleReturnType(pReturnTypeDescr); + if (bSimpleReturn) { pCppReturn = pUnoReturn; // direct way for simple types } @@ -269,7 +286,7 @@ static void cpp_call( OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); callVirtualMethod( pAdjustedThisPtr, aVtableSlot.index, - pCppReturn, pReturnTypeDescr->eTypeClass, + pCppReturn, pReturnTypeDescr, bSimpleReturn, (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); // NO exception occurred... *ppUnoExc = 0; @@ -328,6 +345,38 @@ static void cpp_call( } +namespace x86 +{ + bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive) + { + if (bridges::cpp_uno::shared::isSimpleType( pTD )) + return true; +#if defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(MACOSX) + // Only structs of exactly 1, 2, 4, or 8 bytes are returned through + // registers, see <http://developer.apple.com/documentation/DeveloperTools/ + // Conceptual/LowLevelABI/Articles/IA32.html>: + if (pTD->eTypeClass == typelib_TypeClass_STRUCT && + (recursive || pTD->nSize <= 2 || pTD->nSize == 4 || pTD->nSize == 8)) + { + typelib_CompoundTypeDescription *const pCompTD = + (typelib_CompoundTypeDescription *) pTD; + for ( sal_Int32 pos = pCompTD->nMembers; pos--; ) { + typelib_TypeDescription * pMemberTD = 0; + TYPELIB_DANGER_GET( &pMemberTD, pCompTD->ppTypeRefs[pos] ); + bool const b = isSimpleReturnType(pMemberTD, true); + TYPELIB_DANGER_RELEASE( pMemberTD ); + if (! b) + return false; + } + return true; + } +#else + (void)recursive; +#endif + return false; + } +} + namespace bridges { namespace cpp_uno { namespace shared { void unoInterfaceProxyDispatch(
_______________________________________________ LibreOffice mailing list LibreOffice@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice