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 245a583a7b Substantially harden the macOS Silicon bridge
     new 9aebfb1384 Merge branch 'trunk' of 
https://github.com/apache/openoffice into trunk
245a583a7b is described below

commit 245a583a7b65e1047b3d72e26165ab349b0ae791
Author: Jim Jagielski <[email protected]>
AuthorDate: Mon Aug 3 07:56:36 2026 -0400

    Substantially harden the macOS Silicon bridge
---
 .../source/cpp_uno/s5abi_macosx_aarch64/abi.cxx    |  40 ++++-
 .../source/cpp_uno/s5abi_macosx_aarch64/abi.hxx    |   5 +
 .../source/cpp_uno/s5abi_macosx_aarch64/call.s     |  56 +++++--
 .../cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx       |  27 ++-
 .../source/cpp_uno/s5abi_macosx_aarch64/except.cxx | 184 +++++----------------
 .../source/cpp_uno/s5abi_macosx_aarch64/share.hxx  |  73 +-------
 .../cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx       | 138 ++++++++++------
 .../source/cpp_uno/shared/vtablefactory.cxx        |   6 +
 main/solenv/bin/addsym-macosx.sh                   |   2 +-
 main/solenv/src/component.map                      |   2 +
 main/testtools/source/bridgetest/bridgetest.cxx    |  54 ++++++
 main/testtools/source/bridgetest/cppobj.cxx        |  25 +++
 .../testtools/source/bridgetest/idl/bridgetest.idl |  48 ++++++
 13 files changed, 381 insertions(+), 279 deletions(-)

diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.cxx 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.cxx
index 48d7ce36aa..d99ee651ee 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.cxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.cxx
@@ -49,6 +49,7 @@
 #include "bridges/cpp_uno/shared/types.hxx"
 
 #include <rtl/ustring.hxx>
+#include <string.h>
 
 using namespace aarch64;
 
@@ -135,6 +136,14 @@ bool collectHfa( typelib_TypeDescriptionReference 
*pTypeRef, HfaKind &rKind, int
             for ( sal_Int32 i = 0; bOk && i < pComp->nMembers; ++i )
                 bOk = collectHfa( pComp->ppTypeRefs[i], rKind, rCount );
 
+            if ( bOk )
+            {
+                sal_Int32 elementSize = rKind == HFA_FLOAT ? 4 : 8;
+                bOk = pTypeDescr->nSize == rCount * elementSize;
+                for ( sal_Int32 i = 0; bOk && i < pComp->nMembers; ++i )
+                    bOk = pComp->pMemberOffsets[i] % elementSize == 0;
+            }
+
             TYPELIB_DANGER_RELEASE( pTypeDescr );
             return bOk;
         }
@@ -316,9 +325,32 @@ void aarch64::fill_struct( 
typelib_TypeDescriptionReference *pTypeRef, const sal
     }
     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];
+        typelib_TypeDescription * pTypeDescr = 0;
+        TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
+        // The registers contain up to 16 bytes, but the destination has the
+        // aggregate's exact size and need not be 64-bit aligned.
+        memcpy( pStruct, pGPR, pTypeDescr->nSize );
+        TYPELIB_DANGER_RELEASE( pTypeDescr );
     }
 }
+
+sal_uInt32 aarch64::align_stack_offset(
+    sal_uInt32 offset, typelib_TypeDescriptionReference *pTypeRef )
+{
+    typelib_TypeDescription * pTypeDescr = 0;
+    TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
+    sal_uInt32 alignment = pTypeDescr->nAlignment;
+    TYPELIB_DANGER_RELEASE( pTypeDescr );
+    if ( alignment == 0 )
+        alignment = 1;
+    return (offset + alignment - 1) & ~(alignment - 1);
+}
+
+sal_uInt32 aarch64::stack_size( typelib_TypeDescriptionReference *pTypeRef )
+{
+    typelib_TypeDescription * pTypeDescr = 0;
+    TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
+    sal_uInt32 size = pTypeDescr->nSize;
+    TYPELIB_DANGER_RELEASE( pTypeDescr );
+    return size;
+}
diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.hxx 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.hxx
index e6b210afdb..8bdd0d9a9d 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.hxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.hxx
@@ -90,6 +90,11 @@ sal_uInt32 get_return_kind( typelib_TypeDescriptionReference 
*pTypeRef );
 */
 void fill_struct( typelib_TypeDescriptionReference *pTypeRef, const 
sal_uInt64* pGPR, const double* pFPR, void *pStruct );
 
+sal_uInt32 align_stack_offset(
+    sal_uInt32 offset, typelib_TypeDescriptionReference *pTypeRef );
+
+sal_uInt32 stack_size( typelib_TypeDescriptionReference *pTypeRef );
+
 } // 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
index 25677b3294..90994778d1 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/call.s
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/call.s
@@ -32,8 +32,8 @@
 //     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
+//     unsigned char *pStack,     // x4: packed overflow-argument bytes
+//     sal_uInt32  nStackBytes,   // x5: byte count
 //     sal_uInt64 *pGPRReturn,    // x6: [out] x0,x1
 //     double     *pFPRReturn);   // x7: [out] d0..d3 (HFA up to 4 elements)
 
@@ -51,6 +51,12 @@ _callVirtualFunction:
     .cfi_def_cfa x29, 64
     .cfi_offset x29, -16
     .cfi_offset x30, -8
+    .cfi_offset x19, -32
+    .cfi_offset x20, -24
+    .cfi_offset x21, -48
+    .cfi_offset x22, -40
+    .cfi_offset x23, -64
+    .cfi_offset x24, -56
 
     // stash inputs that must survive the call into callee-saved registers
     mov     x19, x0                     // pFunction
@@ -61,17 +67,16 @@ _callVirtualFunction:
     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
+    // Round the packed byte area up to preserve 16-byte SP alignment.
+    add     x9, x5, #15
+    bic     x9, x9, #15
     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]
+    ldrb    w11, [x4, x10]
+    strb    w11, [sp, x10]
     add     x10, x10, #1
     b       Lcvf_copy
 Lcvf_copied:
@@ -168,10 +173,24 @@ _privateSnippetExecutor:
     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.
+    cmp     w0, #3                      // typelib_TypeClass_BYTE
+    b.eq    Lpse_signed_byte
+    cmp     w0, #4                      // typelib_TypeClass_SHORT
+    b.eq    Lpse_signed_short
+    cmp     w0, #1                      // typelib_TypeClass_CHAR
+    b.eq    Lpse_unsigned_short
+    cmp     w0, #5                      // typelib_TypeClass_UNSIGNED_SHORT
+    b.eq    Lpse_unsigned_short
+    cmp     w0, #2                      // typelib_TypeClass_BOOLEAN
+    b.eq    Lpse_unsigned_byte
+    cmp     w0, #6                      // typelib_TypeClass_LONG
+    b.eq    Lpse_word
+    cmp     w0, #7                      // typelib_TypeClass_UNSIGNED_LONG
+    b.eq    Lpse_word
+    cmp     w0, #15                     // typelib_TypeClass_ENUM
+    b.eq    Lpse_word
+    // Integer / pointer / <=16B aggregate.
     ldp     x0, x1, [sp, #144]
-    ldp     d0, d1, [sp, #144]
     b       Lpse_done
 Lpse_float:
     ldr     d0, [sp, #144]
@@ -185,6 +204,21 @@ Lpse_hfa_float:
 Lpse_hfa_double:
     ldp     d0, d1, [sp, #144]
     ldp     d2, d3, [sp, #160]
+    b       Lpse_done
+Lpse_signed_byte:
+    ldrsb   w0, [sp, #144]
+    b       Lpse_done
+Lpse_unsigned_byte:
+    ldrb    w0, [sp, #144]
+    b       Lpse_done
+Lpse_signed_short:
+    ldrsh   w0, [sp, #144]
+    b       Lpse_done
+Lpse_unsigned_short:
+    ldrh    w0, [sp, #144]
+    b       Lpse_done
+Lpse_word:
+    ldr     w0, [sp, #144]
 Lpse_done:
     mov     sp, x29
     ldp     x29, x30, [sp], #176
diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx
index 5d8161498e..c6bb914985 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx
@@ -69,12 +69,13 @@ static typelib_TypeClass cpp2uno_call(
        const typelib_TypeDescription * pMemberTypeDescr,
        typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void 
return
        sal_Int32 nParams, typelib_MethodParameter * pParams,
-       void ** gpreg, void ** fpreg, void ** ovrflw,
+       void ** gpreg, void ** fpreg, unsigned char * 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
+       sal_uInt32 stackOffset = 0;
 
        // return
        typelib_TypeDescription * pReturnTypeDescr = 0;
@@ -137,7 +138,12 @@ static typelib_TypeClass cpp2uno_call(
                                        nr_fpr++;
                                }
                                else
-                                       pCppArgs[nPos] = pUnoArgs[nPos] = 
ovrflw++;
+                               {
+                                       stackOffset = 
aarch64::align_stack_offset(
+                                               stackOffset, rParam.pTypeRef );
+                                       pCppArgs[nPos] = pUnoArgs[nPos] = 
ovrflw + stackOffset;
+                                       stackOffset += aarch64::stack_size( 
rParam.pTypeRef );
+                               }
                        }
                        else if ( nUsedGPR == 1 )
                        {
@@ -147,7 +153,12 @@ static typelib_TypeClass cpp2uno_call(
                                        nr_gpr++;
                                }
                                else
-                                       pCppArgs[nPos] = pUnoArgs[nPos] = 
ovrflw++;
+                               {
+                                       stackOffset = 
aarch64::align_stack_offset(
+                                               stackOffset, rParam.pTypeRef );
+                                       pCppArgs[nPos] = pUnoArgs[nPos] = 
ovrflw + stackOffset;
+                                       stackOffset += aarch64::stack_size( 
rParam.pTypeRef );
+                               }
                        }
                }
                else // struct <= 16 bytes || ptr to complex value || ref
@@ -162,7 +173,13 @@ static typelib_TypeClass cpp2uno_call(
                                nr_gpr++;
                        }
                        else
-                               pCppArgs[nPos] = pCppStack = *ovrflw++;
+                       {
+                               stackOffset = (stackOffset + sizeof(void *) - 
1) &
+                                       ~(sizeof(void *) - 1);
+                               pCppArgs[nPos] = pCppStack =
+                                       *reinterpret_cast<void **>( ovrflw + 
stackOffset );
+                               stackOffset += sizeof(void *);
+                       }
 
                        if (! rParam.bIn) // is pure out
                        {
@@ -264,7 +281,7 @@ static typelib_TypeClass cpp2uno_call(
 
//==================================================================================================
 extern "C" sal_uInt32 cpp_vtable_call(
        sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
-       void ** gpreg, void ** fpreg, void ** ovrflw,
+       void ** gpreg, void ** fpreg, unsigned char * ovrflw,
        void * pIndirectReturn, // AArch64 x8 indirect-result pointer (0 if 
none)
        sal_uInt64 * pRegisterReturn /* space for register return */ )
 {
diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/except.cxx 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/except.cxx
index 1e88673b81..7d920cf975 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/except.cxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/except.cxx
@@ -60,14 +60,27 @@ namespace CPPU_CURRENT_NAMESPACE
 
 namespace {
 
+typedef hash_map< void *, typelib_TypeDescription * > ThrownTypes;
 typedef hash_map< OUString, type_info *, OUStringHash > ObservedRttiMap;
 
+ThrownTypes & thrownTypes()
+{
+    static ThrownTypes types;
+    return types;
+}
+
 ObservedRttiMap & observedRttis()
 {
     static ObservedRttiMap map;
     return map;
 }
 
+Mutex & observedRttisMutex()
+{
+    static Mutex mutex;
+    return mutex;
+}
+
 }
 
 void dummy_can_throw_anything( char const * )
@@ -119,9 +132,6 @@ class RTTI
 
     Mutex m_mutex;
        t_rtti_map m_rttis;
-    t_rtti_map m_generatedRttis;
-
-    void * m_hApp;
 
 public:
     RTTI() SAL_THROW( () );
@@ -132,14 +142,12 @@ public:
 
 
//__________________________________________________________________________________________________
 RTTI::RTTI() SAL_THROW( () )
-    : m_hApp( dlopen( 0, RTLD_LAZY ) )
 {
 }
 
 
//__________________________________________________________________________________________________
 RTTI::~RTTI() SAL_THROW( () )
 {
-    dlclose( m_hApp );
 }
 
 
//__________________________________________________________________________________________________
@@ -151,9 +159,12 @@ type_info * RTTI::getRTTI( typelib_CompoundTypeDescription 
*pTypeDescr ) SAL_THR
 
     MutexGuard guard( m_mutex );
 
-    ObservedRttiMap::const_iterator observed( observedRttis().find( unoName ) 
);
-    if ( observed != observedRttis().end() )
-        return observed->second;
+    {
+        MutexGuard observedGuard( observedRttisMutex() );
+        ObservedRttiMap::const_iterator observed( observedRttis().find( 
unoName ) );
+        if ( observed != observedRttis().end() )
+            return observed->second;
+    }
 
     t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) );
     if (iFind == m_rttis.end())
@@ -177,50 +188,10 @@ type_info * RTTI::getRTTI( 
typelib_CompoundTypeDescription *pTypeDescr ) SAL_THR
 
         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?!" );
+            m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) );
         }
         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;
-            }
-        }
+            rtti = 0;
     }
     else
     {
@@ -233,25 +204,21 @@ type_info * RTTI::getRTTI( 
typelib_CompoundTypeDescription *pTypeDescr ) SAL_THR
 
//--------------------------------------------------------------------------------------------------
 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)
+    typelib_TypeDescription * pTD = 0;
     {
-        header = reinterpret_cast<__cxa_exception const 
*>(reinterpret_cast<char const *>(header) - 8);
+        MutexGuard guard( observedRttisMutex() );
+        ThrownTypes::iterator i = thrownTypes().find( pExc );
+        if ( i != thrownTypes().end() )
+        {
+            pTD = i->second;
+            thrownTypes().erase( i );
+        }
     }
-    if( !header->exceptionType)
+    if ( pTD )
     {
-        return; // NOTE: leak for now
+        ::uno_destructData( pExc, pTD, cpp_release );
+        ::typelib_typedescription_release( pTD );
     }
-    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 );
-       }
 }
 
 
//==================================================================================================
@@ -266,6 +233,8 @@ void raiseException( uno_Any * pUnoExc, uno_Mapping * 
pUno2Cpp )
 #endif
     void * pCppExc;
     type_info * rtti;
+    OUString typeName(
+        *reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ) );
 
     {
     // construct cpp exception object
@@ -283,93 +252,30 @@ void raiseException( uno_Any * pUnoExc, uno_Mapping * 
pUno2Cpp )
        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 );
+       static RTTI rtti_data;
+       rtti = rtti_data.getRTTI(
+               (typelib_CompoundTypeDescription *) 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 
),
+            typeName,
             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;
+        MutexGuard guard( Mutex::getGlobalMutex() );
+        typelib_typedescription_acquire( pTypeDescr );
+        thrownTypes()[pCppExc] = pTypeDescr;
     }
+    TYPELIB_DANGER_RELEASE( pTypeDescr );
 
-    /*
-     * 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);
+       // The C++ payload and its retained type description now own the value.
+       ::uno_any_destruct( pUnoExc, 0 );
     }
 
-       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 );
-    }
+       __cxa_throw( pCppExc, rtti, deleteException );
 }
 
 void fillUnoException(
diff --git a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/share.hxx 
b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/share.hxx
index 451f925b4a..aeac9e526f 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/share.hxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/share.hxx
@@ -32,88 +32,17 @@ 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_free_exception( void *thrown_exception ) 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();
 extern "C" std::type_info *__cxa_current_exception_type();
 
-// -----
-
-// 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 );
 void fillUnoException(
     std::type_info const & type, void * exception, 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
index fdecf3c547..41c1bc3048 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx
@@ -56,20 +56,20 @@ using namespace ::com::sun::star::uno;
 extern "C" void callVirtualFunction(
     sal_uInt64 pFunction, sal_uInt64 pIndirectRet,
     sal_uInt64 *pGPR, double *pFPR,
-    sal_uInt64 *pStack, sal_uInt32 nStackWords,
+    unsigned char *pStack, sal_uInt32 nStackBytes,
     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,
+                              unsigned char *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,
+                               unsigned char *pStack, sal_uInt32 nStack,
                               sal_uInt64 *pGPR, sal_uInt32 nGPR,
                               double *pFPR, sal_uInt32 nFPR)
 {
@@ -136,27 +136,40 @@ static void callVirtualMethod(void * pThis, sal_uInt32 
nVtableIndex,
         *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = gpReturn[0];
         break;
     case typelib_TypeClass_LONG:
+        *reinterpret_cast<sal_Int32 *>( pRegisterReturn ) =
+            *reinterpret_cast<sal_Int32 *>( &gpReturn[0] );
+        break;
     case typelib_TypeClass_UNSIGNED_LONG:
     case typelib_TypeClass_ENUM:
-        *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = 
*reinterpret_cast<sal_uInt32*>( &gpReturn[0] );
+        *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_SHORT:
+        *reinterpret_cast<sal_Int16 *>( pRegisterReturn ) =
+            *reinterpret_cast<sal_Int16 *>( &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_BYTE:
+        *reinterpret_cast<sal_Int8 *>( pRegisterReturn ) =
+            *reinterpret_cast<sal_Int8 *>( &gpReturn[0] );
+        break;
     case typelib_TypeClass_FLOAT:
+        *reinterpret_cast<float *>( pRegisterReturn ) =
+            *reinterpret_cast<float *>( &fpReturn[0] );
+        break;
     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)
+            if (bSimpleReturn && 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.
@@ -169,52 +182,52 @@ static void callVirtualMethod(void * pThis, sal_uInt32 
nVtableIndex,
 
 
//==================================================================================================
 
-// Macros for easier insertion of values to registers or stack
+// Macros for inserting values into registers. Stack arguments are handled
+// separately with a byte cursor because Apple packs them by size/alignment.
 // 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]
 
 // Each pFPR slot is the low 64 bits of a v register.  A float occupies only
 // the low 32 bits, while a double occupies all 64 bits.
-#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \
+#define INSERT_FLOAT( pSV, nr, pFPR ) \
        if ( nr < aarch64::MAX_FPR_REGS ) \
        { \
                pFPR[nr] = 0; \
                *reinterpret_cast<float *>( pFPR + nr++ ) = 
*reinterpret_cast<const float *>( pSV ); \
-       } \
-       else \
-               *pDS++ = *reinterpret_cast<const sal_uInt32 *>( pSV );
+       }
 
-#define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \
+#define INSERT_DOUBLE( pSV, nr, pFPR ) \
        if ( nr < aarch64::MAX_FPR_REGS ) \
-               pFPR[nr++] = *reinterpret_cast<const double *>( pSV ); \
-       else \
-               *pDS++ = *reinterpret_cast<const sal_uInt64 *>( pSV ); // 
verbatim!
+               pFPR[nr++] = *reinterpret_cast<const double *>( pSV );
+
+#define INSERT_INT64( pSV, nr, pGPR ) \
+       if ( nr < aarch64::MAX_GPR_REGS ) \
+               pGPR[nr++] = *reinterpret_cast<const sal_uInt64 *>( pSV );
+
+#define INSERT_INT32( pSV, nr, pGPR ) \
+       if ( nr < aarch64::MAX_GPR_REGS ) \
+               pGPR[nr++] = *reinterpret_cast<const sal_uInt32 *>( pSV );
 
-#define INSERT_INT64( pSV, nr, pGPR, pDS ) \
+#define INSERT_SIGNED_INT32( pSV, nr, pGPR ) \
        if ( nr < aarch64::MAX_GPR_REGS ) \
-               pGPR[nr++] = *reinterpret_cast<const sal_uInt64 *>( pSV ); \
-       else \
-               *pDS++ = *reinterpret_cast<const sal_uInt64 *>( pSV );
+               pGPR[nr++] = static_cast<sal_Int64>( *reinterpret_cast<const 
sal_Int32 *>( pSV ) );
 
-#define INSERT_INT32( pSV, nr, pGPR, pDS ) \
+#define INSERT_INT16( pSV, nr, pGPR ) \
        if ( nr < aarch64::MAX_GPR_REGS ) \
-               pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
-       else \
-               *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
+               pGPR[nr++] = *reinterpret_cast<const sal_uInt16 *>( pSV );
 
-#define INSERT_INT16( pSV, nr, pGPR, pDS ) \
+#define INSERT_SIGNED_INT16( pSV, nr, pGPR ) \
        if ( nr < aarch64::MAX_GPR_REGS ) \
-               pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
-       else \
-               *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
+               pGPR[nr++] = static_cast<sal_Int64>( *reinterpret_cast<const 
sal_Int16 *>( pSV ) );
 
-#define INSERT_INT8( pSV, nr, pGPR, pDS ) \
+#define INSERT_INT8( pSV, nr, pGPR ) \
        if ( nr < aarch64::MAX_GPR_REGS ) \
-               pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
-       else \
-               *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
+               pGPR[nr++] = *reinterpret_cast<const sal_uInt8 *>( pSV );
+
+#define INSERT_SIGNED_INT8( pSV, nr, pGPR ) \
+       if ( nr < aarch64::MAX_GPR_REGS ) \
+               pGPR[nr++] = static_cast<sal_Int64>( *reinterpret_cast<const 
sal_Int8 *>( pSV ) );
 
 
//==================================================================================================
 
@@ -237,10 +250,9 @@ static void cpp_call(
        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;
+       unsigned char *pStackStart = static_cast<unsigned char *>(
+               __builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) ) );
+       sal_uInt32 nStack = 0;
 
        sal_uInt64 pGPR[aarch64::MAX_GPR_REGS];
        sal_uInt32 nGPR = 0;
@@ -280,7 +292,7 @@ static void cpp_call(
 
        // Push "this" pointer
        void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() 
) + aVtableSlot.offset;
-       INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
+       INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR );
 
        // Args
        void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
@@ -301,36 +313,59 @@ static void cpp_call(
                {
                        uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), 
pUnoArgs[nPos], pParamTypeDescr,
                                                                        
pThis->getBridge()->getUno2Cpp() );
+                       bool onStack = false;
 
                        switch (pParamTypeDescr->eTypeClass)
                        {
                        case typelib_TypeClass_HYPER:
                        case typelib_TypeClass_UNSIGNED_HYPER:
-                               INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, 
pStack );
+                               onStack = nGPR >= aarch64::MAX_GPR_REGS;
+                               INSERT_INT64( pCppArgs[nPos], nGPR, pGPR );
                                break;
                        case typelib_TypeClass_LONG:
+                               onStack = nGPR >= aarch64::MAX_GPR_REGS;
+                               INSERT_SIGNED_INT32( pCppArgs[nPos], nGPR, pGPR 
);
+                               break;
                        case typelib_TypeClass_UNSIGNED_LONG:
                        case typelib_TypeClass_ENUM:
-                               INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, 
pStack );
+                               onStack = nGPR >= aarch64::MAX_GPR_REGS;
+                               INSERT_INT32( pCppArgs[nPos], nGPR, pGPR );
                                break;
                        case typelib_TypeClass_SHORT:
+                               onStack = nGPR >= aarch64::MAX_GPR_REGS;
+                               INSERT_SIGNED_INT16( pCppArgs[nPos], nGPR, pGPR 
);
+                               break;
                        case typelib_TypeClass_CHAR:
                        case typelib_TypeClass_UNSIGNED_SHORT:
-                               INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, 
pStack );
+                               onStack = nGPR >= aarch64::MAX_GPR_REGS;
+                               INSERT_INT16( pCppArgs[nPos], nGPR, pGPR );
                                break;
-                       case typelib_TypeClass_BOOLEAN:
                        case typelib_TypeClass_BYTE:
-                               INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack 
);
+                               onStack = nGPR >= aarch64::MAX_GPR_REGS;
+                               INSERT_SIGNED_INT8( pCppArgs[nPos], nGPR, pGPR 
);
+                               break;
+                       case typelib_TypeClass_BOOLEAN:
+                               onStack = nGPR >= aarch64::MAX_GPR_REGS;
+                               INSERT_INT8( pCppArgs[nPos], nGPR, pGPR );
                                break;
                        case typelib_TypeClass_FLOAT:
-                               INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, 
pStack );
+                               onStack = nFPR >= aarch64::MAX_FPR_REGS;
+                               INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR );
                                break;
                        case typelib_TypeClass_DOUBLE:
-                               INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, 
pStack );
+                               onStack = nFPR >= aarch64::MAX_FPR_REGS;
+                               INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR );
                                break;
                        default:
                                break;
                        }
+                       if ( onStack )
+                       {
+                               nStack = aarch64::align_stack_offset( nStack, 
rParam.pTypeRef );
+                               sal_uInt32 size = aarch64::stack_size( 
rParam.pTypeRef );
+                               memcpy( pStackStart + nStack, pCppArgs[nPos], 
size );
+                               nStack += size;
+                       }
 
                        // no longer needed
                        TYPELIB_DANGER_RELEASE( pParamTypeDescr );
@@ -364,7 +399,16 @@ static void cpp_call(
                                // no longer needed
                                TYPELIB_DANGER_RELEASE( pParamTypeDescr );
                        }
-                       INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
+                       if ( nGPR < aarch64::MAX_GPR_REGS )
+                       {
+                               INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR );
+                       }
+                       else
+                       {
+                               nStack = (nStack + sizeof(void *) - 1) & 
~(sizeof(void *) - 1);
+                               memcpy( pStackStart + nStack, &pCppArgs[nPos], 
sizeof(void *) );
+                               nStack += sizeof(void *);
+                       }
                }
        }
 
@@ -375,7 +419,7 @@ static void cpp_call(
                 pAdjustedThisPtr, aVtableSlot.index,
                 pCppReturn, pReturnTypeRef, bSimpleReturn,
                 pIndirectReturn,
-                pStackStart, ( pStack - pStackStart ),
+                               pStackStart, nStack,
                 pGPR, nGPR,
                 pFPR, nFPR );
         } catch (Exception &) {
diff --git a/main/bridges/source/cpp_uno/shared/vtablefactory.cxx 
b/main/bridges/source/cpp_uno/shared/vtablefactory.cxx
index 39cdee1cfb..fa7cd1bb4e 100644
--- a/main/bridges/source/cpp_uno/shared/vtablefactory.cxx
+++ b/main/bridges/source/cpp_uno/shared/vtablefactory.cxx
@@ -352,12 +352,18 @@ void VtableFactory::freeBlock(Block const & block) const {
 #else
 bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const
 {
+#if defined MACOSX && defined AARCH64
+    JitWriteGuard jitWriteGuard;
+#endif
     block.size = getBlockSize(slotCount);
     block.start = rtl_arena_alloc(m_arena, &block.size);
     return block.start != 0;
 }
 
 void VtableFactory::freeBlock(Block const & block) const {
+#if defined MACOSX && defined AARCH64
+    JitWriteGuard jitWriteGuard;
+#endif
     rtl_arena_free(m_arena, block.start, block.size);
 }
 #endif
diff --git a/main/solenv/bin/addsym-macosx.sh b/main/solenv/bin/addsym-macosx.sh
index a0b2ed6601..604440a5b5 100755
--- a/main/solenv/bin/addsym-macosx.sh
+++ b/main/solenv/bin/addsym-macosx.sh
@@ -45,4 +45,4 @@ s#$#$#' | tr '\n' '|' | sed "s#|\$##" >$2
 # On Panther we have to filter out symbols with a value "1f" otherwise external
 # symbols will erroneously be added to the generated export symbols list file.
 awk -v SYMBOLSREGEXP="`cat $2`" '
-match ($6,SYMBOLSREGEXP) > 0 &&  $6 !~ /_GLOBAL_/ { if (($2 != 1) && ( $2 != 
"1f" ) ) print $6 }'
+match ($6,SYMBOLSREGEXP) > 0 && $6 !~ /_GLOBAL_/ { if (($2 != 1) && (($2 != 
"1f") || ($6 ~ /^__ZT[IS]/))) print $6 }'
diff --git a/main/solenv/src/component.map b/main/solenv/src/component.map
index ae0e47828f..aecd1e1ffe 100644
--- a/main/solenv/src/component.map
+++ b/main/solenv/src/component.map
@@ -22,6 +22,8 @@ UDK_3_0_0 {
     global:
                component_getImplementationEnvironment;
                component_getFactory;
+               _ZTI*;
+               _ZTS*;
        local:
        *;
 };
diff --git a/main/testtools/source/bridgetest/bridgetest.cxx 
b/main/testtools/source/bridgetest/bridgetest.cxx
index 70197b1443..e0a5265433 100644
--- a/main/testtools/source/bridgetest/bridgetest.cxx
+++ b/main/testtools/source/bridgetest/bridgetest.cxx
@@ -518,10 +518,64 @@ static sal_Bool performTest(
                     memcmp(&aIn, &aOut, sizeof(AllFloats)) == 0,
                     "all floats struct test");
             }
+            {
+                TwoFloats aIn(1.25f, -2.5f);
+                TwoFloats aOut(xLBT->echoTwoFloats(aIn));
+                bRet &= check(aOut.a == aIn.a && aOut.b == aIn.b,
+                    "two-float HFA test");
+            }
+            {
+                ThreeDoubles aIn(1.25, -2.5, 9.75);
+                ThreeDoubles aOut(xLBT->echoThreeDoubles(aIn));
+                bRet &= check(
+                    aOut.a == aIn.a && aOut.b == aIn.b && aOut.c == aIn.c,
+                    "three-double HFA test");
+            }
+            {
+                MixedFloatLong aIn(1.25f, -123456);
+                MixedFloatLong aOut(xLBT->echoMixedFloatLong(aIn));
+                bRet &= check(aOut.a == aIn.a && aOut.b == aIn.b,
+                    "mixed float-long struct test");
+            }
+            {
+                OneByte aIn(-7);
+                OneByte aOut(xLBT->echoOneByte(aIn));
+                bRet &= check(aOut.value == aIn.value, "one-byte struct test");
+            }
+            {
+                ThreeLongs aIn(0x11223344, -7, 0x55667788);
+                ThreeLongs aOut(xLBT->echoThreeLongs(aIn));
+                bRet &= check(
+                    aOut.a == aIn.a && aOut.b == aIn.b && aOut.c == aIn.c,
+                    "three-long struct test");
+            }
             {
                 sal_Int32 i2 = xLBT->testPPCAlignment(0, 0, 0, 0, 0xBEAF);
                 bRet &= check(i2 == 0xBEAF, "ppc-style alignment test");
             }
+            {
+                sal_Int8 b = -2;
+                sal_Int8 c = 0x35;
+                sal_Int16 s = -1234;
+                sal_Int32 l = 0x11223344;
+                sal_Int8 d = -7;
+                sal_Int64 h = SAL_CONST_INT64(0x0102030405060708);
+                sal_Int64 expected = ((static_cast<sal_Int64>(b) << 56) |
+                    (static_cast<sal_uInt64>(static_cast<sal_uInt8>(c)) << 48) 
|
+                    (static_cast<sal_uInt64>(static_cast<sal_uInt16>(s)) << 
32) |
+                    static_cast<sal_uInt32>(l)) ^
+                    (static_cast<sal_Int64>(d) << 24) ^ h;
+                bRet &= check(
+                    xLBT->testPackedStack(0, 1, 2, 3, 4, 5, 6, b, c, s, l, d, 
h)
+                        == expected,
+                    "packed stack argument test");
+            }
+            {
+                double result = xLBT->testFpStack(
+                    0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0,
+                    -3.25f, 9.5);
+                bRet &= check(result == 6.25, "fp stack argument test");
+            }
             // Test extended attributes that raise exceptions:
             try {
                 xLBT->getRaiseAttr1();
diff --git a/main/testtools/source/bridgetest/cppobj.cxx 
b/main/testtools/source/bridgetest/cppobj.cxx
index b6dd183cd7..5d2cc941fd 100644
--- a/main/testtools/source/bridgetest/cppobj.cxx
+++ b/main/testtools/source/bridgetest/cppobj.cxx
@@ -217,8 +217,33 @@ public:
         { return rStruct; }
     virtual AllFloats SAL_CALL echoAllFloats(const AllFloats& rStruct) 
throw(com::sun::star::uno::RuntimeException)
         { return rStruct; }
+    virtual TwoFloats SAL_CALL echoTwoFloats(const TwoFloats& rStruct) 
throw(com::sun::star::uno::RuntimeException)
+        { return rStruct; }
+    virtual ThreeDoubles SAL_CALL echoThreeDoubles(const ThreeDoubles& 
rStruct) throw(com::sun::star::uno::RuntimeException)
+        { return rStruct; }
+    virtual MixedFloatLong SAL_CALL echoMixedFloatLong(const MixedFloatLong& 
rStruct) throw(com::sun::star::uno::RuntimeException)
+        { return rStruct; }
+    virtual OneByte SAL_CALL echoOneByte(const OneByte& rStruct) 
throw(com::sun::star::uno::RuntimeException)
+        { return rStruct; }
+    virtual ThreeLongs SAL_CALL echoThreeLongs(const ThreeLongs& rStruct) 
throw(com::sun::star::uno::RuntimeException)
+        { return rStruct; }
     virtual sal_Int32 SAL_CALL testPPCAlignment( sal_Int64, sal_Int64, 
sal_Int32, sal_Int64, sal_Int32 i2 ) 
throw(com::sun::star::uno::RuntimeException)
         { return i2; }
+    virtual sal_Int64 SAL_CALL testPackedStack(
+        sal_Int64, sal_Int64, sal_Int64, sal_Int64, sal_Int64, sal_Int64,
+        sal_Int64, sal_Int8 b, sal_Int8 c, sal_Int16 s, sal_Int32 l,
+        sal_Int8 d, sal_Int64 h) throw(com::sun::star::uno::RuntimeException)
+    {
+        return ((static_cast<sal_Int64>(b) << 56) |
+            (static_cast<sal_uInt64>(static_cast<sal_uInt8>(c)) << 48) |
+            (static_cast<sal_uInt64>(static_cast<sal_uInt16>(s)) << 32) |
+            static_cast<sal_uInt32>(l)) ^
+            (static_cast<sal_Int64>(d) << 24) ^ h;
+    }
+    virtual double SAL_CALL testFpStack(
+        double, double, double, double, double, double, double, double,
+        float f8, double d9) throw(com::sun::star::uno::RuntimeException)
+        { return static_cast<double>(f8) + d9; }
 
     virtual sal_Bool SAL_CALL getBool() 
throw(com::sun::star::uno::RuntimeException)
                { return _aData.Bool; }
diff --git a/main/testtools/source/bridgetest/idl/bridgetest.idl 
b/main/testtools/source/bridgetest/idl/bridgetest.idl
index e4638aef1f..103bd6f9a6 100644
--- a/main/testtools/source/bridgetest/idl/bridgetest.idl
+++ b/main/testtools/source/bridgetest/idl/bridgetest.idl
@@ -106,6 +106,37 @@ struct AllFloats
     float                      c;
     float                      d;
 };
+
+struct TwoFloats
+{
+    float                      a;
+    float                      b;
+};
+
+struct ThreeDoubles
+{
+    double                     a;
+    double                     b;
+    double                     c;
+};
+
+struct MixedFloatLong
+{
+    float                      a;
+    long                       b;
+};
+
+struct OneByte
+{
+    byte                       value;
+};
+
+struct ThreeLongs
+{
+    long                       a;
+    long                       b;
+    long                       c;
+};
 /**
  * complex types adding string, inteface, any
  */
@@ -261,12 +292,29 @@ interface XBridgeTestBase : 
com::sun::star::uno::XInterface
      * register return test 4
      */
     AllFloats echoAllFloats( [in] AllFloats aStruct );
+    TwoFloats echoTwoFloats( [in] TwoFloats aStruct );
+    ThreeDoubles echoThreeDoubles( [in] ThreeDoubles aStruct );
+    MixedFloatLong echoMixedFloatLong( [in] MixedFloatLong aStruct );
+
+    OneByte echoOneByte( [in] OneByte aStruct );
+    ThreeLongs echoThreeLongs( [in] ThreeLongs aStruct );
 
     /**
      * register return test 4 (i107182)
      */
     long testPPCAlignment( [in] hyper l1, [in] hyper l2, [in] long i1, [in] 
hyper l3, [in] long i2 );
 
+    hyper testPackedStack(
+        [in] hyper a0, [in] hyper a1, [in] hyper a2, [in] hyper a3,
+        [in] hyper a4, [in] hyper a5, [in] hyper a6,
+        [in] byte b, [in] byte c, [in] short s, [in] long l,
+        [in] byte d, [in] hyper h );
+
+    double testFpStack(
+        [in] double a0, [in] double a1, [in] double a2, [in] double a3,
+        [in] double a4, [in] double a5, [in] double a6, [in] double a7,
+        [in] float f8, [in] double d9 );
+
     [attribute] boolean                  Bool;
     [attribute] byte                     Byte;
     [attribute] char                     Char;

Reply via email to