diff --git a/libreoffice.changes b/libreoffice.changes index 6d3ba15..7ab4594 100644 --- a/libreoffice.changes +++ b/libreoffice.changes @@ -3,6 +3,12 @@ Mon Feb 6 08:55:57 UTC 2023 - Guillaume GARDET - Update _constraints to match current requirements +------------------------------------------------------------------- +Wed Feb 1 10:47:11 UTC 2023 - Andreas Schwab + +- riscv64-support.patch: Add backport of riscv64 support +- No gold on riscv64 + ------------------------------------------------------------------- Sat Jan 28 23:37:14 UTC 2023 - Dirk Müller diff --git a/libreoffice.spec b/libreoffice.spec index 9927ec1..247d3f0 100644 --- a/libreoffice.spec +++ b/libreoffice.spec @@ -126,11 +126,15 @@ Patch101: 0001-Revert-java-9-changes.patch Patch990: install-with-hardlinks.diff # save time by relying on rpm check rather than doing stupid find+grep Patch991: libreoffice-no-destdircheck.patch +# PATCH-FIX-UPSTREAM Add riscv64 support (backport of commit bc9487f745be) +Patch1000: riscv64-support.patch BuildRequires: %{name}-share-linker BuildRequires: ant BuildRequires: autoconf BuildRequires: awk +%ifnarch riscv64 BuildRequires: binutils-gold +%endif BuildRequires: bison BuildRequires: bsh2 BuildRequires: commons-logging @@ -280,7 +284,7 @@ Provides: %{name}-icon-theme-crystal = %{version} Obsoletes: %{name}-icon-theme-crystal < %{version} Provides: %{name}-icon-theme-oxygen = %{version} Obsoletes: %{name}-icon-theme-oxygen < %{version} -ExclusiveArch: aarch64 %{ix86} x86_64 ppc64le +ExclusiveArch: aarch64 %{ix86} x86_64 ppc64le riscv64 %if 0%{?suse_version} < 1550 # Too old boost on the system Source2020: %{external_url}/boost_1_79_0.tar.xz @@ -1050,6 +1054,7 @@ Provides %{langname} translations and additional resources (help files, etc.) fo %patch17 -p1 %patch990 -p1 %patch991 -p1 +%patch1000 -p1 # Disable some of the failing tests (some are random) %if 0%{?suse_version} < 1330 @@ -1127,7 +1132,11 @@ export NOCONFIGURE=yes %configure \ --with-parallelism=%{jobs} \ --enable-eot \ +%ifarch riscv64 + --enable-ld=bfd \ +%else --enable-ld=gold \ +%endif %if %{with lto} --enable-lto \ %endif diff --git a/riscv64-support.patch b/riscv64-support.patch new file mode 100644 index 0000000..f382709 --- /dev/null +++ b/riscv64-support.patch @@ -0,0 +1,2175 @@ +From bc9487f745befde6534fd46058e119256952323d Mon Sep 17 00:00:00 2001 +From: Sakura286 +Date: Tue, 26 Jul 2022 02:18:23 +0000 +Subject: [PATCH] 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 and Stephan Bergmann + The riscv64 bridge implementation refers to mips64 and + AArch64 bridges. + - Bo Yu configures gbuild for riscv64. + - WANG Xuerui provides lots of guiding tips. + +Change-Id: Ifad3b0de8b2c9e7328627ed03396bbd45a9c71e4 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137445 +Reviewed-by: Stephan Bergmann +Tested-by: Jenkins +--- + +Index: libreoffice-7.4.3.2/bridges/Library_cpp_uno.mk +=================================================================== +--- libreoffice-7.4.3.2.orig/bridges/Library_cpp_uno.mk ++++ libreoffice-7.4.3.2/bridges/Library_cpp_uno.mk +@@ -114,6 +114,15 @@ bridge_noopt_objects := cpp2uno uno2cpp + bridge_exception_objects := except + endif + ++else ifeq ($(CPUNAME),RISCV64) ++ ++ifneq ($(filter LINUX,$(OS)),) ++bridges_SELECTED_BRIDGE := gcc3_linux_riscv64 ++bridge_asm_objects := call ++bridge_noopt_objects := abi cpp2uno uno2cpp ++bridge_exception_objects := except ++endif ++ + else ifeq ($(CPUNAME),POWERPC) + + ifneq ($(filter DRAGONFLY FREEBSD LINUX NETBSD OPENBSD,$(OS)),) +Index: libreoffice-7.4.3.2/bridges/source/cpp_uno/gcc3_linux_riscv64/abi.cxx +=================================================================== +--- /dev/null ++++ libreoffice-7.4.3.2/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 ++#include ++#include ++#include "types.hxx" ++#include "abi.hxx" ++#include ++#include ++ ++//#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(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(pTypeDescr)); ++ char* pAdjust = reinterpret_cast(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: */ +Index: libreoffice-7.4.3.2/bridges/source/cpp_uno/gcc3_linux_riscv64/abi.hxx +=================================================================== +--- /dev/null ++++ libreoffice-7.4.3.2/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 ++#include ++ ++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: */ +Index: libreoffice-7.4.3.2/bridges/source/cpp_uno/gcc3_linux_riscv64/call.hxx +=================================================================== +--- /dev/null ++++ libreoffice-7.4.3.2/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 ++ ++#include ++ ++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: */ +Index: libreoffice-7.4.3.2/bridges/source/cpp_uno/gcc3_linux_riscv64/call.s +=================================================================== +--- /dev/null ++++ libreoffice-7.4.3.2/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: */ +Index: libreoffice-7.4.3.2/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx +=================================================================== +--- /dev/null ++++ libreoffice-7.4.3.2/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 ++#include ++#include ++#include ++#include ++#include "bridge.hxx" ++#include "cppinterfaceproxy.hxx" ++#include "types.hxx" ++#include "vtablefactory.hxx" ++#include "call.hxx" ++#include "share.hxx" ++#include "abi.hxx" ++ ++#include ++//#include ++#include ++ ++using namespace com::sun::star::uno; ++ ++//#define BRIDGE_DEBUG ++ ++#ifdef BRIDGE_DEBUG ++#include ++#include ++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(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(gpreg); ++ char* fpreg_t = reinterpret_cast(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(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( ++ 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(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(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(gpreg[2])->getTypeLibType()); ++ if (pTD) ++ { ++ XInterface* pInterface = 0; ++ (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( ++ pCppI->getBridge()->getCppEnv(), (void**)&pInterface, ++ pCppI->getOid().pData, ++ reinterpret_cast(pTD)); ++ ++ if (pInterface) ++ { ++ ::uno_any_construct(reinterpret_cast(gpreg[0]), &pInterface, ++ pTD, cpp_acquire); ++ ++ pInterface->release(); ++ TYPELIB_DANGER_RELEASE(pTD); ++ ++ reinterpret_cast(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( ++ 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(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(member) ++ ->pAttributeTypeRef)); ++ ++ // Setter: ++ if (!reinterpret_cast(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(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: */ +Index: libreoffice-7.4.3.2/bridges/source/cpp_uno/gcc3_linux_riscv64/except.cxx +=================================================================== +--- /dev/null ++++ libreoffice-7.4.3.2/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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#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 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 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 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::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::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: */ +Index: libreoffice-7.4.3.2/bridges/source/cpp_uno/gcc3_linux_riscv64/share.hxx +=================================================================== +--- /dev/null ++++ libreoffice-7.4.3.2/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 ++#include ++#include ++ ++#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: */ +Index: libreoffice-7.4.3.2/bridges/source/cpp_uno/gcc3_linux_riscv64/uno2cpp.cxx +=================================================================== +--- /dev/null ++++ libreoffice-7.4.3.2/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 ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++#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(pSV); \ ++ else if (ngr < MAX_FP_REGS) \ ++ pGPR[ngr++] = *reinterpret_cast(pSV); \ ++ else \ ++ *pDS++ = *reinterpret_cast(pSV); // verbatim! ++ ++#define INSERT_INT64(pSV, nr, pGPR, pDS) \ ++ if (nr < MAX_GP_REGS) \ ++ pGPR[nr++] = *reinterpret_cast(pSV); \ ++ else \ ++ *pDS++ = *reinterpret_cast(pSV); ++ ++#define INSERT_INT32(pSV, nr, pGPR, pDS) \ ++ if (nr < MAX_GP_REGS) \ ++ pGPR[nr++] = *reinterpret_cast(pSV); \ ++ else \ ++ *pDS++ = *reinterpret_cast(pSV); ++ ++#define INSERT_INT16(pSV, nr, pGPR, pDS) \ ++ if (nr < MAX_GP_REGS) \ ++ pGPR[nr++] = *reinterpret_cast(pSV); \ ++ else \ ++ *pDS++ = *reinterpret_cast(pSV); ++ ++#define INSERT_UINT16(pSV, nr, pGPR, pDS) \ ++ if (nr < MAX_GP_REGS) \ ++ pGPR[nr++] = *reinterpret_cast(pSV); \ ++ else \ ++ *pDS++ = *reinterpret_cast(pSV); ++ ++#define INSERT_INT8(pSV, nr, pGPR, pDS) \ ++ if (nr < MAX_GP_REGS) \ ++ pGPR[nr++] = *reinterpret_cast(pSV); \ ++ else \ ++ *pDS++ = *reinterpret_cast(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(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(pRegisterReturn)[0] = fret[0]; ++ reinterpret_cast(pRegisterReturn)[1] = fret[1]; ++ } ++ else ++ { ++ reinterpret_cast(pRegisterReturn)[0] = gret[0]; ++ reinterpret_cast(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(pRegisterReturn) = gret[0]; ++ break; ++ case typelib_TypeClass_FLOAT: ++ case typelib_TypeClass_DOUBLE: ++ *reinterpret_cast(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(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(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(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(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(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(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(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::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: */ +Index: libreoffice-7.4.3.2/configure.ac +=================================================================== +--- libreoffice-7.4.3.2.orig/configure.ac ++++ libreoffice-7.4.3.2/configure.ac +@@ -5216,6 +5216,11 @@ linux-gnu*|linux-musl*) + RTL_ARCH=PowerPC_64_LE + PLATFORMID=linux_powerpc64_le + ;; ++ riscv64) ++ CPUNAME=RISCV64 ++ RTL_ARCH=RISCV64 ++ PLATFORMID=linux_riscv64 ++ ;; + sparc) + CPUNAME=SPARC + RTL_ARCH=SPARC +@@ -8579,7 +8584,7 @@ if test "$ENABLE_JAVA" != ""; then + JAVAINTERPRETER=`win_short_path_for_make "$JAVAINTERPRETER"` + elif test "$cross_compiling" != "yes"; then + case $CPUNAME in +- AARCH64|AXP|X86_64|HPPA|IA64|POWERPC64|S390X|SPARC64|GODSON64) ++ AARCH64|AXP|X86_64|HPPA|IA64|POWERPC64|S390X|SPARC64|GODSON64|RISCV64) + if test -f "$JAVAINTERPRETER" -a "`$JAVAINTERPRETER -version 2>&1 | $GREP -i 64-bit`" = "" >/dev/null; then + AC_MSG_WARN([You are building 64-bit binaries but the JDK $JAVAINTERPRETER is 32-bit]) + AC_MSG_ERROR([You should pass the --with-jdk-home option pointing to a 64-bit JDK]) +@@ -12876,7 +12881,7 @@ AC_SUBST(RHINO_JAR) + # platforms there. + supports_multilib= + case "$host_cpu" in +-x86_64 | powerpc64 | powerpc64le | s390x | aarch64 | mips64 | mips64el) ++x86_64 | powerpc64 | powerpc64le | s390x | aarch64 | mips64 | mips64el | riscv64) + if test "$SAL_TYPES_SIZEOFLONG" = "8"; then + supports_multilib="yes" + fi +Index: libreoffice-7.4.3.2/jvmfwk/inc/vendorbase.hxx +=================================================================== +--- libreoffice-7.4.3.2.orig/jvmfwk/inc/vendorbase.hxx ++++ libreoffice-7.4.3.2/jvmfwk/inc/vendorbase.hxx +@@ -59,6 +59,8 @@ OpenJDK at least, but probably not true + #else + #define JFW_PLUGIN_ARCH "mips64el" + #endif ++#elif defined RISCV64 ++#define JFW_PLUGIN_ARCH "riscv64" + #elif defined S390X + #define JFW_PLUGIN_ARCH "s390x" + #elif defined S390 +Index: libreoffice-7.4.3.2/m4/ax_boost_base.m4 +=================================================================== +--- libreoffice-7.4.3.2.orig/m4/ax_boost_base.m4 ++++ libreoffice-7.4.3.2/m4/ax_boost_base.m4 +@@ -91,7 +91,7 @@ if test "x$want_boost" = "xyes"; then + dnl are found, e.g. when only header-only libraries are installed! + libsubdirs="lib" + ax_arch=`uname -m` +- if test $ax_arch = x86_64 -o $ax_arch = ppc64 -o $ax_arch = ppc64le -o $ax_arch = s390x -o $ax_arch = sparc64 -o $ax_arch = aarch64; then ++ if test $ax_arch = x86_64 -o $ax_arch = ppc64 -o $ax_arch = ppc64le -o $ax_arch = s390x -o $ax_arch = sparc64 -o $ax_arch = aarch64 -o $ax_arch = riscv64; then + libsubdirs="lib64 lib lib64" + fi + +Index: libreoffice-7.4.3.2/solenv/gbuild/platform/LINUX_RISCV64_GCC.mk +=================================================================== +--- /dev/null ++++ libreoffice-7.4.3.2/solenv/gbuild/platform/LINUX_RISCV64_GCC.mk +@@ -0,0 +1,15 @@ ++# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- ++# ++# 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/. ++# ++ ++#please make generic modifications to unxgcc.mk or linux.mk ++gb_COMPILEROPTFLAGS := -Os ++ ++include $(GBUILDDIR)/platform/linux.mk ++ ++# vim: set noet sw=4: