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] > >
