summaryrefslogtreecommitdiff
path: root/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx')
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx81
1 files changed, 50 insertions, 31 deletions
diff --git a/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx
index 29212988f78d..14673ab7d5e2 100644
--- a/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_x86-64/cpp2uno.cxx
@@ -18,10 +18,6 @@
*/
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <rtl/alloc.h>
#include <sal/log.hxx>
#include <com/sun/star/uno/genfunc.hxx>
@@ -37,9 +33,12 @@
#include "abi.hxx"
#include "call.hxx"
-#include "rtti.hxx"
#include "share.hxx"
+#if !ENABLE_RUNTIME_OPTIMIZATIONS
+#include "rtti.hxx"
+#endif
+
using namespace ::com::sun::star::uno;
// Perform the UNO call
@@ -54,7 +53,9 @@ using namespace ::com::sun::star::uno;
// [ret *] is present when we are returning a structure bigger than 16 bytes
// Simple types are returned in rax, rdx (int), or xmm0, xmm1 (fp).
// Similarly structures <= 16 bytes are in rax, rdx, xmm0, xmm1 as necessary.
-static typelib_TypeClass cpp2uno_call(
+//
+// The return value is the same as for cpp_vtable_call.
+static int cpp2uno_call(
bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
const typelib_TypeDescription * pMemberTypeDescr,
typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
@@ -69,13 +70,16 @@ static typelib_TypeClass cpp2uno_call(
typelib_TypeDescription * pReturnTypeDescr = nullptr;
if (pReturnTypeRef)
TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
+ x86_64::ReturnKind returnKind
+ = (pReturnTypeRef == nullptr || pReturnTypeRef->eTypeClass == typelib_TypeClass_VOID)
+ ? x86_64::ReturnKind::RegistersGeneral : x86_64::getReturnKind(pReturnTypeRef);
void * pUnoReturn = nullptr;
void * pCppReturn = nullptr; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
if ( pReturnTypeDescr )
{
- if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
+ if ( returnKind == x86_64::ReturnKind::Memory )
{
pCppReturn = *gpreg++;
nr_gpr++;
@@ -107,11 +111,12 @@ static typelib_TypeClass cpp2uno_call(
{
const typelib_MethodParameter & rParam = pParams[nPos];
- int nUsedGPR = 0;
- int nUsedSSE = 0;
- bool bFitsRegisters = x86_64::examine_argument( rParam.pTypeRef, false, nUsedGPR, nUsedSSE );
if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) ) // value
{
+ int nUsedGPR = 0;
+ int nUsedSSE = 0;
+ bool bFitsRegisters = x86_64::examine_argument( rParam.pTypeRef, nUsedGPR, nUsedSSE );
+
// Simple types must fit exactly one register on x86_64
assert( bFitsRegisters && ( ( nUsedSSE == 1 && nUsedGPR == 0 ) || ( nUsedSSE == 0 && nUsedGPR == 1 ) ) ); (void)bFitsRegisters;
@@ -136,7 +141,7 @@ static typelib_TypeClass cpp2uno_call(
pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw++;
}
}
- else // struct <= 16 bytes || ptr to complex value || ref
+ else // ref
{
typelib_TypeDescription * pParamTypeDescr = nullptr;
TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
@@ -201,7 +206,7 @@ static typelib_TypeClass cpp2uno_call(
CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
// is here for dummy
- return typelib_TypeClass_VOID;
+ return 0;
}
else // else no exception occurred...
{
@@ -238,17 +243,27 @@ static typelib_TypeClass cpp2uno_call(
}
if ( pReturnTypeDescr )
{
- typelib_TypeClass eRet = pReturnTypeDescr->eTypeClass;
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
- return eRet;
}
- else
- return typelib_TypeClass_VOID;
+ switch (returnKind) {
+ case x86_64::ReturnKind::RegistersFpInt:
+ return 0;
+ case x86_64::ReturnKind::RegistersIntFp:
+ return 1;
+ default:
+ return -1;
+ }
}
}
-
-typelib_TypeClass cpp_vtable_call(
+// Returns -1 for the general case where potential return values from privateSnippetExecutor can be
+// copied from pRegisterReturn to both %rax and %rdx (in that order) and to %xmm0 and %xmm1 (in that
+// order)---each specific return type will only require a subset of that copy operations, but the
+// other copies to those non--callee-saved registers will be redundant and harmless. Returns 0 for
+// the special case where return values from privateSnippetExecutor must be copied from
+// pRegisterReturn to %xmm0 and %rax (in that order). Returns 1 for the special case where return
+// privateSnippetExecutor must be copied from pRegisterReturn to %rax and %xmm0 (in that order).
+int cpp_vtable_call(
sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
void ** gpreg, void ** fpreg, void ** ovrflw,
sal_uInt64 * pRegisterReturn /* space for register return */ )
@@ -293,7 +308,7 @@ typelib_TypeClass cpp_vtable_call(
TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
- typelib_TypeClass eRet;
+ int eRet;
switch ( aMemberDescr.get()->eTypeClass )
{
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
@@ -330,11 +345,11 @@ typelib_TypeClass cpp_vtable_call(
{
case 1: // acquire()
pCppI->acquireProxy(); // non virtual call!
- eRet = typelib_TypeClass_VOID;
+ eRet = 0;
break;
case 2: // release()
pCppI->releaseProxy(); // non virtual call!
- eRet = typelib_TypeClass_VOID;
+ eRet = 0;
break;
case 0: // queryInterface() opt
{
@@ -358,7 +373,7 @@ typelib_TypeClass cpp_vtable_call(
TYPELIB_DANGER_RELEASE( pTD );
reinterpret_cast<void **>( pRegisterReturn )[0] = gpreg[0];
- eRet = typelib_TypeClass_ANY;
+ eRet = 0;
break;
}
TYPELIB_DANGER_RELEASE( pTD );
@@ -426,16 +441,10 @@ static unsigned char * codeSnippet( unsigned char * code,
// jmpq *%r11
*reinterpret_cast<sal_uInt32 *>( code + 20 ) = 0x00e3ff49;
-#if OSL_DEBUG_LEVEL > 1
- fprintf(stderr,
- "==> codeSnippet, functionIndex=%d%s, vtableOffset=%d\n",
- nFunctionIndex, (bHasHiddenParam ? "|0x80000000":""), nVtableOffset);
-#endif
-
return code + codeSnippetSize;
}
-struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void const * fn; };
bridges::cpp_uno::shared::VtableFactory::Slot *
bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
@@ -449,17 +458,27 @@ std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(
return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
}
+#if ENABLE_RUNTIME_OPTIMIZATIONS
+namespace {
+// Some dummy type whose RTTI is used in the synthesized proxy vtables to make uses of dynamic_cast
+// on such proxy objects not crash:
+struct ProxyRtti {};
+}
+#endif
+
bridges::cpp_uno::shared::VtableFactory::Slot *
bridges::cpp_uno::shared::VtableFactory::initializeBlock(
void * block, sal_Int32 slotCount, sal_Int32 vtableNumber,
typelib_InterfaceTypeDescription * type)
{
Slot * slots = mapBlockToVtable(block);
- slots[-2].fn = reinterpret_cast<void *>(-(vtableNumber * sizeof (void *)));
#if ENABLE_RUNTIME_OPTIMIZATIONS
- slots[-1].fn = nullptr;
+ slots[-2].fn = nullptr;
+ slots[-1].fn = &typeid(ProxyRtti);
+ (void)vtableNumber;
(void)type;
#else
+ slots[-2].fn = reinterpret_cast<void *>(-(vtableNumber * sizeof (void *)));
slots[-1].fn = x86_64::getRtti(type->aBase);
#endif
return slots + slotCount;