summaryrefslogtreecommitdiff
path: root/config/coreboot/fam15h_rdimm/patches/0011-gcc-8.3.0_gnat_eh_new.patch
blob: 443d8512125011673e73c9a03f6e86ef34a19d7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
From c5a03de594d6bb6ea5012a6549404e4631c903c8 Mon Sep 17 00:00:00 2001
From: Alexandre Oliva <oliva@adacore.com>
Date: Wed, 9 Aug 2023 16:57:31 +0200
Subject: [PATCH] crossgcc: Backport GNAT exception handler v1 patch

Signed-off-by: Adrien Bourmault <neox@gnu.org>
---
 .../patches/gcc-8.3.0_gnat_eh_new.patch       | 212 ++++++++++++++++++
 1 file changed, 212 insertions(+)
 create mode 100644 util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch

diff --git a/util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch b/util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch
new file mode 100644
index 00000000..75e4f18d
--- /dev/null
+++ b/util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch
@@ -0,0 +1,212 @@
+diff --git a/gcc/ada/libgnat/a-exexpr.adb b/gcc/ada/libgnat/a-exexpr.adb
+index b1aa1c6e6ba..5e72fd6e3f2 100644
+--- a/gcc/ada/libgnat/a-exexpr.adb
++++ b/gcc/ada/libgnat/a-exexpr.adb
+@@ -197,15 +197,75 @@ package body Exception_Propagation is
+    --  whose machine occurrence is Mo. The message is empty, the backtrace
+    --  is empty too and the exception identity is Foreign_Exception.
+ 
+-   --  Hooks called when entering/leaving an exception handler for a given
+-   --  occurrence, aimed at handling the stack of active occurrences. The
+-   --  calls are generated by gigi in tree_transform/N_Exception_Handler.
++   --  Hooks called when entering/leaving an exception handler for a
++   --  given occurrence.  The calls are generated by gigi in
++   --  Exception_Handler_to_gnu_gcc.
++
++   --  Begin_Handler_v1, called when entering an exception handler,
++   --  claims responsibility for the handler to release the
++   --  GCC_Exception occurrence.  End_Handler_v1, called when
++   --  leaving the handler, releases the occurrence, unless the
++   --  occurrence is propagating further up, or the handler is
++   --  dynamically nested in the context of another handler that
++   --  claimed responsibility for releasing that occurrence.
++
++   --  Responsibility is claimed by changing the Cleanup field to
++   --  Claimed_Cleanup, which enables claimed exceptions to be
++   --  recognized, and avoids accidental releases even by foreign
++   --  handlers.
++
++   function Begin_Handler_v1
++     (GCC_Exception : not null GCC_Exception_Access)
++     return System.Address;
++   pragma Export (C, Begin_Handler_v1, "__gnat_begin_handler_v1");
++   --  Called when entering an exception handler.  Claim
++   --  responsibility for releasing GCC_Exception, by setting the
++   --  cleanup/release function to Claimed_Cleanup, and return the
++   --  address of the previous cleanup/release function.
++
++   procedure End_Handler_v1
++     (GCC_Exception : not null GCC_Exception_Access;
++      Saved_Cleanup : System.Address;
++      Propagating_Exception : GCC_Exception_Access);
++   pragma Export (C, End_Handler_v1, "__gnat_end_handler_v1");
++   --  Called when leaving an exception handler.  Restore the
++   --  Saved_Cleanup in the GCC_Exception occurrence, and then release
++   --  it, unless it remains claimed by an enclosing handler, or
++   --  GCC_Exception and Propagating_Exception are the same
++   --  occurrence.  Propagating_Exception could be either an
++   --  occurrence (re)raised within the handler of GCC_Exception, when
++   --  we're executing as an exceptional cleanup, or null, if we're
++   --  completing the handler of GCC_Exception normally.
++
++   procedure Claimed_Cleanup
++     (Reason : Unwind_Reason_Code;
++      GCC_Exception : not null GCC_Exception_Access);
++   pragma Export (C, Claimed_Cleanup, "__gnat_claimed_cleanup");
++   --  A do-nothing placeholder installed as GCC_Exception.Cleanup
++   --  while handling GCC_Exception, to claim responsibility for
++   --  releasing it, and to stop it from being accidentally released.
++
++   --  The following are version 0 implementations of the version 1
++   --  hooks above.  They remain in place for compatibility with the
++   --  output of compilers that still use version 0, such as those
++   --  used during bootstrap.  They are interoperable with the v1
++   --  hooks, except that the older versions may malfunction when
++   --  handling foreign exceptions passed to Reraise_Occurrence.
+ 
+    procedure Begin_Handler (GCC_Exception : not null GCC_Exception_Access);
+    pragma Export (C, Begin_Handler, "__gnat_begin_handler");
++   --  Called when entering an exception handler translated by an old
++   --  compiler.  It does nothing.
+ 
+    procedure End_Handler (GCC_Exception : GCC_Exception_Access);
+    pragma Export (C, End_Handler, "__gnat_end_handler");
++   --  Called when leaving an exception handler translated by an old
++   --  compiler.  It releases GCC_Exception, unless it is null.  It is
++   --  only ever null when the handler has a 'raise;' translated by a
++   --  v0-using compiler.  The artificial handler variable passed to
++   --  End_Handler was set to null to tell End_Handler to refrain from
++   --  releasing the reraised exception.  In v1 safer ways are used to
++   --  accomplish that.
+ 
+    --------------------------------------------------------------------
+    -- Accessors to Basic Components of a GNAT Exception Data Pointer --
+@@ -352,6 +412,128 @@ package body Exception_Propagation is
+       end if;
+    end Setup_Current_Excep;
+ 
++   ----------------------
++   -- Begin_Handler_v1 --
++   ----------------------
++
++   function Begin_Handler_v1
++     (GCC_Exception : not null GCC_Exception_Access)
++     return System.Address is
++      Saved_Cleanup : constant System.Address := GCC_Exception.Cleanup;
++   begin
++      --  Claim responsibility for releasing this exception, and stop
++      --  others from releasing it.
++      GCC_Exception.Cleanup := Claimed_Cleanup'Address;
++      return Saved_Cleanup;
++   end Begin_Handler_v1;
++
++   --------------------
++   -- End_Handler_v1 --
++   --------------------
++
++   procedure End_Handler_v1
++     (GCC_Exception : not null GCC_Exception_Access;
++      Saved_Cleanup : System.Address;
++      Propagating_Exception : GCC_Exception_Access) is
++   begin
++      GCC_Exception.Cleanup := Saved_Cleanup;
++      --  Restore the Saved_Cleanup, so that it is either used to
++      --  release GCC_Exception below, or transferred to the next
++      --  handler of the Propagating_Exception occurrence.  The
++      --  following test ensures that an occurrence is only released
++      --  once, even after reraises.
++      --
++      --  The idea is that the GCC_Exception is not to be released
++      --  unless it had an unclaimed Cleanup when the handler started
++      --  (see Begin_Handler_v1 above), but if we propagate across its
++      --  handler a reraise of the same exception, we transfer to the
++      --  Propagating_Exception the responsibility for running the
++      --  Saved_Cleanup when its handler completes.
++      --
++      --  This ownership transfer mechanism ensures safety, as in
++      --  single release and no dangling pointers, because there is no
++      --  way to hold on to the Machine_Occurrence of an
++      --  Exception_Occurrence: the only situations in which another
++      --  Exception_Occurrence gets the same Machine_Occurrence are
++      --  through Reraise_Occurrence, and plain reraise, and so we
++      --  have the following possibilities:
++      --
++      --  - Reraise_Occurrence is handled within the running handler,
++      --  and so when completing the dynamically nested handler, we
++      --  must NOT release the exception.  A Claimed_Cleanup upon
++      --  entry of the nested handler, installed when entering the
++      --  enclosing handler, ensures the exception will not be
++      --  released by the nested handler, but rather by the enclosing
++      --  handler.
++      --
++      --  - Reraise_Occurrence/reraise escapes the running handler,
++      --  and we run as an exceptional cleanup for GCC_Exception.  The
++      --  Saved_Cleanup was reinstalled, but since we're propagating
++      --  the same machine occurrence, we do not release it.  Instead,
++      --  we transfer responsibility for releasing it to the eventual
++      --  handler of the propagating exception.
++      --
++      --  - An unrelated exception propagates through the running
++      --  handler.  We restored GCC_Exception.Saved_Cleanup above.
++      --  Since we're propagating a different exception, we proceed to
++      --  release GCC_Exception, unless Saved_Cleanup was
++      --  Claimed_Cleanup, because then we know we're not in the
++      --  outermost handler for GCC_Exception.
++      --
++      --  - The handler completes normally, so it reinstalls the
++      --  Saved_Cleanup and runs it, unless it was Claimed_Cleanup.
++      --  If Saved_Cleanup is null, Unwind_DeleteException (currently)
++      --  has no effect, so we could skip it, but if it is ever
++      --  changed to do more in this case, we're ready for that,
++      --  calling it exactly once.
++      if Saved_Cleanup /= Claimed_Cleanup'Address
++        and then
++        Propagating_Exception /= GCC_Exception
++      then
++         declare
++            Current : constant EOA := Get_Current_Excep.all;
++            Cur_Occ : constant GCC_Exception_Access
++              := To_GCC_Exception (Current.Machine_Occurrence);
++         begin
++            --  If we are releasing the Machine_Occurrence of the current
++            --  exception, reset the access to it, so that it is no
++            --  longer accessible.
++            if Cur_Occ = GCC_Exception then
++               Current.Machine_Occurrence := System.Null_Address;
++            end if;
++         end;
++         Unwind_DeleteException (GCC_Exception);
++      end if;
++   end End_Handler_v1;
++
++   ---------------------
++   -- Claimed_Cleanup --
++   ---------------------
++
++   procedure Claimed_Cleanup
++     (Reason : Unwind_Reason_Code;
++      GCC_Exception : not null GCC_Exception_Access) is
++      pragma Unreferenced (Reason);
++      pragma Unreferenced (GCC_Exception);
++   begin
++      --  This procedure should never run.  If it does, it's either a
++      --  version 0 handler or a foreign handler, attempting to
++      --  release an exception while a version 1 handler that claimed
++      --  responsibility for releasing the exception remains still
++      --  active.  This placeholder stops GCC_Exception from being
++      --  released by them.
++
++      --  We could get away with just Null_Address instead, with
++      --  nearly the same effect, but with this placeholder we can
++      --  detect and report unexpected releases, and we can tell apart
++      --  a GCC_Exception without a Cleanup, from one with another
++      --  active handler, so as to still call Unwind_DeleteException
++      --  exactly once: currently, Unwind_DeleteException does nothing
++      --  when the Cleanup is null, but should it ever be changed to
++      --  do more, we'll still be safe.
++      null;
++   end Claimed_Cleanup;
++
+    -------------------
+    -- Begin_Handler --
+    -------------------
-- 
2.30.2