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 ARM EABI and C6X unwinders.
24// This corresponds to unwind-arm-common.h
25
26module gcc.unwind.arm_common;
27
28import gcc.config;
29
30static if (GNU_ARM_EABI_Unwinder):
31
32import gcc.builtins;
33
34extern (C):
35
36// Placed outside @nogc in order to not constrain what the callback does.
37// ??? Does this really need to be extern(C) alias?
38extern(C) alias _Unwind_Exception_Cleanup_Fn
39    = void function(_Unwind_Reason_Code, _Unwind_Exception*);
40
41extern(C) alias personality_routine
42    = _Unwind_Reason_Code function(_Unwind_State,
43                                   _Unwind_Control_Block*,
44                                   _Unwind_Context*);
45
46extern(C) alias _Unwind_Stop_Fn
47    =_Unwind_Reason_Code function(int, _Unwind_Action,
48                                  _Unwind_Exception_Class,
49                                  _Unwind_Control_Block*,
50                                  _Unwind_Context*, void*);
51
52extern(C) alias _Unwind_Trace_Fn
53    = _Unwind_Reason_Code function(_Unwind_Context*, void*);
54
55@nogc:
56
57alias _Unwind_Word = __builtin_machine_uint;
58alias _Unwind_Sword = __builtin_machine_int;
59alias _Unwind_Ptr = __builtin_pointer_uint;
60alias _Unwind_Internal_Ptr =__builtin_pointer_uint;
61alias _uw = _Unwind_Word;
62alias _uw64 = ulong;
63alias _uw16 = ushort;
64alias _uw8 = ubyte;
65
66alias _Unwind_Reason_Code = uint;
67enum : _Unwind_Reason_Code
68{
69    _URC_OK = 0,        // operation completed successfully
70    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
71    _URC_END_OF_STACK = 5,
72    _URC_HANDLER_FOUND = 6,
73    _URC_INSTALL_CONTEXT = 7,
74    _URC_CONTINUE_UNWIND = 8,
75    _URC_FAILURE = 9    // unspecified failure of some kind
76}
77
78alias _Unwind_State = int;
79enum : _Unwind_State
80{
81    _US_VIRTUAL_UNWIND_FRAME = 0,
82    _US_UNWIND_FRAME_STARTING = 1,
83    _US_UNWIND_FRAME_RESUME = 2,
84    _US_ACTION_MASK = 3,
85    _US_FORCE_UNWIND = 8,
86    _US_END_OF_STACK = 16
87}
88
89// Provided only for for compatibility with existing code.
90alias _Unwind_Action = int;
91enum : _Unwind_Action
92{
93    _UA_SEARCH_PHASE = 1,
94    _UA_CLEANUP_PHASE = 2,
95    _UA_HANDLER_FRAME = 4,
96    _UA_FORCE_UNWIND = 8,
97    _UA_END_OF_STACK = 16,
98    _URC_NO_REASON = _URC_OK
99}
100
101struct _Unwind_Context;
102alias _Unwind_EHT_Header = _uw;
103
104struct _Unwind_Control_Block
105{
106    _Unwind_Exception_Class exception_class = '\0';
107    _Unwind_Exception_Cleanup_Fn exception_cleanup;
108    // Unwinder cache, private fields for the unwinder's use
109    struct _unwinder_cache
110    {
111        _uw reserved1;  // Forced unwind stop fn, 0 if not forced
112        _uw reserved2;  // Personality routine address
113        _uw reserved3;  // Saved callsite address
114        _uw reserved4;  // Forced unwind stop arg
115        _uw reserved5;
116    }
117    _unwinder_cache unwinder_cache;
118    // Propagation barrier cache (valid after phase 1):
119    struct _barrier_cache
120    {
121        _uw sp;
122        _uw[5] bitpattern;
123    }
124    _barrier_cache barrier_cache;
125    // Cleanup cache (preserved over cleanup):
126    struct _cleanup_cache
127    {
128        _uw[4] bitpattern;
129    }
130    _cleanup_cache cleanup_cache;
131    // Pr cache (for pr's benefit):
132    struct _pr_cache
133    {
134        _uw fnstart;                // function start address */
135        _Unwind_EHT_Header* ehtp;   // pointer to EHT entry header word
136        _uw additional;             // additional data
137        _uw reserved1;
138    }
139    _pr_cache pr_cache;
140    long[0] _force_alignment;       // Force alignment to 8-byte boundary
141}
142
143// Virtual Register Set
144alias _Unwind_VRS_RegClass = int;
145enum : _Unwind_VRS_RegClass
146{
147    _UVRSC_CORE = 0,    // integer register
148    _UVRSC_VFP = 1,     // vfp
149    _UVRSC_FPA = 2,     // fpa
150    _UVRSC_WMMXD = 3,   // Intel WMMX data register
151    _UVRSC_WMMXC = 4    // Intel WMMX control register
152}
153
154alias _Unwind_VRS_DataRepresentation = int;
155enum : _Unwind_VRS_DataRepresentation
156{
157    _UVRSD_UINT32 = 0,
158    _UVRSD_VFPX = 1,
159    _UVRSD_FPAX = 2,
160    _UVRSD_UINT64 = 3,
161    _UVRSD_FLOAT = 4,
162    _UVRSD_DOUBLE = 5
163}
164
165alias _Unwind_VRS_Result = int;
166enum : _Unwind_VRS_Result
167{
168    _UVRSR_OK = 0,
169    _UVRSR_NOT_IMPLEMENTED = 1,
170    _UVRSR_FAILED = 2
171}
172
173// Frame unwinding state.
174struct __gnu_unwind_state
175{
176    _uw data;           // The current word (bytes packed msb first).
177    _uw* next;          // Pointer to the next word of data.
178    _uw8 bytes_left;    // The number of bytes left in this word.
179    _uw8 words_left;    // The number of words pointed to by ptr.
180}
181
182_Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context*, _Unwind_VRS_RegClass,
183                                   _uw, _Unwind_VRS_DataRepresentation,
184                                   void*);
185
186_Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context*, _Unwind_VRS_RegClass,
187                                   _uw, _Unwind_VRS_DataRepresentation,
188                                   void*);
189
190_Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context*, _Unwind_VRS_RegClass,
191                                   _uw, _Unwind_VRS_DataRepresentation);
192
193
194// Support functions for the PR.
195alias _Unwind_Exception = _Unwind_Control_Block;
196alias _Unwind_Exception_Class = char[8];
197
198void* _Unwind_GetLanguageSpecificData(_Unwind_Context*);
199_Unwind_Ptr _Unwind_GetRegionStart(_Unwind_Context*);
200
201_Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context*);
202// This should never be used.
203_Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*);
204
205// Interface functions:
206_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block*);
207void _Unwind_Resume(_Unwind_Control_Block*);
208_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Control_Block*);
209
210_Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Control_Block*,
211                                         _Unwind_Stop_Fn, void*);
212
213// @@@ Use unwind data to perform a stack backtrace.  The trace callback
214// is called for every stack frame in the call chain, but no cleanup
215// actions are performed.
216_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*);
217
218_Unwind_Word _Unwind_GetCFA(_Unwind_Context*);
219void _Unwind_Complete(_Unwind_Control_Block*);
220void _Unwind_DeleteException(_Unwind_Exception*);
221
222_Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Control_Block*,
223                                       _Unwind_Context*);
224_Unwind_Reason_Code __gnu_unwind_execute(_Unwind_Context*,
225                                         __gnu_unwind_state*);
226
227_Unwind_Word _Unwind_GetGR(_Unwind_Context* context, int regno)
228{
229    _uw val;
230    _Unwind_VRS_Get(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
231    return val;
232}
233
234void _Unwind_SetGR(_Unwind_Context* context, int regno, _Unwind_Word val)
235{
236    _Unwind_VRS_Set(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
237}
238
239// leb128 type numbers have a potentially unlimited size.
240// The target of the following definitions of _sleb128_t and _uleb128_t
241// is to have efficient data types large enough to hold the leb128 type
242// numbers used in the unwind code.
243alias _sleb128_t = __builtin_clong;
244alias _uleb128_t = __builtin_culong;
245