[Libreoffice] Different x86 ABI on BSDs and MaxOSX
Robert Nagy
robert at openbsd.org
Wed Dec 8 09:52:03 PST 2010
Hey,
Sweet!
Should I do a full build with it on i386 or did you test it already
on the box?
On (2010-12-08 16:49), Caolán McNamara wrote:
> 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(
More information about the LibreOffice
mailing list