aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h
blob: dd20ba1e8891a1cf6441ee51719fdfdc10b0fad8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
//  This file implements the "Exception Handling APIs"
//  https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
//
//===----------------------------------------------------------------------===//

#ifndef _CXA_EXCEPTION_H
#define _CXA_EXCEPTION_H

#include <exception> // for std::unexpected_handler and std::terminate_handler
#include "cxxabi.h"
#include "unwind.h"

namespace __cxxabiv1 {

#ifdef __USING_EMSCRIPTEN_EXCEPTIONS__

struct _LIBCXXABI_HIDDEN __cxa_exception {
  size_t referenceCount;
  std::type_info *exceptionType;
  void (*exceptionDestructor)(void *);
  uint8_t caught;
  uint8_t rethrown;
  void *adjustedPtr;
  // Add padding to ensure that the size of __cxa_exception is a multiple of
  // the maximum useful alignment for the target machine.  This ensures that
  // the thrown object that follows has that correct alignment.
  void *padding;
};

static_assert(sizeof(__cxa_exception) % alignof(max_align_t) == 0, "__cxa_exception must have a size that is multipl of max alignment");

#else

static const uint64_t kOurExceptionClass          = 0x434C4E47432B2B00; // CLNGC++\0
static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
static const uint64_t get_vendor_and_language     = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++

_LIBCXXABI_HIDDEN uint64_t __getExceptionClass  (const _Unwind_Exception*);
_LIBCXXABI_HIDDEN void     __setExceptionClass  (      _Unwind_Exception*, uint64_t);
_LIBCXXABI_HIDDEN bool     __isOurExceptionClass(const _Unwind_Exception*);

struct _LIBCXXABI_HIDDEN __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.
    size_t referenceCount;
#endif

    //  Manage the exception object itself.
    std::type_info *exceptionType;
#ifdef __USING_WASM_EXCEPTIONS__
    // In wasm, destructors return their argument
    void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
#else
    void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
#endif
    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.
    size_t referenceCount;
#endif
    _Unwind_Exception unwindHeader;
};

// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
// The layout of this structure MUST match the layout of __cxa_exception, with
// primaryException instead of referenceCount.
struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
    void* reserve; // padding.
    void* primaryException;
#endif

    std::type_info *exceptionType;
    void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
    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)
    void* primaryException;
#endif
    _Unwind_Exception unwindHeader;
};

// Verify the negative offsets of different fields.
static_assert(sizeof(_Unwind_Exception) +
                      offsetof(__cxa_exception, unwindHeader) ==
                  sizeof(__cxa_exception),
              "unwindHeader has wrong negative offsets");
static_assert(sizeof(_Unwind_Exception) +
                      offsetof(__cxa_dependent_exception, unwindHeader) ==
                  sizeof(__cxa_dependent_exception),
              "unwindHeader has wrong negative offsets");

#if defined(_LIBCXXABI_ARM_EHABI)
static_assert(offsetof(__cxa_exception, propagationCount) +
                      sizeof(_Unwind_Exception) + sizeof(void*) ==
                  sizeof(__cxa_exception),
              "propagationCount has wrong negative offset");
static_assert(offsetof(__cxa_dependent_exception, propagationCount) +
                      sizeof(_Unwind_Exception) + sizeof(void*) ==
                  sizeof(__cxa_dependent_exception),
              "propagationCount has wrong negative offset");
#elif defined(__LP64__) || defined(_WIN64)
static_assert(offsetof(__cxa_exception, adjustedPtr) +
                      sizeof(_Unwind_Exception) + sizeof(void*) ==
                  sizeof(__cxa_exception),
              "adjustedPtr has wrong negative offset");
static_assert(offsetof(__cxa_dependent_exception, adjustedPtr) +
                      sizeof(_Unwind_Exception) + sizeof(void*) ==
                  sizeof(__cxa_dependent_exception),
              "adjustedPtr has wrong negative offset");
#else
static_assert(offsetof(__cxa_exception, referenceCount) +
                      sizeof(_Unwind_Exception) + sizeof(void*) ==
                  sizeof(__cxa_exception),
              "referenceCount has wrong negative offset");
static_assert(offsetof(__cxa_dependent_exception, primaryException) +
                      sizeof(_Unwind_Exception) + sizeof(void*) ==
                  sizeof(__cxa_dependent_exception),
              "primaryException has wrong negative offset");
#endif

struct _LIBCXXABI_HIDDEN __cxa_eh_globals {
    __cxa_exception *   caughtExceptions;
    unsigned int        uncaughtExceptions;
#if defined(_LIBCXXABI_ARM_EHABI)
    __cxa_exception* propagatingExceptions;
#endif
};

extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals      ();
extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals_fast ();

extern "C" _LIBCXXABI_FUNC_VIS void * __cxa_allocate_dependent_exception ();
extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * dependent_exception);

#endif // !__USING_EMSCRIPTEN_EXCEPTIONS__

}  // namespace __cxxabiv1

#endif // _CXA_EXCEPTION_H