Make exceptions work better in the x86-64 MacOSX C++-UNO bridge
Putting the privateSnippetExecutor() assembly code as inline asm inside an otherwise empty C++ function helps, for some reason. Use the actual _Unwnd_Exception and __cxa_exception definitions as used by Apple (from opensource.apple.com libunwind and libcppabi sources) instead of guessing. Change-Id: I1ef22a9c0c664d3a357b9a6474406141f53cc490
This commit is contained in:
@@ -46,12 +46,9 @@ $(eval $(call gb_Library_use_libraries,gcc3_uno,\
|
|||||||
sal \
|
sal \
|
||||||
))
|
))
|
||||||
|
|
||||||
$(eval $(call gb_Library_add_asmobjects,gcc3_uno,\
|
|
||||||
bridges/source/cpp_uno/gcc3_macosx_x86-64/call \
|
|
||||||
))
|
|
||||||
|
|
||||||
$(eval $(call gb_Library_add_exception_objects,gcc3_uno,\
|
$(eval $(call gb_Library_add_exception_objects,gcc3_uno,\
|
||||||
bridges/source/cpp_uno/gcc3_macosx_x86-64/abi \
|
bridges/source/cpp_uno/gcc3_macosx_x86-64/abi \
|
||||||
|
bridges/source/cpp_uno/gcc3_macosx_x86-64/call \
|
||||||
bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod \
|
bridges/source/cpp_uno/gcc3_macosx_x86-64/callvirtualmethod \
|
||||||
bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno \
|
bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno \
|
||||||
bridges/source/cpp_uno/gcc3_macosx_x86-64/except \
|
bridges/source/cpp_uno/gcc3_macosx_x86-64/except \
|
||||||
|
73
bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx
Normal file
73
bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the LibreOffice project.
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following license notice:
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed
|
||||||
|
* with this work for additional information regarding copyright
|
||||||
|
* ownership. The ASF licenses this file to you under the Apache
|
||||||
|
* License, Version 2.0 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
privateSnippetExecutor()
|
||||||
|
{
|
||||||
|
asm volatile
|
||||||
|
(
|
||||||
|
" subq $160, %rsp\n"
|
||||||
|
|
||||||
|
" movq %r10, -152(%rbp) # Save (nVtableOffset << 32) + nFunctionIndex\n"
|
||||||
|
|
||||||
|
" movq %rdi, -112(%rbp) # Save GP registers\n"
|
||||||
|
" movq %rsi, -104(%rbp)\n"
|
||||||
|
" movq %rdx, -96(%rbp)\n"
|
||||||
|
" movq %rcx, -88(%rbp)\n"
|
||||||
|
" movq %r8 , -80(%rbp)\n"
|
||||||
|
" movq %r9 , -72(%rbp)\n"
|
||||||
|
|
||||||
|
" movsd %xmm0, -64(%rbp) # Save FP registers\n"
|
||||||
|
" movsd %xmm1, -56(%rbp)\n"
|
||||||
|
" movsd %xmm2, -48(%rbp)\n"
|
||||||
|
" movsd %xmm3, -40(%rbp)\n"
|
||||||
|
" movsd %xmm4, -32(%rbp)\n"
|
||||||
|
" movsd %xmm5, -24(%rbp)\n"
|
||||||
|
" movsd %xmm6, -16(%rbp)\n"
|
||||||
|
" movsd %xmm7, -8(%rbp)\n"
|
||||||
|
|
||||||
|
" leaq -144(%rbp), %r9 # 6th param: sal_uInt64 * pRegisterReturn\n"
|
||||||
|
" leaq 16(%rbp), %r8 # 5rd param: void ** ovrflw\n"
|
||||||
|
" leaq -64(%rbp), %rcx # 4th param: void ** fpreg\n"
|
||||||
|
" leaq -112(%rbp), %rdx # 3rd param: void ** gpreg\n"
|
||||||
|
" movl -148(%rbp), %esi # 2nd param: sal_int32 nVtableOffset\n"
|
||||||
|
" movl -152(%rbp), %edi # 1st param: sal_int32 nFunctionIndex\n"
|
||||||
|
|
||||||
|
" call _cpp_vtable_call\n"
|
||||||
|
|
||||||
|
" cmp $10, %rax # typelib_TypeClass_FLOAT\n"
|
||||||
|
" je .Lfloat\n"
|
||||||
|
" cmp $11, %rax # typelib_TypeClass_DOUBLE\n"
|
||||||
|
" je .Lfloat\n"
|
||||||
|
|
||||||
|
" movq -144(%rbp), %rax # Return value (int case)\n"
|
||||||
|
" movq -136(%rbp), %rdx # Return value (int case)\n"
|
||||||
|
" movq -144(%rbp), %xmm0 # Return value (int case)\n"
|
||||||
|
" movq -136(%rbp), %xmm1 # Return value (int case)\n"
|
||||||
|
" jmp .Lfinish\n"
|
||||||
|
|
||||||
|
".Lfloat:\n"
|
||||||
|
" movlpd -144(%rbp), %xmm0 # Return value (float/double case)\n"
|
||||||
|
|
||||||
|
".Lfinish:\n"
|
||||||
|
" addq $160, %rsp\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the LibreOffice project.
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*
|
|
||||||
* This file incorporates work covered by the following license notice:
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed
|
|
||||||
* with this work for additional information regarding copyright
|
|
||||||
* ownership. The ASF licenses this file to you under the Apache
|
|
||||||
* License, Version 2.0 (the "License"); you may not use this file
|
|
||||||
* except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
||||||
*/
|
|
||||||
|
|
||||||
.text
|
|
||||||
.align 4, 0x90
|
|
||||||
.globl _privateSnippetExecutor
|
|
||||||
_privateSnippetExecutor:
|
|
||||||
.cfi_startproc
|
|
||||||
.LFB3:
|
|
||||||
pushq %rbp
|
|
||||||
.LCFI0:
|
|
||||||
.cfi_def_cfa_offset 16
|
|
||||||
.cfi_offset %rbp, -16
|
|
||||||
movq %rsp, %rbp
|
|
||||||
.LCFI1:
|
|
||||||
subq $160, %rsp
|
|
||||||
.LCFI2:
|
|
||||||
.cfi_def_cfa_register %rbp
|
|
||||||
movq %r10, -152(%rbp) # Save (nVtableOffset << 32) + nFunctionIndex
|
|
||||||
|
|
||||||
movq %rdi, -112(%rbp) # Save GP registers
|
|
||||||
movq %rsi, -104(%rbp)
|
|
||||||
movq %rdx, -96(%rbp)
|
|
||||||
movq %rcx, -88(%rbp)
|
|
||||||
movq %r8 , -80(%rbp)
|
|
||||||
movq %r9 , -72(%rbp)
|
|
||||||
|
|
||||||
movsd %xmm0, -64(%rbp) # Save FP registers
|
|
||||||
movsd %xmm1, -56(%rbp)
|
|
||||||
movsd %xmm2, -48(%rbp)
|
|
||||||
movsd %xmm3, -40(%rbp)
|
|
||||||
movsd %xmm4, -32(%rbp)
|
|
||||||
movsd %xmm5, -24(%rbp)
|
|
||||||
movsd %xmm6, -16(%rbp)
|
|
||||||
movsd %xmm7, -8(%rbp)
|
|
||||||
|
|
||||||
leaq -144(%rbp), %r9 # 6th param: sal_uInt64 * pRegisterReturn
|
|
||||||
leaq 16(%rbp), %r8 # 5rd param: void ** ovrflw
|
|
||||||
leaq -64(%rbp), %rcx # 4th param: void ** fpreg
|
|
||||||
leaq -112(%rbp), %rdx # 3rd param: void ** gpreg
|
|
||||||
movl -148(%rbp), %esi # 2nd param: sal_int32 nVtableOffset
|
|
||||||
movl -152(%rbp), %edi # 1st param: sal_int32 nFunctionIndex
|
|
||||||
|
|
||||||
call _cpp_vtable_call
|
|
||||||
|
|
||||||
cmp $10, %rax # typelib_TypeClass_FLOAT
|
|
||||||
je .Lfloat
|
|
||||||
cmp $11, %rax # typelib_TypeClass_DOUBLE
|
|
||||||
je .Lfloat
|
|
||||||
|
|
||||||
movq -144(%rbp), %rax # Return value (int case)
|
|
||||||
movq -136(%rbp), %rdx # Return value (int case)
|
|
||||||
movq -144(%rbp), %xmm0 # Return value (int case)
|
|
||||||
movq -136(%rbp), %xmm1 # Return value (int case)
|
|
||||||
jmp .Lfinish
|
|
||||||
.Lfloat:
|
|
||||||
movlpd -144(%rbp), %xmm0 # Return value (float/double case)
|
|
||||||
|
|
||||||
.Lfinish:
|
|
||||||
leave
|
|
||||||
ret
|
|
||||||
.cfi_endproc
|
|
||||||
|
|
||||||
.subsections_via_symbols
|
|
@@ -396,7 +396,7 @@ extern "C" typelib_TypeClass cpp_vtable_call(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
extern "C" void privateSnippetExecutor( ... );
|
extern "C" void privateSnippetExecutor();
|
||||||
|
|
||||||
const int codeSnippetSize = 24;
|
const int codeSnippetSize = 24;
|
||||||
|
|
||||||
|
@@ -35,41 +35,102 @@
|
|||||||
namespace CPPU_CURRENT_NAMESPACE
|
namespace CPPU_CURRENT_NAMESPACE
|
||||||
{
|
{
|
||||||
|
|
||||||
// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h
|
// From opensource.apple.com: libunwind-35.1/include/unwind.h
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
_URC_NO_REASON = 0,
|
||||||
|
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
|
||||||
|
_URC_FATAL_PHASE2_ERROR = 2,
|
||||||
|
_URC_FATAL_PHASE1_ERROR = 3,
|
||||||
|
_URC_NORMAL_STOP = 4,
|
||||||
|
_URC_END_OF_STACK = 5,
|
||||||
|
_URC_HANDLER_FOUND = 6,
|
||||||
|
_URC_INSTALL_CONTEXT = 7,
|
||||||
|
_URC_CONTINUE_UNWIND = 8
|
||||||
|
} _Unwind_Reason_Code;
|
||||||
|
|
||||||
struct _Unwind_Exception
|
struct _Unwind_Exception
|
||||||
{
|
{
|
||||||
unsigned exception_class __attribute__((__mode__(__DI__)));
|
uint64_t exception_class;
|
||||||
void * exception_cleanup;
|
void (*exception_cleanup)(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc);
|
||||||
unsigned private_1 __attribute__((__mode__(__word__)));
|
uintptr_t private_1; // non-zero means forced unwind
|
||||||
unsigned private_2 __attribute__((__mode__(__word__)));
|
uintptr_t private_2; // holds sp that phase1 found for phase2 to use
|
||||||
} __attribute__((__aligned__));
|
#if !__LP64__
|
||||||
|
// The gcc implementation of _Unwind_Exception used attribute mode on the above fields
|
||||||
|
// which had the side effect of causing this whole struct to round up to 32 bytes in size.
|
||||||
|
// To be more explicit, we add pad fields added for binary compatibility.
|
||||||
|
uint32_t reserved[3];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// From libcppabi-24.2/include/unwind-cxx.h
|
||||||
|
|
||||||
|
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
|
||||||
|
|
||||||
|
// A C++ exception object consists of a header, which is a wrapper around
|
||||||
|
// an unwind object header with additional C++ specific information,
|
||||||
|
// followed by the exception object itself.
|
||||||
|
|
||||||
struct __cxa_exception
|
struct __cxa_exception
|
||||||
{
|
{
|
||||||
::std::type_info *exceptionType;
|
#if __LP64__
|
||||||
|
// This is a new field to support C++ 0x exception_ptr.
|
||||||
|
// For binary compatibility it is at the start of this
|
||||||
|
// struct which is prepended to the object thrown in
|
||||||
|
// __cxa_allocate_exception.
|
||||||
|
size_t referenceCount;
|
||||||
|
#endif
|
||||||
|
// Manage the exception object itself.
|
||||||
|
std::type_info *exceptionType;
|
||||||
void (*exceptionDestructor)(void *);
|
void (*exceptionDestructor)(void *);
|
||||||
|
|
||||||
::std::unexpected_handler unexpectedHandler;
|
// The C++ standard has entertaining rules wrt calling set_terminate
|
||||||
::std::terminate_handler terminateHandler;
|
// and set_unexpected in the middle of the exception cleanup process.
|
||||||
|
std::unexpected_handler unexpectedHandler;
|
||||||
|
std::terminate_handler terminateHandler;
|
||||||
|
|
||||||
|
// The caught exception stack threads through here.
|
||||||
__cxa_exception *nextException;
|
__cxa_exception *nextException;
|
||||||
|
|
||||||
|
// How many nested handlers have caught this exception. A negated
|
||||||
|
// value is a signal that this object has been rethrown.
|
||||||
int handlerCount;
|
int handlerCount;
|
||||||
|
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
// Stack of exceptions in cleanups.
|
||||||
|
__cxa_exception* nextPropagatingException;
|
||||||
|
|
||||||
|
// The nuber of active cleanup handlers for this exception.
|
||||||
|
int propagationCount;
|
||||||
|
#else
|
||||||
|
// Cache parsed handler data from the personality routine Phase 1
|
||||||
|
// for Phase 2 and __cxa_call_unexpected.
|
||||||
int handlerSwitchValue;
|
int handlerSwitchValue;
|
||||||
const unsigned char *actionRecord;
|
const unsigned char *actionRecord;
|
||||||
const unsigned char *languageSpecificData;
|
const unsigned char *languageSpecificData;
|
||||||
void *catchTemp;
|
_Unwind_Ptr catchTemp;
|
||||||
void *adjustedPtr;
|
void *adjustedPtr;
|
||||||
|
#endif
|
||||||
|
#if !__LP64__
|
||||||
|
// This is a new field to support C++ 0x exception_ptr.
|
||||||
|
// For binary compatibility it is placed where the compiler
|
||||||
|
// previously adding padded to 64-bit align unwindHeader.
|
||||||
|
size_t referenceCount;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// The generic exception header. Must be last.
|
||||||
_Unwind_Exception unwindHeader;
|
_Unwind_Exception unwindHeader;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Each thread in a C++ program has access to a __cxa_eh_globals object.
|
||||||
struct __cxa_eh_globals
|
struct __cxa_eh_globals
|
||||||
{
|
{
|
||||||
__cxa_exception *caughtExceptions;
|
__cxa_exception *caughtExceptions;
|
||||||
unsigned int uncaughtExceptions;
|
unsigned int uncaughtExceptions;
|
||||||
|
#ifdef __ARM_EABI_UNWINDER__
|
||||||
|
__cxa_exception* propagatingExceptions;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user