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 79670aa18e Handle arm64 HFA marshalling failure in the bridge
79670aa18e is described below
commit 79670aa18e015d263a20a2826ce53832fcd22063
Author: Jim Jagielski <[email protected]>
AuthorDate: Mon Aug 3 06:51:03 2026 -0400
Handle arm64 HFA marshalling failure in the bridge
---
.../source/cpp_uno/s5abi_macosx_aarch64/abi.cxx | 54 +++++++++++++++++++--
.../source/cpp_uno/s5abi_macosx_aarch64/abi.hxx | 9 ++++
.../source/cpp_uno/s5abi_macosx_aarch64/call.s | 26 +++++++++-
.../cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx | 14 +++---
.../source/cpp_uno/s5abi_macosx_aarch64/except.cxx | 47 +++++++++++++++++-
.../source/cpp_uno/s5abi_macosx_aarch64/share.hxx | 4 ++
.../cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx | 56 +++++++++++++++++-----
7 files changed, 187 insertions(+), 23 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 dc10b9fb88..48d7ce36aa 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.cxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.cxx
@@ -46,6 +46,8 @@
#include "abi.hxx"
+#include "bridges/cpp_uno/shared/types.hxx"
+
#include <rtl/ustring.hxx>
using namespace aarch64;
@@ -71,6 +73,27 @@ HfaKind mergeHfa( HfaKind running, HfaKind seen )
return ( running == seen ) ? running : HFA_NONE;
}
+bool isComplexAggregate( typelib_TypeDescriptionReference *pTypeRef )
+{
+ typelib_TypeDescription * pTypeDescr = 0;
+ TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
+ const typelib_CompoundTypeDescription *pComp =
+ reinterpret_cast<const typelib_CompoundTypeDescription *>( pTypeDescr
);
+ bool complex = pComp->pBaseTypeDescription != 0 &&
+ isComplexAggregate( pComp->pBaseTypeDescription->aBase.pWeakRef );
+ for ( sal_Int32 i = 0; !complex && i < pComp->nMembers; ++i )
+ {
+ typelib_TypeClass typeClass = pComp->ppTypeRefs[i]->eTypeClass;
+ if ( typeClass == typelib_TypeClass_STRUCT ||
+ typeClass == typelib_TypeClass_EXCEPTION )
+ complex = isComplexAggregate( pComp->ppTypeRefs[i] );
+ else
+ complex = !bridges::cpp_uno::shared::isSimpleType( typeClass );
+ }
+ TYPELIB_DANGER_RELEASE( pTypeDescr );
+ return complex;
+}
+
// Recursively determine whether pTypeRef is (part of) a homogeneous
// floating-point aggregate, accumulating the element kind and member count.
//
@@ -158,7 +181,7 @@ bool classifyAggregate( typelib_TypeDescriptionReference
*pTypeRef, int &nUsedGP
} // anonymous namespace
-bool aarch64::examine_argument( typelib_TypeDescriptionReference *pTypeRef,
bool /*bInReturn*/, int &nUsedGPR, int &nUsedFPR )
+bool aarch64::examine_argument( typelib_TypeDescriptionReference *pTypeRef,
bool bInReturn, int &nUsedGPR, int &nUsedFPR )
{
nUsedGPR = 0;
nUsedFPR = 0;
@@ -199,7 +222,10 @@ bool aarch64::examine_argument(
typelib_TypeDescriptionReference *pTypeRef, bool
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION:
- return classifyAggregate( pTypeRef, nUsedGPR, nUsedFPR );
+ if ( bInReturn )
+ return classifyAggregate( pTypeRef, nUsedGPR, nUsedFPR );
+ nUsedGPR = 1; // generated UNO C++ bindings pass aggregates by
const reference
+ return true;
default:
#if OSL_DEBUG_LEVEL > 1
@@ -218,6 +244,8 @@ bool aarch64::return_in_hidden_param(
typelib_TypeDescriptionReference *pTypeRef
case typelib_TypeClass_TYPE:
case typelib_TypeClass_ANY:
case typelib_TypeClass_TYPEDEF:
+ case typelib_TypeClass_UNION:
+ case typelib_TypeClass_ARRAY:
case typelib_TypeClass_SEQUENCE:
case typelib_TypeClass_INTERFACE:
// These are C++ wrapper objects, not pointer-sized scalar values.
@@ -227,12 +255,32 @@ bool aarch64::return_in_hidden_param(
typelib_TypeDescriptionReference *pTypeRef
break;
}
+ if ( pTypeRef->eTypeClass == typelib_TypeClass_STRUCT ||
+ pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION )
+ {
+ if ( isComplexAggregate( pTypeRef ) )
+ return true;
+ }
+
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 );
}
+sal_uInt32 aarch64::get_return_kind( typelib_TypeDescriptionReference
*pTypeRef )
+{
+ if ( pTypeRef->eTypeClass == typelib_TypeClass_STRUCT ||
+ pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION )
+ {
+ HfaKind kind = HFA_NONE;
+ int count = 0;
+ if ( collectHfa( pTypeRef, kind, count ) && count >= 1 && count <= 4 )
+ return kind == HFA_FLOAT ? RETURN_KIND_HFA_FLOAT :
RETURN_KIND_HFA_DOUBLE;
+ }
+ return pTypeRef->eTypeClass;
+}
+
void aarch64::fill_struct( typelib_TypeDescriptionReference *pTypeRef, const
sal_uInt64 *pGPR, const double *pFPR, void *pStruct )
{
int nUsedGPR = 0;
@@ -257,7 +305,7 @@ void aarch64::fill_struct( typelib_TypeDescriptionReference
*pTypeRef, const sal
{
float *pDest = reinterpret_cast<float *>( pStruct );
for ( int i = 0; i < nUsedFPR; ++i )
- pDest[i] = static_cast<float>( pFPR[i] );
+ pDest[i] = *reinterpret_cast<const float *>( pFPR + i );
}
else // HFA_DOUBLE
{
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 7d55ac076c..e6b210afdb 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.hxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/abi.hxx
@@ -48,6 +48,12 @@ const sal_uInt32 MAX_FPR_REGS = 8;
most 2 (16 bytes / 8). */
const sal_uInt32 MAX_AGGREGATE_REGS = 4;
+enum ReturnKind
+{
+ RETURN_KIND_HFA_FLOAT = 0x100,
+ RETURN_KIND_HFA_DOUBLE = 0x101
+};
+
/* 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
@@ -72,6 +78,9 @@ bool examine_argument( typelib_TypeDescriptionReference
*pTypeRef, bool bInRetur
*/
bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef );
+/** Return the assembly return kind for an HFA, or the type class otherwise. */
+sal_uInt32 get_return_kind( 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.
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 035b38555a..25677b3294 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/call.s
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/call.s
@@ -41,12 +41,16 @@
.globl _callVirtualFunction
.p2align 2
_callVirtualFunction:
+ .cfi_startproc
// 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
+ .cfi_def_cfa x29, 64
+ .cfi_offset x29, -16
+ .cfi_offset x30, -8
// stash inputs that must survive the call into callee-saved registers
mov x19, x0 // pFunction
@@ -103,6 +107,7 @@ Lcvf_copied:
ldp x19, x20, [sp], #16
ldp x29, x30, [sp], #16
ret
+ .cfi_endproc
// ---------------------------------------------------------------------------
// privateSnippetExecutor: the incoming (cpp2uno) register-spill executor.
@@ -124,13 +129,17 @@ Lcvf_copied:
// void* pIndirectReturn, sal_uInt64* pRegisterReturn);
//
// Frame (176 bytes): [0]=x29,x30 [16..79]=x0..x7 [80..143]=d0..d7
-// [144..159]=return buffer.
+// [144..175]=return buffer (up to four HFA doubles).
.globl _privateSnippetExecutor
.p2align 2
_privateSnippetExecutor:
+ .cfi_startproc
mov x17, sp // x17 = ovrflw (incoming stack args)
stp x29, x30, [sp, #-176]!
mov x29, sp
+ .cfi_def_cfa x29, 176
+ .cfi_offset x29, -176
+ .cfi_offset x30, -168
stp x0, x1, [sp, #16] // save GP argument registers x0..x7
stp x2, x3, [sp, #32]
@@ -151,6 +160,10 @@ _privateSnippetExecutor:
add x6, sp, #144 // pRegisterReturn (16-byte buffer)
bl _cpp_vtable_call
+ cmp w0, #0x100 // RETURN_KIND_HFA_FLOAT
+ b.eq Lpse_hfa_float
+ cmp w0, #0x101 // RETURN_KIND_HFA_DOUBLE
+ b.eq Lpse_hfa_double
cmp w0, #10 // typelib_TypeClass_FLOAT
b.eq Lpse_float
cmp w0, #11 // typelib_TypeClass_DOUBLE
@@ -162,7 +175,18 @@ _privateSnippetExecutor:
b Lpse_done
Lpse_float:
ldr d0, [sp, #144]
+ b Lpse_done
+Lpse_hfa_float:
+ ldr s0, [sp, #144]
+ ldr s1, [sp, #148]
+ ldr s2, [sp, #152]
+ ldr s3, [sp, #156]
+ b Lpse_done
+Lpse_hfa_double:
+ ldp d0, d1, [sp, #144]
+ ldp d2, d3, [sp, #160]
Lpse_done:
mov sp, x29
ldp x29, x30, [sp], #176
ret
+ .cfi_endproc
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 c1ed5e8be2..5d8161498e 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/cpp2uno.cxx
@@ -123,11 +123,11 @@ static typelib_TypeClass cpp2uno_call(
int nUsedGPR = 0;
int nUsedFPR = 0;
- bool bFitsRegisters = aarch64::examine_argument(
rParam.pTypeRef, false, nUsedGPR, nUsedFPR );
+ 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 ) ) );
+ OSL_ASSERT( ( nUsedFPR == 1 && nUsedGPR == 0 ) || (
nUsedFPR == 0 && nUsedGPR == 1 ) );
if ( nUsedFPR == 1 )
{
@@ -155,7 +155,7 @@ static typelib_TypeClass cpp2uno_call(
typelib_TypeDescription * pParamTypeDescr = 0;
TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
- void *pCppStack;
+ void *pCppStack = 0;
if ( nr_gpr < aarch64::MAX_GPR_REGS )
{
pCppArgs[nPos] = pCppStack = *gpreg++;
@@ -262,7 +262,7 @@ static typelib_TypeClass cpp2uno_call(
//==================================================================================================
-extern "C" typelib_TypeClass cpp_vtable_call(
+extern "C" sal_uInt32 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)
@@ -300,7 +300,7 @@ extern "C" typelib_TypeClass cpp_vtable_call(
TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
- typelib_TypeClass eRet;
+ sal_uInt32 eRet;
switch ( aMemberDescr.get()->eTypeClass )
{
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
@@ -311,9 +311,10 @@ extern "C" typelib_TypeClass cpp_vtable_call(
if (
pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
{
// is GET method
- eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
pAttrTypeRef,
+ eRet = cpp2uno_call( pCppI,
aMemberDescr.get(), pAttrTypeRef,
0, 0, // no params
gpreg, fpreg, ovrflw,
pIndirectReturn, pRegisterReturn );
+ eRet = aarch64::get_return_kind(
pAttrTypeRef );
}
else
{
@@ -385,6 +386,7 @@ extern "C" typelib_TypeClass cpp_vtable_call(
pMethodTD->nParams,
pMethodTD->pParams,
gpreg, fpreg, ovrflw, pIndirectReturn, pRegisterReturn );
+ eRet = aarch64::get_return_kind(
pMethodTD->pReturnTypeRef );
}
}
break;
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 60784a4172..1e88673b81 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/except.cxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/except.cxx
@@ -58,6 +58,18 @@ using namespace ::__cxxabiv1;
namespace CPPU_CURRENT_NAMESPACE
{
+namespace {
+
+typedef hash_map< OUString, type_info *, OUStringHash > ObservedRttiMap;
+
+ObservedRttiMap & observedRttis()
+{
+ static ObservedRttiMap map;
+ return map;
+}
+
+}
+
void dummy_can_throw_anything( char const * )
{
}
@@ -138,6 +150,11 @@ type_info * RTTI::getRTTI( typelib_CompoundTypeDescription
*pTypeDescr ) SAL_THR
OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName;
MutexGuard guard( m_mutex );
+
+ 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())
{
@@ -156,7 +173,7 @@ type_info * RTTI::getRTTI( typelib_CompoundTypeDescription
*pTypeDescr ) SAL_THR
buf.append( 'E' );
OString symName( buf.makeStringAndClear() );
- rtti = static_cast<std::type_info *>(dlsym( m_hApp, symName.getStr()
));
+ rtti = static_cast<std::type_info *>(dlsym( RTLD_DEFAULT,
symName.getStr() ));
if (rtti)
{
@@ -355,4 +372,32 @@ void fillUnoException( __cxa_exception * header, uno_Any *
pUnoExc, uno_Mapping
}
}
+void fillUnoException(
+ std::type_info const & type, void * exception, uno_Any * pUnoExc,
+ uno_Mapping * pCpp2Uno )
+{
+ typelib_TypeDescription * pExcTypeDescr = 0;
+ OUString unoName( toUNOname( type.name() ) );
+ {
+ MutexGuard guard( Mutex::getGlobalMutex() );
+ observedRttis()[unoName] = const_cast<std::type_info *>( &type );
+ }
+ typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
+ if ( pExcTypeDescr == 0 )
+ {
+ 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 );
+ }
+ else
+ {
+ uno_any_constructAndConvert(
+ pUnoExc, exception, pExcTypeDescr, pCpp2Uno );
+ typelib_typedescription_release( pExcTypeDescr );
+ }
+}
+
}
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 e4fcf4dbf9..451f925b4a 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/share.hxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/share.hxx
@@ -82,6 +82,7 @@ struct __cxa_eh_globals
unsigned int uncaughtExceptions;
};
extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
+extern "C" std::type_info *__cxa_current_exception_type();
// -----
@@ -113,4 +114,7 @@ void raiseException(
//==================================================================================================
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 adaa3f2a5f..fdecf3c547 100644
--- a/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx
+++ b/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx
@@ -175,19 +175,28 @@ static void callVirtualMethod(void * pThis, sal_uInt32
nVtableIndex,
// 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 ) \
+// 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 ) \
if ( nr < aarch64::MAX_FPR_REGS ) \
- pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
+ { \
+ pFPR[nr] = 0; \
+ *reinterpret_cast<float *>( pFPR + nr++ ) =
*reinterpret_cast<const float *>( pSV ); \
+ } \
else \
- *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
+ *pDS++ = *reinterpret_cast<const sal_uInt32 *>( pSV );
+
+#define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \
+ if ( nr < aarch64::MAX_FPR_REGS ) \
+ pFPR[nr++] = *reinterpret_cast<const double *>( pSV ); \
+ else \
+ *pDS++ = *reinterpret_cast<const sal_uInt64 *>( pSV ); //
verbatim!
#define INSERT_INT64( pSV, nr, pGPR, pDS ) \
if ( nr < aarch64::MAX_GPR_REGS ) \
- pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
+ pGPR[nr++] = *reinterpret_cast<const sal_uInt64 *>( pSV ); \
else \
- *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
+ *pDS++ = *reinterpret_cast<const sal_uInt64 *>( pSV );
#define INSERT_INT32( pSV, nr, pGPR, pDS ) \
if ( nr < aarch64::MAX_GPR_REGS ) \
@@ -314,8 +323,10 @@ static void cpp_call(
INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack
);
break;
case typelib_TypeClass_FLOAT:
+ INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR,
pStack );
+ break;
case typelib_TypeClass_DOUBLE:
- INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR,
pFPR, pStack );
+ INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR,
pStack );
break;
default:
break;
@@ -421,10 +432,13 @@ static void cpp_call(
uno_destructData( pCppReturn, pReturnTypeDescr,
cpp_release );
}
}
- catch (...)
- {
- // fill uno exception
- fillUnoException(
CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc,
pThis->getBridge()->getCpp2Uno() );
+ catch (Exception & e)
+ {
+ // fill uno exception
+ std::type_info * type =
CPPU_CURRENT_NAMESPACE::__cxa_current_exception_type();
+ CPPU_CURRENT_NAMESPACE::fillUnoException(
+ type ? *type : typeid(e), &e, *ppUnoExc,
+ pThis->getBridge()->getCpp2Uno() );
// temporary params
for ( ; nTempIndizes--; )
@@ -438,6 +452,24 @@ static void cpp_call(
if (pReturnTypeDescr)
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
}
+ catch (...)
+ {
+ RuntimeException e(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("C++ code threw
unknown exception") ),
+ Reference< XInterface >() );
+ uno_type_any_constructAndConvert(
+ *ppUnoExc, &e, ::getCppuType( &e ).getTypeLibType(),
+ pThis->getBridge()->getCpp2Uno() );
+ for ( ; nTempIndizes--; )
+ {
+ sal_Int32 nIndex = pTempIndizes[nTempIndizes];
+ uno_destructData(
+ pCppArgs[nIndex],
ppTempParamTypeDescr[nTempIndizes], cpp_release );
+ TYPELIB_DANGER_RELEASE(
ppTempParamTypeDescr[nTempIndizes] );
+ }
+ if (pReturnTypeDescr)
+ TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+ }
}
//==================================================================================================