xref: /netbsd-src/external/gpl3/gcc.old/dist/libphobos/libdruntime/gcc/unwind/generic.d (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1 // Exception handling and frame unwind runtime interface routines.
2 // Copyright (C) 2011-2020 Free Software Foundation, Inc.
3 
4 // GCC is free software; you can redistribute it and/or modify it under
5 // the terms of the GNU General Public License as published by the Free
6 // Software Foundation; either version 3, or (at your option) any later
7 // version.
8 
9 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
10 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 // for more details.
13 
14 // Under Section 7 of GPL version 3, you are granted additional
15 // permissions described in the GCC Runtime Library Exception, version
16 // 3.1, as published by the Free Software Foundation.
17 
18 // You should have received a copy of the GNU General Public License and
19 // a copy of the GCC Runtime Library Exception along with this program;
20 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
21 // <http://www.gnu.org/licenses/>.
22 
23 // extern(C) interface for the generic unwinder library.
24 // This corresponds to unwind-generic.h
25 
26 module gcc.unwind.generic;
27 
28 import gcc.config;
29 
30 static if (!GNU_ARM_EABI_Unwinder):
31 
32 import gcc.builtins;
33 
34 // This is derived from the C++ ABI for IA-64.  Where we diverge
35 // for cross-architecture compatibility are noted with "@@@".
36 
37 extern (C):
38 
39 // Placed outside @nogc in order to not constrain what the callback does.
40 // ??? Does this really need to be extern(C) alias?
41 
42 extern(C) alias _Unwind_Exception_Cleanup_Fn
43     = void function(_Unwind_Reason_Code, _Unwind_Exception*);
44 
45 extern(C) alias _Unwind_Stop_Fn
46     = _Unwind_Reason_Code function(int, _Unwind_Action,
47                                    _Unwind_Exception_Class,
48                                    _Unwind_Exception*,
49                                    _Unwind_Context*, void*);
50 
51 extern(C) alias _Unwind_Trace_Fn
52     = _Unwind_Reason_Code function(_Unwind_Context*, void*);
53 
54 // The personality routine is the function in the C++ (or other language)
55 // runtime library which serves as an interface between the system unwind
56 // library and language-specific exception handling semantics.  It is
57 // specific to the code fragment described by an unwind info block, and
58 // it is always referenced via the pointer in the unwind info block, and
59 // hence it has no ABI-specified name.
60 
61 // Note that this implies that two different C++ implementations can
62 // use different names, and have different contents in the language
63 // specific data area.  Moreover, that the language specific data
64 // area contains no version info because name of the function invoked
65 // provides more effective versioning by detecting at link time the
66 // lack of code to handle the different data format.
67 
68 extern(C) alias _Unwind_Personality_Fn
69     = _Unwind_Reason_Code function(int, _Unwind_Action,
70                                    _Unwind_Exception_Class,
71                                    _Unwind_Exception*,
72                                    _Unwind_Context*);
73 
74 @nogc:
75 
76 // Level 1: Base ABI
77 
78 // @@@ The IA-64 ABI uses uint64 throughout.
79 // Most places this is inefficient for 32-bit and smaller machines.
80 alias _Unwind_Word = __builtin_unwind_uint;
81 alias _Unwind_Sword = __builtin_unwind_int;
version(IA64)82 version (IA64)
83 {
84     version (HPUX)
85         alias _Unwind_Ptr = __builtin_machine_uint;
86     else
87         alias _Unwind_Ptr = __builtin_pointer_uint;
88 }
89 else
90 {
91     alias _Unwind_Ptr = __builtin_pointer_uint;
92 }
93 alias _Unwind_Internal_Ptr = __builtin_pointer_uint;
94 
95 // @@@ The IA-64 ABI uses a 64-bit word to identify the producer and
96 // consumer of an exception.  We'll go along with this for now even on
97 // 32-bit machines.  We'll need to provide some other option for
98 // 16-bit machines and for machines with > 8 bits per byte.
99 alias _Unwind_Exception_Class = ulong;
100 
101 // The unwind interface uses reason codes in several contexts to
102 // identify the reasons for failures or other actions.
103 alias _Unwind_Reason_Code = uint;
104 enum : _Unwind_Reason_Code
105 {
106     _URC_NO_REASON = 0,
107     _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
108     _URC_FATAL_PHASE2_ERROR = 2,
109     _URC_FATAL_PHASE1_ERROR = 3,
110     _URC_NORMAL_STOP = 4,
111     _URC_END_OF_STACK = 5,
112     _URC_HANDLER_FOUND = 6,
113     _URC_INSTALL_CONTEXT = 7,
114     _URC_CONTINUE_UNWIND = 8
115 }
116 
117 // The unwind interface uses a pointer to an exception header object
118 // as its representation of an exception being thrown. In general, the
119 // full representation of an exception object is language- and
120 // implementation-specific, but it will be prefixed by a header
121 // understood by the unwind interface.
122 
123 // @@@ The IA-64 ABI says that this structure must be double-word aligned.
124 // Taking that literally does not make much sense generically.  Instead we
125 // provide the maximum alignment required by any type for the machine.
126      version (ARM)      private enum __aligned__ = 8;
127 else version (AArch64)  private enum __aligned__ = 16;
128 else version (HPPA)     private enum __aligned__ = 8;
129 else version (HPPA64)   private enum __aligned__ = 16;
130 else version (MIPS_N32) private enum __aligned__ = 16;
131 else version (MIPS_N64) private enum __aligned__ = 16;
132 else version (MIPS32)   private enum __aligned__ = 8;
133 else version (MIPS64)   private enum __aligned__ = 8;
134 else version (PPC)      private enum __aligned__ = 16;
135 else version (PPC64)    private enum __aligned__ = 16;
136 else version (RISCV32)  private enum __aligned__ = 16;
137 else version (RISCV64)  private enum __aligned__ = 16;
138 else version (S390)     private enum __aligned__ = 8;
139 else version (SPARC)    private enum __aligned__ = 8;
140 else version (SPARC64)  private enum __aligned__ = 16;
141 else version (SystemZ)  private enum __aligned__ = 8;
142 else version (X86)      private enum __aligned__ = 16;
143 else version (X86_64)   private enum __aligned__ = 16;
144 else static assert( false, "Platform not supported.");
145 
146 align(__aligned__) struct _Unwind_Exception
147 {
148     _Unwind_Exception_Class exception_class;
149     _Unwind_Exception_Cleanup_Fn exception_cleanup;
150     _Unwind_Word private_1;
151     _Unwind_Word private_2;
152 }
153 
154 // The ACTIONS argument to the personality routine is a bitwise OR of one
155 // or more of the following constants.
156 alias _Unwind_Action = int;
157 enum : _Unwind_Action
158 {
159     _UA_SEARCH_PHASE = 1,
160     _UA_CLEANUP_PHASE = 2,
161     _UA_HANDLER_FRAME = 4,
162     _UA_FORCE_UNWIND = 8,
163     _UA_END_OF_STACK = 16
164 }
165 
166 // This is an opaque type used to refer to a system-specific data
167 // structure used by the system unwinder. This context is created and
168 // destroyed by the system, and passed to the personality routine
169 // during unwinding.
170 struct _Unwind_Context;
171 
172 // Raise an exception, passing along the given exception object.
173 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*);
174 
175 // Raise an exception for forced unwinding.
176 _Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception*, _Unwind_Stop_Fn, void*);
177 
178 // Helper to invoke the exception_cleanup routine.
179 void _Unwind_DeleteException(_Unwind_Exception*);
180 
181 // Resume propagation of an existing exception.  This is used after
182 // e.g. executing cleanup code, and not to implement rethrowing.
183 void _Unwind_Resume(_Unwind_Exception*);
184 
185 // @@@ Resume propagation of an FORCE_UNWIND exception, or to rethrow
186 // a normal exception that was handled.
187 _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception*);
188 
189 // @@@ Use unwind data to perform a stack backtrace.  The trace callback
190 // is called for every stack frame in the call chain, but no cleanup
191 // actions are performed.
192 _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*);
193 
194 // These functions are used for communicating information about the unwind
195 // context (i.e. the unwind descriptors and the user register state) between
196 // the unwind library and the personality routine and landing pad.  Only
197 // selected registers may be manipulated.
198 
199 _Unwind_Word _Unwind_GetGR(_Unwind_Context*, int);
200 void _Unwind_SetGR(_Unwind_Context*, int, _Unwind_Word);
201 
202 _Unwind_Ptr _Unwind_GetIP(_Unwind_Context*);
203 _Unwind_Ptr _Unwind_GetIPInfo(_Unwind_Context*, int*);
204 void _Unwind_SetIP(_Unwind_Context*, _Unwind_Ptr);
205 
206 // @@@ Retrieve the CFA of the given context.
207 _Unwind_Word _Unwind_GetCFA(_Unwind_Context*);
208 
209 void* _Unwind_GetLanguageSpecificData(_Unwind_Context*);
210 
211 _Unwind_Ptr _Unwind_GetRegionStart(_Unwind_Context*);
212 
213 
214 // @@@ The following alternate entry points are for setjmp/longjmp
215 // based unwinding.
216 
217 struct SjLj_Function_Context;
218 extern void _Unwind_SjLj_Register(SjLj_Function_Context*);
219 extern void _Unwind_SjLj_Unregister(SjLj_Function_Context*);
220 
221 _Unwind_Reason_Code _Unwind_SjLj_RaiseException(_Unwind_Exception*);
222 _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(_Unwind_Exception*, _Unwind_Stop_Fn, void*);
223 void _Unwind_SjLj_Resume(_Unwind_Exception*);
224 _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception*);
225 
226 // @@@ The following provide access to the base addresses for text
227 // and data-relative addressing in the LDSA.  In order to stay link
228 // compatible with the standard ABI for IA-64, we inline these.
229 
version(IA64)230 version (IA64)
231 {
232     _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context* _C)
233     {
234         // The GP is stored in R1.
235         return _Unwind_GetGR(_C, 1);
236     }
237 
238     _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*)
239     {
240         __builtin_abort();
241         return 0;
242     }
243 
244     // @@@ Retrieve the Backing Store Pointer of the given context.
245     _Unwind_Word _Unwind_GetBSP(_Unwind_Context*);
246 }
247 else
248 {
249     _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context*);
250     _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*);
251 }
252 
253 // @@@ Given an address, return the entry point of the function that
254 // contains it.
255 extern void* _Unwind_FindEnclosingFunction(void* pc);
256 
257 
258 // leb128 type numbers have a potentially unlimited size.
259 // The target of the following definitions of _sleb128_t and _uleb128_t
260 // is to have efficient data types large enough to hold the leb128 type
261 // numbers used in the unwind code.
262 // Mostly these types will simply be defined to long and unsigned long
263 // except when a unsigned long data type on the target machine is not
264 // capable of storing a pointer.
265 
266 static if (__builtin_clong.sizeof >= (void*).sizeof)
267 {
268     alias _sleb128_t = __builtin_clong;
269     alias _uleb128_t = __builtin_culong;
270 }
271 else static if (long.sizeof >= (void*).sizeof)
272 {
273     alias _sleb128_t = long;
274     alias _uleb128_t = ulong;
275 }
276 else
277 {
278     static assert(false, "What type shall we use for _sleb128_t?");
279 }
280 
version(GNU_SEH_Exceptions)281 version (GNU_SEH_Exceptions)
282 {
283     // We're lazy, exact definition in MinGW/winnt.h
284     enum EXCEPTION_DISPOSITION
285     {
286         ExceptionContinueExecution,
287         ExceptionContinueSearch,
288         ExceptionNestedException,
289         ExceptionCollidedUnwind
290     }
291 
292     extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*,
293                                                           _Unwind_Personality_Fn);
294 }
295