Outstanding work Jim. Thank you so much.

On Fri, Jun 5, 2026 at 5:13 PM Dave Fisher <[email protected]> wrote:

> I want to highlight the two hugely important contributions in this commit.
>
> 1. Native Apple Silicon support.
> 2. Python 3.10 support.
>
> A big thanks to Jim!
>
> Best,
> Dave
>
> > On Jun 5, 2026, at 8:46 AM, [email protected] wrote:
> >
> > This is an automated email from the ASF dual-hosted git repository.
> >
> > jimjag pushed a commit to branch trunk
> > in repository https://gitbox.apache.org/repos/asf/openoffice.git
> >
> >
> > The following commit(s) were added to refs/heads/trunk by this push:
> >     new 5e139d9fe4 Native Apple Silicon (arm64) support and bundled
> Python 3.10 baseline
> > 5e139d9fe4 is described below
> >
> > commit 5e139d9fe42a654147771da4118aea6285c03168
> > Author: Jim Jagielski <[email protected]>
> > AuthorDate: Fri Jun 5 09:44:36 2026 -0400
> >
> >    Native Apple Silicon (arm64) support and bundled Python 3.10 baseline
> >
> >    Squashed combination of two efforts, applied onto trunk as a single
> >    commit. (trunk is not intended to be buildable; this lands the work
> for
> >    reference/integration.)
> >
> >    === Apple Silicon (macOS arm64 / AAPCS64) ===
> >    Build plumbing: set_soenv.in + source_soenv.sh arm64 Darwin branch
> >    (CPU=R, CPUNAME=AARCH64, OUTPATH=unxmaccr); new solenv/inc/
> unxmaccr.mk
> >    and unx.mk dispatch; macro.hxx AARCH64 arch string; osarch.pm +
> >    gbuild/platform/macosx.mk arch entries; configure.ac arm64 host
> >    detection, Big Sur+ version math, and 11.0 deployment target.
> >
> >    C++/UNO bridge (new s5abi_macosx_aarch64): abi.cxx/hxx AAPCS64
> classifier
> >    (HFA + <=16B/>16B size rules), uno2cpp + call.s AArch64 trampoline,
> >    cpp2uno incoming path + privateSnippetExecutor + AArch64 codeSnippet
> >    codegen (x8 indirect-result handled, not displacing this/x0),
> share.hxx
> >    __cxa_exception reserved-member alignment fix; Library_cpp_uno.mk +
> >    makefile.mk wiring. sal/osl/unx/interlck.c arm64 atomics (__sync_* ->
> >    LSE).
> >
> >    Externals: openssl darwin64-arm64-cc; icu arm64 little-endian. (NSS
> 3.39
> >    deferred -- too old for arm64.)
> >
> >    Packaging/JVM: Info.plist LSMinimumSystemVersion 11.0; installer
> >    download.pm/worker.pm/update_module_ignore_lists.pl recognize
> unxmaccr;
> >    jvmfwk modern macOS JDK discovery (/Library/Java/JavaVirtualMachines +
> >    Contents/Home probe).
> >
> >    The ABI/atomics/trampoline/JDK-discovery code was unit-tested natively
> >    on an arm64 macOS host; a full AOO build (and bridgetest) was not run.
> >    Code-signing infra (mandatory for arm64 distribution) is NOT included.
> >
> >    === Bundled Python 2.7.18 -> 3.10 baseline (Unix/macOS first) ===
> >    pyversion.mk/_dmake.mk -> 3.10.18 (single version knob). Shipped .py
> >    fixes: imp -> types.ModuleType (pythonscript.py, pythonloader.py) and
> >    file() -> open(); mailmerge.py Py3 email module imports + encoders.
> >    Windows Python 3 build and the makefile.mk/d.lst/configure.ac Py3
> work
> >    are NOT included (separate, larger effort).
> >
> >    NOTE: macOS 11 becomes the minimum supported version. Python 3.10 is
> >    EOL 2026-10; the version knob allows a later bump.
> > ---
> > main/bridges/Library_cpp_uno.mk                    |  18 +
> > .../source/cpp_uno/s5abi_macosx_aarch64/abi.cxx    | 261 +++++++++
> > .../source/cpp_uno/s5abi_macosx_aarch64/abi.hxx    |  86 +++
> > .../source/cpp_uno/s5abi_macosx_aarch64/call.s     | 168 ++++++
> > .../cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx       | 543
> +++++++++++++++++++
> > .../source/cpp_uno/s5abi_macosx_aarch64/except.cxx | 358 +++++++++++++
> > .../cpp_uno/s5abi_macosx_aarch64/makefile.mk       |  81 +++
> > .../source/cpp_uno/s5abi_macosx_aarch64/share.hxx  | 116 ++++
> > .../cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx       | 581
> +++++++++++++++++++++
> > main/configure.ac                                  |  42 +-
> > main/icu/icu4c-4_2_1-src.patch                     |   2 +-
> > main/jvmfwk/plugins/sunmajor/pluginlib/util.cxx    |  14 +
> > main/openssl/makefile.mk                           |   4 +
> > main/python/pyversion.mk                           |   4 +-
> > main/python/pyversion_dmake.mk                     |   4 +-
> > main/pyuno/source/loader/pythonloader.py           |   6 +-
> > main/sal/osl/unx/interlck.c                        |  23 +
> > main/sal/rtl/source/macro.hxx                      |   2 +
> > main/scripting/source/pyprov/mailmerge.py          |  16 +-
> > main/scripting/source/pyprov/pythonscript.py       |  10 +-
> > main/set_soenv.in                                  |   8 +
> > main/setup_native/source/mac/Info.plist.langpack   |   2 +-
> > main/solenv/bin/modules/installer/download.pm      |   4 +
> > main/solenv/bin/modules/installer/worker.pm        |   4 +
> > main/solenv/bin/modules/osarch.pm                  |  12 +-
> > main/solenv/bin/update_module_ignore_lists.pl      |   1 +
> > main/solenv/gbuild/platform/macosx.mk              |   2 +
> > main/solenv/inc/unx.mk                             |   4 +
> > main/solenv/inc/unxmaccr.mk                        |  42 ++
> > main/source_soenv.sh                               |   3 +
> > main/sysui/desktop/macosx/Info.plist               |   2 +-
> > 31 files changed, 2391 insertions(+), 32 deletions(-)
> >
> > diff --git a/main/bridges/Library_cpp_uno.mk b/main/bridges/Library_cpp_
> uno.mk
> > index d868df954f..0d8525362a 100644
> > --- a/main/bridges/Library_cpp_uno.mk
> > +++ b/main/bridges/Library_cpp_uno.mk
> > @@ -431,6 +431,24 @@ $(eval $(call
> gb_Library_add_exception_objects,$(COMNAME)_uno,\
> >       bridges/source/cpp_uno/s5abi_macosx_x86-64/uno2cpp \
> > ))
> >
> > +###########################################################
> > +else ifeq ($(OS)-$(CPUNAME)-$(COMNAME),MACOSX-AARCH64-s5abi)
> > +###########################################################
> > +# Apple Silicon (arm64) bridge. The COMNAME is "s5abi" macOS-wide (set
> in
> > +# solenv/gbuild/platform/macosx.mk); for arm64 the actual calling
> convention
> > +# is AAPCS64, so "s5abi" here is a historical label, not a literal ABI
> claim.
> > +
> > +$(eval $(call gb_Library_add_exception_objects,$(COMNAME)_uno,\
> > +     bridges/source/cpp_uno/s5abi_macosx_aarch64/abi \
> > +     bridges/source/cpp_uno/s5abi_macosx_aarch64/except \
> > +     bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno \
> > +     bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp \
> > +))
> > +
> > +$(eval $(call gb_Library_add_asmobjects,$(COMNAME)_uno,\
> > +     bridges/source/cpp_uno/s5abi_macosx_aarch64/call \
> > +))
> > +
> > #########################################################
> > else ifeq ($(OS)-$(CPUNAME)-$(COMNAME),NETBSD-INTEL-gcc3)
> > #########################################################
> > diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.cxx
> b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.cxx
> > new file mode 100644
> > index 0000000000..d51c5ccf12
> > --- /dev/null
> > +++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.cxx
> > @@ -0,0 +1,261 @@
> > +/**************************************************************
> > + *
> > + * 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
> > + *
> > + * Unless required by applicable law or agreed to in writing,
> > + * software distributed under the License is distributed on an
> > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> > + * KIND, either express or implied.  See the License for the
> > + * specific language governing permissions and limitations
> > + * under the License.
> > + *
> > + *************************************************************/
> > +
> > +
> > +
> > +// MARKER(update_precomp.py): autogen include statement, do not remove
> > +#include "precompiled_bridges.hxx"
> > +
> > +// This is an implementation of the parameter-classification rules of
> the
> > +// AArch64 procedure call standard ("Procedure Call Standard for the
> Arm 64-bit
> > +// Architecture", ARM IHI 0055), with the deviations documented in
> Apple's
> > +// "Writing ARM64 Code for Apple Platforms".
> > +//
> > +// Unlike the System V AMD64 ABI (used by the x86-64 bridge), AAPCS64
> does not
> > +// split aggregates into per-eightbyte INTEGER/SSE classes.  Instead:
> > +//   * scalars go in one GPR (x) or one FP/SIMD (v) register;
> > +//   * a Homogeneous Floating-point Aggregate (HFA: <= 4 members, all
> the same
> > +//     FP type, recursively) goes in consecutive v registers;
> > +//   * any other aggregate <= 16 bytes goes in 1-2 GPRs;
> > +//   * a non-HFA aggregate > 16 bytes is passed indirectly (a pointer
> to a
> > +//     caller-allocated copy).
> > +// Register fill is "all or nothing": if an aggregate does not fit
> entirely in
> > +// the remaining registers of its bank, it is passed wholly on the
> stack.
> > +//
> > +// This is a clean-room implementation from the public specifications;
> see
> > +// ../../../../AAPCS64_BRIDGE_SPEC.md.  libffi's aarch64 backend was
> consulted
> > +// only as a behavioural reference; no code is copied.
> > +
> > +#include "abi.hxx"
> > +
> > +#include <rtl/ustring.hxx>
> > +
> > +using namespace aarch64;
> > +
> > +namespace {
> > +
> > +// The element type of a Homogeneous Floating-point Aggregate.
> > +enum HfaKind
> > +{
> > +    HFA_NONE,       // not (yet) an HFA
> > +    HFA_FLOAT,      // all members are FLOAT (4-byte)
> > +    HFA_DOUBLE      // all members are DOUBLE (8-byte)
> > +};
> > +
> > +// Combine the running HFA kind with a newly-seen member kind.  Two
> members
> > +// of different FP types, or any non-FP member, break the homogeneity.
> > +HfaKind mergeHfa( HfaKind running, HfaKind seen )
> > +{
> > +    if ( seen == HFA_NONE )
> > +        return HFA_NONE;
> > +    if ( running == HFA_NONE )
> > +        return seen;
> > +    return ( running == seen ) ? running : HFA_NONE;
> > +}
> > +
> > +// Recursively determine whether pTypeRef is (part of) a homogeneous
> > +// floating-point aggregate, accumulating the element kind and member
> count.
> > +//
> > +// Returns false the moment homogeneity is violated (a non-FP scalar,
> or a
> > +// second distinct FP type, or > 4 elements).  A FLOAT/DOUBLE scalar
> counts as
> > +// a 1-element HFA of itself; a struct flattens its members (and base
> classes).
> > +bool collectHfa( typelib_TypeDescriptionReference *pTypeRef, HfaKind
> &rKind, int &rCount )
> > +{
> > +    switch ( pTypeRef->eTypeClass )
> > +    {
> > +        case typelib_TypeClass_FLOAT:
> > +            rKind = mergeHfa( rKind, HFA_FLOAT );
> > +            if ( rKind == HFA_NONE ) return false;
> > +            return ( ++rCount <= 4 );
> > +
> > +        case typelib_TypeClass_DOUBLE:
> > +            rKind = mergeHfa( rKind, HFA_DOUBLE );
> > +            if ( rKind == HFA_NONE ) return false;
> > +            return ( ++rCount <= 4 );
> > +
> > +        case typelib_TypeClass_STRUCT:
> > +        case typelib_TypeClass_EXCEPTION:
> > +        {
> > +            typelib_TypeDescription * pTypeDescr = 0;
> > +            TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
> > +
> > +            const typelib_CompoundTypeDescription *pComp =
> > +                reinterpret_cast<const
> typelib_CompoundTypeDescription*>( pTypeDescr );
> > +
> > +            bool bOk = true;
> > +
> > +            // Flatten base class first (its members precede ours in
> layout).
> > +            if ( pComp->pBaseTypeDescription )
> > +            {
> > +                bOk = collectHfa(
> > +                    pComp->pBaseTypeDescription->aBase.pWeakRef, rKind,
> rCount );
> > +            }
> > +
> > +            for ( sal_Int32 i = 0; bOk && i < pComp->nMembers; ++i )
> > +                bOk = collectHfa( pComp->ppTypeRefs[i], rKind, rCount );
> > +
> > +            TYPELIB_DANGER_RELEASE( pTypeDescr );
> > +            return bOk;
> > +        }
> > +
> > +        default:
> > +            // Any non-FP, non-aggregate member breaks homogeneity.
> > +            rKind = HFA_NONE;
> > +            return false;
> > +    }
> > +}
> > +
> > +// Classify an aggregate (STRUCT/EXCEPTION).  Sets the GPR/FPR counts
> and
> > +// returns true if it is passed in registers, false if it must be passed
> > +// indirectly (in memory).
> > +bool classifyAggregate( typelib_TypeDescriptionReference *pTypeRef, int
> &nUsedGPR, int &nUsedFPR )
> > +{
> > +    // First, the HFA test.
> > +    HfaKind kind = HFA_NONE;
> > +    int count = 0;
> > +    if ( collectHfa( pTypeRef, kind, count ) && kind != HFA_NONE &&
> count >= 1 && count <= 4 )
> > +    {
> > +        nUsedGPR = 0;
> > +        nUsedFPR = count;       // one v register per member
> > +        return true;
> > +    }
> > +
> > +    // Otherwise classify by size.
> > +    typelib_TypeDescription * pTypeDescr = 0;
> > +    TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
> > +    sal_Int32 nSize = pTypeDescr->nSize;
> > +    TYPELIB_DANGER_RELEASE( pTypeDescr );
> > +
> > +    if ( nSize > 16 )
> > +    {
> > +        // Non-HFA aggregate > 16 bytes => passed indirectly.
> > +        return false;
> > +    }
> > +
> > +    // Non-HFA aggregate <= 16 bytes => 1 or 2 GPRs (8 bytes each).
> > +    nUsedGPR = ( nSize > 8 ) ? 2 : 1;
> > +    nUsedFPR = 0;
> > +    return true;
> > +}
> > +
> > +} // anonymous namespace
> > +
> > +bool aarch64::examine_argument( typelib_TypeDescriptionReference
> *pTypeRef, bool /*bInReturn*/, int &nUsedGPR, int &nUsedFPR )
> > +{
> > +    nUsedGPR = 0;
> > +    nUsedFPR = 0;
> > +
> > +    switch ( pTypeRef->eTypeClass )
> > +    {
> > +        case typelib_TypeClass_VOID:
> > +            return true;
> > +
> > +        case typelib_TypeClass_CHAR:
> > +        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_ENUM:
> > +            nUsedGPR = 1;
> > +            return true;
> > +
> > +        case typelib_TypeClass_FLOAT:
> > +        case typelib_TypeClass_DOUBLE:
> > +            nUsedFPR = 1;
> > +            return true;
> > +
> > +        // These UNO types are always handled by the bridge as a
> pointer/
> > +        // reference (one GPR), never passed by value through this
> classifier.
> > +        case typelib_TypeClass_STRING:
> > +        case typelib_TypeClass_TYPE:
> > +        case typelib_TypeClass_ANY:
> > +        case typelib_TypeClass_TYPEDEF:
> > +        case typelib_TypeClass_SEQUENCE:
> > +        case typelib_TypeClass_INTERFACE:
> > +            nUsedGPR = 1;
> > +            return true;
> > +
> > +        case typelib_TypeClass_STRUCT:
> > +        case typelib_TypeClass_EXCEPTION:
> > +            return classifyAggregate( pTypeRef, nUsedGPR, nUsedFPR );
> > +
> > +        default:
> > +#if OSL_DEBUG_LEVEL > 1
> > +            OSL_TRACE( "Unhandled case: pTypeRef->eTypeClass == %d\n",
> pTypeRef->eTypeClass );
> > +#endif
> > +            OSL_ASSERT( 0 );
> > +    }
> > +    return false;
> > +}
> > +
> > +bool aarch64::return_in_hidden_param( typelib_TypeDescriptionReference
> *pTypeRef )
> > +{
> > +    int g, s;
> > +    // Returned in registers iff examine_argument() says it fits;
> otherwise the
> > +    // caller must pass an indirect-result buffer in x8.
> > +    return !examine_argument( pTypeRef, true, g, s );
> > +}
> > +
> > +void aarch64::fill_struct( typelib_TypeDescriptionReference *pTypeRef,
> const sal_uInt64 *pGPR, const double *pFPR, void *pStruct )
> > +{
> > +    int nUsedGPR = 0;
> > +    int nUsedFPR = 0;
> > +    if ( !examine_argument( pTypeRef, true, nUsedGPR, nUsedFPR ) )
> > +    {
> > +        // Should not happen: indirect returns are written through x8
> directly,
> > +        // not scattered here.
> > +        OSL_ASSERT( 0 );
> > +        return;
> > +    }
> > +
> > +    if ( nUsedFPR > 0 )
> > +    {
> > +        // HFA: each member occupies one v register; the members are
> contiguous
> > +        // in the struct.  Copy element-by-element to honour FLOAT
> (4-byte) vs
> > +        // DOUBLE (8-byte) element width.
> > +        HfaKind kind = HFA_NONE;
> > +        int count = 0;
> > +        collectHfa( pTypeRef, kind, count );
> > +        if ( kind == HFA_FLOAT )
> > +        {
> > +            float *pDest = reinterpret_cast<float *>( pStruct );
> > +            for ( int i = 0; i < nUsedFPR; ++i )
> > +                pDest[i] = static_cast<float>( pFPR[i] );
> > +        }
> > +        else // HFA_DOUBLE
> > +        {
> > +            double *pDest = reinterpret_cast<double *>( pStruct );
> > +            for ( int i = 0; i < nUsedFPR; ++i )
> > +                pDest[i] = pFPR[i];
> > +        }
> > +    }
> > +    else
> > +    {
> > +        // Non-HFA aggregate <= 16 bytes: raw copy of the 1-2 GPRs.
> > +        sal_uInt64 *pDest = reinterpret_cast<sal_uInt64 *>( pStruct );
> > +        for ( int i = 0; i < nUsedGPR; ++i )
> > +            pDest[i] = pGPR[i];
> > +    }
> > +}
> > diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.hxx
> b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.hxx
> > new file mode 100644
> > index 0000000000..7d55ac076c
> > --- /dev/null
> > +++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.hxx
> > @@ -0,0 +1,86 @@
> > +/**************************************************************
> > + *
> > + * 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
> > + *
> > + * Unless required by applicable law or agreed to in writing,
> > + * software distributed under the License is distributed on an
> > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> > + * KIND, either express or implied.  See the License for the
> > + * specific language governing permissions and limitations
> > + * under the License.
> > + *
> > + *************************************************************/
> > +
> > +
> > +
> > +#ifndef _BRIDGES_CPP_UNO_AARCH64_ABI_HXX_
> > +#define _BRIDGES_CPP_UNO_AARCH64_ABI_HXX_
> > +
> > +// This is an implementation of the AArch64 procedure call standard, as
> > +// described in "Procedure Call Standard for the Arm 64-bit
> Architecture"
> > +// (ARM IHI 0055), with the deviations documented in Apple's "Writing
> ARM64
> > +// Code for Apple Platforms".  It is a clean-room implementation
> written from
> > +// those public specifications; see ../../../../AAPCS64_BRIDGE_SPEC.md.
> > +
> > +#include <typelib/typedescription.hxx>
> > +
> > +namespace aarch64
> > +{
> > +
> > +/* 8 general purpose registers (x0..x7) are used for parameter passing.
> > +   Note: the indirect-result-location register x8 is *separate* and is
> NOT
> > +   part of this count. */
> > +const sal_uInt32 MAX_GPR_REGS = 8;
> > +
> > +/* 8 SIMD/FP registers (v0..v7) are used for parameter passing. */
> > +const sal_uInt32 MAX_FPR_REGS = 8;
> > +
> > +/* The largest number of registers a single aggregate can occupy: an
> HFA/HVA
> > +   may use up to 4 FP registers; a non-HFA aggregate passed in GPRs
> uses at
> > +   most 2 (16 bytes / 8). */
> > +const sal_uInt32 MAX_AGGREGATE_REGS = 4;
> > +
> > +/* Count the number of registers required to pass the given type.
> > +
> > +   Examines the argument and sets the number of GPR (x) and FPR (v)
> registers
> > +   it would consume.  For a Homogeneous Floating-point Aggregate the
> FPR count
> > +   is the number of members (<= 4); for a non-HFA aggregate <= 16 bytes
> the GPR
> > +   count is 1 or 2; scalars use exactly one register of the appropriate
> bank.
> > +
> > +   Returns false iff the parameter must be passed indirectly (in
> memory): a
> > +   non-HFA aggregate larger than 16 bytes.  When bInReturn is true the
> same
> > +   classification answers "can this be returned in registers?" (false
> => the
> > +   caller must allocate a buffer and pass it in x8).
> > +*/
> > +bool examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool
> bInReturn, int &nUsedGPR, int &nUsedFPR );
> > +
> > +/** Does a function returning this type use the hidden indirect-result
> pointer
> > +    (passed by the caller in x8), or can it return in registers?
> > +
> > +    A scalar returns in x0 or v0; an HFA returns in v0..v3; a non-HFA
> aggregate
> > +    of <= 16 bytes returns in x0,x1.  Anything larger (non-HFA aggregate
> > +    > 16 bytes) is returned via the caller-allocated buffer addressed
> by x8 -
> > +    that is the "hidden param" case, for which this returns true.
> > +*/
> > +bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef
> );
> > +
> > +/** Scatter a register-resident return value (an HFA returned in
> v0..v3, or a
> > +    non-HFA aggregate <= 16 bytes returned in x0,x1) into the caller's
> struct.
> > +
> > +    pGPR points at the saved x0,x1,... ; pFPR at the saved v0,v1,...
> (each
> > +    element the low 8 bytes of a v register, i.e. a double slot).  Only
> valid
> > +    when return_in_hidden_param() is false.
> > +*/
> > +void fill_struct( typelib_TypeDescriptionReference *pTypeRef, const
> sal_uInt64* pGPR, const double* pFPR, void *pStruct );
> > +
> > +} // namespace aarch64
> > +
> > +#endif // _BRIDGES_CPP_UNO_AARCH64_ABI_HXX_
> > diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/call.s
> b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/call.s
> > new file mode 100644
> > index 0000000000..035b38555a
> > --- /dev/null
> > +++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/call.s
> > @@ -0,0 +1,168 @@
> > +/**************************************************************
> > + *
> > + * 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
> > + *
> > + * Unless required by applicable law or agreed to in writing,
> > + * software distributed under the License is distributed on an
> > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> > + * KIND, either express or implied.  See the License for the
> > + * specific language governing permissions and limitations
> > + * under the License.
> > + *
> > + *************************************************************/
> > +
> > +// AArch64 (Apple Silicon, AAPCS64) outgoing-call trampoline for the
> C++-UNO
> > +// bridge.  Loads the argument registers from caller-prepared arrays,
> copies
> > +// any overflow arguments to the outgoing stack, performs the indirect
> call,
> > +// and stores the integer and FP/SIMD return registers back.
> > +//
> > +// See AAPCS64_BRIDGE_SPEC.md.  Mach-O assembler syntax; symbols are
> prefixed
> > +// with an underscore per the Darwin C ABI.
> > +//
> > +// extern "C" void callVirtualFunction(
> > +//     sal_uInt64  pFunction,     // x0: target C++ virtual method
> > +//     sal_uInt64  pIndirectRet,  // x1: value for x8 (indirect result
> ptr), 0 if none
> > +//     sal_uInt64 *pGPR,          // x2: 8 words  -> x0..x7
> > +//     double     *pFPR,          // x3: 8 doubles -> d0..d7
> > +//     sal_uInt64 *pStack,        // x4: overflow-arg words
> > +//     sal_uInt32  nStackWords,   // x5: number of 8-byte overflow words
> > +//     sal_uInt64 *pGPRReturn,    // x6: [out] x0,x1
> > +//     double     *pFPRReturn);   // x7: [out] d0..d3 (HFA up to 4
> elements)
> > +
> > +    .text
> > +    .globl _callVirtualFunction
> > +    .p2align 2
> > +_callVirtualFunction:
> > +    // prologue: save fp/lr and the callee-saved registers we use
> > +    stp     x29, x30, [sp, #-16]!
> > +    stp     x19, x20, [sp, #-16]!
> > +    stp     x21, x22, [sp, #-16]!
> > +    stp     x23, x24, [sp, #-16]!
> > +    mov     x29, sp
> > +
> > +    // stash inputs that must survive the call into callee-saved
> registers
> > +    mov     x19, x0                     // pFunction
> > +    mov     x20, x2                     // pGPR
> > +    mov     x21, x3                     // pFPR
> > +    mov     x22, x6                     // pGPRReturn
> > +    mov     x23, x7                     // pFPRReturn
> > +    mov     x24, x1                     // x8 indirect-result value
> > +
> > +    // allocate and copy the outgoing overflow stack arguments.
> > +    // bytes = ((nStackWords + 1) & ~1) * 8, to keep sp 16-byte aligned.
> > +    add     x9, x5, #1
> > +    bic     x9, x9, #1
> > +    lsl     x9, x9, #3
> > +    sub     sp, sp, x9
> > +    mov     x10, #0
> > +Lcvf_copy:
> > +    cmp     x10, x5
> > +    b.ge    Lcvf_copied
> > +    ldr     x11, [x4, x10, lsl #3]
> > +    str     x11, [sp, x10, lsl #3]
> > +    add     x10, x10, #1
> > +    b       Lcvf_copy
> > +Lcvf_copied:
> > +
> > +    // load the FP/SIMD argument registers d0..d7
> > +    ldp     d0, d1, [x21, #0]
> > +    ldp     d2, d3, [x21, #16]
> > +    ldp     d4, d5, [x21, #32]
> > +    ldp     d6, d7, [x21, #48]
> > +
> > +    // load the GP argument registers x0..x7 and the x8 indirect-result
> reg
> > +    mov     x8, x24
> > +    ldp     x6, x7, [x20, #48]
> > +    ldp     x4, x5, [x20, #32]
> > +    ldp     x2, x3, [x20, #16]
> > +    ldp     x0, x1, [x20, #0]
> > +
> > +    // perform the virtual call
> > +    blr     x19
> > +
> > +    // store the return registers
> > +    str     x0, [x22, #0]
> > +    str     x1, [x22, #8]
> > +    str     d0, [x23, #0]
> > +    str     d1, [x23, #8]
> > +    str     d2, [x23, #16]
> > +    str     d3, [x23, #24]
> > +
> > +    // epilogue
> > +    mov     sp, x29
> > +    ldp     x23, x24, [sp], #16
> > +    ldp     x21, x22, [sp], #16
> > +    ldp     x19, x20, [sp], #16
> > +    ldp     x29, x30, [sp], #16
> > +    ret
> > +
> > +//
> ---------------------------------------------------------------------------
> > +// privateSnippetExecutor: the incoming (cpp2uno) register-spill
> executor.
> > +//
> > +// Reached by a BR from a per-vtable-slot code snippet (see
> codeSnippet() in
> > +// cpp2uno.cxx) with:
> > +//   x16 = (nVtableOffset << 32) | nFunctionIndex  (low bit 0x80000000
> flags a
> > +//         hidden/indirect return)
> > +//   x0..x7, d0..d7, x8 = the original incoming arguments (untouched)
> > +//   sp  = the caller's stack-argument area (overflow)
> > +//   x30 = return address back into the original C++ caller
> > +//
> > +// It spills the argument registers to a save area and calls
> cpp_vtable_call,
> > +// then loads the return value back into x0/x1 and d0/d1 (or d0 for fp).
> > +//
> > +//   typelib_TypeClass cpp_vtable_call(
> > +//       sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
> > +//       void** gpreg, void** fpreg, void** ovrflw,
> > +//       void* pIndirectReturn, sal_uInt64* pRegisterReturn);
> > +//
> > +// Frame (176 bytes): [0]=x29,x30  [16..79]=x0..x7  [80..143]=d0..d7
> > +//                    [144..159]=return buffer.
> > +    .globl _privateSnippetExecutor
> > +    .p2align 2
> > +_privateSnippetExecutor:
> > +    mov     x17, sp                     // x17 = ovrflw (incoming stack
> args)
> > +    stp     x29, x30, [sp, #-176]!
> > +    mov     x29, sp
> > +
> > +    stp     x0, x1, [sp, #16]           // save GP argument registers
> x0..x7
> > +    stp     x2, x3, [sp, #32]
> > +    stp     x4, x5, [sp, #48]
> > +    stp     x6, x7, [sp, #64]
> > +
> > +    stp     d0, d1, [sp, #80]           // save FP/SIMD argument
> registers d0..d7
> > +    stp     d2, d3, [sp, #96]
> > +    stp     d4, d5, [sp, #112]
> > +    stp     d6, d7, [sp, #128]
> > +
> > +    mov     w0, w16                     // nFunctionIndex (low 32 bits)
> > +    lsr     x1, x16, #32                // nVtableOffset (high 32 bits)
> > +    add     x2, sp, #16                 // gpreg
> > +    add     x3, sp, #80                 // fpreg
> > +    mov     x4, x17                     // ovrflw
> > +    mov     x5, x8                      // pIndirectReturn (x8
> indirect-result reg)
> > +    add     x6, sp, #144                // pRegisterReturn (16-byte
> buffer)
> > +    bl      _cpp_vtable_call
> > +
> > +    cmp     w0, #10                     // typelib_TypeClass_FLOAT
> > +    b.eq    Lpse_float
> > +    cmp     w0, #11                     // typelib_TypeClass_DOUBLE
> > +    b.eq    Lpse_float
> > +    // integer / pointer / <=16B aggregate: load both banks; caller
> reads the
> > +    // ones that matter for its return type.
> > +    ldp     x0, x1, [sp, #144]
> > +    ldp     d0, d1, [sp, #144]
> > +    b       Lpse_done
> > +Lpse_float:
> > +    ldr     d0, [sp, #144]
> > +Lpse_done:
> > +    mov     sp, x29
> > +    ldp     x29, x30, [sp], #176
> > +    ret
> > diff --git
> a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx
> b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx
> > new file mode 100644
> > index 0000000000..6fa6bac7a2
> > --- /dev/null
> > +++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx
> > @@ -0,0 +1,543 @@
> > +/**************************************************************
> > + *
> > + * 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
> > + *
> > + * Unless required by applicable law or agreed to in writing,
> > + * software distributed under the License is distributed on an
> > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> > + * KIND, either express or implied.  See the License for the
> > + * specific language governing permissions and limitations
> > + * under the License.
> > + *
> > + *************************************************************/
> > +
> > +
> > +
> > +// MARKER(update_precomp.py): autogen include statement, do not remove
> > +#include "precompiled_bridges.hxx"
> > +
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <hash_map>
> > +
> > +#include <rtl/alloc.h>
> > +#include <osl/mutex.hxx>
> > +
> > +#include <com/sun/star/uno/genfunc.hxx>
> > +#include "com/sun/star/uno/RuntimeException.hpp"
> > +#include <uno/data.h>
> > +#include <typelib/typedescription.hxx>
> > +
> > +#include "bridges/cpp_uno/shared/bridge.hxx"
> > +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
> > +#include "bridges/cpp_uno/shared/types.hxx"
> > +#include "bridges/cpp_uno/shared/vtablefactory.hxx"
> > +
> > +#include "abi.hxx"
> > +#include "share.hxx"
> > +
> > +using namespace ::osl;
> > +using namespace ::rtl;
> > +using namespace ::com::sun::star::uno;
> > +
> >
> +//==================================================================================================
> > +
> > +// Perform the UNO call
> > +//
> > +// We must convert the parameters stored in gpreg, fpreg and ovrflw to
> UNO
> > +// arguments and call pThis->getUnoI()->pDispatcher.
> > +//
> > +// gpreg:  this, [gpr params x0..x7]   (the indirect-result ptr is x8,
> separate)
> > +// fpreg:  [fpr params d0..d7]
> > +// ovrflw: [gpr or fpr params (properly aligned)]
> > +//
> > +// On AArch64 a structure bigger than 16 bytes is returned via the
> buffer
> > +// addressed by x8 (pIndirectReturn); 'this' is always x0 = gpreg[0].
> > +// Simple types are returned in x0,x1 (int) or d0,d1 (fp); HFAs in
> d0..d3;
> > +// non-HFA structures <= 16 bytes in x0,x1.
> > +static typelib_TypeClass cpp2uno_call(
> > +     bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
> > +     const typelib_TypeDescription * pMemberTypeDescr,
> > +     typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates
> void return
> > +     sal_Int32 nParams, typelib_MethodParameter * pParams,
> > +     void ** gpreg, void ** fpreg, void ** ovrflw,
> > +     void * pIndirectReturn, // AArch64 x8 indirect-result pointer (0
> if none)
> > +     sal_uInt64 * pRegisterReturn /* space for register return */ )
> > +{
> > +     unsigned int nr_gpr = 0; //number of gpr registers used
> > +     unsigned int nr_fpr = 0; //number of fpr registers used
> > +
> > +     // return
> > +     typelib_TypeDescription * pReturnTypeDescr = 0;
> > +     if (pReturnTypeRef)
> > +             TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
> > +
> > +     void * pUnoReturn = 0;
> > +     void * pCppReturn = 0; // complex return ptr: if != 0 && !=
> pUnoReturn, reconversion need
> > +
> > +     if ( pReturnTypeDescr )
> > +     {
> > +             if ( aarch64::return_in_hidden_param( pReturnTypeRef ) )
> > +             {
> > +                     // AArch64: the indirect-result pointer arrives in
> x8, NOT in the
> > +                     // first general-purpose argument register (unlike
> x86-64 SysV).
> > +                     // So we take it from pIndirectReturn and do NOT
> consume a gpreg
> > +                     // slot here; 'this' still occupies gpreg[0] below.
> > +                     pCppReturn = pIndirectReturn;
> > +
> > +                     pUnoReturn = (
> bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
> > +                                                ? alloca(
> pReturnTypeDescr->nSize )
> > +                                                : pCppReturn ); //
> direct way
> > +             }
> > +             else
> > +                     pUnoReturn = pRegisterReturn; // direct way for
> simple types
> > +     }
> > +
> > +     // pop this (x0)
> > +     gpreg++;
> > +     nr_gpr++;
> > +
> > +     // stack space
> > +     // parameters
> > +     void ** pUnoArgs = reinterpret_cast<void **>(alloca( 4 *
> sizeof(void *) * nParams ));
> > +     void ** pCppArgs = pUnoArgs + nParams;
> > +     // indizes of values this have to be converted (interface
> conversion cpp<=>uno)
> > +     sal_Int32 * pTempIndizes = reinterpret_cast<sal_Int32 *>(pUnoArgs
> + (2 * nParams));
> > +     // type descriptions for reconversions
> > +     typelib_TypeDescription ** ppTempParamTypeDescr =
> reinterpret_cast<typelib_TypeDescription **>(pUnoArgs + (3 * nParams));
> > +
> > +     sal_Int32 nTempIndizes = 0;
> > +
> > +     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
> > +     {
> > +             const typelib_MethodParameter & rParam = pParams[nPos];
> > +
> > +             int nUsedGPR = 0;
> > +             int nUsedFPR = 0;
> > +             bool bFitsRegisters = aarch64::examine_argument(
> rParam.pTypeRef, false, nUsedGPR, nUsedFPR );
> > +             if ( !rParam.bOut &&
> bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
> > +             {
> > +                     // A simple UNO type occupies exactly one
> register, GPR or FPR.
> > +                     OSL_ASSERT( bFitsRegisters && ( ( nUsedFPR == 1 &&
> nUsedGPR == 0 ) || ( nUsedFPR == 0 && nUsedGPR == 1 ) ) );
> > +
> > +                     if ( nUsedFPR == 1 )
> > +                     {
> > +                             if ( nr_fpr < aarch64::MAX_FPR_REGS )
> > +                             {
> > +                                     pCppArgs[nPos] = pUnoArgs[nPos] =
> fpreg++;
> > +                                     nr_fpr++;
> > +                             }
> > +                             else
> > +                                     pCppArgs[nPos] = pUnoArgs[nPos] =
> ovrflw++;
> > +                     }
> > +                     else if ( nUsedGPR == 1 )
> > +                     {
> > +                             if ( nr_gpr < aarch64::MAX_GPR_REGS )
> > +                             {
> > +                                     pCppArgs[nPos] = pUnoArgs[nPos] =
> gpreg++;
> > +                                     nr_gpr++;
> > +                             }
> > +                             else
> > +                                     pCppArgs[nPos] = pUnoArgs[nPos] =
> ovrflw++;
> > +                     }
> > +             }
> > +             else // struct <= 16 bytes || ptr to complex value || ref
> > +             {
> > +                     typelib_TypeDescription * pParamTypeDescr = 0;
> > +                     TYPELIB_DANGER_GET( &pParamTypeDescr,
> rParam.pTypeRef );
> > +
> > +                     void *pCppStack;
> > +                     if ( nr_gpr < aarch64::MAX_GPR_REGS )
> > +                     {
> > +                             pCppArgs[nPos] = pCppStack = *gpreg++;
> > +                             nr_gpr++;
> > +                     }
> > +                     else
> > +                             pCppArgs[nPos] = pCppStack = *ovrflw++;
> > +
> > +                     if (! rParam.bIn) // is pure out
> > +                     {
> > +                             // uno out is unconstructed mem!
> > +                             pUnoArgs[nPos] = alloca(
> pParamTypeDescr->nSize );
> > +                             pTempIndizes[nTempIndizes] = nPos;
> > +                             // will be released at reconversion
> > +                             ppTempParamTypeDescr[nTempIndizes++] =
> pParamTypeDescr;
> > +                     }
> > +                     else if (
> bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is
> in/inout
> > +                     {
> > +                             uno_copyAndConvertData( pUnoArgs[nPos] =
> alloca( pParamTypeDescr->nSize ),
> > +
>      pCppStack, pParamTypeDescr,
> > +
>      pThis->getBridge()->getCpp2Uno() );
> > +                             pTempIndizes[nTempIndizes] = nPos; // has
> to be reconverted
> > +                             // will be released at reconversion
> > +                             ppTempParamTypeDescr[nTempIndizes++] =
> pParamTypeDescr;
> > +                     }
> > +                     else // direct way
> > +                     {
> > +                             pUnoArgs[nPos] = pCppStack;
> > +                             // 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 ( ; nTempIndizes--; )
> > +             {
> > +                     sal_Int32 nIndex = pTempIndizes[nTempIndizes];
> > +
> > +                     if (pParams[nIndex].bIn) // is in/inout => was
> constructed
> > +                             uno_destructData( pUnoArgs[nIndex],
> ppTempParamTypeDescr[nTempIndizes], 0 );
> > +                     TYPELIB_DANGER_RELEASE(
> ppTempParamTypeDescr[nTempIndizes] );
> > +             }
> > +             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 ( ; nTempIndizes--; )
> > +             {
> > +                     sal_Int32 nIndex = pTempIndizes[nTempIndizes];
> > +                     typelib_TypeDescription * pParamTypeDescr =
> ppTempParamTypeDescr[nTempIndizes];
> > +
> > +                     if ( pParams[nIndex].bOut ) // inout/out
> > +                     {
> > +                             // convert and assign
> > +                             uno_destructData( pCppArgs[nIndex],
> pParamTypeDescr, cpp_release );
> > +                             uno_copyAndConvertData( pCppArgs[nIndex],
> pUnoArgs[nIndex], pParamTypeDescr,
> > +
>      pThis->getBridge()->getUno2Cpp() );
> > +                     }
> > +                     // destroy temp uno param
> > +                     uno_destructData( pUnoArgs[nIndex],
> pParamTypeDescr, 0 );
> > +
> > +                     TYPELIB_DANGER_RELEASE( pParamTypeDescr );
> > +             }
> > +             // return
> > +             if ( pCppReturn ) // has complex return
> > +             {
> > +                     if ( pUnoReturn != pCppReturn ) // needs
> reconversion
> > +                     {
> > +                             uno_copyAndConvertData( pCppReturn,
> pUnoReturn, pReturnTypeDescr,
> > +
>      pThis->getBridge()->getUno2Cpp() );
> > +                             // destroy temp uno return
> > +                             uno_destructData( pUnoReturn,
> pReturnTypeDescr, 0 );
> > +                     }
> > +                     // complex return ptr is set to return reg
> > +                     *reinterpret_cast<void **>(pRegisterReturn) =
> pCppReturn;
> > +             }
> > +             if ( pReturnTypeDescr )
> > +             {
> > +                     typelib_TypeClass eRet =
> (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
> > +                     TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
> > +                     return eRet;
> > +             }
> > +             else
> > +                     return typelib_TypeClass_VOID;
> > +     }
> > +}
> > +
> > +
> >
> +//==================================================================================================
> > +extern "C" typelib_TypeClass cpp_vtable_call(
> > +     sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
> > +     void ** gpreg, void ** fpreg, void ** ovrflw,
> > +     void * pIndirectReturn, // AArch64 x8 indirect-result pointer (0
> if none)
> > +     sal_uInt64 * pRegisterReturn /* space for register return */ )
> > +{
> > +     // gpreg:  this, [other gpr params x0..x7]
> > +     // fpreg:  [fpr params d0..d7]
> > +     // ovrflw: [gpr or fpr params (properly aligned)]
> > +     // pIndirectReturn: x8 (the hidden return buffer), when bit
> 0x80000000 set.
> > +     //
> > +     // On AArch64 'this' is ALWAYS x0 = gpreg[0]; the hidden return
> pointer is
> > +     // the separate x8 register, not a displaced first GPR (unlike
> x86-64 SysV
> > +     // where it occupied gpreg[0] and 'this' moved to gpreg[1]).
> > +     if ( nFunctionIndex & 0x80000000 )
> > +             nFunctionIndex &= 0x7fffffff;
> > +
> > +     void * pThis = gpreg[0];
> > +     pThis = static_cast<char *>( pThis ) - nVtableOffset;
> > +
> > +     bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
> > +
>  bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
> > +
> > +     typelib_InterfaceTypeDescription * pTypeDescr =
> pCppI->getTypeDescr();
> > +
> > +     OSL_ENSURE( nFunctionIndex <
> pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
> > +     if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
> > +     {
> > +             throw RuntimeException( OUString::createFromAscii("illegal
> vtable index!"),
> > +
>  reinterpret_cast<XInterface *>( pCppI ) );
> > +     }
> > +
> > +     // determine called method
> > +     sal_Int32 nMemberPos =
> pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
> > +     OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal
> member index!\n" );
> > +
> > +     TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos]
> );
> > +
> > +     typelib_TypeClass eRet;
> > +     switch ( aMemberDescr.get()->eTypeClass )
> > +     {
> > +             case typelib_TypeClass_INTERFACE_ATTRIBUTE:
> > +             {
> > +                     typelib_TypeDescriptionReference *pAttrTypeRef =
> > +
>  reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>(
> aMemberDescr.get() )->pAttributeTypeRef;
> > +
> > +                     if (
> pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
> > +                     {
> > +                             // is GET method
> > +                             eRet = cpp2uno_call( pCppI,
> aMemberDescr.get(), pAttrTypeRef,
> > +                                             0, 0, // no params
> > +                                             gpreg, fpreg, ovrflw,
> pIndirectReturn, pRegisterReturn );
> > +                     }
> > +                     else
> > +                     {
> > +                             // is SET method
> > +                             typelib_MethodParameter aParam;
> > +                             aParam.pTypeRef = pAttrTypeRef;
> > +                             aParam.bIn              = sal_True;
> > +                             aParam.bOut             = sal_False;
> > +
> > +                             eRet = cpp2uno_call( pCppI,
> aMemberDescr.get(),
> > +                                             0, // indicates void return
> > +                                             1, &aParam,
> > +                                             gpreg, fpreg, ovrflw,
> pIndirectReturn, 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
> > +                             {
> > +                                     // queryInterface([in] type)
> returns an Any (> 16 bytes),
> > +                                     // so on AArch64 the result buffer
> is x8 (pIndirectReturn),
> > +                                     // 'this' is gpreg[0], and the
> type argument is the first
> > +                                     // real parameter, gpreg[1].
> > +                                     typelib_TypeDescription * pTD = 0;
> > +                                     TYPELIB_DANGER_GET( &pTD,
> reinterpret_cast<Type *>( gpreg[1] )->getTypeLibType() );
> > +                                     if ( pTD )
> > +                                     {
> > +                                             XInterface * pInterface =
> 0;
> > +
>  (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
> > +                                                     (
> pCppI->getBridge()->getCppEnv(),
> > +
>  reinterpret_cast<void **>(&pInterface),
> > +
>  pCppI->getOid().pData,
> > +
>  reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
> > +
> > +                                             if ( pInterface )
> > +                                             {
> > +
>  ::uno_any_construct( reinterpret_cast<uno_Any *>( pIndirectReturn ),
> > +
>                       &pInterface, pTD, cpp_acquire );
> > +
> > +
>  pInterface->release();
> > +
>  TYPELIB_DANGER_RELEASE( pTD );
> > +
> > +
>  reinterpret_cast<void **>( pRegisterReturn )[0] = pIndirectReturn;
> > +                                                     eRet =
> typelib_TypeClass_ANY;
> > +                                                     break;
> > +                                             }
> > +                                             TYPELIB_DANGER_RELEASE(
> pTD );
> > +                                     }
> > +                             } // else perform queryInterface()
> > +                             default:
> > +                             {
> > +
>  typelib_InterfaceMethodTypeDescription *pMethodTD =
> > +
>  reinterpret_cast<typelib_InterfaceMethodTypeDescription *>(
> aMemberDescr.get() );
> > +
> > +                                     eRet = cpp2uno_call( pCppI,
> aMemberDescr.get(),
> > +
>       pMethodTD->pReturnTypeRef,
> > +
>       pMethodTD->nParams,
> > +
>       pMethodTD->pParams,
> > +
>       gpreg, fpreg, ovrflw, pIndirectReturn, pRegisterReturn );
> > +                             }
> > +                     }
> > +                     break;
> > +             }
> > +             default:
> > +             {
> > +                     throw RuntimeException(
> OUString::createFromAscii("no member description found!"),
> > +
>  reinterpret_cast<XInterface *>( pCppI ) );
> > +                     // is here for dummy
> > +                     eRet = typelib_TypeClass_VOID;
> > +             }
> > +     }
> > +
> > +     return eRet;
> > +}
> > +
> >
> +//==================================================================================================
> > +// The incoming register-spill executor, implemented in call.s.  It is
> reached
> > +// via BR from a per-slot snippet (codeSnippet below) with x16 carrying
> the
> > +// packed (nVtableOffset << 32) | nFunctionIndex; it spills the argument
> > +// registers and calls cpp_vtable_call.
> > +extern "C" void privateSnippetExecutor( void );
> > +
> > +// Each snippet is 5 AArch64 instructions (20 bytes) + 4 bytes padding
> to an
> > +// 8-byte boundary + two 8-byte literals (the packed index and the
> executor
> > +// address) = 40 bytes.
> > +const int codeSnippetSize = 40;
> > +
> > +// Generate a per-vtable-slot trampoline that loads the packed function
> index
> > +// into x16 and branches to privateSnippetExecutor(), preserving every
> > +// argument register.  Uses PC-relative literal loads because AArch64
> cannot
> > +// embed a 64-bit immediate in a single instruction.
> > +//
> > +// Layout (offsets in bytes from code):
> > +//    0:  ldr  x16, #24      ; x16 = nOffsetAndIndex (literal at +24)
> > +//    4:  ldr  x17, #28      ; x17 = privateSnippetExecutor (literal at
> +32)
> > +//    8:  br   x17
> > +//   12:  (unused / padding)
> > +//   16:  (padding to 8-byte align the literals at 24)
> > +//   24:  .quad nOffsetAndIndex
> > +//   32:  .quad privateSnippetExecutor
> > +//
> > +// Note: the snippet creates no stack frame, so the C++ unwinder walks
> straight
> > +// through it to the original caller (required for UNO exception
> propagation).
> > +unsigned char * codeSnippet( unsigned char * code,
> > +        sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
> > +        bool bHasHiddenParam ) SAL_THROW( () )
> > +{
> > +     sal_uInt64 nOffsetAndIndex = ( static_cast<sal_uInt64>(
> nVtableOffset ) << 32 ) | static_cast<sal_uInt64>( nFunctionIndex );
> > +
> > +     if ( bHasHiddenParam )
> > +             nOffsetAndIndex |= 0x80000000;
> > +
> > +     sal_uInt32 * p = reinterpret_cast<sal_uInt32 *>( code );
> > +
> > +     // ldr x16, #24  -> literal at code+24. imm19 = 24/4 = 6.
> > +     //   encoding: 0x58000000 | (imm19 << 5) | Rt(16)
> > +     p[0] = 0x58000000 | ( 6 << 5 ) | 16;
> > +     // ldr x17, #28  -> literal at code+32 (relative to this insn at
> +4): 28.
> > +     //   imm19 = 28/4 = 7.
> > +     p[1] = 0x58000000 | ( 7 << 5 ) | 17;
> > +     // br x17  -> 0xD61F0000 | (Rn(17) << 5)
> > +     p[2] = 0xD61F0000 | ( 17 << 5 );
> > +     // p[3] (offset 12) and p[4] (offset 16..20) are padding.
> > +     p[3] = 0xD503201F; // NOP
> > +     p[4] = 0xD503201F; // NOP
> > +
> > +     // literals, 8-byte aligned at offset 24 and 32
> > +     *reinterpret_cast<sal_uInt64 *>( code + 24 ) = nOffsetAndIndex;
> > +     *reinterpret_cast<sal_uInt64 *>( code + 32 ) =
> reinterpret_cast<sal_uInt64>( privateSnippetExecutor );
> > +
> > +     return code + codeSnippetSize;
> > +}
> > +
> >
> +//==================================================================================================
> > +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;
> > +}
> > +
> >
> +//==================================================================================================
> > +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
> > +    sal_Int32 slotCount)
> > +{
> > +    return (slotCount + 2) * sizeof (Slot) + slotCount *
> codeSnippetSize;
> > +}
> > +
> >
> +//==================================================================================================
> > +bridges::cpp_uno::shared::VtableFactory::Slot *
> > +bridges::cpp_uno::shared::VtableFactory::initializeBlock(
> > +    void * block, sal_Int32 slotCount)
> > +{
> > +    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, /*sal_PtrDiff
> writetoexecdiff,*/
> > +     typelib_InterfaceTypeDescription const * type, sal_Int32
> nFunctionOffset,
> > +     sal_Int32 functionCount, sal_Int32 nVtableOffset )
> > +{
> > +     const sal_PtrDiff writetoexecdiff = 0;
> > +     (*slots) -= functionCount;
> > +     Slot * s = *slots;
> > +     for ( sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos )
> > +     {
> > +             typelib_TypeDescription * pTD = 0;
> > +
> > +             TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
> > +             OSL_ASSERT( pTD );
> > +
> > +             if ( typelib_TypeClass_INTERFACE_ATTRIBUTE ==
> pTD->eTypeClass )
> > +             {
> > +                     typelib_InterfaceAttributeTypeDescription *pAttrTD
> =
> > +
>  reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
> > +
> > +                     // get method
> > +                     (s++)->fn = code + writetoexecdiff;
> > +                     code = codeSnippet( code, nFunctionOffset++,
> nVtableOffset,
> > +
>  aarch64::return_in_hidden_param( pAttrTD->pAttributeTypeRef ) );
> > +
> > +                     if ( ! pAttrTD->bReadOnly )
> > +                     {
> > +                             // set method
> > +                             (s++)->fn = code + writetoexecdiff;
> > +                             code = codeSnippet( code,
> nFunctionOffset++, nVtableOffset, false );
> > +                     }
> > +             }
> > +             else if ( typelib_TypeClass_INTERFACE_METHOD ==
> pTD->eTypeClass )
> > +             {
> > +                     typelib_InterfaceMethodTypeDescription *pMethodTD =
> > +
>  reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
> > +
> > +                     (s++)->fn = code + writetoexecdiff;
> > +                     code = codeSnippet( code, nFunctionOffset++,
> nVtableOffset,
> > +
>  aarch64::return_in_hidden_param( pMethodTD->pReturnTypeRef ) );
> > +             }
> > +             else
> > +                     OSL_ASSERT( false );
> > +
> > +             TYPELIB_DANGER_RELEASE( pTD );
> > +     }
> > +     return code;
> > +}
> > +
> >
> +//==================================================================================================
> > +void bridges::cpp_uno::shared::VtableFactory::flushCode(
> > +     unsigned char const *, unsigned char const * )
> > +{
> > +}
> > diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/except.cxx
> b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/except.cxx
> > new file mode 100644
> > index 0000000000..60784a4172
> > --- /dev/null
> > +++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/except.cxx
> > @@ -0,0 +1,358 @@
> > +/**************************************************************
> > + *
> > + * 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
> > + *
> > + * Unless required by applicable law or agreed to in writing,
> > + * software distributed under the License is distributed on an
> > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> > + * KIND, either express or implied.  See the License for the
> > + * specific language governing permissions and limitations
> > + * under the License.
> > + *
> > + *************************************************************/
> > +
> > +
> > +
> > +// MARKER(update_precomp.py): autogen include statement, do not remove
> > +#include "precompiled_bridges.hxx"
> > +
> > +#if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
> > +#include <exception>
> > +#endif
> > +
> > +#include <stdio.h>
> > +#include <string.h>
> > +#include <dlfcn.h>
> > +#include <cxxabi.h>
> > +#include <hash_map>
> > +#include <sys/param.h>
> > +
> > +#include <rtl/strbuf.hxx>
> > +#include <rtl/ustrbuf.hxx>
> > +#include <osl/diagnose.h>
> > +#include <osl/mutex.hxx>
> > +
> > +#include <com/sun/star/uno/genfunc.hxx>
> > +#include "com/sun/star/uno/RuntimeException.hpp"
> > +#include <typelib/typedescription.hxx>
> > +#include <uno/any2.h>
> > +
> > +#include "share.hxx"
> > +
> > +
> > +using namespace ::std;
> > +using namespace ::osl;
> > +using namespace ::rtl;
> > +using namespace ::com::sun::star::uno;
> > +using namespace ::__cxxabiv1;
> > +
> > +
> > +namespace CPPU_CURRENT_NAMESPACE
> > +{
> > +
> > +void dummy_can_throw_anything( char const * )
> > +{
> > +}
> > +
> >
> +//==================================================================================================
> > +static OUString toUNOname( char const * p ) SAL_THROW( () )
> > +{
> > +#if OSL_DEBUG_LEVEL > 1
> > +    char const * start = p;
> > +#endif
> > +
> > +    // example: N3com3sun4star4lang24IllegalArgumentExceptionE
> > +
> > +     OUStringBuffer buf( 64 );
> > +    OSL_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( (sal_Unicode)'.' );
> > +    }
> > +
> > +#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 hash_map< OUString, type_info *, OUStringHash > t_rtti_map;
> > +
> > +    Mutex m_mutex;
> > +     t_rtti_map m_rttis;
> > +    t_rtti_map m_generatedRttis;
> > +
> > +    void * m_hApp;
> > +
> > +public:
> > +    RTTI() SAL_THROW( () );
> > +    ~RTTI() SAL_THROW( () );
> > +
> > +    type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW(
> () );
> > +};
> > +
> >
> +//__________________________________________________________________________________________________
> > +RTTI::RTTI() SAL_THROW( () )
> > +    : m_hApp( dlopen( 0, RTLD_LAZY ) )
> > +{
> > +}
> > +
> >
> +//__________________________________________________________________________________________________
> > +RTTI::~RTTI() SAL_THROW( () )
> > +{
> > +    dlclose( m_hApp );
> > +}
> > +
> >
> +//__________________________________________________________________________________________________
> > +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr
> ) SAL_THROW( () )
> > +{
> > +    type_info * rtti;
> > +
> > +    OUString const & unoName = *(OUString const
> *)&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( RTL_CONSTASCII_STRINGPARAM("_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)
> > +        {
> > +            pair< t_rtti_map::iterator, bool > insertion(
> > +                m_rttis.insert( t_rtti_map::value_type( unoName, rtti )
> ) );
> > +            OSL_ENSURE( insertion.second, "### 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 const * rttiName = symName.getStr() +4;
> > +#if OSL_DEBUG_LEVEL > 1
> > +                fprintf( stderr,"generated rtti for %s\n", rttiName );
> > +                const OString aCUnoName = OUStringToOString( unoName,
> RTL_TEXTENCODING_UTF8);
> > +                OSL_TRACE( "TypeInfo for \"%s\" not found and cannot be
> generated.\n", aCUnoName.getStr());
> > +#endif
> > +#ifndef AOO_BYPASS_RTTI
> > +                if (pTypeDescr->pBaseTypeDescription)
> > +                {
> > +                    // ensure availability of base
> > +                    type_info * base_rtti = getRTTI(
> > +                        (typelib_CompoundTypeDescription
> *)pTypeDescr->pBaseTypeDescription );
> > +                    rtti = new __si_class_type_info(
> > +                        strdup( rttiName ), (__class_type_info
> *)base_rtti );
> > +                }
> > +                else
> > +                {
> > +                    // this class has no base class
> > +                    rtti = new __class_type_info( strdup( rttiName ) );
> > +                }
> > +#else
> > +                rtti = NULL;
> > +#endif
> > +                bool bOK = m_generatedRttis.insert(
> t_rtti_map::value_type( unoName, rtti )).second;
> > +                OSL_ENSURE( bOK, "### 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;
> > +    /* More __cxa_exception mumbo-jumbo. See share.hxx and
> fillUnoException() below */
> > +    if (header->exceptionDestructor != &deleteException)
> > +    {
> > +        header = reinterpret_cast<__cxa_exception const
> *>(reinterpret_cast<char const *>(header) - 8);
> > +    }
> > +    if( !header->exceptionType)
> > +    {
> > +        return; // NOTE: leak for now
> > +    }
> > +    typelib_TypeDescription * pTD = 0;
> > +    OUString unoName( toUNOname( header->exceptionType->name() ) );
> > +    ::typelib_typedescription_getByName( &pTD, unoName.pData );
> > +    OSL_ENSURE( 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(
> > +            *reinterpret_cast< OUString const * >(
> &pUnoExc->pType->pTypeName ),
> > +            RTL_TEXTENCODING_ASCII_US ) );
> > +    fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() );
> > +#endif
> > +    void * pCppExc;
> > +    type_info * rtti;
> > +
> > +    {
> > +    // construct cpp exception object
> > +     typelib_TypeDescription * pTypeDescr = 0;
> > +     TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
> > +    OSL_ASSERT( pTypeDescr );
> > +    if (! pTypeDescr)
> > +    {
> > +        throw RuntimeException(
> > +            OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get
> typedescription for type ") ) +
> > +            *reinterpret_cast< OUString const * >(
> &pUnoExc->pType->pTypeName ),
> > +            Reference< XInterface >() );
> > +    }
> > +
> > +     pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
> > +     ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr,
> pUno2Cpp );
> > +
> > +     // destruct uno exception
> > +     ::uno_any_destruct( pUnoExc, 0 );
> > +    // avoiding locked counts
> > +    static RTTI * s_rtti = 0;
> > +    if (! s_rtti)
> > +    {
> > +        MutexGuard guard( Mutex::getGlobalMutex() );
> > +        if (! s_rtti)
> > +        {
> > +#ifdef LEAK_STATIC_DATA
> > +            s_rtti = new RTTI();
> > +#else
> > +            static RTTI rtti_data;
> > +            s_rtti = &rtti_data;
> > +#endif
> > +        }
> > +    }
> > +     rtti = (type_info *)s_rtti->getRTTI(
> (typelib_CompoundTypeDescription *) pTypeDescr );
> > +    TYPELIB_DANGER_RELEASE( pTypeDescr );
> > +    OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
> > +    if (! rtti)
> > +    {
> > +        throw RuntimeException(
> > +            OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ")
> ) +
> > +            *reinterpret_cast< OUString const * >(
> &pUnoExc->pType->pTypeName ),
> > +            Reference< XInterface >() );
> > +    }
> > +    }
> > +
> > +     __cxa_throw( pCppExc, rtti, deleteException );
> > +}
> > +
> >
> +//==================================================================================================
> > +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc,
> uno_Mapping * pCpp2Uno )
> > +{
> > +    if (! header)
> > +    {
> > +        RuntimeException aRE(
> > +            OUString( RTL_CONSTASCII_USTRINGPARAM("no exception
> header!") ),
> > +            Reference< XInterface >() );
> > +        Type const & rType = ::getCppuType( &aRE );
> > +        uno_type_any_constructAndConvert( pUnoExc, &aRE,
> rType.getTypeLibType(), pCpp2Uno );
> > +#if OSL_DEBUG_LEVEL > 0
> > +        OString cstr( OUStringToOString( aRE.Message,
> RTL_TEXTENCODING_ASCII_US ) );
> > +        OSL_ENSURE( 0, cstr.getStr() );
> > +#endif
> > +        return;
> > +    }
> > +
> > +    /*
> > +     * Handle the case where we are built on llvm 10 (or later) but are
> running
> > +     * on an earlier version (eg, community builds). In this situation
> the
> > +     * reserved ptr doesn't exist in the struct returned and so the
> offsets
> > +     * that header uses are wrong. This assumes that reserved isn't used
> > +     * and that referenceCount is always >0 in the cases we handle.
> > +     * See share.hxx for the definition of __cxa_exception
> > +     */
> > +    if (*reinterpret_cast<void **>(header) == 0)
> > +    {
> > +        header = reinterpret_cast<__cxa_exception
> *>(reinterpret_cast<char *>(header) + 8);
> > +    }
> > +
> > +     typelib_TypeDescription * pExcTypeDescr = 0;
> > +    OUString unoName( toUNOname( header->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 (0 == pExcTypeDescr)
> > +    {
> > +        RuntimeException aRE(
> > +            OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not
> found: ") ) + unoName,
> > +            Reference< XInterface >() );
> > +        Type const & rType = ::getCppuType( &aRE );
> > +        uno_type_any_constructAndConvert( pUnoExc, &aRE,
> rType.getTypeLibType(), pCpp2Uno );
> > +#if OSL_DEBUG_LEVEL > 0
> > +        OString cstr( OUStringToOString( aRE.Message,
> RTL_TEXTENCODING_ASCII_US ) );
> > +        OSL_ENSURE( 0, cstr.getStr() );
> > +#endif
> > +    }
> > +    else
> > +    {
> > +        // construct uno exception any
> > +        uno_any_constructAndConvert( pUnoExc, header->adjustedPtr,
> pExcTypeDescr, pCpp2Uno );
> > +        typelib_typedescription_release( pExcTypeDescr );
> > +    }
> > +}
> > +
> > +}
> > diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/
> makefile.mk b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/makefile.mk
> > new file mode 100644
> > index 0000000000..af6c6c22d4
> > --- /dev/null
> > +++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/makefile.mk
> > @@ -0,0 +1,81 @@
> > +#**************************************************************
> > +#
> > +#  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
> > +#
> > +#  Unless required by applicable law or agreed to in writing,
> > +#  software distributed under the License is distributed on an
> > +#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> > +#  KIND, either express or implied.  See the License for the
> > +#  specific language governing permissions and limitations
> > +#  under the License.
> > +#
> > +#**************************************************************
> > +
> > +
> > +
> > +PRJ=..$/..$/..
> > +
> > +PRJNAME=bridges
> > +TARGET=$(COMNAME)_uno
> > +LIBTARGET=no
> > +ENABLE_EXCEPTIONS=TRUE
> > +
> > +# --- Settings -----------------------------------------------------
> > +
> > +.INCLUDE :  settings.mk
> > +
> > +# --- Files --------------------------------------------------------
> > +
> > +# Apple Silicon (arm64 / AAPCS64) C++-UNO bridge. CPU=R,
> CPUNAME=AARCH64.
> > +# Note: the "s5abi" in this directory's name is the macOS-wide COMNAME
> (see
> > +# solenv/gbuild/platform/macosx.mk); the actual arm64 calling
> convention is
> > +# AAPCS64, so "s5abi" here is a historical label, not a literal ABI
> claim.
> > +.IF "$(OS)$(CPU)" == "MACOSXR"
> > +
> > +.IF "$(cppu_no_leak)" == ""
> > +CFLAGS += -DLEAK_STATIC_DATA
> > +.ENDIF
> > +
> > +# In case someone enabled the non-standard -fomit-frame-pointer which
> does not
> > +# work with the .cxx sources in this directory:
> > +CFLAGSCXX += -fno-omit-frame-pointer -fnon-call-exceptions
> > +
> > +SLOFILES= \
> > +     $(SLO)$/abi.obj                 \
> > +     $(SLO)$/except.obj              \
> > +     $(SLO)$/cpp2uno.obj             \
> > +     $(SLO)$/uno2cpp.obj             \
> > +     $(SLO)$/call.obj
> > +
> > +SHL1TARGET= $(TARGET)
> > +
> > +SHL1DEF=$(MISC)$/$(SHL1TARGET).def
> > +SHL1IMPLIB=i$(TARGET)
> > +SHL1VERSIONMAP=..$/..$/bridge_exports.map
> > +SHL1RPATH=URELIB
> > +
> > +SHL1OBJS = $(SLOFILES)
> > +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib
> > +
> > +SHL1STDLIBS= \
> > +     $(CPPULIB)                      \
> > +     $(SALLIB)
> > +
> > +.ENDIF
> > +
> > +# --- Targets ------------------------------------------------------
> > +
> > +.INCLUDE :  target.mk
> > +
> > +# Assemble the AArch64 call trampoline (call.s) into call.obj,
> mirroring the
> > +# pattern rule used by the gcc3_linux_arm bridge for its armhelper.S.
> > +$(SLO)$/%.obj: %.s
> > +     $(CXX) -c -o $(SLO)$/$(@:b).o $< -fPIC ; touch $@
> > diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/share.hxx
> b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/share.hxx
> > new file mode 100644
> > index 0000000000..e4fcf4dbf9
> > --- /dev/null
> > +++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/share.hxx
> > @@ -0,0 +1,116 @@
> > +/**************************************************************
> > + *
> > + * 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
> > + *
> > + * Unless required by applicable law or agreed to in writing,
> > + * software distributed under the License is distributed on an
> > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> > + * KIND, either express or implied.  See the License for the
> > + * specific language governing permissions and limitations
> > + * under the License.
> > + *
> > + *************************************************************/
> > +
> > +
> > +
> > +#include "uno/mapping.h"
> > +
> > +#include <typeinfo>
> > +#include <exception>
> > +#include <cstddef>
> > +
> > +namespace CPPU_CURRENT_NAMESPACE
> > +{
> > +
> > +void dummy_can_throw_anything( char const * );
> > +
> > +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
> > +
> > +// ----- the following structure is compatible with the one declared in
> libunwind's unwind.h
> > +// (use forced types)
> > +
> > +struct _Unwind_Exception
> > +{
> > +    uint64_t exception_class;
> > +    void * exception_cleanup;
> > +    uintptr_t private_1;
> > +    uintptr_t private_2;
> > +};
> > +
> > +struct __cxa_exception
> > +{
> > +    /* From LLVM 10 a reserved member was added at the top of the
> struct on
> > +       64-bit targets. Who the hell does that?
> > +
> https://reviews.llvm.org/rG674ec1eb16678b8addc02a4b0534ab383d22fa77
> > +       It is required on arm64 (Apple Silicon): the trailing
> _Unwind_Exception
> > +       must be 16-byte aligned within the allocation, and only WITH
> this member
> > +       does unwindHeader land at a 16-byte boundary (offset 96, vs a
> misaligned
> > +       88 without it).  Verified empirically against this host's
> libc++abi.
> > +       NOTE: Apple clang version != upstream LLVM version. */
> > +    void *reserved;
> > +    size_t referenceCount;
> > +    ::std::type_info *exceptionType;
> > +    void (*exceptionDestructor)(void *);
> > +    ::std::unexpected_handler unexpectedHandler;
> > +    ::std::terminate_handler terminateHandler;
> > +    __cxa_exception *nextException;
> > +    int handlerCount;
> > +    int handlerSwitchValue;
> > +    const unsigned char *actionRecord;
> > +    const unsigned char *languageSpecificData;
> > +    void *catchTemp;
> > +    void *adjustedPtr;
> > +    _Unwind_Exception unwindHeader;
> > +};
> > +
> > +extern "C" void *__cxa_allocate_exception(
> > +    std::size_t thrown_size ) throw();
> > +extern "C" void __cxa_throw (
> > +    void *thrown_exception, std::type_info *tinfo, void (*dest) (void
> *) ) __attribute__((noreturn));
> > +
> > +struct __cxa_eh_globals
> > +{
> > +    __cxa_exception *caughtExceptions;
> > +    unsigned int uncaughtExceptions;
> > +};
> > +extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
> > +
> > +// -----
> > +
> > +// on OSX 64bit the class_type_info classes are specified
> > +// in http://refspecs.linuxbase.org/cxxabi-1.86.html#rtti but
> > +// these details are not generally available in a public header
> > +// of most development environments. So we define them here.
> > +// NOTE:
> https://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012-Skochinsky-Compiler-Internals.pdf
> > +class __class_type_info : public std::type_info
> > +{
> > +public:
> > +        explicit __class_type_info( const char* pRttiName)
> > +        : std::type_info( pRttiName)
> > +        {}
> > +};
> > +
> > +class __si_class_type_info : public __class_type_info
> > +{
> > +        const __class_type_info* mpBaseType;
> > +public:
> > +        explicit __si_class_type_info( const char* pRttiName,
> __class_type_info* pBaseType)
> > +        : __class_type_info( pRttiName), mpBaseType( pBaseType)
> > +        {}
> > +};
> > +
> >
> +//==================================================================================================
> > +void raiseException(
> > +    uno_Any * pUnoExc, uno_Mapping * pUno2Cpp );
> >
> +//==================================================================================================
> > +void fillUnoException(
> > +    __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno );
> > +}
> > diff --git
> a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx
> b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx
> > new file mode 100644
> > index 0000000000..adaa3f2a5f
> > --- /dev/null
> > +++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx
> > @@ -0,0 +1,581 @@
> > +/**************************************************************
> > + *
> > + * 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
> > + *
> > + * Unless required by applicable law or agreed to in writing,
> > + * software distributed under the License is distributed on an
> > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> > + * KIND, either express or implied.  See the License for the
> > + * specific language governing permissions and limitations
> > + * under the License.
> > + *
> > + *************************************************************/
> > +
> > +
> > +
> > +// MARKER(update_precomp.py): autogen include statement, do not remove
> > +#include "precompiled_bridges.hxx"
> > +
> > +#include <exception>
> > +#include <typeinfo>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +
> > +#include "rtl/alloc.h"
> > +#include "rtl/ustrbuf.hxx"
> > +
> > +#include <com/sun/star/uno/genfunc.hxx>
> > +#include "com/sun/star/uno/RuntimeException.hpp"
> > +#include <uno/data.h>
> > +
> > +#include <bridges/cpp_uno/shared/bridge.hxx>
> > +#include <bridges/cpp_uno/shared/types.hxx>
> > +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
> > +#include "bridges/cpp_uno/shared/vtables.hxx"
> > +
> > +#include "abi.hxx"
> > +#include "share.hxx"
> > +
> > +using namespace ::rtl;
> > +using namespace ::com::sun::star::uno;
> > +
> >
> +//==================================================================================================
> > +
> > +// The AArch64 outgoing-call trampoline, implemented in call.s.  It
> loads the
> > +// argument registers from the caller-prepared arrays, copies overflow
> args to
> > +// the outgoing stack, performs the indirect call, and returns x0/x1
> and d0..d3.
> > +extern "C" void callVirtualFunction(
> > +    sal_uInt64 pFunction, sal_uInt64 pIndirectRet,
> > +    sal_uInt64 *pGPR, double *pFPR,
> > +    sal_uInt64 *pStack, sal_uInt32 nStackWords,
> > +    sal_uInt64 *pGPRReturn, double *pFPRReturn );
> > +
> > +static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
> > +                              void * pRegisterReturn,
> typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
> > +                              void * pIndirectReturn,
> > +                              sal_uInt64 *pStack, sal_uInt32 nStack,
> > +                              sal_uInt64 *pGPR, sal_uInt32 nGPR,
> > +                              double *pFPR, sal_uInt32 nFPR)
> __attribute__((noinline));
> > +
> > +static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
> > +                              void * pRegisterReturn,
> typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
> > +                              void * pIndirectReturn,
> > +                              sal_uInt64 *pStack, sal_uInt32 nStack,
> > +                              sal_uInt64 *pGPR, sal_uInt32 nGPR,
> > +                              double *pFPR, sal_uInt32 nFPR)
> > +{
> > +#if OSL_DEBUG_LEVEL > 1
> > +    // Let's figure out what is really going on here
> > +    {
> > +        fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR
> );
> > +        for ( unsigned int i = 0; i < nGPR; ++i )
> > +            fprintf( stderr, "0x%lx, ", pGPR[i] );
> > +        fprintf( stderr, "\nFPR's (%d): ", nFPR );
> > +        for ( unsigned int i = 0; i < nFPR; ++i )
> > +            fprintf( stderr, "%f, ", pFPR[i] );
> > +        fprintf( stderr, "\nStack (%d): ", nStack );
> > +        for ( unsigned int i = 0; i < nStack; ++i )
> > +            fprintf( stderr, "0x%lx, ", pStack[i] );
> > +        fprintf( stderr, "\n" );
> > +    }
> > +#endif
> > +
> > +    // The call instruction within callVirtualFunction may throw
> exceptions.  So
> > +    // that the compiler handles this correctly, it is important that
> (a)
> > +    // callVirtualMethod might call dummy_can_throw_anything (although
> this never
> > +    // happens at runtime), which in turn can throw exceptions, and (b)
> > +    // callVirtualMethod is not inlined at its call site (so that any
> exceptions
> > +    // thrown across the call are caught):
> > +    if ( !pThis )
> > +        CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); //
> address something
> > +
> > +    // Should not happen, but...
> > +    if ( nFPR > aarch64::MAX_FPR_REGS )
> > +        nFPR = aarch64::MAX_FPR_REGS;
> > +    if ( nGPR > aarch64::MAX_GPR_REGS )
> > +        nGPR = aarch64::MAX_GPR_REGS;
> > +
> > +    // Get pointer to the C++ virtual method from the vtable.
> > +    sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
> > +    pMethod += 8 * nVtableIndex;
> > +    pMethod = *((sal_uInt64 *)pMethod);
> > +
> > +    // Return register save areas: x0,x1 and d0..d3 (HFA up to 4
> elements).
> > +    sal_uInt64 gpReturn[2] = { 0, 0 };
> > +    double fpReturn[4] = { 0, 0, 0, 0 };
> > +
> > +    // Ensure the GPR/FPR arrays are the full register width even if
> fewer were
> > +    // filled (the trampoline always loads all 8 of each).
> > +    sal_uInt64 gpr[aarch64::MAX_GPR_REGS];
> > +    double fpr[aarch64::MAX_FPR_REGS];
> > +    for ( sal_uInt32 i = 0; i < aarch64::MAX_GPR_REGS; ++i )
> > +        gpr[i] = ( i < nGPR ) ? pGPR[i] : 0;
> > +    for ( sal_uInt32 i = 0; i < aarch64::MAX_FPR_REGS; ++i )
> > +        fpr[i] = ( i < nFPR ) ? pFPR[i] : 0;
> > +
> > +    callVirtualFunction(
> > +        pMethod,
> > +        reinterpret_cast<sal_uInt64>( pIndirectReturn ), // x8, 0 if
> none
> > +        gpr, fpr,
> > +        pStack, nStack,
> > +        gpReturn, fpReturn );
> > +
> > +    switch (pReturnTypeRef->eTypeClass)
> > +    {
> > +    case typelib_TypeClass_HYPER:
> > +    case typelib_TypeClass_UNSIGNED_HYPER:
> > +        *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) =
> gpReturn[0];
> > +        break;
> > +    case typelib_TypeClass_LONG:
> > +    case typelib_TypeClass_UNSIGNED_LONG:
> > +    case typelib_TypeClass_ENUM:
> > +        *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) =
> *reinterpret_cast<sal_uInt32*>( &gpReturn[0] );
> > +        break;
> > +    case typelib_TypeClass_CHAR:
> > +    case typelib_TypeClass_SHORT:
> > +    case typelib_TypeClass_UNSIGNED_SHORT:
> > +        *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) =
> *reinterpret_cast<sal_uInt16*>( &gpReturn[0] );
> > +        break;
> > +    case typelib_TypeClass_BOOLEAN:
> > +    case typelib_TypeClass_BYTE:
> > +        *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) =
> *reinterpret_cast<sal_uInt8*>( &gpReturn[0] );
> > +        break;
> > +    case typelib_TypeClass_FLOAT:
> > +    case typelib_TypeClass_DOUBLE:
> > +        *reinterpret_cast<double *>( pRegisterReturn ) = fpReturn[0];
> > +        break;
> > +    default:
> > +        {
> > +            sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
> > +            if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
> > +            {
> > +                // Register-returned aggregate: an HFA arrives in
> d0..d3, a
> > +                // non-HFA <= 16 bytes in x0,x1.  fill_struct picks the
> right one.
> > +                aarch64::fill_struct( pReturnTypeRef, &gpReturn[0],
> &fpReturn[0], pRegisterReturn);
> > +            }
> > +            break;
> > +        }
> > +    }
> > +}
> > +
> >
> +//==================================================================================================
> > +
> > +// Macros for easier insertion of values to registers or stack
> > +// pSV - pointer to the source
> > +// nr - order of the value [will be increased if stored to register]
> > +// pFPR, pGPR - pointer to the registers
> > +// pDS - pointer to the stack [will be increased if stored here]
> > +
> > +// The pFPR slot holds the value to be loaded into a v register; the
> trampoline
> > +// loads it with LDR d<n>, so float and double are stored the same way
> here.
> > +#define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \
> > +     if ( nr < aarch64::MAX_FPR_REGS ) \
> > +             pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
> > +     else \
> > +             *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); //
> verbatim!
> > +
> > +#define INSERT_INT64( pSV, nr, pGPR, pDS ) \
> > +     if ( nr < aarch64::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 < aarch64::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 < aarch64::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 < aarch64::MAX_GPR_REGS ) \
> > +             pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
> > +     else \
> > +             *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
> > +
> >
> +//==================================================================================================
> > +
> > +namespace {
> > +
> > +void appendCString(OUStringBuffer & buffer, char const * text) {
> > +    if (text != 0) {
> > +        buffer.append(
> > +            OStringToOUString(OString(text),
> RTL_TEXTENCODING_ISO_8859_1));
> > +            // use 8859-1 to avoid conversion failure
> > +    }
> > +}
> > +
> > +}
> > +
> > +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 )
> > +{
> > +     // Maxium space for [complex ret ptr], values | ptr ...
> > +     // (but will be used less - some of the values will be in pGPR and
> pFPR)
> > +     sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( (nParams + 3)
> * sizeof(sal_uInt64) );
> > +     sal_uInt64 *pStackStart = pStack;
> > +
> > +     sal_uInt64 pGPR[aarch64::MAX_GPR_REGS];
> > +     sal_uInt32 nGPR = 0;
> > +
> > +     double pFPR[aarch64::MAX_FPR_REGS];
> > +     sal_uInt32 nFPR = 0;
> > +
> > +     // Return
> > +     typelib_TypeDescription * pReturnTypeDescr = 0;
> > +     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
> > +     OSL_ENSURE( pReturnTypeDescr, "### expected return type
> description!" );
> > +
> > +     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs
> reconversion (see below)
> > +
> > +     // Indirect-result pointer. On AArch64 this is passed in the
> dedicated x8
> > +     // register, NOT as the first general-purpose argument (unlike
> x86-64 SysV).
> > +     // So we do NOT insert it into pGPR here; it is threaded to the
> trampoline
> > +     // separately as pIndirectReturn.
> > +     void * pIndirectReturn = 0;
> > +
> > +     bool bSimpleReturn = true;
> > +     if ( pReturnTypeDescr )
> > +     {
> > +             if ( aarch64::return_in_hidden_param( pReturnTypeRef ) )
> > +                     bSimpleReturn = false;
> > +
> > +             if ( bSimpleReturn )
> > +                     pCppReturn = pUnoReturn; // direct way for simple
> types
> > +             else
> > +             {
> > +                     // complex return via the x8 indirect-result buffer
> > +                     pCppReturn =
> bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
> > +                                              __builtin_alloca(
> pReturnTypeDescr->nSize ) : pUnoReturn;
> > +                     pIndirectReturn = pCppReturn;
> > +             }
> > +     }
> > +
> > +     // Push "this" pointer
> > +     void * pAdjustedThisPtr = reinterpret_cast< void ** >(
> pThis->getCppI() ) + aVtableSlot.offset;
> > +     INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
> > +
> > +     // Args
> > +     void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
> > +     // Indizes of values this have to be converted (interface
> conversion cpp<=>uno)
> > +     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
> > +     // Type descriptions for reconversions
> > +     typelib_TypeDescription ** ppTempParamTypeDescr =
> (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
> > +
> > +     sal_Int32 nTempIndizes = 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:
> > +                     case typelib_TypeClass_DOUBLE:
> > +                             INSERT_FLOAT_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 );
> > +                             pTempIndizes[nTempIndizes] = nPos; //
> default constructed for cpp call
> > +                             // will be released at reconversion
> > +                             ppTempParamTypeDescr[nTempIndizes++] =
> 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() );
> > +
> > +                             pTempIndizes[nTempIndizes] = nPos; // has
> to be reconverted
> > +                             // will be released at reconversion
> > +                             ppTempParamTypeDescr[nTempIndizes++] =
> pParamTypeDescr;
> > +                     }
> > +                     else // direct way
> > +                     {
> > +                             pCppArgs[nPos] = pUnoArgs[nPos];
> > +                             // no longer needed
> > +                             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
> > +                     }
> > +                     INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR,
> pStack );
> > +             }
> > +     }
> > +
> > +     try
> > +     {
> > +        try {
> > +            callVirtualMethod(
> > +                pAdjustedThisPtr, aVtableSlot.index,
> > +                pCppReturn, pReturnTypeRef, bSimpleReturn,
> > +                pIndirectReturn,
> > +                pStackStart, ( pStack - pStackStart ),
> > +                pGPR, nGPR,
> > +                pFPR, nFPR );
> > +        } catch (Exception &) {
> > +            throw;
> > +        } catch (std::exception & e) {
> > +            OUStringBuffer buf;
> > +            buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("C++ code threw
> "));
> > +            appendCString(buf, typeid(e).name());
> > +            buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": "));
> > +            appendCString(buf, e.what());
> > +            throw RuntimeException(
> > +                buf.makeStringAndClear(), Reference< XInterface >());
> > +        } catch (...) {
> > +            throw RuntimeException(
> > +                OUString(
> > +                    RTL_CONSTASCII_USTRINGPARAM(
> > +                        "C++ code threw unknown exception")),
> > +                Reference< XInterface >());
> > +        }
> > +
> > +             // NO exception occurred...
> > +             *ppUnoExc = 0;
> > +
> > +             // reconvert temporary params
> > +             for ( ; nTempIndizes--; )
> > +             {
> > +                     sal_Int32 nIndex = pTempIndizes[nTempIndizes];
> > +                     typelib_TypeDescription * pParamTypeDescr =
> ppTempParamTypeDescr[nTempIndizes];
> > +
> > +                     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
> > +             fillUnoException(
> CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc,
> pThis->getBridge()->getCpp2Uno() );
> > +
> > +             // temporary params
> > +             for ( ; nTempIndizes--; )
> > +             {
> > +                     sal_Int32 nIndex = pTempIndizes[nTempIndizes];
> > +                     // destroy temp cpp param => cpp: every param was
> constructed
> > +                     uno_destructData( pCppArgs[nIndex],
> ppTempParamTypeDescr[nTempIndizes], cpp_release );
> > +                     TYPELIB_DANGER_RELEASE(
> ppTempParamTypeDescr[nTempIndizes] );
> > +             }
> > +             // return type
> > +             if (pReturnTypeDescr)
> > +                     TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
> > +     }
> > +}
> > +
> >
> +//==================================================================================================
> > +
> > +namespace bridges { namespace cpp_uno { namespace 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;
> > +             OSL_ENSURE( 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(
> RTL_CONSTASCII_USTRINGPARAM("void") );
> > +                     typelib_typedescriptionreference_new(
> > +                             &pReturnTypeRef, typelib_TypeClass_VOID,
> aVoidName.pData );
> > +
> > +                     // dependent dispatch
> > +                     aVtableSlot.index += 1; // get, then set method
> > +                     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;
> > +             OSL_ENSURE( 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()
> > +             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(
> > +                     OUString( RTL_CONSTASCII_USTRINGPARAM("illegal
> member type description!") ),
> > +                     ::com::sun::star::uno::Reference<
> ::com::sun::star::uno::XInterface >() );
> > +
> > +             Type const & rExcType = ::getCppuType( &aExc );
> > +             // binary identical null reference
> > +             ::uno_type_any_construct( *ppException, &aExc,
> rExcType.getTypeLibType(), 0 );
> > +     }
> > +     }
> > +}
> > +
> > +} } }
> > diff --git a/main/configure.ac b/main/configure.ac
> > index 3f67e5b3fb..8731dc71f4 100644
> > --- a/main/configure.ac
> > +++ b/main/configure.ac
> > @@ -922,8 +922,8 @@ AC_ARG_WITH(arm-target,
> > AC_ARG_WITH(macosx-target,
> > [  --macosx-target            The minimal macOS/OSX deployment and build
> target
> >
> > -                              Usage: --with-macosx-target=10.9
> > -],with_macosx_target=$withval,with_macosx_target=10.9)
> > +                              Usage: --with-macosx-target=11.0
> > +],with_macosx_target=$withval,with_macosx_target=11.0)
> > AC_ARG_WITH(macosx-sdk,
> > [  --macosx-sdk            The macOS SDK to build against
> >
> > @@ -1159,9 +1159,29 @@ case "$build_os" in
> >               fi
> >               # Don't use OSVERSION until we know no conflicts result
> from it
> >               _darwin_version="`uname -r | $AWK -F . '{ print $1 }'`"
> > -             # FIXME: Assumes 10.x, breaks w/ Big Sur
> > -             _osx_version="10.`expr $_darwin_version - 4`"
> > +             # Map the Darwin (XNU) major version to the macOS version.
> > +             # Darwin 6..19  => macOS 10.(darwin-4)   (10.2 .. 10.15)
> > +             # Darwin 20+    => macOS (darwin-9)       (11, 12, 13, ...)
> > +             if test "$_darwin_version" -ge 20; then
> > +                _osx_version="`expr $_darwin_version - 9`"
> > +             else
> > +                _osx_version="10.`expr $_darwin_version - 4`"
> > +             fi
> >               AC_MSG_NOTICE([Detected Darwin version: $_darwin_version
> ($_osx_version)])
> > +             # Detect the build CPU architecture. Apple Silicon (arm64)
> reports
> > +             # "arm64" from uname -m and maps to the aarch64
> toolchain/bridge.
> > +             _darwin_cpu="`uname -m`"
> > +             case "$_darwin_cpu" in
> > +                arm64|aarch64)
> > +                   AC_MSG_NOTICE([Detected Apple Silicon (arm64) build
> host])
> > +                   ;;
> > +                x86_64|i*86)
> > +                   AC_MSG_NOTICE([Detected Intel (x86_64) build host])
> > +                   ;;
> > +                *)
> > +                   AC_MSG_ERROR([Unsupported macOS CPU architecture:
> $_darwin_cpu])
> > +                   ;;
> > +             esac
> >               ;;
> >       os2*)
> >               test_x=no
> > @@ -3907,10 +3927,20 @@ if test  "$_os" = "Darwin"; then
> >    sdk_target=$with_macosx_target
> >    AC_MSG_CHECKING([checking SDK compatibility with OSX $sdk_target])
> >
> > +   sdk_major=`echo $sdk_target | cut -d"." -f1`
> >    sdk_minor=`echo $sdk_target | cut -d"." -f2`
> > +   test -z "$sdk_minor" && sdk_minor=0
> > +
> > +   dnl Minimum supported macOS is 11.0 (Big Sur). Pre-11 targets are
> only
> > +   dnl accepted down to the old 10.9 floor for legacy Intel builds.
> > +   if test "$_darwin_cpu" = "arm64" -o "$_darwin_cpu" = "aarch64"; then
> > +      if test "$sdk_major" -lt "11"; then
> > +         AC_MSG_ERROR([Apple Silicon (arm64) requires
> --with-macosx-target=11.0 or later])
> > +      fi
> > +   fi
> >
> > -   if test "$sdk_minor" -lt "9"; then
> > -      AC_MSG_ERROR([SDK version < 10.9 is not longer supported])
> > +   if test "$sdk_major" -lt "10" -o \( "$sdk_major" -eq "10" -a
> "$sdk_minor" -lt "9" \); then
> > +      AC_MSG_ERROR([macOS deployment target < 10.9 is no longer
> supported])
> >    else
> >       MACOSX_DEPLOYMENT_TARGET=$sdk_target
> >       sdk_path=$with_macosx_sdk
> > diff --git a/main/icu/icu4c-4_2_1-src.patch
> b/main/icu/icu4c-4_2_1-src.patch
> > index 77fc719528..572572a3ea 100644
> > --- a/main/icu/icu4c-4_2_1-src.patch
> > +++ b/main/icu/icu4c-4_2_1-src.patch
> > @@ -212,7 +212,7 @@ diff -ru misc/icu/source/tools/genuca/genuca.cpp
> misc/build/icu/source/tools/gen
> > +     echo "${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}"
> >       case "${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}" in  #(
> > -       *-arch*ppc*|*-arch*i386*|*-arch*x86_64*)
> ac_cv_c_bigendian=universal;;
> > -+      *-arch*i386*|*-arch*x86_64*) ac_cv_c_bigendian=no;;
> > ++      *-arch*i386*|*-arch*x86_64*|*-arch*arm64*|*-arch*aarch64*)
> ac_cv_c_bigendian=no;;
> > +       *-arch*ppc*) ac_cv_c_bigendian=yes;;
> >       esac
> >  else
> > diff --git a/main/jvmfwk/plugins/sunmajor/pluginlib/util.cxx
> b/main/jvmfwk/plugins/sunmajor/pluginlib/util.cxx
> > index daec7fe94a..fbeb1ef201 100644
> > --- a/main/jvmfwk/plugins/sunmajor/pluginlib/util.cxx
> > +++ b/main/jvmfwk/plugins/sunmajor/pluginlib/util.cxx
> > @@ -102,6 +102,12 @@ struct JavaSearchPathEntry {
> > struct JavaSearchPathEntry g_arSearchPaths[] = {
> > #ifdef MACOSX
> >     { 0, "" },
> > +    // Modern macOS JDK location (Oracle/Temurin/etc., both arm64 and
> x86_64
> > +    // install here). Each subdirectory is a JDK whose home is
> Contents/Home,
> > +    // so scan the immediate contents. A JDK of the wrong architecture
> (e.g. a
> > +    // Rosetta x86_64 JDK on Apple Silicon) is harmlessly skipped when
> its
> > +    // libjvm.dylib fails to load into the native-arch process.
> > +    { 1, "Library/Java/JavaVirtualMachines/" },
> >     { 0, "Library/Internet
> Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin" },
> >     { 0, "System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/" },
> > #else
> > @@ -1245,6 +1251,14 @@ void
> createJavaInfoDirScan(vector<rtl::Reference<VendorBase> >& vecInfos)
> >                                    OUSTR(" is a Java. \n"));
> >
> >                         getJREInfoByPath(aStatus.getFileURL(),vecInfos);
> > +#ifdef MACOSX
> > +                        // On macOS a JDK bundle's home is at
> <bundle>/Contents/Home
> > +                        // (e.g. under
> /Library/Java/JavaVirtualMachines/<jdk>/),
> > +                        // not the bundle directory itself, so also
> probe there.
> > +                        getJREInfoByPath(
> > +                            aStatus.getFileURL() +
> > +                            OUSTR("/Contents/Home"), vecInfos);
> > +#endif
> >                     }
> >
> >                     JFW_ENSURE(errNext == File::E_None || errNext ==
> File::E_NOENT,
> > diff --git a/main/openssl/makefile.mk b/main/openssl/makefile.mk
> > index cecba9e26e..a5662eabea 100644
> > --- a/main/openssl/makefile.mk
> > +++ b/main/openssl/makefile.mk
> > @@ -107,8 +107,12 @@ UNAME=$(shell uname)
> > .ENDIF
> >
> > .IF "$(OS)" == "MACOSX"
> > +.IF "$(CPUNAME)" == "AARCH64"
> > +     CONFIGURE_ACTION=Configure darwin64-arm64-cc no-dso no-shared
> $(NO_ASM)
> > +.ELSE
> >       CONFIGURE_ACTION=Configure darwin64-x86_64-cc no-dso no-shared
> $(NO_ASM)
> > .ENDIF
> > +.ENDIF
> >
> > .IF "$(OS)" == "WNT"
> >
> > diff --git a/main/python/pyversion.mk b/main/python/pyversion.mk
> > index 353925e92e..95f7b299da 100644
> > --- a/main/python/pyversion.mk
> > +++ b/main/python/pyversion.mk
> > @@ -20,8 +20,8 @@
> > # *************************************************************
> > # when you want to change the python version, you must update the d.lst
> > # in the python project accordingly !!!
> > -PYMAJOR=2
> > -PYMINOR=7
> > +PYMAJOR=3
> > +PYMINOR=10
> > PYMICRO=18
> > PYVERSION=$(PYMAJOR).$(PYMINOR).$(PYMICRO)
> >
> > diff --git a/main/python/pyversion_dmake.mk b/main/python/
> pyversion_dmake.mk
> > index 37aa099277..b8252a9767 100644
> > --- a/main/python/pyversion_dmake.mk
> > +++ b/main/python/pyversion_dmake.mk
> > @@ -20,8 +20,8 @@
> > # *************************************************************
> > # when you want to change the python version, you must update the d.lst
> > # in the python project accordingly !!!
> > -PYMAJOR=2
> > -PYMINOR=7
> > +PYMAJOR=3
> > +PYMINOR=10
> > PYMICRO=18
> > PYVERSION=$(PYMAJOR).$(PYMINOR).$(PYMICRO)
> >
> > diff --git a/main/pyuno/source/loader/pythonloader.py
> b/main/pyuno/source/loader/pythonloader.py
> > index 46e051da98..34ff1c532b 100644
> > --- a/main/pyuno/source/loader/pythonloader.py
> > +++ b/main/pyuno/source/loader/pythonloader.py
> > @@ -21,7 +21,7 @@
> > import uno
> > import unohelper
> > import sys
> > -import imp
> > +import types
> > import os
> > from com.sun.star.uno import Exception,RuntimeException
> > from com.sun.star.loader import XImplementationLoader
> > @@ -84,14 +84,14 @@ class Loader( XImplementationLoader, XServiceInfo,
> unohelper.Base ):
> >                 # did we load the module already ?
> >                 mod = g_loadedComponents.get( url )
> >                 if not mod:
> > -                    mod = imp.new_module("uno_component")
> > +                    mod = types.ModuleType("uno_component")
> >
> >                     # check for pythonpath.zip beside .py files
> >                     checkForPythonPathBesideComponent(
> url[0:url.rfind('/')] )
> >
> >                     # read the file
> >                     filename = unohelper.fileUrlToSystemPath( url )
> > -                    fileHandle = file( filename )
> > +                    fileHandle = open( filename )
> >                     src = fileHandle.read().replace("\r","")
> >                     if not src.endswith( "\n" ):
> >                         src = src + "\n"
> > diff --git a/main/sal/osl/unx/interlck.c b/main/sal/osl/unx/interlck.c
> > index cfcea0fbc0..d24db7b341 100644
> > --- a/main/sal/osl/unx/interlck.c
> > +++ b/main/sal/osl/unx/interlck.c
> > @@ -178,6 +178,29 @@ oslInterlockedCount SAL_CALL
> osl_decrementInterlockedCount(oslInterlockedCount*
> > #endif
> > }
> >
> > +#elif (defined(__GNUC__) || defined(__clang__)) && defined ( AARCH64 )
> > +/* AArch64 (ARM 64-bit, e.g. Apple Silicon). Use the compiler's atomic
> > +   built-ins, which clang/gcc lower to the AArch64
> load-exclusive/store-exclusive
> > +   (ldaxr/stlxr) sequence, or to LSE atomics (ldadd) on ARMv8.1+. This
> avoids the
> > +   global-mutex fallback below. __sync_*_and_fetch are full-barrier and
> return
> > +   the new value, matching the required semantics. */
> > +
> >
> +/*****************************************************************************/
> > +/* osl_incrementInterlockedCount */
> >
> +/*****************************************************************************/
> > +oslInterlockedCount SAL_CALL
> osl_incrementInterlockedCount(oslInterlockedCount* pCount)
> > +{
> > +    return __sync_add_and_fetch( pCount, 1 );
> > +}
> > +
> >
> +/*****************************************************************************/
> > +/* osl_decrementInterlockedCount */
> >
> +/*****************************************************************************/
> > +oslInterlockedCount SAL_CALL
> osl_decrementInterlockedCount(oslInterlockedCount* pCount)
> > +{
> > +    return __sync_sub_and_fetch( pCount, 1 );
> > +}
> > +
> > #else
> > /* use only if nothing else works, expensive due to single mutex for all
> reference counts */
> >
> > diff --git a/main/sal/rtl/source/macro.hxx
> b/main/sal/rtl/source/macro.hxx
> > index 10948868f3..4aee4358aa 100644
> > --- a/main/sal/rtl/source/macro.hxx
> > +++ b/main/sal/rtl/source/macro.hxx
> > @@ -77,6 +77,8 @@ this is inserted for the case that the preprocessor
> ignores error
> > #    else
> > #        define THIS_ARCH "MIPS_EL"
> > #    endif
> > +#elif defined AARCH64
> > +#    define THIS_ARCH "AARCH64"
> > #elif defined ARM
> > #    ifdef __ARM_EABI__
> > #        define THIS_ARCH "ARM_EABI"
> > diff --git a/main/scripting/source/pyprov/mailmerge.py
> b/main/scripting/source/pyprov/mailmerge.py
> > index 4a4c430c28..c11ddd8c7a 100644
> > --- a/main/scripting/source/pyprov/mailmerge.py
> > +++ b/main/scripting/source/pyprov/mailmerge.py
> > @@ -54,13 +54,13 @@ from com.sun.star.lang import
> IllegalArgumentException
> > from com.sun.star.lang import EventObject
> > from com.sun.star.mail import SendMailMessageFailedException
> >
> > -from email.MIMEBase import MIMEBase
> > -from email.Message import Message
> > -from email import Encoders
> > -from email.Header import Header
> > -from email.MIMEMultipart import MIMEMultipart
> > -from email.Utils import formatdate
> > -from email.Utils import parseaddr
> > +from email.mime.base import MIMEBase
> > +from email.message import Message
> > +from email import encoders
> > +from email.header import Header
> > +from email.mime.multipart import MIMEMultipart
> > +from email.utils import formatdate
> > +from email.utils import parseaddr
> > from socket import _GLOBAL_DEFAULT_TIMEOUT
> >
> > import sys, smtplib, imaplib, poplib
> > @@ -245,7 +245,7 @@ class PyMailSMTPService(unohelper.Base,
> XSmtpService):
> >             msgattachment = MIMEBase(maintype, subtype)
> >             data = content.getTransferData(flavor)
> >             msgattachment.set_payload(data)
> > -            Encoders.encode_base64(msgattachment)
> > +            encoders.encode_base64(msgattachment)
> >             fname = attachment.ReadableName
> >             try:
> >                 fname.encode('ascii')
> > diff --git a/main/scripting/source/pyprov/pythonscript.py
> b/main/scripting/source/pyprov/pythonscript.py
> > index 4e7fc4667e..03f52b897a 100644
> > --- a/main/scripting/source/pyprov/pythonscript.py
> > +++ b/main/scripting/source/pyprov/pythonscript.py
> > @@ -24,7 +24,7 @@ import uno
> > import unohelper
> > import sys
> > import os
> > -import imp
> > +import types
> > import time
> > import ast
> >
> > @@ -356,7 +356,7 @@ class ScriptContext(unohelper.Base):
> > #        code = readTextFromStream( sfa.openFileRead( url ) )
> >
> >         # execute the module
> > -#        entry = ModuleEntry( lastRead,
> imp.new_module("ooo_script_framework") )
> > +#        entry = ModuleEntry( lastRead,
> types.ModuleType("ooo_script_framework") )
> > #        entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] =
> g_scriptContext
> > #        entry.module.__file__ = url
> > #        exec code in entry.module.__dict__
> > @@ -489,7 +489,7 @@ class ProviderContext:
> >             src = ensureSourceState( src )
> >
> >             # execute the module
> > -            entry = ModuleEntry( lastRead,
> imp.new_module("ooo_script_framework") )
> > +            entry = ModuleEntry( lastRead,
> types.ModuleType("ooo_script_framework") )
> >             entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] =
> self.scriptContext
> >
> >             code = None
> > @@ -666,7 +666,7 @@ class ScriptBrowseNode( unohelper.Base, XBrowseNode,
> XPropertySet, XInvocation,
> >             if event.ActionCommand == "Run":
> >                 code =
> self.editor.getControl("EditorTextField").getText()
> >                 code = ensureSourceState( code )
> > -                mod = imp.new_module("ooo_script_framework")
> > +                mod = types.ModuleType("ooo_script_framework")
> >                 mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] =
> self.provCtx.scriptContext
> >                 exec(code, mod.__dict__)
> >                 values = mod.__dict__.get( CALLABLE_CONTAINER_NAME ,
> None )
> > @@ -827,7 +827,7 @@ class FileBrowseNode( unohelper.Base, XBrowseNode,
> XPropertySet, XInvocation, XA
> >             if event.ActionCommand == "Run":
> >                 code =
> self.editor.getControl("EditorTextField").getText()
> >                 code = ensureSourceState( code )
> > -                mod = imp.new_module("ooo_script_framework")
> > +                mod = types.ModuleType("ooo_script_framework")
> >                 mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] =
> self.provCtx.scriptContext
> >                 exec(code, mod.__dict__)
> >                 values = mod.__dict__.get( CALLABLE_CONTAINER_NAME ,
> None )
> > diff --git a/main/set_soenv.in b/main/set_soenv.in
> > index 189b6afdfe..6812905f8e 100644
> > --- a/main/set_soenv.in
> > +++ b/main/set_soenv.in
> > @@ -807,6 +807,14 @@ elsif ( $platform =~ m/darwin/ )
> >           $CPUNAME        = "X86_64";
> >           $OUTPATH        = "unxmaccx";
> >       }
> > +      elsif ($platform =~ m/^(aarch64|arm64)/)
> > +      {
> > +          print "Setting values for MacOSX/Darwin on aarch64 (Apple
> Silicon)... ";
> > +          $outfile        = "MacOSXAARCH64Env.Set";
> > +          $CPU            = "R";
> > +          $CPUNAME        = "AARCH64";
> > +          $OUTPATH        = "unxmaccr";
> > +      }
> >       else
> >       {
> >         print "\nset_soenv: Unknown MacOSX/Darwin platform: $platform\n";
> > diff --git a/main/setup_native/source/mac/Info.plist.langpack
> b/main/setup_native/source/mac/Info.plist.langpack
> > index 0e12cc1c19..80ad91f30b 100644
> > --- a/main/setup_native/source/mac/Info.plist.langpack
> > +++ b/main/setup_native/source/mac/Info.plist.langpack
> > @@ -23,7 +23,7 @@
> > <plist version="1.0">
> > <dict>
> >       <key>LSMinimumSystemVersion</key>
> > -     <string>10.7.0</string>
> > +     <string>11.0</string>
> >       <key>CFBundleDevelopmentRegion</key>
> >       <string>English</string>
> >       <!-- UTI declarations for OS X >= 10.4  -->
> > diff --git a/main/solenv/bin/modules/installer/download.pm
> b/main/solenv/bin/modules/installer/download.pm
> > index 6605bbdbc6..6ad1570ab0 100644
> > --- a/main/solenv/bin/modules/installer/download.pm
> > +++ b/main/solenv/bin/modules/installer/download.pm
> > @@ -607,6 +607,10 @@ sub get_download_architecture
> >       {
> >               $arch = "x86-64";
> >       }
> > +     elsif ( $installer::globals::compiler =~ /^unxmaccr/ )
> > +     {
> > +             $arch = "aarch64";
> > +     }
> >       elsif ( $installer::globals::issolarissparcbuild )
> >       {
> >               $arch = "Sparc";
> > diff --git a/main/solenv/bin/modules/installer/worker.pm
> b/main/solenv/bin/modules/installer/worker.pm
> > index 0d387a3e33..ef22a34e2a 100644
> > --- a/main/solenv/bin/modules/installer/worker.pm
> > +++ b/main/solenv/bin/modules/installer/worker.pm
> > @@ -2280,6 +2280,10 @@ sub get_platform_name
> >       {
> >               $platformname = "MacOSXX86-64";
> >       }
> > +     elsif ( $installer::globals::compiler =~ /^unxmaccr/ )
> > +     {
> > +             $platformname = "MacOSXAArch64";
> > +     }
> >       elsif ( $installer::globals::compiler =~ /^unxmacxp/ )
> >       {
> >               $platformname = "MacOSXPowerPC";
> > diff --git a/main/solenv/bin/modules/osarch.pm
> b/main/solenv/bin/modules/osarch.pm
> > index 4ded37ed15..1093b81a27 100644
> > --- a/main/solenv/bin/modules/osarch.pm
> > +++ b/main/solenv/bin/modules/osarch.pm
> > @@ -102,7 +102,9 @@ chop( $m_str, $s_str );
> >                          "IP22",          "mips",         # voyager
> >                          "IP32",          "mips",         # giotto
> >                          "Power Macintosh",                   "ppc",
>               # NetBSD/arm32
> > -                        "arm32",                     "arm32"
>      # NetBSD/arm32
> > +                        "arm32",                     "arm32",
>       # NetBSD/arm32
> > +                        "arm64",                     "aarch64",
>       # macOS Apple Silicon (uname -m)
> > +                        "aarch64",           "aarch64"               #
> Linux aarch64
> >                          );
> >
> > %archDefTable=("sun4c",                       "-DSPARC -DSUN -DSUN4", #
> hawai
> > @@ -130,7 +132,9 @@ chop( $m_str, $s_str );
> >                          "IP22",          "-DMIPS",                   #
> voyager
> >                          "IP32",          "-DMIPS",                   #
> giotto
> >                          "Power Macintosh",           "-DPPC",
>       # NetBSD/arm32
> > -                        "arm32",                     "-DARM32"
>      # NetBSD/arm32
> > +                        "arm32",                     "-DARM32",
>       # NetBSD/arm32
> > +                        "arm64",                     "-DAARCH64",
>       # macOS Apple Silicon (uname -m)
> > +                        "aarch64",           "-DAARCH64"             #
> Linux aarch64
> >                          );
> >
> > %archDosTable=("sun4c",                       "s",            # hawai
> > @@ -158,7 +162,9 @@ chop( $m_str, $s_str );
> >                          "IP22",          "m",                # voyager
> >                          "IP32",          "m",                # giotto
> >                          "Power Macintosh",                   "p",
>               # NetBSD/arm32
> > -                        "arm32",                     "a"
>      # NetBSD/arm32
> > +                        "arm32",                     "a",
>       # NetBSD/arm32
> > +                        "arm64",                     "r",
>       # macOS Apple Silicon (uname -m)
> > +                        "aarch64",           "r"                     #
> Linux aarch64
> >                          );
> >
> > $main::solarDef               = $osDefTable{ $s_str }.' '.$archDefTable{
> $m_str };
> > diff --git a/main/solenv/bin/update_module_ignore_lists.pl
> b/main/solenv/bin/update_module_ignore_lists.pl
> > index 3a827d743f..f7eecef05d 100644
> > --- a/main/solenv/bin/update_module_ignore_lists.pl
> > +++ b/main/solenv/bin/update_module_ignore_lists.pl
> > @@ -47,6 +47,7 @@ my @platforms = (
> >         "unxmacxp",
> >         "unxmacci",
> >         "unxmaccx",
> > +        "unxmaccr",
> >         "unxubit8",
> >         "unxaixp",
> >         "unxbsda",
> > diff --git a/main/solenv/gbuild/platform/macosx.mk
> b/main/solenv/gbuild/platform/macosx.mk
> > index 3b5d65805a..b9501be453 100644
> > --- a/main/solenv/gbuild/platform/macosx.mk
> > +++ b/main/solenv/gbuild/platform/macosx.mk
> > @@ -64,6 +64,8 @@ ifeq ($(CPUNAME),POWERPC)
> > gb_CPUDEFS += -DPOWERPC -DPPC
> > else ifeq ($(CPUNAME),INTEL)
> > gb_CPUDEFS += -DX86
> > +else ifeq ($(CPUNAME),AARCH64)
> > +gb_CPUDEFS += -DARM64
> > endif
> >
> > ifeq ($(strip $(SYSBASE)),)
> > diff --git a/main/solenv/inc/unx.mk b/main/solenv/inc/unx.mk
> > index f956e43a82..b5b4731cd6 100644
> > --- a/main/solenv/inc/unx.mk
> > +++ b/main/solenv/inc/unx.mk
> > @@ -160,6 +160,10 @@
> > .INCLUDE : unxmaccx.mk
> > .ENDIF
> >
> > +.IF "$(COM)$(OS)$(CPU)" == "CLANGMACOSXR"
> > +.INCLUDE : unxmaccr.mk
> > +.ENDIF
> > +
> > .IF "$(OS)$(CPU)" == "LINUXM"
> > .INCLUDE : unxlngmips.mk
> > .ENDIF
> > diff --git a/main/solenv/inc/unxmaccr.mk b/main/solenv/inc/unxmaccr.mk
> > new file mode 100644
> > index 0000000000..0fdf36cc2d
> > --- /dev/null
> > +++ b/main/solenv/inc/unxmaccr.mk
> > @@ -0,0 +1,42 @@
> > +#**************************************************************
> > +#
> > +#  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
> > +#
> > +#  Unless required by applicable law or agreed to in writing,
> > +#  software distributed under the License is distributed on an
> > +#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> > +#  KIND, either express or implied.  See the License for the
> > +#  specific language governing permissions and limitations
> > +#  under the License.
> > +#
> > +#**************************************************************
> > +
> > +# Mac OSX aarch64 (Apple Silicon) specific defines
> > +
> > +PROCESSOR_DEFINES=-DAARCH64
> > +BUILD64=1
> > +
> > +DLLPOSTFIX=
> > +
> > +# Build explicitly for arm64. Use conditional assignment (*=) so the
> value can
> > +# still be overridden by exporting ARCH_FLAGS in the environment.
> unxmacc.mk
> > +# also declares ARCH_FLAGS*= (empty), which becomes a no-op once set
> here.
> > +ARCH_FLAGS*=-arch arm64
> > +
> > +# flags to enable build with symbols; required by crashdump feature
> > +.IF "$(ENABLE_SYMBOLS)"=="SMALL"
> > +CFLAGSENABLESYMBOLS=-g1
> > +.ELSE
> > +CFLAGSENABLESYMBOLS=-g
> > +.ENDIF
> > +
> > +# Include generic Mac OS X makefile
> > +.INCLUDE : unxmacc.mk
> > diff --git a/main/source_soenv.sh b/main/source_soenv.sh
> > index 9d522c359f..ce87621c36 100644
> > --- a/main/source_soenv.sh
> > +++ b/main/source_soenv.sh
> > @@ -108,6 +108,9 @@ else
> >         i[3456]86-*-darwin*|x86_64-*-darwin*)
> >             . ./MacOSXX64Env.Set.sh
> >         ;;
> > +        aarch64-*-darwin*|arm64-*-darwin*)
> > +            . ./MacOSXAARCH64Env.Set.sh
> > +        ;;
> >         powerpc-*-darwin*)
> >             . ./MacOSXPPCEnv.Set.sh
> >         ;;
> > diff --git a/main/sysui/desktop/macosx/Info.plist
> b/main/sysui/desktop/macosx/Info.plist
> > index d26d4251fe..9ffda6b8fa 100644
> > --- a/main/sysui/desktop/macosx/Info.plist
> > +++ b/main/sysui/desktop/macosx/Info.plist
> > @@ -23,7 +23,7 @@
> > <plist version="1.0">
> > <dict>
> >       <key>LSMinimumSystemVersion</key>
> > -     <string>10.7.0</string>
> > +     <string>11.0</string>
> >       <key>CFBundleDevelopmentRegion</key>
> >       <string>English</string>
> >       <!-- UTI declarations for OS X >= 10.4  -->
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>

Reply via email to