From 12f9d7e02c2469265d9f68934196111dd6c8056e Mon Sep 17 00:00:00 2001 From: Ivo Hinkelmann Date: Thu, 24 Apr 2008 15:25:02 +0000 Subject: INTEGRATION: CWS sb85 (1.1.2); FILE ADDED 2008/03/12 10:50:09 sb 1.1.2.1: #i86117# Solaris SPARC64 bridge --- .../source/cpp_uno/cc5_solaris_sparc64/cpp2uno.cxx | 585 +++++++++++++++++++++ 1 file changed, 585 insertions(+) create mode 100644 bridges/source/cpp_uno/cc5_solaris_sparc64/cpp2uno.cxx (limited to 'bridges') diff --git a/bridges/source/cpp_uno/cc5_solaris_sparc64/cpp2uno.cxx b/bridges/source/cpp_uno/cc5_solaris_sparc64/cpp2uno.cxx new file mode 100644 index 000000000000..000a9171ee84 --- /dev/null +++ b/bridges/source/cpp_uno/cc5_solaris_sparc64/cpp2uno.cxx @@ -0,0 +1,585 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: cpp2uno.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: ihi $ $Date: 2008-04-24 16:25:02 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2008 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "precompiled_bridges.hxx" +#include "sal/config.h" + +#include +#include +#include + +#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 "com/sun/star/uno/genfunc.hxx" +#include "osl/diagnose.h" +#include "sal/alloca.h" +#include "sal/types.h" +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" +#include "typelib/typedescription.hxx" +#include "uno/any2.h" +#include "uno/data.h" + +#include "exceptions.hxx" +#include "flushcode.hxx" +#include "fp.hxx" +#include "isdirectreturntype.hxx" +#include "vtableslotcall.hxx" + +namespace { + +namespace css = com::sun::star; + +void loadFpRegsFromStruct(typelib_TypeDescription * type, void * data) { + for (typelib_CompoundTypeDescription * t = + reinterpret_cast< typelib_CompoundTypeDescription * >(type); + t != NULL; t = t->pBaseTypeDescription) + { + for (sal_Int32 i = 0; i < t->nMembers; ++i) { + switch (t->ppTypeRefs[i]->eTypeClass) { + case typelib_TypeClass_FLOAT: + switch (t->pMemberOffsets[i]) { + case 0: + fp_loadf0(reinterpret_cast< float * >(data)); + break; + case 4: + fp_loadf1(reinterpret_cast< float * >(data) + 1); + break; + case 8: + fp_loadf2(reinterpret_cast< float * >(data) + 2); + break; + case 12: + fp_loadf3(reinterpret_cast< float * >(data) + 3); + break; + case 16: + fp_loadf4(reinterpret_cast< float * >(data) + 4); + break; + case 20: + fp_loadf5(reinterpret_cast< float * >(data) + 5); + break; + case 24: + fp_loadf6(reinterpret_cast< float * >(data) + 6); + break; + case 28: + fp_loadf7(reinterpret_cast< float * >(data) + 7); + break; + default: + OSL_ASSERT(false); + break; + } + break; + case typelib_TypeClass_DOUBLE: + switch (t->pMemberOffsets[i]) { + case 0: + fp_loadd0(reinterpret_cast< double * >(data)); + break; + case 8: + fp_loadd2(reinterpret_cast< double * >(data) + 1); + break; + case 16: + fp_loadd4(reinterpret_cast< double * >(data) + 2); + break; + case 24: + fp_loadd6(reinterpret_cast< double * >(data) + 3); + break; + default: + OSL_ASSERT(false); + break; + } + break; + case typelib_TypeClass_STRUCT: + { + typelib_TypeDescription * td = NULL; + TYPELIB_DANGER_GET(&td, t->ppTypeRefs[i]); + loadFpRegsFromStruct(td, data); + TYPELIB_DANGER_RELEASE(td); + break; + } + } + } + } +} + +void call( + bridges::cpp_uno::shared::CppInterfaceProxy * proxy, + css::uno::TypeDescription const & description, + bool directReturn, typelib_TypeDescriptionReference * returnType, + sal_Int32 count, typelib_MethodParameter * parameters, + unsigned long * callStack) +{ + typelib_TypeDescription * rtd = NULL; + if (returnType != NULL) { + TYPELIB_DANGER_GET(&rtd, returnType); + } + bool retconv = + rtd != NULL && bridges::cpp_uno::shared::relatesToInterfaceType(rtd); + OSL_ASSERT(!(directRet && retconv)); + void * retin; + void * retout; + char retbuf[32]; + if (directReturn) { + retin = returnType == NULL ? NULL : retbuf; + } else { + retout = reinterpret_cast< void * >(callStack[0]); + retin = retconv ? alloca(rtd->nSize) : retout; + } + void ** args = static_cast< void ** >(alloca(count * sizeof (void *))); + void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *))); + typelib_TypeDescription ** argtds = + static_cast< typelib_TypeDescription ** >( + alloca(count * sizeof (typelib_TypeDescription *))); + union fp { float f; double d; }; + fp copies[15]; + sal_Int32 stackPos = directReturn ? 1 : 2; // skip return ptr and this ptr + for (sal_Int32 i = 0; i < count; ++i) { + typelib_TypeDescription * ptd = NULL; + TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef); + if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(ptd)) + { + switch (ptd->eTypeClass) { + case typelib_TypeClass_FLOAT: + if (stackPos <= 15) { + switch (stackPos) { + case 1: + fp_storef3(&copies[0].f); + break; + case 2: + fp_storef5(&copies[1].f); + break; + case 3: + fp_storef7(&copies[2].f); + break; + case 4: + fp_storef9(&copies[3].f); + break; + case 5: + fp_storef11(&copies[4].f); + break; + case 6: + fp_storef13(&copies[5].f); + break; + case 7: + fp_storef15(&copies[6].f); + break; + case 8: + fp_storef17(&copies[7].f); + break; + case 9: + fp_storef19(&copies[8].f); + break; + case 10: + fp_storef21(&copies[9].f); + break; + case 11: + fp_storef23(&copies[10].f); + break; + case 12: + fp_storef25(&copies[11].f); + break; + case 13: + fp_storef27(&copies[12].f); + break; + case 14: + fp_storef29(&copies[13].f); + break; + case 15: + fp_storef31(&copies[14].f); + break; + default: + OSL_ASSERT(false); + break; + } + args[i] = &copies[stackPos - 1].f; + } else { + args[i] = reinterpret_cast< char * >(callStack + stackPos) + + (sizeof (unsigned long) - sizeof (float)); + } + break; + case typelib_TypeClass_DOUBLE: + if (stackPos <= 15) { + switch (stackPos) { + case 1: + fp_stored2(&copies[0].d); + break; + case 2: + fp_stored4(&copies[1].d); + break; + case 3: + fp_stored6(&copies[2].d); + break; + case 4: + fp_stored8(&copies[3].d); + break; + case 5: + fp_stored10(&copies[4].d); + break; + case 6: + fp_stored12(&copies[5].d); + break; + case 7: + fp_stored14(&copies[6].d); + break; + case 8: + fp_stored16(&copies[7].d); + break; + case 9: + fp_stored18(&copies[8].d); + break; + case 10: + fp_stored20(&copies[9].d); + break; + case 11: + fp_stored22(&copies[10].d); + break; + case 12: + fp_stored24(&copies[11].d); + break; + case 13: + fp_stored26(&copies[12].d); + break; + case 14: + fp_stored28(&copies[13].d); + break; + case 15: + fp_stored30(&copies[14].d); + break; + default: + OSL_ASSERT(false); + break; + } + args[i] = &copies[stackPos - 1].d; + } else { + args[i] = reinterpret_cast< char * >(callStack + stackPos) + + (sizeof (unsigned long) - sizeof (double)); + } + break; + default: + OSL_ASSERT(ptd->nSize <= 8); + args[i] = reinterpret_cast< char * >(callStack + stackPos) + + (sizeof (unsigned long) - ptd->nSize); + break; + } + argtds[i] = NULL; + TYPELIB_DANGER_RELEASE(ptd); + } else { + cppArgs[i] = reinterpret_cast< void * >(callStack[stackPos]); + if (!parameters[i].bIn) { + args[i] = alloca(ptd->nSize); + argtds[i] = ptd; + } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) { + args[i] = alloca(ptd->nSize); + uno_copyAndConvertData( + args[i], reinterpret_cast< void * >(callStack[stackPos]), + ptd, proxy->getBridge()->getCpp2Uno()); + argtds[i] = ptd; + } else { + args[i] = reinterpret_cast< void * >(callStack[stackPos]); + argtds[i] = NULL; + TYPELIB_DANGER_RELEASE(ptd); + } + } + ++stackPos; + } + uno_Any exc; + uno_Any * pexc = &exc; + proxy->getUnoI()->pDispatcher( + proxy->getUnoI(), description.get(), retin, args, &pexc); + if (pexc != NULL) { + for (sal_Int32 i = 0; i < count; ++i) { + if (argtds[i] != NULL) { + if (parameters[i].bIn) { + uno_destructData(args[i], argtds[i], NULL); + } + TYPELIB_DANGER_RELEASE(argtds[i]); + } + } + if (rtd != NULL) { + TYPELIB_DANGER_RELEASE(rtd); + } + bridges::cpp_uno::cc5_solaris_sparc64::raiseException( + &exc, proxy->getBridge()->getUno2Cpp()); + std::abort(); // just in case + } + for (sal_Int32 i = 0; i < count; ++i) { + if (argtds[i] != NULL) { + if (parameters[i].bOut) { + uno_destructData( + cppArgs[i], argtds[i], + reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); + uno_copyAndConvertData( + cppArgs[i], args[i], argtds[i], + proxy->getBridge()->getUno2Cpp()); + } + uno_destructData(args[i], argtds[i], NULL); + TYPELIB_DANGER_RELEASE(argtds[i]); + } + } + if (directReturn) { + if (rtd != NULL) { + switch (rtd->eTypeClass) { + case typelib_TypeClass_FLOAT: + fp_loadf0(reinterpret_cast< float * >(retbuf)); + break; + case typelib_TypeClass_DOUBLE: + fp_loadd0(reinterpret_cast< double * >(retbuf)); + break; + case typelib_TypeClass_STRUCT: + loadFpRegsFromStruct(rtd, retbuf); + // fall through + case typelib_TypeClass_ANY: + std::memcpy(callStack, retbuf, rtd->nSize); + break; + default: + OSL_ASSERT(rtd->nSize <= 8); + std::memcpy( + reinterpret_cast< char * >(callStack) + (8 - rtd->nSize), + retbuf, rtd->nSize); + break; + } + } + } else if (retconv) { + uno_copyAndConvertData( + retout, retin, rtd, proxy->getBridge()->getUno2Cpp()); + uno_destructData(retin, rtd, NULL); + } + if (rtd != NULL) { + TYPELIB_DANGER_RELEASE(rtd); + } +} + +extern "C" void vtableCall( + sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned long * callStack) +{ + bool direct = static_cast< sal_uInt32 >((functionIndex) & 0x80000000) == 0; + functionIndex = static_cast< sal_uInt32 >(functionIndex) & 0x7FFFFFFF; + bridges::cpp_uno::shared::CppInterfaceProxy * proxy + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + reinterpret_cast< char * >(callStack[direct ? 0 : 1]) - + vtableOffset); + typelib_InterfaceTypeDescription * type = proxy->getTypeDescr(); + OSL_ASSERT(functionIndex < type->nMapFunctionIndexToMemberIndex); + sal_Int32 pos = type->pMapFunctionIndexToMemberIndex[functionIndex]; + css::uno::TypeDescription desc(type->ppAllMembers[pos]); + switch (desc.get()->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + if (type->pMapMemberIndexToFunctionIndex[pos] == functionIndex) { + // Getter: + call( + proxy, desc, direct, + reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( + desc.get())->pAttributeTypeRef, + 0, NULL, callStack); + } else { + // Setter: + typelib_MethodParameter param = { + NULL, + reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( + desc.get())->pAttributeTypeRef, + true, false }; + call(proxy, desc, true, NULL, 1, ¶m, callStack); + } + break; + case typelib_TypeClass_INTERFACE_METHOD: + switch (functionIndex) { + case 1: + proxy->acquireProxy(); + break; + case 2: + proxy->releaseProxy(); + break; + case 0: + { + typelib_TypeDescription * td = NULL; + TYPELIB_DANGER_GET( + &td, + reinterpret_cast< css::uno::Type * >( + callStack[2])->getTypeLibType()); + if (td != NULL) { + css::uno::XInterface * ifc = NULL; + proxy->getBridge()->getCppEnv()->getRegisteredInterface( + proxy->getBridge()->getCppEnv(), + reinterpret_cast< void ** >(&ifc), + proxy->getOid().pData, + reinterpret_cast< typelib_InterfaceTypeDescription * >( + td)); + if (ifc != NULL) { + uno_any_construct( + reinterpret_cast< uno_Any * >(callStack[0]), &ifc, + td, + reinterpret_cast< uno_AcquireFunc >( + css::uno::cpp_acquire)); + ifc->release(); + TYPELIB_DANGER_RELEASE(td); + break; + } + TYPELIB_DANGER_RELEASE(td); + } + } // fall through + default: + call( + proxy, desc, direct, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + desc.get())->pReturnTypeRef, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + desc.get())->nParams, + reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( + desc.get())->pParams, + callStack); + } + break; + default: + OSL_ASSERT(false); + break; + } +} + +int const codeSnippetSize = 10 * 4; + +unsigned char * generateCodeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, + bool directReturn) +{ + sal_uInt32 index = functionIndex; + if (!directReturn) { + index |= 0x80000000; + } + unsigned int * p = reinterpret_cast< unsigned int * >(code); + OSL_ASSERT(sizeof (unsigned int) == 4); + // 0*4: save %sp, -176, %sp ! minimal stack frame: + *p++ = 0x9DE3BF50; + // 1*4: rd %pc, %l0: + *p++ = 0xA1414000; + // 2*4: ldx %l0, (8-1)*4, %l0: + *p++ = 0xE05C201C; + // 3*4: sethi %hi(index), %o0: + *p++ = 0x11000000 | (index >> 10); + // 4*4: or %o0, %lo(index), %o0: + *p++ = 0x90122000 | (index & 0x3FF); + // 5*4: sethi %hi(vtableOffset), %o1: + *p++ = 0x13000000 | (vtableOffset >> 10); + // 6*4: jmpl %l0, %g0, %g0: + *p++ = 0x81C40000; + // 7*4: or %o1, %lo(vtableOffset), %o1: + *p++ = 0x92126000 | (vtableOffset & 0x3FF); + // 8*4: .xword privateSnippetExecutor: + *reinterpret_cast< unsigned long * >(p) = + reinterpret_cast< unsigned long >(vtableSlotCall); + return code + codeSnippetSize; +} + +} + +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) + 1; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 3) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + Slot * slots = mapBlockToVtable(block) + 2; + slots[-3].fn = NULL; // RTTI + slots[-2].fn = NULL; // null + slots[-1].fn = NULL; // destructor + 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]); + OSL_ASSERT(member != 0); + switch (member->eTypeClass) { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + // Getter: + (s++)->fn = code; + code = generateCodeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->pAttributeTypeRef)); + // Setter: + if (!reinterpret_cast< + typelib_InterfaceAttributeTypeDescription * >( + member)->bReadOnly) + { + (s++)->fn = code; + code = generateCodeSnippet( + code, functionOffset++, vtableOffset, true); + } + break; + + case typelib_TypeClass_INTERFACE_METHOD: + (s++)->fn = code; + code = generateCodeSnippet( + code, functionOffset++, vtableOffset, + bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription * >( + member)->pReturnTypeRef)); + break; + + default: + OSL_ASSERT(false); + break; + } + TYPELIB_DANGER_RELEASE(member); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const * begin, unsigned char const * end) +{ + bridges::cpp_uno::cc5_solaris_sparc64::flushCode(begin, end); +} -- cgit