diff options
author | jan Iversen <jani@libreoffice.org> | 2017-09-21 11:17:35 +0200 |
---|---|---|
committer | jan Iversen <jani@libreoffice.org> | 2017-09-21 14:08:16 +0200 |
commit | 0dedbd2040a10098c6079443e21d1949ff384c14 (patch) | |
tree | ccf983af7c5eaa5a252d878800d519c21a5e5186 | |
parent | 079525b21fa4f55902af86f67a79b5439db1a289 (diff) |
iOS, change bridges to 64bit and reduce
Changed __i386 to not __arm64
iOS either compiles for arm64 (production) or x86_64 (simulator)
add common parts to cpp2uno and uno2cpp
Change-Id: I059f3cc23bb658d6d53dbf2bf4aa6634eeac9662
-rw-r--r-- | bridges/Library_cpp_uno.mk | 2 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios/cpp2uno-arm64.cxx | 560 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios/cpp2uno-i386.cxx | 532 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx | 529 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios/share.hxx | 8 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios/uno2cpp-arm64.cxx | 557 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_ios/uno2cpp.cxx | 527 |
7 files changed, 1055 insertions, 1660 deletions
diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk index 993342baea58..7c85b051f27d 100644 --- a/bridges/Library_cpp_uno.mk +++ b/bridges/Library_cpp_uno.mk @@ -11,7 +11,7 @@ $(eval $(call gb_Library_Library,$(gb_CPPU_ENV)_uno)) ifeq ($(OS),IOS) bridges_SELECTED_BRIDGE := gcc3_ios -bridge_noopt_objects := cpp2uno cpp2uno-arm64 cpp2uno-i386 except uno2cpp uno2cpp-arm64 uno2cpp-i386 +bridge_noopt_objects := cpp2uno except uno2cpp uno2cpp-i386 else ifeq ($(CPUNAME),ARM) diff --git a/bridges/source/cpp_uno/gcc3_ios/cpp2uno-arm64.cxx b/bridges/source/cpp_uno/gcc3_ios/cpp2uno-arm64.cxx deleted file mode 100644 index 64ac9ed38b2b..000000000000 --- a/bridges/source/cpp_uno/gcc3_ios/cpp2uno-arm64.cxx +++ /dev/null @@ -1,560 +0,0 @@ -/* -*- 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 . - */ - -#ifdef __arm64 - -// For iOS devices (64-bit ARM). Originally a copy of -// ../gcc3_linux_arm/cpp2uno.cxx. - -// No attempts at factoring out the large amounts of more or less -// common code in this, cpp2uno-arm.cxx and cpp2uno-i386.cxx have been -// done. Which is sad. But then the whole bridges/source/cpp_uno is -// full of copy/paste. So I continue in that tradition... - -#include <com/sun/star/uno/RuntimeException.hpp> -#include <sal/log.hxx> -#include <uno/data.h> -#include <typelib/typedescription.hxx> - -#include "bridge.hxx" -#include "cppinterfaceproxy.hxx" -#include "types.hxx" -#include "vtablefactory.hxx" - -#include "share.hxx" - -extern "C" { - extern int nFunIndexes, nVtableOffsets; - extern int codeSnippets[]; -} - -using namespace ::com::sun::star::uno; - -namespace -{ - static typelib_TypeClass cpp2uno_call( - bridges::cpp_uno::shared::CppInterfaceProxy* pThis, - const typelib_TypeDescription * pMemberTypeDescr, - typelib_TypeDescriptionReference * pReturnTypeRef, - sal_Int32 nParams, - typelib_MethodParameter * pParams, - void ** pCallStack, - sal_Int64 * pRegisterReturn /* space for register return */ ) - { - // pCallStack: x8, lr, d0..d7, x0..x7, rest of params originally on stack - char *pTopStack = (char *)pCallStack; - char *pFloatRegs = pTopStack + 2; - char *pGPRegs = pTopStack + (2+8)*8; - char *pStackedArgs = pTopStack + (2+8+8)*8; - - int nGPR = 0; - int nFPR = 0; - - // return - typelib_TypeDescription * pReturnTypeDescr = 0; - if (pReturnTypeRef) - TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); - - void * pUnoReturn = 0; - // complex return ptr: if != 0 && != pUnoReturn, reconversion need - void * pCppReturn = 0; - - if (pReturnTypeDescr) - { - if (!arm::return_in_x8(pReturnTypeRef)) - pUnoReturn = pRegisterReturn; // direct way for simple types - else // complex return via x8 - { - pCppReturn = pCallStack[0]; - - pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( - pReturnTypeDescr ) - ? alloca( pReturnTypeDescr->nSize ) - : pCppReturn); // direct way - } - } - - // Skip 'this' - pGPRegs += 8; - nGPR++; - - // Parameters - void ** pUnoArgs = (void **)alloca( sizeof(void *) * nParams ); - void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams ); - - // Indices of values this have to be converted (interface conversion - // cpp<=>uno) - int * pTempIndices = (sal_Int32 *)alloca( sizeof(int) * nParams); - - // Type descriptions for reconversions - typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(typelib_TypeDescription *) * nParams); - - int nTempIndices = 0; - - for ( int 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 )) - { - if (nFPR < 8 && (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT || - pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE)) - { - pCppArgs[nPos] = pUnoArgs[nPos] = pFloatRegs; - pFloatRegs += 8; - nFPR++; - } - else if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT) - { - if ((pStackedArgs - pTopStack) % 4) - pStackedArgs += 4 - ((pStackedArgs - pTopStack) % 4); - pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; - pStackedArgs += 4; - } - else if (pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE) - { - if ((pStackedArgs - pTopStack) % 8) - pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8); - pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; - pStackedArgs += 8; - } - else if (nGPR < 8) - { - pCppArgs[nPos] = pUnoArgs[nPos] = pGPRegs; - pGPRegs += 8; - nGPR++; - } - else - switch (pParamTypeDescr->eTypeClass) - { - case typelib_TypeClass_HYPER: - case typelib_TypeClass_UNSIGNED_HYPER: - if ((pStackedArgs - pTopStack) % 8) - pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8); - pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; - pStackedArgs += 8; - break; - case typelib_TypeClass_ENUM: - case typelib_TypeClass_LONG: - case typelib_TypeClass_UNSIGNED_LONG: - if ((pStackedArgs - pTopStack) % 4) - pStackedArgs += 4 - ((pStackedArgs - pTopStack) % 4); - pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; - pStackedArgs += 4; - break; - case typelib_TypeClass_CHAR: - case typelib_TypeClass_SHORT: - case typelib_TypeClass_UNSIGNED_SHORT: - if ((pStackedArgs - pTopStack) % 2) - pStackedArgs += 1; - pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; - pStackedArgs += 2; - break; - case typelib_TypeClass_BOOLEAN: - case typelib_TypeClass_BYTE: - pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; - pStackedArgs += 1; - break; - default: - assert(!"should not happen"); - break; - } - // no longer needed - TYPELIB_DANGER_RELEASE( pParamTypeDescr ); - } - else // ptr to complex value | ref - { - if (nGPR < 8) - { - pCppArgs[nPos] = *(void **)pGPRegs; - pGPRegs += 8; - } - else - { - if ((pStackedArgs - pTopStack) % 8) - pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8); - pCppArgs[nPos] = pStackedArgs; - pStackedArgs += 8; - } - - 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 ), - pCppArgs[nPos], pParamTypeDescr, - pThis->getBridge()->getCpp2Uno() ); - pTempIndices[nTempIndices] = nPos; // has to be reconverted - // will be released at reconversion - ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr; - } - else // direct way - { - pUnoArgs[nPos] = pCppArgs[nPos]; - // no longer needed - TYPELIB_DANGER_RELEASE( pParamTypeDescr ); - } - } - } - - // 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--; ) - { - int 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--; ) - { - int 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 ); - } - *(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 ) - { - // pCallStack: x8, lr, d0..d7, x0..x7, rest of params originally on stack - // _this_ ptr is patched cppu_XInterfaceProxy object - void *pThis = pCallStack[2 + 8]; - - pThis = static_cast< char * >(pThis) - nVtableOffset; - bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = - bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( - pThis); - - typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); - - // determine called method - assert( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex ); - - if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) - { - throw RuntimeException( "illegal vtable index!", (XInterface *)pCppI ); - } - - sal_Int32 nMemberPos = - pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; - assert( nMemberPos < pTypeDescr->nAllMembers ); - - TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); - - 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() - SAL_FALLTHROUGH; - 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) - */ - -extern "C" sal_Int64 cpp_vtable_call( sal_Int32 *pFunctionAndOffset, - void **pCallStack ) -{ - sal_Int64 nRegReturn; - typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, &nRegReturn ); - - switch( aType ) - { - case typelib_TypeClass_BOOLEAN: - case typelib_TypeClass_BYTE: - nRegReturn = (unsigned long)(*(unsigned char *)&nRegReturn); - break; - case typelib_TypeClass_CHAR: - case typelib_TypeClass_UNSIGNED_SHORT: - case typelib_TypeClass_SHORT: - nRegReturn = (unsigned long)(*(unsigned short *)&nRegReturn); - break; - case typelib_TypeClass_ENUM: - case typelib_TypeClass_UNSIGNED_LONG: - case typelib_TypeClass_LONG: - nRegReturn = (unsigned long)(*(unsigned int *)&nRegReturn); - break; - case typelib_TypeClass_VOID: - default: - break; - } - - return nRegReturn; -} - -namespace -{ - unsigned char *codeSnippet(const typelib_InterfaceTypeDescription *type, - const typelib_TypeDescription *member, - sal_Int32 functionIndex, - sal_Int32 vtableOffset) - { - assert(functionIndex < nFunIndexes); - if (!(functionIndex < nFunIndexes)) - return NULL; - - assert(vtableOffset < nVtableOffsets); - if (!(vtableOffset < nVtableOffsets)) - return NULL; - - // The codeSnippets table is indexed by functionIndex and vtableOffset - - int index = functionIndex*nVtableOffsets + vtableOffset; - unsigned char *result = ((unsigned char *) &codeSnippets) + codeSnippets[index]; - - SAL_INFO( "bridges.ios", "codeSnippet(" << OUString(type->aBase.pTypeName) << "::" << OUString(member->pTypeName) << "): [" << functionIndex << "," << vtableOffset << "]=" << (void *) result << " (" << std::hex << ((int*)result)[0] << "," << ((int*)result)[1] << "," << ((int*)result)[2] << "," << ((int*)result)[3] << ")"); - - return result; - } -} - -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; -} - -std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize( - sal_Int32 slotCount) -{ - return (slotCount + 2) * sizeof (Slot); -} - -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; - slots[-1].fn = 0; - return slots + slotCount; -} - -unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( - Slot ** slots, - unsigned char * code, - 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: - { - typelib_InterfaceAttributeTypeDescription *pAttrTD = - reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member ); - - // Getter: - (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset ); - - // Setter: - if (!pAttrTD->bReadOnly) - { - (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset ); - } - break; - } - case typelib_TypeClass_INTERFACE_METHOD: - { - (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset ); - break; - } - default: - assert(false); - break; - } - TYPELIB_DANGER_RELEASE(member); - } - return code; -} - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_ios/cpp2uno-i386.cxx b/bridges/source/cpp_uno/gcc3_ios/cpp2uno-i386.cxx deleted file mode 100644 index 6a3689ca6c33..000000000000 --- a/bridges/source/cpp_uno/gcc3_ios/cpp2uno-i386.cxx +++ /dev/null @@ -1,532 +0,0 @@ -/* -*- 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 . - */ - -#ifdef __i386 - -// For the iOS emulator (i386). Basically a copy of -// ../gcc3_macosx_intel/cpp2uno.cxx with some cleanups and necessary -// changes: To match what we do on iOS devices, we don't do any -// dynamic code generation on the emulator either (even if it as such -// wouldn't be prohibited). - -// No attempts at factoring out the large amounts of more or less -// common code in this and cpp2uno-arm.cxx have been done. Which is -// sad. But then the whole bridges/source/cpp_uno is full of -// copy/paste. So I continue in that tradition... - -#include <com/sun/star/uno/RuntimeException.hpp> -#include <sal/log.hxx> -#include <uno/data.h> -#include <typelib/typedescription.hxx> - -#include "bridge.hxx" -#include "cppinterfaceproxy.hxx" -#include "types.hxx" -#include "vtablefactory.hxx" - -#include "share.hxx" - -extern "C" { - extern int nFunIndexes, nVtableOffsets; - extern int codeSnippets[]; -} - -using namespace ::com::sun::star::uno; - -namespace -{ - -void 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, - void * pReturnValue ) -{ - // pCallStack: ret, [return ptr], this, params - char * pCppStack = (char *)(pCallStack +1); - - // 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 - - if (pReturnTypeDescr) - { - // xxx todo: test PolyStructy<STRUCT<long>> foo() - if (CPPU_CURRENT_NAMESPACE::isSimpleReturnType( pReturnTypeDescr )) - { - pUnoReturn = pReturnValue; // direct way for simple types - } - else // complex return via ptr (pCppReturn) - { - pCppReturn = *(void **)pCppStack; - pCppStack += sizeof(void *); - pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( - pReturnTypeDescr ) - ? alloca( pReturnTypeDescr->nSize ) - : pCppReturn); // direct way - } - } - // pop this - pCppStack += sizeof( void* ); - - // stack space - static_assert(sizeof(void *) == sizeof(sal_Int32), "### 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] = pCppStack; - pUnoArgs[nPos] = pCppStack; - switch (pParamTypeDescr->eTypeClass) - { - case typelib_TypeClass_HYPER: - case typelib_TypeClass_UNSIGNED_HYPER: - case typelib_TypeClass_DOUBLE: - pCppStack += sizeof(sal_Int32); // extra long - SAL_FALLTHROUGH; - 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_Int32); // 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 - } - 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 ); - } - if (pReturnValue != pCppReturn) { - // complex return ptr is set to eax if return value - // is not transferred via eax[/edx]: - *static_cast< void ** >(pReturnValue) = pCppReturn; - } - } - if (pReturnTypeDescr) - { - TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); - } - } -} - - -extern "C" void cpp_vtable_call( - int nFunctionIndex, int nVtableOffset, void** pCallStack, - void * pReturnValue ) -{ - static_assert(sizeof(sal_Int32)==sizeof(void *), "### unexpected!"); - - // pCallStack: ret adr, [ret *], this, params - void * pThis; - if( nFunctionIndex & 0x80000000 ) - { - nFunctionIndex &= 0x7fffffff; - pThis = pCallStack[2]; - } - else - { - pThis = pCallStack[1]; - } - pThis = static_cast< char * >(pThis) - nVtableOffset; - bridges::cpp_uno::shared::CppInterfaceProxy * pCppI - = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( - pThis); - - typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); - - SAL_INFO( "bridges.ios", "cpp_vtable_call: pCallStack=[" << - std::hex << pCallStack[0] << "," << pCallStack[1] << "," << pCallStack[2] << ",...]" << - ", pThis=" << pThis << ", pCppI=" << pCppI << - std::dec << ", nFunctionIndex=" << nFunctionIndex << ", nVtableOffset=" << nVtableOffset ); - - SAL_INFO( "bridges.ios", "name=" << OUString::unacquired(&pTypeDescr->aBase.pTypeName) ); - - assert( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex ); - - if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) - { - throw RuntimeException( "illegal vtable index!", (XInterface *)pThis ); - } - - // determine called method - sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; - - assert( nMemberPos < pTypeDescr->nAllMembers ); - - TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); - - SAL_INFO( "bridges.ios", "Calling " << OUString::unacquired(&aMemberDescr.get()->pTypeName) ); - - switch (aMemberDescr.get()->eTypeClass) - { - case typelib_TypeClass_INTERFACE_ATTRIBUTE: - { - if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) - { - // is GET method - cpp2uno_call( - pCppI, aMemberDescr.get(), - ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, - 0, 0, // no params - pCallStack, pReturnValue ); - } - else - { - // is SET method - typelib_MethodParameter aParam; - aParam.pTypeRef = - ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; - aParam.bIn = sal_True; - aParam.bOut = sal_False; - - cpp2uno_call( - pCppI, aMemberDescr.get(), - 0, // indicates void return - 1, &aParam, - pCallStack, pReturnValue ); - } - break; - } - case typelib_TypeClass_INTERFACE_METHOD: - { - // is METHOD - switch (nFunctionIndex) - { - case 1: // acquire() - pCppI->acquireProxy(); // non virtual call! - break; - case 2: // release() - pCppI->releaseProxy(); // non virtual call! - break; - case 0: // queryInterface() opt - { - typelib_TypeDescription * pTD = 0; - TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->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[1] ), - &pInterface, pTD, cpp_acquire ); - pInterface->release(); - TYPELIB_DANGER_RELEASE( pTD ); - *static_cast< void ** >(pReturnValue) = pCallStack[1]; - break; - } - TYPELIB_DANGER_RELEASE( pTD ); - } - } // else perform queryInterface() - SAL_FALLTHROUGH; - default: - cpp2uno_call( - pCppI, aMemberDescr.get(), - ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, - ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, - ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, - pCallStack, pReturnValue ); - } - break; - } - default: - { - throw RuntimeException( "no member description found!", (XInterface *)pThis ); - } - } -} - -typedef enum { privateSnippetExecutorGeneral, privateSnippetExecutorVoid, privateSnippetExecutorHyper, privateSnippetExecutorFloat, privateSnippetExecutorDouble, privateSnippetExecutorClass } snippetExecutorKind; - -static const char * snippetExecutorClassName( - snippetExecutorKind exec) -{ - switch (exec) { - case privateSnippetExecutorGeneral: return "General"; - case privateSnippetExecutorVoid: return "Void"; - case privateSnippetExecutorHyper: return "Hyper"; - case privateSnippetExecutorFloat: return "Float"; - case privateSnippetExecutorDouble: return "Double"; - case privateSnippetExecutorClass: return "Class"; - default: - abort(); - } -} - -unsigned char * codeSnippet( - sal_Int32 functionIndex, sal_Int32 vtableOffset, - typelib_TypeDescriptionReference * pReturnTypeRef) -{ - assert(functionIndex < nFunIndexes); - if (!(functionIndex < nFunIndexes)) - return NULL; - - assert(vtableOffset < nVtableOffsets); - if (!(vtableOffset < nVtableOffsets)) - return NULL; - - snippetExecutorKind exec; - bool bHasHiddenParam = false; - if (pReturnTypeRef == 0) { - exec = privateSnippetExecutorVoid; - } - else { - switch (pReturnTypeRef->eTypeClass) { - case typelib_TypeClass_VOID: - exec = privateSnippetExecutorVoid; - break; - case typelib_TypeClass_HYPER: - case typelib_TypeClass_UNSIGNED_HYPER: - exec = privateSnippetExecutorHyper; - break; - case typelib_TypeClass_FLOAT: - exec = privateSnippetExecutorFloat; - break; - case typelib_TypeClass_DOUBLE: - exec = privateSnippetExecutorDouble; - break; - case typelib_TypeClass_STRUCT: - case typelib_TypeClass_EXCEPTION: { - typelib_TypeDescription * pReturnTypeDescr = 0; - TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); - bool const bSimpleReturnStruct = - CPPU_CURRENT_NAMESPACE::isSimpleReturnType(pReturnTypeDescr); - sal_Int32 const nRetSize = pReturnTypeDescr->nSize; - TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); - if (bSimpleReturnStruct && nRetSize <= 8) { - exec = privateSnippetExecutorGeneral; // fills eax - if (nRetSize > 4) - exec = privateSnippetExecutorHyper; // fills eax/edx - break; - } - } - SAL_FALLTHROUGH; - case typelib_TypeClass_STRING: - case typelib_TypeClass_TYPE: - case typelib_TypeClass_SEQUENCE: - case typelib_TypeClass_INTERFACE: - case typelib_TypeClass_ANY: - bHasHiddenParam = 1; - exec = privateSnippetExecutorClass; - break; - default: - exec = privateSnippetExecutorGeneral; - break; - } - } - - // The codeSnippets table is indexed by functionIndex, - // vtableOffset, exec and the has-hidden-param flag - - int index = functionIndex*nVtableOffsets*6*2 + vtableOffset*6*2 + exec*2 + bHasHiddenParam; - unsigned char *result = ((unsigned char *) &codeSnippets) + codeSnippets[index]; - - SAL_INFO( "bridges.ios", "codeSnippet: [" << - functionIndex << "," << vtableOffset << "," << snippetExecutorClassName(exec) << "," << bHasHiddenParam << "]=" << - (void *) result); - - return result; -} - -} - -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; -} - -std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize( - sal_Int32 slotCount) -{ - return (slotCount + 2) * sizeof (Slot); -} - -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; - slots[-1].fn = 0; - return slots + slotCount; -} - -unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( - Slot ** slots, unsigned char * code, - 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 = codeSnippet( - functionOffset++, vtableOffset, - reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( - member)->pAttributeTypeRef); - // Setter: - if (!reinterpret_cast< - typelib_InterfaceAttributeTypeDescription * >( - member)->bReadOnly) - { - (s++)->fn = codeSnippet( - functionOffset++, vtableOffset, - 0 /* indicates VOID */); - } - break; - - case typelib_TypeClass_INTERFACE_METHOD: - (s++)->fn = codeSnippet( - functionOffset++, vtableOffset, - reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( - member)->pReturnTypeRef); - break; - - default: - assert(false); - break; - } - TYPELIB_DANGER_RELEASE(member); - } - return code; -} - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx index 46726a8b30ba..6773486e9c9c 100644 --- a/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx +++ b/bridges/source/cpp_uno/gcc3_ios/cpp2uno.cxx @@ -17,11 +17,536 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -// If we eventually get around to factoring out stuff from -// cpp2uno-arm.cxx and cpp2uno-i386.cxx here, this is where to put it. +#include <com/sun/star/uno/RuntimeException.hpp> +#include <sal/log.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> +#include "bridge.hxx" +#include "cppinterfaceproxy.hxx" +#include "types.hxx" #include "vtablefactory.hxx" +#include "share.hxx" + +extern "C" { + extern int nFunIndexes, nVtableOffsets; + extern int codeSnippets[]; +} + +using namespace ::com::sun::star::uno; + +namespace +{ + static typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy* pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, + typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) + { + // pCallStack: x8, lr, d0..d7, x0..x7, rest of params originally on stack + char *pTopStack = (char *)pCallStack; + char *pFloatRegs = pTopStack + 2; + char *pGPRegs = pTopStack + (2+8)*8; + char *pStackedArgs = pTopStack + (2+8+8)*8; + + int nGPR = 0; + int nFPR = 0; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + // complex return ptr: if != 0 && != pUnoReturn, reconversion need + void * pCppReturn = 0; + + if (pReturnTypeDescr) + { + if (!arm::return_in_x8(pReturnTypeRef)) + pUnoReturn = pRegisterReturn; // direct way for simple types + else // complex return via x8 + { + pCppReturn = pCallStack[0]; + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + + // Skip 'this' + pGPRegs += 8; + nGPR++; + + // Parameters + void ** pUnoArgs = (void **)alloca( sizeof(void *) * nParams ); + void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams ); + + // Indices of values this have to be converted (interface conversion + // cpp<=>uno) + int * pTempIndices = (sal_Int32 *)alloca( sizeof(int) * nParams); + + // Type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(typelib_TypeDescription *) * nParams); + + int nTempIndices = 0; + + for ( int 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 )) + { + if (nFPR < 8 && (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT || + pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE)) + { + pCppArgs[nPos] = pUnoArgs[nPos] = pFloatRegs; + pFloatRegs += 8; + nFPR++; + } + else if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT) + { + if ((pStackedArgs - pTopStack) % 4) + pStackedArgs += 4 - ((pStackedArgs - pTopStack) % 4); + pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; + pStackedArgs += 4; + } + else if (pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE) + { + if ((pStackedArgs - pTopStack) % 8) + pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8); + pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; + pStackedArgs += 8; + } + else if (nGPR < 8) + { + pCppArgs[nPos] = pUnoArgs[nPos] = pGPRegs; + pGPRegs += 8; + nGPR++; + } + else + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + if ((pStackedArgs - pTopStack) % 8) + pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8); + pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; + pStackedArgs += 8; + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + if ((pStackedArgs - pTopStack) % 4) + pStackedArgs += 4 - ((pStackedArgs - pTopStack) % 4); + pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; + pStackedArgs += 4; + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + if ((pStackedArgs - pTopStack) % 2) + pStackedArgs += 1; + pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; + pStackedArgs += 2; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + pCppArgs[nPos] = pUnoArgs[nPos] = pStackedArgs; + pStackedArgs += 1; + break; + default: + assert(!"should not happen"); + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (nGPR < 8) + { + pCppArgs[nPos] = *(void **)pGPRegs; + pGPRegs += 8; + } + else + { + if ((pStackedArgs - pTopStack) % 8) + pStackedArgs += 8 - ((pStackedArgs - pTopStack) % 8); + pCppArgs[nPos] = pStackedArgs; + pStackedArgs += 8; + } + + 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 ), + pCppArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndices[nTempIndices] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = pCppArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + + // 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--; ) + { + int 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--; ) + { + int 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 ); + } + *(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 ) + { + // pCallStack: x8, lr, d0..d7, x0..x7, rest of params originally on stack + // _this_ ptr is patched cppu_XInterfaceProxy object + void *pThis = pCallStack[2 + 8]; + + pThis = static_cast< char * >(pThis) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI = + bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + + // determine called method + assert( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex ); + + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( "illegal vtable index!", (XInterface *)pCppI ); + } + + sal_Int32 nMemberPos = + pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + assert( nMemberPos < pTypeDescr->nAllMembers ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + 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() + SAL_FALLTHROUGH; + 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) + */ + +extern "C" sal_Int64 cpp_vtable_call( sal_Int32 *pFunctionAndOffset, + void **pCallStack ) +{ + sal_Int64 nRegReturn; + typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack, &nRegReturn ); + + switch( aType ) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + nRegReturn = (unsigned long)(*(unsigned char *)&nRegReturn); + break; + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_SHORT: + nRegReturn = (unsigned long)(*(unsigned short *)&nRegReturn); + break; + case typelib_TypeClass_ENUM: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_LONG: + nRegReturn = (unsigned long)(*(unsigned int *)&nRegReturn); + break; + case typelib_TypeClass_VOID: + default: + break; + } + + return nRegReturn; +} + +#ifdef __arm64 +namespace +{ + unsigned char *codeSnippet(const typelib_InterfaceTypeDescription *type, + const typelib_TypeDescription *member, + sal_Int32 functionIndex, + sal_Int32 vtableOffset) + { + assert(functionIndex < nFunIndexes); + if (!(functionIndex < nFunIndexes)) + return NULL; + + assert(vtableOffset < nVtableOffsets); + if (!(vtableOffset < nVtableOffsets)) + return NULL; + + // The codeSnippets table is indexed by functionIndex and vtableOffset + + int index = functionIndex*nVtableOffsets + vtableOffset; + unsigned char *result = ((unsigned char *) &codeSnippets) + codeSnippets[index]; + + SAL_INFO( "bridges.ios", "codeSnippet(" << OUString(type->aBase.pTypeName) << "::" << OUString(member->pTypeName) << "): [" << functionIndex << "," << vtableOffset << "]=" << (void *) result << " (" << std::hex << ((int*)result)[0] << "," << ((int*)result)[1] << "," << ((int*)result)[2] << "," << ((int*)result)[3] << ")"); + + return result; + } +} + +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; +} + +std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 2) * sizeof (Slot); +} + +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; + slots[-1].fn = 0; + return slots + slotCount; +} + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, + unsigned char * code, + 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: + { + typelib_InterfaceAttributeTypeDescription *pAttrTD = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member ); + + // Getter: + (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset ); + + // Setter: + if (!pAttrTD->bReadOnly) + { + (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + (s++)->fn = codeSnippet( type, member, functionOffset++, vtableOffset ); + break; + } + default: + assert(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} +#endif + + void bridges::cpp_uno::shared::VtableFactory::flushCode( unsigned char const *, unsigned char const *) { diff --git a/bridges/source/cpp_uno/gcc3_ios/share.hxx b/bridges/source/cpp_uno/gcc3_ios/share.hxx index 589f4ba7a174..bcddcdb1f807 100644 --- a/bridges/source/cpp_uno/gcc3_ios/share.hxx +++ b/bridges/source/cpp_uno/gcc3_ios/share.hxx @@ -49,19 +49,11 @@ namespace CPPU_CURRENT_NAMESPACE namespace arm { -#if defined(__arm) - enum armlimits { - MAX_GPR_REGS = 4, - MAX_FPR_REGS = 8 - }; - bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); -#elif defined(__arm64) enum armlimits { MAX_GPR_REGS = 8, MAX_FPR_REGS = 8 }; bool return_in_x8( typelib_TypeDescriptionReference *pTypeRef ); -#endif } #endif diff --git a/bridges/source/cpp_uno/gcc3_ios/uno2cpp-arm64.cxx b/bridges/source/cpp_uno/gcc3_ios/uno2cpp-arm64.cxx deleted file mode 100644 index 7915fa7a9513..000000000000 --- a/bridges/source/cpp_uno/gcc3_ios/uno2cpp-arm64.cxx +++ /dev/null @@ -1,557 +0,0 @@ -/* -*- 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 . - */ - -#ifdef __arm64 - -#include <com/sun/star/uno/RuntimeException.hpp> - -#include "bridge.hxx" -#include "types.hxx" -#include "unointerfaceproxy.hxx" -#include "vtables.hxx" - -#include "share.hxx" - -using namespace ::com::sun::star::uno; - -namespace arm -{ - bool is_hfa_struct(const typelib_TypeDescription * type) - { - const typelib_CompoundTypeDescription * p - = reinterpret_cast< const typelib_CompoundTypeDescription * >(type); - if (p->nMembers >= 4) - return false; - for (sal_Int32 i = 0; i < p->nMembers; ++i) - { - if ((p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT && - p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE) || - p->ppTypeRefs[i]->eTypeClass != p->ppTypeRefs[0]->eTypeClass) - return false; - } - return true; - } - - bool return_in_x8( 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 16 bytes is returned in x0, x1 - bool bRet = pTypeDescr->nSize > 16; - - if (is_hfa_struct(pTypeDescr)) - bRet = false; - - TYPELIB_DANGER_RELEASE( pTypeDescr ); - return bRet; - } - return true; - } -} - -void MapReturn(sal_uInt64 x0, sal_uInt64 x1, typelib_TypeDescriptionReference *pReturnType, sal_uInt64 *pRegisterReturn) -{ - switch( pReturnType->eTypeClass ) - { - case typelib_TypeClass_HYPER: - case typelib_TypeClass_UNSIGNED_HYPER: - pRegisterReturn[1] = x1; - SAL_FALLTHROUGH; - case typelib_TypeClass_LONG: - case typelib_TypeClass_UNSIGNED_LONG: - case typelib_TypeClass_ENUM: - case typelib_TypeClass_CHAR: - case typelib_TypeClass_SHORT: - case typelib_TypeClass_UNSIGNED_SHORT: - case typelib_TypeClass_BOOLEAN: - case typelib_TypeClass_BYTE: - pRegisterReturn[0] = x0; - break; - case typelib_TypeClass_FLOAT: - register float fret asm("s0"); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" - *(float*)pRegisterReturn = fret; -#pragma GCC diagnostic pop - break; - case typelib_TypeClass_DOUBLE: - register double dret asm("d0"); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" - *(double*)pRegisterReturn = dret; -#pragma GCC diagnostic pop - break; - case typelib_TypeClass_STRUCT: - case typelib_TypeClass_EXCEPTION: - if (!arm::return_in_x8(pReturnType)) - { - pRegisterReturn[0] = x0; - pRegisterReturn[1] = x1; - } - break; - default: - break; - } -} - -namespace -{ -void callVirtualMethod( - void *pThis, - sal_Int32 nVtableIndex, - void *pRegisterReturn, - typelib_TypeDescriptionReference *pReturnType, - sal_uInt64 *pStack, - int nStack, - sal_uInt64 *pGPR, - double *pFPR) -{ - // never called - if (! pThis) - CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something - - if ( nStack ) - { - // 16-bytes aligned - sal_uInt32 nStackBytes = ( ( nStack + 3 ) >> 2 ) * 16; - sal_uInt32 *stack = (sal_uInt32 *) alloca( nStackBytes ); - memcpy( stack, pStack, nStackBytes ); - } - - sal_uInt64 pMethod = *((sal_uInt64*)pThis); - pMethod += 8 * nVtableIndex; - pMethod = *((sal_uInt64 *)pMethod); - - // For value returned in registers - sal_uInt64 x0; - sal_uInt64 x1; - - __asm__ __volatile__ - ( - " ldp x0, x1, %[pgpr_0]\n" - " ldp x2, x3, %[pgpr_2]\n" - " ldp x4, x5, %[pgpr_4]\n" - " ldp x6, x7, %[pgpr_6]\n" - " ldr x8, %[pregisterreturn]\n" - " ldp d0, d1, %[pfpr_0]\n" - " ldp d2, d3, %[pfpr_2]\n" - " ldp d4, d5, %[pfpr_4]\n" - " ldp d6, d7, %[pfpr_6]\n" - " blr %[pmethod]\n" - " str x0, %[x0]\n" - " str x1, %[x1]\n" - : [x0]"=m" (x0), [x1]"=m" (x1) - : [pgpr_0]"m" (pGPR[0]), - [pgpr_2]"m" (pGPR[2]), - [pgpr_4]"m" (pGPR[4]), - [pgpr_6]"m" (pGPR[6]), - [pregisterreturn]"m" (pRegisterReturn), - [pfpr_0]"m" (pFPR[0]), - [pfpr_2]"m" (pFPR[2]), - [pfpr_4]"m" (pFPR[4]), - [pfpr_6]"m" (pFPR[6]), - [pmethod]"r" (pMethod) - : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7" - ); - - MapReturn(x0, x1, pReturnType, (sal_uInt64 *) pRegisterReturn); -} -} - -#define INSERT_INT64( pSV, nr, pGPR, pDS ) \ - if ( nr < arm::MAX_GPR_REGS ) \ - pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ - else \ - *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); - -#define INSERT_INT32( pSV, nr, pGPR, pDS ) \ - if ( nr < arm::MAX_GPR_REGS ) \ - pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ - else \ - *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); - -#define INSERT_INT16( pSV, nr, pGPR, pDS ) \ - if ( nr < arm::MAX_GPR_REGS ) \ - pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ - else \ - *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); - -#define INSERT_INT8( pSV, nr, pGPR, pDS ) \ - if ( nr < arm::MAX_GPR_REGS ) \ - pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ - else \ - *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); - -#define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \ - if ( nr < arm::MAX_FPR_REGS ) \ - pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \ - else \ - *pDS++ = *reinterpret_cast<double *>( pSV ); - -#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \ - INSERT_DOUBLE( pSV, nr, pGPR, pDS ) - -namespace { -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: values|ptr ... - sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+2) * sizeof(sal_Int64) ); - sal_uInt64 * pStackStart = pStack; - - sal_uInt64 pGPR[arm::MAX_GPR_REGS]; - int nGPR = 0; - - // storage and counter for SIMD/FP registers - double pFPR[arm::MAX_FPR_REGS]; - int nFPR = 0; - - // return - typelib_TypeDescription * pReturnTypeDescr = 0; - TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); - assert( pReturnTypeDescr); - - void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion - - if (pReturnTypeDescr) - { - if (!arm::return_in_x8( pReturnTypeRef ) ) - pCppReturn = pUnoReturn; // direct way for simple types - else - { - // complex return via x8 - pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) - ? alloca( pReturnTypeDescr->nSize ) - : pUnoReturn); // direct way - } - } - // push this - void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) - + aVtableSlot.offset; - INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack ); - - // stack space - // args - void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams ); - - // indices of values this have to be converted (interface conversion cpp<=>uno) - int * pTempIndices = (int *)alloca( sizeof(int) * nParams ); - - // type descriptions for reconversions - typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(void *) * 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_HYPER: - case typelib_TypeClass_UNSIGNED_HYPER: - INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack ); - break; - case typelib_TypeClass_LONG: - case typelib_TypeClass_UNSIGNED_LONG: - case typelib_TypeClass_ENUM: - INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack ); - break; - case typelib_TypeClass_SHORT: - case typelib_TypeClass_CHAR: - case typelib_TypeClass_UNSIGNED_SHORT: - INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack ); - break; - case typelib_TypeClass_BOOLEAN: - case typelib_TypeClass_BYTE: - 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_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack ); - 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( - 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( - 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 - { - pCppArgs[nPos] = pUnoArgs[nPos]; - // no longer needed - TYPELIB_DANGER_RELEASE( pParamTypeDescr ); - } - INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack ); - } - } - - assert( nGPR <= arm::MAX_GPR_REGS ); - assert( nFPR <= arm::MAX_FPR_REGS ); - - try - { - callVirtualMethod( - pAdjustedThisPtr, aVtableSlot.index, - pCppReturn, pReturnTypeRef, - pStackStart, - (pStack - pStackStart), - pGPR, - pFPR); - - // 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 (...) - { - // fill uno exception - CPPU_CURRENT_NAMESPACE::fillUnoException( abi::__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 ) -{ - // is my surrogate - bridges::cpp_uno::shared::UnoInterfaceProxy * pThis - = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); -#if OSL_DEBUG_LEVEL > 0 - typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; -#endif - - switch (pMemberDescr->eTypeClass) - { - case typelib_TypeClass_INTERFACE_ATTRIBUTE: - { -#if OSL_DEBUG_LEVEL > 0 - // determine vtable call index - sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; - assert( nMemberPos < pTypeDescr->nAllMembers && "### member pos out of range!"); -#endif - - 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; - cpp_call( - pThis, aVtableSlot, // get, then set method - pReturnTypeRef, - 1, &aParam, - pReturn, pArgs, ppException ); - - typelib_typedescriptionreference_release( pReturnTypeRef ); - } - - break; - } - case typelib_TypeClass_INTERFACE_METHOD: - { -#if OSL_DEBUG_LEVEL > 0 - // determine vtable call index - sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; - assert(nMemberPos < pTypeDescr->nAllMembers && "### member pos out of range!"); -#endif - - 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->getBridge()->getUnoEnv()->getRegisteredInterface)( - pThis->getBridge()->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() - SAL_FALLTHROUGH; - 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( - "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 ); - } - } -} - -} } } - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/gcc3_ios/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_ios/uno2cpp.cxx index 17bd59583737..6d2c82fbe0d4 100644 --- a/bridges/source/cpp_uno/gcc3_ios/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_ios/uno2cpp.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <com/sun/star/uno/RuntimeException.hpp> + #include "bridge.hxx" #include "types.hxx" #include "unointerfaceproxy.hxx" @@ -26,4 +28,529 @@ using namespace ::com::sun::star::uno; +#ifdef __arm64 +namespace arm +{ + bool is_hfa_struct(const typelib_TypeDescription * type) + { + const typelib_CompoundTypeDescription * p + = reinterpret_cast< const typelib_CompoundTypeDescription * >(type); + if (p->nMembers >= 4) + return false; + for (sal_Int32 i = 0; i < p->nMembers; ++i) + { + if ((p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT && + p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE) || + p->ppTypeRefs[i]->eTypeClass != p->ppTypeRefs[0]->eTypeClass) + return false; + } + return true; + } + + bool return_in_x8( 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 16 bytes is returned in x0, x1 + bool bRet = pTypeDescr->nSize > 16; + + if (is_hfa_struct(pTypeDescr)) + bRet = false; + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + return bRet; + } + return true; + } +} + +void MapReturn(sal_uInt64 x0, sal_uInt64 x1, typelib_TypeDescriptionReference *pReturnType, sal_uInt64 *pRegisterReturn) +{ + switch( pReturnType->eTypeClass ) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + pRegisterReturn[1] = x1; + SAL_FALLTHROUGH; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + pRegisterReturn[0] = x0; + break; + case typelib_TypeClass_FLOAT: + register float fret asm("s0"); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" + *(float*)pRegisterReturn = fret; +#pragma GCC diagnostic pop + break; + case typelib_TypeClass_DOUBLE: + register double dret asm("d0"); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" + *(double*)pRegisterReturn = dret; +#pragma GCC diagnostic pop + break; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + if (!arm::return_in_x8(pReturnType)) + { + pRegisterReturn[0] = x0; + pRegisterReturn[1] = x1; + } + break; + default: + break; + } +} + +namespace +{ +void callVirtualMethod( + void *pThis, + sal_Int32 nVtableIndex, + void *pRegisterReturn, + typelib_TypeDescriptionReference *pReturnType, + sal_uInt64 *pStack, + int nStack, + sal_uInt64 *pGPR, + double *pFPR) +{ + // never called + if (! pThis) + CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + if ( nStack ) + { + // 16-bytes aligned + sal_uInt32 nStackBytes = ( ( nStack + 3 ) >> 2 ) * 16; + sal_uInt32 *stack = (sal_uInt32 *) alloca( nStackBytes ); + memcpy( stack, pStack, nStackBytes ); + } + + sal_uInt64 pMethod = *((sal_uInt64*)pThis); + pMethod += 8 * nVtableIndex; + pMethod = *((sal_uInt64 *)pMethod); + + // For value returned in registers + sal_uInt64 x0; + sal_uInt64 x1; + + __asm__ __volatile__ + ( + " ldp x0, x1, %[pgpr_0]\n" + " ldp x2, x3, %[pgpr_2]\n" + " ldp x4, x5, %[pgpr_4]\n" + " ldp x6, x7, %[pgpr_6]\n" + " ldr x8, %[pregisterreturn]\n" + " ldp d0, d1, %[pfpr_0]\n" + " ldp d2, d3, %[pfpr_2]\n" + " ldp d4, d5, %[pfpr_4]\n" + " ldp d6, d7, %[pfpr_6]\n" + " blr %[pmethod]\n" + " str x0, %[x0]\n" + " str x1, %[x1]\n" + : [x0]"=m" (x0), [x1]"=m" (x1) + : [pgpr_0]"m" (pGPR[0]), + [pgpr_2]"m" (pGPR[2]), + [pgpr_4]"m" (pGPR[4]), + [pgpr_6]"m" (pGPR[6]), + [pregisterreturn]"m" (pRegisterReturn), + [pfpr_0]"m" (pFPR[0]), + [pfpr_2]"m" (pFPR[2]), + [pfpr_4]"m" (pFPR[4]), + [pfpr_6]"m" (pFPR[6]), + [pmethod]"r" (pMethod) + : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7" + ); + + MapReturn(x0, x1, pReturnType, (sal_uInt64 *) pRegisterReturn); +} +} + +#define INSERT_INT64( pSV, nr, pGPR, pDS ) \ + if ( nr < arm::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); + +#define INSERT_INT32( pSV, nr, pGPR, pDS ) \ + if ( nr < arm::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV ); + +#define INSERT_INT16( pSV, nr, pGPR, pDS ) \ + if ( nr < arm::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV ); + +#define INSERT_INT8( pSV, nr, pGPR, pDS ) \ + if ( nr < arm::MAX_GPR_REGS ) \ + pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV ); + +#define INSERT_DOUBLE( pSV, nr, pFPR, pDS ) \ + if ( nr < arm::MAX_FPR_REGS ) \ + pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \ + else \ + *pDS++ = *reinterpret_cast<double *>( pSV ); + +#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \ + INSERT_DOUBLE( pSV, nr, pGPR, pDS ) + +namespace { +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: values|ptr ... + sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+2) * sizeof(sal_Int64) ); + sal_uInt64 * pStackStart = pStack; + + sal_uInt64 pGPR[arm::MAX_GPR_REGS]; + int nGPR = 0; + + // storage and counter for SIMD/FP registers + double pFPR[arm::MAX_FPR_REGS]; + int nFPR = 0; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + assert( pReturnTypeDescr); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (!arm::return_in_x8( pReturnTypeRef ) ) + pCppReturn = pUnoReturn; // direct way for simple types + else + { + // complex return via x8 + pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + } + } + // push this + void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) + + aVtableSlot.offset; + INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack ); + + // stack space + // args + void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams ); + + // indices of values this have to be converted (interface conversion cpp<=>uno) + int * pTempIndices = (int *)alloca( sizeof(int) * nParams ); + + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(void *) * 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_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_ENUM: + INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_UNSIGNED_SHORT: + INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack ); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + 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_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack ); + 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( + 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( + 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 + { + pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack ); + } + } + + assert( nGPR <= arm::MAX_GPR_REGS ); + assert( nFPR <= arm::MAX_FPR_REGS ); + + try + { + callVirtualMethod( + pAdjustedThisPtr, aVtableSlot.index, + pCppReturn, pReturnTypeRef, + pStackStart, + (pStack - pStackStart), + pGPR, + pFPR); + + // 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 (...) + { + // fill uno exception + CPPU_CURRENT_NAMESPACE::fillUnoException( abi::__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 ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); +#if OSL_DEBUG_LEVEL > 0 + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; +#endif + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + assert( nMemberPos < pTypeDescr->nAllMembers && "### member pos out of range!"); +#endif + + 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; + cpp_call( + pThis, aVtableSlot, // get, then set method + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { +#if OSL_DEBUG_LEVEL > 0 + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + assert(nMemberPos < pTypeDescr->nAllMembers && "### member pos out of range!"); +#endif + + 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->getBridge()->getUnoEnv()->getRegisteredInterface)( + pThis->getBridge()->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() + SAL_FALLTHROUGH; + 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( + "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 ); + } + } +} + +} } } + +#endif + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |