INTEGRATION: CWS sb29 (1.6.46); FILE MERGED

2005/02/01 15:36:20 sb 1.6.46.1: #i41817# When calling from binary UNO to C++, correctly remove from the stack the pointer to a class object return value.
This commit is contained in:
Vladimir Glazounov
2005-02-21 11:13:28 +00:00
parent 4215fbaa2f
commit a23800e270

View File

@@ -2,9 +2,9 @@
* *
* $RCSfile: cpp2uno.cxx,v $ * $RCSfile: cpp2uno.cxx,v $
* *
* $Revision: 1.6 $ * $Revision: 1.7 $
* *
* last change: $Author: obo $ $Date: 2004-06-04 02:59:45 $ * last change: $Author: vg $ $Date: 2005-02-21 12:13:28 $
* *
* The Contents of this file are made available subject to the terms of * The Contents of this file are made available subject to the terms of
* either of the following licenses * either of the following licenses
@@ -77,7 +77,7 @@ namespace
{ {
//================================================================================================== //==================================================================================================
static typelib_TypeClass cpp2uno_call( void cpp2uno_call(
bridges::cpp_uno::shared::CppInterfaceProxy * pThis, bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
const typelib_TypeDescription * pMemberTypeDescr, const typelib_TypeDescription * pMemberTypeDescr,
typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
@@ -209,8 +209,6 @@ static typelib_TypeClass cpp2uno_call(
CPPU_CURRENT_NAMESPACE::raiseException( CPPU_CURRENT_NAMESPACE::raiseException(
&aUnoExc, pThis->getBridge()->getUno2Cpp() ); &aUnoExc, pThis->getBridge()->getUno2Cpp() );
// has to destruct the any // has to destruct the any
// is here for dummy
return typelib_TypeClass_VOID;
} }
else // else no exception occured... else // else no exception occured...
{ {
@@ -247,22 +245,16 @@ static typelib_TypeClass cpp2uno_call(
} }
if (pReturnTypeDescr) if (pReturnTypeDescr)
{ {
typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
return eRet;
} }
else
return typelib_TypeClass_VOID;
} }
} }
//================================================================================================== //==================================================================================================
static typelib_TypeClass cpp_mediate( extern "C" void cpp_vtable_call(
sal_Int32 nFunctionIndex, int nFunctionIndex, int nVtableOffset, void** pCallStack,
sal_Int32 nVtableOffset, sal_Int64 nRegReturn )
void ** pCallStack,
sal_Int64 * pRegisterReturn /* space for register return */ )
{ {
OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
@@ -298,7 +290,6 @@ static typelib_TypeClass cpp_mediate(
TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
typelib_TypeClass eRet;
switch (aMemberDescr.get()->eTypeClass) switch (aMemberDescr.get()->eTypeClass)
{ {
case typelib_TypeClass_INTERFACE_ATTRIBUTE: case typelib_TypeClass_INTERFACE_ATTRIBUTE:
@@ -306,11 +297,11 @@ static typelib_TypeClass cpp_mediate(
if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
{ {
// is GET method // is GET method
eRet = cpp2uno_call( cpp2uno_call(
pCppI, aMemberDescr.get(), pCppI, aMemberDescr.get(),
((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
0, 0, // no params 0, 0, // no params
pCallStack, pRegisterReturn ); pCallStack, &nRegReturn );
} }
else else
{ {
@@ -321,11 +312,11 @@ static typelib_TypeClass cpp_mediate(
aParam.bIn = sal_True; aParam.bIn = sal_True;
aParam.bOut = sal_False; aParam.bOut = sal_False;
eRet = cpp2uno_call( cpp2uno_call(
pCppI, aMemberDescr.get(), pCppI, aMemberDescr.get(),
0, // indicates void return 0, // indicates void return
1, &aParam, 1, &aParam,
pCallStack, pRegisterReturn ); pCallStack, &nRegReturn );
} }
break; break;
} }
@@ -336,11 +327,9 @@ static typelib_TypeClass cpp_mediate(
{ {
case 1: // acquire() case 1: // acquire()
pCppI->acquireProxy(); // non virtual call! pCppI->acquireProxy(); // non virtual call!
eRet = typelib_TypeClass_VOID;
break; break;
case 2: // release() case 2: // release()
pCppI->releaseProxy(); // non virtual call! pCppI->releaseProxy(); // non virtual call!
eRet = typelib_TypeClass_VOID;
break; break;
case 0: // queryInterface() opt case 0: // queryInterface() opt
{ {
@@ -361,20 +350,19 @@ static typelib_TypeClass cpp_mediate(
&pInterface, pTD, cpp_acquire ); &pInterface, pTD, cpp_acquire );
pInterface->release(); pInterface->release();
TYPELIB_DANGER_RELEASE( pTD ); TYPELIB_DANGER_RELEASE( pTD );
*(void **)pRegisterReturn = pCallStack[1]; *(void **)&nRegReturn = pCallStack[1];
eRet = typelib_TypeClass_ANY;
break; break;
} }
TYPELIB_DANGER_RELEASE( pTD ); TYPELIB_DANGER_RELEASE( pTD );
} }
} // else perform queryInterface() } // else perform queryInterface()
default: default:
eRet = cpp2uno_call( cpp2uno_call(
pCppI, aMemberDescr.get(), pCppI, aMemberDescr.get(),
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
pCallStack, pRegisterReturn ); pCallStack, &nRegReturn );
} }
break; break;
} }
@@ -383,72 +371,55 @@ static typelib_TypeClass cpp_mediate(
throw RuntimeException( throw RuntimeException(
rtl::OUString::createFromAscii("no member description found!"), rtl::OUString::createFromAscii("no member description found!"),
(XInterface *)pThis ); (XInterface *)pThis );
// is here for dummy
eRet = typelib_TypeClass_VOID;
} }
} }
return eRet;
} }
//================================================================================================== //==================================================================================================
/** extern "C" void privateSnippetExecutorGeneral();
* is called on incoming vtable calls extern "C" void privateSnippetExecutorVoid();
* (called by asm snippets) extern "C" void privateSnippetExecutorHyper();
*/ extern "C" void privateSnippetExecutorFloat();
static void cpp_vtable_call( extern "C" void privateSnippetExecutorDouble();
int nFunctionIndex, int nVtableOffset, void** pCallStack ) extern "C" void privateSnippetExecutorClass();
__attribute__((regparm(3))); extern "C" typedef void (*PrivateSnippetExecutor)();
void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** pCallStack ) int const codeSnippetSize = 16;
{
volatile long nRegReturn[2];
typelib_TypeClass aType = cpp_mediate(
nFunctionIndex, nVtableOffset, pCallStack, (sal_Int64*)nRegReturn );
switch( aType )
{
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
__asm__( "movl %1, %%edx\n\t"
"movl %0, %%eax\n"
: : "m"(nRegReturn[0]), "m"(nRegReturn[1]) );
break;
case typelib_TypeClass_FLOAT:
__asm__( "flds %0\n\t"
"fstp %%st(0)\n\t"
"flds %0\n"
: : "m"(*(float *)nRegReturn) );
break;
case typelib_TypeClass_DOUBLE:
__asm__( "fldl %0\n\t"
"fstp %%st(0)\n\t"
"fldl %0\n"
: : "m"(*(double *)nRegReturn) );
break;
// case typelib_TypeClass_UNSIGNED_SHORT:
// case typelib_TypeClass_SHORT:
// __asm__( "movswl %0, %%eax\n"
// : : "m"(nRegReturn) );
// break;
default:
__asm__( "movl %0, %%eax\n"
: : "m"(nRegReturn[0]) );
break;
}
}
//==================================================================================================
int const codeSnippetSize = 20;
unsigned char * codeSnippet( unsigned char * codeSnippet(
unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
bool simpleRetType) typelib_TypeClass returnTypeClass)
{ {
if (!simpleRetType) { if (!bridges::cpp_uno::shared::isSimpleType(returnTypeClass)) {
functionIndex |= 0x80000000; functionIndex |= 0x80000000;
} }
PrivateSnippetExecutor exec;
switch (returnTypeClass) {
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_STRING:
case typelib_TypeClass_TYPE:
case typelib_TypeClass_ANY:
case typelib_TypeClass_SEQUENCE:
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_INTERFACE:
exec = privateSnippetExecutorClass;
break;
default:
exec = privateSnippetExecutorGeneral;
break;
}
unsigned char * p = code; unsigned char * p = code;
OSL_ASSERT(sizeof (sal_Int32) == 4); OSL_ASSERT(sizeof (sal_Int32) == 4);
// mov function_index, %eax: // mov function_index, %eax:
@@ -459,13 +430,10 @@ unsigned char * codeSnippet(
*p++ = 0xBA; *p++ = 0xBA;
*reinterpret_cast< sal_Int32 * >(p) = vtableOffset; *reinterpret_cast< sal_Int32 * >(p) = vtableOffset;
p += sizeof (sal_Int32); p += sizeof (sal_Int32);
// mov %esp, %ecx: // jmp privateSnippetExecutor:
*p++ = 0x89;
*p++ = 0xE1;
// jmp cpp_vtable_call:
*p++ = 0xE9; *p++ = 0xE9;
*reinterpret_cast< sal_Int32 * >(p) *reinterpret_cast< sal_Int32 * >(p)
= ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int32); = ((unsigned char *) exec) - p - sizeof (sal_Int32);
p += sizeof (sal_Int32); p += sizeof (sal_Int32);
OSL_ASSERT(p - code <= codeSnippetSize); OSL_ASSERT(p - code <= codeSnippetSize);
return code + codeSnippetSize; return code + codeSnippetSize;
@@ -504,17 +472,17 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
*slots++ = code; *slots++ = code;
code = codeSnippet( code = codeSnippet(
code, functionOffset++, vtableOffset, code, functionOffset++, vtableOffset,
bridges::cpp_uno::shared::isSimpleType( reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
reinterpret_cast< member)->pAttributeTypeRef->eTypeClass);
typelib_InterfaceAttributeTypeDescription * >(
member)->pAttributeTypeRef));
// Setter: // Setter:
if (!reinterpret_cast< if (!reinterpret_cast<
typelib_InterfaceAttributeTypeDescription * >( typelib_InterfaceAttributeTypeDescription * >(
member)->bReadOnly) member)->bReadOnly)
{ {
*slots++ = code; *slots++ = code;
code = codeSnippet(code, functionOffset++, vtableOffset, true); code = codeSnippet(
code, functionOffset++, vtableOffset,
typelib_TypeClass_VOID);
} }
break; break;
@@ -522,10 +490,8 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
*slots++ = code; *slots++ = code;
code = codeSnippet( code = codeSnippet(
code, functionOffset++, vtableOffset, code, functionOffset++, vtableOffset,
bridges::cpp_uno::shared::isSimpleType( reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
reinterpret_cast< member)->pReturnTypeRef->eTypeClass);
typelib_InterfaceMethodTypeDescription * >(
member)->pReturnTypeRef));
break; break;
default: default: