Skip to content

Commit 0ff385a

Browse files
committed
Emit debuginfo for variant parts
This changes gnat-llvm to emit debuginfo for variant parts. (Note that this code won't actually be activated until the next patch in the series.)
1 parent 78017e5 commit 0ff385a

File tree

1 file changed

+198
-22
lines changed

1 file changed

+198
-22
lines changed

llvm-interface/gnatllvm-records-debug.adb

Lines changed: 198 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
-- of the license. --
1616
------------------------------------------------------------------------------
1717

18-
with Sem_Util; use Sem_Util;
18+
with Nlists; use Nlists;
1919
with Sinput; use Sinput;
2020
with Uintp.LLVM; use Uintp.LLVM;
2121

@@ -28,20 +28,91 @@ with LLVM.Debug_Info; use LLVM.Debug_Info;
2828

2929
package body GNATLLVM.Records.Debug is
3030

31-
function Convert_One_Field (F : Record_Field_Kind_Id) return Metadata_T;
32-
-- Convert a single field to LLVM debuginfo metadata.
31+
function Hash (F : Record_Field_Kind_Id) return Ada.Containers.Hash_Type
32+
is (Hash_Type (F));
33+
-- A hash function for use in the discriminant map.
3334

34-
function Convert_RI_Chain (Start : Record_Info_Id;
35-
Original_Type : Entity_Id) return Metadata_Array;
35+
package Discriminant_Map is new Ada.Containers.Hashed_Maps
36+
(Key_Type => Record_Field_Kind_Id,
37+
Element_Type => Metadata_T,
38+
Hash => Hash,
39+
Equivalent_Keys => "=");
40+
-- A map from a discriminant's entity to the LLVM debuginfo.
41+
42+
function Convert_Choices (Choices : List_Id) return Word_Array;
43+
-- Convert a list of choices (the discrete choices selecting a
44+
-- variant part) to a word array. The resulting word array has an
45+
-- even number of entries, with each pair holding the low and high
46+
-- bounds of a given choice. Returns an empty array for 'others'
47+
-- or if the choice list is not recognized in some way.
48+
49+
function Convert_One_Field (M : in out Discriminant_Map.Map;
50+
F : Record_Field_Kind_Id) return Metadata_T;
51+
-- Convert a single field to LLVM debug metadata. M is a map to
52+
-- update; if the field is a discriminant, then it is recorded in
53+
-- the map for later lookup. Returns the LLVM debug metadata.
54+
55+
function Convert_Variant_Part (M : in out Discriminant_Map.Map;
56+
RI : Record_Info;
57+
Original_Type : Entity_Id;
58+
Is_Union : Boolean) return Metadata_Array
59+
with pre => RI.Variants /= null;
60+
-- Convert a variant part to LLVM debug metadata, returning an
61+
-- array holding the LLVM debug metadata for all the relevant
62+
-- fields.
63+
64+
function Convert_RI_Chain (M : in out Discriminant_Map.Map;
65+
Start : Record_Info_Id;
66+
Original_Type : Entity_Id;
67+
Is_Union : Boolean) return Metadata_Array;
3668
-- Convert a chain of Record_Info_Ids to LLVM debug metadata,
3769
-- returning an array holding the metadata for the relevant
3870
-- fields.
3971

72+
---------------------
73+
-- Convert_Choices --
74+
---------------------
75+
76+
function Convert_Choices (Choices : List_Id) return Word_Array is
77+
package Choice_Table is new Table.Table
78+
(Table_Component_Type => uint64_t,
79+
Table_Index_Type => Int,
80+
Table_Low_Bound => 1,
81+
Table_Initial => 20,
82+
Table_Increment => 5,
83+
Table_Name => "Choice_Table");
84+
85+
Low : Uint;
86+
High : Uint;
87+
Choice : Entity_Id := First (Choices);
88+
Empty_Result : Word_Array (1 .. 0);
89+
begin
90+
while Present (Choice) loop
91+
if Nkind (Choice) = N_Others_Choice then
92+
return Empty_Result;
93+
end if;
94+
Decode_Range (Choice, Low, High);
95+
Choice_Table.Append (uint64_t (UI_To_ULL (Low)));
96+
Choice_Table.Append (uint64_t (UI_To_ULL (High)));
97+
Next (Choice);
98+
end loop;
99+
100+
declare
101+
Result : Word_Array (1 .. Choice_Table.Last);
102+
begin
103+
for J in Result'Range loop
104+
Result (J) := Choice_Table.Table (J);
105+
end loop;
106+
return Result;
107+
end;
108+
end Convert_Choices;
109+
40110
-----------------------
41111
-- Convert_One_Field --
42112
-----------------------
43113

44-
function Convert_One_Field (F : Record_Field_Kind_Id) return Metadata_T
114+
function Convert_One_Field (M : in out Discriminant_Map.Map;
115+
F : Record_Field_Kind_Id) return Metadata_T
45116
is
46117
F_GT : constant GL_Type := Field_Type (F);
47118
Mem_MD : constant Metadata_T :=
@@ -67,15 +138,82 @@ package body GNATLLVM.Records.Debug is
67138
UI_To_ULL (Esize (F)),
68139
Get_Type_Alignment (F_GT), Offset, Mem_MD));
69140
begin
141+
-- Ensure the field is available so that a later lookup of a
142+
-- discriminant will succeed.
143+
if Ekind (F) = E_Discriminant then
144+
-- Should not have been seen before.
145+
pragma Assert (not M.Contains (Original_Record_Component (F)));
146+
M.Insert (Original_Record_Component (F), MD);
147+
end if;
70148
return MD;
71149
end Convert_One_Field;
72150

151+
--------------------------
152+
-- Convert_Variant_Part --
153+
--------------------------
154+
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
159+
is
160+
package Member_Table is new Table.Table
161+
(Table_Component_Type => Metadata_T,
162+
Table_Index_Type => Int,
163+
Table_Low_Bound => 1,
164+
Table_Initial => 20,
165+
Table_Increment => 5,
166+
Table_Name => "Member_Table");
167+
168+
Var_Node : Node_Id := First (RI.Variant_List);
169+
begin
170+
for J in RI.Variants'Range loop
171+
declare
172+
Empty_Fields : Metadata_Array (1 .. 0);
173+
Fields : constant Metadata_Array :=
174+
(if Present (RI.Variants (J))
175+
then Convert_RI_Chain (M, RI.Variants (J), Original_Type,
176+
Is_Union)
177+
else Empty_Fields);
178+
begin
179+
if Is_Union then
180+
for I in Fields'Range loop
181+
Member_Table.Append (Fields (I));
182+
end loop;
183+
else
184+
declare
185+
Choices : constant Word_Array :=
186+
Convert_Choices (Discrete_Choices (Var_Node));
187+
MD : Metadata_T;
188+
begin
189+
MD := Create_Variant_Member (DI_Builder, Fields, Choices);
190+
Member_Table.Append (MD);
191+
end;
192+
end if;
193+
end;
194+
Next (Var_Node);
195+
end loop;
196+
197+
-- ??? handle Overlap_Variants here.
198+
199+
declare
200+
Members : Metadata_Array (1 .. Member_Table.Last);
201+
begin
202+
for J in Members'Range loop
203+
Members (J) := Member_Table.Table (J);
204+
end loop;
205+
return Members;
206+
end;
207+
end Convert_Variant_Part;
208+
73209
----------------------
74210
-- Convert_RI_Chain --
75211
----------------------
76212

77-
function Convert_RI_Chain (Start : Record_Info_Id;
78-
Original_Type : Entity_Id) return Metadata_Array
213+
function Convert_RI_Chain (M : in out Discriminant_Map.Map;
214+
Start : Record_Info_Id;
215+
Original_Type : Entity_Id;
216+
Is_Union : Boolean) return Metadata_Array
79217
is
80218
package Member_Table is new Table.Table
81219
(Table_Component_Type => Metadata_T,
@@ -86,30 +224,26 @@ package body GNATLLVM.Records.Debug is
86224
Table_Name => "Member_Table");
87225

88226
Ridx : Record_Info_Id := Start;
89-
90227
RI : Record_Info;
91-
92228
F : Record_Field_Kind_Id;
93229
F_Idx : Field_Info_Id;
94230
FI : Field_Info;
95-
96231
begin
232+
-- Convert the ordinary fields.
97233
while Present (Ridx) loop
98234
RI := Record_Info_Table.Table (Ridx);
99235
F_Idx := RI.First_Field;
100236
while Present (F_Idx) loop
101237
FI := Field_Info_Table.Table (F_Idx);
102238
F := FI.Field;
103239

104-
if Present (Original_Type) and then
105-
Get_Fullest_View (Scope (Ancestor_Field (F))) /= Original_Type
106-
then
240+
if FI.Is_Inherited then
107241
-- Inherited component, so we can skip it here.
108242
null;
109-
elsif Known_Static_Component_Bit_Offset (F)
110-
and then Known_Static_Esize (F)
243+
elsif Known_Static_Component_Bit_Offset (F) and then
244+
Known_Static_Esize (F)
111245
then
112-
Member_Table.Append (Convert_One_Field (F));
246+
Member_Table.Append (Convert_One_Field (M, F));
113247
end if;
114248

115249
F_Idx := FI.Next;
@@ -118,6 +252,35 @@ package body GNATLLVM.Records.Debug is
118252
Ridx := RI.Next;
119253
end loop;
120254

255+
-- Convert the variant part, if any -- but only if compiled
256+
-- against an LLVM that supports variant parts with multiple
257+
-- members.
258+
if Types_Can_Have_Multiple_Variant_Members and then
259+
RI.Variants /= null
260+
then
261+
declare
262+
MD : Metadata_T;
263+
Parts : constant Metadata_Array :=
264+
Convert_Variant_Part (M, RI, Original_Type, Is_Union);
265+
Discrim : constant Entity_Id := Entity (RI.Variant_Expr);
266+
begin
267+
if Is_Union then
268+
for I in Parts'Range loop
269+
Member_Table.Append (Parts (I));
270+
end loop;
271+
else
272+
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);
279+
end if;
280+
end if;
281+
end;
282+
end if;
283+
121284
declare
122285
Members : Metadata_Array (1 .. Member_Table.Last);
123286

@@ -143,12 +306,16 @@ package body GNATLLVM.Records.Debug is
143306
Align : Nat;
144307
S : Source_Ptr) return Metadata_T
145308
is
146-
147309
Empty_Fields : Metadata_Array (1 .. 0);
148-
149310
Result : Metadata_T;
150-
311+
Is_Union : constant Boolean := Is_Unchecked_Union (Original_Type);
151312
begin
313+
if Original_Type /= TE
314+
and then Present (Get_Debug_Metadata (Original_Type))
315+
then
316+
return Get_Debug_Metadata (Original_Type);
317+
end if;
318+
152319
-- A type might be self-referential. For example, a
153320
-- record may have a member whose type refers back to the
154321
-- same record type. To handle this case, we construct a
@@ -169,18 +336,27 @@ package body GNATLLVM.Records.Debug is
169336
end if;
170337

171338
Set_Debug_Metadata (TE, Result);
339+
if Original_Type /= TE then
340+
Set_Debug_Metadata (Original_Type, Result);
341+
end if;
172342

173343
declare
174-
Ridx : constant Record_Info_Id := Get_Record_Info (TE);
344+
M : Discriminant_Map.Map;
345+
Ridx : constant Record_Info_Id := Get_Record_Info (Original_Type);
175346
Members : constant Metadata_Array :=
176-
Convert_RI_Chain (Ridx, Original_Type);
347+
Convert_RI_Chain (M, Ridx, Original_Type, Is_Union);
177348
begin
178349
-- At least in theory it seems that LLVM may replace
179350
-- the object entirely, so don't assume Result will be
180351
-- the same, and be sure to clear it from the cache.
181352
Result := Replace_Composite_Elements (DI_Builder, Result, Members);
182353

354+
if Original_Type /= TE then
355+
Clear_Debug_Metadata (Original_Type);
356+
Set_Debug_Metadata (Original_Type, Result);
357+
end if;
183358
Clear_Debug_Metadata (TE);
359+
184360
return Result;
185361
end;
186362

0 commit comments

Comments
 (0)