diff options
4 files changed, 44 insertions, 3 deletions
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.cxx b/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.cxx index 686cbb596317..f9eb09517358 100644 --- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.cxx @@ -56,6 +56,8 @@ int loongarch64::flatten_struct(typelib_TypeDescription* pTypeDescr, Registers& regs.priorInt = true; break; case typelib_TypeClass_FLOAT: + regs.complex_float = true; + [[fallthrough]]; case typelib_TypeClass_DOUBLE: regs.nr_fp++; if (!regs.priorInt && !regs.priorFp) @@ -88,22 +90,34 @@ loongarch64::ReturnKind loongarch64::getReturnKind(typelib_TypeDescriptionRefere return ReturnKind::RegistersFp; case typelib_TypeClass_STRUCT: { - Registers regs = { 0, 0, false, false }; + Registers regs = { false, false, false, 0, 0 }; typelib_TypeDescription* pTypeDescr = nullptr; TYPELIB_DANGER_GET(&pTypeDescr, pTypeRef); int sum = flatten_struct(pTypeDescr, regs); TYPELIB_DANGER_RELEASE(pTypeDescr); if ((sum == 1 || sum == 2) && sum == regs.nr_fp) + { + if (regs.complex_float && pTypeRef->pType->nSize == 8) + return ReturnKind::RegistersTwoFloat; return ReturnKind::RegistersFp; + } if (sum == 2 && regs.nr_fp == regs.nr_int) { if (regs.priorInt) + { + if (regs.complex_float && pTypeRef->pType->nSize == 8) + return ReturnKind::RegistersIntFloat; return ReturnKind::RegistersIntFp; + } if (regs.priorFp) + { + if (regs.complex_float && pTypeRef->pType->nSize == 8) + return ReturnKind::RegistersFloatInt; return ReturnKind::RegistersFpInt; + } } - return ReturnKind::RegistersInt; } + [[fallthrough]]; default: return ReturnKind::RegistersInt; } @@ -119,14 +133,26 @@ void loongarch64::fillReturn(typelib_TypeDescriptionReference* pTypeRef, sal_Int reinterpret_cast<double*>(pRegisterReturn)[0] = fret[0]; reinterpret_cast<double*>(pRegisterReturn)[1] = fret[1]; break; + case ReturnKind::RegistersTwoFloat: + memcpy(reinterpret_cast<char*>(pRegisterReturn), &(fret[0]), 4); + memcpy(reinterpret_cast<char*>(pRegisterReturn) + 4, &(fret[1]), 4); + break; case ReturnKind::RegistersFpInt: reinterpret_cast<double*>(pRegisterReturn)[0] = fret[0]; reinterpret_cast<sal_Int64*>(pRegisterReturn)[1] = gret[0]; break; + case ReturnKind::RegistersFloatInt: + memcpy(reinterpret_cast<char*>(pRegisterReturn), fret, 4); + memcpy(reinterpret_cast<char*>(pRegisterReturn) + 4, gret, 4); + break; case ReturnKind::RegistersIntFp: reinterpret_cast<sal_Int64*>(pRegisterReturn)[0] = gret[0]; reinterpret_cast<double*>(pRegisterReturn)[1] = fret[0]; break; + case ReturnKind::RegistersIntFloat: + memcpy(reinterpret_cast<char*>(pRegisterReturn), gret, 4); + memcpy(reinterpret_cast<char*>(pRegisterReturn) + 4, fret, 4); + break; default: reinterpret_cast<sal_Int64*>(pRegisterReturn)[0] = gret[0]; reinterpret_cast<sal_Int64*>(pRegisterReturn)[1] = gret[1]; diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.hxx b/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.hxx index 90aa544f128b..1fe9e9b58866 100644 --- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.hxx +++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/abi.hxx @@ -30,11 +30,15 @@ enum class ReturnKind { RegistersInt, RegistersFp, + RegistersTwoFloat, RegistersFpInt, - RegistersIntFp + RegistersFloatInt, + RegistersIntFp, + RegistersIntFloat }; typedef struct Registers { + bool complex_float; bool priorInt; bool priorFp; int nr_fp; diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx index aa8f4be3cf72..1a0c42b0da67 100644 --- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx @@ -263,10 +263,19 @@ static int cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* pThis, } switch (returnKind) { + case loongarch64::ReturnKind::RegistersIntFloat: + memcpy(pRegisterReturn + 1, static_cast<char*>(pUnoReturn) + 4, 4); + [[fallthrough]]; case loongarch64::ReturnKind::RegistersIntFp: return 0; + case loongarch64::ReturnKind::RegistersFloatInt: + memcpy(pRegisterReturn + 1, static_cast<char*>(pUnoReturn) + 4, 4); + [[fallthrough]]; case loongarch64::ReturnKind::RegistersFpInt: return 1; + case loongarch64::ReturnKind::RegistersTwoFloat: + memcpy(pRegisterReturn + 1, static_cast<char*>(pUnoReturn) + 4, 4); + [[fallthrough]]; default: return -1; } @@ -386,6 +395,7 @@ int cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, void** gp TYPELIB_DANGER_RELEASE(pTD); } } // else perform queryInterface() + [[fallthrough]]; default: typelib_InterfaceMethodTypeDescription* pMethodTD = reinterpret_cast<typelib_InterfaceMethodTypeDescription*>( diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx index 7242a43bd76c..c4e7815e0a0a 100644 --- a/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx @@ -450,6 +450,7 @@ void unoInterfaceProxyDispatch(uno_Interface* pUnoI, const typelib_TypeDescripti TYPELIB_DANGER_RELEASE(pTD); } } // else perform queryInterface() + [[fallthrough]]; default: // dependent dispatch cpp_call( |