diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-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_linux_aarch64/uno2cpp.cxx')
-rw-r--r-- | bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx | 519 |
1 files changed, 519 insertions, 0 deletions
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx new file mode 100644 index 000000000..57beb6dfa --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx @@ -0,0 +1,519 @@ +/* -*- 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 <cstring> +#include <exception> +#include <typeinfo> + +#include <bridge.hxx> +#include <types.hxx> +#include <unointerfaceproxy.hxx> +#include <vtables.hxx> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/genfunc.hxx> +#include <rtl/textenc.h> +#include <rtl/ustring.hxx> +#include <sal/alloca.h> +#include <sal/types.h> +#include <typelib/typeclass.h> +#include <typelib/typedescription.h> +#include <uno/any2.h> +#include <uno/data.h> + +#include "abi.hxx" +#include "callvirtualfunction.hxx" + +namespace { + +void pushArgument( +#ifdef MACOSX + typelib_TypeClass typeclass, + sal_Int32 * const subsp, +#endif + unsigned long value, unsigned long * const stack, sal_Int32 * const sp, + unsigned long * const regs, sal_Int32 * const nregs) +{ +#ifdef MACOSX + if (*nregs != 8) + { + regs[(*nregs)++] = value; + } + else + { + switch (typeclass) { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(stack + *sp) + *subsp) = value; + (*subsp) += 1; + if (*subsp == 8) + { + (*sp)++; + *subsp = 0; + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_CHAR: + *subsp = (*subsp + 1) & ~0x1; + if (*subsp == 8) + { + (*sp)++; + *subsp = 0; + } + *reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(stack + *sp) + *subsp) = value; + (*subsp) += 2; + if (*subsp == 8) + { + (*sp)++; + *subsp = 0; + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_FLOAT: + *subsp = (*subsp + 3) & ~0x3; + if (*subsp == 8) + { + (*sp)++; + *subsp = 0; + } + *reinterpret_cast<uint32_t*>(reinterpret_cast<uintptr_t>(stack + *sp) + *subsp) = value; + (*subsp) += 4; + if (*subsp == 8) + { + (*sp)++; + *subsp = 0; + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + default: + if (*subsp > 0) + { + (*sp)++; + *subsp = 0; + } + stack[*sp] = value; + (*sp)++; + break; + } + } +#else + (*nregs != 8 ? regs[(*nregs)++] : stack[(*sp)++]) = value; +#endif +} + +void call( + bridges::cpp_uno::shared::UnoInterfaceProxy * proxy, + bridges::cpp_uno::shared::VtableSlot slot, + typelib_TypeDescriptionReference * returnType, sal_Int32 count, + typelib_MethodParameter * parameters, void * returnValue, void ** arguments, + uno_Any ** exception) +{ + typelib_TypeDescription * rtd = nullptr; + TYPELIB_DANGER_GET(&rtd, returnType); + abi_aarch64::ReturnKind retKind = abi_aarch64::getReturnKind(rtd); + bool retConv = bridges::cpp_uno::shared::relatesToInterfaceType(rtd); + void * ret = retConv ? alloca(rtd->nSize) : returnValue; + unsigned long ** thisPtr + = reinterpret_cast<unsigned long **>(proxy->getCppI()) + slot.offset; + unsigned long * stack = static_cast<unsigned long *>( + alloca(count * sizeof (unsigned long))); + sal_Int32 sp = 0; +#ifdef MACOSX + sal_Int32 subsp = 0; +#endif + unsigned long gpr[8]; + sal_Int32 ngpr = 0; + unsigned long fpr[8]; + sal_Int32 nfpr = 0; + gpr[ngpr++] = reinterpret_cast<unsigned long>(thisPtr); + void ** cppArgs = static_cast<void **>(alloca(count * sizeof (void *))); + typelib_TypeDescription ** ptds = + static_cast<typelib_TypeDescription **>( + alloca(count * sizeof (typelib_TypeDescription *))); + for (sal_Int32 i = 0; i != count; ++i) { + if (!parameters[i].bOut && + bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef)) + { + cppArgs[i] = nullptr; + switch (parameters[i].pTypeRef->eTypeClass) { + case typelib_TypeClass_BOOLEAN: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + static_cast<unsigned long>(*static_cast<sal_Bool *>(arguments[i])), stack, &sp, + gpr, &ngpr); + break; + case typelib_TypeClass_BYTE: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<sal_Int8 *>(arguments[i]), stack, &sp, gpr, + &ngpr); + break; + case typelib_TypeClass_SHORT: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<sal_Int16 *>(arguments[i]), stack, &sp, gpr, + &ngpr); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<sal_uInt16 *>(arguments[i]), stack, &sp, gpr, + &ngpr); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_ENUM: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<sal_Int32 *>(arguments[i]), stack, &sp, gpr, + &ngpr); + break; + case typelib_TypeClass_UNSIGNED_LONG: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<sal_uInt32 *>(arguments[i]), stack, &sp, gpr, + &ngpr); + break; + case typelib_TypeClass_HYPER: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<sal_Int64 *>(arguments[i]), stack, &sp, gpr, + &ngpr); + break; + case typelib_TypeClass_UNSIGNED_HYPER: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<sal_uInt64 *>(arguments[i]), stack, &sp, gpr, + &ngpr); + break; + case typelib_TypeClass_FLOAT: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<unsigned int *>(arguments[i]), stack, &sp, fpr, + &nfpr); + break; + case typelib_TypeClass_DOUBLE: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<unsigned long *>(arguments[i]), stack, &sp, + fpr, &nfpr); + break; + case typelib_TypeClass_CHAR: + pushArgument( +#ifdef MACOSX + parameters[i].pTypeRef->eTypeClass, &subsp, +#endif + *static_cast<sal_Unicode *>(arguments[i]), stack, &sp, gpr, + &ngpr); + break; + default: + assert(false); + } + } else { + typelib_TypeDescription * ptd = nullptr; + TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef); + if (!parameters[i].bIn) { + cppArgs[i] = alloca(ptd->nSize); + uno_constructData(cppArgs[i], ptd); + ptds[i] = ptd; + pushArgument( +#ifdef MACOSX + typelib_TypeClass_HYPER, &subsp, +#endif + reinterpret_cast<unsigned long>(cppArgs[i]), stack, &sp, + gpr, &ngpr); + } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) { + cppArgs[i] = alloca(ptd->nSize); + uno_copyAndConvertData( + cppArgs[i], arguments[i], ptd, + proxy->getBridge()->getUno2Cpp()); + ptds[i] = ptd; + pushArgument( +#ifdef MACOSX + typelib_TypeClass_HYPER, &subsp, +#endif + reinterpret_cast<unsigned long>(cppArgs[i]), stack, &sp, + gpr, &ngpr); + } else { + cppArgs[i] = nullptr; + pushArgument( +#ifdef MACOSX + typelib_TypeClass_HYPER, &subsp, +#endif + reinterpret_cast<unsigned long>(arguments[i]), stack, &sp, + gpr, &ngpr); + TYPELIB_DANGER_RELEASE(ptd); + } + } + } + try { + try { + callVirtualFunction( + (*thisPtr)[slot.index], gpr, fpr, stack, sp, ret); + } catch (css::uno::Exception &) { + throw; + } catch (std::exception & e) { + throw css::uno::RuntimeException( + "C++ code threw " + + OStringToOUString(typeid(e).name(), RTL_TEXTENCODING_UTF8) + + ": " + OStringToOUString(e.what(), RTL_TEXTENCODING_UTF8)); + } catch (...) { + throw css::uno::RuntimeException( + "C++ code threw unknown exception"); + } + } catch (css::uno::Exception &) { + __cxxabiv1::__cxa_exception * header = reinterpret_cast<__cxxabiv1::__cxa_eh_globals *>( + __cxxabiv1::__cxa_get_globals())->caughtExceptions; +#if !defined MACOSX && defined _LIBCPPABI_VERSION // detect libc++abi + // 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_linux_aarch64/abi.hxx), this hack (together with the + // "#ifdef MACOSX" 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<__cxxabiv1::__cxa_exception*>( + reinterpret_cast<void **>(header) + 1); + } +#endif + abi_aarch64::mapException( + header, + __cxxabiv1::__cxa_current_exception_type(), *exception, + proxy->getBridge()->getCpp2Uno()); + for (sal_Int32 i = 0; i != count; ++i) { + if (cppArgs[i] != nullptr) { + uno_destructData( + cppArgs[i], ptds[i], + reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release)); + TYPELIB_DANGER_RELEASE(ptds[i]); + } + } + TYPELIB_DANGER_RELEASE(rtd); + return; + } + *exception = nullptr; + for (sal_Int32 i = 0; i != count; ++i) { + if (cppArgs[i] != nullptr) { + if (parameters[i].bOut) { + if (parameters[i].bIn) { + uno_destructData(arguments[i], ptds[i], nullptr); + } + uno_copyAndConvertData( + arguments[i], cppArgs[i], ptds[i], + proxy->getBridge()->getCpp2Uno()); + } + uno_destructData( + cppArgs[i], ptds[i], + reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release)); + TYPELIB_DANGER_RELEASE(ptds[i]); + } + } + switch (retKind) { + case abi_aarch64::RETURN_KIND_REG: + switch (rtd->eTypeClass) { + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_STRUCT: + std::memcpy(ret, gpr, rtd->nSize); + break; + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + std::memcpy(ret, fpr, rtd->nSize); + break; + default: + assert(false); + } + break; + case abi_aarch64::RETURN_KIND_HFA_FLOAT: + switch (rtd->nSize) { + case 16: + std::memcpy(static_cast<char *>(ret) + 12, fpr + 3, 4); + [[fallthrough]]; + case 12: + std::memcpy(static_cast<char *>(ret) + 8, fpr + 2, 4); + [[fallthrough]]; + case 8: + std::memcpy(static_cast<char *>(ret) + 4, fpr + 1, 4); + [[fallthrough]]; + case 4: + std::memcpy(ret, fpr, 4); + break; + default: + assert(false); + } + break; + case abi_aarch64::RETURN_KIND_HFA_DOUBLE: + std::memcpy(ret, fpr, rtd->nSize); + break; + case abi_aarch64::RETURN_KIND_INDIRECT: + break; + } + if (retConv) { + uno_copyAndConvertData( + returnValue, ret, rtd, proxy->getBridge()->getCpp2Uno()); + uno_destructData( + ret, rtd, reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release)); + } + TYPELIB_DANGER_RELEASE(rtd); +} + +} + +namespace bridges::cpp_uno::shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, typelib_TypeDescription const * pMemberDescr, + void * pReturn, void ** pArgs, uno_Any ** ppException) +{ + UnoInterfaceProxy * proxy = static_cast<UnoInterfaceProxy *>(pUnoI); + switch (pMemberDescr->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + typelib_InterfaceAttributeTypeDescription const * atd + = reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const *>( + pMemberDescr); + VtableSlot slot(getVtableSlot(atd)); + if (pReturn != nullptr) { // getter + call( + proxy, slot, atd->pAttributeTypeRef, 0, nullptr, pReturn, pArgs, + ppException); + } else { // setter + typelib_MethodParameter param = { + nullptr, atd->pAttributeTypeRef, true, false }; + typelib_TypeDescriptionReference * rtd = nullptr; + typelib_typedescriptionreference_new( + &rtd, typelib_TypeClass_VOID, OUString("void").pData); + slot.index += 1; + call(proxy, slot, rtd, 1, ¶m, pReturn, pArgs, ppException); + typelib_typedescriptionreference_release(rtd); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + typelib_InterfaceMethodTypeDescription const * mtd + = reinterpret_cast< + typelib_InterfaceMethodTypeDescription const *>( + pMemberDescr); + VtableSlot slot(getVtableSlot(mtd)); + switch (slot.index) { + case 1: + pUnoI->acquire(pUnoI); + *ppException = nullptr; + break; + case 2: + pUnoI->release(pUnoI); + *ppException = nullptr; + break; + case 0: + { + typelib_TypeDescription * td = nullptr; + TYPELIB_DANGER_GET( + &td, + (static_cast<css::uno::Type *>(pArgs[0]) + ->getTypeLibType())); + if (td != nullptr) { + uno_Interface * ifc = nullptr; + proxy->pBridge->getUnoEnv()->getRegisteredInterface( + proxy->pBridge->getUnoEnv(), + reinterpret_cast<void **>(&ifc), proxy->oid.pData, + reinterpret_cast< + typelib_InterfaceTypeDescription *>(td)); + if (ifc != nullptr) { + uno_any_construct( + static_cast<uno_Any *>(pReturn), &ifc, td, + nullptr); + ifc->release(ifc); + TYPELIB_DANGER_RELEASE(td); + *ppException = nullptr; + break; + } + TYPELIB_DANGER_RELEASE(td); + } + } + [[fallthrough]]; + default: + call( + proxy, slot, mtd->pReturnTypeRef, mtd->nParams, + mtd->pParams, pReturn, pArgs, ppException); + break; + } + break; + } + default: + assert(false); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |