[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Porting libreoffice to riscv64 arch



Hi,
On Thu, May 12, 2022 at 08:28:26PM +0200, Rene Engelhard wrote:
Hi,

You should definitely get a failure at bridges I guess ;-):

You definitely have porting work before you. See e.g. https://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_aarch64 for arm64. You need to know the ABI and calling conventions.

Update here: I headless copyed mips64 in bridge source into riscv64
(fix calling conventions for riscv64 is not easy thing for me now).
It seems it was passed for riscv64 bridge "build check". But it stops
at pdfium here:

```
In file included from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fpdfapi/font/cpdf_font.h:16,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fpdfapi/page/cpdf_docpagedata.h:14,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/fpdfsdk/fpdf_dataavail.cpp:12:
/<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/build/build_config.h:127:2: error: #error Please add support for your architecture in build/build_config.h
 127 | #error Please add support for your architecture in build/build_config.h
     |  ^~~~~
test -f /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.cpp || (echo "Missing generated source file /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.cpp" && false)
[build CXX] workdir/UnpackedTarball/pdfium/fpdfsdk/fpdf_progressive.cpp
In file included from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/third_party/base/check.h:10,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fxcrt/retain_ptr.h:15,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fxcrt/bytestring.h:20,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fxcrt/fx_string.h:14,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fpdfapi/parser/cpdf_object.h:15,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fpdfapi/parser/cpdf_dictionary.h:15,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/fpdfsdk/fpdf_ext.cpp:9:
/<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/build/build_config.h:127:2: error: #error Please add support for your architecture in build/build_config.h
 127 | #error Please add support for your architecture in build/build_config.h
     |  ^~~~~
S=/<<PKGBUILDDIR>> && I=$S/instdir && W=$S/workdir &&  mkdir -p $W/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/ $W/Dep/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/ && cd /<<PKGBUILDDIR>> &&      riscv64-linux-gnu-g++ -DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_DEPRECATED -DCPPU_ENV=gcc3 -DLINUX -DNDEBUG -DOSL_DEBUG_LEVEL=0 -DRISCV64 -DUNIX -DUNX -D_FORTIFY_SOURCE=2 -D_PTHREADS -D_REENTRANT -Wdate-time -Wdate-time -D_FORTIFY_SOURCE=2 -DFPDF_IMPLEMENTATION -DUSE_SYSTEM_LCMS2 -DUSE_SYSTEM_LIBJPEG -DUSE_SYSTEM_ZLIB -DUSE_SYSTEM_ICUUC -DMEMORY_TOOL_REPLACES_ALLOCATOR -DUNICODE -DWIN32_LEAN_AND_MEAN -DCOMPONENT_BUILD  -DUSE_SYSTEM_LIBOPENJPEG2  -DSYSTEM_ZLIB -DZLIB_CONST  -DDEFINE_PS_TABLES_DATA  -flto=16 -fuse-linker-plugin -O2 -fvisibility=hidden    -Wall -Wno-missing-braces -Wnon-virtual-dtor -Wendif-labels -Wextra -Wundef -Wunreachable-code -Wshadow -Wunused-macros  -finput-charset=UTF-8 -fmessage-length=0 -fno-common -pipe   -Wdeprecated-copy-dtor -Wduplicated-cond -Wlogical-op -Wshift-overflow=2 -Wunused-const-variable=1 -Wno-cast-function-type -fvisibility-inlines-hidden -fPIC -Wshadow -Woverloaded-virtual -std=c++17 -pthread  -g1 -g1 -O2 -ffile-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security  -DEXCEPTIONS_ON -fexceptions -fno-enforce-eh-specs  -w -DLIBO_INTERNAL_ONLY  -c $W/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.cpp -o $W/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.o -MMD -MT $W/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.o -MP -MF $W/Dep/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.d_ -I$W/UnpackedTarball/pdfium -I$W/UnpackedTarball/pdfium/third_party -I$W/UnpackedTarball/pdfium/third_party/agg23  -isystem /usr/include/openjpeg-2.4 -I$S/include  -I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux -I$S/config_host            -Wno-long-long     -isystem /usr/include/freetype2 -isystem /usr/include/libpng16   && mv $W/Dep/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.d_ $W/Dep/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.d
In file included from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/third_party/base/check.h:10,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fxcrt/retain_ptr.h:15,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fxcrt/bytestring.h:20,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fxcrt/fx_string.h:14,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fpdfapi/parser/cpdf_object.h:15,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fpdfapi/parser/cpdf_dictionary.h:15,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fpdfapi/page/cpdf_pageobjectholder.h:20,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/core/fpdfapi/page/cpdf_page.h:13,
                from /<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.cpp:20:
/<<PKGBUILDDIR>>/workdir/UnpackedTarball/pdfium/build/build_config.h:127:2: error: #error Please add support for your architecture in build/build_config.h
 127 | #error Please add support for your architecture in build/build_config.h
     |  ^~~~~
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/cpdfsdk_annothandlermgr.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/cpdfsdk_annot.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/cpdfsdk_annotiteration.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/cpdfsdk_baannot.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/cpdfsdk_baannothandler.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/fpdf_ext.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/cpdfsdk_widget.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/cpdfsdk_formfillenvironment.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/cpdfsdk_widgethandler.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/cpdfsdk_pageview.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/fpdf_flatten.o] Error 1
make[3]: *** [/<<PKGBUILDDIR>>/solenv/gbuild/LinkTarget.mk:400: /<<PKGBUILDDIR>>/workdir/GenCxxObject/UnpackedTarball/pdfium/fpdfsdk/fpdf_dataavail.o] Error 1

```
But I have added riscv64 arch here:

```
--- a/external/pdfium/configs/build_config.h
+++ b/external/pdfium/configs/build_config.h
@@ -121,6 +121,8 @@
#elif defined(__m68k__)
#define ARCH_CPU_M68K 1
#define ARCH_CPU_32_BITS 1
+#define ARCH_CPU_RISCV64 1
+#define ARCH_CPU_64_BITS 1
#else
#error Please add support for your architecture in build/build_config.h
#endif

```
and output of the `echo | gcc -E -dM -` is here: https://paste.debian.net/1241666/

It seems the build_config.h can not detect the cpu info.

If anyone has interesting to try it, please apply the patch and add
riscv64 support for d/rules.

BR,
Bo


(And no, unfortunately I can't help you in that, only to get it to apply and (maybe) build system issues)


Regards,


Rene

add support for riscv64 arch

--- a/configure.ac
+++ b/configure.ac
@@ -5112,6 +5112,12 @@
         RTL_ARCH=PowerPC_64_LE
         PLATFORMID=linux_powerpc64_le
         ;;
+    riscv64)
+        CPUNAME=RISCV64
+        PLATFORMID=linux_riscv64
+        RTL_ARCH=RISCV64
+        EPM_FLAGS="-a riscv64"
+        ;;
     sparc)
         CPUNAME=SPARC
         RTL_ARCH=SPARC
@@ -8413,7 +8419,7 @@
         JAVAINTERPRETER=`win_short_path_for_make "$JAVAINTERPRETER"`
     elif test "$cross_compiling" != "yes"; then
         case $CPUNAME in
-            AARCH64|AXP|X86_64|IA64|POWERPC64|S390X|SPARC64|GODSON64)
+            AARCH64|AXP|X86_64|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])
@@ -12875,7 +12881,7 @@
 # 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
--- /dev/null
+++ b/solenv/gbuild/platform/LINUX_RISCV64_GCC.mk
@@ -0,0 +1,14 @@
+# -*- 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/.
+#
+
+gb_COMPILEROPTFLAGS := -Os
+
+include $(GBUILDDIR)/platform/linux.mk
+
+# vim: set noet sw=4:
--- /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: */
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/call.s
@@ -0,0 +1,134 @@
+/*
+ * 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
+        .globl	privateSnippetExecutor
+.LFB0 = .
+        .cfi_startproc
+        .cfi_personality 0x80,DW.ref.__gxx_personality_v0
+        .cfi_lsda 0,.LLSDA0
+        .ent	privateSnippetExecutor
+        .type	privateSnippetExecutor, @function
+privateSnippetExecutor:
+        .set	noreorder
+        daddiu	$sp,$sp,-160
+        .cfi_def_cfa_offset 160
+        sd	$ra,152($sp)
+        .cfi_offset 31, -8
+.LEHB0 = .
+        // Save the float point registers
+        sdc1	$f12,80($sp)
+        sdc1	$f13,88($sp)
+        sdc1	$f14,96($sp)
+        sdc1	$f15,104($sp)
+        sdc1	$f16,112($sp)
+        sdc1	$f17,120($sp)
+        sdc1	$f18,128($sp)
+        sdc1	$f19,136($sp)
+        // Save the general purpose registers
+        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)
+        // Load arguments
+        // a0=index
+        move	$a0,$v0
+        // a1=offset
+        move	$a1,$v1
+        // a2=gpregptr
+        daddiu	$a2,$sp,16
+        // a3=fpregptr
+        daddiu	$a3,$sp,80
+        // a4=ovrflw
+        daddiu	$a4,$sp,160
+        // Call cpp_vtable_call
+        jalr	$t9
+        // a5=retregptr
+        move	$a5,$sp
+
+.LEHE0 = .
+        // Perform return value
+        li	$v1,10
+        beq	$v0,$v1,.Lfloat
+        li	$v1,11
+        beq	$v0,$v1,.Lfloat
+        ldc1	$f0,0($sp)
+        ldc1	$f2,8($sp)
+        ld	$v0,0($sp)
+        b	.Lfinish
+        ld	$v1,8($sp)
+.Lfloat:
+        ldc1	$f0,0($sp)
+        ldc1	$f2,8($sp)
+
+.Lfinish:
+        ld	$ra,152($sp)
+        .cfi_restore 31
+        jr	$ra
+        daddiu	$sp,$sp,160
+        .cfi_def_cfa_offset 0
+
+        .set	reorder
+        .end	privateSnippetExecutor
+        .cfi_endproc
+.LFE0:
+        .globl	__gxx_personality_v0
+        .section	.gcc_except_table,"aw",@progbits
+        .align	3
+.LLSDA0:
+        .byte	0xff
+        .byte	0x80
+        .uleb128 .LLSDATT0-.LLSDATTD0
+.LLSDATTD0:
+        .byte	0x1
+        .uleb128 .LLSDACSE0-.LLSDACSB0
+.LLSDACSB0:
+        .uleb128 .LEHB0-.LFB0
+        .uleb128 .LEHE0-.LEHB0
+        .uleb128 0
+        .uleb128 0
+.LLSDACSE0:
+        .byte	0x7f
+        .byte	0
+        .align	3
+        .8byte	DW.ref._ZTIi
+.LLSDATT0:
+        .byte	0x1
+        .byte	0
+        .text
+        .size	privateSnippetExecutor, .-privateSnippetExecutor
+        .hidden	DW.ref._ZTIi
+        .weak	DW.ref._ZTIi
+        .section	.data.DW.ref._ZTIi,"awG",@progbits,DW.ref._ZTIi,comdat
+        .align	3
+        .type	DW.ref._ZTIi, @object
+        .size	DW.ref._ZTIi, 8
+DW.ref._ZTIi:
+        .dword	_ZTIi
+        .hidden	DW.ref.__gxx_personality_v0
+        .weak	DW.ref.__gxx_personality_v0
+        .section	.data.DW.ref.__gxx_personality_v0,"awG",@progbits,DW.ref.__gxx_personality_v0,comdat
+        .align	3
+        .type	DW.ref.__gxx_personality_v0, @object
+        .size	DW.ref.__gxx_personality_v0, 8
+DW.ref.__gxx_personality_v0:
+        .dword	__gxx_personality_v0
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/cpp2uno.cxx
@@ -0,0 +1,704 @@
+/* -*- 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
+
+#ifndef ANDROID
+#include <sys/sysmips.h>
+#endif
+
+#ifdef ANDROID
+#include <unistd.h>
+#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(stderr, "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(stderr, "cpp2uno_call:complexreturn\n");
+#endif
+      }
+      else
+      {
+        pUnoReturn = pRegisterReturn; // direct way for simple types
+#ifdef BRDEBUG
+        fprintf(stderr, "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(stderr, "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(stderr, "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(stderr, "cpp2uno_call:fpr=%p\n", fpreg[nREG]);
+#endif
+              pCppArgs[nPos] = &(fpreg[nREG]);
+              pUnoArgs[nPos] = &(fpreg[nREG]);
+            } else {
+#ifdef BRDEBUG
+              fprintf(stderr, "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(stderr, "cpp2uno_call:gpr=%p\n", gpreg[nREG]);
+#endif
+              pCppArgs[nPos] = &(gpreg[nREG]);
+              pUnoArgs[nPos] = &(gpreg[nREG]);
+            } else {
+#ifdef BRDEBUG
+              fprintf(stderr, "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(stderr,"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(stderr, "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(stderr, "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(stderr, "cpp2uno_call:direct,pUnoArgs[%d]=%p\n", nPos, pUnoArgs[nPos]);
+#endif
+          // no longer needed
+          TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+        }
+      }
+    }
+#ifdef BRDEBUG
+    fprintf(stderr, "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(stderr, "cpp2uno_call2,after dispatch\n");
+#endif
+
+    // in case an exception occurred...
+    if (pUnoExc)
+    {
+      // 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(stderr, "in cpp_vtable_call nFunctionIndex is %d\n", nFunctionIndex);
+    fprintf(stderr, "in cpp_vtable_call nVtableOffset is %d\n", nVtableOffset);
+    fprintf(stderr, "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(stderr, "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(stderr, "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(stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
+#endif
+    typelib_TypeClass eRet;
+    switch (aMemberDescr.get()->eTypeClass)
+    {
+      case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+        {
+#ifdef BRDEBUG
+    fprintf(stderr, "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(stderr, "cpp_vtable_call interface method\n");
+#endif
+          // is METHOD
+          switch (nFunctionIndex)
+          {
+            case 1: // acquire()
+#ifdef BRDEBUG
+    fprintf(stderr, "cpp_vtable_call method acquire\n");
+#endif
+              pCppI->acquireProxy(); // non virtual call!
+              eRet = typelib_TypeClass_VOID;
+              break;
+            case 2: // release()
+#ifdef BRDEBUG
+    fprintf(stderr, "cpp_vtable_call method release\n");
+#endif
+              pCppI->releaseProxy(); // non virtual call!
+              eRet = typelib_TypeClass_VOID;
+              break;
+            case 0: // queryInterface() opt
+              {
+#ifdef BRDEBUG
+    fprintf(stderr, "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(stderr, "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(stderr, "cpp_vtable_call no member\n");
+#endif
+          throw RuntimeException( "no member description found!", (XInterface *)pThis );
+        }
+    }
+
+    return eRet;
+  }
+
+  extern "C" void privateSnippetExecutor( ... );
+
+  int const codeSnippetSize = 0x44;
+
+  unsigned char *  codeSnippet( unsigned char * code,
+      sal_Int32 functionIndex, sal_Int32 vtableOffset,
+      bool bHasHiddenParam )
+  {
+#ifdef BRDEBUG
+     fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex);
+     fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset);
+     fflush(stderr);
+#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 */
+    /*
+       # index
+        0:   3c020000        lui     v0,0x0
+        4:   34420000        ori     v0,v0,0x0
+       # privateSnippetExecutor
+        8:   3c0c0000        lui     t0,0x0
+        c:   358c0000        ori     t0,t0,0x0
+       10:   000c6438        dsll    t0,t0,0x10
+       14:   358c0000        ori     t0,t0,0x0
+       18:   000c6438        dsll    t0,t0,0x10
+       1c:   358c0000        ori     t0,t0,0x0
+       # cpp_vtable_call
+       20:   3c190000        lui     t9,0x0
+       24:   37390000        ori     t9,t9,0x0
+       28:   0019cc38        dsll    t9,t9,0x10
+       2c:   37390000        ori     t9,t9,0x0
+       30:   0019cc38        dsll    t9,t9,0x10
+       34:   37390000        ori     t9,t9,0x0
+       # offset
+       38:   3c030000        lui     v1,0x0
+       3c:   01800008        jr      t0
+       40:   34630000        ori     v1,v1,0x0
+     */
+
+    * p++ = 0x3c020000 | ((functionIndex>>16) & 0x0000ffff);
+    * p++ = 0x34420000 | (functionIndex & 0x0000ffff);
+    * p++ = 0x3c0c0000 | ((((unsigned long)privateSnippetExecutor) >> 48) & 0x0000ffff);
+    * p++ = 0x358c0000 | ((((unsigned long)privateSnippetExecutor) >> 32) & 0x0000ffff);
+    * p++ = 0x000c6438;
+    * p++ = 0x358c0000 | ((((unsigned long)privateSnippetExecutor) >> 16) & 0x0000ffff);
+    * p++ = 0x000c6438;
+    * p++ = 0x358c0000 | (((unsigned long)privateSnippetExecutor) & 0x0000ffff);
+    * p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 48) & 0x0000ffff);
+    * p++ = 0x37390000 | ((((unsigned long)cpp_vtable_call) >> 32) & 0x0000ffff);
+    * p++ = 0x0019cc38;
+    * p++ = 0x37390000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff);
+    * p++ = 0x0019cc38;
+    * p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000ffff);
+    * p++ = 0x3c030000 | ((vtableOffset>>16) & 0x0000ffff);
+    * p++ = 0x01800008;
+    * p++ = 0x34630000 | (vtableOffset & 0x0000ffff);
+    return (code + codeSnippetSize);
+
+  }
+
+}
+
+
+void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const *bptr, unsigned char const *eptr)
+{
+#ifndef ANDROID
+  (void) bptr;
+  (void) eptr;
+  sysmips(FLUSH_CACHE, 0, 0, 0);
+#else
+  cacheflush((long) bptr, (long) eptr, 0);
+#endif
+}
+
+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(stderr, "in addLocalFunctions functionOffset is %d\n", functionOffset);
+   fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n", vtableOffset);
+   fprintf(stderr, "nMembers=%d\n", type->nMembers);
+   fflush(stderr);
+#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: */
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/except.cxx
@@ -0,0 +1,290 @@
+/* -*- 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;
+
+
+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 )
+{
+    __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 );
+    }
+}
+
+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: */
--- /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: */
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_riscv64/uno2cpp.cxx
@@ -0,0 +1,592 @@
+/* -*- 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(stderr, "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 mips64 \n\t"
+        // Fill the general purpose registers
+        "ld $4, 0(%[gpr]) \n\t"
+        "ld $5, 8(%[gpr]) \n\t"
+        "ld $6, 16(%[gpr]) \n\t"
+        "ld $7, 24(%[gpr]) \n\t"
+        "ld $8, 32(%[gpr]) \n\t"
+        "ld $9, 40(%[gpr]) \n\t"
+        "ld $10, 48(%[gpr]) \n\t"
+        "ld $11, 56(%[gpr]) \n\t"
+        // Fill the floating pointer registers
+        "ldc1 $f12, 0(%[fpr]) \n\t"
+        "ldc1 $f13, 8(%[fpr]) \n\t"
+        "ldc1 $f14, 16(%[fpr]) \n\t"
+        "ldc1 $f15, 24(%[fpr]) \n\t"
+        "ldc1 $f16, 32(%[fpr]) \n\t"
+        "ldc1 $f17, 40(%[fpr]) \n\t"
+        "ldc1 $f18, 48(%[fpr]) \n\t"
+        "ldc1 $f19, 56(%[fpr]) \n\t"
+        // Perform the call
+        "jalr %[mfunc] \n\t"
+        // Fill the return values
+        "move %[gret1], $2 \n\t"
+        "move %[gret2], $3 \n\t"
+        "mov.d %[fret1], $f0 \n\t"
+        "mov.d %[fret2], $f2 \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]"c"(mfunc),
+         [stack]"m"(pCallStack) // dummy input to prevent the compiler from optimizing the alloca out
+        :"$2", "$3", "$4", "$5", "$6", "$7", "$8",
+         "$9", "$10", "$11", "$31",
+         "$f0", "$f2", "$f12", "$f13", "$f14", "$f15",
+         "$f16", "$f17", "$f18", "$f19", "memory"
+    );
+
+    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(stderr,"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(stderr, "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:
+          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(stderr, "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: */
--- a/bridges/Library_cpp_uno.mk
+++ b/bridges/Library_cpp_uno.mk
@@ -131,6 +131,15 @@
 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),S390)

 ifneq ($(filter DRAGONFLY FREEBSD LINUX NETBSD OPENBSD,$(OS)),)
--- a/external/pdfium/configs/build_config.h
+++ b/external/pdfium/configs/build_config.h
@@ -121,6 +121,8 @@
 #elif defined(__m68k__)
 #define ARCH_CPU_M68K 1
 #define ARCH_CPU_32_BITS 1
+#define ARCH_CPU_RISCV64 1
+#define ARCH_CPU_64_BITS 1
 #else
 #error Please add support for your architecture in build/build_config.h
 #endif

Attachment: signature.asc
Description: PGP signature


Reply to: