From 9f5227d66bfca9dd2ffc338f68001ad6ba3b485d Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Thu, 27 Sep 2012 22:27:49 +0300 Subject: 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 --- bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx | 73 ++++++++++++++ bridges/source/cpp_uno/gcc3_macosx_x86-64/call.s | 79 ---------------- .../source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx | 2 +- .../source/cpp_uno/gcc3_macosx_x86-64/share.hxx | 105 ++++++++++++++++----- 4 files changed, 157 insertions(+), 102 deletions(-) create mode 100644 bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx delete mode 100644 bridges/source/cpp_uno/gcc3_macosx_x86-64/call.s (limited to 'bridges/source') diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx new file mode 100644 index 000000000000..96834dae6e51 --- /dev/null +++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.cxx @@ -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: */ diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.s b/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.s deleted file mode 100644 index 8b8072ff049c..000000000000 --- a/bridges/source/cpp_uno/gcc3_macosx_x86-64/call.s +++ /dev/null @@ -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 diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx index 89ab4624911a..bc194c4342e4 100644 --- a/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/cpp2uno.cxx @@ -396,7 +396,7 @@ extern "C" typelib_TypeClass cpp_vtable_call( } //================================================================================================== -extern "C" void privateSnippetExecutor( ... ); +extern "C" void privateSnippetExecutor(); const int codeSnippetSize = 24; diff --git a/bridges/source/cpp_uno/gcc3_macosx_x86-64/share.hxx b/bridges/source/cpp_uno/gcc3_macosx_x86-64/share.hxx index f84958b96368..910a5e46c6cd 100644 --- a/bridges/source/cpp_uno/gcc3_macosx_x86-64/share.hxx +++ b/bridges/source/cpp_uno/gcc3_macosx_x86-64/share.hxx @@ -35,41 +35,102 @@ 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 { - unsigned exception_class __attribute__((__mode__(__DI__))); - void * exception_cleanup; - unsigned private_1 __attribute__((__mode__(__word__))); - unsigned private_2 __attribute__((__mode__(__word__))); -} __attribute__((__aligned__)); + uint64_t exception_class; + void (*exception_cleanup)(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc); + uintptr_t private_1; // non-zero means forced unwind + uintptr_t private_2; // holds sp that phase1 found for phase2 to use +#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 +}; -struct __cxa_exception -{ - ::std::type_info *exceptionType; - void (*exceptionDestructor)(void *); - ::std::unexpected_handler unexpectedHandler; - ::std::terminate_handler terminateHandler; +// From libcppabi-24.2/include/unwind-cxx.h - __cxa_exception *nextException; +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); - int handlerCount; +// 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. - int handlerSwitchValue; - const unsigned char *actionRecord; - const unsigned char *languageSpecificData; - void *catchTemp; - void *adjustedPtr; +struct __cxa_exception +{ +#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 *); + + // The C++ standard has entertaining rules wrt calling set_terminate + // 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; + + // How many nested handlers have caught this exception. A negated + // value is a signal that this object has been rethrown. + 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; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + _Unwind_Ptr catchTemp; + 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 - _Unwind_Exception unwindHeader; + // The generic exception header. Must be last. + _Unwind_Exception unwindHeader; }; +// Each thread in a C++ program has access to a __cxa_eh_globals object. struct __cxa_eh_globals { - __cxa_exception *caughtExceptions; - unsigned int uncaughtExceptions; + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +#ifdef __ARM_EABI_UNWINDER__ + __cxa_exception* propagatingExceptions; +#endif }; } -- cgit