diff options
author | Caolán McNamara <caolanm@redhat.com> | 2014-08-22 13:31:03 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2014-08-22 13:34:50 +0100 |
commit | 970ad502e3ea2cc992c6cc1c7583231aec5bf5da (patch) | |
tree | f3e6d83febe42476fd0d0076202f9039efa47a0b /bridges | |
parent | d931eb2a93d6ae8a2549077c446d2b856ebe9e41 (diff) |
Related: rhbz#1125588 ppc64le has new struct passing rules
http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01145.html
http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01147.html
now we just fail instead of crash
Change-Id: I329c676337885bcf4fdfdcdb5912d75424862126
Diffstat (limited to 'bridges')
3 files changed, 58 insertions, 8 deletions
diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx index c0ca97f400f7..dbdef1bce881 100644 --- a/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/cpp2uno.cxx @@ -72,7 +72,7 @@ static typelib_TypeClass cpp2uno_call( if (pReturnTypeDescr) { - if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + if (!ppc64::return_in_hidden_param(pReturnTypeRef)) { pUnoReturn = pRegisterReturn; // direct way for simple types } @@ -599,7 +599,7 @@ const int codeSnippetSize = 24; #endif unsigned char * codeSnippet( unsigned char * code, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, - bool simpleRetType) + bool bHasHiddenParam) { #if OSL_DEBUG_LEVEL > 2 fprintf(stderr,"in codeSnippet functionIndex is %x\n", nFunctionIndex); @@ -608,9 +608,8 @@ unsigned char * codeSnippet( unsigned char * code, sal_Int32 nFunctionIndex, sa sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex ); - if ( !simpleRetType ) + if ( bHasHiddenParam ) nOffsetAndIndex |= 0x80000000; - #if _CALL_ELF == 2 unsigned int *raw = (unsigned int *)&code[0]; @@ -629,7 +628,7 @@ unsigned char * codeSnippet( unsigned char * code, sal_Int32 nFunctionIndex, sa #endif #if OSL_DEBUG_LEVEL > 2 fprintf(stderr, "in: offset/index is %x %x %d, %lx\n", - nFunctionIndex, nVtableOffset, !simpleRetType, raw[2]); + nFunctionIndex, nVtableOffset, bHasHiddenParam, raw[2]); #endif return (code + codeSnippetSize); } @@ -696,7 +695,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( (s++)->fn = code + writetoexecdiff; code = codeSnippet( code, functionOffset++, vtableOffset, - bridges::cpp_uno::shared::isSimpleType( + ppc64::return_in_hidden_param( reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( member)->pAttributeTypeRef)); @@ -707,7 +706,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( member)->bReadOnly) { (s++)->fn = code + writetoexecdiff; - code = codeSnippet(code, functionOffset++, vtableOffset, true); + code = codeSnippet(code, functionOffset++, vtableOffset, false); } break; @@ -715,7 +714,7 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( (s++)->fn = code + writetoexecdiff; code = codeSnippet( code, functionOffset++, vtableOffset, - bridges::cpp_uno::shared::isSimpleType( + ppc64::return_in_hidden_param( reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( member)->pReturnTypeRef)); diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc64/share.hxx b/bridges/source/cpp_uno/gcc3_linux_powerpc64/share.hxx index 87303b60c407..b5f609adc39a 100644 --- a/bridges/source/cpp_uno/gcc3_linux_powerpc64/share.hxx +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/share.hxx @@ -85,6 +85,7 @@ void fillUnoException( namespace ppc64 { enum ppclimits { MAX_GPR_REGS = 8, MAX_SSE_REGS = 13 }; + bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); } #endif diff --git a/bridges/source/cpp_uno/gcc3_linux_powerpc64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_powerpc64/uno2cpp.cxx index 33131ea78799..55a53081cc95 100644 --- a/bridges/source/cpp_uno/gcc3_linux_powerpc64/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_linux_powerpc64/uno2cpp.cxx @@ -37,6 +37,56 @@ using namespace ::rtl; using namespace ::com::sun::star::uno; +namespace ppc64 +{ +#if _CALL_ELF == 2 + bool is_complex_struct(const typelib_TypeDescription * type) + { + const typelib_CompoundTypeDescription * p + = reinterpret_cast< const typelib_CompoundTypeDescription * >(type); + for (sal_Int32 i = 0; i < p->nMembers; ++i) + { + if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT || + p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * t = 0; + TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]); + bool b = is_complex_struct(t); + TYPELIB_DANGER_RELEASE(t); + if (b) { + return true; + } + } + else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass)) + return true; + } + if (p->pBaseTypeDescription != 0) + return is_complex_struct(&p->pBaseTypeDescription->aBase); + return false; + } +#endif + + bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) + { + if (bridges::cpp_uno::shared::isSimpleType(pTypeRef)) + return false; +#if _CALL_ELF == 2 + else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); + + //A Composite Type not larger than 16 bytes is returned in up to two GPRs + bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr); + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return bRet; + } +#endif + return true; + } +} + void MapReturn(long r3, double dret, typelib_TypeClass eTypeClass, void *pRegisterReturn) { switch (eTypeClass) |