Date: prev next · Thread: first prev next last
2010 Archives by date, by thread · List index


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(

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.