diff options
author | Yixun Lan <dlan@gentoo.org> | 2022-10-13 04:56:33 +0800 |
---|---|---|
committer | Yixun Lan <dlan@gentoo.org> | 2022-10-13 04:59:52 +0800 |
commit | 85f216842196ad85d1efbb0e9b782fb10e03081e (patch) | |
tree | 8d95cecdff2bf9a66cdc25b1a2e2391c384463d1 | |
parent | app-office/libreoffice: import from portage (diff) | |
download | riscv-85f216842196ad85d1efbb0e9b782fb10e03081e.tar.gz riscv-85f216842196ad85d1efbb0e9b782fb10e03081e.tar.bz2 riscv-85f216842196ad85d1efbb0e9b782fb10e03081e.zip |
app-office/libreoffice: add riscv64 support
the patch is still under review..
pushed this package here to give users more testing
Signed-off-by: Yixun Lan <dlan@gentoo.org>
-rw-r--r-- | app-office/libreoffice/files/libreoffice-7.3.6.2-riscv64.patch | 1964 | ||||
-rw-r--r-- | app-office/libreoffice/libreoffice-7.3.6.2.ebuild | 3 |
2 files changed, 1967 insertions, 0 deletions
diff --git a/app-office/libreoffice/files/libreoffice-7.3.6.2-riscv64.patch b/app-office/libreoffice/files/libreoffice-7.3.6.2-riscv64.patch new file mode 100644 index 0000000..0937fbe --- /dev/null +++ b/app-office/libreoffice/files/libreoffice-7.3.6.2-riscv64.patch @@ -0,0 +1,1964 @@ +Subject: [PATCH] libreoffice-riscv64 + +https://gerrit.libreoffice.org/c/core/+/137445 + +--- + bridges/Library_cpp_uno.mk | 9 + + .../cpp_uno/gcc3_linux_riscv64/call.hxx | 35 + + .../source/cpp_uno/gcc3_linux_riscv64/call.s | 72 ++ + .../cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx | 723 ++++++++++++++++++ + .../cpp_uno/gcc3_linux_riscv64/except.cxx | 297 +++++++ + .../cpp_uno/gcc3_linux_riscv64/share.hxx | 89 +++ + .../cpp_uno/gcc3_linux_riscv64/uno2cpp.cxx | 595 ++++++++++++++ + configure.ac | 10 +- + jvmfwk/inc/vendorbase.hxx | 2 + + solenv/gbuild/platform/LINUX_RISCV64_GCC.mk | 15 + + 10 files changed, 1845 insertions(+), 2 deletions(-) + create mode 100644 bridges/source/cpp_uno/gcc3_linux_riscv64/call.hxx + create mode 100644 bridges/source/cpp_uno/gcc3_linux_riscv64/call.s + create mode 100644 bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx + create mode 100644 bridges/source/cpp_uno/gcc3_linux_riscv64/except.cxx + create mode 100644 bridges/source/cpp_uno/gcc3_linux_riscv64/share.hxx + create mode 100644 bridges/source/cpp_uno/gcc3_linux_riscv64/uno2cpp.cxx + create mode 100644 solenv/gbuild/platform/LINUX_RISCV64_GCC.mk + +diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk +index a76d2b8..ce27a7e 100644 +--- a/bridges/Library_cpp_uno.mk ++++ b/bridges/Library_cpp_uno.mk +@@ -120,6 +120,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 := cpp2uno uno2cpp ++bridge_exception_objects := except ++endif ++ + else ifeq ($(CPUNAME),POWERPC) + + ifneq ($(filter DRAGONFLY FREEBSD LINUX NETBSD OPENBSD,$(OS)),) +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 0000000..dc84d56 +--- /dev/null ++++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/call.hxx +@@ -0,0 +1,35 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* ++ * 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" typelib_TypeClass 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: */ +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 0000000..2bddfc1 +--- /dev/null ++++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/call.s +@@ -0,0 +1,72 @@ ++/* ++ * 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 . ++ */ ++// https://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_mips64/call.s ++ ++ .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 ++ ld a0,0(sp) ++ ld a1,8(sp) ++ fld fa0,0(sp) ++ fld fa1,8(sp) ++ 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 +\ No newline at end of file +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 0000000..4ee41ab +--- /dev/null ++++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx +@@ -0,0 +1,723 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* ++ * 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 <stdio.h> ++#include <string.h> ++ ++using namespace com::sun::star::uno; ++ ++//#define BRDEBUG ++ ++#ifdef BRDEBUG ++#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 typelib_TypeClass cpp2uno_call( ++ bridges::cpp_uno::shared::CppInterfaceProxy * pThis, ++ const typelib_TypeDescription * pMemberTypeDescr, ++ typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return ++ sal_Int32 nParams, typelib_MethodParameter * pParams, ++ void ** gpreg, void ** fpreg, void ** ovrflw, ++ sal_uInt64 * pRegisterReturn /* space for register return */ ) ++ { ++ /* Most MIPS ABIs view the arguments as a struct, of which the ++ first N words go in registers and the rest go on the stack. If I < N, the ++ With word might go in With integer argument register or the With ++ floating-point one. For these ABIs, we only need to remember the number ++ of words passed so far. We are interested only in n64 ABI,so it is the ++ case. ++ */ ++ unsigned int nREG = 0; ++ ++#ifdef BRDEBUG ++ 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[nREG]; // complex return via ptr (pCppReturn) ++ nREG++; ++ ++ pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) ++ ? alloca( pReturnTypeDescr->nSize ) ++ : pCppReturn); // direct way ++#ifdef BRDEBUG ++ fprintf(stdout, "cpp2uno_call:complexreturn\n"); ++#endif ++ } ++ else ++ { ++ pUnoReturn = pRegisterReturn; // direct way for simple types ++#ifdef BRDEBUG ++ fprintf(stdout, "cpp2uno_call:simplereturn\n"); ++#endif ++ } ++ } ++ ++ // pop this ++ nREG++; ++ ++ // 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 BRDEBUG ++ 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 BRDEBUG ++ 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 (nREG < MAX_FP_REGS) { ++#ifdef BRDEBUG ++ fprintf(stdout, "cpp2uno_call:fpr=%p\n", fpreg[nREG]); ++#endif ++ pCppArgs[nPos] = &(fpreg[nREG]); ++ pUnoArgs[nPos] = &(fpreg[nREG]); ++ } else { ++#ifdef BRDEBUG ++ fprintf(stdout, "cpp2uno_call:fpr=%p\n", ovrflw[nREG - MAX_FP_REGS]); ++#endif ++ pCppArgs[nPos] = &(ovrflw[nREG - MAX_FP_REGS]); ++ pUnoArgs[nPos] = &(ovrflw[nREG - MAX_FP_REGS]); ++ } ++ nREG++; ++ break; ++ ++ ++ default: ++ if (nREG < MAX_GP_REGS) { ++#ifdef BRDEBUG ++ fprintf(stdout, "cpp2uno_call:gpr=%p\n", gpreg[nREG]); ++#endif ++ pCppArgs[nPos] = &(gpreg[nREG]); ++ pUnoArgs[nPos] = &(gpreg[nREG]); ++ } else { ++#ifdef BRDEBUG ++ fprintf(stdout, "cpp2uno_call:gpr=%p\n", ovrflw[nREG - MAX_GP_REGS]); ++#endif ++ pCppArgs[nPos] = &(ovrflw[nREG - MAX_GP_REGS]); ++ pUnoArgs[nPos] = &(ovrflw[nREG - MAX_GP_REGS]); ++ } ++ nREG++; ++ break; ++ ++ } ++ // no longer needed ++ TYPELIB_DANGER_RELEASE( pParamTypeDescr ); ++ } ++ else // ptr to complex value | ref ++ { ++#ifdef BRDEBUG ++ fprintf(stdout,"cpp2uno_call:ptr|ref\n"); ++#endif ++ void *pCppStack; ++ if (nREG < MAX_GP_REGS) { ++ pCppArgs[nPos] = pCppStack = gpreg[nREG]; ++ } else { ++ pCppArgs[nPos] = pCppStack = ovrflw[nREG - MAX_GP_REGS]; ++ } ++ nREG++; ++#ifdef BRDEBUG ++ 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 BRDEBUG ++ 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 BRDEBUG ++ fprintf(stdout, "cpp2uno_call:direct,pUnoArgs[%d]=%p\n", nPos, pUnoArgs[nPos]); ++#endif ++ // no longer needed ++ TYPELIB_DANGER_RELEASE( pParamTypeDescr ); ++ } ++ } ++ } ++#ifdef BRDEBUG ++ fprintf(stdout, "cpp2uno_call2,%p,unoargs=%p\n", pThis->getUnoI()->pDispatcher, pUnoArgs); ++#endif ++ ++ // ExceptionHolder ++ uno_Any aUnoExc; // Any will be constructed by callee ++ uno_Any * pUnoExc = &aUnoExc; ++ ++ // invoke uno dispatch call ++ (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); ++#ifdef BRDEBUG ++ 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 ); ++ } ++ // return ++ if (pCppReturn) // has complex return ++ { ++ if (pUnoReturn != pCppReturn) // needs reconversion ++ { ++ 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; ++ } ++ if (pReturnTypeDescr) ++ { ++ typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; ++ TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); ++ return eRet; ++ } ++ else ++ return typelib_TypeClass_VOID; ++ } ++ } ++ ++ ++ /** ++ * is called on incoming vtable calls ++ * (called by asm snippets) ++ */ ++ typelib_TypeClass cpp_vtable_call( ++ sal_Int32 nFunctionIndex, ++ sal_Int32 nVtableOffset, ++ void ** gpreg, void ** fpreg, void ** ovrflw, ++ sal_uInt64 * pRegisterReturn /* space for register return */ ) ++ { ++ static_assert( sizeof(sal_Int64)==sizeof(void *), "### unexpected!" ); ++ ++#ifdef BRDEBUG ++ 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 BRDEBUG ++ 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 BRDEBUG ++ 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 BRDEBUG ++ //OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); ++ //fprintf(stdout, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex ); ++#endif ++ typelib_TypeClass eRet; ++ switch (aMemberDescr.get()->eTypeClass) ++ { ++ case typelib_TypeClass_INTERFACE_ATTRIBUTE: ++ { ++#ifdef BRDEBUG ++ 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 BRDEBUG ++ fprintf(stdout, "cpp_vtable_call interface method\n"); ++#endif ++ // is METHOD ++ switch (nFunctionIndex) ++ { ++ case 1: // acquire() ++#ifdef BRDEBUG ++ fprintf(stdout, "cpp_vtable_call method acquire\n"); ++#endif ++ pCppI->acquireProxy(); // non virtual call! ++ eRet = typelib_TypeClass_VOID; ++ break; ++ case 2: // release() ++#ifdef BRDEBUG ++ fprintf(stdout, "cpp_vtable_call method release\n"); ++#endif ++ pCppI->releaseProxy(); // non virtual call! ++ eRet = typelib_TypeClass_VOID; ++ break; ++ case 0: // queryInterface() opt ++ { ++#ifdef BRDEBUG ++ 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 = typelib_TypeClass_ANY; ++ break; ++ } ++ TYPELIB_DANGER_RELEASE( pTD ); ++ } ++ } // else perform queryInterface() ++ default: ++#ifdef BRDEBUG ++ 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 BRDEBUG ++ 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 BRDEBUG ++ 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 */ ++ /* ++ # 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 BRDEBUG ++ 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: */ +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 0000000..e37e5d8 +--- /dev/null ++++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/except.cxx +@@ -0,0 +1,297 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* ++ * 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 BRIDGES_DEBUG ++ ++namespace CPPU_CURRENT_NAMESPACE ++{ ++ ++void dummy_can_throw_anything( char const * ) ++{ ++} ++ ++static OUString toUNOname( char const * p ) ++{ ++#if defined BRIDGES_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 BRIDGES_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 BRIDGES_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 ) ++{ ++ fprintf( stderr, "in deleteException: pExc = %p\n",pExc ); ++ __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 BRIDGES_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 BRIDGES_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: */ +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 0000000..ee2235e +--- /dev/null ++++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/share.hxx +@@ -0,0 +1,89 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* ++ * 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: */ +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 0000000..cae7507 +--- /dev/null ++++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/uno2cpp.cxx +@@ -0,0 +1,595 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* ++ * 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" ++ ++//#define BRDEBUG ++#ifdef BRDEBUG ++#include <stdio.h> ++#endif ++ ++#define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \ ++ if ( nr < MAX_FP_REGS ) \ ++ pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \ ++ else \ ++ *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim! ++ ++#define INSERT_INT64( pSV, nr, pGPR, pDS ) \ ++ if ( nr < MAX_GP_REGS ) \ ++ pGPR[nr++] = *reinterpret_cast<sal_Int64 *>( pSV ); \ ++ else \ ++ *pDS++ = *reinterpret_cast<sal_Int64 *>( pSV ); ++ ++#define INSERT_INT32( pSV, nr, pGPR, pDS ) \ ++ if ( nr < MAX_GP_REGS ) \ ++ pGPR[nr++] = *reinterpret_cast<sal_Int32 *>( pSV ); \ ++ else \ ++ *pDS++ = *reinterpret_cast<sal_Int32 *>( pSV ); ++ ++#define INSERT_INT16( pSV, nr, pGPR, pDS ) \ ++ if ( nr < MAX_GP_REGS ) \ ++ pGPR[nr++] = *reinterpret_cast<sal_Int16 *>( pSV ); \ ++ else \ ++ *pDS++ = *reinterpret_cast<sal_Int16 *>( pSV ); ++ ++#define INSERT_UINT16( pSV, nr, pGPR, pDS ) \ ++ if ( nr < MAX_GP_REGS ) \ ++ pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ ++ else \ ++ *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); ++ ++#define INSERT_INT8( pSV, nr, pGPR, pDS ) \ ++ if ( nr < MAX_GP_REGS ) \ ++ pGPR[nr++] = *reinterpret_cast<sal_Int8 *>( pSV ); \ ++ else \ ++ *pDS++ = *reinterpret_cast<sal_Int8 *>( pSV ); ++ ++using namespace ::com::sun::star::uno; ++ ++namespace ++{ ++ ++ bool isReturnInFPR(const typelib_TypeDescription * pTypeDescr, sal_uInt32 & nSize) ++ { ++ const typelib_CompoundTypeDescription *p = ++ reinterpret_cast<const typelib_CompoundTypeDescription*>( pTypeDescr ); ++ ++ for (sal_Int32 i = 0; i < p->nMembers; ++i) ++ { ++ typelib_TypeDescriptionReference *pTypeInStruct = p->ppTypeRefs[ i ]; ++ ++ switch (pTypeInStruct->eTypeClass) ++ { ++ case typelib_TypeClass_STRUCT: ++ case typelib_TypeClass_EXCEPTION: ++ { ++ typelib_TypeDescription * t = 0; ++ TYPELIB_DANGER_GET(&t, pTypeInStruct); ++ bool isFPR = isReturnInFPR(t, nSize); ++ TYPELIB_DANGER_RELEASE(t); ++ if (!isFPR) ++ return false; ++ } ++ break; ++ case typelib_TypeClass_FLOAT: ++ case typelib_TypeClass_DOUBLE: ++ if (nSize >= 16) ++ return false; ++ nSize += 8; ++ break; ++ default: ++ return false; ++ } ++ } ++ return true; ++ } ++ ++ void fillReturn(const typelib_TypeDescription * pTypeDescr, ++ sal_Int64 * gret, double * fret, void * pRegisterReturn) ++ { ++ sal_uInt32 nSize = 0; ++ if (isReturnInFPR(pTypeDescr, nSize)) ++ { ++ reinterpret_cast<double *>( pRegisterReturn )[0] = fret[0]; ++ reinterpret_cast<double *>( pRegisterReturn )[1] = fret[1]; ++ } ++ else ++ { ++ reinterpret_cast<sal_Int64 *>( pRegisterReturn )[0] = gret[0]; ++ reinterpret_cast<sal_Int64 *>( pRegisterReturn )[1] = gret[1]; ++ } ++ } ++ ++ static void callVirtualMethod( ++ void * pAdjustedThisPtr, ++ sal_Int32 nVtableIndex, ++ void * pRegisterReturn, ++ typelib_TypeDescriptionReference * pReturnTypeRef, ++ bool bSimpleReturn, ++ sal_uInt64 *pStack, ++ sal_uInt32 nStack, ++ sal_uInt64 *pGPR, ++ double *pFPR, ++ sal_uInt32 nREG) ++ { ++ // Should not happen, but... ++ static_assert(MAX_GP_REGS == MAX_FP_REGS, "must be the same size"); ++ if ( nREG > MAX_GP_REGS ) ++ nREG = MAX_GP_REGS; ++ ++ // Get pointer to method ++ sal_uInt64 pMethod = *((sal_uInt64 *)pAdjustedThisPtr); ++ pMethod += 8 * nVtableIndex; ++ void *mfunc = (void *) *((sal_uInt64 *)pMethod); ++#ifdef BRDEBUG ++ 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[2]; ++ double fret[2]; ++ 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" ++ "fcvt.d.l ft7,zero \n\t" ++ "fadd.d %[fret1], fa0,ft7 \n\t" ++ "fadd.d %[fret2], fa1,ft7 \n\t" ++ //".set pop \n\t" ++ :[gret1]"=r"(gret[0]), [gret2]"=r"(gret[1]), ++ [fret1]"=f"(fret[0]), [fret2]"=f"(fret[1]) ++ :[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", ++ "ft7" ++ ); ++ ++ 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; ++ if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0) ++ { ++ typelib_TypeDescription * pTypeDescr = 0; ++ TYPELIB_DANGER_GET( &pTypeDescr, pReturnTypeRef ); ++ fillReturn(pTypeDescr, gret, fret, pRegisterReturn); ++ TYPELIB_DANGER_RELEASE( pTypeDescr ); ++ } ++ break; ++ } ++ default: ++#ifdef BRDEBUG ++ 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 ) ++ { ++ // 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]; ++ double pFPR[MAX_FP_REGS]; ++ sal_uInt32 nREG = 0; ++ ++#ifdef BRDEBUG ++ fprintf(stdout, "in cpp_call\n"); ++#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; ++ ++ 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 )) ++ { ++ uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr, ++ pThis->getBridge()->getUno2Cpp() ); ++ ++ switch (pParamTypeDescr->eTypeClass) ++ { ++ case typelib_TypeClass_LONG: ++ case typelib_TypeClass_UNSIGNED_LONG: ++ INSERT_INT64( pCppArgs[nPos], nREG, pGPR, pStack ); ++ break; ++ case typelib_TypeClass_ENUM: ++ INSERT_INT32( pCppArgs[nPos], nREG, pGPR, pStack ); ++ 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], nREG, pFPR, 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, nREG); ++ } 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 ) ++{ ++ // is my surrogate ++ bridges::cpp_uno::shared::UnoInterfaceProxy * pThis ++ = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI); ++ //typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; ++ ++#ifdef BRDEBUG ++ 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: */ +diff --git a/configure.ac b/configure.ac +index 8c868fa..5fbd4fc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -5085,6 +5085,12 @@ linux-gnu*|linux-musl*) + EPM_FLAGS="-a mipsel" + PLATFORMID=linux_mips_el + ;; ++ riscv64) ++ CPUNAME=RISCV64 ++ RTL_ARCH=RISCV64 ++ EPM_FLAGS="-a riscv64" ++ PLATFORMID=linux_riscv64 ++ ;; + m68k) + CPUNAME=M68K + RTL_ARCH=M68K +@@ -8411,7 +8417,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]) +@@ -12830,7 +12836,7 @@ AC_SUBST(RHINO_JAR) + # platforms there. + supports_multilib= + case "$host_cpu" in +-x86_64 | powerpc64 | powerpc64le | s390x | aarch64 | mips64 | mips64el | loongarch64) ++x86_64 | powerpc64 | powerpc64le | s390x | aarch64 | mips64 | mips64el | loongarch64 | riscv64) + if test "$SAL_TYPES_SIZEOFLONG" = "8"; then + supports_multilib="yes" + fi +diff --git a/jvmfwk/inc/vendorbase.hxx b/jvmfwk/inc/vendorbase.hxx +index c0008c5..de4647b 100644 +--- a/jvmfwk/inc/vendorbase.hxx ++++ b/jvmfwk/inc/vendorbase.hxx +@@ -59,6 +59,8 @@ OpenJDK at least, but probably not true for Lemotes JDK */ + #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 +diff --git a/solenv/gbuild/platform/LINUX_RISCV64_GCC.mk b/solenv/gbuild/platform/LINUX_RISCV64_GCC.mk +new file mode 100644 +index 0000000..9e00710 +--- /dev/null ++++ b/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: +-- +2.37.2 + diff --git a/app-office/libreoffice/libreoffice-7.3.6.2.ebuild b/app-office/libreoffice/libreoffice-7.3.6.2.ebuild index 7237092..2582c1b 100644 --- a/app-office/libreoffice/libreoffice-7.3.6.2.ebuild +++ b/app-office/libreoffice/libreoffice-7.3.6.2.ebuild @@ -297,6 +297,9 @@ PATCHES=( # pending upstream "${FILESDIR}/${PN}-7.3.5.2-poppler-22.09.0.patch" + + # riscv64 port + "${FILESDIR}/${PN}-7.3.6.2-riscv64.patch" ) S="${WORKDIR}/${PN}-${MY_PV}" |