annotate libcxxabi/src/aix_state_tab_eh.inc @ 266:00f31e85ec16 default tip

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