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]
