[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