From afde0ef9fe127393ab445cb6798ce718245734b4 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Fri, 30 Mar 2012 11:13:40 +0200 Subject: MinGW: callVirtualMethod needs same treatment as on gcc3_linux_x86_64 ...for reasons that are yet unclear to me. --- .../cpp_uno/mingw_intel/callvirtualmethod.cxx | 148 +++++++++++++++++++++ .../cpp_uno/mingw_intel/callvirtualmethod.hxx | 49 +++++++ bridges/source/cpp_uno/mingw_intel/makefile.mk | 1 + bridges/source/cpp_uno/mingw_intel/share.hxx | 3 + bridges/source/cpp_uno/mingw_intel/uno2cpp.cxx | 117 +--------------- 5 files changed, 203 insertions(+), 115 deletions(-) create mode 100644 bridges/source/cpp_uno/mingw_intel/callvirtualmethod.cxx create mode 100644 bridges/source/cpp_uno/mingw_intel/callvirtualmethod.hxx (limited to 'bridges/source/cpp_uno/mingw_intel') diff --git a/bridges/source/cpp_uno/mingw_intel/callvirtualmethod.cxx b/bridges/source/cpp_uno/mingw_intel/callvirtualmethod.cxx new file mode 100644 index 000000000000..b8c17fb2fd14 --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/callvirtualmethod.cxx @@ -0,0 +1,148 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "sal/config.h" + +#include "cppu/macros.hxx" +#include "osl/diagnose.h" +#include "sal/types.h" +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" + +#include "callvirtualmethod.hxx" +#include "share.hxx" +#include "smallstruct.hxx" + +// For some reason, callVirtualMethod needs to be in a source file of its own, +// so that stack unwinding upon a thrown exception from within the asm block +// call works, at least with GCC 4.7.0 and --enable-dbgutil. + +// The call instruction within the asm section of callVirtualMethod may throw +// exceptions. So that the compiler handles this correctly, it is important +// that (a) callVirtualMethod might call dummy_can_throw_anything (although this +// never happens at runtime), which in turn can throw exceptions, and (b) +// callVirtualMethod is not inlined at its call site (so that any exceptions are +// caught which are thrown from the instruction calling callVirtualMethod). [It +// is unclear how much of this comment is still relevent -- see the above +// comment.] +void CPPU_CURRENT_NAMESPACE::callVirtualMethod( + void * pAdjustedThisPtr, sal_Int32 nVtableIndex, void * pRegisterReturn, + typelib_TypeDescription const * returnType, sal_Int32 * pStackLongs, + sal_Int32 nStackLongs) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); + OSL_ENSURE( (sizeof(void *) == 4) && (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); + + // never called + if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something + + volatile long edx = 0, eax = 0; // for register returns + void * stackptr; + asm volatile ( + "mov %%esp, %6\n\t" + // copy values + "mov %0, %%eax\n\t" + "mov %%eax, %%edx\n\t" + "dec %%edx\n\t" + "shl $2, %%edx\n\t" + "add %1, %%edx\n" + "Lcopy:\n\t" + "pushl 0(%%edx)\n\t" + "sub $4, %%edx\n\t" + "dec %%eax\n\t" + "jne Lcopy\n\t" + // do the actual call + "mov %2, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "mov %3, %%eax\n\t" + "shl $2, %%eax\n\t" + "add %%eax, %%edx\n\t" + "mov 0(%%edx), %%edx\n\t" + "call *%%edx\n\t" + // save return registers + "mov %%eax, %4\n\t" + "mov %%edx, %5\n\t" + // cleanup stack + "mov %6, %%esp\n\t" + : + : "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr), + "m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr) + : "eax", "ecx", "edx" ); + switch( returnType->eTypeClass ) + { + case typelib_TypeClass_VOID: + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + ((long*)pRegisterReturn)[1] = edx; + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + ((long*)pRegisterReturn)[0] = eax; + break; + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + *(unsigned short*)pRegisterReturn = eax; + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + *(unsigned char*)pRegisterReturn = eax; + break; + case typelib_TypeClass_FLOAT: + asm ( "fstps %0" : : "m"(*(char *)pRegisterReturn) ); + break; + case typelib_TypeClass_DOUBLE: + asm ( "fstpl %0\n\t" : : "m"(*(char *)pRegisterReturn) ); + break; + case typelib_TypeClass_STRUCT: + if (bridges::cpp_uno::shared::isSmallStruct(returnType)) { + if (returnType->nSize <= 1) { + *(unsigned char*)pRegisterReturn = eax; + } + else if (returnType->nSize <= 2) { + *(unsigned short*)pRegisterReturn = eax; + } + else if (returnType->nSize <= 8) { + ((long*)pRegisterReturn)[0] = eax; + if (returnType->nSize > 4) { + ((long*)pRegisterReturn)[1] = edx; + } + } + } + break; + default: + break; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/mingw_intel/callvirtualmethod.hxx b/bridges/source/cpp_uno/mingw_intel/callvirtualmethod.hxx new file mode 100644 index 000000000000..d26821b2f97d --- /dev/null +++ b/bridges/source/cpp_uno/mingw_intel/callvirtualmethod.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_MINGW_INTEL_CALLVIRTUALMETHOD_HXX +#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_MINGW_INTEL_CALLVIRTUALMETHOD_HXX + +#include "sal/config.h" + +#include "cppu/macros.hxx" +#include "sal/types.h" +#include "typelib/typedescription.h" + +namespace CPPU_CURRENT_NAMESPACE { + +void callVirtualMethod( + void * pAdjustedThisPtr, sal_Int32 nVtableIndex, void * pRegisterReturn, + typelib_TypeDescription const * returnType, sal_Int32 * pStackLongs, + sal_Int32 nStackLongs); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/mingw_intel/makefile.mk b/bridges/source/cpp_uno/mingw_intel/makefile.mk index 51a995129240..ba1040596adb 100644 --- a/bridges/source/cpp_uno/mingw_intel/makefile.mk +++ b/bridges/source/cpp_uno/mingw_intel/makefile.mk @@ -63,6 +63,7 @@ SLOFILES= \ $(SLO)$/dllinit.obj \ $(SLO)$/smallstruct.obj \ $(SLO)$/except.obj \ + $(SLO)$/callvirtualmethod.obj \ $(SLO)$/cpp2uno.obj \ $(SLO)$/uno2cpp.obj \ $(SLO)$/call.obj diff --git a/bridges/source/cpp_uno/mingw_intel/share.hxx b/bridges/source/cpp_uno/mingw_intel/share.hxx index 58fb72dc06cd..e813f49b7ba6 100644 --- a/bridges/source/cpp_uno/mingw_intel/share.hxx +++ b/bridges/source/cpp_uno/mingw_intel/share.hxx @@ -32,6 +32,9 @@ #include #include +#include "cppu/macros.hxx" +#include "uno/any2.h" + namespace CPPU_CURRENT_NAMESPACE { diff --git a/bridges/source/cpp_uno/mingw_intel/uno2cpp.cxx b/bridges/source/cpp_uno/mingw_intel/uno2cpp.cxx index d2ae05721b3d..87592da53f25 100644 --- a/bridges/source/cpp_uno/mingw_intel/uno2cpp.cxx +++ b/bridges/source/cpp_uno/mingw_intel/uno2cpp.cxx @@ -37,6 +37,7 @@ #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" #include "bridges/cpp_uno/shared/vtables.hxx" +#include "callvirtualmethod.hxx" #include "share.hxx" #include "smallstruct.hxx" @@ -46,120 +47,6 @@ using namespace ::com::sun::star::uno; namespace { -//================================================================================================== -// The call instruction within the asm section of callVirtualMethod may throw -// exceptions. So that the compiler handles this correctly, it is important -// that (a) callVirtualMethod might call dummy_can_throw_anything (although this -// never happens at runtime), which in turn can throw exceptions, and (b) -// callVirtualMethod is not inlined at its call site (so that any exceptions are -// caught which are thrown from the instruction calling callVirtualMethod): -void callVirtualMethod( - void * pAdjustedThisPtr, - sal_Int32 nVtableIndex, - void * pRegisterReturn, - typelib_TypeDescription const * returnType, - sal_Int32 * pStackLongs, - sal_Int32 nStackLongs ) __attribute__((noinline)); - -void callVirtualMethod( - void * pAdjustedThisPtr, - sal_Int32 nVtableIndex, - void * pRegisterReturn, - typelib_TypeDescription const * returnType, - sal_Int32 * pStackLongs, - sal_Int32 nStackLongs ) -{ - // parameter list is mixed list of * and values - // reference parameters are pointers - - OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); - OSL_ENSURE( (sizeof(void *) == 4) && (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); - OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" ); - - // never called - if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something - - volatile long edx = 0, eax = 0; // for register returns - void * stackptr; - asm volatile ( - "mov %%esp, %6\n\t" - // copy values - "mov %0, %%eax\n\t" - "mov %%eax, %%edx\n\t" - "dec %%edx\n\t" - "shl $2, %%edx\n\t" - "add %1, %%edx\n" - "Lcopy:\n\t" - "pushl 0(%%edx)\n\t" - "sub $4, %%edx\n\t" - "dec %%eax\n\t" - "jne Lcopy\n\t" - // do the actual call - "mov %2, %%edx\n\t" - "mov 0(%%edx), %%edx\n\t" - "mov %3, %%eax\n\t" - "shl $2, %%eax\n\t" - "add %%eax, %%edx\n\t" - "mov 0(%%edx), %%edx\n\t" - "call *%%edx\n\t" - // save return registers - "mov %%eax, %4\n\t" - "mov %%edx, %5\n\t" - // cleanup stack - "mov %6, %%esp\n\t" - : - : "m"(nStackLongs), "m"(pStackLongs), "m"(pAdjustedThisPtr), - "m"(nVtableIndex), "m"(eax), "m"(edx), "m"(stackptr) - : "eax", "ecx", "edx" ); - switch( returnType->eTypeClass ) - { - case typelib_TypeClass_VOID: - break; - case typelib_TypeClass_HYPER: - case typelib_TypeClass_UNSIGNED_HYPER: - ((long*)pRegisterReturn)[1] = edx; - case typelib_TypeClass_LONG: - case typelib_TypeClass_UNSIGNED_LONG: - case typelib_TypeClass_CHAR: - case typelib_TypeClass_ENUM: - ((long*)pRegisterReturn)[0] = eax; - break; - case typelib_TypeClass_SHORT: - case typelib_TypeClass_UNSIGNED_SHORT: - *(unsigned short*)pRegisterReturn = eax; - break; - case typelib_TypeClass_BOOLEAN: - case typelib_TypeClass_BYTE: - *(unsigned char*)pRegisterReturn = eax; - break; - case typelib_TypeClass_FLOAT: - asm ( "fstps %0" : : "m"(*(char *)pRegisterReturn) ); - break; - case typelib_TypeClass_DOUBLE: - asm ( "fstpl %0\n\t" : : "m"(*(char *)pRegisterReturn) ); - break; - case typelib_TypeClass_STRUCT: - if (bridges::cpp_uno::shared::isSmallStruct(returnType)) { - if (returnType->nSize <= 1) { - *(unsigned char*)pRegisterReturn = eax; - } - else if (returnType->nSize <= 2) { - *(unsigned short*)pRegisterReturn = eax; - } - else if (returnType->nSize <= 8) { - ((long*)pRegisterReturn)[0] = eax; - if (returnType->nSize > 4) { - ((long*)pRegisterReturn)[1] = edx; - } - } - } - break; - default: - break; - } -} - -//================================================================================================== static void cpp_call( bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, bridges::cpp_uno::shared::VtableSlot aVtableSlot, @@ -299,7 +186,7 @@ static void cpp_call( try { OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic)" ); - callVirtualMethod( + CPPU_CURRENT_NAMESPACE::callVirtualMethod( pAdjustedThisPtr, aVtableSlot.index, pCppReturn, pReturnTypeDescr, (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); -- cgit