Skip to content

Commit 107a9a0

Browse files
committed
Handle inherited discriminants in DWARF
gnat-llvm crashed while generating debuginfo for a variant part where the corresponding discriminant was inherited from a parent. It's not completely clear how this should be represented in DWARF, as I think it doesn't really make sense to refer to a DIE in some other type (and anyway implementing that might be difficult in LLVM). So, I decided to emit such discriminants in the derived type, but marked DW_AT_artificial. I've also patched gdb to ignore such fields when printing (but not when computing the runtime type).
1 parent 22b3ce3 commit 107a9a0

File tree

1 file changed

+96
-34
lines changed

1 file changed

+96
-34
lines changed

llvm-interface/gnatllvm-records-debug.adb

Lines changed: 96 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
-- of the license. --
1616
------------------------------------------------------------------------------
1717

18+
with Ada.Containers.Vectors;
19+
1820
with Nlists; use Nlists;
1921
with Sinput; use Sinput;
2022
with Uintp.LLVM; use Uintp.LLVM;
@@ -39,6 +41,15 @@ package body GNATLLVM.Records.Debug is
3941
Equivalent_Keys => "=");
4042
-- A map from a discriminant's entity to the LLVM debuginfo.
4143

44+
package Member_Vectors is new
45+
Ada.Containers.Vectors (Index_Type => Pos,
46+
Element_Type => Metadata_T);
47+
-- A vector of LLVM metadata, used when building the fields for a
48+
-- type or a variant part.
49+
50+
subtype Member_Vector is Member_Vectors.Vector;
51+
-- Type of vector of members.
52+
4253
function Convert_Choices (Choices : List_Id) return Word_Array;
4354
-- Convert a list of choices (the discrete choices selecting a
4455
-- variant part) to a word array. The resulting word array has an
@@ -47,15 +58,20 @@ package body GNATLLVM.Records.Debug is
4758
-- or if the choice list is not recognized in some way.
4859

4960
function Convert_One_Field (M : in out Discriminant_Map.Map;
50-
F : Record_Field_Kind_Id) return Metadata_T;
61+
F : Record_Field_Kind_Id;
62+
Artificial : Boolean := False)
63+
return Metadata_T;
5164
-- Convert a single field to LLVM debug metadata. M is a map to
5265
-- update; if the field is a discriminant, then it is recorded in
53-
-- the map for later lookup. Returns the LLVM debug metadata.
66+
-- the map for later lookup. If Artificial is True, the created
67+
-- field is marked artificial. Returns the LLVM debug metadata.
5468

5569
function Convert_Variant_Part (M : in out Discriminant_Map.Map;
5670
RI : Record_Info;
5771
Original_Type : Entity_Id;
58-
Is_Union : Boolean) return Metadata_Array
72+
Is_Union : Boolean;
73+
Toplevel_Members : in out Member_Vector)
74+
return Metadata_Array
5975
with pre => RI.Variants /= null;
6076
-- Convert a variant part to LLVM debug metadata, returning an
6177
-- array holding the LLVM debug metadata for all the relevant
@@ -64,10 +80,24 @@ package body GNATLLVM.Records.Debug is
6480
function Convert_RI_Chain (M : in out Discriminant_Map.Map;
6581
Start : Record_Info_Id;
6682
Original_Type : Entity_Id;
67-
Is_Union : Boolean) return Metadata_Array;
83+
Is_Union : Boolean;
84+
Toplevel_Members : in out Member_Vector;
85+
Outermost_Call : Boolean)
86+
return Metadata_Array;
6887
-- Convert a chain of Record_Info_Ids to LLVM debug metadata,
6988
-- returning an array holding the metadata for the relevant
70-
-- fields.
89+
-- fields. Toplevel_Members points to the vector of members for
90+
-- the outermost type being constructed; in some cases we may need
91+
-- to add a field there when processing a variant part. This is
92+
-- only null for the outermost call to Convert_RI_Chain.
93+
94+
function Convert_RI_Chain (M : in out Discriminant_Map.Map;
95+
Start : Record_Info_Id;
96+
Original_Type : Entity_Id;
97+
Is_Union : Boolean)
98+
return Metadata_Array;
99+
-- A wrapper for Convert_RI_Chain that creates the outermost
100+
-- member vector and passes it in.
71101

72102
---------------------
73103
-- Convert_Choices --
@@ -112,7 +142,8 @@ package body GNATLLVM.Records.Debug is
112142
-----------------------
113143

114144
function Convert_One_Field (M : in out Discriminant_Map.Map;
115-
F : Record_Field_Kind_Id) return Metadata_T
145+
F : Record_Field_Kind_Id;
146+
Artificial : Boolean := False) return Metadata_T
116147
is
117148
F_GT : constant GL_Type := Field_Type (F);
118149
Mem_MD : constant Metadata_T :=
@@ -125,18 +156,20 @@ package body GNATLLVM.Records.Debug is
125156
UI_To_ULL (Component_Bit_Offset (F));
126157
Storage_Offset : constant ULL :=
127158
(Offset / UBPU) * UBPU;
159+
Flags : constant DI_Flags_T :=
160+
(if Artificial then DI_Flag_Artificial else DI_Flag_Zero);
128161
MD : constant Metadata_T :=
129162
(if Is_Bitfield (F)
130163
then DI_Create_Bit_Field_Member_Type
131164
(No_Metadata_T, Name, File,
132165
Get_Physical_Line_Number (F_S),
133166
UI_To_ULL (Esize (F)), Offset,
134-
Storage_Offset, Mem_MD)
167+
Storage_Offset, Mem_MD, Flags)
135168
else DI_Create_Member_Type
136169
(No_Metadata_T, Name, File,
137170
Get_Physical_Line_Number (F_S),
138171
UI_To_ULL (Esize (F)),
139-
Get_Type_Alignment (F_GT), Offset, Mem_MD));
172+
Get_Type_Alignment (F_GT), Offset, Mem_MD, Flags));
140173
begin
141174
-- Ensure the field is available so that a later lookup of a
142175
-- discriminant will succeed.
@@ -152,10 +185,12 @@ package body GNATLLVM.Records.Debug is
152185
-- Convert_Variant_Part --
153186
--------------------------
154187

155-
function Convert_Variant_Part (M : in out Discriminant_Map.Map;
156-
RI : Record_Info;
157-
Original_Type : Entity_Id;
158-
Is_Union : Boolean) return Metadata_Array
188+
function Convert_Variant_Part
189+
(M : in out Discriminant_Map.Map;
190+
RI : Record_Info;
191+
Original_Type : Entity_Id;
192+
Is_Union : Boolean;
193+
Toplevel_Members : in out Member_Vector) return Metadata_Array
159194
is
160195
package Member_Table is new Table.Table
161196
(Table_Component_Type => Metadata_T,
@@ -173,7 +208,7 @@ package body GNATLLVM.Records.Debug is
173208
Fields : constant Metadata_Array :=
174209
(if Present (RI.Variants (J))
175210
then Convert_RI_Chain (M, RI.Variants (J), Original_Type,
176-
Is_Union)
211+
Is_Union, Toplevel_Members, False)
177212
else Empty_Fields);
178213
begin
179214
if Is_Union then
@@ -213,16 +248,16 @@ package body GNATLLVM.Records.Debug is
213248
function Convert_RI_Chain (M : in out Discriminant_Map.Map;
214249
Start : Record_Info_Id;
215250
Original_Type : Entity_Id;
216-
Is_Union : Boolean) return Metadata_Array
251+
Is_Union : Boolean;
252+
Toplevel_Members : in out Member_Vector;
253+
Outermost_Call : Boolean)
254+
return Metadata_Array
217255
is
218-
package Member_Table is new Table.Table
219-
(Table_Component_Type => Metadata_T,
220-
Table_Index_Type => Int,
221-
Table_Low_Bound => 1,
222-
Table_Initial => 20,
223-
Table_Increment => 5,
224-
Table_Name => "Member_Table");
225-
256+
Local_Members : aliased Member_Vector;
257+
Members_To_Update : constant access Member_Vector :=
258+
(if Outermost_Call
259+
then Toplevel_Members'Access
260+
else Local_Members'Access);
226261
Ridx : Record_Info_Id := Start;
227262
RI : Record_Info;
228263
F : Record_Field_Kind_Id;
@@ -243,7 +278,7 @@ package body GNATLLVM.Records.Debug is
243278
elsif Known_Static_Component_Bit_Offset (F) and then
244279
Known_Static_Esize (F)
245280
then
246-
Member_Table.Append (Convert_One_Field (M, F));
281+
Members_To_Update.Append (Convert_One_Field (M, F));
247282
end if;
248283

249284
F_Idx := FI.Next;
@@ -259,41 +294,68 @@ package body GNATLLVM.Records.Debug is
259294
RI.Variants /= null
260295
then
261296
declare
297+
Variant_MD : Metadata_T;
262298
MD : Metadata_T;
263299
Parts : constant Metadata_Array :=
264-
Convert_Variant_Part (M, RI, Original_Type, Is_Union);
300+
Convert_Variant_Part (M, RI, Original_Type, Is_Union,
301+
Toplevel_Members);
265302
Discrim : constant Entity_Id := Entity (RI.Variant_Expr);
266303
begin
267304
if Is_Union then
268305
for I in Parts'Range loop
269-
Member_Table.Append (Parts (I));
306+
Members_To_Update.Append (Parts (I));
270307
end loop;
271308
else
272309
if Ekind (Discrim) = E_Discriminant then
273-
pragma Assert
274-
(M.Contains (Original_Record_Component (Discrim)));
275-
MD := Create_Variant_Part
276-
(DI_Builder, M (Original_Record_Component (Discrim)),
277-
Parts);
278-
Member_Table.Append (MD);
310+
-- If we already processed the discriminant, just
311+
-- reuse its metadata here. However, if the
312+
-- discriminant was inherited, there will not be
313+
-- debuginfo for it. In this case, we emit an
314+
-- artificial discriminant into this record, so
315+
-- that the variant part can refer to it.
316+
if M.Contains (Original_Record_Component (Discrim)) then
317+
Variant_MD := M (Original_Record_Component (Discrim));
318+
else
319+
Variant_MD := Convert_One_Field
320+
(M, Original_Record_Component (Discrim), True);
321+
Toplevel_Members.Append (Variant_MD);
322+
end if;
323+
MD := Create_Variant_Part (DI_Builder, Variant_MD, Parts);
324+
Members_To_Update.Append (MD);
279325
end if;
280326
end if;
281327
end;
282328
end if;
283329

284330
declare
285-
Members : Metadata_Array (1 .. Member_Table.Last);
286-
331+
Members : Metadata_Array (Members_To_Update.First_Index
332+
.. Members_To_Update.Last_Index);
287333
begin
288334
for J in Members'Range loop
289-
Members (J) := Member_Table.Table (J);
335+
Members (J) := Members_To_Update (J);
290336
end loop;
291337

292338
return Members;
293339
end;
294340

295341
end Convert_RI_Chain;
296342

343+
----------------------
344+
-- Convert_RI_Chain --
345+
----------------------
346+
347+
function Convert_RI_Chain (M : in out Discriminant_Map.Map;
348+
Start : Record_Info_Id;
349+
Original_Type : Entity_Id;
350+
Is_Union : Boolean)
351+
return Metadata_Array
352+
is
353+
Toplevel_Members : Member_Vector;
354+
begin
355+
return Convert_RI_Chain (M, Start, Original_Type, Is_Union,
356+
Toplevel_Members, True);
357+
end Convert_RI_Chain;
358+
297359
------------------------------
298360
-- Create_Record_Debug_Info --
299361
------------------------------

0 commit comments

Comments
 (0)