bridges/Library_cpp_uno.mk                                |    2 
 bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.cxx     |  137 ++++++++++++
 bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.hxx     |   51 ++++
 bridges/source/cpp_uno/gcc3_linux_loongarch64/call.hxx    |    6 
 bridges/source/cpp_uno/gcc3_linux_loongarch64/call.s      |   15 +
 bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx |   97 +++------
 bridges/source/cpp_uno/gcc3_linux_loongarch64/share.hxx   |    3 
 bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx |  150 +++-----------
 8 files changed, 288 insertions(+), 173 deletions(-)

New commits:
commit 14b4f0701c1d8f21e550c57e68c37ae3d8d6f9d6
Author:     wjh-la <wujiah...@loongson.cn>
AuthorDate: Tue Jan 3 17:22:11 2023 +0800
Commit:     Stephan Bergmann <sberg...@redhat.com>
CommitDate: Thu Jan 12 09:02:44 2023 +0000

    bridges:Fixed test fail caused by bridges on the loongarch64
    
    Some failed test are caused by the bridges when testing on the
    loongarch64 machine. After adjust the function parameters and return
    value processing according to the characteristics of the loongarch64
    architercture. I tested in version 7.4.3 on the loongarch64 machine, and
    all tests passed.
    
    Change-Id: I9c67287cd7cc89fd79a907afdbffa507bb6052e3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144986
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    (cherry picked from commit d3152ea3ae0d6d1bdbc6379c3505812434da6466)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145303

diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk
index 1718202e94d0..5dc92c23cdbb 100644
--- a/bridges/Library_cpp_uno.mk
+++ b/bridges/Library_cpp_uno.mk
@@ -119,7 +119,7 @@ else ifeq ($(CPUNAME),LOONGARCH64)
 ifneq ($(filter LINUX,$(OS)),)
 bridges_SELECTED_BRIDGE := gcc3_linux_loongarch64
 bridge_asm_objects := call
-bridge_noopt_objects := cpp2uno uno2cpp
+bridge_noopt_objects := abi cpp2uno uno2cpp
 bridge_exception_objects := except
 endif
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.cxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.cxx
new file mode 100644
index 000000000000..686cbb596317
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.cxx
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include "abi.hxx"
+
+int loongarch64::flatten_struct(typelib_TypeDescription* pTypeDescr, 
Registers& regs)
+{
+    const typelib_CompoundTypeDescription* p
+        = reinterpret_cast<const typelib_CompoundTypeDescription*>(pTypeDescr);
+    int sum = p->nMembers;
+    for (sal_Int32 i = 0; i < p->nMembers; ++i)
+    {
+        typelib_TypeDescriptionReference* pTypeInStruct = p->ppTypeRefs[i];
+
+        switch (pTypeInStruct->eTypeClass)
+        {
+            case typelib_TypeClass_STRUCT:
+            {
+                typelib_TypeDescription* t = 0;
+                TYPELIB_DANGER_GET(&t, pTypeInStruct);
+                sum--;
+                sum += flatten_struct(t, regs);
+                TYPELIB_DANGER_RELEASE(t);
+            }
+            break;
+            case typelib_TypeClass_CHAR:
+            case typelib_TypeClass_BOOLEAN:
+            case typelib_TypeClass_BYTE:
+            case typelib_TypeClass_SHORT:
+            case typelib_TypeClass_UNSIGNED_SHORT:
+            case typelib_TypeClass_LONG:
+            case typelib_TypeClass_UNSIGNED_LONG:
+            case typelib_TypeClass_HYPER:
+            case typelib_TypeClass_UNSIGNED_HYPER:
+            case typelib_TypeClass_ENUM:
+                regs.nr_int++;
+                if (!regs.priorInt && !regs.priorFp)
+                    regs.priorInt = true;
+                break;
+            case typelib_TypeClass_FLOAT:
+            case typelib_TypeClass_DOUBLE:
+                regs.nr_fp++;
+                if (!regs.priorInt && !regs.priorFp)
+                    regs.priorFp = true;
+                break;
+            default:
+                break;
+        }
+    }
+    return sum;
+}
+
+loongarch64::ReturnKind 
loongarch64::getReturnKind(typelib_TypeDescriptionReference* pTypeRef)
+{
+    switch (pTypeRef->eTypeClass)
+    {
+        case typelib_TypeClass_CHAR:
+        case typelib_TypeClass_BOOLEAN:
+        case typelib_TypeClass_BYTE:
+        case typelib_TypeClass_SHORT:
+        case typelib_TypeClass_UNSIGNED_SHORT:
+        case typelib_TypeClass_LONG:
+        case typelib_TypeClass_UNSIGNED_LONG:
+        case typelib_TypeClass_HYPER:
+        case typelib_TypeClass_UNSIGNED_HYPER:
+        case typelib_TypeClass_ENUM:
+            return ReturnKind::RegistersInt;
+        case typelib_TypeClass_FLOAT:
+        case typelib_TypeClass_DOUBLE:
+            return ReturnKind::RegistersFp;
+        case typelib_TypeClass_STRUCT:
+        {
+            Registers regs = { 0, 0, false, false };
+            typelib_TypeDescription* pTypeDescr = nullptr;
+            TYPELIB_DANGER_GET(&pTypeDescr, pTypeRef);
+            int sum = flatten_struct(pTypeDescr, regs);
+            TYPELIB_DANGER_RELEASE(pTypeDescr);
+            if ((sum == 1 || sum == 2) && sum == regs.nr_fp)
+                return ReturnKind::RegistersFp;
+            if (sum == 2 && regs.nr_fp == regs.nr_int)
+            {
+                if (regs.priorInt)
+                    return ReturnKind::RegistersIntFp;
+                if (regs.priorFp)
+                    return ReturnKind::RegistersFpInt;
+            }
+            return ReturnKind::RegistersInt;
+        }
+        default:
+            return ReturnKind::RegistersInt;
+    }
+}
+
+void loongarch64::fillReturn(typelib_TypeDescriptionReference* pTypeRef, 
sal_Int64* gret,
+                             double* fret, void* pRegisterReturn)
+{
+    ReturnKind returnKind = getReturnKind(pTypeRef);
+    switch (returnKind)
+    {
+        case ReturnKind::RegistersFp:
+            reinterpret_cast<double*>(pRegisterReturn)[0] = fret[0];
+            reinterpret_cast<double*>(pRegisterReturn)[1] = fret[1];
+            break;
+        case ReturnKind::RegistersFpInt:
+            reinterpret_cast<double*>(pRegisterReturn)[0] = fret[0];
+            reinterpret_cast<sal_Int64*>(pRegisterReturn)[1] = gret[0];
+            break;
+        case ReturnKind::RegistersIntFp:
+            reinterpret_cast<sal_Int64*>(pRegisterReturn)[0] = gret[0];
+            reinterpret_cast<double*>(pRegisterReturn)[1] = fret[0];
+            break;
+        default:
+            reinterpret_cast<sal_Int64*>(pRegisterReturn)[0] = gret[0];
+            reinterpret_cast<sal_Int64*>(pRegisterReturn)[1] = gret[1];
+            break;
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.hxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.hxx
new file mode 100644
index 000000000000..90aa544f128b
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <typelib/typedescription.hxx>
+
+#define MAX_GP_REGS 8
+#define MAX_FP_REGS 8
+
+namespace loongarch64
+{
+enum class ReturnKind
+{
+    RegistersInt,
+    RegistersFp,
+    RegistersFpInt,
+    RegistersIntFp
+};
+typedef struct Registers
+{
+    bool priorInt;
+    bool priorFp;
+    int nr_fp;
+    int nr_int;
+} Registers;
+int flatten_struct(typelib_TypeDescription* pTypeDescr, Registers& regs);
+
+ReturnKind getReturnKind(typelib_TypeDescriptionReference* type);
+
+void fillReturn(typelib_TypeDescriptionReference* pTypeRef, sal_Int64* gret, 
double* fret,
+                void* pRegisterReturn);
+} // namespace loongarch64
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.hxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.hxx
index 51b9772c0f51..ee8daa9ad04a 100644
--- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.hxx
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.hxx
@@ -25,9 +25,9 @@
 
 namespace
 {
-extern "C" typelib_TypeClass
-cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, void** 
gpreg, void** fpreg,
-                void** ovrflw, sal_uInt64* pRegisterReturn /* space for 
register return */);
+extern "C" int cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 
nVtableOffset, void** gpreg,
+                               void** fpreg, void** ovrflw,
+                               sal_uInt64* pRegisterReturn /* space for 
register return */);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.s 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.s
index b8388508eea1..d27b5bd8a552 100644
--- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.s
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.s
@@ -30,6 +30,9 @@ privateSnippetExecutor:
         st.d   $ra,$sp,152
         .cfi_offset 1, -8
 .LEHB0 = .
+       // Clear return value space
+       st.d    $zero,$sp,0
+       st.d    $zero,$sp,8
         // Save the float point registers
         fst.d  $f0,$sp,80
         fst.d  $f1,$sp,88
@@ -67,11 +70,21 @@ privateSnippetExecutor:
 
 .LEHE0 = .
         // Perform return value
+       beq     $a0,$zero,.Lintfp
+       blt     $zero,$a0,.Lfpint
         fld.d  $f0,$sp,0
         fld.d  $f1,$sp,8
         ld.d   $a0,$sp,0
         ld.d   $a1,$sp,8
-
+       b       .Lfinish
+.Lintfp:
+       ld.d    $a0,$sp,0
+       fld.d   $f0,$sp,8
+       b       .Lfinish
+.Lfpint:
+       fld.d   $f0,$sp,0
+       ld.d    $a0,$sp,8
+.Lfinish:
         ld.d   $ra,$sp,152
         .cfi_restore 1
         addi.d $sp,$sp,160
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx
index 0273b39da4e3..299861de753c 100644
--- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx
@@ -28,6 +28,7 @@
 #include "vtablefactory.hxx"
 #include "call.hxx"
 #include "share.hxx"
+#include "abi.hxx"
 
 #include <stdio.h>
 #include <string.h>
@@ -84,19 +85,25 @@ bool 
return_in_hidden_param(typelib_TypeDescriptionReference* pTypeRef)
 
 namespace
 {
-static typelib_TypeClass
-cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
-             const typelib_TypeDescription* pMemberTypeDescr,
-             typelib_TypeDescriptionReference* pReturnTypeRef, // 0 indicates 
void return
-             sal_Int32 nParams, typelib_MethodParameter* pParams, void** 
gpreg, void** fpreg,
-             void** ovrflw, sal_uInt64* pRegisterReturn /* space for register 
return */)
+static int cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
+                        const typelib_TypeDescription* pMemberTypeDescr,
+                        typelib_TypeDescriptionReference* pReturnTypeRef, // 0 
indicates void return
+                        sal_Int32 nParams, typelib_MethodParameter* pParams, 
void** gpreg,
+                        void** fpreg, void** ovrflw,
+                        sal_uInt64* pRegisterReturn /* space for register 
return */)
 {
-    unsigned int nREG = 0;
+    sal_Int32 gCount = 0;
+    sal_Int32 fCount = 0;
+    sal_Int32 sp = 0;
 
     // return
     typelib_TypeDescription* pReturnTypeDescr = 0;
     if (pReturnTypeRef)
         TYPELIB_DANGER_GET(&pReturnTypeDescr, pReturnTypeRef);
+    loongarch64::ReturnKind returnKind
+        = (pReturnTypeRef == nullptr || pReturnTypeRef->eTypeClass == 
typelib_TypeClass_VOID)
+              ? loongarch64::ReturnKind::RegistersInt
+              : loongarch64::getReturnKind(pReturnTypeRef);
 
     void* pUnoReturn = 0;
     void* pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, 
reconversion need
@@ -105,9 +112,7 @@ cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* 
pThis,
     {
         if (CPPU_CURRENT_NAMESPACE::return_in_hidden_param(pReturnTypeRef))
         {
-            pCppReturn = gpreg[nREG]; // complex return via ptr (pCppReturn)
-            nREG++;
-
+            pCppReturn = gpreg[gCount++]; // complex return via ptr 
(pCppReturn)
             pUnoReturn = 
(bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr)
                               ? alloca(pReturnTypeDescr->nSize)
                               : pCppReturn); // direct way
@@ -119,7 +124,7 @@ cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* 
pThis,
     }
 
     // pop this
-    nREG++;
+    gCount++;
 
     // stack space
     static_assert(sizeof(void*) == sizeof(sal_Int64), "### unexpected size!");
@@ -147,31 +152,15 @@ cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* 
pThis,
             {
                 case typelib_TypeClass_FLOAT:
                 case typelib_TypeClass_DOUBLE:
-                    if (nREG < MAX_FP_REGS)
-                    {
-                        pCppArgs[nPos] = &(fpreg[nREG]);
-                        pUnoArgs[nPos] = &(fpreg[nREG]);
-                    }
-                    else
-                    {
-                        pCppArgs[nPos] = &(ovrflw[nREG - MAX_FP_REGS]);
-                        pUnoArgs[nPos] = &(ovrflw[nREG - MAX_FP_REGS]);
-                    }
-                    nREG++;
+                    pCppArgs[nPos]
+                        = fCount != MAX_FP_REGS
+                              ? &(fpreg[fCount++])
+                              : (gCount != MAX_GP_REGS ? &(gpreg[gCount++]) : 
&(ovrflw[sp++]));
+                    pUnoArgs[nPos] = pCppArgs[nPos];
                     break;
-
                 default:
-                    if (nREG < MAX_GP_REGS)
-                    {
-                        pCppArgs[nPos] = &(gpreg[nREG]);
-                        pUnoArgs[nPos] = &(gpreg[nREG]);
-                    }
-                    else
-                    {
-                        pCppArgs[nPos] = &(ovrflw[nREG - MAX_GP_REGS]);
-                        pUnoArgs[nPos] = &(ovrflw[nREG - MAX_GP_REGS]);
-                    }
-                    nREG++;
+                    pCppArgs[nPos] = gCount == MAX_GP_REGS ? &(ovrflw[sp++]) : 
&(gpreg[gCount++]);
+                    pUnoArgs[nPos] = pCppArgs[nPos];
                     break;
             }
             // no longer needed
@@ -180,16 +169,8 @@ cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* 
pThis,
         else // ptr to complex value | ref
         {
             void* pCppStack;
-            if (nREG < MAX_GP_REGS)
-            {
-                pCppArgs[nPos] = pCppStack = gpreg[nREG];
-            }
-            else
-            {
-                pCppArgs[nPos] = pCppStack = ovrflw[nREG - MAX_GP_REGS];
-            }
-            nREG++;
-
+            pCppStack = gCount == MAX_GP_REGS ? ovrflw[sp++] : gpreg[gCount++];
+            pCppArgs[nPos] = pCppStack;
             if (!rParam.bIn) // is pure out
             {
                 // uno out is unconstructed mem!
@@ -240,7 +221,7 @@ cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* 
pThis,
         CPPU_CURRENT_NAMESPACE::raiseException(&aUnoExc, 
pThis->getBridge()->getUno2Cpp());
         // has to destruct the any
         // is here for dummy
-        return typelib_TypeClass_VOID;
+        return -1;
     }
     else // else no exception occurred...
     {
@@ -277,12 +258,17 @@ cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* 
pThis,
         }
         if (pReturnTypeDescr)
         {
-            typelib_TypeClass eRet = 
(typelib_TypeClass)pReturnTypeDescr->eTypeClass;
             TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
-            return eRet;
         }
-        else
-            return typelib_TypeClass_VOID;
+        switch (returnKind)
+        {
+            case loongarch64::ReturnKind::RegistersIntFp:
+                return 0;
+            case loongarch64::ReturnKind::RegistersFpInt:
+                return 1;
+            default:
+                return -1;
+        }
     }
 }
 
@@ -290,9 +276,8 @@ cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* 
pThis,
    * is called on incoming vtable calls
    * (called by asm snippets)
    */
-typelib_TypeClass cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 
nVtableOffset, void** gpreg,
-                                  void** fpreg, void** ovrflw,
-                                  sal_uInt64* pRegisterReturn /* space for 
register return */)
+int cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, void** 
gpreg, void** fpreg,
+                    void** ovrflw, sal_uInt64* pRegisterReturn /* space for 
register return */)
 {
     static_assert(sizeof(sal_Int64) == sizeof(void*), "### unexpected!");
 
@@ -331,7 +316,7 @@ typelib_TypeClass cpp_vtable_call(sal_Int32 nFunctionIndex, 
sal_Int32 nVtableOff
 
     TypeDescription aMemberDescr(pTypeDescr->ppAllMembers[nMemberPos]);
 
-    typelib_TypeClass eRet;
+    int eRet;
     switch (aMemberDescr.get()->eTypeClass)
     {
         case typelib_TypeClass_INTERFACE_ATTRIBUTE:
@@ -367,11 +352,11 @@ typelib_TypeClass cpp_vtable_call(sal_Int32 
nFunctionIndex, sal_Int32 nVtableOff
             {
                 case 1: // acquire()
                     pCppI->acquireProxy(); // non virtual call!
-                    eRet = typelib_TypeClass_VOID;
+                    eRet = -1;
                     break;
                 case 2: // release()
                     pCppI->releaseProxy(); // non virtual call!
-                    eRet = typelib_TypeClass_VOID;
+                    eRet = -1;
                     break;
                 case 0: // queryInterface() opt
                 {
@@ -394,7 +379,7 @@ typelib_TypeClass cpp_vtable_call(sal_Int32 nFunctionIndex, 
sal_Int32 nVtableOff
                             TYPELIB_DANGER_RELEASE(pTD);
 
                             reinterpret_cast<void**>(pRegisterReturn)[0] = 
gpreg[0];
-                            eRet = typelib_TypeClass_ANY;
+                            eRet = -1;
                             break;
                         }
                         TYPELIB_DANGER_RELEASE(pTD);
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/share.hxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/share.hxx
index 331ed789e39f..258aac64a77e 100644
--- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/share.hxx
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/share.hxx
@@ -24,9 +24,6 @@
 #include <exception>
 #include <cstddef>
 
-#define MAX_GP_REGS (8)
-#define MAX_FP_REGS (8)
-
 namespace CPPU_CURRENT_NAMESPACE
 {
 void dummy_can_throw_anything(char const*);
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx
index 0004794ce55d..7242a43bd76c 100644
--- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx
@@ -36,108 +36,22 @@
 #include "vtables.hxx"
 
 #include "share.hxx"
-
-#define INSERT_FLOAT_DOUBLE(pSV, nr, pFPR, pDS)                                
                    \
-    if (nr < MAX_FP_REGS)                                                      
                    \
-        pFPR[nr++] = *reinterpret_cast<double*>(pSV);                          
                    \
-    else                                                                       
                    \
-        *pDS++ = *reinterpret_cast<sal_uInt64*>(pSV); // verbatim!
-
-#define INSERT_INT64(pSV, nr, pGPR, pDS)                                       
                    \
-    if (nr < MAX_GP_REGS)                                                      
                    \
-        pGPR[nr++] = *reinterpret_cast<sal_Int64*>(pSV);                       
                    \
-    else                                                                       
                    \
-        *pDS++ = *reinterpret_cast<sal_Int64*>(pSV);
-
-#define INSERT_INT32(pSV, nr, pGPR, pDS)                                       
                    \
-    if (nr < MAX_GP_REGS)                                                      
                    \
-        pGPR[nr++] = *reinterpret_cast<sal_Int32*>(pSV);                       
                    \
-    else                                                                       
                    \
-        *pDS++ = *reinterpret_cast<sal_Int32*>(pSV);
-
-#define INSERT_INT16(pSV, nr, pGPR, pDS)                                       
                    \
-    if (nr < MAX_GP_REGS)                                                      
                    \
-        pGPR[nr++] = *reinterpret_cast<sal_Int16*>(pSV);                       
                    \
-    else                                                                       
                    \
-        *pDS++ = *reinterpret_cast<sal_Int16*>(pSV);
-
-#define INSERT_UINT16(pSV, nr, pGPR, pDS)                                      
                    \
-    if (nr < MAX_GP_REGS)                                                      
                    \
-        pGPR[nr++] = *reinterpret_cast<sal_uInt16*>(pSV);                      
                    \
-    else                                                                       
                    \
-        *pDS++ = *reinterpret_cast<sal_uInt16*>(pSV);
-
-#define INSERT_INT8(pSV, nr, pGPR, pDS)                                        
                    \
-    if (nr < MAX_GP_REGS)                                                      
                    \
-        pGPR[nr++] = *reinterpret_cast<sal_Int8*>(pSV);                        
                    \
-    else                                                                       
                    \
-        *pDS++ = *reinterpret_cast<sal_Int8*>(pSV);
+#include "abi.hxx"
 
 using namespace ::com::sun::star::uno;
 
 namespace
 {
-bool isReturnInFPR(const typelib_TypeDescription* pTypeDescr, sal_uInt32& 
nSize)
+void pushArgs(unsigned long value, unsigned long* const stack, sal_Int32* 
const sp,
+              unsigned long* const regs, sal_Int32* const nregs)
 {
-    const typelib_CompoundTypeDescription* p
-        = reinterpret_cast<const typelib_CompoundTypeDescription*>(pTypeDescr);
-
-    for (sal_Int32 i = 0; i < p->nMembers; ++i)
-    {
-        typelib_TypeDescriptionReference* pTypeInStruct = p->ppTypeRefs[i];
-
-        switch (pTypeInStruct->eTypeClass)
-        {
-            case typelib_TypeClass_STRUCT:
-            case typelib_TypeClass_EXCEPTION:
-            {
-                typelib_TypeDescription* t = 0;
-                TYPELIB_DANGER_GET(&t, pTypeInStruct);
-                bool isFPR = isReturnInFPR(t, nSize);
-                TYPELIB_DANGER_RELEASE(t);
-                if (!isFPR)
-                    return false;
-            }
-            break;
-            case typelib_TypeClass_FLOAT:
-            case typelib_TypeClass_DOUBLE:
-                if (nSize >= 16)
-                    return false;
-                nSize += 8;
-                break;
-            default:
-                return false;
-        }
-    }
-    return true;
-}
-
-void fillReturn(const typelib_TypeDescription* pTypeDescr, sal_Int64* gret, 
double* fret,
-                void* pRegisterReturn)
-{
-    sal_uInt32 nSize = 0;
-    if (isReturnInFPR(pTypeDescr, nSize))
-    {
-        reinterpret_cast<double*>(pRegisterReturn)[0] = fret[0];
-        reinterpret_cast<double*>(pRegisterReturn)[1] = fret[1];
-    }
-    else
-    {
-        reinterpret_cast<sal_Int64*>(pRegisterReturn)[0] = gret[0];
-        reinterpret_cast<sal_Int64*>(pRegisterReturn)[1] = gret[1];
-    }
+    (*nregs != 8 ? regs[(*nregs)++] : stack[(*sp)++]) = value;
 }
 
 static void callVirtualMethod(void* pAdjustedThisPtr, sal_Int32 nVtableIndex, 
void* pRegisterReturn,
                               typelib_TypeDescriptionReference* 
pReturnTypeRef, bool bSimpleReturn,
-                              sal_uInt64* pStack, sal_uInt32 nStack, 
sal_uInt64* pGPR, double* pFPR,
-                              sal_uInt32 nREG)
+                              sal_uInt64* pStack, sal_uInt32 nStack, 
sal_uInt64* pGPR, double* pFPR)
 {
-    // Should not happen, but...
-    static_assert(MAX_GP_REGS == MAX_FP_REGS, "must be the same size");
-    if (nREG > MAX_GP_REGS)
-        nREG = MAX_GP_REGS;
-
     // Get pointer to method
     sal_uInt64 pMethod = *((sal_uInt64*)pAdjustedThisPtr);
     pMethod += 8 * nVtableIndex;
@@ -211,10 +125,7 @@ static void callVirtualMethod(void* pAdjustedThisPtr, 
sal_Int32 nVtableIndex, vo
             sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
             if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
             {
-                typelib_TypeDescription* pTypeDescr = 0;
-                TYPELIB_DANGER_GET(&pTypeDescr, pReturnTypeRef);
-                fillReturn(pTypeDescr, gret, fret, pRegisterReturn);
-                TYPELIB_DANGER_RELEASE(pTypeDescr);
+                loongarch64::fillReturn(pReturnTypeRef, gret, fret, 
pRegisterReturn);
             }
             break;
         }
@@ -232,10 +143,12 @@ static void 
cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy* pThis,
     // max space for: [complex ret ptr], values|ptr ...
     sal_uInt64* pStack = (sal_uInt64*)__builtin_alloca(((nParams + 3) * 
sizeof(sal_Int64)));
     sal_uInt64* pStackStart = pStack;
+    sal_Int32 sp = 0;
 
     sal_uInt64 pGPR[MAX_GP_REGS];
+    sal_Int32 gCount = 0;
     double pFPR[MAX_FP_REGS];
-    sal_uInt32 nREG = 0;
+    sal_Int32 fCount = 0;
 
     // return
     typelib_TypeDescription* pReturnTypeDescr = 0;
@@ -254,7 +167,7 @@ static void 
cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy* pThis,
             pCppReturn = 
bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr)
                              ? __builtin_alloca(pReturnTypeDescr->nSize)
                              : pUnoReturn;
-            INSERT_INT64(&pCppReturn, nREG, pGPR, pStack);
+            pGPR[gCount++] = reinterpret_cast<unsigned long>(pCppReturn);
         }
         else
         {
@@ -264,7 +177,7 @@ static void 
cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy* pThis,
 
     // push this
     void* pAdjustedThisPtr = reinterpret_cast<void**>(pThis->getCppI()) + 
aVtableSlot.offset;
-    INSERT_INT64(&pAdjustedThisPtr, nREG, pGPR, pStack);
+    pGPR[gCount++] = reinterpret_cast<unsigned long>(pAdjustedThisPtr);
 
     // args
     void** pCppArgs = (void**)alloca(3 * sizeof(void*) * nParams);
@@ -290,30 +203,49 @@ static void 
cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy* pThis,
             switch (pParamTypeDescr->eTypeClass)
             {
                 case typelib_TypeClass_LONG:
-                case typelib_TypeClass_UNSIGNED_LONG:
-                    INSERT_INT64(pCppArgs[nPos], nREG, pGPR, pStack);
-                    break;
                 case typelib_TypeClass_ENUM:
-                    INSERT_INT32(pCppArgs[nPos], nREG, pGPR, pStack);
+                    pushArgs(*static_cast<sal_Int32*>(pCppArgs[nPos]), pStack, 
&sp, pGPR, &gCount);
+                    break;
+                case typelib_TypeClass_UNSIGNED_LONG:
+                    pushArgs(*static_cast<sal_uInt32*>(pCppArgs[nPos]), 
pStack, &sp, pGPR, &gCount);
                     break;
                 case typelib_TypeClass_CHAR:
+                    pushArgs(*static_cast<sal_Unicode*>(pCppArgs[nPos]), 
pStack, &sp, pGPR,
+                             &gCount);
+                    break;
                 case typelib_TypeClass_SHORT:
-                    INSERT_INT16(pCppArgs[nPos], nREG, pGPR, pStack);
+                    pushArgs(*static_cast<sal_Int16*>(pCppArgs[nPos]), pStack, 
&sp, pGPR, &gCount);
                     break;
                 case typelib_TypeClass_UNSIGNED_SHORT:
-                    INSERT_UINT16(pCppArgs[nPos], nREG, pGPR, pStack);
+                    pushArgs(*static_cast<sal_uInt16*>(pCppArgs[nPos]), 
pStack, &sp, pGPR, &gCount);
                     break;
                 case typelib_TypeClass_BOOLEAN:
+                    pushArgs(static_cast<unsigned 
long>(*static_cast<sal_Bool*>(pCppArgs[nPos])),
+                             pStack, &sp, pGPR, &gCount);
+                    break;
                 case typelib_TypeClass_BYTE:
-                    INSERT_INT8(pCppArgs[nPos], nREG, pGPR, pStack);
+                    pushArgs(*static_cast<sal_Int8*>(pCppArgs[nPos]), pStack, 
&sp, pGPR, &gCount);
                     break;
                 case typelib_TypeClass_FLOAT:
                 case typelib_TypeClass_DOUBLE:
-                    INSERT_FLOAT_DOUBLE(pCppArgs[nPos], nREG, pFPR, pStack);
+                    if (fCount != MAX_FP_REGS)
+                    {
+                        pFPR[fCount++] = *static_cast<double*>(pCppArgs[nPos]);
+                    }
+                    else if (gCount != MAX_GP_REGS)
+                    {
+                        pGPR[gCount++] = *static_cast<unsigned 
long*>(pCppArgs[nPos]);
+                    }
+                    else
+                    {
+                        pStack[sp++] = *static_cast<unsigned 
long*>(pCppArgs[nPos]);
+                    }
                     break;
                 case typelib_TypeClass_HYPER:
+                    pushArgs(*static_cast<sal_Int64*>(pCppArgs[nPos]), pStack, 
&sp, pGPR, &gCount);
+                    break;
                 case typelib_TypeClass_UNSIGNED_HYPER:
-                    INSERT_INT64(pCppArgs[nPos], nREG, pGPR, pStack);
+                    pushArgs(*static_cast<sal_uInt64*>(pCppArgs[nPos]), 
pStack, &sp, pGPR, &gCount);
                     break;
                 default:
                     break;
@@ -349,7 +281,7 @@ static void 
cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy* pThis,
                 // no longer needed
                 TYPELIB_DANGER_RELEASE(pParamTypeDescr);
             }
-            INSERT_INT64(&(pCppArgs[nPos]), nREG, pGPR, pStack);
+            pushArgs(reinterpret_cast<unsigned long>(pCppArgs[nPos]), pStack, 
&sp, pGPR, &gCount);
         }
     }
 
@@ -358,7 +290,7 @@ static void 
cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy* pThis,
         try
         {
             callVirtualMethod(pAdjustedThisPtr, aVtableSlot.index, pCppReturn, 
pReturnTypeRef,
-                              bSimpleReturn, pStackStart, (pStack - 
pStackStart), pGPR, pFPR, nREG);
+                              bSimpleReturn, pStackStart, sp, pGPR, pFPR);
         }
         catch (css::uno::Exception&)
         {

Reply via email to