annotate libcxxabi/src/aix_state_tab_eh.inc @ 240:ca573705d418

merge
author matac
date Fri, 28 Jul 2023 20:50:09 +0900
parents c4bab56944e8
children 1f2b6ac9f198
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
236
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
1 //===----------------------------------------------------------------------===//
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
2 //
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
6 //
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
7 //
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
8 // This file implements the personality and helper functions for the state
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
9 // table based EH used by IBM legacy compilers xlC and xlclang++ on AIX.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
10 //
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
11 //===----------------------------------------------------------------------===//
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
12
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
13 #include <new>
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
14 #include <stdio.h>
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
15 #include <sys/debug.h>
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
16
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
17 #if !__has_cpp_attribute(clang::optnone)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
18 #error This file requires clang::optnone attribute support
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
19 #endif
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
20
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
21 /*
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
22 The legacy IBM xlC and xlclang++ compilers use the state table for EH
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
23 instead of the range table. Destructors, or addresses of the possible catch
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
24 sites or cleanup code are specified in the state table which is a finite
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
25 state machine (FSM). Each function that has a state table also has an
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
26 autolocal state variable. The state variable represents the current state
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
27 of the function for EH and is found through the traceback table of the
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
28 function during unwinding, which is located at the end of each function.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
29 The FSM is an array of state entries. Each state entry has the following
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
30 fields:
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
31
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
32 * offset/address/pointer - the offset used to locate the object, or the
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
33 address of a global object, or the address of the next state if it is an
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
34 old conditional state change entry;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
35 * dtor/landing pad - address of the destructor function to invoke,
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
36 or address of the catch block or cleanup code in the user code to branch to;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
37 * element count/action flag - the number of elements or the flag for actions;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
38 * element size - if the object is an array this is the size of one element
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
39 of the array;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
40 * flags - flags used to control how fields in the entry are interpreted;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
41 * next state - the state to execute next after the action for this state is
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
42 performed. The value of zero indicates the end of the state for this
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
43 function.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
44
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
45 The following is the description of 'element count/action flag' field.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
46 +-----------------------------------------------------------------------------+
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
47 | value | description | action |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
48 +-------+------------------------+--------------------------------------------+
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
49 | > 1 | object is an array | calls __cxa_vec_cleanup to run dtor for |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
50 | | | each member of the array |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
51 +-------+------------------------+--------------------------------------------+
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
52 | 1, 0 | object is a scalar | calls dtor for the object |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
53 +-------+------------------------+--------------------------------------------+
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
54 | -1 | begin catch | branches to the handler which performes |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
55 | | | catch-match. If there is no catch that |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
56 | | | matches the exception it will be rethrown |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
57 +-------+------------------------+--------------------------------------------+
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
58 | -2 | end catch | ends current catch block and continues |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
59 | | | attempting to catch the exception |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
60 +-------+------------------------+--------------------------------------------+
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
61 | -3 | delete the object | calls the delete function of the object |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
62 +-------+------------------------+--------------------------------------------+
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
63 | -4 | cleanup label | branches to the user code for cleaning up |
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
64 +-------+------------------------+--------------------------------------------+
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
65 */
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
66
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
67 namespace __cxxabiv1 {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
68
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
69 extern "C" {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
70
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
71 // Macros for debugging the state table parsing.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
72 #ifdef NDEBUG
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
73 # define _LIBCXXABI_TRACE_STATETAB(msg, ...)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
74 # define _LIBCXXABI_TRACE_STATETAB0(msg)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
75 # define _LIBCXXABI_TRACE_STATETAB1(msg)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
76 # define _LIBCXXABI_TRACING_STATETAB 0
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
77 #else
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
78 static bool state_tab_dbg() {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
79 static bool checked = false;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
80 static bool log = false;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
81 if (!checked) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
82 log = (getenv("LIBCXXABI_PRINT_STATTAB") != NULL);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
83 checked = true;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
84 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
85 return log;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
86 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
87
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
88 # define _LIBCXXABI_TRACE_STATETAB(msg, ...) \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
89 do { \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
90 if (state_tab_dbg()) \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
91 fprintf(stderr, "libcxxabi: " msg, __VA_ARGS__); \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
92 } while (0)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
93 # define _LIBCXXABI_TRACE_STATETAB0(msg) \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
94 do { \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
95 if (state_tab_dbg()) \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
96 fprintf(stderr, "libcxxabi: " msg); \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
97 } while (0)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
98 # define _LIBCXXABI_TRACE_STATETAB1(msg) \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
99 do { \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
100 if (state_tab_dbg()) \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
101 fprintf(stderr, msg); \
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
102 } while (0)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
103
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
104 # define _LIBCXXABI_TRACING_STATETAB state_tab_dbg()
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
105 #endif // NDEBUG
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
106
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
107 namespace __state_table_eh {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
108
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
109 using destruct_f = void (*)(void*);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
110
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
111 // Definition of flags for the state table entry field 'action flag'.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
112 enum FSMEntryCount : intptr_t { beginCatch = -1, endCatch = -2, deleteObject = -3, cleanupLabel = -4, terminate = -5 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
113
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
114 // Definition of flags for the state table entry field 'flags'.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
115 enum FSMEntryFlag : int16_t {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
116 indirect = 0x100, // Object was thrown from a function where
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
117 // the return value optimization was used.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
118 oldConditionalStateChange = 0x400, // State table entry is an indirect state
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
119 // change, dereference the address in
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
120 // offset as int for the target state.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
121 // This is deprecated. This indicates
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
122 // the address is direct. (static local).
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
123 conditionalStateChange = 0x800, // State table entry is an indirect state
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
124 // change, dereference the address in
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
125 // offset as int for the target state.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
126 // The temporary is an automatic. State
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
127 // change is used in cases such as
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
128 // (b?(T1(),foo()):(T2(),foo())),throw 42;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
129 // which causes a conditional state change
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
130 // so that we know if T1 or T2 need to be
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
131 // destroyed.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
132 thisFlag = 0x01, // The address of the object for the
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
133 // cleanup action is based on the
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
134 // StateVariable::thisValue.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
135 vBaseFlag = 0x02, // The object is of a virtual base class.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
136 globalObj = 0x04 // FSMEntry::address is the address of
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
137 // a global object.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
138 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
139
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
140 namespace {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
141 // The finite state machine to be walked.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
142 struct FSMEntry {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
143 union {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
144 // Offset of the object within its stack frame or containing object.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
145 intptr_t offset;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
146 // Address of a global object.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
147 intptr_t address;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
148 // Address of the next state if it is an old conditional state change entry.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
149 intptr_t nextStatePtr;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
150 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
151 union {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
152 // Address of the destructor function.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
153 void (*destructor)(void*, size_t);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
154 // The address of the catch block or cleanup code.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
155 void* landingPad;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
156 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
157 union {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
158 // The flag for actions (when the value is negative).
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
159 FSMEntryCount actionFlag;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
160 // The element count (when the value is positive or zero).
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
161 size_t elementCount;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
162 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
163 size_t elemSize;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
164 FSMEntryFlag flags;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
165 uint16_t nextState;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
166 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
167
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
168 struct FSM {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
169 uint32_t magic; // Magic number of the state table.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
170 int32_t numberOfStates;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
171 FSMEntry table[1]; // Actually table[numberOfStates].
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
172 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
173
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
174 // The state variable on the stack.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
175 struct StateVariable {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
176 int32_t state;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
177 struct FSM* table;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
178 intptr_t thisValue;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
179 int32_t ignoreVBasePtrs;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
180 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
181 } // namespace
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
182
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
183 // State table magic number
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
184 enum FSMMagic : uint32_t {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
185 number = 0xbeefdead, // State table generated by xlC compiler.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
186 number2 = 0xbeeedead, // State table generated by early version xlC compiler.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
187 number3 = 0x1cedbeef // State table generated by xlclang++ compiler.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
188 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
189
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
190 constexpr size_t dtorArgument = 0x02; // Flag to destructor indicating to free
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
191 // virtual bases, don't delete object.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
192
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
193 static void invoke_destructor(FSMEntry* fsmEntry, void* addr) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
194 _LIBCXXABI_TRACE_STATETAB("Destruct object=%p, fsmEntry=%p\n", addr, reinterpret_cast<void*>(fsmEntry));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
195 try {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
196 if (fsmEntry->elementCount == 1) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
197 _LIBCXXABI_TRACE_STATETAB0("calling scalar destructor\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
198 (*fsmEntry->destructor)(addr, dtorArgument);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
199 _LIBCXXABI_TRACE_STATETAB0("returned from scalar destructor\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
200 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
201 _LIBCXXABI_TRACE_STATETAB0("calling vector destructor\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
202 __cxa_vec_cleanup(addr, reinterpret_cast<size_t>(fsmEntry->elementCount), fsmEntry->elemSize,
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
203 reinterpret_cast<destruct_f>(fsmEntry->destructor));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
204 _LIBCXXABI_TRACE_STATETAB0("returned from vector destructor\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
205 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
206 } catch (...) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
207 _LIBCXXABI_TRACE_STATETAB0("Uncaught exception in destructor, terminating\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
208 std::terminate();
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
209 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
210 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
211
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
212 static void invoke_delete(FSMEntry* fsmEntry, void* addr) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
213 char* objectAddress = *reinterpret_cast<char**>(addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
214
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
215 _LIBCXXABI_TRACE_STATETAB("Delete object=%p, fsmEntry=%p\n", reinterpret_cast<void*>(objectAddress),
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
216 reinterpret_cast<void*>(fsmEntry));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
217 try {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
218 _LIBCXXABI_TRACE_STATETAB0("..calling delete()\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
219 // 'destructor' holds a function pointer to delete().
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
220 (*fsmEntry->destructor)(objectAddress, fsmEntry->elemSize);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
221 _LIBCXXABI_TRACE_STATETAB0("..returned from delete()\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
222 } catch (...) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
223 _LIBCXXABI_TRACE_STATETAB0("Uncaught exception in delete(), terminating\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
224 std::terminate();
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
225 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
226 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
227
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
228 // Get the frame address of the current function from its traceback table
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
229 // which is at the end of each function.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
230 static uintptr_t get_frame_addr(_Unwind_Context* context) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
231 int framePointerReg = 1; // default frame pointer == SP.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
232 uint32_t* p = reinterpret_cast<uint32_t*>(_Unwind_GetIP(context));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
233
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
234 // Keep looking forward until a word of 0 is found. The traceback
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
235 // table starts at the following word.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
236 while (*p)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
237 ++p;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
238 tbtable* TBTable = reinterpret_cast<tbtable*>(p + 1);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
239
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
240 p = reinterpret_cast<uint32_t*>(&TBTable->tb_ext);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
241
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
242 // Skip field parminfo if it exists.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
243 if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
244 ++p;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
245
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
246 // Skip field tb_offset if it exists.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
247 if (TBTable->tb.has_tboff)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
248 ++p;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
249
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
250 // Skip field hand_mask if it exists.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
251 if (TBTable->tb.int_hndl)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
252 ++p;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
253
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
254 // Skip fields ctl_info and ctl_info_disp if they exist.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
255 if (TBTable->tb.has_ctl)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
256 p += 1 + *p;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
257
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
258 // Skip fields name_len and name if exist.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
259 if (TBTable->tb.name_present) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
260 const uint16_t name_len = *reinterpret_cast<uint16_t*>(p);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
261 p = reinterpret_cast<uint32_t*>(reinterpret_cast<char*>(p) + name_len + sizeof(uint16_t));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
262 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
263
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
264 if (TBTable->tb.uses_alloca)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
265 framePointerReg = *reinterpret_cast<char*>(p);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
266
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
267 return _Unwind_GetGR(context, framePointerReg);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
268 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
269
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
270 // Calculate the object address from the FSM entry.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
271 static void* compute_addr_from_table(FSMEntry* fsmEntry, StateVariable* const state, _Unwind_Context* context) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
272 void* addr;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
273 if (fsmEntry->flags & FSMEntryFlag::globalObj) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
274 addr = reinterpret_cast<void*>(fsmEntry->address);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
275 _LIBCXXABI_TRACE_STATETAB("Address calculation (global obj) addr=fsmEntry->address=%p\n", addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
276 } else if (fsmEntry->flags & FSMEntryFlag::thisFlag) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
277 addr = reinterpret_cast<void*>(state->thisValue + fsmEntry->offset);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
278 _LIBCXXABI_TRACE_STATETAB("Address calculation (this obj) fsmEntry->offset=%ld : "
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
279 "state->thisValue=%ld addr=(fsmEntry->offset+state->thisValue)=%p\n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
280 fsmEntry->offset, state->thisValue, addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
281 } else if (fsmEntry->flags & FSMEntryFlag::indirect) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
282 addr = reinterpret_cast<void*>(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
283 *reinterpret_cast<char**>(get_frame_addr(context) + static_cast<uintptr_t>(fsmEntry->offset)));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
284 _LIBCXXABI_TRACE_STATETAB("Address calculation (indirect obj) addr=%p, fsmEntry->offset=%ld \n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
285 addr, fsmEntry->offset);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
286 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
287 addr = reinterpret_cast<void*>(get_frame_addr(context) + static_cast<uintptr_t>(fsmEntry->offset));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
288 _LIBCXXABI_TRACE_STATETAB("Address calculation. (local obj) addr=fsmEntry->offset=%p\n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
289 addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
290 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
291 return addr;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
292 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
293
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
294 static void scan_state_tab(scan_results& results, _Unwind_Action actions, bool native_exception,
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
295 _Unwind_Exception* unwind_exception, _Unwind_Context* context) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
296 // Initialize results to found nothing but an error.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
297 results.ttypeIndex = 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
298 results.actionRecord = 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
299 results.languageSpecificData = 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
300 results.landingPad = 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
301 results.adjustedPtr = 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
302 results.reason = _URC_FATAL_PHASE1_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
303
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
304 // Check for consistent actions.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
305 if (actions & _UA_SEARCH_PHASE) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
306 // Do Phase 1
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
307 if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
308 // None of these flags should be set during Phase 1.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
309 // Client error
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
310 results.reason = _URC_FATAL_PHASE1_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
311 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
312 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
313 } else if (actions & _UA_CLEANUP_PHASE) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
314 if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
315 // _UA_HANDLER_FRAME should only be set if phase 1 found a handler.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
316 // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
317 // Client error
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
318 results.reason = _URC_FATAL_PHASE2_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
319 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
320 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
321 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
322 // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
323 // Client error
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
324 results.reason = _URC_FATAL_PHASE1_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
325 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
326 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
327
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
328 if (_LIBCXXABI_TRACING_STATETAB) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
329 _LIBCXXABI_TRACE_STATETAB1("\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
330 _LIBCXXABI_TRACE_STATETAB("%s: actions=%d (", __func__, actions);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
331
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
332 if (_UA_SEARCH_PHASE & actions)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
333 _LIBCXXABI_TRACE_STATETAB1("_UA_SEARCH_PHASE ");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
334 if (_UA_CLEANUP_PHASE & actions)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
335 _LIBCXXABI_TRACE_STATETAB1("_UA_CLEANUP_PHASE ");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
336 if (_UA_HANDLER_FRAME & actions)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
337 _LIBCXXABI_TRACE_STATETAB1("_UA_HANDLER_FRAME ");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
338 if (_UA_FORCE_UNWIND & actions)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
339 _LIBCXXABI_TRACE_STATETAB1("_UA_FORCE_UNWIND ");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
340 _LIBCXXABI_TRACE_STATETAB1(")\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
341 _LIBCXXABI_TRACE_STATETAB(" unwind_exception=%p context=%p\n", reinterpret_cast<void*>(unwind_exception),
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
342 reinterpret_cast<void*>(context));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
343 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
344
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
345 // Start scan by getting state table address.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
346 StateVariable* const state = reinterpret_cast<StateVariable* const>(_Unwind_GetLanguageSpecificData(context));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
347 if (state->state <= 0) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
348 // The state is not correct - give up on this routine.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
349 _LIBCXXABI_TRACE_STATETAB("state=%d and is <= 0), continue unwinding\n", state->state);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
350 results.reason = _URC_CONTINUE_UNWIND;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
351 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
352 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
353 // Parse the state table.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
354 FSM* const fsm = state->table;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
355 FSMEntry* currFSMEntry;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
356
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
357 if (fsm->magic != FSMMagic::number && fsm->magic != FSMMagic::number2 && fsm->magic != FSMMagic::number3) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
358 // Something is wrong with the state table we found.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
359 if (_UA_SEARCH_PHASE & actions) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
360 _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table, return _URC_FATAL_PHASE1_ERROR\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
361 results.reason = _URC_FATAL_PHASE1_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
362 } else if (_UA_CLEANUP_PHASE & actions) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
363 _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table, return _URC_FATAL_PHASE2_ERROR\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
364 results.reason = _URC_FATAL_PHASE2_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
365 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
366 // We should never get here.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
367 _LIBCXXABI_TRACE_STATETAB0("Invalid FSM table + RT Internal error, return _URC_FATAL_PHASE2_ERROR\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
368 results.reason = _URC_FATAL_PHASE2_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
369 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
370 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
371 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
372
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
373 if (_LIBCXXABI_TRACING_STATETAB) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
374 // Print the state table for debugging purposes.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
375 _LIBCXXABI_TRACE_STATETAB("state->state=%d, state->ignoreVBasePtrs=%d\n", state->state, state->ignoreVBasePtrs);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
376 _LIBCXXABI_TRACE_STATETAB("fsm->magic=%#x, fsm->numberOfStates=%d\n", fsm->magic, fsm->numberOfStates);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
377 // Print out the FSM table.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
378 _LIBCXXABI_TRACE_STATETAB0("FSM table:\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
379 _LIBCXXABI_TRACE_STATETAB("%12s %10s %8s %10s %7s %7s %7s %7s\n", "Entry Addr", "state", "Offset", "DTR/lpad",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
380 "count", "el_size", "flags", "next");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
381 for (int i = 0; i < fsm->numberOfStates; i++) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
382 currFSMEntry = &fsm->table[i];
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
383 _LIBCXXABI_TRACE_STATETAB("%12p (%8d) %8ld %10p %7ld "
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
384 "%7ld %#7x %7d\n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
385 reinterpret_cast<void*>(&currFSMEntry), i + 1, currFSMEntry->offset,
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
386 reinterpret_cast<void*>(currFSMEntry->destructor),
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
387 currFSMEntry->elementCount, currFSMEntry->elemSize, currFSMEntry->flags,
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
388 currFSMEntry->nextState);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
389 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
390 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
391
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
392 if (_UA_SEARCH_PHASE & actions) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
393 // Start walking the state table. Use a local copy of state->state so when
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
394 // we return from search phase we don't change the state number.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
395 int currState = state->state;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
396
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
397 while (currState > 0) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
398 currFSMEntry = &fsm->table[currState - 1];
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
399 _LIBCXXABI_TRACE_STATETAB("Processing state=%d, flags=0x%hx\n", currState, currFSMEntry->flags);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
400
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
401 if (currFSMEntry->actionFlag == FSMEntryCount::beginCatch) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
402 // Found a catch handler.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
403 if (fsm->magic == FSMMagic::number) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
404 _LIBCXXABI_TRACE_STATETAB0("Found a xlC catch handler, return _URC_FATAL_PHASE1_ERROR\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
405 // xlC catch handlers cannot be entered because they use a
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
406 // proprietary EH runtime that is not interoperable.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
407 results.reason = _URC_FATAL_PHASE1_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
408 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
409 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
410 // xlclang++ compiled frames use CXA-abi EH calls and any catch
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
411 // block will include a catch(...) block so it is safe to assume that
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
412 // the handler is found without checking the catch match. The
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
413 // catch(...) block will rethrow the exception if there isn't a
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
414 // match.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
415 _LIBCXXABI_TRACE_STATETAB0("Found a catch handler, return _URC_HANDLER_FOUND\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
416 results.reason = _URC_HANDLER_FOUND;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
417 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
418 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
419 if (currFSMEntry->actionFlag == FSMEntryCount::terminate) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
420 _LIBCXXABI_TRACE_STATETAB0("Found the terminate state, return _URC_HANDLER_FOUND\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
421 results.reason = _URC_HANDLER_FOUND;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
422 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
423 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
424 if (currFSMEntry->flags & FSMEntryFlag::oldConditionalStateChange) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
425 // Deprecated conditional expression.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
426 currState = *reinterpret_cast<int*>(currFSMEntry->nextStatePtr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
427 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::oldConditionalStateChange, dereference "
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
428 "currFSMEntry->nextStatePtr(%ld), set state=%d\n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
429 currFSMEntry->nextStatePtr, currState);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
430 continue; // We are done this iteration of the loop, since
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
431 // we changed a state.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
432 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
433 if (currFSMEntry->flags & FSMEntryFlag::conditionalStateChange) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
434 void* addr = compute_addr_from_table(currFSMEntry, state, context);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
435 currState = *reinterpret_cast<int*>(addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
436 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::conditionalStateChange, dereference "
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
437 "addr(%p), set state=%d\n", addr, currState);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
438 continue; // We are done this iteration of the loop, since we
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
439 // changed the state.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
440 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
441 // Go to the next state.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
442 currState = currFSMEntry->nextState;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
443 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
444 _LIBCXXABI_TRACE_STATETAB0("No catch handler found, return _URC_CONTINUE_UNWIND\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
445 results.reason = _URC_CONTINUE_UNWIND;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
446 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
447 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
448 if (_UA_CLEANUP_PHASE & actions) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
449 // Start walking the state table.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
450 while (state->state > 0) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
451 currFSMEntry = &fsm->table[state->state - 1];
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
452
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
453 if (currFSMEntry->actionFlag == FSMEntryCount::terminate) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
454 _LIBCXXABI_TRACE_STATETAB0("Reached terminate state. Call terminate.\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
455 std::terminate();
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
456 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
457 // Perform action according to the currFSMEntry->actionFlag,
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
458 // except when flag is FSMEntryFlag::conditionalStateChange or
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
459 // FSMEntryFlag::oldConditionalStateChange.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
460 _LIBCXXABI_TRACE_STATETAB("Processing state=%d, flags=0x%hx\n", state->state, currFSMEntry->flags);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
461 if (currFSMEntry->flags & FSMEntryFlag::oldConditionalStateChange) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
462 state->state = *reinterpret_cast<int*>(currFSMEntry->nextStatePtr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
463 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::oldConditionalStateChange, dereference "
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
464 "currFSMEntry->nextStatePtr(%ld), set state=%d\n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
465 currFSMEntry->nextStatePtr, state->state);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
466 continue; // We are done with this iteration of the loop, since we changed a state.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
467 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
468 if (currFSMEntry->flags & FSMEntryFlag::conditionalStateChange) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
469 // A conditional state table entry holds the address of a local
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
470 // that holds the next state.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
471 void* addr = compute_addr_from_table(currFSMEntry, state, context);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
472 state->state = *reinterpret_cast<int*>(addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
473 _LIBCXXABI_TRACE_STATETAB("Flag: FSMEntryFlag::conditionalStateChange, dereference "
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
474 "addr(%p), set state=%d\n", addr, state->state);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
475 continue; // We are done with this iteration of the loop, since we changed a state.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
476 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
477 if (currFSMEntry->actionFlag == FSMEntryCount::beginCatch || currFSMEntry->actionFlag == FSMEntryCount::endCatch ||
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
478 currFSMEntry->actionFlag == FSMEntryCount::cleanupLabel) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
479
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
480 _LIBCXXABI_TRACE_STATETAB(
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
481 "FSMEntryCount::%s: handler %p/%p, return _URC_HANDLER_FOUND\n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
482 (currFSMEntry->actionFlag == FSMEntryCount::beginCatch
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
483 ? "beginCatch"
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
484 : (currFSMEntry->actionFlag == FSMEntryCount::endCatch ? "endCatch" : "cleanupLabel")),
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
485 currFSMEntry->landingPad, *reinterpret_cast<void**>(currFSMEntry->landingPad));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
486
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
487 state->state = currFSMEntry->nextState;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
488 results.landingPad = reinterpret_cast<uintptr_t>(*reinterpret_cast<void**>(currFSMEntry->landingPad));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
489 results.reason = _URC_HANDLER_FOUND;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
490 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
491 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
492 if (currFSMEntry->elementCount > 0) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
493 if (currFSMEntry->flags & FSMEntryFlag::vBaseFlag && state->ignoreVBasePtrs) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
494 _LIBCXXABI_TRACE_STATETAB0("Ignoring virtual base dtor.\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
495 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
496 // We need to invoke the virtual base destructor. This must be
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
497 // a frame from the legacy xlC compiler as the xlclang++ compiler
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
498 // generates inline cleanup code rather than specifying
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
499 // the destructor via the state table.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
500 void* addr = compute_addr_from_table(currFSMEntry, state, context);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
501
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
502 // An extra indirect to get to the object according to the object
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
503 // model used by the xlC compiler.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
504 addr = reinterpret_cast<void*>(*reinterpret_cast<char**>(addr));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
505 _LIBCXXABI_TRACE_STATETAB("Invoke dtor for object=%p\n", addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
506 invoke_destructor(currFSMEntry, addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
507 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
508 } else if (currFSMEntry->actionFlag == FSMEntryCount::deleteObject) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
509 void* addr = compute_addr_from_table(currFSMEntry, state, context);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
510 if (currFSMEntry->flags & FSMEntryFlag::vBaseFlag) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
511 // We need to invoke the virtual base delete function. This must be
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
512 // a frame from the legacy xlC compiler as the xlclang++ compiler
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
513 // generates inline cleanup code rather than specifying
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
514 // the delete function via the state table.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
515
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
516 // An extra indirect to get to the object according to the object
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
517 // model used by the xlC compiler.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
518 addr = reinterpret_cast<void*>(*reinterpret_cast<char**>(addr));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
519 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
520 _LIBCXXABI_TRACE_STATETAB("Delete object at %p\n", addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
521 invoke_delete(currFSMEntry, addr);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
522 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
523 _LIBCXXABI_TRACE_STATETAB("Unknown entry in FSM (count=%ld), ignored\n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
524 currFSMEntry->elementCount);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
525 } // End of action switching.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
526
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
527 // Go to next state.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
528 state->state = currFSMEntry->nextState;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
529 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
530 _LIBCXXABI_TRACE_STATETAB0("No catch handler, return _URC_CONTINUE_UNWIND\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
531 results.reason = _URC_CONTINUE_UNWIND;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
532 return;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
533 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
534 _LIBCXXABI_TRACE_STATETAB0("No state table entry for this exception, call_terminate()\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
535 // It is possible that no state table entry specify how to handle
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
536 // this exception. By spec, terminate it immediately.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
537 call_terminate(native_exception, unwind_exception);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
538 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
539
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
540 // Personality routine for EH using the state table.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
541 _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
542 __xlcxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass,
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
543 _Unwind_Exception* unwind_exception, _Unwind_Context* context) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
544 if (version != 1 || unwind_exception == 0 || context == 0)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
545 return _URC_FATAL_PHASE1_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
546
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
547 bool native_exception = (exceptionClass & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
548 scan_results results;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
549 scan_state_tab(results, actions, native_exception, unwind_exception, context);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
550 if (actions & _UA_SEARCH_PHASE) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
551 // Phase 1 search: All we're looking for in phase 1 is a handler that
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
552 // halts unwinding
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
553 return results.reason;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
554 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
555 if (actions & _UA_CLEANUP_PHASE) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
556 // Phase 2 cleanup:
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
557 if (results.reason == _URC_HANDLER_FOUND) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
558 // Store the address of unwind_exception in the stack field
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
559 // reserved for compilers (SP + 3 * sizeof(uintptr_t)) in the stack of
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
560 // the caller of the function containing the landing pad (within the link
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
561 // area for the call to the latter) for __xlc_exception_handle()
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
562 // to retrieve when it is called by the landing pad.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
563 uintptr_t *currentSP = reinterpret_cast<uintptr_t*>(_Unwind_GetGR(context, 1));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
564 uintptr_t *callersSP = reinterpret_cast<uintptr_t*>(currentSP[0]);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
565 callersSP[3] = reinterpret_cast<uintptr_t>(unwind_exception);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
566 _LIBCXXABI_TRACE_STATETAB("Handshake: set unwind_exception=%p in stack=%p\n", reinterpret_cast<void*>(unwind_exception), reinterpret_cast<void*>(callersSP));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
567 // Jump to the handler.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
568 _Unwind_SetIP(context, results.landingPad);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
569 return _URC_INSTALL_CONTEXT;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
570 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
571 // Did not find a handler. Return the results of the scan. Normally
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
572 // _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
573 return results.reason;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
574 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
575 // We were called improperly: neither a phase 1 or phase 2 search.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
576 return _URC_FATAL_PHASE1_ERROR;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
577 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
578 } // namespace __state_table_eh
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
579
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
580 // The following are EH helper functions for xlclang++ compiled code.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
581
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
582 // __xlc_catch_matchv2
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
583 // Check whether the thrown object matches the catch handler's exception
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
584 // declaration. If there is a match, the function returns true with adjusted
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
585 // address of the thrown object. Otherwise, returns false.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
586 _LIBCXXABI_FUNC_VIS bool
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
587 __xlc_catch_matchv2(_Unwind_Exception* exceptionObject, std::type_info* catchTypeInfo, void*& obj) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
588 _LIBCXXABI_TRACE_STATETAB("Entering %s, exceptionObject=%p\n", __func__, reinterpret_cast<void*>(exceptionObject));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
589
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
590 if (!__isOurExceptionClass(exceptionObject)) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
591 _LIBCXXABI_TRACE_STATETAB0("No match, not a C++ exception\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
592 return false;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
593 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
594
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
595 __cxa_exception* exceptionHeader = 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
596
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
597 if (__getExceptionClass(exceptionObject) == kOurDependentExceptionClass) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
598 // Walk to the __cxa_dependent_exception primary exception for the
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
599 // exception object and its type_info.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
600 __cxa_dependent_exception* dependentExceptionHeader =
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
601 reinterpret_cast<__cxa_dependent_exception*>(exceptionObject + 1) - 1;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
602 exceptionHeader = reinterpret_cast<__cxa_exception*>(dependentExceptionHeader->primaryException) - 1;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
603 _LIBCXXABI_TRACE_STATETAB("exceptionObject 0x%p is a dependent, primary 0x%p\n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
604 reinterpret_cast<void*>(exceptionObject),
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
605 reinterpret_cast<void*>(&exceptionHeader->unwindHeader));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
606 exceptionObject = &exceptionHeader->unwindHeader;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
607 } else {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
608 _LIBCXXABI_TRACE_STATETAB("exceptionObject %p is NOT a dependent\n", reinterpret_cast<void*>(exceptionObject));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
609 exceptionHeader = reinterpret_cast<__cxa_exception*>(exceptionObject + 1) - 1;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
610 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
611
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
612 void* thrownObject = reinterpret_cast<void*>(exceptionObject + 1);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
613 std::type_info* throwTypeInfo = exceptionHeader->exceptionType;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
614
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
615 // Get the type info for the thrown type and this catch clause and
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
616 // see if the catch caluse can catch that type.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
617
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
618 __cxxabiv1::__shim_type_info* catchType = reinterpret_cast<__cxxabiv1::__shim_type_info*>(catchTypeInfo);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
619 __cxxabiv1::__shim_type_info* throwType = reinterpret_cast<__cxxabiv1::__shim_type_info*>(throwTypeInfo);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
620 _LIBCXXABI_TRACE_STATETAB("UnwindException=%p, thrownObject=%p, throwTypeInfo=%p(%s), catchTypeInfo=%p(%s)\n",
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
621 reinterpret_cast<void*>(exceptionObject), thrownObject, reinterpret_cast<void*>(throwType),
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
622 throwType->name(), reinterpret_cast<void*>(catchType), catchType->name());
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
623 if (catchType->can_catch(throwType, thrownObject)) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
624 exceptionHeader->adjustedPtr = thrownObject;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
625 obj = thrownObject;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
626 _LIBCXXABI_TRACE_STATETAB("Match found for thrownObject=%p\n", thrownObject);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
627 return true;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
628 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
629 _LIBCXXABI_TRACE_STATETAB0("No match\n");
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
630 return false;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
631 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
632
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
633 // __xlc_throw_badexception
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
634 // This function is for xlclang++. It allocates and throws a bad_exception.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
635 // During unwinding for this bad_exception, the previous exception which is
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
636 // not matching the throw spec will be cleaned up. Thus having the same
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
637 // effect as replace the top most exception (which is bad) with a bad_exception.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
638 _LIBCXXABI_FUNC_VIS void __xlc_throw_badexception() {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
639 _LIBCXXABI_TRACE_STATETAB("Entering function: %s\n\n", __func__);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
640 void* newexception = new (__cxa_allocate_exception(sizeof(std::bad_exception))) std::bad_exception;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
641 __cxa_throw(newexception, const_cast<std::type_info*>(&typeid(std::bad_exception)), 0);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
642 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
643
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
644 // force_a_stackframe
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
645 // This function is called by __xlc_exception_handle() to ensure a stack frame
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
646 // is created for __xlc_exception_handle().
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
647 __attribute__((noinline, optnone))
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
648 static void force_a_stackframe() {}
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
649
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
650 // __xlc_exception_handle
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
651 // This function is for xlclang++. It returns the address of the exception
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
652 // object stored in the reserved field in the stack of the caller of the
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
653 // function that calls __xlc_exception_handle() (within the link area for the
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
654 // call to the latter). The address is stored by the personality routine for
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
655 // xlclang++ compiled code. The implementation of __xlc_exception_handle()
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
656 // assumes a stack frame is created for it. The following ensures this
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
657 // assumption holds true: 1) a call to force_a_stackframe() is made inside
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
658 // __xlc_exception_handle() to make it non-leaf; and 2) optimizations are
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
659 // disabled for this function with attribute 'optnone'. Note: this function
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
660 // may not work as expected if these are changed.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
661 __attribute__((optnone))
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
662 _LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
663 // Make a call to force_a_stackframe() so that the compiler creates a stack
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
664 // frame for this function.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
665 force_a_stackframe();
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
666
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
667 // Get the SP of this function, i.e., __xlc_exception_handle().
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
668 uintptr_t *lastStack;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
669 asm("mr %0, 1" : "=r"(lastStack));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
670 // Get the SP of the caller of __xlc_exception_handle().
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
671 uintptr_t *callerStack = reinterpret_cast<uintptr_t*>(lastStack[0]);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
672 // Get the SP of the caller of the caller.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
673 uintptr_t *callerStack2 = reinterpret_cast<uintptr_t*>(callerStack[0]);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
674 uintptr_t exceptionObject = callerStack2[3];
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
675 _LIBCXXABI_TRACE_STATETAB("Handshake: exceptionObject=%p from stack=%p\n", reinterpret_cast<void*>(exceptionObject), reinterpret_cast<void*>(callerStack2));
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
676 return exceptionObject;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
677 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
678
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
679 // xlclang++ may generate calls to __Deleted_Virtual.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
680 _LIBCXXABI_FUNC_VIS void __Deleted_Virtual() { abort(); }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
681
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
682 // __catchThrownException is called during AIX library initialization and
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
683 // termination to handle exceptions. An implementation is also provided in
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
684 // libC.a(shrcore.o). This implementation is provided for applications that
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
685 // link with -lc++ (the xlclang++ or ibm-clang++ link default.)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
686 _LIBCXXABI_FUNC_VIS int
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
687 __catchThrownException(void (*cdfunc)(void), // function which may fail
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
688 void (*cleanup)(void*), // cleanup function
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
689 void* cleanuparg, // parameter to cleanup function
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
690 int action) { // control exception throwing and termination
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
691 enum Action : int { None = 0, Rethrow = 1, Terminate = 2 };
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
692 if (!cdfunc)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
693 return 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
694 if (action == Action::Rethrow && !cleanup) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
695 // No cleanup and rethrow is effectively no-op.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
696 // Avoid the catch handler when possible to allow exceptions generated
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
697 // from xlC binaries to flow through.
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
698 (*cdfunc)();
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
699 return 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
700 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
701 try {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
702 (*cdfunc)();
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
703 } catch (...) {
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
704 if (action == Action::Terminate)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
705 std::terminate();
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
706 if (cleanup)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
707 (*cleanup)(cleanuparg);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
708 if (action == Action::Rethrow)
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
709 throw;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
710 assert(action == Action::None);
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
711 return -1; // FAILED
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
712 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
713 return 0;
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
714 }
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
715
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
716 } // extern "C"
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
717
c4bab56944e8 LLVM 16
kono
parents:
diff changeset
718 } // __cxxabiv1