summaryrefslogtreecommitdiff
path: root/bridges/source
diff options
context:
space:
mode:
authorSakura286 <sakura286@outlook.com>2022-07-26 02:18:23 +0000
committerStephan Bergmann <sbergman@redhat.com>2022-11-10 13:47:06 +0100
commitbc9487f745befde6534fd46058e119256952323d (patch)
tree10b4ac8fd4be55ff19da95d39a51da7e753b6cd6 /bridges/source
parent7ac572437ac972ef37aed8003f5a476f49b27b89 (diff)
Add riscv64 support
1. Configure gbuild 2. Add UNO Bridge for riscv64 Till now base function works well on riscv64. The bridgetest has passed. Test on Debian, Gentoo and openEuler. Credits: - Heiher <r@hev.cc> and Stephan Bergmann <sbergman@redhat.com> The riscv64 bridge implementation refers to mips64 and AArch64 bridges. - Bo Yu <tsu.yubo@gmail.com> configures gbuild for riscv64. - WANG Xuerui <xen0n@gentoo.org> provides lots of guiding tips. Change-Id: Ifad3b0de8b2c9e7328627ed03396bbd45a9c71e4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137445 Reviewed-by: Stephan Bergmann <sbergman@redhat.com> Tested-by: Jenkins
Diffstat (limited to 'bridges/source')
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_riscv64/abi.cxx95
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_riscv64/abi.hxx23
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_riscv64/call.hxx33
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_riscv64/call.s81
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx795
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_riscv64/except.cxx282
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_riscv64/share.hxx85
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_riscv64/uno2cpp.cxx616
8 files changed, 2010 insertions, 0 deletions
diff --git a/bridges/source/cpp_uno/gcc3_linux_riscv64/abi.cxx b/bridges/source/cpp_uno/gcc3_linux_riscv64/abi.cxx
new file mode 100644
index 000000000000..b090953efde9
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/abi.cxx
@@ -0,0 +1,95 @@
+/* -*- 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/.
+ */
+
+#include <com/sun/star/uno/genfunc.hxx>
+#include <uno/data.h>
+#include <typelib/typedescription.hxx>
+#include "types.hxx"
+#include "abi.hxx"
+#include <stdio.h>
+#include <cstring>
+
+//#define BRIDGE_DEBUG
+
+namespace abi_riscv64
+{
+void countnGreg(sal_Int32& nGreg, sal_Int32& nFreg,
+ const typelib_CompoundTypeDescription* pTypeDescr)
+{
+ for (int i = 0; i < pTypeDescr->nMembers; i++)
+ {
+ typelib_TypeDescriptionReference* pTypeInStruct = pTypeDescr->ppTypeRefs[i];
+ switch (pTypeInStruct->eTypeClass)
+ {
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ typelib_TypeDescription* childTypeDescr = nullptr;
+ TYPELIB_DANGER_GET(&childTypeDescr, pTypeInStruct);
+ countnGreg(
+ nGreg, nFreg,
+ reinterpret_cast<typelib_CompoundTypeDescription const*>(childTypeDescr));
+ TYPELIB_DANGER_RELEASE(childTypeDescr);
+ }
+ break;
+ case typelib_TypeClass_FLOAT:
+ case typelib_TypeClass_DOUBLE:
+ nFreg++;
+ break;
+ default:
+ nGreg++;
+ break;
+ }
+ }
+}
+
+void fillStruct(const typelib_TypeDescription* pTypeDescr, sal_Int64* gret, double* fret,
+ void* pRegisterReturn)
+{
+#ifdef BRIDGE_DEBUG
+ printf("In fillStruct, pTypeDescr = %p, gret = %p, fret = %p, pRegisterReturn = %p\n",
+ pTypeDescr, gret, fret, pRegisterReturn);
+#endif
+ sal_Int32 nGreg = 0;
+ sal_Int32 nFreg = 0;
+ countnGreg(nGreg, nFreg, reinterpret_cast<typelib_CompoundTypeDescription const*>(pTypeDescr));
+ char* pAdjust = reinterpret_cast<char*>(pRegisterReturn);
+ if (nGreg == 0 && nFreg <= 2)
+ {
+ if (pTypeDescr->nSize <= 8 && nFreg == 2)
+ {
+ std::memcpy(pAdjust, fret, 4);
+ std::memcpy(pAdjust + 4, fret + 1, 4);
+ }
+ else
+ {
+ std::memcpy(pAdjust, fret, 16);
+ }
+ }
+ else if (nFreg == 1 && nGreg == 1)
+ {
+ if (pTypeDescr->nSize > 8)
+ {
+ std::memcpy(pAdjust, gret, 8);
+ std::memcpy(pAdjust + 8, fret, 8);
+ }
+ else
+ {
+ std::memcpy(pAdjust, gret, 4);
+ std::memcpy(pAdjust + 4, fret, 4);
+ }
+ }
+ else
+ {
+ std::memcpy(pAdjust, gret, 16);
+ }
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_riscv64/abi.hxx b/bridges/source/cpp_uno/gcc3_linux_riscv64/abi.hxx
new file mode 100644
index 000000000000..081e578150e1
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/abi.hxx
@@ -0,0 +1,23 @@
+/* -*- 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/.
+ */
+
+//#pragma once
+#include <uno/data.h>
+#include <typelib/typedescription.hxx>
+
+namespace abi_riscv64
+{
+void countnGreg(sal_Int32& nGreg, sal_Int32& nFreg,
+ const typelib_CompoundTypeDescription* pTypeDescr);
+
+void fillStruct(const typelib_TypeDescription* pTypeDescr, sal_Int64* gret, double* fret,
+ void* pRegisterReturn);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_riscv64/call.hxx b/bridges/source/cpp_uno/gcc3_linux_riscv64/call.hxx
new file mode 100644
index 000000000000..4b58f24c4bd1
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/call.hxx
@@ -0,0 +1,33 @@
+/* -*- 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 <sal/config.h>
+
+#include <sal/types.h>
+
+namespace
+{
+extern "C" sal_Int32 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_riscv64/call.s b/bridges/source/cpp_uno/gcc3_linux_riscv64/call.s
new file mode 100644
index 000000000000..4eab63b7eb0a
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/call.s
@@ -0,0 +1,81 @@
+/* -*- 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 .
+ */
+
+ .text
+ .align 2
+ .global privateSnippetExecutor
+ .hidden privateSnippetExecutor
+ .type privateSnippetExecutor, %function
+privateSnippetExecutor:
+ .cfi_startproc
+ addi sp,sp,-160
+ .cfi_def_cfa_offset 160
+ sd ra,152(sp)
+ .cfi_offset 1, -8
+ fsd fa0,80(sp)
+ fsd fa1,88(sp)
+ fsd fa2,96(sp)
+ fsd fa3,104(sp)
+ fsd fa4,112(sp)
+ fsd fa5,120(sp)
+ fsd fa6,128(sp)
+ fsd fa7,136(sp)
+ sd a0,16(sp)
+ sd a1,24(sp)
+ sd a2,32(sp)
+ sd a3,40(sp)
+ sd a4,48(sp)
+ sd a5,56(sp)
+ sd a6,64(sp)
+ sd a7,72(sp)
+ // a0 = functionIndex
+ // a1 = vtableOffset
+ // a2 = gpreg
+ // a3 = fpreg
+ // a4 = overflw
+ // a5 = pRegisterReturn
+ add a0,t4,zero
+ add a1,t5,zero
+ addi a2,sp,16
+ addi a3,sp,80
+ addi a4,sp,160
+ add a5,sp,zero
+ // jump to cpp_vtable_call
+ jalr ra,t6,0
+
+ bne a0,zero,.OneFloatOneInt
+ ld a0,0(sp)
+ ld a1,8(sp)
+ fld fa0,0(sp)
+ fld fa1,8(sp)
+ jal zero,.EndProgram
+.OneFloatOneInt:
+ ld a0,0(sp)
+ fld fa0,8(sp)
+.EndProgram:
+ ld ra,152(sp)
+ .cfi_restore 1
+ addi sp,sp,160
+ .cfi_def_cfa_offset 0
+ jalr zero,ra,0
+ .cfi_endproc
+ .size privateSnippetExecutor, .-privateSnippetExecutor
+ .section .note.GNU-stack, "", @progbits
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx
new file mode 100644
index 000000000000..6af52e9e471a
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx
@@ -0,0 +1,795 @@
+/* -*- 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 <com/sun/star/uno/genfunc.hxx>
+#include <sal/log.hxx>
+#include <typelib/typedescription.hxx>
+#include <uno/data.h>
+#include <osl/endian.h>
+#include "bridge.hxx"
+#include "cppinterfaceproxy.hxx"
+#include "types.hxx"
+#include "vtablefactory.hxx"
+#include "call.hxx"
+#include "share.hxx"
+#include "abi.hxx"
+
+#include <stdio.h>
+//#include <string.h>
+#include <cstring>
+
+using namespace com::sun::star::uno;
+
+//#define BRIDGE_DEBUG
+
+#ifdef BRIDGE_DEBUG
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+using namespace ::std;
+using namespace ::osl;
+using namespace ::rtl;
+#endif
+
+namespace CPPU_CURRENT_NAMESPACE
+{
+bool is_complex_struct(const typelib_TypeDescription* type)
+{
+ const typelib_CompoundTypeDescription* p
+ = reinterpret_cast<const typelib_CompoundTypeDescription*>(type);
+ for (sal_Int32 i = 0; i < p->nMembers; ++i)
+ {
+ if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT
+ || p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
+ {
+ typelib_TypeDescription* t = 0;
+ TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
+ bool b = is_complex_struct(t);
+ TYPELIB_DANGER_RELEASE(t);
+ if (b)
+ {
+ return true;
+ }
+ }
+ else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
+ return true;
+ }
+ if (p->pBaseTypeDescription != 0)
+ return is_complex_struct(&p->pBaseTypeDescription->aBase);
+ return false;
+}
+
+bool return_in_hidden_param(typelib_TypeDescriptionReference* pTypeRef)
+{
+ if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
+ return false;
+ else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT
+ || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
+ {
+ typelib_TypeDescription* pTypeDescr = 0;
+ TYPELIB_DANGER_GET(&pTypeDescr, pTypeRef);
+
+ //A Composite Type not larger than 16 bytes is returned in up to two GPRs
+ bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
+
+ TYPELIB_DANGER_RELEASE(pTypeDescr);
+ return bRet;
+ }
+ return true;
+}
+}
+
+namespace
+{
+static sal_Int32
+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 */)
+{
+#ifdef BRIDGE_DEBUG
+ printf("In cpp2uno_call, pThis = %p, pMemberTypeDescr = %p, pReturnTypeRef = %p\n", pThis,
+ pMemberTypeDescr, pReturnTypeRef);
+ printf("In cpp2uno_call, nParams = %d, pParams = %p, pRegisterReturn = %p\n", nParams, pParams,
+ pRegisterReturn);
+ printf("In cpp2uno_call, gpreg = %p, fpreg = %p, ovrflw = %p\n", gpreg, fpreg, ovrflw);
+#endif
+ unsigned int nr_gpr = 0;
+ unsigned int nr_fpr = 0;
+
+ char* gpreg_t = reinterpret_cast<char*>(gpreg);
+ char* fpreg_t = reinterpret_cast<char*>(fpreg);
+
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:begin\n");
+#endif
+ // return
+ typelib_TypeDescription* pReturnTypeDescr = 0;
+ if (pReturnTypeRef)
+ TYPELIB_DANGER_GET(&pReturnTypeDescr, pReturnTypeRef);
+
+ void* pUnoReturn = 0;
+ void* pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
+
+ if (pReturnTypeDescr)
+ {
+ if (CPPU_CURRENT_NAMESPACE::return_in_hidden_param(pReturnTypeRef))
+ {
+ pCppReturn = *gpreg++; // complex return via ptr (pCppReturn)
+ nr_gpr++;
+
+ pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr)
+ ? alloca(pReturnTypeDescr->nSize)
+ : pCppReturn); // direct way
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:complexreturn\n");
+#endif
+ }
+ else
+ {
+ pUnoReturn = pRegisterReturn; // direct way for simple types
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:simplereturn\n");
+#endif
+ }
+ }
+
+ // pop this
+ gpreg++;
+ nr_gpr++;
+
+ // stack space
+ static_assert(sizeof(void*) == sizeof(sal_Int64), "### unexpected size!");
+ // parameters
+ void** pUnoArgs = (void**)alloca(4 * sizeof(void*) * nParams);
+ void** pCppArgs = pUnoArgs + nParams;
+ // indices of values this have to be converted (interface conversion cpp<=>uno)
+ sal_Int32* pTempIndices = (sal_Int32*)(pUnoArgs + (2 * nParams));
+ // type descriptions for reconversions
+ typelib_TypeDescription** ppTempParamTypeDescr
+ = (typelib_TypeDescription**)(pUnoArgs + (3 * nParams));
+
+ sal_Int32 nTempIndices = 0;
+
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:nParams=%d\n", nParams);
+#endif
+ for (sal_Int32 nPos = 0; nPos < nParams; ++nPos)
+ {
+ const typelib_MethodParameter& rParam = pParams[nPos];
+
+ typelib_TypeDescription* pParamTypeDescr = 0;
+ TYPELIB_DANGER_GET(&pParamTypeDescr, rParam.pTypeRef);
+
+ if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType(pParamTypeDescr)) // value
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:Param %u, type %u\n", nPos, pParamTypeDescr->eTypeClass);
+#endif
+ switch (pParamTypeDescr->eTypeClass)
+ {
+ case typelib_TypeClass_FLOAT:
+ case typelib_TypeClass_DOUBLE:
+ if (nr_fpr < MAX_FP_REGS)
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:fpr=%p\n", *fpreg);
+#endif
+ pCppArgs[nPos] = pUnoArgs[nPos] = fpreg++;
+ nr_fpr++;
+ }
+ else if (nr_gpr < MAX_GP_REGS)
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:fpr=%p\n", *gpreg);
+#endif
+ pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
+ nr_gpr++;
+ }
+ else
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:fpr=%p\n", *ovrflw);
+#endif
+ pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
+ }
+
+ break;
+
+ default:
+ if (nr_gpr < MAX_GP_REGS)
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:gpr=%p\n", *gpreg);
+#endif
+ pCppArgs[nPos] = pUnoArgs[nPos] = gpreg++;
+ nr_gpr++;
+ }
+ else
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:gpr=%p\n", *ovrflw);
+#endif
+ pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
+ }
+ break;
+ }
+ // no longer needed
+ TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+ }
+ else // ptr to complex value | ref
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:ptr|ref\n");
+#endif
+ void* pCppStack;
+ if (nr_gpr < MAX_GP_REGS)
+ {
+ pCppArgs[nPos] = pCppStack = *gpreg++;
+ nr_gpr++;
+ }
+ else
+ {
+ pCppArgs[nPos] = pCppStack = *ovrflw++;
+ }
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:pCppStack=%p\n", pCppStack);
+#endif
+
+ if (!rParam.bIn) // is pure out
+ {
+ // uno out is unconstructed mem!
+ pUnoArgs[nPos] = alloca(pParamTypeDescr->nSize);
+ pTempIndices[nTempIndices] = nPos;
+ // will be released at reconversion
+ ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+ }
+ // is in/inout
+ else if (bridges::cpp_uno::shared::relatesToInterfaceType(pParamTypeDescr))
+ {
+ uno_copyAndConvertData(pUnoArgs[nPos] = alloca(pParamTypeDescr->nSize), pCppStack,
+ pParamTypeDescr, pThis->getBridge()->getCpp2Uno());
+ pTempIndices[nTempIndices] = nPos; // has to be reconverted
+ // will be released at reconversion
+ ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",
+ pCppStack, pParamTypeDescr->nSize, nPos, pUnoArgs[nPos]);
+#endif
+ }
+ else // direct way
+ {
+ pUnoArgs[nPos] = pCppStack;
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call:direct,pUnoArgs[%d]=%p\n", nPos, pUnoArgs[nPos]);
+#endif
+ // no longer needed
+ TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+ }
+ }
+ }
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call2,%p,unoargs=%p\n", pThis->getUnoI()->pDispatcher, pUnoArgs);
+ printf("pMemberTypeDescr=%p,pUnoReturn=%p\n", pMemberTypeDescr, pUnoReturn);
+#endif
+
+ // ExceptionHolder
+ uno_Any aUnoExc; // Any will be constructed by callee
+ uno_Any* pUnoExc = &aUnoExc;
+#ifdef BRIDGE_DEBUG
+ printf("pThis=%p,pThis->getUnoI()=%p,pMemberTypeDescr=%p\npUnoReturn=%p,pUnoArgs=%p", pThis,
+ pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs);
+#endif
+ // invoke uno dispatch call
+ (*pThis->getUnoI()->pDispatcher)(pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs,
+ &pUnoExc);
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp2uno_call2,after dispatch\n");
+#endif
+
+ // in case an exception occurred...
+ if (pUnoExc)
+ {
+ fflush(stdout);
+ // destruct temporary in/inout params
+ for (; nTempIndices--;)
+ {
+ sal_Int32 nIndex = pTempIndices[nTempIndices];
+
+ if (pParams[nIndex].bIn) // is in/inout => was constructed
+ uno_destructData(pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], 0);
+ TYPELIB_DANGER_RELEASE(ppTempParamTypeDescr[nTempIndices]);
+ }
+ if (pReturnTypeDescr)
+ TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
+
+ CPPU_CURRENT_NAMESPACE::raiseException(&aUnoExc, pThis->getBridge()->getUno2Cpp());
+ // has to destruct the any
+ // is here for dummy
+ return typelib_TypeClass_VOID;
+ }
+ else // else no exception occurred...
+ {
+ // temporary params
+ for (; nTempIndices--;)
+ {
+ sal_Int32 nIndex = pTempIndices[nTempIndices];
+ typelib_TypeDescription* pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
+
+ if (pParams[nIndex].bOut) // inout/out
+ {
+ // convert and assign
+ uno_destructData(pCppArgs[nIndex], pParamTypeDescr, cpp_release);
+ uno_copyAndConvertData(pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
+ pThis->getBridge()->getUno2Cpp());
+ }
+ // destroy temp uno param
+ uno_destructData(pUnoArgs[nIndex], pParamTypeDescr, 0);
+
+ TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+ }
+ void* retout = nullptr; // avoid false -Werror=maybe-uninitialized
+ // return
+ sal_Int32 returnType = 0;
+ if (pReturnTypeDescr)
+ {
+ char* pReturn = reinterpret_cast<char*>(pRegisterReturn);
+ if (!bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr))
+ {
+ switch (pReturnTypeDescr == nullptr ? typelib_TypeClass_VOID
+ : pReturnTypeDescr->eTypeClass)
+ {
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_CHAR:
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ std::memcpy(pReturn, pUnoReturn, 8);
+ break;
+ case typelib_TypeClass_FLOAT:
+ std::memcpy(pReturn, pUnoReturn, 4);
+ std::memset(pReturn + 4, 0xFF, 4);
+ break;
+ case typelib_TypeClass_DOUBLE:
+ std::memcpy(pReturn, pUnoReturn, 8);
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ std::memcpy(pReturn, pUnoReturn, 16);
+ sal_Int32 nGreg = 0;
+ sal_Int32 nFreg = 0;
+ abi_riscv64::countnGreg(
+ nGreg, nFreg,
+ reinterpret_cast<typelib_CompoundTypeDescription const*>(
+ pReturnTypeDescr));
+ if (pReturnTypeDescr->nSize <= 8 && nFreg == 2 && nGreg == 0)
+ {
+ std::memcpy(pReturn + 8, pReturn + 4, 4);
+ std::memset(pReturn + 4, 0xFF, 4);
+ std::memset(pReturn + 12, 0xFF, 4);
+ }
+ else if (nGreg == 1 && nFreg == 1)
+ {
+ returnType = 1;
+ if (pReturnTypeDescr->nSize <= 8)
+ {
+ std::memcpy(pReturn + 8, pReturn + 4, 4);
+ std::memset(pReturn + 12, 0xFF, 4);
+ }
+ }
+ }
+ break;
+ case typelib_TypeClass_VOID:
+ break;
+ default:
+ if (pUnoReturn)
+ {
+ std::memcpy(pRegisterReturn, pUnoReturn, 16);
+ }
+#ifdef BRIDGE_DEBUG
+ printf("Unhandled Type: %d\n", pReturnTypeDescr->eTypeClass);
+#endif
+ }
+ }
+ else
+ {
+ uno_copyAndConvertData(pCppReturn, pUnoReturn, pReturnTypeDescr,
+ pThis->getBridge()->getUno2Cpp());
+ // destroy temp uno return
+ uno_destructData(pUnoReturn, pReturnTypeDescr, 0);
+ // complex return ptr is set to return reg
+ *(void**)pRegisterReturn = pCppReturn;
+ }
+ TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
+ }
+ return returnType;
+ }
+}
+
+/**
+ * is called on incoming vtable calls
+ * (called by asm snippets)
+ */
+sal_Int32 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!");
+
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "in cpp_vtable_call nFunctionIndex is %d\n", nFunctionIndex);
+ fprintf(stdout, "in cpp_vtable_call nVtableOffset is %d\n", nVtableOffset);
+ fprintf(stdout, "in cpp_vtable_call gp=%p, fp=%p, ov=%p\n", gpreg, fpreg, ovrflw);
+#endif
+
+ // gpreg: [ret *], this, [other gpr params]
+ // fpreg: [fpr params]
+ // ovrflw: [gpr or fpr params (properly aligned)]
+ void* pThis;
+ if (nFunctionIndex & 0x80000000)
+ {
+ nFunctionIndex &= 0x7fffffff;
+ pThis = gpreg[1];
+ }
+ else
+ {
+ pThis = gpreg[0];
+ }
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp_vtable_call, pThis=%p, nFunctionIndex=%d, nVtableOffset=%d\n", pThis,
+ nFunctionIndex, nVtableOffset);
+#endif
+
+ pThis = static_cast<char*>(pThis) - nVtableOffset;
+ bridges::cpp_uno::shared::CppInterfaceProxy* pCppI
+ = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis);
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp_vtable_call, pCppI=%p\n", pCppI);
+#endif
+
+ typelib_InterfaceTypeDescription* pTypeDescr = pCppI->getTypeDescr();
+
+ if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
+ {
+ SAL_WARN("bridges", "illegal " << OUString::unacquired(&pTypeDescr->aBase.pTypeName)
+ << " vtable index " << nFunctionIndex << "/"
+ << pTypeDescr->nMapFunctionIndexToMemberIndex);
+ throw RuntimeException(("illegal " + OUString::unacquired(&pTypeDescr->aBase.pTypeName)
+ + " vtable index " + OUString::number(nFunctionIndex) + "/"
+ + OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)),
+ (XInterface*)pThis);
+ }
+
+ // determine called method
+ sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
+ assert(nMemberPos < pTypeDescr->nAllMembers);
+
+ TypeDescription aMemberDescr(pTypeDescr->ppAllMembers[nMemberPos]);
+
+#ifdef BRIDGE_DEBUG
+ //OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
+ //fprintf(stdout, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
+#endif
+ sal_Int32 eRet;
+ switch (aMemberDescr.get()->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp_vtable_call interface attribute\n");
+#endif
+ typelib_TypeDescriptionReference* pAttrTypeRef
+ = reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(aMemberDescr.get())
+ ->pAttributeTypeRef;
+
+ if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
+ {
+ // is GET method
+ eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pAttrTypeRef, 0, 0, // no params
+ gpreg, fpreg, ovrflw, pRegisterReturn);
+ }
+ else
+ {
+ // is SET method
+ typelib_MethodParameter aParam;
+ aParam.pTypeRef = pAttrTypeRef;
+ aParam.bIn = sal_True;
+ aParam.bOut = sal_False;
+
+ eRet = cpp2uno_call(pCppI, aMemberDescr.get(),
+ 0, // indicates void return
+ 1, &aParam, gpreg, fpreg, ovrflw, pRegisterReturn);
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp_vtable_call interface method\n");
+#endif
+ // is METHOD
+ switch (nFunctionIndex)
+ {
+ case 1: // acquire()
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp_vtable_call method acquire\n");
+#endif
+ pCppI->acquireProxy(); // non virtual call!
+ eRet = 0;
+ break;
+ case 2: // release()
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp_vtable_call method release\n");
+#endif
+ pCppI->releaseProxy(); // non virtual call!
+ eRet = 0;
+ break;
+ case 0: // queryInterface() opt
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp_vtable_call method query interface opt\n");
+#endif
+ typelib_TypeDescription* pTD = 0;
+ TYPELIB_DANGER_GET(&pTD, reinterpret_cast<Type*>(gpreg[2])->getTypeLibType());
+ if (pTD)
+ {
+ XInterface* pInterface = 0;
+ (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
+ pCppI->getBridge()->getCppEnv(), (void**)&pInterface,
+ pCppI->getOid().pData,
+ reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD));
+
+ if (pInterface)
+ {
+ ::uno_any_construct(reinterpret_cast<uno_Any*>(gpreg[0]), &pInterface,
+ pTD, cpp_acquire);
+
+ pInterface->release();
+ TYPELIB_DANGER_RELEASE(pTD);
+
+ reinterpret_cast<void**>(pRegisterReturn)[0] = gpreg[0];
+ eRet = 0;
+ break;
+ }
+ TYPELIB_DANGER_RELEASE(pTD);
+ }
+ } // else perform queryInterface()
+ default:
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp_vtable_call method query interface\n");
+#endif
+ typelib_InterfaceMethodTypeDescription* pMethodTD
+ = reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(
+ aMemberDescr.get());
+
+ eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pMethodTD->pReturnTypeRef,
+ pMethodTD->nParams, pMethodTD->pParams, gpreg, fpreg,
+ ovrflw, pRegisterReturn);
+ }
+ break;
+ }
+ default:
+ {
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "cpp_vtable_call no member\n");
+#endif
+ throw RuntimeException("no member description found!", (XInterface*)pThis);
+ }
+ }
+
+ return eRet;
+}
+
+extern "C" void privateSnippetExecutor(...);
+
+int const codeSnippetSize = 0x6c;
+
+unsigned char* codeSnippet(unsigned char* code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
+ bool bHasHiddenParam)
+{
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "in codeSnippet functionIndex is %d\n", functionIndex);
+ fprintf(stdout, "in codeSnippet vtableOffset is %d\n", vtableOffset);
+ fprintf(stdout, "in codeSnippet privateSnippetExecutor is %lx\n",
+ (unsigned long)privateSnippetExecutor);
+ fprintf(stdout, "in codeSnippet cpp_vtable_call is %lx\n", (unsigned long)cpp_vtable_call);
+
+ fflush(stdout);
+#endif
+
+ if (bHasHiddenParam)
+ functionIndex |= 0x80000000;
+
+ unsigned int* p = (unsigned int*)code;
+
+ assert((((unsigned long)code) & 0x3) == 0); //aligned to 4 otherwise a mistake
+
+ /* generate this code */
+ /*
+ It is complex to load a 64bit address because uou cannot load
+ an unsigned number to register on RISC-V.
+ # load functionIndex to t4
+ 00000eb7 lui t4,0x0
+ 000eee93 ori t4,t4,0x0
+ # load privateSnippetExecutor to t0
+ 000002b7 lui t0,0x0
+ 02429293 slli t0,t0,36
+ 00000337 lui t1,0x0
+ 01431313 slli t1,t1,20
+ 0062e2b3 or t0,t0,t1
+ 00000337 lui t1,0x0
+ 00431313 slli t1,t1,4
+ 0062e2b3 or t0,t0,t1
+ 00000337 lui t1,0x0
+ 00c35313 srli t1,t1,12
+ 0062e2b3 or t0,t0,t1
+ # load cpp_vtable_call to t6
+ 00000fb7 lui t6,0x0
+ 024f9f93 slli t6,t6,36
+ 00000337 lui t1,0x0
+ 01431313 slli t1,t1,20
+ 006fefb3 or t6,t6,t1
+ 00000337 lui t1,0x0
+ 00431313 slli t1,t1,4
+ 006fefb3 or t6,t6,t1
+ 00000337 lui t1,0x0
+ 00c35313 srli t1,t1,12
+ 006fefb3 or t6,t6,t1
+ # load vtableOffset to t5
+ 00000f37 lui t5,0x0
+ 000f6f13 ori t5,t5,0x0
+ # jump to privateSnippetExecutor
+ 00028067 jalr zero,t0,0x0
+ */
+
+ *p++ = 0x00000eb7 | ((functionIndex)&0xfffff000);
+ *p++ = 0x000eee93 | ((functionIndex << 20) & 0xfff00000);
+
+ // load privateSnippetExecutor to t0
+ unsigned long functionEntry = ((unsigned long)privateSnippetExecutor);
+ *p++ = 0x000002b7 | ((functionEntry >> 36) & 0x000000000ffff000);
+ *p++ = 0x02429293;
+ *p++ = 0x00000337 | ((functionEntry >> 20) & 0x000000000ffff000);
+ *p++ = 0x01431313;
+ *p++ = 0x0062e2b3;
+ *p++ = 0x00000337 | ((functionEntry >> 4) & 0x000000000ffff000);
+ *p++ = 0x00431313;
+ *p++ = 0x0062e2b3;
+ *p++ = 0x00000337 | ((functionEntry << 12) & 0x000000000ffff000);
+ *p++ = 0x00c35313;
+ *p++ = 0x0062e2b3;
+ // load cpp_vtable_call to t6
+ functionEntry = (unsigned long)cpp_vtable_call;
+ *p++ = 0x00000fb7 | ((functionEntry >> 36) & 0x000000000ffff000);
+ *p++ = 0x024f9f93;
+ *p++ = 0x00000337 | ((functionEntry >> 20) & 0x000000000ffff000);
+ *p++ = 0x01431313;
+ *p++ = 0x006fefb3;
+ *p++ = 0x00000337 | ((functionEntry >> 4) & 0x000000000ffff000);
+ *p++ = 0x00431313;
+ *p++ = 0x006fefb3;
+ *p++ = 0x00000337 | ((functionEntry << 12) & 0x000000000ffff000);
+ *p++ = 0x00c35313;
+ *p++ = 0x006fefb3;
+ // load vtableOffset to t5
+ *p++ = 0x00000f37 | ((vtableOffset)&0xfffff000);
+ *p++ = 0x000f6f13 | ((vtableOffset << 20) & 0xfff00000);
+ // jump to privateSnippetExecutor
+ *p++ = 0x00028067;
+ return (code + codeSnippetSize);
+}
+}
+
+void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const* bptr,
+ unsigned char const* eptr)
+{
+ asm volatile("fence" :::);
+}
+
+struct bridges::cpp_uno::shared::VtableFactory::Slot
+{
+ void* fn;
+};
+
+bridges::cpp_uno::shared::VtableFactory::Slot*
+bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void* block)
+{
+ return static_cast<Slot*>(block) + 2;
+}
+
+std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(sal_Int32 slotCount)
+{
+ return (slotCount + 2) * sizeof(Slot) + slotCount * codeSnippetSize;
+}
+
+bridges::cpp_uno::shared::VtableFactory::Slot*
+bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, sal_Int32 slotCount,
+ sal_Int32,
+ typelib_InterfaceTypeDescription*)
+{
+ Slot* slots = mapBlockToVtable(block);
+ slots[-2].fn = 0; //null
+ slots[-1].fn = 0; //destructor
+ return slots + slotCount;
+}
+
+unsigned char* bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
+ Slot** slots, unsigned char* code, sal_PtrDiff writetoexecdiff,
+ typelib_InterfaceTypeDescription const* type, sal_Int32 functionOffset, sal_Int32 functionCount,
+ sal_Int32 vtableOffset)
+{
+ (*slots) -= functionCount;
+ Slot* s = *slots;
+
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "in addLocalFunctions functionOffset is %d\n", functionOffset);
+ fprintf(stdout, "in addLocalFunctions vtableOffset is %d\n", vtableOffset);
+ fprintf(stdout, "nMembers=%d\n", type->nMembers);
+ fflush(stdout);
+#endif
+
+ for (sal_Int32 i = 0; i < type->nMembers; ++i)
+ {
+ typelib_TypeDescription* member = 0;
+ TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
+ assert(member != 0);
+ switch (member->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ // Getter:
+ (s++)->fn = code + writetoexecdiff;
+ code = codeSnippet(
+ code, functionOffset++, vtableOffset,
+ CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
+ ->pAttributeTypeRef));
+
+ // Setter:
+ if (!reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
+ ->bReadOnly)
+ {
+ (s++)->fn = code + writetoexecdiff;
+ code = codeSnippet(code, functionOffset++, vtableOffset, false);
+ }
+ break;
+
+ case typelib_TypeClass_INTERFACE_METHOD:
+ (s++)->fn = code + writetoexecdiff;
+ code = codeSnippet(
+ code, functionOffset++, vtableOffset,
+ CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(member)
+ ->pReturnTypeRef));
+ break;
+
+ default:
+ assert(false);
+ break;
+ }
+ TYPELIB_DANGER_RELEASE(member);
+ }
+ return code;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_riscv64/except.cxx b/bridges/source/cpp_uno/gcc3_linux_riscv64/except.cxx
new file mode 100644
index 000000000000..f95da4252674
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/except.cxx
@@ -0,0 +1,282 @@
+/* -*- 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 <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <cxxabi.h>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/uno/genfunc.hxx>
+#include <typelib/typedescription.hxx>
+#include <uno/any2.h>
+
+#include <unordered_map>
+#include "share.hxx"
+
+using namespace ::std;
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+using namespace ::__cxxabiv1;
+
+//#define BRIDGE_DEBUG
+
+namespace CPPU_CURRENT_NAMESPACE
+{
+void dummy_can_throw_anything(char const*) {}
+
+static OUString toUNOname(char const* p)
+{
+#if defined BRIDGE_DEBUG
+ char const* start = p;
+#endif
+
+ // example: N3com3sun4star4lang24IllegalArgumentExceptionE
+
+ OUStringBuffer buf(64);
+ assert('N' == *p);
+ ++p; // skip N
+
+ while ('E' != *p)
+ {
+ // read chars count
+ long n = (*p++ - '0');
+ while ('0' <= *p && '9' >= *p)
+ {
+ n *= 10;
+ n += (*p++ - '0');
+ }
+ buf.appendAscii(p, n);
+ p += n;
+ if ('E' != *p)
+ buf.append('.');
+ }
+
+#if defined BRIDGE_DEBUG
+ OUString ret(buf.makeStringAndClear());
+ OString c_ret(OUStringToOString(ret, RTL_TEXTENCODING_ASCII_US));
+ fprintf(stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr());
+ return ret;
+#else
+ return buf.makeStringAndClear();
+#endif
+}
+
+class RTTI
+{
+ typedef std::unordered_map<OUString, type_info*> t_rtti_map;
+
+ Mutex m_mutex;
+ t_rtti_map m_rttis;
+ t_rtti_map m_generatedRttis;
+
+ void* m_hApp;
+
+public:
+ RTTI();
+ ~RTTI();
+
+ type_info* getRTTI(typelib_CompoundTypeDescription*);
+};
+
+RTTI::RTTI()
+ : m_hApp(dlopen(0, RTLD_LAZY))
+{
+}
+
+RTTI::~RTTI() { dlclose(m_hApp); }
+
+type_info* RTTI::getRTTI(typelib_CompoundTypeDescription* pTypeDescr)
+{
+ type_info* rtti;
+
+ OUString const& unoName = *(OUString const*)&pTypeDescr->aBase.pTypeName;
+
+ MutexGuard guard(m_mutex);
+ t_rtti_map::const_iterator iRttiFind(m_rttis.find(unoName));
+ if (iRttiFind == m_rttis.end())
+ {
+ // RTTI symbol
+ OStringBuffer buf(64);
+ buf.append("_ZTIN");
+ sal_Int32 index = 0;
+ do
+ {
+ OUString token(unoName.getToken(0, '.', index));
+ buf.append(token.getLength());
+ OString c_token(OUStringToOString(token, RTL_TEXTENCODING_ASCII_US));
+ buf.append(c_token);
+ } while (index >= 0);
+ buf.append('E');
+
+ OString symName(buf.makeStringAndClear());
+ rtti = (type_info*)dlsym(m_hApp, symName.getStr());
+
+ if (rtti)
+ {
+ pair<t_rtti_map::iterator, bool> insertion(
+ m_rttis.insert(t_rtti_map::value_type(unoName, rtti)));
+ assert(insertion.second && "### inserting new rtti failed?!");
+ }
+ else
+ {
+ // try to lookup the symbol in the generated rtti map
+ t_rtti_map::const_iterator iFind(m_generatedRttis.find(unoName));
+ if (iFind == m_generatedRttis.end())
+ {
+ // we must generate it !
+ // symbol and rtti-name is nearly identical,
+ // the symbol is prefixed with _ZTI
+ char const* rttiName = symName.getStr() + 4;
+#if defined BRIDGE_DEBUG
+ fprintf(stderr, "generated rtti for %s\n", rttiName);
+#endif
+ if (pTypeDescr->pBaseTypeDescription)
+ {
+ // ensure availability of base
+ type_info* base_rtti = getRTTI(
+ (typelib_CompoundTypeDescription*)pTypeDescr->pBaseTypeDescription);
+ rtti
+ = new __si_class_type_info(strdup(rttiName), (__class_type_info*)base_rtti);
+ }
+ else
+ {
+ // this class has no base class
+ rtti = new __class_type_info(strdup(rttiName));
+ }
+
+ pair<t_rtti_map::iterator, bool> insertion(
+ m_generatedRttis.insert(t_rtti_map::value_type(unoName, rtti)));
+ assert(insertion.second && "### inserting new generated rtti failed?!");
+ }
+ else // taking already generated rtti
+ {
+ rtti = iFind->second;
+ }
+ }
+ }
+ else
+ {
+ rtti = iRttiFind->second;
+ }
+
+ return rtti;
+}
+
+static void deleteException(void* pExc)
+{
+#if defined BRIDGE_DEBUG
+ fprintf(stderr, "in deleteException: pExc = %p\n", pExc);
+#endif
+ __cxa_exception const* header = ((__cxa_exception const*)pExc - 1);
+ typelib_TypeDescription* pTD = 0;
+ OUString unoName(toUNOname(header->exceptionType->name()));
+ ::typelib_typedescription_getByName(&pTD, unoName.pData);
+ assert(pTD && "### unknown exception type! leaving out destruction => leaking!!!");
+ if (pTD)
+ {
+ ::uno_destructData(pExc, pTD, cpp_release);
+ ::typelib_typedescription_release(pTD);
+ }
+}
+
+//extern "C" {
+// void __cxa_throw(void* ex, void* info, void (*dest)(void*)) { ::abort(); }
+//}
+
+void raiseException(uno_Any* pUnoExc, uno_Mapping* pUno2Cpp)
+{
+#if defined BRIDGE_DEBUG
+ OString cstr(OUStringToOString(OUString::unacquired(&pUnoExc->pType->pTypeName),
+ RTL_TEXTENCODING_ASCII_US));
+ fprintf(stderr, "> uno exception occurred: %s\n", cstr.getStr());
+#endif
+ void* pCppExc;
+ type_info* rtti;
+
+ {
+ // construct cpp exception object
+ typelib_TypeDescription* pTypeDescr = 0;
+ TYPELIB_DANGER_GET(&pTypeDescr, pUnoExc->pType);
+ assert(pTypeDescr);
+ if (!pTypeDescr)
+ {
+ throw RuntimeException(OUString("cannot get typedescription for type ")
+ + OUString::unacquired(&pUnoExc->pType->pTypeName));
+ }
+
+ pCppExc = __cxa_allocate_exception(pTypeDescr->nSize);
+ ::uno_copyAndConvertData(pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp);
+
+ // destruct uno exception
+ ::uno_any_destruct(pUnoExc, 0);
+ // avoiding locked counts
+ static RTTI rtti_data;
+ rtti = (type_info*)rtti_data.getRTTI((typelib_CompoundTypeDescription*)pTypeDescr);
+ TYPELIB_DANGER_RELEASE(pTypeDescr);
+ assert(rtti && "### no rtti for throwing exception!");
+ if (!rtti)
+ {
+ throw RuntimeException(OUString("no rtti for type ")
+ + OUString::unacquired(&pUnoExc->pType->pTypeName));
+ }
+ }
+ __cxa_throw(pCppExc, rtti, deleteException);
+}
+
+void fillUnoException(uno_Any* pUnoExc, uno_Mapping* pCpp2Uno)
+{
+ __cxa_exception* header = __cxa_get_globals()->caughtExceptions;
+ if (!header)
+ {
+ RuntimeException aRE("no exception header!");
+ Type const& rType = cppu::UnoType<decltype(aRE)>::get();
+ uno_type_any_constructAndConvert(pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno);
+ SAL_WARN("bridges", aRE.Message);
+ return;
+ }
+
+ std::type_info* exceptionType = __cxa_current_exception_type();
+
+ typelib_TypeDescription* pExcTypeDescr = 0;
+ OUString unoName(toUNOname(exceptionType->name()));
+#if defined BRIDGE_DEBUG
+ OString cstr_unoName(OUStringToOString(unoName, RTL_TEXTENCODING_ASCII_US));
+ fprintf(stderr, "> c++ exception occurred: %s\n", cstr_unoName.getStr());
+#endif
+ typelib_typedescription_getByName(&pExcTypeDescr, unoName.pData);
+ if (0 == pExcTypeDescr)
+ {
+ RuntimeException aRE(OUString("exception type not found: ") + unoName);
+ Type const& rType = cppu::UnoType<decltype(aRE)>::get();
+ uno_type_any_constructAndConvert(pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno);
+ SAL_WARN("bridges", aRE.Message);
+ }
+ else
+ {
+ // construct uno exception any
+ uno_any_constructAndConvert(pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno);
+ typelib_typedescription_release(pExcTypeDescr);
+ }
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_riscv64/share.hxx b/bridges/source/cpp_uno/gcc3_linux_riscv64/share.hxx
new file mode 100644
index 000000000000..331ed789e39f
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/share.hxx
@@ -0,0 +1,85 @@
+/* -*- 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 "uno/mapping.h"
+
+#include <typeinfo>
+#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*);
+
+// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h
+
+struct _Unwind_Exception
+{
+ unsigned exception_class __attribute__((__mode__(__DI__)));
+ void* exception_cleanup;
+ unsigned private_1 __attribute__((__mode__(__word__)));
+ unsigned private_2 __attribute__((__mode__(__word__)));
+} __attribute__((__aligned__));
+
+struct __cxa_exception
+{
+ std::type_info* exceptionType;
+ void (*exceptionDestructor)(void*);
+
+ void (*unexpectedHandler)(); // std::unexpected_handler dropped from C++17
+ std::terminate_handler terminateHandler;
+
+ __cxa_exception* nextException;
+
+ int handlerCount;
+
+ int handlerSwitchValue;
+ const unsigned char* actionRecord;
+ const unsigned char* languageSpecificData;
+ void* catchTemp;
+ void* adjustedPtr;
+
+ _Unwind_Exception unwindHeader;
+};
+
+extern "C" void* __cxa_allocate_exception(std::size_t thrown_size) throw();
+extern "C" void __cxa_throw(void* thrown_exception, std::type_info* tinfo, void (*dest)(void*))
+ __attribute__((noreturn));
+
+struct __cxa_eh_globals
+{
+ __cxa_exception* caughtExceptions;
+ unsigned int uncaughtExceptions;
+};
+
+extern "C" __cxa_eh_globals* __cxa_get_globals() throw();
+extern "C" std::type_info* __cxa_current_exception_type() throw();
+
+void raiseException(uno_Any* pUnoExc, uno_Mapping* pUno2Cpp);
+
+void fillUnoException(uno_Any*, uno_Mapping* pCpp2Uno);
+
+bool return_in_hidden_param(typelib_TypeDescriptionReference* pTypeRef);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_riscv64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_riscv64/uno2cpp.cxx
new file mode 100644
index 000000000000..a23bcc3e8cec
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/uno2cpp.cxx
@@ -0,0 +1,616 @@
+/* -*- 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 <exception>
+#include <malloc.h>
+#include <cstring>
+#include <typeinfo>
+
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/genfunc.hxx>
+#include <o3tl/runtimetooustring.hxx>
+#include <uno/data.h>
+
+#include "bridge.hxx"
+#include "types.hxx"
+#include "unointerfaceproxy.hxx"
+#include "vtables.hxx"
+
+#include "share.hxx"
+#include "abi.hxx"
+
+//#define BRIDGE_DEBUG
+#ifdef BRIDGE_DEBUG
+#include <stdio.h>
+#endif
+
+// FP reg -> GP reg -> stack
+#define INSERT_FLOAT_DOUBLE(pSV, nfr, pFPR, ngr, pGPR, pDS) \
+ if (nfr < MAX_FP_REGS) \
+ pFPR[nfr++] = *reinterpret_cast<double*>(pSV); \
+ else if (ngr < MAX_FP_REGS) \
+ pGPR[ngr++] = *reinterpret_cast<sal_Int64*>(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);
+
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+bool isReturnInFPR(const typelib_TypeDescription* pTypeDescr, sal_uInt32& nSize)
+{
+#ifdef BRIDGE_DEBUG
+ printf("In isReturnInFPR, pTypeDescr = %p, nSize = %d\n", pTypeDescr, nSize);
+#endif
+ 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)
+{
+#ifdef BRIDGE_DEBUG
+ printf("In fillReturn, pTypeDescr = %p, gret = %p, fret = %p, pRegisterReturn = %p\n",
+ pTypeDescr, gret, fret, pRegisterReturn);
+#endif
+ 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];
+ }
+}
+
+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,
+ typelib_TypeDescription* pReturnTypeDescr)
+{
+#ifdef BRIDGE_DEBUG
+ printf("In callVirtualMethod:\n");
+ printf("pAdjustedThisPtr = %p, nVtableIndex = %d, pRegisterReturn = %p, pReturnTypeRef = %p\n",
+ pAdjustedThisPtr, nVtableIndex, pRegisterReturn, pReturnTypeRef);
+ printf("bSimpleReturn = %d, pStack = %p, nStack = %d, pGPR = %p, pFPR = %p, pReturnTypeDescr = "
+ "%p\n",
+ bSimpleReturn, pStack, nStack, pGPR, pFPR, pReturnTypeDescr);
+#endif
+ // Get pointer to method
+ sal_uInt64 pMethod = *((sal_uInt64*)pAdjustedThisPtr);
+ pMethod += 8 * nVtableIndex;
+ void* mfunc = (void*)*((sal_uInt64*)pMethod);
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "calling function %p\n", mfunc);
+#endif
+
+ // Load parameters to stack, if necessary
+ sal_uInt64* pCallStack = NULL;
+ if (nStack)
+ {
+ // 16-bytes aligned
+ sal_uInt32 nStackBytes = ((nStack + 1) >> 1) * 16;
+ pCallStack = (sal_uInt64*)__builtin_alloca(nStackBytes);
+ std::memcpy(pCallStack, pStack, nStackBytes);
+ }
+
+ sal_Int64* gret = (sal_Int64*)malloc(2 * sizeof(sal_Int64));
+ sal_Int64* gret1 = gret;
+ sal_Int64* gret2 = gret + 1;
+ double* fret = (double*)malloc(2 * sizeof(double));
+ double* fret1 = fret;
+ double* fret2 = fret + 1;
+ asm volatile(
+ //".set push \n\t"
+ //".set riscv64 \n\t"
+ // Fill the general purpose registers
+ "ld a0, 0(%[gpr]) \n\t"
+ "ld a1, 8(%[gpr]) \n\t"
+ "ld a2, 16(%[gpr]) \n\t"
+ "ld a3, 24(%[gpr]) \n\t"
+ "ld a4, 32(%[gpr]) \n\t"
+ "ld a5, 40(%[gpr]) \n\t"
+ "ld a6, 48(%[gpr]) \n\t"
+ "ld a7, 56(%[gpr]) \n\t"
+ // Fill the floating pointer registers
+ "fld fa0, 0(%[fpr]) \n\t"
+ "fld fa1, 8(%[fpr]) \n\t"
+ "fld fa2, 16(%[fpr]) \n\t"
+ "fld fa3, 24(%[fpr]) \n\t"
+ "fld fa4, 32(%[fpr]) \n\t"
+ "fld fa5, 40(%[fpr]) \n\t"
+ "fld fa6, 48(%[fpr]) \n\t"
+ "fld fa7, 56(%[fpr]) \n\t"
+ // Perform the call
+ "jalr ra,%[mfunc],0 \n\t"
+ // Fill the return values
+ "add %[gret1], a0,zero \n\t"
+ "add %[gret2], a1,zero \n\t"
+ "fmv.d %[fret1], fa0 \n\t"
+ "fmv.d %[fret2], fa1 \n\t"
+ //".set pop \n\t"
+ : [gret1] "=&r"(*gret1), [gret2] "=&r"(*gret2), [fret1] "=&f"(*fret1), [fret2] "=&f"(*fret2)
+ : [gpr] "r"(pGPR), [fpr] "r"(pFPR), [mfunc] "r"(mfunc),
+ [stack] "m"(
+ pCallStack) // dummy input to prevent the compiler from optimizing the alloca out
+ : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "ra", "fa0", "fa1", "fa2", "fa3", "fa4",
+ "fa5", "fa6", "fa7", "memory");
+#ifdef BRIDGE_DEBUG
+ printf("In callVirtualMethod, fret = %p, gret = %p\n", fret, gret);
+#endif
+
+ switch (pReturnTypeRef->eTypeClass)
+ {
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_CHAR:
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ *reinterpret_cast<sal_Int64*>(pRegisterReturn) = gret[0];
+ break;
+ case typelib_TypeClass_FLOAT:
+ case typelib_TypeClass_DOUBLE:
+ *reinterpret_cast<double*>(pRegisterReturn) = fret[0];
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ {
+ sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
+#ifdef BRIDGE_DEBUG
+ printf("nRetSize = %d\n", nRetSize);
+#endif
+ if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
+ {
+ typelib_TypeDescription* pTypeDescr = 0;
+ TYPELIB_DANGER_GET(&pTypeDescr, pReturnTypeRef);
+ abi_riscv64::fillStruct(pTypeDescr, gret, fret, pRegisterReturn);
+ TYPELIB_DANGER_RELEASE(pTypeDescr);
+ }
+ break;
+ }
+ default:
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "unhandled return type %u\n", pReturnTypeRef->eTypeClass);
+#endif
+ break;
+ }
+}
+
+static void cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy* pThis,
+ bridges::cpp_uno::shared::VtableSlot aVtableSlot,
+ typelib_TypeDescriptionReference* pReturnTypeRef, sal_Int32 nParams,
+ typelib_MethodParameter* pParams, void* pUnoReturn, void* pUnoArgs[],
+ uno_Any** ppUnoExc)
+{
+#ifdef BRIDGE_DEBUG
+ printf("In cpp_call\n");
+ printf("pThis = %p, aVtableSlot = %p, pReturnTypeRef = %p, nParams = %d\n", pThis, aVtableSlot,
+ pReturnTypeRef, nParams);
+ printf("pParams = %p , pUnoReturn = %p, pUnoArgs = %p\n", pParams, pUnoReturn, pUnoArgs);
+#endif
+ // 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_uInt64 pGPR[MAX_GP_REGS];
+ sal_uInt64 nREG = 0;
+
+ double pFPR[MAX_FP_REGS];
+ sal_uInt32 nFPR = 0;
+#ifdef BRIDGE_DEBUG
+ printf("pGPR = %p, pFPR = %p\n", pGPR, pFPR);
+#endif
+
+ // return
+ typelib_TypeDescription* pReturnTypeDescr = 0;
+ TYPELIB_DANGER_GET(&pReturnTypeDescr, pReturnTypeRef);
+ assert(pReturnTypeDescr);
+
+ void* pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
+
+ bool bSimpleReturn = true;
+ if (pReturnTypeDescr)
+ {
+ if (CPPU_CURRENT_NAMESPACE::return_in_hidden_param(pReturnTypeRef))
+ {
+ bSimpleReturn = false;
+ // complex return via ptr
+ pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr)
+ ? __builtin_alloca(pReturnTypeDescr->nSize)
+ : pUnoReturn;
+ INSERT_INT64(&pCppReturn, nREG, pGPR, pStack);
+ }
+ else
+ {
+ pCppReturn = pUnoReturn; // direct way for simple types
+ }
+ }
+
+ // push this
+ void* pAdjustedThisPtr = reinterpret_cast<void**>(pThis->getCppI()) + aVtableSlot.offset;
+ INSERT_INT64(&pAdjustedThisPtr, nREG, pGPR, pStack);
+
+ // args
+ void** pCppArgs = (void**)alloca(3 * sizeof(void*) * nParams);
+ // indices of values this have to be converted (interface conversion cpp<=>uno)
+ sal_Int32* pTempIndices = (sal_Int32*)(pCppArgs + nParams);
+ // type descriptions for reconversions
+ typelib_TypeDescription** ppTempParamTypeDescr
+ = (typelib_TypeDescription**)(pCppArgs + (2 * nParams));
+
+ sal_Int32 nTempIndices = 0;
+#ifdef BRIDGE_DEBUG
+ printf("In cpp_call, nParams = %d\n", nParams);
+ printf("pCppArgs = %p, pStack = %p\n", pCppArgs, pStack);
+#endif
+ for (sal_Int32 nPos = 0; nPos < nParams; ++nPos)
+ {
+#ifdef BRIDGE_DEBUG
+ printf("In cpp_call, nPos = %d\n", nPos);
+#endif
+ const typelib_MethodParameter& rParam = pParams[nPos];
+ typelib_TypeDescription* pParamTypeDescr = 0;
+ TYPELIB_DANGER_GET(&pParamTypeDescr, rParam.pTypeRef);
+
+ if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType(pParamTypeDescr))
+ {
+#ifdef BRIDGE_DEBUG
+ printf("Before uno_copyAndConvertData and tons of switch.\n");
+#endif
+ uno_copyAndConvertData(pCppArgs[nPos] = alloca(8), pUnoArgs[nPos], pParamTypeDescr,
+ pThis->getBridge()->getUno2Cpp());
+#ifdef BRIDGE_DEBUG
+ printf("Type = %d, Param = 0x%lx\n", pParamTypeDescr->eTypeClass,
+ *reinterpret_cast<sal_uInt64*>(pCppArgs[nPos]));
+#endif
+ switch (pParamTypeDescr->eTypeClass)
+ {
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_ENUM:
+ INSERT_INT32(pCppArgs[nPos], nREG, pGPR, pStack);
+ break;
+ case typelib_TypeClass_CHAR:
+ case typelib_TypeClass_SHORT:
+ INSERT_INT16(pCppArgs[nPos], nREG, pGPR, pStack);
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ INSERT_UINT16(pCppArgs[nPos], nREG, pGPR, pStack);
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ INSERT_INT8(pCppArgs[nPos], nREG, pGPR, pStack);
+ break;
+ case typelib_TypeClass_FLOAT:
+ case typelib_TypeClass_DOUBLE:
+ INSERT_FLOAT_DOUBLE(pCppArgs[nPos], nFPR, pFPR, nREG, pGPR, pStack);
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ INSERT_INT64(pCppArgs[nPos], nREG, pGPR, pStack);
+ break;
+ default:
+ break;
+ }
+
+ // no longer needed
+ TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+ }
+ else // ptr to complex value | ref
+ {
+ if (!rParam.bIn) // is pure out
+ {
+ // cpp out is constructed mem, uno out is not!
+ uno_constructData(pCppArgs[nPos] = alloca(pParamTypeDescr->nSize), pParamTypeDescr);
+ pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
+ // will be released at reconversion
+ ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+ }
+ // is in/inout
+ else if (bridges::cpp_uno::shared::relatesToInterfaceType(pParamTypeDescr))
+ {
+ uno_copyAndConvertData(pCppArgs[nPos] = alloca(pParamTypeDescr->nSize),
+ pUnoArgs[nPos], pParamTypeDescr,
+ pThis->getBridge()->getUno2Cpp());
+
+ pTempIndices[nTempIndices] = nPos; // has to be reconverted
+ // will be released at reconversion
+ ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+ }
+ else // direct way
+ {
+ pCppArgs[nPos] = pUnoArgs[nPos];
+ // no longer needed
+ TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+ }
+ INSERT_INT64(&(pCppArgs[nPos]), nREG, pGPR, pStack);
+ }
+ }
+
+ try
+ {
+ try
+ {
+ callVirtualMethod(pAdjustedThisPtr, aVtableSlot.index, pCppReturn, pReturnTypeRef,
+ bSimpleReturn, pStackStart, (pStack - pStackStart), pGPR, pFPR,
+ pReturnTypeDescr);
+ }
+ catch (css::uno::Exception&)
+ {
+ throw;
+ }
+ catch (std::exception& e)
+ {
+ throw css::uno::RuntimeException("C++ code threw "
+ + o3tl::runtimeToOUString(typeid(e).name()) + ": "
+ + o3tl::runtimeToOUString(e.what()));
+ }
+ catch (...)
+ {
+ throw css::uno::RuntimeException("C++ code threw unknown exception");
+ }
+ // NO exception occurred...
+ *ppUnoExc = 0;
+
+ // reconvert temporary params
+ for (; nTempIndices--;)
+ {
+ sal_Int32 nIndex = pTempIndices[nTempIndices];
+ typelib_TypeDescription* pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
+
+ if (pParams[nIndex].bIn)
+ {
+ if (pParams[nIndex].bOut) // inout
+ {
+ uno_destructData(pUnoArgs[nIndex], pParamTypeDescr, 0); // destroy uno value
+ uno_copyAndConvertData(pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
+ pThis->getBridge()->getCpp2Uno());
+ }
+ }
+ else // pure out
+ {
+ uno_copyAndConvertData(pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
+ pThis->getBridge()->getCpp2Uno());
+ }
+ // destroy temp cpp param => cpp: every param was constructed
+ uno_destructData(pCppArgs[nIndex], pParamTypeDescr, cpp_release);
+
+ TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+ }
+ // return value
+ if (pCppReturn && pUnoReturn != pCppReturn)
+ {
+ uno_copyAndConvertData(pUnoReturn, pCppReturn, pReturnTypeDescr,
+ pThis->getBridge()->getCpp2Uno());
+ uno_destructData(pCppReturn, pReturnTypeDescr, cpp_release);
+ }
+ }
+ catch (...)
+ {
+ // fill uno exception
+ CPPU_CURRENT_NAMESPACE::fillUnoException(*ppUnoExc, pThis->getBridge()->getCpp2Uno());
+
+ // temporary params
+ for (; nTempIndices--;)
+ {
+ sal_Int32 nIndex = pTempIndices[nTempIndices];
+ // destroy temp cpp param => cpp: every param was constructed
+ uno_destructData(pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release);
+ TYPELIB_DANGER_RELEASE(ppTempParamTypeDescr[nTempIndices]);
+ }
+ // return type
+ if (pReturnTypeDescr)
+ TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
+ }
+}
+}
+
+namespace bridges::cpp_uno::shared
+{
+void unoInterfaceProxyDispatch(uno_Interface* pUnoI, const typelib_TypeDescription* pMemberDescr,
+ void* pReturn, void* pArgs[], uno_Any** ppException)
+{
+#ifdef BRIDGE_DEBUG
+ printf("In unoInterfaceProxyDispatch:\n");
+ printf("pMemberDescr = %p, pReturn = %p, pArgs = %p, ppExeption = %p\n", pMemberDescr, pReturn,
+ pArgs, ppException);
+#endif
+ // is my surrogate
+ bridges::cpp_uno::shared::UnoInterfaceProxy* pThis
+ = static_cast<bridges::cpp_uno::shared::UnoInterfaceProxy*>(pUnoI);
+ //typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
+
+#ifdef BRIDGE_DEBUG
+ fprintf(stdout, "in dispatch\n");
+#endif
+
+ switch (pMemberDescr->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ VtableSlot aVtableSlot(getVtableSlot(
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription const*>(pMemberDescr)));
+
+ if (pReturn)
+ {
+ // dependent dispatch
+ cpp_call(
+ pThis, aVtableSlot,
+ ((typelib_InterfaceAttributeTypeDescription*)pMemberDescr)->pAttributeTypeRef,
+ 0, 0, // no params
+ pReturn, pArgs, ppException);
+ }
+ else
+ {
+ // is SET
+ typelib_MethodParameter aParam;
+ aParam.pTypeRef
+ = ((typelib_InterfaceAttributeTypeDescription*)pMemberDescr)->pAttributeTypeRef;
+ aParam.bIn = sal_True;
+ aParam.bOut = sal_False;
+
+ typelib_TypeDescriptionReference* pReturnTypeRef = 0;
+ OUString aVoidName("void");
+ typelib_typedescriptionreference_new(&pReturnTypeRef, typelib_TypeClass_VOID,
+ aVoidName.pData);
+
+ // dependent dispatch
+ aVtableSlot.index += 1; //get then set method
+ cpp_call(pThis, aVtableSlot, pReturnTypeRef, 1, &aParam, pReturn, pArgs,
+ ppException);
+
+ typelib_typedescriptionreference_release(pReturnTypeRef);
+ }
+
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ VtableSlot aVtableSlot(getVtableSlot(
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription const*>(pMemberDescr)));
+ switch (aVtableSlot.index)
+ {
+ // standard calls
+ case 1: // acquire uno interface
+ (*pUnoI->acquire)(pUnoI);
+ *ppException = 0;
+ break;
+ case 2: // release uno interface
+ (*pUnoI->release)(pUnoI);
+ *ppException = 0;
+ break;
+ case 0: // queryInterface() opt
+ {
+ typelib_TypeDescription* pTD = 0;
+ TYPELIB_DANGER_GET(&pTD, reinterpret_cast<Type*>(pArgs[0])->getTypeLibType());
+ if (pTD)
+ {
+ uno_Interface* pInterface = 0;
+ (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
+ pThis->pBridge->getUnoEnv(), (void**)&pInterface, pThis->oid.pData,
+ (typelib_InterfaceTypeDescription*)pTD);
+
+ if (pInterface)
+ {
+ ::uno_any_construct(reinterpret_cast<uno_Any*>(pReturn), &pInterface,
+ pTD, 0);
+ (*pInterface->release)(pInterface);
+ TYPELIB_DANGER_RELEASE(pTD);
+ *ppException = 0;
+ break;
+ }
+ TYPELIB_DANGER_RELEASE(pTD);
+ }
+ } // else perform queryInterface()
+ default:
+ // dependent dispatch
+ cpp_call(
+ pThis, aVtableSlot,
+ ((typelib_InterfaceMethodTypeDescription*)pMemberDescr)->pReturnTypeRef,
+ ((typelib_InterfaceMethodTypeDescription*)pMemberDescr)->nParams,
+ ((typelib_InterfaceMethodTypeDescription*)pMemberDescr)->pParams, pReturn,
+ pArgs, ppException);
+ }
+ break;
+ }
+ default:
+ {
+ ::com::sun::star::uno::RuntimeException aExc(
+ "illegal member type description!",
+ ::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface>());
+
+ Type const& rExcType = cppu::UnoType<decltype(aExc)>::get();
+ // binary identical null reference
+ ::uno_type_any_construct(*ppException, &aExc, rExcType.getTypeLibType(), 0);
+ }
+ }
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */