INTEGRATION: CWS mipselport01 (1.1.2); FILE ADDED

2007/10/15 08:58:01 cmc 1.1.2.2: #i81482# remove warnings and add a to-the-compiler possible throw to ensure that the exception infrastructure is created
2007/10/13 13:48:00 cmc 1.1.2.1: #i81482# add mips bridge
This commit is contained in:
Jens-Heiner Rechtien
2007-11-02 14:22:16 +00:00
parent 98a0273f0e
commit ac3a304902
4 changed files with 1839 additions and 0 deletions

View File

@@ -0,0 +1,808 @@
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: cpp2uno.cxx,v $
*
* $Revision: 1.2 $
*
* Wrote by Fuxin Zhang. fxzhang@ict.ac.cn.
*
* last change: $Author: hr $ $Date: 2007-11-02 15:21:19 $
*
* 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 2005 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 <com/sun/star/uno/genfunc.hxx>
#include <typelib/typedescription.hxx>
#include <uno/data.h>
#include "bridges/cpp_uno/shared/bridge.hxx"
#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
#include "bridges/cpp_uno/shared/types.hxx"
#include "bridges/cpp_uno/shared/vtablefactory.hxx"
#include "share.hxx"
using namespace com::sun::star::uno;
//#define BRDEBUG
#ifdef BRDEBUG
#include <stdio.h>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>
using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
#endif
#include <sys/sysmips.h>
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, // 0 indicates void return
sal_Int32 nParams, typelib_MethodParameter * pParams,
void ** gpreg, void ** /*fpreg*/, void ** ovrflw,
sal_Int64 * pRegisterReturn /* space for register return */ )
{
/* Most MIPS ABIs view the arguments as a struct, of which the
first N words go in registers and the rest go on the stack. If I < N, the
Ith word might go in Ith integer argument register or the Ith
floating-point one. For these ABIs, we only need to remember the number
of words passed so far. We are interested only in o32 ABI,so it is the
case.
*/
int nw = 0; // number of words used by arguments
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call1\n");
#endif
/* C++ has [ret *] or this as the first arguments, so no arguments will
* be passed in floating-point registers?
*/
//int int_seen = 0; // have we seen integer arguments?
void ** pCppStack; //temporary stack pointer
// gpreg: [ret *], this, [gpr params]
// fpreg: [fpr params]
// ovrflw: [gpr or fpr params (properly aligned)]
// 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)
{
if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
{
pUnoReturn = pRegisterReturn; // direct way for simple types
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:simplereturn\n");
#endif
}
else // complex return via ptr (pCppReturn)
{
pCppReturn = *(void **)gpreg;
gpreg++;
nw++;
pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
? alloca( pReturnTypeDescr->nSize )
: pCppReturn); // direct way
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:complexreturn\n");
#endif
}
}
// pop this
gpreg++;
nw++;
// stack space
OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
// parameters
void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
void ** pCppArgs = pUnoArgs + nParams;
// indizes of values this have to be converted (interface conversion cpp<=>uno)
sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
// type descriptions for reconversions
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
sal_Int32 nTempIndizes = 0;
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:nParams=%d\n",nParams);
#endif
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
{
switch (pParamTypeDescr->eTypeClass)
{
case typelib_TypeClass_DOUBLE:
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:hyper=%d,%p\n",pParamTypeDescr->eTypeClass,gpreg[0]);
#endif
if (nw < 3) {
if (nw & 1) {
nw++;
gpreg++;
}
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:gpreg=%p,%p\n",gpreg[0],gpreg[1]);
#endif
pCppArgs[nPos] = gpreg;
pUnoArgs[nPos] = gpreg;
nw += 2;
gpreg += 2;
} else {
if (((long)ovrflw) & 4) ovrflw++;
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:overflw=%p,%p\n",ovrflw[0],ovrflw[1]);
#endif
pCppArgs[nPos] = ovrflw;
pUnoArgs[nPos] = ovrflw;
ovrflw += 2;
}
break;
case typelib_TypeClass_BYTE:
case typelib_TypeClass_BOOLEAN:
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:byte=%p,%p\n",gpreg[0],ovrflw[0]);
#endif
if (nw < 4) {
pCppArgs[nPos] = ((char *)gpreg);
pUnoArgs[nPos] = ((char *)gpreg);
nw++;
gpreg++;
} else {
pCppArgs[nPos] = ((char *)ovrflw);
pUnoArgs[nPos] = ((char *)ovrflw);
ovrflw++;
}
break;
case typelib_TypeClass_CHAR:
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:char=%p,%p\n",gpreg[0],ovrflw[0]);
#endif
if (nw < 4) {
pCppArgs[nPos] = ((char *)gpreg);
pUnoArgs[nPos] = ((char *)gpreg);
nw++;
gpreg++;
} else {
pCppArgs[nPos] = ((char *)ovrflw);
pUnoArgs[nPos] = ((char *)ovrflw);
ovrflw++;
}
break;
default:
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:def=%p,%p\n",gpreg[0],ovrflw[0]);
#endif
if (nw < 4) {
pCppArgs[nPos] = gpreg;
pUnoArgs[nPos] = gpreg;
nw++;
gpreg++;
} else {
pCppArgs[nPos] = ovrflw;
pUnoArgs[nPos] = ovrflw;
ovrflw++;
}
break;
}
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
else // ptr to complex value | ref
{
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:ptr|ref\n");
#endif
if (nw < 4) {
pCppArgs[nPos] = *(void **)gpreg;
pCppStack = gpreg;
nw++;
gpreg++;
} else {
pCppArgs[nPos] = *(void **)ovrflw;
pCppStack = ovrflw;
ovrflw++;
}
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:pCppStack=%p\n",pCppStack);
#endif
if (! rParam.bIn) // is pure out
{
// uno out is unconstructed mem!
pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
pTempIndizes[nTempIndizes] = nPos;
// will be released at reconversion
ppTempParamTypeDescr[nTempIndizes++] = 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() );
pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
// will be released at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:related to interface,%p,%d,pUnoargs[%d]=%p\n",*(void**)pCppStack,pParamTypeDescr->nSize,nPos,pUnoArgs[nPos]);
#endif
}
else // direct way
{
pUnoArgs[nPos] = *(void **)pCppStack;
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call:direct,pUnoArgs[%d]=%p\n",nPos,pUnoArgs[nPos]);
#endif
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
}
}
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call2,%p,unoargs=%p\n",pThis->getUnoI()->pDispatcher,pUnoArgs);
#endif
// 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 );
#ifdef BRDEBUG
fprintf(stderr,"cpp2uno_call2,after dispatch\n");
#endif
// in case an exception occured...
if (pUnoExc)
{
// destruct temporary in/inout params
for ( ; nTempIndizes--; )
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
if (pParams[nIndex].bIn) // is in/inout => was constructed
uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
}
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 occured...
{
// temporary params
for ( ; nTempIndizes--; )
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
if (pParams[nIndex].bOut) // inout/out
{
// convert and assign
uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
pThis->getBridge()->getUno2Cpp() );
}
// destroy temp uno param
uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
// return
if (pCppReturn) // has complex return
{
if (pUnoReturn != pCppReturn) // needs reconversion
{
uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
pThis->getBridge()->getUno2Cpp() );
// destroy temp uno return
uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
}
// complex return ptr is set to return reg
*(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 ** gpreg, void ** fpreg, void ** ovrflw,
sal_Int64 * pRegisterReturn /* space for register return */ )
{
OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate1 gp=%p,fp=%p,ov=%p\n",gpreg,fpreg,ovrflw);
fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
#endif
// gpreg: [ret *], this, [other gpr params]
// fpreg: [fpr params]
// ovrflw: [gpr or fpr params (properly aligned)]
void * pThis;
if (nFunctionIndex & 0x80000000 )
{
nFunctionIndex &= 0x7fffffff;
pThis = gpreg[1];
}
else
{
pThis = gpreg[0];
}
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate12,pThis=%p, nFunctionIndex=%d,nVtableOffset=%d\n",pThis,nFunctionIndex,nVtableOffset);
#endif
pThis = static_cast< char * >(pThis) - nVtableOffset;
bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
= bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
pThis);
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate13,pCppI=%p\n",pCppI);
#endif
typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate2\n");
#endif
OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
{
throw RuntimeException(
rtl::OUString::createFromAscii("illegal vtable index!"),
(XInterface *)pThis );
}
// determine called method
sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate3\n");
OString cstr( OUStringToOString( aMemberDescr.get()->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
fprintf( stderr, "calling %s, nFunctionIndex=%d\n", cstr.getStr(), nFunctionIndex );
#endif
typelib_TypeClass eRet;
switch (aMemberDescr.get()->eTypeClass)
{
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate4\n");
#endif
if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
{
// is GET method
eRet = cpp2uno_call(
pCppI, aMemberDescr.get(),
((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
0, 0, // no params
gpreg, fpreg, ovrflw, 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,
gpreg, fpreg, ovrflw, pRegisterReturn );
}
break;
}
case typelib_TypeClass_INTERFACE_METHOD:
{
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate5\n");
#endif
// is METHOD
switch (nFunctionIndex)
{
case 1: // acquire()
pCppI->acquireProxy(); // non virtual call!
eRet = typelib_TypeClass_VOID;
break;
case 2: // release()
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate51\n");
#endif
pCppI->releaseProxy(); // non virtual call!
eRet = typelib_TypeClass_VOID;
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate52\n");
#endif
break;
case 0: // queryInterface() opt
{
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[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 * >( gpreg[0] ),
&pInterface, pTD, cpp_acquire );
pInterface->release();
TYPELIB_DANGER_RELEASE( pTD );
*(void **)pRegisterReturn = gpreg[0];
eRet = typelib_TypeClass_ANY;
break;
}
TYPELIB_DANGER_RELEASE( pTD );
}
} // else perform queryInterface()
default:
eRet = cpp2uno_call(
pCppI, aMemberDescr.get(),
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
gpreg, fpreg, ovrflw, pRegisterReturn );
}
break;
}
default:
{
#ifdef BRDEBUG
fprintf(stderr,"cpp_mediate6\n");
#endif
throw RuntimeException(
rtl::OUString::createFromAscii("no member description found!"),
(XInterface *)pThis );
// is here for dummy
eRet = typelib_TypeClass_VOID;
}
}
return eRet;
}
//==================================================================================================
/**
* is called on incoming vtable calls
* (called by asm snippets)
*/
// static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw)
// static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** ovrflw)
static void cpp_vtable_call(void)
{
int nFunctionIndex;
int vTableOffset;
void** pCallStack;
void** ovrflw;
sal_Int32 gpreg[4];
double fpreg[2];
//memcpy( fpreg, fpregptr, 16);
volatile long nRegReturn[2];
__asm__( "sw $4, %0\n\t"
"sw $5, %1\n\t"
"sw $6, %2\n\t"
"sw $7, %3\n\t"
::"m"(nFunctionIndex), "m"(vTableOffset), "m"(pCallStack), "m"(ovrflw) );
memcpy( gpreg, pCallStack, 16);
#ifdef BRDEBUG
fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %d\n",nFunctionIndex);
fprintf(stderr,"in cpp_vtable_call nVtableOffset is %d\n",vTableOffset);
fprintf(stderr,"gp=%x,%x,%x,%x\n",gpreg[0],gpreg[1],gpreg[2],gpreg[3]);
#endif
//sal_Bool bComplex = nFunctionIndex & 0x80000000 ? sal_True : sal_False;
typelib_TypeClass aType =
cpp_mediate( nFunctionIndex, vTableOffset, (void**)gpreg, (void**)fpreg, ovrflw, (sal_Int64*)nRegReturn );
switch( aType )
{
// move return value into register space
// (will be loaded by machine code snippet)
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
__asm__( "lbu $2,%0\n\t" : :
"m"(nRegReturn[0]) );
break;
case typelib_TypeClass_CHAR:
case typelib_TypeClass_UNSIGNED_SHORT:
__asm__( "lhu $2,%0\n\t" : :
"m"(nRegReturn[0]) );
break;
case typelib_TypeClass_SHORT:
__asm__( "lh $2,%0\n\t" : :
"m"(nRegReturn[0]) );
break;
case typelib_TypeClass_FLOAT:
__asm__( "lwc1 $f0,%0\n\t" : :
"m" (*((float*)nRegReturn)) );
break;
case typelib_TypeClass_DOUBLE:
__asm__( "lwc1 $f0,%0\n\t"
"lwc1 $f1,%1\n\t" : :
"m" (*((float*)nRegReturn)),
"m" (*(((float*)nRegReturn)+1)) );
break;
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
__asm__( "lw $3,%0\n\t" : :
"m"(nRegReturn[1]) ); // fall through
default:
__asm__( "lw $2,%0\n\t" : :
"m"(nRegReturn[0]) );
break;
}
}
int const codeSnippetSize = 56;
unsigned char * codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
bool simpleRetType)
{
#ifdef BRDEBUG
fprintf(stderr,"in codeSnippet functionIndex is %d\n", functionIndex);
fprintf(stderr,"in codeSnippet vtableOffset is %d\n", vtableOffset);
fflush(stderr);
#endif
if (! simpleRetType )
functionIndex |= 0x80000000;
unsigned long * p = (unsigned long *) code;
// OSL_ASSERT( sizeof (long) == 4 );
OSL_ASSERT((((unsigned long)code) & 0x3) == 0 ); //aligned to 4 otherwise a mistake
/* generate this code */
/*
#save regs into argument space required by mips abi
c: afa40000 sw a0,0(sp)
10: afa50004 sw a1,4(sp)
14: afa60008 sw a2,8(sp)
18: afa7000c sw a3,12(sp)
#a0=index
1c: 3c040000 lui a0,0x0
20: 34840000 ori a0,a0,0x0
#a1=offset
24: 3c050000 lui a1,0x0
28: 34a50000 ori a1,a1,0x0
#a2=gpregptr
2c: 27a60000 addiu a2,sp,0
#a3=ovrflw
30: 27a70010 addiu a3,sp,16
#load cpp_vtable_call addr
34: 3c190000 lui t9,0x0
38: 37390000 ori t9,t9,0
#jmp to the function,note: we don't use jalr, that will destroy $ra
#but be sure to use t9! gp calculation depends on it
3c: 03200008 jr t9
40: 00000000 nop
be careful, we use the argument space reserved by the caller to
write down regs. This can avoid the need to make use of arbitary far away
stack space or to allocate a function frame for this code snippet itself.
Since only functions with variable arguments will overwrite the space,
cpp_vtable_call should be safe.
??? gcc seems change this behavior! cpp_vtable_call overwrite the space!
*/
* p++ = 0xafa40000;
* p++ = 0xafa50004;
* p++ = 0xafa60008;
* p++ = 0xafa7000c;
* p++ = 0x3c040000 | ((functionIndex>>16) & 0x0000ffff);
* p++ = 0x34840000 | (functionIndex & 0x0000ffff);
* p++ = 0x3c050000 | ((vtableOffset>>16) & 0x0000ffff);
* p++ = 0x34a50000 | (vtableOffset & 0x0000ffff);
* p++ = 0x27a60000;
* p++ = 0x27a70010;
* p++ = 0x3c190000 | ((((unsigned long)cpp_vtable_call) >> 16) & 0x0000ffff);
* p++ = 0x37390000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF);
* p++ = 0x03200008;
* p++ = 0x00000000;
return (code + codeSnippetSize);
}
}
#define MIN_LINE_SIZE 32
void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * /*bptr*/, unsigned char const * /*eptr*/)
{
sysmips(FLUSH_CACHE,0,0,0);
}
void ** bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
{
return reinterpret_cast< void ** >(block) + 2;
}
sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
sal_Int32 slotCount)
{
return (slotCount + 2) * sizeof (void *) + slotCount * codeSnippetSize;
}
void ** bridges::cpp_uno::shared::VtableFactory::initializeBlock(void * block) {
void ** slots = mapBlockToVtable(block);
slots[-2] = 0; //null
slots[-1] = 0; //destructor
return slots;
}
unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
void ** slots, unsigned char * code,
typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
sal_Int32
#ifdef BRDEBUG
functionCount
#endif
, sal_Int32 vtableOffset)
{
#ifdef BRDEBUG
fprintf(stderr, "in addLocalFunctions functionOffset is %d\n",functionOffset);
fprintf(stderr, "in addLocalFunctions vtableOffset is %d\n",vtableOffset);
fprintf(stderr, "nMembers=%d\n",type->nMembers);
fflush(stderr);
#endif
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:
*slots++ = code;
code = codeSnippet(
code, functionOffset++, vtableOffset,
bridges::cpp_uno::shared::isSimpleType(
reinterpret_cast<
typelib_InterfaceAttributeTypeDescription * >(
member)->pAttributeTypeRef));
// Setter:
if (!reinterpret_cast<
typelib_InterfaceAttributeTypeDescription * >(
member)->bReadOnly)
{
*slots++ = code;
code = codeSnippet(code, functionOffset++, vtableOffset, true);
}
break;
case typelib_TypeClass_INTERFACE_METHOD:
*slots++ = code;
code = codeSnippet(
code, functionOffset++, vtableOffset,
bridges::cpp_uno::shared::isSimpleType(
reinterpret_cast<
typelib_InterfaceMethodTypeDescription * >(
member)->pReturnTypeRef));
break;
default:
OSL_ASSERT(false);
break;
}
TYPELIB_DANGER_RELEASE(member);
}
return code;
}

View File

@@ -0,0 +1,332 @@
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: except.cxx,v $
*
* $Revision: 1.2 $
*
* last change: $Author: hr $ $Date: 2007-11-02 15:21:34 $
*
* 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 2005 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 <stdio.h>
#include <dlfcn.h>
#include <cxxabi.h>
#include <hash_map>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>
#include <com/sun/star/uno/genfunc.hxx>
#include <typelib/typedescription.hxx>
#include <uno/any2.h>
#include "share.hxx"
using namespace ::std;
using namespace ::osl;
using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::__cxxabiv1;
namespace CPPU_CURRENT_NAMESPACE
{
void dummy_can_throw_anything( char const * )
{
}
//==================================================================================================
static OUString toUNOname( char const * p ) SAL_THROW( () )
{
#if defined BRIDGES_DEBUG
char const * start = p;
#endif
// example: N3com3sun4star4lang24IllegalArgumentExceptionE
OUStringBuffer buf( 64 );
OSL_ASSERT( 'N' == *p );
++p; // skip N
while ('E' != *p)
{
// read chars count
long n = (*p++ - '0');
while ('0' <= *p && '9' >= *p)
{
n *= 10;
n += (*p++ - '0');
}
buf.appendAscii( p, n );
p += n;
if ('E' != *p)
buf.append( (sal_Unicode)'.' );
}
#if defined BRIDGES_DEBUG
OUString ret( buf.makeStringAndClear() );
OString c_ret( OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ) );
fprintf( stderr, "> toUNOname(): %s => %s\n", start, c_ret.getStr() );
return ret;
#else
return buf.makeStringAndClear();
#endif
}
//==================================================================================================
class RTTI
{
typedef hash_map< OUString, type_info *, OUStringHash > t_rtti_map;
Mutex m_mutex;
t_rtti_map m_rttis;
t_rtti_map m_generatedRttis;
void * m_hApp;
public:
RTTI() SAL_THROW( () );
~RTTI() SAL_THROW( () );
type_info * getRTTI( typelib_CompoundTypeDescription * ) SAL_THROW( () );
};
//__________________________________________________________________________________________________
RTTI::RTTI() SAL_THROW( () )
: m_hApp( dlopen( 0, RTLD_LAZY ) )
{
}
//__________________________________________________________________________________________________
RTTI::~RTTI() SAL_THROW( () )
{
dlclose( m_hApp );
}
//__________________________________________________________________________________________________
type_info * RTTI::getRTTI( typelib_CompoundTypeDescription *pTypeDescr ) SAL_THROW( () )
{
type_info * rtti;
OUString const & unoName = *(OUString const *)&pTypeDescr->aBase.pTypeName;
MutexGuard guard( m_mutex );
t_rtti_map::const_iterator iRttiFind( m_rttis.find( unoName ) );
if (iRttiFind == m_rttis.end())
{
// RTTI symbol
OStringBuffer buf( 64 );
buf.append( RTL_CONSTASCII_STRINGPARAM("_ZTIN") );
sal_Int32 index = 0;
do
{
OUString token( unoName.getToken( 0, '.', index ) );
buf.append( token.getLength() );
OString c_token( OUStringToOString( token, RTL_TEXTENCODING_ASCII_US ) );
buf.append( c_token );
}
while (index >= 0);
buf.append( 'E' );
OString symName( buf.makeStringAndClear() );
rtti = (type_info *)dlsym( m_hApp, symName.getStr() );
if (rtti)
{
pair< t_rtti_map::iterator, bool > insertion(
m_rttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
OSL_ENSURE( insertion.second, "### inserting new rtti failed?!" );
}
else
{
// try to lookup the symbol in the generated rtti map
t_rtti_map::const_iterator iFind( m_generatedRttis.find( unoName ) );
if (iFind == m_generatedRttis.end())
{
// we must generate it !
// symbol and rtti-name is nearly identical,
// the symbol is prefixed with _ZTI
char const * rttiName = symName.getStr() +4;
#if defined BRIDGES_DEBUG
fprintf( stderr,"generated rtti for %s\n", rttiName );
#endif
if (pTypeDescr->pBaseTypeDescription)
{
// ensure availability of base
type_info * base_rtti = getRTTI(
(typelib_CompoundTypeDescription *)pTypeDescr->pBaseTypeDescription );
rtti = new __si_class_type_info(
strdup( rttiName ), (__class_type_info *)base_rtti );
}
else
{
// this class has no base class
rtti = new __class_type_info( strdup( rttiName ) );
}
pair< t_rtti_map::iterator, bool > insertion(
m_generatedRttis.insert( t_rtti_map::value_type( unoName, rtti ) ) );
OSL_ENSURE( insertion.second, "### inserting new generated rtti failed?!" );
}
else // taking already generated rtti
{
rtti = iFind->second;
}
}
}
else
{
rtti = iRttiFind->second;
}
return rtti;
}
//--------------------------------------------------------------------------------------------------
static void deleteException( void * pExc )
{
__cxa_exception const * header = ((__cxa_exception const *)pExc - 1);
typelib_TypeDescription * pTD = 0;
OUString unoName( toUNOname( header->exceptionType->name() ) );
::typelib_typedescription_getByName( &pTD, unoName.pData );
OSL_ENSURE( pTD, "### unknown exception type! leaving out destruction => leaking!!!" );
if (pTD)
{
::uno_destructData( pExc, pTD, cpp_release );
::typelib_typedescription_release( pTD );
}
}
//==================================================================================================
void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp )
{
#if defined BRIDGES_DEBUG
OString cstr(
OUStringToOString(
*reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
RTL_TEXTENCODING_ASCII_US ) );
fprintf( stderr, "> uno exception occured: %s\n", cstr.getStr() );
#endif
void * pCppExc;
type_info * rtti;
{
// construct cpp exception object
typelib_TypeDescription * pTypeDescr = 0;
TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType );
OSL_ASSERT( pTypeDescr );
if (! pTypeDescr)
{
throw RuntimeException(
OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get typedescription for type ") ) +
*reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
Reference< XInterface >() );
}
pCppExc = __cxa_allocate_exception( pTypeDescr->nSize );
::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp );
// destruct uno exception
::uno_any_destruct( pUnoExc, 0 );
// avoiding locked counts
static RTTI * s_rtti = 0;
if (! s_rtti)
{
MutexGuard guard( Mutex::getGlobalMutex() );
if (! s_rtti)
{
#ifdef LEAK_STATIC_DATA
s_rtti = new RTTI();
#else
static RTTI rtti_data;
s_rtti = &rtti_data;
#endif
}
}
rtti = (type_info *)s_rtti->getRTTI( (typelib_CompoundTypeDescription *) pTypeDescr );
TYPELIB_DANGER_RELEASE( pTypeDescr );
OSL_ENSURE( rtti, "### no rtti for throwing exception!" );
if (! rtti)
{
throw RuntimeException(
OUString( RTL_CONSTASCII_USTRINGPARAM("no rtti for type ") ) +
*reinterpret_cast< OUString const * >( &pUnoExc->pType->pTypeName ),
Reference< XInterface >() );
}
}
__cxa_throw( pCppExc, rtti, deleteException );
}
//==================================================================================================
void fillUnoException( __cxa_exception * header, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno )
{
if (! header)
{
RuntimeException aRE(
OUString( RTL_CONSTASCII_USTRINGPARAM("no exception header!") ),
Reference< XInterface >() );
Type const & rType = ::getCppuType( &aRE );
uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if defined _DEBUG
OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
OSL_ENSURE( 0, cstr.getStr() );
#endif
return;
}
typelib_TypeDescription * pExcTypeDescr = 0;
OUString unoName( toUNOname( header->exceptionType->name() ) );
#if defined BRIDGES_DEBUG
OString cstr_unoName( OUStringToOString( unoName, RTL_TEXTENCODING_ASCII_US ) );
fprintf( stderr, "> c++ exception occured: %s\n", cstr_unoName.getStr() );
#endif
typelib_typedescription_getByName( &pExcTypeDescr, unoName.pData );
if (0 == pExcTypeDescr)
{
RuntimeException aRE(
OUString( RTL_CONSTASCII_USTRINGPARAM("exception type not found: ") ) + unoName,
Reference< XInterface >() );
Type const & rType = ::getCppuType( &aRE );
uno_type_any_constructAndConvert( pUnoExc, &aRE, rType.getTypeLibType(), pCpp2Uno );
#if defined _DEBUG
OString cstr( OUStringToOString( aRE.Message, RTL_TEXTENCODING_ASCII_US ) );
OSL_ENSURE( 0, cstr.getStr() );
#endif
}
else
{
// construct uno exception any
uno_any_constructAndConvert( pUnoExc, header->adjustedPtr, pExcTypeDescr, pCpp2Uno );
typelib_typedescription_release( pExcTypeDescr );
}
}
}

View File

@@ -0,0 +1,89 @@
#*************************************************************************
#
# OpenOffice.org - a multi-platform office productivity suite
#
# $RCSfile: makefile.mk,v $
#
# $Revision: 1.2 $
#
# last change: $Author: hr $ $Date: 2007-11-02 15:21:47 $
#
# 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 2005 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
#
#*************************************************************************
PRJ=..$/..$/..
PRJNAME=bridges
TARGET=gcc3_uno
LIBTARGET=no
ENABLE_EXCEPTIONS=TRUE
NO_BSYMBOLIC=TRUE
# --- Settings -----------------------------------------------------
.INCLUDE : settings.mk
# --- Files --------------------------------------------------------
.IF "$(COM)$(OS)$(CPU)" == "GCCLINUXM"
.IF "$(cppu_no_leak)" == ""
CFLAGS += -DLEAK_STATIC_DATA
.ENDIF
# In case someone enabled the non-standard -fomit-frame-pointer which does not
# work with the .cxx sources in this directory:
CFLAGSCXX += -fno-omit-frame-pointer
CFLAGSNOOPT=-O0
NOOPTFILES = \
$(SLO)$/uno2cpp.obj \
$(SLO)$/cpp2uno.obj
SLOFILES= \
$(SLO)$/except.obj \
$(SLO)$/cpp2uno.obj \
$(SLO)$/uno2cpp.obj
SHL1TARGET=$(TARGET)
SHL1DEF=$(MISC)$/$(SHL1TARGET).def
SHL1IMPLIB=i$(TARGET)
SHL1VERSIONMAP=..$/..$/bridge_exports.map
SHL1OBJS= $(SLOFILES)
SHL1LIBS =$(SLB)$/cpp_uno_shared.lib
SHL1STDLIBS= \
$(CPPULIB) \
$(SALLIB)
.ENDIF
# --- Targets ------------------------------------------------------
.INCLUDE : target.mk

View File

@@ -0,0 +1,610 @@
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: uno2cpp.cxx,v $
*
* $Revision: 1.2 $
*
* Wrote by Fuxin Zhang. fxzhang@ict.ac.cn.
*
* last change: $Author: hr $ $Date: 2007-11-02 15:22:16 $
*
* 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 2005 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 <malloc.h>
#include <com/sun/star/uno/genfunc.hxx>
#include <uno/data.h>
#include "bridges/cpp_uno/shared/bridge.hxx"
#include "bridges/cpp_uno/shared/types.hxx"
#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
#include "bridges/cpp_uno/shared/vtables.hxx"
#include "share.hxx"
//#define BRDEBUG
#ifdef BRDEBUG
#include <stdio.h>
#endif
using namespace ::rtl;
using namespace ::com::sun::star::uno;
namespace
{
//==================================================================================================
static void callVirtualMethod(
void * pAdjustedThisPtr,
sal_Int32 nVtableIndex,
void * pRegisterReturn,
typelib_TypeClass eReturnType,
char * pPT,
sal_Int32 * pStackLongs,
sal_Int32 /*nStackLongs*/)
{
// parameter list is mixed list of * and values
// reference parameters are pointers
unsigned long * mfunc; // actual function to be invoked
void (*ptr)();
int gpr[4]; // storage for gpregisters, map to a0-a3
int off; // offset used to find function
int nw; // number of words mapped
long *p; // pointer to parameter overflow area
int c; // character of parameter type being decoded
float fret,fret2; // temporary function return values
int iret, iret2;
// never called
if (! pAdjustedThisPtr ) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
#ifdef BRDEBUG
fprintf(stderr,"in CallVirtualMethod\n");
#endif
// Because of the MIPS O32 calling conventions we could be passing
// parameters in both register types and on the stack. To create the
// stack parameter area we need we now simply allocate local
// variable storage param[] that is at least the size of the parameter stack
// (more than enough space) which we can overwrite the parameters into.
/* p = sp - 512; new sp will be p - 16, but we don't change sp
* at this time to avoid breaking ABI--not sure whether changing sp will break
* references to local variables. For the same reason, we use abosulte value.
*/
__asm__ __volatile__ (
"addiu $2,$29,-512\n\t"
"move %0,$2\n\t"
:"=r"(p): : "$2","$29" );
#ifdef BRDEBUG
if (nStackLongs * 4 > 512 )
fprintf(stderr,"too many arguments");
#endif
// now begin to load the C++ function arguments into storage
nw = 0;
// now we need to parse the entire signature string */
// until we get the END indicator */
// treat complex return pointer like any other parameter //
#ifdef BRDEBUG
fprintf(stderr,"overflow area pointer p=%p\n",p);
/* Let's figure out what is really going on here*/
fprintf(stderr,"callVirtualMethod paramters string is %s\n",pPT);
int k = nStackLongs;
long * q = (long *)pStackLongs;
while (k > 0) {
fprintf(stderr,"uno stack is: %x\n",(unsigned int)*q);
k--;
q++;
}
#endif
/* parse the argument list up to the ending ) */
while (*pPT != 'X') {
c = *pPT;
switch (c) {
case 'D': /* type is double */
/* treat the same as long long */
case 'H': /* type is long long */
if (nw & 1) nw++; /* note even elements gpr[] will map to
odd registers*/
if (nw < 4) {
gpr[nw++] = *pStackLongs;
gpr[nw++] = *(pStackLongs+1);
} else {
if (((long) p) & 4)
p++;
*p++ = *pStackLongs;
*p++ = *(pStackLongs+1);
}
pStackLongs += 2;
break;
case 'S':
if (nw < 4) {
gpr[nw++] = *((unsigned short*)pStackLongs);
} else {
*p++ = *((unsigned short *)pStackLongs);
}
pStackLongs += 1;
break;
case 'B':
if (nw < 4) {
gpr[nw++] = *((char *)pStackLongs);
} else {
*p++ = *((char *)pStackLongs);
}
pStackLongs += 1;
break;
default:
if (nw < 4) {
gpr[nw++] = *pStackLongs;
} else {
*p++ = *pStackLongs;
}
pStackLongs += 1;
break;
}
pPT++;
}
/* figure out the address of the function we need to invoke */
off = nVtableIndex;
off = off * 4; // 4 bytes per slot
mfunc = *((unsigned long **)pAdjustedThisPtr); // get the address of the vtable
mfunc = (unsigned long *)((char *)mfunc + off); // get the address from the vtable entry at offset
mfunc = *((unsigned long **)mfunc); // the function is stored at the address
ptr = (void (*)())mfunc;
#ifdef BRDEBUG
fprintf(stderr,"calling function %p\n",mfunc);
#endif
/* Set up the machine registers and invoke the function */
__asm__ __volatile__ (
"lw $4, 0(%0)\n\t"
"lw $5, 4(%0)\n\t"
"lw $6, 8(%0)\n\t"
"lw $7, 12(%0)\n\t"
: : "r" (gpr)
: "$4", "$5", "$6", "$7"
);
__asm__ __volatile__ ("addiu $29,$29,-528\r\n":::"$29");
(*ptr)();
__asm__ __volatile__ ("addiu $29,$29,528\r\n":::"$29");
__asm__ __volatile__ (
"sw $2,%0 \n\t"
"sw $3,%1 \n\t"
"swc1 $f0,%2\n\t"
"swc1 $f1,%3\n\t"
: "=m" (iret), "=m" (iret2),"=m"(fret),"=m"(fret2) : );
switch( eReturnType )
{
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
((long*)pRegisterReturn)[0] = iret;
((long*)pRegisterReturn)[1] = iret2;
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
case typelib_TypeClass_ENUM:
((long*)pRegisterReturn)[0] = iret;
break;
case typelib_TypeClass_CHAR:
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
*(unsigned short*)pRegisterReturn = (unsigned short)iret;
break;
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
*(unsigned char*)pRegisterReturn = (unsigned char)iret;
break;
case typelib_TypeClass_FLOAT:
*(float*)pRegisterReturn = fret;
break;
case typelib_TypeClass_DOUBLE:
((float*)pRegisterReturn)[0] = fret;
((float*)pRegisterReturn)[1] = fret2;
break;
default:
break;
}
}
//==================================================================================================
static void cpp_call(
bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
bridges::cpp_uno::shared::VtableSlot aVtableSlot,
typelib_TypeDescriptionReference * pReturnTypeRef,
sal_Int32 nParams, typelib_MethodParameter * pParams,
void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
{
// max space for: [complex ret ptr], values|ptr ...
char * pCppStack =
(char *)alloca( sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
char * pCppStackStart = pCppStack;
// need to know parameter types for callVirtualMethod so generate a signature string
char * pParamType = (char *) alloca(nParams+2);
char * pPT = pParamType;
#ifdef BRDEBUG
fprintf(stderr,"in cpp_call\n");
#endif
// return
typelib_TypeDescription * pReturnTypeDescr = 0;
TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
// OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
if (pReturnTypeDescr)
{
if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
{
pCppReturn = pUnoReturn; // direct way for simple types
}
else
{
// complex return via ptr
pCppReturn = *(void **)pCppStack =
(bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
? alloca( pReturnTypeDescr->nSize ): pUnoReturn); // direct way
*pPT++ = 'I'; //signify that a complex return type on stack
pCppStack += sizeof(void *);
}
}
// push this
void* pAdjustedThisPtr = reinterpret_cast< void **>(pThis->getCppI()) + aVtableSlot.offset;
*(void**)pCppStack = pAdjustedThisPtr;
pCppStack += sizeof( void* );
*pPT++ = 'I';
// stack space
// OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
// args
void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
// indizes of values this have to be converted (interface conversion cpp<=>uno)
sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
// type descriptions for reconversions
typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
sal_Int32 nTempIndizes = 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] = pCppStack, pUnoArgs[nPos], pParamTypeDescr,
pThis->getBridge()->getUno2Cpp() );
switch (pParamTypeDescr->eTypeClass)
{
// we need to know type of each param so that we know whether to use
// gpr or fpr to pass in parameters:
// Key: I - int, long, pointer, etc means pass in gpr
// B - byte value passed in gpr
// S - short value passed in gpr
// F - float value pass in fpr
// D - double value pass in fpr
// H - long long int pass in proper pairs of gpr (3,4) (5,6), etc
// X - indicates end of parameter description string
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
case typelib_TypeClass_ENUM:
*pPT++ = 'I';
break;
case typelib_TypeClass_SHORT:
case typelib_TypeClass_CHAR:
case typelib_TypeClass_UNSIGNED_SHORT:
*pPT++ = 'S';
break;
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
*pPT++ = 'B';
break;
case typelib_TypeClass_FLOAT:
*pPT++ = 'F';
break;
case typelib_TypeClass_DOUBLE:
*pPT++ = 'D';
pCppStack += sizeof(sal_Int32); // extra long
break;
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
*pPT++ = 'H';
pCppStack += sizeof(sal_Int32); // extra long
break;
default:
break;
}
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
else // ptr to complex value | ref
{
if (! rParam.bIn) // is pure out
{
// cpp out is constructed mem, uno out is not!
uno_constructData(
*(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
pParamTypeDescr );
pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
// will be released at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
// is in/inout
else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
{
uno_copyAndConvertData(
*(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
pUnoArgs[nPos], pParamTypeDescr,
pThis->getBridge()->getUno2Cpp() );
pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
// will be released at reconversion
ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
}
else // direct way
{
*(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
// no longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
// KBH: FIXME: is this the right way to pass these
*pPT++='I';
}
pCppStack += sizeof(sal_Int32); // standard parameter length
}
// terminate the signature string
*pPT++='X';
*pPT=0;
try
{
OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" );
callVirtualMethod(
pAdjustedThisPtr, aVtableSlot.index,
pCppReturn, pReturnTypeDescr->eTypeClass, pParamType,
(sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) );
// NO exception occured...
*ppUnoExc = 0;
// reconvert temporary params
for ( ; nTempIndizes--; )
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
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
fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions,
*ppUnoExc, pThis->getBridge()->getCpp2Uno() );
// temporary params
for ( ; nTempIndizes--; )
{
sal_Int32 nIndex = pTempIndizes[nTempIndizes];
// destroy temp cpp param => cpp: every param was constructed
uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
}
// 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);
//typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
#ifdef BRDEBUG
fprintf(stderr,"in dispatch\n");
#endif
switch (pMemberDescr->eTypeClass)
{
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
VtableSlot aVtableSlot(
getVtableSlot(
reinterpret_cast<
typelib_InterfaceAttributeTypeDescription const * >(
pMemberDescr)));
if (pReturn)
{
// dependent dispatch
cpp_call(
pThis, aVtableSlot,
((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
0, 0, // no params
pReturn, pArgs, ppException );
}
else
{
// is SET
typelib_MethodParameter aParam;
aParam.pTypeRef =
((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
aParam.bIn = sal_True;
aParam.bOut = sal_False;
typelib_TypeDescriptionReference * pReturnTypeRef = 0;
OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
typelib_typedescriptionreference_new(
&pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
// dependent dispatch
aVtableSlot.index += 1; //get then set method
cpp_call(
pThis, aVtableSlot,
pReturnTypeRef,
1, &aParam,
pReturn, pArgs, ppException );
typelib_typedescriptionreference_release( pReturnTypeRef );
}
break;
}
case typelib_TypeClass_INTERFACE_METHOD:
{
VtableSlot aVtableSlot(
getVtableSlot(
reinterpret_cast<
typelib_InterfaceMethodTypeDescription const * >(
pMemberDescr)));
switch (aVtableSlot.index)
{
// standard calls
case 1: // acquire uno interface
(*pUnoI->acquire)( pUnoI );
*ppException = 0;
break;
case 2: // release uno interface
(*pUnoI->release)( pUnoI );
*ppException = 0;
break;
case 0: // queryInterface() opt
{
typelib_TypeDescription * pTD = 0;
TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
if (pTD)
{
uno_Interface * pInterface = 0;
(*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
pThis->pBridge->getUnoEnv(),
(void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
if (pInterface)
{
::uno_any_construct(
reinterpret_cast< uno_Any * >( pReturn ),
&pInterface, pTD, 0 );
(*pInterface->release)( pInterface );
TYPELIB_DANGER_RELEASE( pTD );
*ppException = 0;
break;
}
TYPELIB_DANGER_RELEASE( pTD );
}
} // else perform queryInterface()
default:
// dependent dispatch
cpp_call(
pThis, aVtableSlot,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
pReturn, pArgs, ppException );
}
break;
}
default:
{
::com::sun::star::uno::RuntimeException aExc(
OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
Type const & rExcType = ::getCppuType( &aExc );
// binary identical null reference
::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
}
}
}
}}}