summaryrefslogtreecommitdiffstats
path: root/bridges/source/cpp_uno/gcc3_ios
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /bridges/source/cpp_uno/gcc3_ios
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'bridges/source/cpp_uno/gcc3_ios')
-rw-r--r--bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx540
-rw-r--r--bridges/source/cpp_uno/gcc3_ios/except.cxx406
-rw-r--r--bridges/source/cpp_uno/gcc3_ios/ios64_helper.s233
-rw-r--r--bridges/source/cpp_uno/gcc3_ios/rtti.h410
-rw-r--r--bridges/source/cpp_uno/gcc3_ios/share.hxx57
-rw-r--r--bridges/source/cpp_uno/gcc3_ios/uno2cpp.cxx572
-rw-r--r--bridges/source/cpp_uno/gcc3_ios/unwind-cxx.h283
7 files changed, 2501 insertions, 0 deletions
diff --git a/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
new file mode 100644
index 000000000..21de11b5e
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx
@@ -0,0 +1,540 @@
+/* -*- 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/RuntimeException.hpp>
+#include <sal/log.hxx>
+#include <uno/data.h>
+#include <typelib/typedescription.hxx>
+#include "bridge.hxx"
+#include "cppinterfaceproxy.hxx"
+#include "types.hxx"
+#include "vtablefactory.hxx"
+#include "share.hxx"
+
+
+
+extern "C" int codeSnippets[];
+const int nFunIndexes = 8;
+const int nVtableOffsets = 4;
+
+
+
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+ static typelib_TypeClass cpp2uno_call(
+ bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
+ const typelib_TypeDescription * pMemberTypeDescr,
+ typelib_TypeDescriptionReference * pReturnTypeRef,
+ sal_Int32 nParams,
+ typelib_MethodParameter * pParams,
+ void ** pCallStack,
+ sal_Int64 * pRegisterReturn /* space for register return */ )
+ {
+ // pCallStack: x8, lr, d0..d7, x0..x7, rest of params originally on stack
+ char *pTopStack = (char *)pCallStack;
+ char *pFloatRegs = pTopStack + 2;
+ char *pGPRegs = pTopStack + (2+8)*8;
+ char *pStackedArgs = pTopStack + (2+8+8)*8;
+
+ int nGPR = 0;
+ int nFPR = 0;
+
+ // return
+ typelib_TypeDescription * pReturnTypeDescr = 0;
+ if (pReturnTypeRef)
+ TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
+
+ void * pUnoReturn = 0;
+ // complex return ptr: if != 0 && != pUnoReturn, reconversion need
+ void * pCppReturn = 0;
+
+ if (pReturnTypeDescr)
+ {
+ if (!arm::return_in_x8(pReturnTypeRef))
+ pUnoReturn = pRegisterReturn; // direct way for simple types
+ else // complex return via x8
+ {
+ pCppReturn = pCallStack[0];
+
+ pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
+ pReturnTypeDescr )
+ ? alloca( pReturnTypeDescr->nSize )
+ : pCppReturn); // direct way
+ }
+ }
+
+ // Skip 'this'
+ pGPRegs += 8;
+ nGPR++;
+
+ // Parameters
+ void ** pUnoArgs = (void **)alloca( sizeof(void *) * nParams );
+ void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams );
+
+ // Indices of values this have to be converted (interface conversion
+ // cpp<=>uno)
+ int * pTempIndices = (sal_Int32 *)alloca( sizeof(int) * nParams);
+
+ // Type descriptions for reconversions
+ typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(typelib_TypeDescription *) * nParams);
+
+ int nTempIndices = 0;
+
+ for ( int 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 ))
+ {
+ if (nFPR < 8 && (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT ||
+ pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE))
+ {
+ pCppArgs[nPos] = pUnoArgs[nPos] = pFloatRegs;
+ pFloatRegs += 8;
+ nFPR++;
+ }
+ else if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT)
+ {
+ if ((pStackedArgs - pTopStack) % 4)
+ pStackedArgs += 4 - ((pStackedArgs - pTopStack) % 4);
+ pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
+ pStackedArgs += 4;
+ }
+ else if (pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE)
+ {
+ if ((pStackedArgs - pTopStack) % 8)
+ pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8);
+ pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
+ pStackedArgs += 8;
+ }
+ else if (nGPR < 8)
+ {
+ pCppArgs[nPos] = pUnoArgs[nPos] = pGPRegs;
+ pGPRegs += 8;
+ nGPR++;
+ }
+ else
+ switch (pParamTypeDescr->eTypeClass)
+ {
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if ((pStackedArgs - pTopStack) % 8)
+ pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8);
+ pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
+ pStackedArgs += 8;
+ break;
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ if ((pStackedArgs - pTopStack) % 4)
+ pStackedArgs += 4 - ((pStackedArgs - pTopStack) % 4);
+ pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
+ pStackedArgs += 4;
+ break;
+ case typelib_TypeClass_CHAR:
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ if ((pStackedArgs - pTopStack) % 2)
+ pStackedArgs += 1;
+ pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
+ pStackedArgs += 2;
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs;
+ pStackedArgs += 1;
+ break;
+ default:
+ assert(!"should not happen");
+ break;
+ }
+ // no longer needed
+ TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+ }
+ else // ptr to complex value | ref
+ {
+ if (nGPR < 8)
+ {
+ pCppArgs[nPos] = *(void **)pGPRegs;
+ pGPRegs += 8;
+ }
+ else
+ {
+ if ((pStackedArgs - pTopStack) % 8)
+ pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8);
+ pCppArgs[nPos] = pStackedArgs;
+ pStackedArgs += 8;
+ }
+
+ 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 ),
+ pCppArgs[nPos], pParamTypeDescr,
+ pThis->getBridge()->getCpp2Uno() );
+ pTempIndices[nTempIndices] = nPos; // has to be reconverted
+ // will be released at reconversion
+ ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+ }
+ else // direct way
+ {
+ pUnoArgs[nPos] = pCppArgs[nPos];
+ // no longer needed
+ TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+ }
+ }
+ }
+
+ // 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 );
+
+ // in case an exception occurred...
+ if (pUnoExc)
+ {
+ // destruct temporary in/inout params
+ for ( ; nTempIndices--; )
+ {
+ int 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--; )
+ {
+ int 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 );
+ }
+ *(void **)pRegisterReturn = pCppReturn;
+ }
+ if (pReturnTypeDescr)
+ {
+ typelib_TypeClass eRet =
+ (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
+ TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+ return eRet;
+ }
+ else
+ return typelib_TypeClass_VOID;
+ }
+ }
+
+
+ static void cpp_mediate(sal_Int32 nFunctionIndex,
+ sal_Int32 nVtableOffset,
+ void ** pCallStack)
+ {
+ sal_Int64 nRegReturn;
+ sal_Int64 *pRegisterReturn = &nRegReturn;
+
+ // pCallStack: x8, lr, d0..d7, x0..x7, rest of params originally on stack
+ // _this_ ptr is patched cppu_XInterfaceProxy object
+ void *pThis = pCallStack[2 + 8];
+
+ pThis = static_cast< char * >(pThis) - nVtableOffset;
+ bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
+ bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
+ pThis);
+
+ typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
+
+ // determine called method
+ assert( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex );
+
+ if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
+ {
+ throw RuntimeException( "illegal vtable index!", (XInterface *)pCppI );
+ }
+
+ sal_Int32 nMemberPos =
+ pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
+ assert( nMemberPos < pTypeDescr->nAllMembers );
+
+ TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
+
+ typelib_TypeClass eRet;
+ switch (aMemberDescr.get()->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] ==
+ nFunctionIndex)
+ {
+ // is GET method
+ eRet = cpp2uno_call(
+ pCppI, aMemberDescr.get(),
+ ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
+ 0, 0, // no params
+ pCallStack, pRegisterReturn );
+ }
+ else
+ {
+ // is SET method
+ typelib_MethodParameter aParam;
+ aParam.pTypeRef =
+ ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
+ aParam.bIn = sal_True;
+ aParam.bOut = sal_False;
+
+ eRet = cpp2uno_call(
+ pCppI, aMemberDescr.get(),
+ 0, // indicates void return
+ 1, &aParam,
+ pCallStack, pRegisterReturn );
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ // is METHOD
+ switch (nFunctionIndex)
+ {
+ case 1: // acquire()
+ pCppI->acquireProxy(); // non virtual call!
+ eRet = typelib_TypeClass_VOID;
+ break;
+ case 2: // release()
+ pCppI->releaseProxy(); // non virtual call!
+ eRet = typelib_TypeClass_VOID;
+ break;
+ case 0: // queryInterface() opt
+ {
+ typelib_TypeDescription * pTD = 0;
+ TYPELIB_DANGER_GET(&pTD,
+ reinterpret_cast<Type *>(pCallStack[2])->getTypeLibType());
+ if (pTD)
+ {
+ XInterface * pInterface = 0;
+ (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
+ pCppI->getBridge()->getCppEnv(),
+ (void **)&pInterface, pCppI->getOid().pData,
+ (typelib_InterfaceTypeDescription *)pTD );
+
+ if (pInterface)
+ {
+ ::uno_any_construct(
+ reinterpret_cast< uno_Any * >( pCallStack[0] ),
+ &pInterface, pTD, cpp_acquire );
+ pInterface->release();
+ TYPELIB_DANGER_RELEASE( pTD );
+ *(void **)pRegisterReturn = pCallStack[0];
+ eRet = typelib_TypeClass_ANY;
+ break;
+ }
+ TYPELIB_DANGER_RELEASE( pTD );
+ }
+ } // else perform queryInterface()
+ [[fallthrough]];
+ default:
+ eRet = cpp2uno_call(
+ pCppI, aMemberDescr.get(),
+ ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
+ ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
+ ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
+ pCallStack, pRegisterReturn );
+ }
+ break;
+ }
+ default:
+ {
+ throw RuntimeException( "no member description found!", (XInterface *)pCppI );
+ }
+ }
+
+ (void)eRet;
+ return;
+ }
+}
+
+/**
+ * is called on incoming vtable calls
+ * (called by asm snippets)
+ */
+
+extern "C" void cpp_vtable_call( sal_Int32 func, sal_Int32 offset,
+ void **pStack )
+{
+ cpp_mediate(func, offset, pStack);
+}
+
+namespace
+{
+ unsigned char *codeSnippet(const typelib_InterfaceTypeDescription *type,
+ const typelib_TypeDescription *member,
+ sal_Int32 functionIndex,
+ sal_Int32 vtableOffset)
+ {
+ // For now temporarily assert when we get here. The intent is
+ // that we won't need the code snippets at all on iOS.
+ assert(false);
+
+ assert(functionIndex < nFunIndexes);
+ if (!(functionIndex < nFunIndexes))
+ return NULL;
+
+ assert(vtableOffset < nVtableOffsets);
+ if (!(vtableOffset < nVtableOffsets))
+ return NULL;
+
+ // The codeSnippets table is indexed by functionIndex and vtableOffset
+
+ int index = functionIndex*nVtableOffsets + vtableOffset;
+ unsigned char *result = ((unsigned char *) &codeSnippets) + codeSnippets[index];
+
+ SAL_INFO( "bridges", "codeSnippet(" << OUString(type->aBase.pTypeName) << "::" << OUString(member->pTypeName) << "): [" << functionIndex << "," << vtableOffset << "]=" << (void *) result << " (" << std::hex << ((int*)result)[0] << "," << ((int*)result)[1] << "," << ((int*)result)[2] << "," << ((int*)result)[3] << ")");
+
+ return result;
+ }
+}
+
+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);
+}
+
+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;
+ slots[-1].fn = 0;
+ return slots + slotCount;
+}
+
+unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
+ Slot ** slots,
+ unsigned char * code,
+ typelib_InterfaceTypeDescription const * type,
+ sal_Int32 functionOffset,
+ sal_Int32 functionCount,
+ sal_Int32 vtableOffset)
+{
+ (*slots) -= functionCount;
+ Slot * s = *slots;
+ 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:
+ {
+ typelib_InterfaceAttributeTypeDescription *pAttrTD =
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member );
+
+ // Getter:
+ (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset );
+
+ // Setter:
+ if (!pAttrTD->bReadOnly)
+ {
+ (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset );
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset );
+ break;
+ }
+ default:
+ assert(false);
+ break;
+ }
+ TYPELIB_DANGER_RELEASE(member);
+ }
+ return code;
+}
+
+
+
+void bridges::cpp_uno::shared::VtableFactory::flushCode(
+ unsigned char const *, unsigned char const *)
+{
+ // No dynamic code generation so nothing to flush
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_ios/except.cxx b/bridges/source/cpp_uno/gcc3_ios/except.cxx
new file mode 100644
index 000000000..d5c49859d
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios/except.cxx
@@ -0,0 +1,406 @@
+/* -*- 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 <cassert>
+#include <new>
+#include <stdio.h>
+#include <string.h>
+#include <typeinfo>
+
+#include <cxxabi.h>
+#include <dlfcn.h>
+
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/genfunc.hxx"
+#include <sal/log.hxx>
+#include "osl/mutex.hxx"
+#include "rtl/strbuf.hxx"
+#include "rtl/ustrbuf.hxx"
+#include "typelib/typedescription.h"
+#include "uno/any2.h"
+#include <unordered_map>
+#include "share.hxx"
+
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+
+namespace CPPU_CURRENT_NAMESPACE {
+
+namespace {
+
+struct Fake_type_info {
+ virtual ~Fake_type_info() = delete;
+ char const * name;
+};
+
+struct Fake_class_type_info: Fake_type_info {
+ virtual ~Fake_class_type_info() override = delete;
+};
+
+struct Fake_si_class_type_info: Fake_class_type_info {
+ virtual ~Fake_si_class_type_info() override = delete;
+ void const * base;
+};
+
+struct Base {};
+struct Derived: Base {};
+
+std::type_info * createFake_class_type_info(char const * name) {
+ char * buf = new char[sizeof (Fake_class_type_info)];
+
+ *reinterpret_cast<void **>(buf) = *reinterpret_cast<void * const *>(
+ &typeid(Base));
+ // copy __cxxabiv1::__class_type_info vtable into place
+ Fake_class_type_info * fake = reinterpret_cast<Fake_class_type_info *>(buf);
+ fake->name = name;
+ return reinterpret_cast<std::type_info *>(
+ static_cast<Fake_type_info *>(fake));
+}
+
+std::type_info * createFake_si_class_type_info(
+ char const * name, std::type_info const * base)
+{
+ char * buf = new char[sizeof (Fake_si_class_type_info)];
+
+ *reinterpret_cast<void **>(buf) = *reinterpret_cast<void * const *>(
+ &typeid(Derived));
+ // copy __cxxabiv1::__si_class_type_info vtable into place
+ Fake_si_class_type_info * fake
+ = reinterpret_cast<Fake_si_class_type_info *>(buf);
+ fake->name = name;
+ fake->base = base;
+ return reinterpret_cast<std::type_info *>(
+ static_cast<Fake_type_info *>(fake));
+}
+
+}
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+void dummy_can_throw_anything( char const * )
+{
+}
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+static OUString toUNOname( char const * p )
+{
+#if OSL_DEBUG_LEVEL > 1
+ 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 OSL_DEBUG_LEVEL > 1
+ 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, std::type_info *, OUStringHash > t_rtti_map;
+
+ Mutex m_mutex;
+ t_rtti_map m_rttis;
+ t_rtti_map m_generatedRttis;
+
+ void * m_hApp;
+
+public:
+ RTTI();
+ ~RTTI();
+
+ std::type_info * getRTTI( typelib_CompoundTypeDescription * );
+};
+
+RTTI::RTTI()
+ : m_hApp( dlopen( nullptr, RTLD_LAZY ) )
+{
+}
+
+RTTI::~RTTI()
+{
+ dlclose( m_hApp );
+}
+
+
+std::type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr )
+{
+ std::type_info * rtti;
+
+ OUString const & unoName = OUString::unacquired(&pTypeDescr->aBase.pTypeName);
+
+ MutexGuard guard( m_mutex );
+ t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
+ if (iFind == 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 = static_cast<std::type_info *>(dlsym( m_hApp, symName.getStr() ));
+
+ if (rtti)
+ {
+ std::pair< t_rtti_map::iterator, bool > insertion(
+ m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
+ SAL_WARN_IF( !insertion.second,
+ "bridges",
+ "inserting new rtti failed" );
+ }
+ else
+ {
+ // try to lookup the symbol in the generated rtti map
+ t_rtti_map::const_iterator iFind2( m_generatedRttis.find( unoName ) );
+ if (iFind2 == m_generatedRttis.end())
+ {
+ // we must generate it !
+ // symbol and rtti-name is nearly identical,
+ // the symbol is prefixed with _ZTI
+ char * rttiName = strdup(symName.getStr() + 4);
+ if (rttiName == nullptr) {
+ throw std::bad_alloc();
+ }
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr,"generated rtti for %s\n", rttiName );
+#endif
+ if (pTypeDescr->pBaseTypeDescription)
+ {
+ // ensure availability of base
+ std::type_info * base_rtti = getRTTI(
+ pTypeDescr->pBaseTypeDescription );
+ rtti = createFake_si_class_type_info(rttiName, base_rtti);
+ }
+ else
+ {
+ rtti = createFake_class_type_info(rttiName);
+ }
+
+ std::pair< t_rtti_map::iterator, bool > insertion(
+ m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
+ SAL_WARN_IF( !insertion.second,
+ "bridges",
+ "inserting new generated rtti failed" );
+ }
+ else // taking already generated rtti
+ {
+ rtti = iFind2->second;
+ }
+ }
+ }
+ else
+ {
+ rtti = iFind->second;
+ }
+
+ return rtti;
+}
+
+
+static void deleteException( void * pExc )
+{
+ __cxa_exception const * header = static_cast<__cxa_exception const *>(pExc) - 1;
+ // The libcxxabi commit
+ // <http://llvm.org/viewvc/llvm-project?view=revision&revision=303175>
+ // "[libcxxabi] Align unwindHeader on a double-word boundary" towards
+ // LLVM 5.0 changed the size of __cxa_exception by adding
+ //
+ // __attribute__((aligned))
+ //
+ // to the final member unwindHeader, on x86-64 effectively adding a hole of
+ // size 8 in front of that member (changing its offset from 88 to 96,
+ // sizeof(__cxa_exception) from 120 to 128, and alignof(__cxa_exception)
+ // from 8 to 16); a hack to dynamically determine whether we run against a
+ // LLVM 5 libcxxabi is to look at the exceptionDestructor member, which must
+ // point to this function (the use of __cxa_exception in fillUnoException is
+ // unaffected, as it only accesses members towards the start of the struct,
+ // through a pointer known to actually point at the start). The libcxxabi commit
+ // <https://github.com/llvm/llvm-project/commit/9ef1daa46edb80c47d0486148c0afc4e0d83ddcf>
+ // "Insert padding before the __cxa_exception header to ensure the thrown" in LLVM 6
+ // removes the need for this hack, so it can be removed again once we can be sure that we only
+ // run against libcxxabi from LLVM >= 6:
+ if (header->exceptionDestructor != &deleteException) {
+ header = reinterpret_cast<__cxa_exception const *>(
+ reinterpret_cast<char const *>(header) - 8);
+ assert(header->exceptionDestructor == &deleteException);
+ }
+ typelib_TypeDescription * pTD = nullptr;
+ 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 OSL_DEBUG_LEVEL > 1
+ OString cstr(
+ OUStringToOString(
+ OUString::unacquired( &pUnoExc->pType->pTypeName ),
+ RTL_TEXTENCODING_ASCII_US ) );
+ fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() );
+#endif
+ void * pCppExc;
+ std::type_info * rtti;
+
+ {
+ // construct cpp exception object
+ typelib_TypeDescription * pTypeDescr = nullptr;
+ TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
+ assert(pTypeDescr);
+ if (! pTypeDescr)
+ {
+ throw RuntimeException(
+ "cannot get typedescription for type " +
+ OUString::unacquired( &pUnoExc->pType->pTypeName ) );
+ }
+
+ pCppExc = __cxxabiv1::__cxa_allocate_exception( pTypeDescr->nSize );
+ ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
+
+ // destruct uno exception
+ ::uno_any_destruct( pUnoExc, nullptr );
+ // avoiding locked counts
+ static RTTI rtti_data;
+ rtti = rtti_data.getRTTI(reinterpret_cast<typelib_CompoundTypeDescription*>(pTypeDescr));
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ assert(rtti && "### no rtti for throwing exception!");
+ if (! rtti)
+ {
+ throw RuntimeException(
+ "no rtti for type " +
+ OUString::unacquired( &pUnoExc->pType->pTypeName ) );
+ }
+ }
+
+ // void __cxa_throw(void* thrown_exception,
+ // struct std::type_info * tinfo,
+ // void (*dest)(void*));
+ __cxxabiv1::__cxa_throw( pCppExc, rtti, deleteException );
+}
+
+void fillUnoException(uno_Any * pUnoExc, uno_Mapping * pCpp2Uno)
+{
+ __cxa_exception * header = __cxxabiv1::__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;
+ }
+
+ // Very bad HACK to find out whether we run against a libcxxabi that has a new
+ // __cxa_exception::reserved member at the start, introduced with LLVM 10
+ // <https://github.com/llvm/llvm-project/commit/674ec1eb16678b8addc02a4b0534ab383d22fa77>
+ // "[libcxxabi] Insert padding in __cxa_exception struct for compatibility". The layout of the
+ // start of __cxa_exception is
+ //
+ // [8 byte void *reserve]
+ // 8 byte size_t referenceCount
+ //
+ // where the (bad, hacky) assumption is that reserve (if present) is null
+ // (__cxa_allocate_exception in at least LLVM 11 zero-fills the object, and nothing actively
+ // sets reserve) while referenceCount is non-null (__cxa_throw sets it to 1, and
+ // __cxa_decrement_exception_refcount destroys the exception as soon as it drops to 0; for a
+ // __cxa_dependent_exception, the referenceCount member is rather
+ //
+ // 8 byte void* primaryException
+ //
+ // but which also will always be set to a non-null value in __cxa_rethrow_primary_exception).
+ // As described in the definition of __cxa_exception
+ // (bridges/source/cpp_uno/gcc3_macosx_x86-64/share.hxx), this hack (together with the "#if 0"
+ // there) can be dropped once we can be sure that we only run against new libcxxabi that has the
+ // reserve member:
+ if (*reinterpret_cast<void **>(header) == nullptr) {
+ header = reinterpret_cast<__cxa_exception *>(reinterpret_cast<void **>(header) + 1);
+ }
+
+ std::type_info *exceptionType = __cxxabiv1::__cxa_current_exception_type();
+
+ typelib_TypeDescription * pExcTypeDescr = nullptr;
+ OUString unoName( toUNOname( exceptionType->name() ) );
+#if OSL_DEBUG_LEVEL > 1
+ 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 (nullptr == pExcTypeDescr)
+ {
+ RuntimeException aRE( "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_ios/ios64_helper.s b/bridges/source/cpp_uno/gcc3_ios/ios64_helper.s
new file mode 100644
index 000000000..12308f1a9
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios/ios64_helper.s
@@ -0,0 +1,233 @@
+// -*- Mode: Asm; tab-width: 4; tab-stop-list: (4 12 32); comment-column: 30; comment-start: "// "; indent-tabs-mode: nil -*-
+//
+// 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 .
+//
+ .section __TEXT,__text,regular,pure_instructions
+
+ .p2align 2
+codeSnippet_0_0:
+ mov x14, 0
+ mov x15, 0
+ b _privateSnippetExecutor
+codeSnippet_0_1:
+ mov x14, 0
+ mov x15, 1
+ b _privateSnippetExecutor
+codeSnippet_0_2:
+ mov x14, 0
+ mov x15, 2
+ b _privateSnippetExecutor
+codeSnippet_0_3:
+ mov x14, 0
+ mov x15, 3
+ b _privateSnippetExecutor
+codeSnippet_1_0:
+ mov x14, 1
+ mov x15, 0
+ b _privateSnippetExecutor
+ .long 0x000001
+ .long 0
+codeSnippet_1_1:
+ mov x14, 1
+ mov x15, 1
+ b _privateSnippetExecutor
+codeSnippet_1_2:
+ mov x14, 1
+ mov x15, 2
+ b _privateSnippetExecutor
+codeSnippet_1_3:
+ mov x14, 1
+ mov x15, 3
+ b _privateSnippetExecutor
+codeSnippet_2_0:
+ mov x14, 2
+ mov x15, 0
+ b _privateSnippetExecutor
+codeSnippet_2_1:
+ mov x14, 2
+ mov x15, 1
+ b _privateSnippetExecutor
+codeSnippet_2_2:
+ mov x14, 2
+ mov x15, 2
+ b _privateSnippetExecutor
+codeSnippet_2_3:
+ mov x14, 2
+ mov x15, 3
+ b _privateSnippetExecutor
+ .long 0x000002
+ .long 3
+codeSnippet_3_0:
+ mov x14, 3
+ mov x15, 0
+ b _privateSnippetExecutor
+codeSnippet_3_1:
+ mov x14, 3
+ mov x15, 1
+ b _privateSnippetExecutor
+codeSnippet_3_2:
+ mov x14, 3
+ mov x15, 2
+ b _privateSnippetExecutor
+codeSnippet_3_3:
+ mov x14, 3
+ mov x15, 3
+ b _privateSnippetExecutor
+codeSnippet_4_0:
+ mov x14, 4
+ mov x15, 0
+ b _privateSnippetExecutor
+codeSnippet_4_1:
+ mov x14, 4
+ mov x15, 1
+ b _privateSnippetExecutor
+codeSnippet_4_2:
+ mov x14, 4
+ mov x15, 2
+ b _privateSnippetExecutor
+codeSnippet_4_3:
+ mov x14, 4
+ mov x15, 3
+ b _privateSnippetExecutor
+codeSnippet_5_0:
+ mov x14, 5
+ mov x15, 0
+ b _privateSnippetExecutor
+codeSnippet_5_1:
+ mov x14, 5
+ mov x15, 1
+ b _privateSnippetExecutor
+codeSnippet_5_2:
+ mov x14, 5
+ mov x15, 2
+ b _privateSnippetExecutor
+codeSnippet_5_3:
+ mov x14, 5
+ mov x15, 3
+ b _privateSnippetExecutor
+codeSnippet_6_0:
+ mov x14, 6
+ mov x15, 0
+ b _privateSnippetExecutor
+codeSnippet_6_1:
+ mov x14, 6
+ mov x15, 1
+ b _privateSnippetExecutor
+codeSnippet_6_2:
+ mov x14, 6
+ mov x15, 2
+ b _privateSnippetExecutor
+codeSnippet_6_3:
+ mov x14, 6
+ mov x15, 3
+ b _privateSnippetExecutor
+codeSnippet_7_0:
+ mov x14, 7
+ mov x15, 0
+ b _privateSnippetExecutor
+codeSnippet_7_1:
+ mov x14, 7
+ mov x15, 1
+ b _privateSnippetExecutor
+codeSnippet_7_2:
+ mov x14, 7
+ mov x15, 2
+ b _privateSnippetExecutor
+codeSnippet_7_3:
+ mov x14, 7
+ mov x15, 3
+ b _privateSnippetExecutor
+
+ .globl _codeSnippets
+_codeSnippets:
+ .long codeSnippet_0_0 - _codeSnippets
+ .long codeSnippet_0_1 - _codeSnippets
+ .long codeSnippet_0_2 - _codeSnippets
+ .long codeSnippet_0_3 - _codeSnippets
+ .long codeSnippet_1_0 - _codeSnippets
+ .long codeSnippet_1_1 - _codeSnippets
+ .long codeSnippet_1_2 - _codeSnippets
+ .long codeSnippet_1_3 - _codeSnippets
+ .long codeSnippet_2_0 - _codeSnippets
+ .long codeSnippet_2_1 - _codeSnippets
+ .long codeSnippet_2_2 - _codeSnippets
+ .long codeSnippet_2_3 - _codeSnippets
+ .long codeSnippet_3_0 - _codeSnippets
+ .long codeSnippet_3_1 - _codeSnippets
+ .long codeSnippet_3_2 - _codeSnippets
+ .long codeSnippet_3_3 - _codeSnippets
+ .long codeSnippet_4_0 - _codeSnippets
+ .long codeSnippet_4_1 - _codeSnippets
+ .long codeSnippet_4_2 - _codeSnippets
+ .long codeSnippet_4_3 - _codeSnippets
+ .long codeSnippet_5_0 - _codeSnippets
+ .long codeSnippet_5_1 - _codeSnippets
+ .long codeSnippet_5_2 - _codeSnippets
+ .long codeSnippet_5_3 - _codeSnippets
+ .long codeSnippet_6_0 - _codeSnippets
+ .long codeSnippet_6_1 - _codeSnippets
+ .long codeSnippet_6_2 - _codeSnippets
+ .long codeSnippet_6_3 - _codeSnippets
+ .long codeSnippet_7_0 - _codeSnippets
+ .long codeSnippet_7_1 - _codeSnippets
+ .long codeSnippet_7_2 - _codeSnippets
+ .long codeSnippet_7_3 - _codeSnippets
+
+
+
+ .private_extern _privateSnippetExecutor
+ .globl _privateSnippetExecutor
+ .p2align 2
+_privateSnippetExecutor:
+ .cfi_startproc
+ .cfi_def_cfa w29, 16
+ .cfi_offset w30, -8
+ .cfi_offset w29, -16
+
+ // _privateSnippetExecutor is jumped to from codeSnippet_*
+
+ // push all GP, FP/SIMD registers to the stack
+ stp x6, x7, [sp, #-16]!
+ stp x4, x5, [sp, #-16]!
+ stp x2, x3, [sp, #-16]!
+ stp x0, x1, [sp, #-16]!
+ stp d6, d7, [sp, #-16]!
+ stp d4, d5, [sp, #-16]!
+ stp d2, d3, [sp, #-16]!
+ stp d0, d1, [sp, #-16]!
+
+ // push x8 (RC pointer) and lr to stack
+ stp x8, lr, [sp, #-16]!
+
+ // First argument (x15 set up in the codeSnippet instance)
+ // Second argument: The pointer to all the above
+ mov x0, x14
+ mov x1, x15
+ mov x2, sp
+ bl _cpp_vtable_call
+
+ // restore x8 (RC pointer) and lr (skip RC from cpp_vtable_call)
+ ldp x8, lr, [sp, #0]
+
+ // restore stack
+ add sp, sp, #144
+
+ // continue with throw/catch
+ ret lr
+ .cfi_endproc
+
+// vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/bridges/source/cpp_uno/gcc3_ios/rtti.h b/bridges/source/cpp_uno/gcc3_ios/rtti.h
new file mode 100644
index 000000000..fd8ef3715
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios/rtti.h
@@ -0,0 +1,410 @@
+// Copyright (C) 2000, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+// GCC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+//
+// Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>
+#ifndef __RTTI_H
+#define __RTTI_H
+
+#include <typeinfo>
+
+namespace __cxxabiv1
+{
+ // Type information for int, float etc.
+ class __fundamental_type_info : public std::type_info
+ {
+ public:
+ explicit
+ __fundamental_type_info(const char* __n) : std::type_info(__n) { }
+
+ virtual
+ ~__fundamental_type_info();
+ };
+
+ // Type information for array objects.
+ class __array_type_info : public std::type_info
+ {
+ public:
+ explicit
+ __array_type_info(const char* __n) : std::type_info(__n) { }
+
+ virtual
+ ~__array_type_info();
+ };
+
+ // Type information for functions (both member and non-member).
+ class __function_type_info : public std::type_info
+ {
+ public:
+ explicit
+ __function_type_info(const char* __n) : std::type_info(__n) { }
+
+ virtual
+ ~__function_type_info();
+
+ protected:
+ // Implementation defined member function.
+ virtual bool
+ __is_function_p() const;
+ };
+
+ // Type information for enumerations.
+ class __enum_type_info : public std::type_info
+ {
+ public:
+ explicit
+ __enum_type_info(const char* __n) : std::type_info(__n) { }
+
+ virtual
+ ~__enum_type_info();
+ };
+
+ // Common type information for simple pointers and pointers to member.
+ class __pbase_type_info : public std::type_info
+ {
+ public:
+ unsigned int __flags; // Qualification of the target object.
+ const std::type_info* __pointee; // Type of pointed to object.
+
+ explicit
+ __pbase_type_info(const char* __n, int __quals,
+ const std::type_info* __type)
+ : std::type_info(__n), __flags(__quals), __pointee(__type)
+ { }
+
+ virtual
+ ~__pbase_type_info();
+
+ // Implementation defined type.
+ enum __masks
+ {
+ __const_mask = 0x1,
+ __volatile_mask = 0x2,
+ __restrict_mask = 0x4,
+ __incomplete_mask = 0x8,
+ __incomplete_class_mask = 0x10
+ };
+
+ protected:
+ __pbase_type_info(const __pbase_type_info&);
+
+ __pbase_type_info&
+ operator=(const __pbase_type_info&);
+
+ // Implementation defined member functions.
+ virtual bool
+ __do_catch(const std::type_info* __thr_type, void** __thr_obj,
+ unsigned int __outer) const;
+
+ inline virtual bool
+ __pointer_catch(const __pbase_type_info* __thr_type, void** __thr_obj,
+ unsigned __outer) const;
+ };
+
+ // Type information for simple pointers.
+ class __pointer_type_info : public __pbase_type_info
+ {
+ public:
+ explicit
+ __pointer_type_info(const char* __n, int __quals,
+ const std::type_info* __type)
+ : __pbase_type_info (__n, __quals, __type) { }
+
+
+ virtual
+ ~__pointer_type_info();
+
+ protected:
+ // Implementation defined member functions.
+ virtual bool
+ __is_pointer_p() const;
+
+ virtual bool
+ __pointer_catch(const __pbase_type_info* __thr_type, void** __thr_obj,
+ unsigned __outer) const;
+ };
+
+ class __class_type_info;
+
+ // Type information for a pointer to member variable.
+ class __pointer_to_member_type_info : public __pbase_type_info
+ {
+ public:
+ __class_type_info* __context; // Class of the member.
+
+ explicit
+ __pointer_to_member_type_info(const char* __n, int __quals,
+ const std::type_info* __type,
+ __class_type_info* __klass)
+ : __pbase_type_info(__n, __quals, __type), __context(__klass) { }
+
+ virtual
+ ~__pointer_to_member_type_info();
+
+ protected:
+ __pointer_to_member_type_info(const __pointer_to_member_type_info&);
+
+ __pointer_to_member_type_info&
+ operator=(const __pointer_to_member_type_info&);
+
+ // Implementation defined member function.
+ virtual bool
+ __pointer_catch(const __pbase_type_info* __thr_type, void** __thr_obj,
+ unsigned __outer) const;
+ };
+
+ // Helper class for __vmi_class_type.
+ class __base_class_type_info
+ {
+ public:
+ const __class_type_info* __base_type; // Base class type.
+ long __offset_flags; // Offset and info.
+
+ enum __offset_flags_masks
+ {
+ __virtual_mask = 0x1,
+ __public_mask = 0x2,
+ __hwm_bit = 2,
+ __offset_shift = 8 // Bits to shift offset.
+ };
+
+ // Implementation defined member functions.
+ bool
+ __is_virtual_p() const
+ { return __offset_flags & __virtual_mask; }
+
+ bool
+ __is_public_p() const
+ { return __offset_flags & __public_mask; }
+
+ ptrdiff_t
+ __offset() const
+ {
+ // This shift, being of a signed type, is implementation
+ // defined. GCC implements such shifts as arithmetic, which is
+ // what we want.
+ return static_cast<ptrdiff_t>(__offset_flags) >> __offset_shift;
+ }
+ };
+
+ // Type information for a class.
+ class __class_type_info : public std::type_info
+ {
+ public:
+ explicit
+ __class_type_info (const char *__n) : type_info(__n) { }
+
+ virtual
+ ~__class_type_info ();
+
+ // Implementation defined types.
+ // The type sub_kind tells us about how a base object is contained
+ // within a derived object. We often do this lazily, hence the
+ // UNKNOWN value. At other times we may use NOT_CONTAINED to mean
+ // not publicly contained.
+ enum __sub_kind
+ {
+ // We have no idea.
+ __unknown = 0,
+
+ // Not contained within us (in some circumstances this might
+ // mean not contained publicly)
+ __not_contained,
+
+ // Contained ambiguously.
+ __contained_ambig,
+
+ // Via a virtual path.
+ __contained_virtual_mask = __base_class_type_info::__virtual_mask,
+
+ // Via a public path.
+ __contained_public_mask = __base_class_type_info::__public_mask,
+
+ // Contained within us.
+ __contained_mask = 1 << __base_class_type_info::__hwm_bit,
+
+ __contained_private = __contained_mask,
+ __contained_public = __contained_mask | __contained_public_mask
+ };
+
+ struct __upcast_result;
+ struct __dyncast_result;
+
+ protected:
+ // Implementation defined member functions.
+ virtual bool
+ __do_upcast(const __class_type_info* __dst_type, void**__obj_ptr) const;
+
+ virtual bool
+ __do_catch(const type_info* __thr_type, void** __thr_obj,
+ unsigned __outer) const;
+
+ public:
+ // Helper for upcast. See if DST is us, or one of our bases.
+ // Return false if not found, true if found.
+ virtual bool
+ __do_upcast(const __class_type_info* __dst, const void* __obj,
+ __upcast_result& __restrict __result) const;
+
+ // Indicate whether SRC_PTR of type SRC_TYPE is contained publicly
+ // within OBJ_PTR. OBJ_PTR points to a base object of our type,
+ // which is the destination type. SRC2DST indicates how SRC
+ // objects might be contained within this type. If SRC_PTR is one
+ // of our SRC_TYPE bases, indicate the virtuality. Returns
+ // not_contained for non containment or private containment.
+ inline __sub_kind
+ __find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr,
+ const __class_type_info* __src_type,
+ const void* __src_ptr) const;
+
+ // Helper for dynamic cast. ACCESS_PATH gives the access from the
+ // most derived object to this base. DST_TYPE indicates the
+ // desired type we want. OBJ_PTR points to a base of our type
+ // within the complete object. SRC_TYPE indicates the static type
+ // started from and SRC_PTR points to that base within the most
+ // derived object. Fill in RESULT with what we find. Return true
+ // if we have located an ambiguous match.
+ virtual bool
+ __do_dyncast(ptrdiff_t __src2dst, __sub_kind __access_path,
+ const __class_type_info* __dst_type, const void* __obj_ptr,
+ const __class_type_info* __src_type, const void* __src_ptr,
+ __dyncast_result& __result) const;
+
+ // Helper for find_public_subobj. SRC2DST indicates how SRC_TYPE
+ // bases are inherited by the type started from -- which is not
+ // necessarily the current type. The current type will be a base
+ // of the destination type. OBJ_PTR points to the current base.
+ virtual __sub_kind
+ __do_find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr,
+ const __class_type_info* __src_type,
+ const void* __src_ptr) const;
+ };
+
+ // Type information for a class with a single non-virtual base.
+ class __si_class_type_info : public __class_type_info
+ {
+ public:
+ const __class_type_info* __base_type;
+
+ explicit
+ __si_class_type_info(const char *__n, const __class_type_info *__base)
+ : __class_type_info(__n), __base_type(__base) { }
+
+ virtual
+ ~__si_class_type_info();
+
+ protected:
+ __si_class_type_info(const __si_class_type_info&);
+
+ __si_class_type_info&
+ operator=(const __si_class_type_info&);
+
+ // Implementation defined member functions.
+ virtual bool
+ __do_dyncast(ptrdiff_t __src2dst, __sub_kind __access_path,
+ const __class_type_info* __dst_type, const void* __obj_ptr,
+ const __class_type_info* __src_type, const void* __src_ptr,
+ __dyncast_result& __result) const;
+
+ virtual __sub_kind
+ __do_find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr,
+ const __class_type_info* __src_type,
+ const void* __sub_ptr) const;
+
+ virtual bool
+ __do_upcast(const __class_type_info*__dst, const void*__obj,
+ __upcast_result& __restrict __result) const;
+ };
+
+ // Type information for a class with multiple and/or virtual bases.
+ class __vmi_class_type_info : public __class_type_info
+ {
+ public:
+ unsigned int __flags; // Details about the class hierarchy.
+ unsigned int __base_count; // Number of direct bases.
+
+ // The array of bases uses the trailing array struct hack so this
+ // class is not constructable with a normal constructor. It is
+ // internally generated by the compiler.
+ __base_class_type_info __base_info[1]; // Array of bases.
+
+ explicit
+ __vmi_class_type_info(const char* __n, int ___flags)
+ : __class_type_info(__n), __flags(___flags), __base_count(0) { }
+
+ virtual
+ ~__vmi_class_type_info();
+
+ // Implementation defined types.
+ enum __flags_masks
+ {
+ __non_diamond_repeat_mask = 0x1, // Distinct instance of repeated base.
+ __diamond_shaped_mask = 0x2, // Diamond shaped multiple inheritance.
+ __flags_unknown_mask = 0x10
+ };
+
+ protected:
+ // Implementation defined member functions.
+ virtual bool
+ __do_dyncast(ptrdiff_t __src2dst, __sub_kind __access_path,
+ const __class_type_info* __dst_type, const void* __obj_ptr,
+ const __class_type_info* __src_type, const void* __src_ptr,
+ __dyncast_result& __result) const;
+
+ virtual __sub_kind
+ __do_find_public_src(ptrdiff_t __src2dst, const void* __obj_ptr,
+ const __class_type_info* __src_type,
+ const void* __src_ptr) const;
+
+ virtual bool
+ __do_upcast(const __class_type_info* __dst, const void* __obj,
+ __upcast_result& __restrict __result) const;
+ };
+
+ // Dynamic cast runtime.
+ // src2dst has the following possible values
+ // >-1: src_type is a unique public non-virtual base of dst_type
+ // dst_ptr + src2dst == src_ptr
+ // -1: unspecified relationship
+ // -2: src_type is not a public base of dst_type
+ // -3: src_type is a multiple public non-virtual base of dst_type
+ extern "C" void*
+ __dynamic_cast(const void* __src_ptr, // Starting object.
+ const __class_type_info* __src_type, // Static type of object.
+ const __class_type_info* __dst_type, // Desired target type.
+ ptrdiff_t __src2dst); // How src and dst are related.
+
+
+ // Returns the type_info for the currently handled exception [15.3/8], or
+ // null if there is none.
+ extern "C" std::type_info*
+ __cxa_current_exception_type();
+} // namespace __cxxabiv1
+
+// User programs should use the alias `abi'.
+namespace abi = __cxxabiv1;
+
+
+#endif // __RTTI_H
diff --git a/bridges/source/cpp_uno/gcc3_ios/share.hxx b/bridges/source/cpp_uno/gcc3_ios/share.hxx
new file mode 100644
index 000000000..65461d7fd
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios/share.hxx
@@ -0,0 +1,57 @@
+/* -*- 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>
+
+// from opensource.apple.com: libcppabi-24.4/include/rtti.h
+#include "rtti.h"
+
+// from opensource.apple.com: libcppabi-24.4/include/unwind-cxx.h
+#include "unwind-cxx.h"
+
+// Import the __cxxabiv1 a.k.a. "abi" namespace
+using namespace abi;
+
+namespace CPPU_CURRENT_NAMESPACE
+{
+ void dummy_can_throw_anything( char const * );
+
+ void raiseException(
+ uno_Any * pUnoExc, uno_Mapping * pUno2Cpp );
+
+ void fillUnoException(uno_Any *, uno_Mapping * pCpp2Uno);
+
+ bool isSimpleReturnType(typelib_TypeDescription * pTD, bool recursive = false);
+}
+
+namespace arm
+{
+ enum armlimits {
+ MAX_GPR_REGS = 8,
+ MAX_FPR_REGS = 8
+ };
+ bool return_in_x8( typelib_TypeDescriptionReference *pTypeRef );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_ios/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_ios/uno2cpp.cxx
new file mode 100644
index 000000000..07ec8501f
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios/uno2cpp.cxx
@@ -0,0 +1,572 @@
+/* -*- 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 .
+ */
+
+#ifdef __arm64
+
+#include <sal/config.h>
+
+#include <exception>
+#include <typeinfo>
+
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <o3tl/runtimetooustring.hxx>
+
+#include "bridge.hxx"
+#include "types.hxx"
+#include "unointerfaceproxy.hxx"
+#include "vtables.hxx"
+
+#include "share.hxx"
+
+using namespace ::com::sun::star::uno;
+
+namespace arm
+{
+ bool is_hfa_struct(const typelib_TypeDescription * type)
+ {
+ const typelib_CompoundTypeDescription * p
+ = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
+ if (p->nMembers >= 4)
+ return false;
+ for (sal_Int32 i = 0; i < p->nMembers; ++i)
+ {
+ if ((p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT &&
+ p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE) ||
+ p->ppTypeRefs[i]->eTypeClass != p->ppTypeRefs[0]->eTypeClass)
+ return false;
+ }
+ return true;
+ }
+
+ bool return_in_x8( 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 x0, x1
+ bool bRet = pTypeDescr->nSize > 16;
+
+ if (is_hfa_struct(pTypeDescr))
+ bRet = false;
+
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ return bRet;
+ }
+ return true;
+ }
+}
+
+void MapReturn(sal_uInt64 x0, sal_uInt64 x1, double d0, typelib_TypeDescriptionReference *pReturnType, sal_uInt64 *pRegisterReturn)
+{
+ switch( pReturnType->eTypeClass )
+ {
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ pRegisterReturn[1] = x1;
+ [[fallthrough]];
+ 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:
+ pRegisterReturn[0] = x0;
+ break;
+ case typelib_TypeClass_FLOAT:
+ *(float*)pRegisterReturn = *(float*)&d0;
+ break;
+ case typelib_TypeClass_DOUBLE:
+ *(double*)pRegisterReturn = d0;
+ break;
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_EXCEPTION:
+ if (!arm::return_in_x8(pReturnType))
+ {
+ pRegisterReturn[0] = x0;
+ pRegisterReturn[1] = x1;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+namespace
+{
+void callVirtualMethod(
+ void *pThis,
+ sal_Int32 nVtableIndex,
+ void *pRegisterReturn,
+ typelib_TypeDescriptionReference *pReturnType,
+ sal_uInt64 *pStack,
+ int nStack,
+ sal_uInt64 *pGPR,
+ double *pFPR)
+{
+ // never called
+ if (! pThis)
+ CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
+
+ if ( nStack )
+ {
+ // 16-bytes aligned
+ sal_uInt32 nStackBytes = ( ( nStack + 3 ) >> 2 ) * 16;
+ sal_uInt32 *stack = (sal_uInt32 *) alloca( nStackBytes );
+ memcpy( stack, pStack, nStackBytes );
+ }
+
+ sal_uInt64 pMethod = *((sal_uInt64*)pThis);
+ pMethod += 8 * nVtableIndex;
+ pMethod = *((sal_uInt64 *)pMethod);
+
+ // For value returned in registers
+ sal_uInt64 x0;
+ sal_uInt64 x1;
+ double d0;
+
+ __asm__ __volatile__
+ (
+ // Assembly string
+ " ldp x0, x1, %[pgpr_0]\n"
+ " ldp x2, x3, %[pgpr_2]\n"
+ " ldp x4, x5, %[pgpr_4]\n"
+ " ldp x6, x7, %[pgpr_6]\n"
+ " ldr x8, %[pregisterreturn]\n"
+ " ldp d0, d1, %[pfpr_0]\n"
+ " ldp d2, d3, %[pfpr_2]\n"
+ " ldp d4, d5, %[pfpr_4]\n"
+ " ldp d6, d7, %[pfpr_6]\n"
+ " blr %[pmethod]\n"
+ " str x0, %[x0]\n"
+ " str x1, %[x1]\n"
+ " str d0, %[d0]\n"
+ // Output operands
+ : [x0]"=m" (x0), [x1]"=m" (x1), [d0]"=m" (d0)
+ // Input operands
+ : [pgpr_0]"m" (pGPR[0]),
+ [pgpr_2]"m" (pGPR[2]),
+ [pgpr_4]"m" (pGPR[4]),
+ [pgpr_6]"m" (pGPR[6]),
+ [pregisterreturn]"m" (pRegisterReturn),
+ [pfpr_0]"m" (pFPR[0]),
+ [pfpr_2]"m" (pFPR[2]),
+ [pfpr_4]"m" (pFPR[4]),
+ [pfpr_6]"m" (pFPR[6]),
+ [pmethod]"r" (pMethod)
+ // Clobbers
+ : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7"
+ );
+
+ MapReturn(x0, x1, d0, pReturnType, (sal_uInt64 *) pRegisterReturn);
+}
+}
+
+#define INSERT_INT64( pSV, nr, pGPR, pDS ) \
+ if ( nr < arm::MAX_GPR_REGS ) \
+ pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
+
+#define INSERT_INT32( pSV, nr, pGPR, pDS ) \
+ if ( nr < arm::MAX_GPR_REGS ) \
+ pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
+
+#define INSERT_INT16( pSV, nr, pGPR, pDS ) \
+ if ( nr < arm::MAX_GPR_REGS ) \
+ pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
+
+#define INSERT_INT8( pSV, nr, pGPR, pDS ) \
+ if ( nr < arm::MAX_GPR_REGS ) \
+ pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
+
+#define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \
+ if ( nr < arm::MAX_FPR_REGS ) \
+ pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<double *>( pSV );
+
+#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \
+ INSERT_DOUBLE( pSV, nr, pGPR, pDS )
+
+namespace {
+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: values|ptr ...
+ sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+2) * sizeof(sal_Int64) );
+ sal_uInt64 * pStackStart = pStack;
+
+ sal_uInt64 pGPR[arm::MAX_GPR_REGS];
+ int nGPR = 0;
+
+ // storage and counter for SIMD/FP registers
+ double pFPR[arm::MAX_FPR_REGS];
+ int nFPR = 0;
+
+ // return
+ typelib_TypeDescription * pReturnTypeDescr = 0;
+ TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
+ assert( pReturnTypeDescr);
+
+ void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
+
+ if (pReturnTypeDescr)
+ {
+ if (!arm::return_in_x8( pReturnTypeRef ) )
+ pCppReturn = pUnoReturn; // direct way for simple types
+ else
+ {
+ // complex return via x8
+ pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
+ ? alloca( pReturnTypeDescr->nSize )
+ : pUnoReturn); // direct way
+ }
+ }
+ // push this
+ void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
+ + aVtableSlot.offset;
+ INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
+
+ // stack space
+ // args
+ void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams );
+
+ // indices of values this have to be converted (interface conversion cpp<=>uno)
+ int * pTempIndices = (int *)alloca( sizeof(int) * nParams );
+
+ // type descriptions for reconversions
+ typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(void *) * 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_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_ENUM:
+ INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_CHAR:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
+ break;
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
+ break;
+ case typelib_TypeClass_FLOAT:
+ INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, pStack );
+ break;
+ case typelib_TypeClass_DOUBLE:
+ INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, 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]), nGPR, pGPR, pStack );
+ }
+ }
+
+ assert( nGPR <= arm::MAX_GPR_REGS );
+ assert( nFPR <= arm::MAX_FPR_REGS );
+
+ try
+ {
+ try {
+ callVirtualMethod(
+ pAdjustedThisPtr, aVtableSlot.index,
+ pCppReturn, pReturnTypeRef,
+ pStackStart,
+ (pStack - pStackStart),
+ pGPR,
+ pFPR);
+ } 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);
+#if OSL_DEBUG_LEVEL > 0
+ typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
+#endif
+
+ switch (pMemberDescr->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+#if OSL_DEBUG_LEVEL > 0
+ // determine vtable call index
+ sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
+ assert( nMemberPos < pTypeDescr->nAllMembers && "### member pos out of range!");
+#endif
+
+ 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;
+ cpp_call(
+ pThis, aVtableSlot, // get, then set method
+ pReturnTypeRef,
+ 1, &aParam,
+ pReturn, pArgs, ppException );
+
+ typelib_typedescriptionreference_release( pReturnTypeRef );
+ }
+
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+#if OSL_DEBUG_LEVEL > 0
+ // determine vtable call index
+ sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
+ assert(nMemberPos < pTypeDescr->nAllMembers && "### member pos out of range!");
+#endif
+
+ 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->getBridge()->getUnoEnv()->getRegisteredInterface)(
+ pThis->getBridge()->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()
+ [[fallthrough]];
+ 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 );
+ }
+ }
+}
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_ios/unwind-cxx.h b/bridges/source/cpp_uno/gcc3_ios/unwind-cxx.h
new file mode 100644
index 000000000..83ed08486
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios/unwind-cxx.h
@@ -0,0 +1,283 @@
+// -*- C++ -*- Exception handling and frame unwind runtime interface routines.
+// Copyright (C) 2001 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// GCC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+// This is derived from the C++ ABI for IA-64. Where we diverge
+// for cross-architecture compatibility are noted with "@@@".
+
+#ifndef _UNWIND_CXX_H
+#define _UNWIND_CXX_H 1
+
+// Level 2: C++ ABI
+
+#include <typeinfo>
+#include <exception>
+
+#include <stddef.h>
+#include "unwind.h"
+
+
+typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
+typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
+typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
+typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
+typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
+typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
+
+#pragma GCC visibility push(default)
+
+namespace __cxxabiv1
+{
+
+// A C++ exception object consists of a header, which is a wrapper around
+// an unwind object header with additional C++ specific information,
+// followed by the exception object itself.
+
+struct __cxa_exception
+{
+#if __LP64__
+#if 0
+ // This is a new field added with LLVM 10
+ // <https://github.com/llvm/llvm-project/commit/674ec1eb16678b8addc02a4b0534ab383d22fa77>
+ // "[libcxxabi] Insert padding in __cxa_exception struct for compatibility". The HACK in
+ // fillUnoException (bridges/source/cpp_uno/gcc3_macosx_x86-64/except.cxx) tries to find out at
+ // runtime whether a __cxa_exception has this member. Once we can be sure that we only run
+ // against new libcxxabi that has this member, we can drop the "#if 0" here and drop the hack
+ // in fillUnoException.
+
+ // Now _Unwind_Exception is marked with __attribute__((aligned)),
+ // which implies __cxa_exception is also aligned. Insert padding
+ // in the beginning of the struct, rather than before unwindHeader.
+ void *reserve;
+#endif
+
+ // This is a new field to support C++ 0x exception_ptr.
+ // For binary compatibility it is at the start of this
+ // struct which is prepended to the object thrown in
+ // __cxa_allocate_exception.
+ size_t referenceCount;
+#endif
+ // Manage the exception object itself.
+ std::type_info *exceptionType;
+ void (*exceptionDestructor)(void *);
+
+ // The C++ standard has entertaining rules wrt calling set_terminate
+ // and set_unexpected in the middle of the exception cleanup process.
+ void (*unexpectedHandler)(); // std::unexpected_handler dropped from C++17
+ std::terminate_handler terminateHandler;
+
+ // The caught exception stack threads through here.
+ __cxa_exception *nextException;
+
+ // How many nested handlers have caught this exception. A negated
+ // value is a signal that this object has been rethrown.
+ int handlerCount;
+
+#ifdef __ARM_EABI_UNWINDER__
+ // Stack of exceptions in cleanups.
+ __cxa_exception* nextPropagatingException;
+
+ // The number of active cleanup handlers for this exception.
+ int propagationCount;
+#else
+ // Cache parsed handler data from the personality routine Phase 1
+ // for Phase 2 and __cxa_call_unexpected.
+ int handlerSwitchValue;
+ const unsigned char *actionRecord;
+ const unsigned char *languageSpecificData;
+ _Unwind_Ptr catchTemp;
+ void *adjustedPtr;
+#endif
+#if !__LP64__
+ // This is a new field to support C++ 0x exception_ptr.
+ // For binary compatibility it is placed where the compiler
+ // previously adding padded to 64-bit align unwindHeader.
+ size_t referenceCount;
+#endif
+
+ // The generic exception header. Must be last.
+ _Unwind_Exception unwindHeader;
+};
+
+// Each thread in a C++ program has access to a __cxa_eh_globals object.
+struct __cxa_eh_globals
+{
+ __cxa_exception *caughtExceptions;
+ unsigned int uncaughtExceptions;
+#ifdef __ARM_EABI_UNWINDER__
+ __cxa_exception* propagatingExceptions;
+#endif
+};
+
+
+// The __cxa_eh_globals for the current thread can be obtained by using
+// either of the following functions. The "fast" version assumes at least
+// one prior call of __cxa_get_globals has been made from the current
+// thread, so no initialization is necessary.
+extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
+extern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw();
+
+// Allocate memory for the exception plus the thrown object.
+extern "C" void *__cxa_allocate_exception(size_t thrown_size) throw();
+
+// Free the space allocated for the exception.
+extern "C" void __cxa_free_exception(void *thrown_exception) throw();
+
+#pragma GCC visibility push(hidden)
+extern "C" void *__cxa_allocate_dependent_exception() throw();
+extern "C" void __cxa_free_dependent_exception(void *thrown_exception) throw();
+#pragma GCC visibility pop
+
+// Throw the exception.
+extern "C" void __cxa_throw (void *thrown_exception,
+ std::type_info *tinfo,
+ void (*dest) (void *))
+ __attribute__((noreturn));
+
+// Used to implement exception handlers.
+extern "C" void *__cxa_get_exception_ptr (void *) throw();
+extern "C" void *__cxa_begin_catch (void *) throw();
+extern "C" void __cxa_end_catch ();
+extern "C" void __cxa_rethrow () __attribute__((noreturn));
+
+// These facilitate code generation for recurring situations.
+extern "C" void __cxa_bad_cast ();
+extern "C" void __cxa_bad_typeid ();
+
+// @@@ These are not directly specified by the IA-64 C++ ABI.
+
+// Handles re-checking the exception specification if unexpectedHandler
+// throws, and if bad_exception needs to be thrown. Called from the
+// compiler.
+extern "C" void __cxa_call_unexpected (void *) __attribute__((noreturn));
+extern "C" void __cxa_call_terminate (void*) __attribute__((noreturn));
+
+#ifdef __ARM_EABI_UNWINDER__
+// Arm EABI specified routines.
+typedef enum {
+ ctm_failed = 0,
+ ctm_succeeded = 1,
+ ctm_succeeded_with_ptr_to_base = 2
+} __cxa_type_match_result;
+extern "C" bool __cxa_type_match(_Unwind_Exception*, const std::type_info*,
+ bool, void**);
+extern "C" void __cxa_begin_cleanup (_Unwind_Exception*);
+extern "C" void __cxa_end_cleanup (void);
+#endif
+
+// These are explicitly GNU C++ specific.
+
+// Acquire the C++ exception header from the C++ object.
+static inline __cxa_exception *
+__get_exception_header_from_obj (void *ptr)
+{
+ return reinterpret_cast<__cxa_exception *>(ptr) - 1;
+}
+
+// Acquire the C++ exception header from the generic exception header.
+static inline __cxa_exception *
+__get_exception_header_from_ue (_Unwind_Exception *exc)
+{
+ return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;
+}
+
+#ifdef __ARM_EABI_UNWINDER__
+static inline bool
+__is_gxx_exception_class(_Unwind_Exception_Class c)
+{
+ // TODO: Take advantage of the fact that c will always be word aligned.
+ return c[0] == 'G'
+ && c[1] == 'N'
+ && c[2] == 'U'
+ && c[3] == 'C'
+ && c[4] == 'C'
+ && c[5] == '+'
+ && c[6] == '+';
+}
+
+static inline void
+__GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
+{
+ c[0] = 'G';
+ c[1] = 'N';
+ c[2] = 'U';
+ c[3] = 'C';
+ c[4] = 'C';
+ c[5] = '+';
+ c[6] = '+';
+ c[7] = '\0';
+}
+
+static inline void*
+__gxx_caught_object(_Unwind_Exception* eo)
+{
+ return (void*)eo->barrier_cache.bitpattern[0];
+}
+#else // !__ARM_EABI_UNWINDER__
+// This is the exception class we report -- "GNUCC++\0".
+const _Unwind_Exception_Class __gxx_exception_class
+= ((((((((_Unwind_Exception_Class) 'G'
+ << 8 | (_Unwind_Exception_Class) 'N')
+ << 8 | (_Unwind_Exception_Class) 'U')
+ << 8 | (_Unwind_Exception_Class) 'C')
+ << 8 | (_Unwind_Exception_Class) 'C')
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '\0');
+
+static inline bool
+__is_gxx_exception_class(_Unwind_Exception_Class c)
+{
+ return (c & ((_Unwind_Exception_Class)~0 << 8)) == __gxx_exception_class;
+}
+
+#define __GXX_INIT_EXCEPTION_CLASS(c) c = __gxx_exception_class
+
+// GNU C++ personality routine, Version 0.
+extern "C" _Unwind_Reason_Code __gxx_personality_v0
+ (int, _Unwind_Action, _Unwind_Exception_Class,
+ struct _Unwind_Exception *, struct _Unwind_Context *);
+
+// GNU C++ sjlj personality routine, Version 0.
+extern "C" _Unwind_Reason_Code __gxx_personality_sj0
+ (int, _Unwind_Action, _Unwind_Exception_Class,
+ struct _Unwind_Exception *, struct _Unwind_Context *);
+
+static inline void*
+__gxx_caught_object(_Unwind_Exception* eo)
+{
+ __cxa_exception* header = __get_exception_header_from_ue (eo);
+ return header->adjustedPtr;
+}
+#endif // !__ARM_EABI_UNWINDER__
+
+} /* namespace __cxxabiv1 */
+
+#pragma GCC visibility pop
+
+#endif // _UNWIND_CXX_H