From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx | 390 ++++++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx (limited to 'bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx') diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx new file mode 100644 index 000000000..b0a359967 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx @@ -0,0 +1,390 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "abi.hxx" +#include +#include + +namespace { + +OUString toUnoName(char const * name) { + assert(name != 0); + OUStringBuffer b; + bool scoped = *name == 'N'; + if (scoped) { + ++name; + } + for (;;) { + assert(*name >= '0' && *name <= '9'); + std::size_t n = *name++ - '0'; + while (*name >= '0' && *name <= '9') { + n = 10 * n + (*name++ - '0'); + } + b.appendAscii(name, n); + name += n; + if (!scoped) { + assert(*name == 0); + break; + } + if (*name == 'E') { + assert(name[1] == 0); + break; + } + b.append('.'); + } + return b.makeStringAndClear(); +} + +class Rtti { +public: + Rtti(): app_(dlopen(0, RTLD_LAZY)) {} + + ~Rtti() { dlclose(app_); } + + std::type_info * getRtti(typelib_TypeDescription const & type); + +private: + typedef std::unordered_map Map; + + void * app_; + + osl::Mutex mutex_; + Map map_; +}; + +std::type_info * Rtti::getRtti(typelib_TypeDescription const & type) { + OUString unoName(type.pTypeName); + osl::MutexGuard g(mutex_); + Map::iterator i(map_.find(unoName)); + if (i == map_.end()) { + OStringBuffer b; + b.append("_ZTIN"); + for (sal_Int32 j = 0; j != -1;) { + OString t( + OUStringToOString( + unoName.getToken(0, '.', j), RTL_TEXTENCODING_ASCII_US)); + b.append(t.getLength()); + b.append(t); + } + b.append('E'); + OString sym(b.makeStringAndClear()); + std::type_info * rtti = static_cast( + dlsym(app_, sym.getStr())); +#if defined MACOSX + + // Horrible but hopefully temporary hack. + + // For some reason, with the Xcode 12 betas, when compiling for arm64-apple-macos, the + // symbols for the typeinfos for the UNO exception types + // (_ZTIN3com3sun4star3uno16RuntimeExceptionE etc) end up as "weak private external" in the + // object file, as displayed by "nm -f darwin". We try to look them up with dlsym() above, + // but that then fails. So use a hackaround... introduce separate real variables (see end of + // this file) that point to these typeinfos. + + // When compiling for x86_64-apple-macos, the typeinfo symbols end up as "weak external" + // which is fine. + + if (rtti == nullptr) + { + const OString ptrSym = "ptr" + sym; + auto ptr = static_cast(dlsym(app_, ptrSym.getStr())); + if (ptr != nullptr) + rtti = *ptr; + else + SAL_WARN("bridges.osx", dlerror()); + } +#endif + + if (rtti == 0) { + char const * rttiName = sym.getStr() + std::strlen("_ZTI"); + assert(type.eTypeClass == typelib_TypeClass_EXCEPTION); + typelib_CompoundTypeDescription const & ctd + = reinterpret_cast( + type); + if (ctd.pBaseTypeDescription == 0) { + rtti = new __cxxabiv1::__class_type_info(strdup(rttiName)); + } else { + std::type_info * base = getRtti( + ctd.pBaseTypeDescription->aBase); + rtti = new __cxxabiv1::__si_class_type_info( + strdup(rttiName), + static_cast<__cxxabiv1::__class_type_info *>(base)); + } + } + i = map_.insert(Map::value_type(unoName, rtti)).first; + } + return i->second; +} + +struct theRttiFactory: public rtl::Static {}; + +std::type_info * getRtti(typelib_TypeDescription const & type) { + return theRttiFactory::get().getRtti(type); +} + +extern "C" void _GLIBCXX_CDTOR_CALLABI deleteException(void * exception) { + __cxxabiv1::__cxa_exception * header = + static_cast<__cxxabiv1::__cxa_exception *>(exception) - 1; +#if defined _LIBCPPABI_VERSION // detect libc++abi + // The libcxxabi commit + // + // "[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 + // new 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): + + // Later, libcxxabi, as used at least on macOS on arm64, added a + // void *reserve at the start of the __cxa_exception in front of + // the referenceCount. See + // https://github.com/llvm/llvm-project/commit/f2a436058fcbc11291e73badb44e243f61046183#diff-ba9cda1ceca630ba040b154fe198adbd + + if (header->exceptionDestructor != &deleteException) { + header = reinterpret_cast<__cxxabiv1::__cxa_exception *>( + reinterpret_cast(header) - 8); + assert(header->exceptionDestructor == &deleteException); + } +#endif + OUString unoName(toUnoName(header->exceptionType->name())); + typelib_TypeDescription * td = 0; + typelib_typedescription_getByName(&td, unoName.pData); + assert(td != 0); + uno_destructData(exception, td, &css::uno::cpp_release); + typelib_typedescription_release(td); +} + +enum StructKind { + STRUCT_KIND_EMPTY, STRUCT_KIND_FLOAT, STRUCT_KIND_DOUBLE, STRUCT_KIND_POD, + STRUCT_KIND_DTOR +}; + +StructKind getStructKind(typelib_CompoundTypeDescription const * type) { + StructKind k = type->pBaseTypeDescription == 0 + ? STRUCT_KIND_EMPTY : getStructKind(type->pBaseTypeDescription); + for (sal_Int32 i = 0; i != type->nMembers; ++i) { + StructKind k2 = StructKind(); + switch (type->ppTypeRefs[i]->eTypeClass) { + 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: + k2 = STRUCT_KIND_POD; + break; + case typelib_TypeClass_FLOAT: + k2 = STRUCT_KIND_FLOAT; + break; + case typelib_TypeClass_DOUBLE: + k2 = STRUCT_KIND_DOUBLE; + break; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + k2 = STRUCT_KIND_DTOR; + break; + case typelib_TypeClass_STRUCT: + { + typelib_TypeDescription * td = 0; + TYPELIB_DANGER_GET(&td, type->ppTypeRefs[i]); + k2 = getStructKind( + reinterpret_cast( + td)); + TYPELIB_DANGER_RELEASE(td); + break; + } + default: + assert(false); + } + switch (k2) { + case STRUCT_KIND_EMPTY: + // this means an empty sub-object, which nevertheless obtains a byte + // of storage (TODO: does it?), so the full object cannot be a + // homogeneous collection of float or double + case STRUCT_KIND_POD: + assert(k != STRUCT_KIND_DTOR); + k = STRUCT_KIND_POD; + break; + case STRUCT_KIND_FLOAT: + case STRUCT_KIND_DOUBLE: + if (k == STRUCT_KIND_EMPTY) { + k = k2; + } else if (k != k2) { + assert(k != STRUCT_KIND_DTOR); + k = STRUCT_KIND_POD; + } + break; + case STRUCT_KIND_DTOR: + return STRUCT_KIND_DTOR; + } + } + return k; +} + +} + +namespace abi_aarch64 { + +void mapException( + __cxxabiv1::__cxa_exception * exception, std::type_info const * type, uno_Any * any, uno_Mapping * mapping) +{ + assert(exception != 0); + assert(type != nullptr); + OUString unoName(toUnoName(type->name())); + typelib_TypeDescription * td = 0; + typelib_typedescription_getByName(&td, unoName.pData); + if (td == 0) { + css::uno::RuntimeException e("exception type not found: " + unoName); + uno_type_any_constructAndConvert( + any, &e, + cppu::UnoType::get().getTypeLibType(), + mapping); + } else { + uno_any_constructAndConvert(any, exception->adjustedPtr, td, mapping); + typelib_typedescription_release(td); + } +} + +void raiseException(uno_Any * any, uno_Mapping * mapping) { + typelib_TypeDescription * td = 0; + TYPELIB_DANGER_GET(&td, any->pType); + if (td == 0) { + throw css::uno::RuntimeException( + "no typedescription for " + OUString(any->pType->pTypeName)); + } + void * exc = __cxxabiv1::__cxa_allocate_exception(td->nSize); + uno_copyAndConvertData(exc, any->pData, td, mapping); + uno_any_destruct(any, 0); + std::type_info * rtti = getRtti(*td); + TYPELIB_DANGER_RELEASE(td); + __cxxabiv1::__cxa_throw(exc, rtti, deleteException); +} + +ReturnKind getReturnKind(typelib_TypeDescription const * type) { + switch (type->eTypeClass) { + default: + assert(false); +#ifdef NDEBUG + [[fallthrough]]; +#endif + case typelib_TypeClass_VOID: + 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_FLOAT: + case typelib_TypeClass_DOUBLE: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + assert(type->nSize <= 16); + return RETURN_KIND_REG; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + return RETURN_KIND_INDIRECT; + case typelib_TypeClass_STRUCT: + if (type->nSize > 16) { + return RETURN_KIND_INDIRECT; + } + switch (getStructKind( + reinterpret_cast( + type))) + { + case STRUCT_KIND_FLOAT: + return RETURN_KIND_HFA_FLOAT; + case STRUCT_KIND_DOUBLE: + return RETURN_KIND_HFA_DOUBLE; + case STRUCT_KIND_DTOR: + return RETURN_KIND_INDIRECT; + default: + return RETURN_KIND_REG; + } + } +} + +} + +#ifdef MACOSX + +// See the comment about the horrible hack above. + +// This set of types are compiled based on what 'make check' needs, but I haven't been able to run +// it completely yet. And of course as such this hack isn't a viable long-term solution. + +#include +#include +#include +#include +#include +#include + +extern "C" { + const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star4lang24IllegalArgumentExceptionE = &typeid(css::lang::IllegalArgumentException); + const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3uno9ExceptionE = &typeid(css::uno::Exception); + const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3uno16RuntimeExceptionE = &typeid(css::uno::RuntimeException); + const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3ucb31InteractiveAugmentedIOExceptionE = &typeid(css::ucb::InteractiveAugmentedIOException); + const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3ucb22InteractiveIOExceptionE = &typeid(css::ucb::InteractiveIOException); + const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star3ucb18NameClashExceptionE = &typeid(css::ucb::NameClashException); + const std::type_info* __attribute((visibility("default"),used)) ptr_ZTIN3com3sun4star4task28ClassifiedInteractionRequestE = &typeid(css::task::ClassifiedInteractionRequest); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3