diff options
Diffstat (limited to 'bridges/source/cpp_uno/gcc3_linux_aarch64')
8 files changed, 615 insertions, 167 deletions
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx index 4a5a1d1b662d..dcd27e95ae30 100644 --- a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * @@ -21,6 +21,7 @@ #include <cassert> #include <cstddef> +#include <cstdint> #include <cstring> #include <typeinfo> @@ -28,6 +29,7 @@ #include <com/sun/star/uno/RuntimeException.hpp> #include <com/sun/star/uno/genfunc.h> +#include <o3tl/string_view.hxx> #include <rtl/strbuf.hxx> #include <rtl/ustrbuf.hxx> #include <rtl/ustring.hxx> @@ -44,7 +46,7 @@ namespace { OUString toUnoName(char const * name) { - assert(name != 0); + assert(name != nullptr); OUStringBuffer b; bool scoped = *name == 'N'; if (scoped) { @@ -73,7 +75,7 @@ OUString toUnoName(char const * name) { class Rtti { public: - Rtti(): app_(dlopen(0, RTLD_LAZY)) {} + Rtti(): app_(dlopen(nullptr, RTLD_LAZY)) {} ~Rtti() { dlclose(app_); } @@ -93,32 +95,40 @@ std::type_info * Rtti::getRtti(typelib_TypeDescription const & type) { osl::MutexGuard g(mutex_); Map::iterator i(map_.find(unoName)); if (i == map_.end()) { - OStringBuffer b; - b.append("_ZTIN"); + OStringBuffer b("_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); + o3tl::getToken(unoName, 0, '.', j), RTL_TEXTENCODING_ASCII_US)); + b.append(OString::number(t.getLength()) + t); } b.append('E'); OString sym(b.makeStringAndClear()); std::type_info * rtti = static_cast<std::type_info *>( dlsym(app_, sym.getStr())); - if (rtti == 0) { - char const * rttiName = sym.getStr() + std::strlen("_ZTI"); + if (rtti == nullptr) { + char const * rttiName = strdup(sym.getStr() + std::strlen("_ZTI")); + if (rttiName == nullptr) { + throw std::bad_alloc(); + } +#if defined MACOSX + // For the Apple ARM64 ABI, if the most significant ("non-unique RTTI") bit is set, it + // means that the instance of the name is not unique (and thus RTTI equality needs to be + // determined by string comparison rather than by pointer comparison): + rttiName = reinterpret_cast<char const *>( + reinterpret_cast<std::uintptr_t>(rttiName) | 0x8000'0000'0000'0000); +#endif assert(type.eTypeClass == typelib_TypeClass_EXCEPTION); typelib_CompoundTypeDescription const & ctd = reinterpret_cast<typelib_CompoundTypeDescription const &>( type); - if (ctd.pBaseTypeDescription == 0) { - rtti = new __cxxabiv1::__class_type_info(strdup(rttiName)); + if (ctd.pBaseTypeDescription == nullptr) { + rtti = new __cxxabiv1::__class_type_info(rttiName); } else { std::type_info * base = getRtti( ctd.pBaseTypeDescription->aBase); rtti = new __cxxabiv1::__si_class_type_info( - strdup(rttiName), + rttiName, static_cast<__cxxabiv1::__class_type_info *>(base)); } } @@ -136,8 +146,8 @@ std::type_info * getRtti(typelib_TypeDescription const & 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 +#if !defined MACOSX && defined _LIBCPPABI_VERSION // detect libc++abi + // First, 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 @@ -147,21 +157,52 @@ extern "C" void _GLIBCXX_CDTOR_CALLABI deleteException(void * exception) { // 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 + // from 8 to 16); the "header1" hack below 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 mapException is // unaffected, as it only accesses members towards the start of the struct, - // through a pointer known to actually point at the start): + // 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 the "header1" hack can be removed again once we can be + // sure that we only run against libcxxabi from LLVM >= 6. + // + // Second, the libcxxabi commit + // <https://github.com/llvm/llvm-project/commit/674ec1eb16678b8addc02a4b0534ab383d22fa77> + // "[libcxxabi] Insert padding in __cxa_exception struct for compatibility" in LLVM 10 changed + // the layout of the start of __cxa_exception to + // + // [8 byte void *reserve] + // 8 byte size_t referenceCount + // + // so the "header2" hack below to dynamically determine whether we run against a LLVM >= 10 + // libcxxabi is to look whether the exceptionDestructor (with its known value) has increased its + // offset by 8. As described in the definition of __cxa_exception + // (bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx), the "header2" hack (together with the + // "#ifdef MACOSX" in the definition of __cxa_exception and the corresponding hack in call in + // bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx) can be dropped once we can be sure + // that we only run against new libcxxabi that has the reserve member. if (header->exceptionDestructor != &deleteException) { - header = reinterpret_cast<__cxxabiv1::__cxa_exception *>( + auto const header1 = reinterpret_cast<__cxxabiv1::__cxa_exception *>( reinterpret_cast<char *>(header) - 8); - assert(header->exceptionDestructor == &deleteException); + if (header1->exceptionDestructor == &deleteException) { + header = header1; + } else { + auto const header2 = reinterpret_cast<__cxxabiv1::__cxa_exception *>( + reinterpret_cast<char *>(header) + 8); + if (header2->exceptionDestructor == &deleteException) { + header = header2; + } else { + assert(false); + } + } } #endif + assert(header->exceptionDestructor == &deleteException); OUString unoName(toUnoName(header->exceptionType->name())); - typelib_TypeDescription * td = 0; + typelib_TypeDescription * td = nullptr; typelib_typedescription_getByName(&td, unoName.pData); - assert(td != 0); + assert(td != nullptr); uno_destructData(exception, td, &css::uno::cpp_release); typelib_typedescription_release(td); } @@ -172,7 +213,7 @@ enum StructKind { }; StructKind getStructKind(typelib_CompoundTypeDescription const * type) { - StructKind k = type->pBaseTypeDescription == 0 + StructKind k = type->pBaseTypeDescription == nullptr ? STRUCT_KIND_EMPTY : getStructKind(type->pBaseTypeDescription); for (sal_Int32 i = 0; i != type->nMembers; ++i) { StructKind k2 = StructKind(); @@ -204,7 +245,7 @@ StructKind getStructKind(typelib_CompoundTypeDescription const * type) { break; case typelib_TypeClass_STRUCT: { - typelib_TypeDescription * td = 0; + typelib_TypeDescription * td = nullptr; TYPELIB_DANGER_GET(&td, type->ppTypeRefs[i]); k2 = getStructKind( reinterpret_cast<typelib_CompoundTypeDescription const *>( @@ -247,12 +288,12 @@ namespace abi_aarch64 { void mapException( __cxxabiv1::__cxa_exception * exception, std::type_info const * type, uno_Any * any, uno_Mapping * mapping) { - assert(exception != 0); + assert(exception != nullptr); assert(type != nullptr); OUString unoName(toUnoName(type->name())); - typelib_TypeDescription * td = 0; + typelib_TypeDescription * td = nullptr; typelib_typedescription_getByName(&td, unoName.pData); - if (td == 0) { + if (td == nullptr) { css::uno::RuntimeException e("exception type not found: " + unoName); uno_type_any_constructAndConvert( any, &e, @@ -265,15 +306,15 @@ void mapException( } void raiseException(uno_Any * any, uno_Mapping * mapping) { - typelib_TypeDescription * td = 0; + typelib_TypeDescription * td = nullptr; TYPELIB_DANGER_GET(&td, any->pType); - if (td == 0) { + if (td == nullptr) { throw css::uno::RuntimeException( - "no typedescription for " + OUString(any->pType->pTypeName)); + "no typedescription for " + OUString::unacquired(&any->pType->pTypeName)); } void * exc = __cxxabiv1::__cxa_allocate_exception(td->nSize); uno_copyAndConvertData(exc, any->pData, td, mapping); - uno_any_destruct(any, 0); + uno_any_destruct(any, nullptr); std::type_info * rtti = getRtti(*td); TYPELIB_DANGER_RELEASE(td); __cxxabiv1::__cxa_throw(exc, rtti, deleteException); @@ -283,7 +324,9 @@ 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: diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx index e3dc9b5872a7..10495582dcc0 100644 --- a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_AARCH64_ABI_HXX -#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_AARCH64_ABI_HXX +#pragma once #include <sal/config.h> @@ -71,6 +70,20 @@ namespace __cxxabiv1 { struct __cxa_exception { #if defined _LIBCPPABI_VERSION // detect libc++abi #if defined __LP64__ || LIBCXXABI_ARM_EHABI +#ifdef MACOSX // on arm64 + // 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". For non-MACOSX, + // the HACK in call (bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.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 "#ifdef MACOSX" here and drop the + // hack in call. + + // 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 std::size_t referenceCount; #endif #endif @@ -102,7 +115,7 @@ struct __cxa_eh_globals { #if !HAVE_CXXABI_H_CXA_GET_GLOBALS namespace __cxxabiv1 { -extern "C" __cxa_eh_globals * __cxa_get_globals() throw(); +extern "C" __cxa_eh_globals * __cxa_get_globals() noexcept; } #endif @@ -141,6 +154,4 @@ ReturnKind getReturnKind(typelib_TypeDescription const * type); } -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx index ba5194d6f8c8..b944f31cfd2a 100644 --- a/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx @@ -55,7 +55,7 @@ void callVirtualFunction( "m" (stackargs) // dummy input to prevent optimizing the alloca away : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", -#if !defined ANDROID +#if !defined ANDROID && !defined MACOSX "r18"/*TODO?*/, #endif "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.hxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.hxx index b1b003f413b9..a8b92785f479 100644 --- a/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.hxx +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_AARCH64_CALLVIRTUALFUNCTION_HXX -#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_AARCH64_CALLVIRTUALFUNCTION_HXX +#pragma once #include <sal/config.h> @@ -28,6 +27,4 @@ void callVirtualFunction( unsigned long function, unsigned long * gpr, unsigned long * fpr, unsigned long * stack, sal_Int32 sp, void * ret); -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx index f9396321cb14..669c4443c5f0 100644 --- a/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx @@ -24,6 +24,7 @@ #include <cstddef> #include <cstdlib> #include <cstring> +#include <typeinfo> #include <dlfcn.h> @@ -41,8 +42,7 @@ #include <vtablefactory.hxx> #include "abi.hxx" - -extern "C" void vtableSlotCall_(); +#include "vtablecall.hxx" namespace { @@ -53,16 +53,16 @@ void call( typelib_MethodParameter * parameters, unsigned long * gpr, unsigned long * fpr, unsigned long * stack, void * indirectRet) { - typelib_TypeDescription * rtd = 0; - if (returnType != 0) { + typelib_TypeDescription * rtd = nullptr; + if (returnType != nullptr) { TYPELIB_DANGER_GET(&rtd, returnType); } - abi_aarch64::ReturnKind retKind = rtd == 0 + abi_aarch64::ReturnKind retKind = rtd == nullptr ? abi_aarch64::RETURN_KIND_REG : abi_aarch64::getReturnKind(rtd); - bool retConv = rtd != 0 + bool retConv = rtd != nullptr && bridges::cpp_uno::shared::relatesToInterfaceType(rtd); void * retin = retKind == abi_aarch64::RETURN_KIND_INDIRECT && !retConv - ? indirectRet : rtd == 0 ? 0 : alloca(rtd->nSize); + ? indirectRet : rtd == nullptr ? nullptr : alloca(rtd->nSize); void ** args = static_cast< void ** >(alloca(count * sizeof (void *))); void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *))); typelib_TypeDescription ** argtds = static_cast<typelib_TypeDescription **>( @@ -70,11 +70,142 @@ void call( sal_Int32 ngpr = 1; sal_Int32 nfpr = 0; sal_Int32 sp = 0; +#ifdef MACOSX + sal_Int32 subsp = 0; +#endif for (sal_Int32 i = 0; i != count; ++i) { if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef)) { switch (parameters[i].pTypeRef->eTypeClass) { +#ifdef MACOSX + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + if (ngpr < 8) + { + args[i] = gpr + ngpr; + ngpr++; + } + else + { + args[i] = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(stack + sp) + subsp); + subsp += 1; + if (subsp == 8) + { + sp++; + subsp = 0; + } + } + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_CHAR: + if (ngpr < 8) + { + args[i] = gpr + ngpr; + ngpr++; + } + else + { + subsp = (subsp + 1) & ~0x1; + if (subsp == 8) + { + sp++; + subsp = 0; + } + args[i] = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(stack + sp) + subsp); + subsp += 2; + if (subsp == 8) + { + sp++; + subsp = 0; + } + } + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + if (ngpr < 8) + { + args[i] = gpr + ngpr; + ngpr++; + } + else + { + subsp = (subsp + 3) & ~0x3; + if (subsp == 8) + { + sp++; + subsp = 0; + } + args[i] = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(stack + sp) + subsp); + subsp += 4; + if (subsp == 8) + { + sp++; + subsp = 0; + } + } + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if (ngpr < 8) + { + args[i] = gpr + ngpr; + ngpr++; + } + else + { + if (subsp > 0) + { + sp++; + subsp = 0; + } + args[i] = stack + sp; + sp++; + } + break; + case typelib_TypeClass_FLOAT: + if (nfpr < 8) + { + args[i] = fpr + nfpr; + nfpr++; + } + else + { + subsp = (subsp + 3) & ~0x3; + if (subsp == 8) + { + sp++; + subsp = 0; + } + args[i] = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(stack + sp) + subsp); + subsp += 4; + if (subsp == 8) + { + sp++; + subsp = 0; + } + } + break; + case typelib_TypeClass_DOUBLE: + if (nfpr < 8) + { + args[i] = fpr + nfpr; + nfpr++; + } + else + { + if (subsp > 0) + { + sp++; + subsp = 0; + } + args[i] = stack + sp; + sp++; + } + break; +#else case typelib_TypeClass_BOOLEAN: case typelib_TypeClass_BYTE: case typelib_TypeClass_SHORT: @@ -91,14 +222,22 @@ void call( case typelib_TypeClass_DOUBLE: args[i] = nfpr == 8 ? stack + sp++ : fpr + nfpr++; break; +#endif default: assert(false); } - argtds[i] = 0; + argtds[i] = nullptr; } else { +#ifdef MACOSX + if (subsp > 0) + { + sp++; + subsp = 0; + } +#endif cppArgs[i] = reinterpret_cast<void *>( ngpr == 8 ? stack[sp++] : gpr[ngpr++]); - typelib_TypeDescription * ptd = 0; + typelib_TypeDescription * ptd = nullptr; TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef); if (!parameters[i].bIn) { args[i] = alloca(ptd->nSize); @@ -110,7 +249,7 @@ void call( argtds[i] = ptd; } else { args[i] = cppArgs[i]; - argtds[i] = 0; + argtds[i] = nullptr; TYPELIB_DANGER_RELEASE(ptd); } } @@ -119,22 +258,22 @@ void call( uno_Any * pexc = &exc; proxy->getUnoI()->pDispatcher( proxy->getUnoI(), description.get(), retin, args, &pexc); - if (pexc != 0) { + if (pexc != nullptr) { for (sal_Int32 i = 0; i != count; ++i) { - if (argtds[i] != 0) { + if (argtds[i] != nullptr) { if (parameters[i].bIn) { - uno_destructData(args[i], argtds[i], 0); + uno_destructData(args[i], argtds[i], nullptr); } TYPELIB_DANGER_RELEASE(argtds[i]); } } - if (rtd != 0) { + if (rtd != nullptr) { TYPELIB_DANGER_RELEASE(rtd); } abi_aarch64::raiseException(&exc, proxy->getBridge()->getUno2Cpp()); } for (sal_Int32 i = 0; i != count; ++i) { - if (argtds[i] != 0) { + if (argtds[i] != nullptr) { if (parameters[i].bOut) { uno_destructData( cppArgs[i], argtds[i], @@ -143,25 +282,53 @@ void call( cppArgs[i], args[i], argtds[i], proxy->getBridge()->getUno2Cpp()); } - uno_destructData(args[i], argtds[i], 0); + uno_destructData(args[i], argtds[i], nullptr); TYPELIB_DANGER_RELEASE(argtds[i]); } } - void * retout = 0; // avoid false -Werror=maybe-uninitialized + void * retout = nullptr; // avoid false -Werror=maybe-uninitialized switch (retKind) { case abi_aarch64::RETURN_KIND_REG: - switch (rtd == 0 ? typelib_TypeClass_VOID : rtd->eTypeClass) { + switch (rtd == nullptr ? typelib_TypeClass_VOID : rtd->eTypeClass) { case typelib_TypeClass_VOID: break; +#if defined MACOSX + case typelib_TypeClass_BOOLEAN: + assert(rtd->nSize == sizeof (bool)); + *gpr = static_cast<unsigned long>(*static_cast<bool *>(retin)); + assert(!retConv); + break; + case typelib_TypeClass_BYTE: + assert(rtd->nSize == sizeof (sal_Int8)); + *gpr = *static_cast<sal_Int8 *>(retin); + assert(!retConv); + break; + case typelib_TypeClass_SHORT: + assert(rtd->nSize == sizeof (sal_Int16)); + *gpr = *static_cast<sal_Int16 *>(retin); + assert(!retConv); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + assert(rtd->nSize == sizeof (sal_uInt16)); + *gpr = *static_cast<sal_uInt16 *>(retin); + assert(!retConv); + break; + case typelib_TypeClass_CHAR: + assert(rtd->nSize == sizeof (sal_Unicode)); + *gpr = *static_cast<sal_Unicode *>(retin); + assert(!retConv); + break; +#else case typelib_TypeClass_BOOLEAN: case typelib_TypeClass_BYTE: case typelib_TypeClass_SHORT: case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_CHAR: +#endif 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: std::memcpy(gpr, retin, rtd->nSize); assert(!retConv); @@ -183,7 +350,7 @@ void call( } break; case abi_aarch64::RETURN_KIND_HFA_FLOAT: - assert(rtd != 0); + assert(rtd != nullptr); switch (rtd->nSize) { case 16: std::memcpy(fpr + 3, static_cast<char *>(retin) + 12, 4); @@ -203,7 +370,7 @@ void call( assert(!retConv); break; case abi_aarch64::RETURN_KIND_HFA_DOUBLE: - assert(rtd != 0); + assert(rtd != nullptr); std::memcpy(fpr, retin, rtd->nSize); assert(!retConv); break; @@ -214,14 +381,16 @@ void call( if (retConv) { uno_copyAndConvertData( retout, retin, rtd, proxy->getBridge()->getUno2Cpp()); - uno_destructData(retin, rtd, 0); + uno_destructData(retin, rtd, nullptr); } - if (rtd != 0) { + if (rtd != nullptr) { TYPELIB_DANGER_RELEASE(rtd); } } -extern "C" void vtableCall( +} + +void vtableCall( sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned long * gpr, unsigned long * fpr, unsigned long * stack, void * indirectRet) @@ -241,15 +410,15 @@ extern "C" void vtableCall( proxy, desc, reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( desc.get())->pAttributeTypeRef, - 0, 0, gpr, fpr, stack, indirectRet); + 0, nullptr, gpr, fpr, stack, indirectRet); } else { // Setter: typelib_MethodParameter param = { - 0, + nullptr, reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( desc.get())->pAttributeTypeRef, true, false }; - call(proxy, desc, 0, 1, ¶m, gpr, fpr, stack, indirectRet); + call(proxy, desc, nullptr, 1, ¶m, gpr, fpr, stack, indirectRet); } break; case typelib_TypeClass_INTERFACE_METHOD: @@ -262,21 +431,21 @@ extern "C" void vtableCall( break; case 0: { - typelib_TypeDescription * td = 0; + typelib_TypeDescription * td = nullptr; TYPELIB_DANGER_GET( &td, (reinterpret_cast<css::uno::Type *>(gpr[1]) ->getTypeLibType())); - if (td != 0 && td->eTypeClass == typelib_TypeClass_INTERFACE) { - css::uno::XInterface * ifc = 0; + if (td != nullptr && td->eTypeClass == typelib_TypeClass_INTERFACE) { + css::uno::XInterface * ifc = nullptr; proxy->getBridge()->getCppEnv()->getRegisteredInterface( proxy->getBridge()->getCppEnv(), reinterpret_cast<void **>(&ifc), proxy->getOid().pData, reinterpret_cast<typelib_InterfaceTypeDescription *>( td)); - if (ifc != 0) { + if (ifc != nullptr) { uno_any_construct( - reinterpret_cast<uno_Any *>(indirectRet), &ifc, td, + static_cast<uno_Any *>(indirectRet), &ifc, td, reinterpret_cast<uno_AcquireFunc>( css::uno::cpp_acquire)); ifc->release(); @@ -304,63 +473,7 @@ extern "C" void vtableCall( } } -struct aarch64_va_list { - void * stack; - void * gr_top; - void * vr_top; - int gr_offs; - int vr_offs; -}; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" -#pragma GCC diagnostic ignored "-Wvolatile-register-var" -extern "C" void vtableSlotCall( - unsigned long gpr0, unsigned long gpr1, unsigned long gpr2, - unsigned long gpr3, unsigned long gpr4, unsigned long gpr5, - unsigned long gpr6, unsigned long gpr7, double fpr0, double fpr1, - double fpr2, double fpr3, double fpr4, double fpr5, double fpr6, - double fpr7, ...) -{ - register void * volatile indirectRet asm ("x8"); - register sal_Int32 volatile functionIndex asm ("x9"); - register sal_Int32 volatile vtableOffset asm ("x10"); - va_list ap; - va_start(ap, fpr7); - assert(sizeof (va_list) == sizeof (aarch64_va_list)); - unsigned long gpr[8]; - gpr[0] = gpr0; - gpr[1] = gpr1; - gpr[2] = gpr2; - gpr[3] = gpr3; - gpr[4] = gpr4; - gpr[5] = gpr5; - gpr[6] = gpr6; - gpr[7] = gpr7; - double fpr[8]; - fpr[0] = fpr0; - fpr[1] = fpr1; - fpr[2] = fpr2; - fpr[3] = fpr3; - fpr[4] = fpr4; - fpr[5] = fpr5; - fpr[6] = fpr6; - fpr[7] = fpr7; - vtableCall( - functionIndex, vtableOffset, gpr, - reinterpret_cast<unsigned long *>(fpr), - static_cast<unsigned long *>( - reinterpret_cast<aarch64_va_list *>(&ap)->stack), - indirectRet); - asm volatile( - "ldp x0, x1, [%[gpr_]]\n\t" - "ldp d0, d1, [%[fpr_]]\n\t" - "ldp d2, d3, [%[fpr_], #16]\n\t" - :: [gpr_]"r" (gpr), [fpr_]"r" (fpr) - : "r0", "r1", "v0", "v1", "v2", "v3"); - va_end(ap); -} -#pragma GCC diagnostic pop +namespace { std::size_t const codeSnippetSize = 8 * 4; @@ -390,7 +503,7 @@ unsigned char * generateCodeSnippet( } -struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; +struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; }; bridges::cpp_uno::shared::VtableFactory::Slot * bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) { @@ -403,28 +516,40 @@ std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize( return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; } +namespace { +// Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast +// on such proxy objects not crash: +struct ProxyRtti {}; +} + 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; + slots[-2].fn = nullptr; + slots[-1].fn = &typeid(ProxyRtti); return slots + slotCount; } unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( - Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + Slot ** slots, unsigned char * code, +#ifdef USE_DOUBLE_MMAP + sal_PtrDiff writetoexecdiff, +#endif typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, sal_Int32 functionCount, sal_Int32 vtableOffset) { +#ifndef USE_DOUBLE_MMAP + constexpr sal_PtrDiff writetoexecdiff = 0; +#endif (*slots) -= functionCount; Slot * s = *slots; for (sal_Int32 i = 0; i != type->nMembers; ++i) { - typelib_TypeDescription * td = 0; + typelib_TypeDescription * td = nullptr; TYPELIB_DANGER_GET(&td, type->ppMembers[i]); - assert(td != 0); + assert(td != nullptr); switch (td->eTypeClass) { case typelib_TypeClass_INTERFACE_ATTRIBUTE: { @@ -458,13 +583,23 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( void bridges::cpp_uno::shared::VtableFactory::flushCode( unsigned char const * begin, unsigned char const * end) { -#ifndef ANDROID +#if !defined ANDROID && !defined MACOSX static void (*clear_cache)(unsigned char const *, unsigned char const *) = (void (*)(unsigned char const *, unsigned char const *)) dlsym( RTLD_DEFAULT, "__clear_cache"); (*clear_cache)(begin, end); #else - __builtin___clear_cache((char*)begin, (char*)end); + // GCC clarified with + // <http://gcc.gnu.org/git/?p=gcc.git;a=commit;h=a90b0cdd444f6dde1084a439862cf507f6d3b2ae> + // "extend.texi (__clear_cache): Correct signature" that __builtin___clear_cache takes void* + // parameters, while Clang uses char* ever since + // <https://github.com/llvm/llvm-project/commit/c491a8d4577052bc6b3b4c72a7db6a7cfcbc2ed0> "Add + // support for __builtin___clear_cache in Clang" (TODO: see + // <https://bugs.llvm.org/show_bug.cgi?id=48489> "__builtin___clear_cache() has a different + // prototype than GCC"; once fixed for our Clang baseline, we can drop the reinterpret_casts): + __builtin___clear_cache( + reinterpret_cast<char *>(const_cast<unsigned char *>(begin)), + reinterpret_cast<char *>(const_cast<unsigned char *>(end))); #endif } diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx index d1928942eb06..57beb6dfa106 100644 --- a/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx @@ -46,10 +46,82 @@ namespace { void pushArgument( - unsigned long value, unsigned long * stack, sal_Int32 * sp, - unsigned long * regs, sal_Int32 * nregs) +#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( @@ -59,7 +131,7 @@ void call( typelib_MethodParameter * parameters, void * returnValue, void ** arguments, uno_Any ** exception) { - typelib_TypeDescription * rtd = 0; + 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); @@ -69,6 +141,9 @@ void call( 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]; @@ -82,61 +157,94 @@ void call( if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef)) { - cppArgs[i] = 0; + cppArgs[i] = nullptr; switch (parameters[i].pTypeRef->eTypeClass) { case typelib_TypeClass_BOOLEAN: pushArgument( - *static_cast<sal_Bool *>(arguments[i]), stack, &sp, gpr, - &ngpr); +#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; @@ -144,13 +252,16 @@ void call( assert(false); } } else { - typelib_TypeDescription * ptd = 0; + 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)) { @@ -160,11 +271,17 @@ void call( 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] = 0; + 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); @@ -187,13 +304,42 @@ void call( "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( - reinterpret_cast<__cxxabiv1::__cxa_eh_globals *>( - __cxxabiv1::__cxa_get_globals())->caughtExceptions, + header, __cxxabiv1::__cxa_current_exception_type(), *exception, proxy->getBridge()->getCpp2Uno()); for (sal_Int32 i = 0; i != count; ++i) { - if (cppArgs[i] != 0) { + if (cppArgs[i] != nullptr) { uno_destructData( cppArgs[i], ptds[i], reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release)); @@ -203,12 +349,12 @@ void call( TYPELIB_DANGER_RELEASE(rtd); return; } - *exception = 0; + *exception = nullptr; for (sal_Int32 i = 0; i != count; ++i) { - if (cppArgs[i] != 0) { + if (cppArgs[i] != nullptr) { if (parameters[i].bOut) { if (parameters[i].bIn) { - uno_destructData(arguments[i], ptds[i], 0); + uno_destructData(arguments[i], ptds[i], nullptr); } uno_copyAndConvertData( arguments[i], cppArgs[i], ptds[i], @@ -296,14 +442,14 @@ void unoInterfaceProxyDispatch( typelib_InterfaceAttributeTypeDescription const *>( pMemberDescr); VtableSlot slot(getVtableSlot(atd)); - if (pReturn != 0) { // getter + if (pReturn != nullptr) { // getter call( - proxy, slot, atd->pAttributeTypeRef, 0, 0, pReturn, pArgs, + proxy, slot, atd->pAttributeTypeRef, 0, nullptr, pReturn, pArgs, ppException); } else { // setter typelib_MethodParameter param = { - 0, atd->pAttributeTypeRef, true, false }; - typelib_TypeDescriptionReference * rtd = 0; + nullptr, atd->pAttributeTypeRef, true, false }; + typelib_TypeDescriptionReference * rtd = nullptr; typelib_typedescriptionreference_new( &rtd, typelib_TypeClass_VOID, OUString("void").pData); slot.index += 1; @@ -322,33 +468,33 @@ void unoInterfaceProxyDispatch( switch (slot.index) { case 1: pUnoI->acquire(pUnoI); - *ppException = 0; + *ppException = nullptr; break; case 2: pUnoI->release(pUnoI); - *ppException = 0; + *ppException = nullptr; break; case 0: { - typelib_TypeDescription * td = 0; + typelib_TypeDescription * td = nullptr; TYPELIB_DANGER_GET( &td, - (reinterpret_cast<css::uno::Type *>(pArgs[0]) + (static_cast<css::uno::Type *>(pArgs[0]) ->getTypeLibType())); - if (td != 0) { - uno_Interface * ifc = 0; + 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 != 0) { + if (ifc != nullptr) { uno_any_construct( - reinterpret_cast<uno_Any *>(pReturn), &ifc, td, - 0); + static_cast<uno_Any *>(pReturn), &ifc, td, + nullptr); ifc->release(ifc); TYPELIB_DANGER_RELEASE(td); - *ppException = 0; + *ppException = nullptr; break; } TYPELIB_DANGER_RELEASE(td); diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/vtablecall.hxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/vtablecall.hxx new file mode 100644 index 000000000000..6ec92687c4ae --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/vtablecall.hxx @@ -0,0 +1,33 @@ +/* -*- 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 . + */ + +#pragma once + +#include <sal/config.h> + +#include <sal/types.h> + +extern "C" { +void vtableCall(sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned long* gpr, + unsigned long* fpr, unsigned long* stack, void* indirectRet); + +void vtableSlotCall(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/vtableslotcall.s b/bridges/source/cpp_uno/gcc3_linux_aarch64/vtableslotcall.s new file mode 100644 index 000000000000..60bdb4c9cf4e --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/vtableslotcall.s @@ -0,0 +1,83 @@ +/* -*- tab-width: 4; indent-tabs-mode: nil; 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 . + */ + + .arch armv8-a + .text + .align 2 +#ifndef __APPLE__ + .global vtableSlotCall + .hidden vtableSlotCall + .type vtableSlotCall, %function +vtableSlotCall: +#else + .global _vtableSlotCall +_vtableSlotCall: +#endif + .cfi_startproc + stp x29, x30, [sp, -192]! + .cfi_def_cfa_offset 192 + .cfi_offset 29, -192 + .cfi_offset 30, -184 + add x11, sp, 192 + mov x29, sp + stp x19, x20, [sp, 16] + .cfi_offset 19, -176 + .cfi_offset 20, -168 + add x20, sp, 128 + add x19, sp, 64 + stp x11, x11, [sp, 32] + str x11, [sp, 48] + stp wzr, wzr, [sp, 56] + stp x0, x1, [sp, 64] + mov w0, w9 + mov w1, w10 + stp x2, x3, [sp, 80] + mov x3, x20 + mov x2, x19 + stp x4, x5, [sp, 96] + mov x5, x8 + mov x4, x11 + stp x6, x7, [sp, 112] + stp d0, d1, [sp, 128] + stp d2, d3, [sp, 144] + stp d4, d5, [sp, 160] + stp d6, d7, [sp, 176] +#ifndef __APPLE__ + bl vtableCall +#else + bl _vtableCall +#endif + ldp x0, x1, [x19] + ldp d0, d1, [x20] + ldp d2, d3, [x20, #16] + ldp x19, x20, [sp, 16] + ldp x29, x30, [sp], 192 + .cfi_restore 30 + .cfi_restore 29 + .cfi_restore 19 + .cfi_restore 20 + .cfi_def_cfa_offset 0 + ret + .cfi_endproc +#ifndef __APPLE__ + .size vtableSlotCall, .-vtableSlotCall + .section .note.GNU-stack, "", @progbits +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab */ |