office-gobmx/include/bridges/emscriptencxxabi/cxxabi.hxx
Stephan Bergmann 875997c896 Properly implement cppu::throwException for Emscripten
...by implementing (for now) just enough of the cpp2uno half of the Wasm UNO
bridge to make it work.  In general, that half suffers from the same issue as
the already-implemented uno2cpp half, namely that Wasm doesn't allow to generate
code on the fly (which, in this case, would be needed to implement the vtable
slot trampoline functions).  So, for now just hard-code the few
vtableSlotFunction_* that are needed by the UNO interfaces for
cppuhelper/source/exc_thrower.cxx.  (A proper fix would probably use the same
approach as for the uno2cpp half, and use something like wasmcallgen to generate
at least all the vtableSlotFunction_* needed for udkapi/offapi upfront.)

The RTTI for the exceptions needs to be unique across the executable for
exception catching to actually work (as it compares exception types by RTTI
address rather than by name).  We thus need to export all the relevant RTTI
symbols (which I hacked into the existing wasmcallgen for now, even if that
makes that executable's name a slight misnomer now), and access them with a new
jsGetExportedSymbol.  (This exporting would also be needed by the "classical"
approach of using dlsym on the main module, cf.
<https://gerrit.libreoffice.org/c/core/+/167187> "WIP: Emscripten: Set up
support for dlsym from main module".  And while that dlsym approach would work,
it is much simpler to just use that jsGetExportedSymbol than to use a dlsym
detour, and thereby avoid all the hassle of -sMAIN_MODULE detailed in the commit
message of that Gerrit change.)

It also turned out that including Emscripten's <cxxabi.h> needs
__USING_WASM_EXCEPTIONS__ to be defined, because it uses that in its declaration
of __cxa_throw.  (The source for setting that define internally in Emscripten is
get_cflags in the emsdk's upstream/emscripten/tools/system_libs.py, which
defines __USING_EMSCRIPTEN_EXCEPTIONS__ for the non-Wasm, Emscripten JS
exception mode, and defines __USING_WASM_EXCEPTIONS__ for
--enable-wasm-exceptions, which we use.  The commit message of
f4ec967599 "Fix redefinion of Emscripten
__cxxabiv1::__cxa_exception" documents my prior confusion of when one or the
other would be defined.)

Change-Id: Id08765ab5b4ce1553dc3a61648324526185cb64c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170246
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
2024-07-10 12:32:15 +02:00

108 lines
3.8 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* 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/.
*/
#pragma once
#include <sal/config.h>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <typeinfo>
#define __USING_WASM_EXCEPTIONS__
#include <cxxabi.h>
#include <config_cxxabi.h>
#include <rtl/ustring.hxx>
#if !HAVE_CXXABI_H_CXA_EXCEPTION
// <https://github.com/emscripten-core/emscripten/>, system/lib/libunwind/include/unwind_itanium.h,
// except where MODIFIED:
typedef std::/*MODIFIED*/ uint64_t _Unwind_Exception_Class;
struct _Unwind_Exception
{
_Unwind_Exception_Class exception_class;
void (*exception_cleanup)(/*MODIFIED: _Unwind_Reason_Code reason, _Unwind_Exception* exc*/);
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
std::/*MODIFIED*/ uintptr_t private_[6];
#elif !defined(__USING_WASM_EXCEPTIONS__)
std::/*MODIFIED*/ uintptr_t private_1; // non-zero means forced unwind
std::/*MODIFIED*/ uintptr_t private_2; // holds sp that phase1 found for phase2 to use
#endif
#if __SIZEOF_POINTER__ == 4
// The implementation of _Unwind_Exception uses an attribute mode on the
// above fields which has the side effect of causing this whole struct to
// round up to 32 bytes in size (48 with SEH). To be more explicit, we add
// pad fields added for binary compatibility.
std::/*MODIFIED*/ uint32_t reserved[3];
#endif
// The Itanium ABI requires that _Unwind_Exception objects are "double-word
// aligned". GCC has interpreted this to mean "use the maximum useful
// alignment for the target"; so do we.
} __attribute__((__aligned__));
// <https://github.com/emscripten-core/emscripten/>, system/lib/libcxxabi/src/cxa_exception.h,
// except where MODIFIED:
namespace __cxxabiv1
{
struct __cxa_exception
{
#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
// Now _Unwind_Exception is marked with __attribute__((aligned)),
// which implies __cxa_exception is also aligned. Insert padding
// in the beginning of the struct, rather than before unwindHeader.
void* reserve;
// This is a new field to support C++11 exception_ptr.
// For binary compatibility it is at the start of this
// struct which is prepended to the object thrown in
// __cxa_allocate_exception.
std::/*MODIFIED*/ size_t referenceCount;
#endif
// Manage the exception object itself.
std::type_info* exceptionType;
#ifdef __USING_WASM_EXCEPTIONS__
// In wasm, destructors return their argument
void*(/*MODIFIED: _LIBCXXABI_DTOR_FUNC*/ *exceptionDestructor)(void*);
#else
void(/*MODIFIED: _LIBCXXABI_DTOR_FUNC*/ *exceptionDestructor)(void*);
#endif
void* /*MODIFIED: std::unexpected_handler*/ unexpectedHandler;
std::terminate_handler terminateHandler;
__cxa_exception* nextException;
int handlerCount;
#if defined(_LIBCXXABI_ARM_EHABI)
__cxa_exception* nextPropagatingException;
int propagationCount;
#else
int handlerSwitchValue;
const unsigned char* actionRecord;
const unsigned char* languageSpecificData;
void* catchTemp;
void* adjustedPtr;
#endif
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
// This is a new field to support C++11 exception_ptr.
// For binary compatibility it is placed where the compiler
// previously added padding to 64-bit align unwindHeader.
std::/*MODIFIED*/ size_t referenceCount;
#endif
_Unwind_Exception unwindHeader;
};
}
#endif
namespace emscriptencxxabi
{
OUString toUnoName(char const* name);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */