diff options
author | James Clarke <jrtc27@jrtc27.com> | 2016-08-05 18:07:33 +0200 |
---|---|---|
committer | Rene Engelhard <rene@debian.org> | 2016-08-05 18:09:59 +0200 |
commit | 3cb45765f2accfa749cc56a087059600ec467f28 (patch) | |
tree | dba1da8cd97d624754cb4e9c94776f39ae6e6b6a /bridges | |
parent | 9dd8a0dcfdff21269f6423224d39d168519fb67e (diff) |
(initial) sparc64 port
Change-Id: I8ec9bb5415a9e6b9083ba89a7790872d67625de1
Diffstat (limited to 'bridges')
-rw-r--r-- | bridges/Library_cpp_uno.mk | 7 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_linux_sparc64/call.s | 77 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_linux_sparc64/cpp2uno.cxx | 746 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_linux_sparc64/except.cxx | 301 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_linux_sparc64/share.hxx | 100 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_linux_sparc64/uno2cpp.cxx | 836 |
6 files changed, 2067 insertions, 0 deletions
diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk index ebb8323bcfc3..d7ec27dd1ea5 100644 --- a/bridges/Library_cpp_uno.mk +++ b/bridges/Library_cpp_uno.mk @@ -159,6 +159,13 @@ bridge_noopt_objects := cpp2uno uno2cpp bridge_exception_objects := except endif +else ifeq ($(OS)-$(CPUNAME),LINUX-SPARC64) + +bridges_SELECTED_BRIDGE := gcc3_linux_sparc64 +bridge_asm_objects := call +bridge_noopt_objects := cpp2uno uno2cpp +bridge_exception_objects := except + else ifeq ($(CPUNAME),X86_64) ifneq ($(filter DRAGONFLY FREEBSD LINUX NETBSD OPENBSD,$(OS)),) diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc64/call.s b/bridges/source/cpp_uno/gcc3_linux_sparc64/call.s new file mode 100644 index 000000000000..7aed24c7a45e --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc64/call.s @@ -0,0 +1,77 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +.global doFlushCode +doFlushCode: +.L: flush %o0 + deccc %o1 + bne .L + add %o0, 8, %o0 + retl + nop +.size doFlushCode,(.-doFlushCode) +.align 8 + +// %{o->i}0: index +// %{o->i}1: pCallStack = %{s->f}p+2047 +// %{o->i}2: vtableOffset +// %{o->i}3: cpp_vtable_call +// %{o->i}4: frameSize (negative) +// [%{s->f}p+2047+128]: param 0 ... + .file "call.s" + .text + .align 4 + .global privateSnippetExecutor + .type privateSnippetExecutor, #function +privateSnippetExecutor: +.LFB0: + //// Already done by codeSnippet + .cfi_startproc + save %sp, -176, %sp + .cfi_window_save + // Register 8 (%o0) saved to register 24 (%i0) + .cfi_register 8, 24 + // Register 9 (%o1) saved to register 25 (%i1) + .cfi_register 9, 25 + // Register 10 (%o2) saved to register 26 (%i2) + .cfi_register 10, 26 + // Register 11 (%o3) saved to register 27 (%i3) + .cfi_register 11, 27 + // Register 12 (%o4) saved to register 28 (%i4) + .cfi_register 12, 28 + // Register 15 (%o7) saved to register 31 (%i7) + .cfi_register 15, 31 + // Use register 30 (%i6 - saved stack pointer) for Call Frame Address + .cfi_def_cfa_register 30 + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + jmpl %i3, %o7 + nop + mov %o0, %i0 + mov %o1, %i1 + mov %o2, %i2 + mov %o3, %i3 + ret + restore + .cfi_endproc +.LFE0: + .size privateSnippetExecutor,(.-privateSnippetExecutor) + .section .note.GNU-stack,"",@progbits + +.align 8 diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_sparc64/cpp2uno.cxx new file mode 100644 index 000000000000..746281d75387 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc64/cpp2uno.cxx @@ -0,0 +1,746 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/uno/genfunc.hxx> +#include <sal/log.hxx> +#include <typelib/typedescription.hxx> +#include <uno/data.h> +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" +#include "share.hxx" + +#define GET_FP(n, p) \ + __asm__( "ldx %0, %%l0\n\t" \ + "std %%f" #n ", [%%l0]\n" \ + : : "m"(p) ); + +using namespace com::sun::star::uno; + +namespace CPPU_CURRENT_NAMESPACE +{ + bool is_complex_struct(const typelib_TypeDescription * type) + { + for (const typelib_CompoundTypeDescription * p + = reinterpret_cast< const typelib_CompoundTypeDescription * >(type); + p != NULL; p = p->pBaseTypeDescription) + { + 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; + } + } + return false; + } + + bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) + { + if (bridges::cpp_uno::shared::isSimpleType(pTypeRef)) + return false; + 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 32 bytes is returned in up to two GPRs + bool bRet = pTypeDescr->nSize > 32 || is_complex_struct(pTypeDescr); + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return bRet; + } + return true; + } +} + + +namespace +{ + +static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: [ret ptr], this, params + char * pCppStack = (char *)pCallStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + int paramsOffset; + if (pReturnTypeDescr) + { + if (CPPU_CURRENT_NAMESPACE::return_in_hidden_param( pReturnTypeRef ) ) + { + pCppReturn = *(void**)pCppStack; // complex return via ptr (pCppReturn) + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + pCppStack += sizeof( void* ); + paramsOffset = 2; + } + else + { + pUnoReturn = pRegisterReturn; // direct way for simple types + paramsOffset = 1; + } + } + else + { + paramsOffset = 1; + } + // pop this + pCppStack += sizeof( void* ); + + // stack space + static_assert(sizeof(void *) == sizeof(sal_Int64), "### unexpected size!"); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indices of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndices = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndices = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value + { + pCppArgs[nPos] = pUnoArgs[nPos] = CPPU_CURRENT_NAMESPACE::adjustPointer(pCppStack, pParamTypeDescr); + switch (pParamTypeDescr->eTypeClass) { + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + { + int paramArrayIdx = nPos + paramsOffset; + assert(paramArrayIdx < nParams + paramsOffset); + switch (paramArrayIdx) { + // Cannot be 0 - paramsOffset >= 1 + case 1: + GET_FP(2, pCppStack); + break; + case 2: + GET_FP(4, pCppStack); + break; + case 3: + GET_FP(6, pCppStack); + break; + case 4: + GET_FP(8, pCppStack); + break; + case 5: + GET_FP(10, pCppStack); + break; + case 6: + GET_FP(12, pCppStack); + break; + case 7: + GET_FP(14, pCppStack); + break; + case 8: + GET_FP(16, pCppStack); + break; + case 9: + GET_FP(18, pCppStack); + break; + case 10: + GET_FP(20, pCppStack); + break; + case 11: + GET_FP(22, pCppStack); + break; + case 12: + GET_FP(24, pCppStack); + break; + case 13: + GET_FP(26, pCppStack); + break; + case 14: + GET_FP(28, pCppStack); + break; + case 15: + GET_FP(30, pCppStack); + break; + // Anything larger is passed on the stack + } + break; + } + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndices[nTempIndices] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndices[nTempIndices] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int64); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)(pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + for ( ; nTempIndices--; ) + { + sal_Int32 nIndex = pTempIndices[nTempIndices]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndices], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + CPPU_CURRENT_NAMESPACE::raiseException(&aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + for ( ; nTempIndices--; ) + { + sal_Int32 nIndex = pTempIndices[nTempIndices]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + + +static typelib_TypeClass cpp_mediate( + sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + static_assert(sizeof(sal_Int64)==sizeof(void *), "### unexpected!"); + + // pCallStack: [ret*], this, params + void * pThis; + if (nFunctionIndex & 0x80000000) + { + nFunctionIndex &= 0x7fffffff; + pThis = pCallStack[1]; + } + else + { + pThis = pCallStack[0]; + } + + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = + bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis ); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + SAL_WARN( + "bridges", + "illegal " << OUString::unacquired(&pTypeDescr->aBase.pTypeName) + << " vtable index " << nFunctionIndex << "/" + << pTypeDescr->nMapFunctionIndexToMemberIndex); + throw RuntimeException( + ("illegal " + OUString::unacquired(&pTypeDescr->aBase.pTypeName) + + " vtable index " + OUString::number(nFunctionIndex) + "/" + + OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)), + (XInterface *)pCppI); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + assert(nMemberPos < pTypeDescr->nAllMembers); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + +#if defined BRIDGES_DEBUG + OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex ); +#endif + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[2] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[0] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = pCallStack[0]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( "no member description found!", (XInterface *)pCppI ); + } + } + return eRet; +} + + + +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static void cpp_vtable_call(int nFunctionIndex, void** pCallStack, int vTableOffset) +{ + sal_Int64 nRegReturn[4] = { 0 }; + void * pRegReturn = &nRegReturn[0]; + + //__asm__( "st %%i0, %0\n\t" + // "stx %%i1, %1\n\t" + // "st %%i2, %2\n\t" + // : : "m"(nFunctionIndex), "m"(pCallStack), "m"(vTableOffset) ); + +// fprintf(stderr,"cpp_mediate nFunctionIndex=%x\n",nFunctionIndex); +// fflush(stderr); + + //const sal_Bool bComplex = (nFunctionIndex & 0x80000000) ? sal_True : sal_False; + typelib_TypeClass aType = + cpp_mediate( nFunctionIndex, vTableOffset, pCallStack+16, (sal_Int64*)&nRegReturn ); + + switch( aType ) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + __asm__( "ldx %0, %%l0\n\t" + "ldsb [%%l0], %%i0\n" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + __asm__( "ldx %0, %%l0\n\t" + "ldsh [%%l0], %%i0\n" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + __asm__( "ldx %0, %%l0\n\t" + "ld [%%l0], %%i0\n" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + __asm__( "ldx %0, %%l0\n\t" + "ldx [%%l0], %%i0\n\t" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_FLOAT: + __asm__( "ldx %0, %%l0\n\t" + "ld [%%l0], %%f0\n" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_DOUBLE: + __asm__( "ldx %0, %%l0\n\t" + "ldd [%%l0], %%f0\n" + : : "m"(pRegReturn) ); + break; + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + __asm__( "ldx %0, %%l0\n\t" + "ldx [%%l0 ], %%i0\n\t" + "ldx [%%l0+ 8], %%i1\n\t" + "ldx [%%l0+16], %%i2\n\t" + "ldx [%%l0+24], %%i3\n\t" + "ldd [%%l0 ], %%f0\n\t" + "ldd [%%l0+ 8], %%f2\n\t" + "ldd [%%l0+16], %%f4\n\t" + "ldd [%%l0+24], %%f6\n\t" + : : "m"(pRegReturn) ); + break; + default: + break; + } + + //if( bComplex ) + //{ + // __asm__( "add %i7, 4, %i7\n\t" ); + // // after call to complex return valued funcion there is an unimp instruction + //} + +} + +extern "C" void privateSnippetExecutor(...); + +int const codeSnippetSize = 120; +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + bool bHasHiddenParam, sal_Int32 nParams) +{ + sal_uInt32 index = functionIndex; + if (bHasHiddenParam) { + index |= 0x80000000; + } + unsigned int * p = reinterpret_cast< unsigned int * >(code); + static_assert(sizeof (unsigned int) == 4, "boo"); + static_assert(sizeof (unsigned long long) == 8, "boo"); + ++nParams; // implicit this ptr + if (bHasHiddenParam) { + ++nParams; + } + long long frameSize; + if (nParams > 6) { + frameSize = 128 + nParams * 8; + } else { + frameSize = 176; + } + assert(frameSize <= 4096); + frameSize = -frameSize; + switch (nParams) { + default: + assert(nParams >= 6); + // stx %o5, [%sp+168+2047]: + *p++ = 0xDA73A8A7; + case 5: + // stx %o4, [%sp+160+2047]: + *p++ = 0xD873A89F; + case 4: + // stx %o3, [%sp+152+2047]: + *p++ = 0xD673A897; + case 3: + // stx %o2, [%sp+144+2047]: + *p++ = 0xD473A88F; + case 2: + // stx %o1, [%sp+136+2047]: + *p++ = 0xD273A887; + case 1: + // stx %o0, [%sp+128+2047]: + *p++ = 0xD073A87F; + case 0: + break; + } + // sethi %hi(index), %o0: + *p++ = 0x11000000 | (index >> 10); + // or %o0, %lo(index), %o0: + *p++ = 0x90122000 | (index & 0x3FF); + // sethi %hh(cpp_vtable_call), %o3: + *p++ = 0x17000000 | (reinterpret_cast< unsigned long long >(cpp_vtable_call) >> 42); + // or %o3, %hm(cpp_vtable_call), %o3: + *p++ = 0x9612E000 | ((reinterpret_cast< unsigned long long >(cpp_vtable_call) >> 32) & 0x3FF); + // sllx %o3, 32, %o3 + *p++ = 0x972AF020; + // sethi %lm(cpp_vtable_call), %o2: + *p++ = 0x15000000 | ((reinterpret_cast< unsigned long long >(cpp_vtable_call) >> 10) & 0x3FFFFF); + // or %o2, %lo(cpp_vtable_call), %o2: + *p++ = 0x9412A000 | (reinterpret_cast< unsigned long long >(cpp_vtable_call) & 0x3FF); + // or %o2, %o3, %o3: + *p++ = 0x9612800B; + // sethi %hh(privateSnippetExecutor), %o1: + *p++ = 0x13000000 | (reinterpret_cast< unsigned long long >(privateSnippetExecutor) >> 42); + // or %o1, %hm(privateSnippetExecutor), %o1: + *p++ = 0x92126000 | ((reinterpret_cast< unsigned long long >(privateSnippetExecutor) >> 32) & 0x3FF); + // sllx %o1, 32, %o1: + *p++ = 0x932a7020; + // sethi %lm(privateSnippetExecutor), %o2: + *p++ = 0x15000000 | ((reinterpret_cast< unsigned long long >(privateSnippetExecutor) >> 10) & 0x3FFFFF); + // or %o2, %lo(privateSnippetExecutor), %o2: + *p++ = 0x9412A000 | (reinterpret_cast< unsigned long long >(privateSnippetExecutor) & 0x3FF); + // or %o2, %o1, %o1: + *p++ = 0x92128009; + // sethi %hh(frameSize), %o4: + *p++ = 0x19000000 | (*reinterpret_cast< unsigned long long * >(&frameSize) >> 42); + // or %o4, %hm(frameSize), %o4: + *p++ = 0x98132000 | ((*reinterpret_cast< unsigned long long * >(&frameSize) >> 32) & 0x3FF); + // sllx %o4, 32, %o4 + *p++ = 0x992B3020; + // sethi %lm(frameSize), %o2: + *p++ = 0x15000000 | ((*reinterpret_cast< unsigned long long * >(&frameSize) >> 10) & 0x3FFFFF); + // or %o2, %lo(frameSize), %o2: + *p++ = 0x9412A000 | (*reinterpret_cast< unsigned long long * >(&frameSize) & 0x3FF); + // or %o2, %o4, %o4: + *p++ = 0x9812800C; + // sethi %hi(vtableOffset), %o2: + *p++ = 0x15000000 | (vtableOffset >> 10); + // or %o2, %lo(vtableOffset), %o2: + *p++ = 0x9412A000 | (vtableOffset & 0x3FF); + // save %sp, -frameSize, %sp + //*p++ = 0x9DE3A000 | (*reinterpret_cast< unsigned int * >(&frameSize) & 0x1FFF); + // jmpl %o1, %g0: + *p++ = 0x81C24000; + // add %sp, 2047, %o1: + *p++ = 0x9203A7FF; + assert(reinterpret_cast< unsigned char * >(p) - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} //end of namespace + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 2; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount, sal_Int32, + typelib_InterfaceTypeDescription *) +{ + Slot * slots = mapBlockToVtable(block); + slots[-2].fn = 0; //null + slots[-1].fn = 0; //destructor + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vTableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + for (sal_Int32 i = 0; i < type->nMembers; ++i) { + typelib_TypeDescription * member = 0; + TYPELIB_DANGER_GET(&member, type->ppMembers[i]); + assert(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vTableOffset, + CPPU_CURRENT_NAMESPACE::return_in_hidden_param( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef), 0); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code + writetoexecdiff; + code = codeSnippet(code, functionOffset++, vTableOffset, false, 1); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code + writetoexecdiff; + code = codeSnippet( + code, functionOffset++, vTableOffset, + CPPU_CURRENT_NAMESPACE::return_in_hidden_param( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef), + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->nParams); + break; + + default: + assert(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +// use flush code from cc50_solaris_sparc + +extern "C" void doFlushCode(unsigned long address, unsigned long count); + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const * begin, unsigned char const * end) +{ + unsigned long n = end - begin; + if (n != 0) { + unsigned long adr = reinterpret_cast< unsigned long >(begin); + unsigned long off = adr & 7; + doFlushCode(adr - off, (n + off + 7) >> 3); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc64/except.cxx b/bridges/source/cpp_uno/gcc3_linux_sparc64/except.cxx new file mode 100644 index 000000000000..720e4d617afb --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc64/except.cxx @@ -0,0 +1,301 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <cxxabi.h> +#include <rtl/strbuf.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> +#include <osl/mutex.hxx> + +#include <com/sun/star/uno/genfunc.hxx> +#include <typelib/typedescription.hxx> +#include <uno/any2.h> +#include <unordered_map> +#include "share.hxx" + + +using namespace ::std; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::__cxxabiv1; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +void dummy_can_throw_anything( char const * ) +{ +} + +static OUString toUNOname( char const * p ) +{ +#if defined BRIDGES_DEBUG + char const * start = p; +#endif + + // example: N3com3sun4star4lang24IllegalArgumentExceptionE + + OUStringBuffer buf( 64 ); + assert( 'N' == *p ); + ++p; // skip N + + while ('E' != *p) + { + // read chars count + long n = (*p++ - '0'); + while ('0' <= *p && '9' >= *p) + { + n *= 10; + n += (*p++ - '0'); + } + buf.appendAscii( p, n ); + p += n; + if ('E' != *p) + buf.append( '.' ); + } + +#if defined BRIDGES_DEBUG + OUString ret( buf.makeStringAndClear() ); + OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() ); + return ret; +#else + return buf.makeStringAndClear(); +#endif +} + +class RTTI +{ + typedef std::unordered_map< OUString, type_info *, OUStringHash > t_rtti_map; + + Mutex m_mutex; + t_rtti_map m_rttis; + t_rtti_map m_generatedRttis; + + void * m_hApp; + +public: + RTTI(); + ~RTTI(); + + type_info * getRTTI( typelib_CompoundTypeDescription * ); +}; + +RTTI::RTTI() + : m_hApp( dlopen( 0, RTLD_LAZY ) ) +{ +} + +RTTI::~RTTI() +{ + dlclose( m_hApp ); +} + + +type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) +{ + type_info * rtti; + + OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName; + + MutexGuard guard( m_mutex ); + t_rtti_map::const_iterator iFind( m_rttis.find( unoName ) ); + if (iFind == m_rttis.end()) + { + // RTTI symbol + OStringBuffer buf( 64 ); + buf.append( "_ZTIN" ); + sal_Int32 index = 0; + do + { + OUString token( unoName.getToken( 0, '.', index ) ); + buf.append( token.getLength() ); + OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( c_token ); + } + while (index >= 0); + buf.append( 'E' ); + + OString symName( buf.makeStringAndClear() ); + rtti = (type_info *)dlsym( m_hApp, symName.getStr() ); + + if (rtti) + { + pair< t_rtti_map::iterator, bool > insertion( + m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + assert(insertion.second); + } + else + { + // try to lookup the symbol in the generated rtti map + t_rtti_map::const_iterator iiFind( m_generatedRttis.find( unoName ) ); + if (iiFind == 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 defined BRIDGES_DEBUG + fprintf( stderr,"generated rtti for %s\n", rttiName ); +#endif + 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 ) ); + } + + pair< t_rtti_map::iterator, bool > insertion( + m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) ); + assert(insertion.second); + } + else // taking already generated rtti + { + rtti = iiFind->second; + } + } + } + else + { + rtti = iFind->second; + } + + return rtti; +} + + +static void deleteException( void * pExc ) +{ + __cxa_exception const * header = ((__cxa_exception const *)pExc - 1); + typelib_TypeDescription * pTD = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); + ::typelib_typedescription_getByName( &pTD, unoName.pData ); + assert(pTD && "### unknown exception type! leaving out destruction => leaking!!!"); + if (pTD) + { + ::uno_destructData( pExc, pTD, cpp_release ); + ::typelib_typedescription_release( pTD ); + } +} + +void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ +#if defined BRIDGES_DEBUG + OString cstr( + OUStringToOString( + OUString::unacquired( &pUnoExc->pType->pTypeName ), + RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "> uno exception occurred: %s\n", cstr.getStr() ); +#endif + void * pCppExc; + type_info * rtti; + + { + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + assert(pTypeDescr); + if (! pTypeDescr) + { + throw RuntimeException( + OUString("cannot get typedescription for type ") + + OUString::unacquired( &pUnoExc->pType->pTypeName ) ); + } + + 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 ); + assert(rtti); + if (! rtti) + { + throw RuntimeException( + OUString("no rtti for type ") + + OUString::unacquired( &pUnoExc->pType->pTypeName ) + ); + } + } + + __cxa_throw( pCppExc, rtti, deleteException ); +} + +void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (! header) + { + RuntimeException aRE( "no exception header!" ); + Type const & rType = cppu::UnoType<decltype(aRE)>::get(); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); + SAL_WARN("bridges", aRE.Message); + return; + } + + typelib_TypeDescription * pExcTypeDescr = 0; + OUString unoName( toUNOname( header->exceptionType->name() ) ); +#if defined BRIDGES_DEBUG + 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("exception type not found: ") + unoName ); + Type const & rType = cppu::UnoType<decltype(aRE)>::get(); + uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno ); + SAL_WARN("bridges", aRE.Message); + } + else + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno ); + typelib_typedescription_release( pExcTypeDescr ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc64/share.hxx b/bridges/source/cpp_uno/gcc3_linux_sparc64/share.hxx new file mode 100644 index 000000000000..65dcba617551 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc64/share.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_SPARC64_SHARE_HXX +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_SPARC64_SHARE_HXX + +#include "uno/mapping.h" +#include <typeinfo> +#include <exception> +#include <cstddef> +namespace CPPU_CURRENT_NAMESPACE +{ +void dummy_can_throw_anything( char const * ); +// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h + +struct _Unwind_Exception +{ + unsigned exception_class __attribute__((__mode__(__DI__))); + void * exception_cleanup; + unsigned private_1 __attribute__((__mode__(__word__))); + unsigned private_2 __attribute__((__mode__(__word__))); +} __attribute__((__aligned__)); + +struct __cxa_exception +{ + ::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_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(); + +void raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); + +void fillUnoException( + __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno ); + +bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); + +inline char* adjustPointer( char* pIn, typelib_TypeDescription* pType ) +{ + switch( pType->nSize ) + { + case 1: return pIn + 7; + case 2: return pIn + 6; + case 3: return pIn + 5; + case 4: return pIn + 4; + case 5: return pIn + 3; + case 6: return pIn + 2; + case 7: return pIn + 1; + // Huh ? perhaps a char[3] ? Though that would be a pointer + // well, we have it anyway for symmetry + } + return pIn; +} + +} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_linux_sparc64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_sparc64/uno2cpp.cxx new file mode 100644 index 000000000000..8caaee5f2ffb --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_linux_sparc64/uno2cpp.cxx @@ -0,0 +1,836 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <malloc.h> +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" +#include "bridges/cpp_uno/shared/vtables.hxx" + +#include "share.hxx" + +#define SET_FP(n, p) \ + __asm__( "ldx %0, %%l0\n\t" \ + "ldd [%%l0], %%f" #n "\n" \ + : : "m"(p) ); + +using namespace com::sun::star::uno; + +namespace +{ + void fillReturn(const typelib_TypeDescription * pTypeDescr, + long long * oret, float * fret, double * dret, void * pRegisterReturn) + { + for (const typelib_CompoundTypeDescription *p = + reinterpret_cast<const typelib_CompoundTypeDescription*>( pTypeDescr ); + p != NULL; p = p->pBaseTypeDescription) + { + + for (sal_Int32 i = 0; i < p->nMembers; ++i) + { + typelib_TypeDescriptionReference *pTypeInStruct = p->ppTypeRefs[ i ]; + + sal_Int32 nOff = p->pMemberOffsets[ i ]; + + switch (pTypeInStruct->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *(long*)((char *)pRegisterReturn + nOff) = *(long*)((char *)oret + nOff); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *(int*)((char *)pRegisterReturn + nOff) = *(int*)((char *)oret + nOff); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)((char *)pRegisterReturn + nOff) = *(unsigned short*)((char *)oret + nOff); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)((char *)pRegisterReturn + nOff) = *(unsigned char*)((char *)oret + nOff); + break; + case typelib_TypeClass_FLOAT: + *(float*)((char *)pRegisterReturn + nOff) = *(float*)((char *)fret + nOff); + break; + case typelib_TypeClass_DOUBLE: + *(double*)((char *)pRegisterReturn + nOff) = *(double*)((char *)dret + nOff); + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * td = NULL; + TYPELIB_DANGER_GET(&td, pTypeInStruct); + fillReturn(td, + (long long *)((char *)oret + nOff), + (float *)((char *)fret + nOff), + (double *)((char *)dret + nOff), + (char *)pRegisterReturn + nOff); + TYPELIB_DANGER_RELEASE(td); + } + default: + break; + } + } + } + } + +// The call instruction within the asm section of callVirtualMethod may throw +// exceptions. So that the compiler handles this correctly, it is important +// that (a) callVirtualMethod might call dummy_can_throw_anything (although this +// never happens at runtime), which in turn can throw exceptions, and (b) +// callVirtualMethod is not inlined at its call site (so that any exceptions are +// caught which are thrown from the instruction calling callVirtualMethod): + +void callVirtualMethod( void * pAdjustedThisPtr, + sal_Int32 nVtableIndex, + void * pRegisterReturn, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int64 * pStackHypers, + sal_Int32 nStackHypers, + typelib_MethodParameter * pParams, sal_Int32 nParams) __attribute__((noinline)); + +void callVirtualMethod( void * pAdjustedThisPtr, + sal_Int32 /* nVtableIndex */, + void * pRegisterReturn, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int64 * pStackHypers, +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nStackHypers, +#else +// sal_Int64 * /*pStackHypers*/, + sal_Int32 /*nStackHypers*/, +#endif + typelib_MethodParameter * pParams, sal_Int32 nParams) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + assert(pStackHypers && pAdjustedThisPtr); + static_assert( (sizeof(void *) == 8) && + (sizeof(sal_Int64) == 8), "### unexpected size of int!" ); + assert(nStackHypers && pStackHypers && "### no stack in callVirtualMethod !"); + + // never called + if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + long bSimpleReturn = !CPPU_CURRENT_NAMESPACE::return_in_hidden_param( pReturnTypeRef ); + + int paramsOffset = bSimpleReturn ? 1 : 2; + for (sal_Int32 i = 0; i < nParams; ++i) + { + if (!pParams[i].bOut) + { + switch (pParams[i].pTypeRef->eTypeClass) { + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + { + int paramArrayIdx = i + paramsOffset; + assert(paramArrayIdx < nStackHypers); + void *p = &pStackHypers[paramArrayIdx]; + switch (paramArrayIdx) { + // Cannot be 0 - paramsOffset >= 1 + case 1: + SET_FP(2, p); + break; + case 2: + SET_FP(4, p); + break; + case 3: + SET_FP(6, p); + break; + case 4: + SET_FP(8, p); + break; + case 5: + SET_FP(10, p); + break; + case 6: + SET_FP(12, p); + break; + case 7: + SET_FP(14, p); + break; + case 8: + SET_FP(16, p); + break; + case 9: + SET_FP(18, p); + break; + case 10: + SET_FP(20, p); + break; + case 11: + SET_FP(22, p); + break; + case 12: + SET_FP(24, p); + break; + case 13: + SET_FP(26, p); + break; + case 14: + SET_FP(28, p); + break; + case 15: + SET_FP(30, p); + break; + // Anything larger is passed on the stack + } + break; + } + default: + break; + } + } + } + + //long o0; + //double f0d; + //float f0f; + volatile long long saveReg[14]; + + long long oret[4]; + union { + float f[8]; + double d[4]; + } fdret; + + __asm__ ( + // save registers + "stx %%l0, [%[saveReg]]\n\t" + "stx %%l1, [%[saveReg]+8]\n\t" + "mov %[saveReg], %%l1\n\t" + "add %%l1, 16, %%l0\n\t" + "stx %%l2, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%l3, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%l4, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%l5, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%o0, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%o1, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%o2, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%o3, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%o4, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%o5, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%l6, [%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "stx %%l7, [%%l0]\n\t" + "mov %%l1, %%l7\n\t" + + // increase our own stackframe if necessary + "mov %%sp, %%l3\n\t" // save stack ptr for readjustment + + "subcc %%i5, 6, %%l0\n\t" + "ble .LmoveOn\n\t" + "nop\n\t" + + "sllx %%l0, 3, %%l0\n\t" + "add %%l0, 192, %%l0\n\t" + "add %%sp, 2047, %%l1\n\t" // old stack ptr + "sub %%l1, %%l0, %%l0\n\t" // future stack ptr + "andcc %%l0, 15, %%g0\n\t" // align stack to 16 + "be .LisAligned\n\t" + "nop\n\t" + "sub %%l0, 8, %%l0\n" + ".LisAligned:\n\t" + "mov %%l0, %%o5\n\t" // save newly computed stack ptr + "add %%g0, 16, %%o4\n" + + // now copy hypers down to save register window + // and local variables + ".LcopyDown:\n\t" + "ldx [%%l1], %%l2\n\t" + "stx %%l2,[%%l0]\n\t" + "add %%l0, 8, %%l0\n\t" + "add %%l1, 8, %%l1\n\t" + "subcc %%o4, 1, %%o4\n\t" + "bne .LcopyDown\n\t" + "nop\n\t" + + "sub %%o5, 2047, %%sp\n\t" // move new stack ptr (hopefully) atomically - with bias + // while register window is valid in both spaces + // (scheduling might hit in copyDown loop) + + "sub %%i5, 6, %%l0\n\t" // copy parameters past the sixth to stack + "add %%i4, 48, %%l1\n\t" + "add %%sp, 2223, %%l2\n" // 2047+176 + ".LcopyLong:\n\t" + "ldx [%%l1], %%o0\n\t" + "stx %%o0, [%%l2]\n\t" + "add %%l1, 8, %%l1\n\t" + "add %%l2, 8, %%l2\n\t" + "subcc %%l0, 1, %%l0\n\t" + "bne .LcopyLong\n\t" + "nop\n" + + ".LmoveOn:\n\t" + "mov %%i5, %%l0\n\t" // prepare out registers + "mov %%i4, %%l1\n\t" + + "ldx [%%l1], %%o0\n\t"// // prepare complex return ptr + //"ldd [%%l1], %%f0\n\t" + //"stx %%o0, [%%sp+2047+128]\n\t" + "sub %%l0, 1, %%l0\n\t" + "add %%l1, 8, %%l1\n\t" + //"subxcc %%o0, %%g0, %%o0\n\t" + //"bne .LhadComplexReturn\n\t" + //"nop\n\t" + + // No complex return ptr - this (next on stack) goes in %o0 + + //"ldx [%%l1], %%o0\n\t" + //"subcc %%l0, 1, %%l0\n\t" + //"be .LdoCall\n\t" + //"nop\n\t" + //"add %%l1, 8, %%l1\n\t" + + //".LhadComplexReturn:\n\t" + "ldx [%%l1], %%o1\n\t" + //"ldd [%%l1], %%f2\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 8, %%l1\n\t" + "ldx [%%l1], %%o2\n\t" + //"ldd [%%l1], %%f4\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 8, %%l1\n\t" + "ldx [%%l1], %%o3\n\t" + //"ldd [%%l1], %%f6\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 8, %%l1\n\t" + "ldx [%%l1], %%o4\n\t" + //"ldd [%%l1], %%f8\n\t" + "subcc %%l0, 1, %%l0\n\t" + "be .LdoCall\n\t" + "nop\n\t" + + "add %%l1, 8, %%l1\n\t" + "ldx [%%l1], %%o5\n" + //"ldd [%%l1], %%f10\n\t" + + ".LdoCall:\n\t" + "ldx [%%i0], %%l0\n\t" // get vtable ptr + +"sllx %%i1, 3, %%l6\n\t" +// "add %%l6, 8, %%l6\n\t" + "add %%l6, %%l0, %%l0\n\t" +// // vtable has 8byte wide entries, +// // upper half contains 2 half words, of which the first +// // is the this ptr patch ! +// // first entry is (or __tf) + +// "ldsh [%%l0], %%l6\n\t" // load this ptr patch +// "add %%l6, %%o0, %%o0\n\t" // patch this ptr + +// "add %%l0, 4, %%l0\n\t" // get virtual function ptr + "ldx [%%l0], %%l0\n\t" + +// "ldx %0, %%l2\n\t" +// "subcc %%l2, %%g0, %%l2\n\t" +// "be .LcomplexCall\n\t" +// "nop\n\t" + "call %%l0\n\t" + "nop\n\t" +// "ba .LcallReturned\n\t" +// "nop\n" +// ".LcomplexCall:\n\t" +// "call %%l0\n\t" +// "nop\n\t" +// "unimp\n" + +// ".LcallReturned:\n\t" + "subcc %%l3, %%sp, %%g0\n\t" + "be .LcopiedUp\n\t" + "nop\n\t" + // Copy register save area back up + // Note: copy in reverse order (top down) in case areas overlap + "add %%sp, 2167, %%l0\n\t" // 2047+120 + "add %%l3, 2167, %%l1\n\t" + "add %%g0, 16, %%o4\n\t" + ".LcopyUp:\n\t" + "ldx [%%l0], %%l2\n\t" + "stx %%l2, [%%l1]\n\t" + "sub %%l0, 8, %%l0\n\t" + "sub %%l1, 8, %%l1\n\t" + "subcc %%o4, 1, %%o4\n\t" + "bne .LcopyUp\n\t" + "nop\n\t" + + ".LcopiedUp:\n\t" + "mov %%l3, %%sp\n\t" // readjust stack so that our locals are where they belong + + // save possible return registers into our locals + "stx %%o0, %[oret0]\n\t" + "stx %%o1, %[oret1]\n\t" + "stx %%o2, %[oret2]\n\t" + "stx %%o3, %[oret3]\n\t" + "std %%f0, %[dret0]\n\t" + "std %%f2, %[dret1]\n\t" + "std %%f4, %[dret2]\n\t" + "std %%f6, %[dret3]\n\t" + //"st %%f0, %3\n\t" + + // restore registers + "ldx [%%l7], %%l0\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%l1\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%l2\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%l3\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%l4\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%l5\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%o0\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%o1\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%o2\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%o3\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%o4\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%o5\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%l6\n\t" + "add %%l7, 8, %%l7\n\t" + "ldx [%%l7], %%l7\n\t" + : + //"=m"(bSimpleReturn), + [oret0]"=m"(oret[0]), [oret1]"=m"(oret[1]), [oret2]"=m"(oret[2]), [oret3]"=m"(oret[3]), + [dret0]"=m"(fdret.d[0]), [dret1]"=m"(fdret.d[1]), [dret2]"=m"(fdret.d[2]), [dret3]"=m"(fdret.d[3]) + //"=m"(f0f) + : + [saveReg]"r"(&saveReg[0]) + : + "memory" + ); + switch(pReturnTypeRef->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *(long*)pRegisterReturn = oret[0]; + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *(int*)pRegisterReturn = (int)oret[0]; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = (unsigned short)oret[0]; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = (unsigned char)oret[0]; + break; + case typelib_TypeClass_FLOAT: + *(float*)pRegisterReturn = fdret.f[0]; + break; + case typelib_TypeClass_DOUBLE: + *(double*)pRegisterReturn = fdret.d[0]; + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize; + if (bSimpleReturn && nRetSize <= 32 && nRetSize > 0) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pReturnTypeRef ); + fillReturn(pTypeDescr, oret, fdret.f, fdret.d, pRegisterReturn); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + break; + } + default: + break; + } +} + +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: complex ret ptr, this, values|ptr ... + char * pCppStack = + (char *)alloca( (nParams+2) * sizeof(sal_Int64) ); + char * pCppStackStart = pCppStack; + + //fprintf(stderr, "pCppStack: %p, pCppStackStart: %p\n", pCppStack, pCppStackStart); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + assert(pReturnTypeDescr); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if ( CPPU_CURRENT_NAMESPACE::return_in_hidden_param( pReturnTypeRef ) ) + { + // complex return via ptr + pCppReturn = *(void **)pCppStack = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + pCppStack += sizeof(void*); + } + else + { + pCppReturn = pUnoReturn; // direct way for simple types + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + *(void**)pCppStack = pAdjustedThisPtr; + pCppStack += sizeof( void* ); + + // stack space + static_assert(sizeof(void *) == sizeof(sal_Int64), "### unexpected size!"); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indices of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndices = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_LONG: + *(sal_Int64 *)pCppStack = *(sal_Int32 *)pCppArgs[nPos]; + break; + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + *(sal_Int64 *)pCppStack = *(sal_uInt32 *)pCppArgs[nPos]; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + *(sal_Int64 *)pCppStack = *(sal_Int16 *)pCppArgs[nPos]; + break; + case typelib_TypeClass_UNSIGNED_SHORT: + *(sal_Int64 *)pCppStack = *(sal_uInt16 *)pCppArgs[nPos]; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(sal_Int64 *)pCppStack = *(sal_Int8 *)pCppArgs[nPos]; + break; + case typelib_TypeClass_FLOAT: + *(float *)(pCppStack+4) = *(float *)pCppArgs[nPos]; + break; + case typelib_TypeClass_DOUBLE: + *(double *)pCppStack = *(double *)pCppArgs[nPos]; + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + *(sal_Int64 *)pCppStack = *(sal_Int64 *)pCppArgs[nPos]; + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndices[nTempIndices] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempIndices[nTempIndices] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int64); // standard parameter length + } + + try + { + int nStackHypers = (pCppStack - pCppStackStart)/sizeof(sal_Int64); + assert( !( (pCppStack - pCppStackStart ) & 7) && "UNALIGNED STACK !!! (Please DO panic" ); + + //fprintf( stderr, "callVirtualMethod: %p, %lld, %p, %p, %p, %lld\n", + // pAdjustedThisPtr, + // (long long)aVtableSlot.index, + // pCppReturn, + // pReturnTypeRef, + // pCppStackStart, + // (long long)nStackHypers); + callVirtualMethod( + pAdjustedThisPtr, + aVtableSlot.index, + pCppReturn, + pReturnTypeRef, + (sal_Int64 *)pCppStackStart, + nStackHypers, + pParams, + nParams); + // NO exception occurred... + *ppUnoExc = 0; + + // reconvert temporary params + for ( ; nTempIndices--; ) + { + sal_Int32 nIndex = pTempIndices[nTempIndices]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + catch( ... ) + { + // get exception + fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, + *ppUnoExc, pThis->getBridge()->getCpp2Uno() ); + + // temporary params + for ( ; nTempIndices--; ) + { + sal_Int32 nIndex = pTempIndices[nTempIndices]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] ); + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ +#if defined BRIDGES_DEBUG + OString cstr( OUStringToOString( pMemberDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "received dispatch( %s )\n", cstr.getStr() ); +#endif + + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); +// typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName("void"); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString("illegal member type description!"), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = cppu::UnoType<decltype(aExc)>::get(); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |