diff --git a/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/abi.cxx b/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/abi.cxx index c119e4580b..08c11c4b50 100644 --- a/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/abi.cxx +++ b/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/abi.cxx @@ -333,10 +333,13 @@ void fill_struct( typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64* sal_uInt32 align_stack_offset( sal_uInt32 offset, typelib_TypeDescriptionReference *pTypeRef ) { - // On aarch64 System V ABI, the smallest stack slot is 8 bytes. - // Align to 8 bytes regardless of the type's natural alignment. - const sal_uInt32 align = 8; - return ( offset + align - 1 ) & ~( align - 1 ); + 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 stack_size( typelib_TypeDescriptionReference *pTypeRef ) @@ -344,13 +347,12 @@ sal_uInt32 stack_size( typelib_TypeDescriptionReference *pTypeRef ) typelib_TypeDescription * pTypeDescr = 0; TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); sal_uInt32 size = pTypeDescr->nSize; + // AAPCS64 requires each stack argument to occupy a full 8-byte + // slot; small types are sign- or zero-extended into the slot. + if ( size < 8 ) + size = 8; TYPELIB_DANGER_RELEASE( pTypeDescr ); - // In the System V AMD64 / AAPCS64 stack layout, the smallest slot that - // can be passed is 8 bytes (the natural stack slot size). Round up - // so that small types like BOOLEAN (1B), SHORT (2B), LONG (4B) each - // occupy a full 8-byte slot on the overflow stack, matching what the - // callee's ABI expects. - return ( size + 7 ) & ~7u; + return size; } } // namespace aarch64 diff --git a/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/uno2cpp.cxx b/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/uno2cpp.cxx index 8cb8c0d517..30dbd72000 100644 --- a/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/uno2cpp.cxx +++ b/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/uno2cpp.cxx @@ -164,12 +164,15 @@ static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex, case typelib_TypeClass_DOUBLE: *reinterpret_cast( pRegisterReturn ) = fpReturn[0]; break; - case typelib_TypeClass_STRUCT: - case typelib_TypeClass_EXCEPTION: - aarch64::fill_struct( pReturnTypeRef, &gpReturn[0], &fpReturn[0], pRegisterReturn ); - break; default: - break; + { + sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize; + if (bSimpleReturn && nRetSize > 0) + { + aarch64::fill_struct( pReturnTypeRef, &gpReturn[0], &fpReturn[0], pRegisterReturn ); + } + break; + } } } @@ -353,9 +356,51 @@ static void cpp_call( } if ( onStack ) { - nStack = aarch64::align_stack_offset( nStack, rParam.pTypeRef ); - sal_uInt32 size = aarch64::stack_size( rParam.pTypeRef ); - memcpy( pStackStart + nStack, pCppArgs[nPos], size ); + // AAPCS64: each stack argument occupies a full 8-byte slot + // with the value sign- or zero-extended. The INSERT macros + // already perform the correct extension into a GPR-sized + // (sal_uInt64) scratch slot; reuse them with a local counter. + nStack = aarch64::align_stack_offset( nStack, rParam.pTypeRef ); + sal_uInt32 size = aarch64::stack_size( rParam.pTypeRef ); + sal_uInt64 scratch[1] = {0}; + int tempNr = 0; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_FLOAT: + INSERT_FLOAT( pCppArgs[nPos], tempNr, reinterpret_cast(scratch) ); + break; + case typelib_TypeClass_DOUBLE: + INSERT_DOUBLE( pCppArgs[nPos], tempNr, reinterpret_cast(scratch) ); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + INSERT_INT64( pCppArgs[nPos], tempNr, scratch ); + break; + case typelib_TypeClass_LONG: + INSERT_SIGNED_INT32( pCppArgs[nPos], tempNr, scratch ); + break; + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + INSERT_INT32( pCppArgs[nPos], tempNr, scratch ); + break; + case typelib_TypeClass_SHORT: + INSERT_SIGNED_INT16( pCppArgs[nPos], tempNr, scratch ); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16( pCppArgs[nPos], tempNr, scratch ); + break; + case typelib_TypeClass_BYTE: + INSERT_SIGNED_INT8( pCppArgs[nPos], tempNr, scratch ); + break; + case typelib_TypeClass_BOOLEAN: + INSERT_INT8( pCppArgs[nPos], tempNr, scratch ); + break; + default: + memcpy( scratch, pCppArgs[nPos], pParamTypeDescr->nSize ); + break; + } + memcpy( pStackStart + nStack, scratch, size ); nStack += size; }