15
15
-- of the license. --
16
16
-- ----------------------------------------------------------------------------
17
17
18
- with Sem_Util ; use Sem_Util ;
18
+ with Nlists ; use Nlists ;
19
19
with Sinput ; use Sinput;
20
20
with Uintp.LLVM ; use Uintp.LLVM;
21
21
@@ -28,20 +28,91 @@ with LLVM.Debug_Info; use LLVM.Debug_Info;
28
28
29
29
package body GNATLLVM.Records.Debug is
30
30
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.
33
34
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;
36
68
-- Convert a chain of Record_Info_Ids to LLVM debug metadata,
37
69
-- returning an array holding the metadata for the relevant
38
70
-- fields.
39
71
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
+
40
110
-- ---------------------
41
111
-- Convert_One_Field --
42
112
-- ---------------------
43
113
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
45
116
is
46
117
F_GT : constant GL_Type := Field_Type (F);
47
118
Mem_MD : constant Metadata_T :=
@@ -67,15 +138,82 @@ package body GNATLLVM.Records.Debug is
67
138
UI_To_ULL (Esize (F)),
68
139
Get_Type_Alignment (F_GT), Offset, Mem_MD));
69
140
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 ;
70
148
return MD;
71
149
end Convert_One_Field ;
72
150
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
+
73
209
-- --------------------
74
210
-- Convert_RI_Chain --
75
211
-- --------------------
76
212
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
79
217
is
80
218
package Member_Table is new Table.Table
81
219
(Table_Component_Type => Metadata_T,
@@ -86,30 +224,26 @@ package body GNATLLVM.Records.Debug is
86
224
Table_Name => " Member_Table" );
87
225
88
226
Ridx : Record_Info_Id := Start;
89
-
90
227
RI : Record_Info;
91
-
92
228
F : Record_Field_Kind_Id;
93
229
F_Idx : Field_Info_Id;
94
230
FI : Field_Info;
95
-
96
231
begin
232
+ -- Convert the ordinary fields.
97
233
while Present (Ridx) loop
98
234
RI := Record_Info_Table.Table (Ridx);
99
235
F_Idx := RI.First_Field;
100
236
while Present (F_Idx) loop
101
237
FI := Field_Info_Table.Table (F_Idx);
102
238
F := FI.Field;
103
239
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
107
241
-- Inherited component, so we can skip it here.
108
242
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)
111
245
then
112
- Member_Table.Append (Convert_One_Field (F));
246
+ Member_Table.Append (Convert_One_Field (M, F));
113
247
end if ;
114
248
115
249
F_Idx := FI.Next;
@@ -118,6 +252,35 @@ package body GNATLLVM.Records.Debug is
118
252
Ridx := RI.Next;
119
253
end loop ;
120
254
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
+
121
284
declare
122
285
Members : Metadata_Array (1 .. Member_Table.Last);
123
286
@@ -143,12 +306,16 @@ package body GNATLLVM.Records.Debug is
143
306
Align : Nat;
144
307
S : Source_Ptr) return Metadata_T
145
308
is
146
-
147
309
Empty_Fields : Metadata_Array (1 .. 0 );
148
-
149
310
Result : Metadata_T;
150
-
311
+ Is_Union : constant Boolean := Is_Unchecked_Union (Original_Type);
151
312
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
+
152
319
-- A type might be self-referential. For example, a
153
320
-- record may have a member whose type refers back to the
154
321
-- same record type. To handle this case, we construct a
@@ -169,18 +336,27 @@ package body GNATLLVM.Records.Debug is
169
336
end if ;
170
337
171
338
Set_Debug_Metadata (TE, Result);
339
+ if Original_Type /= TE then
340
+ Set_Debug_Metadata (Original_Type, Result);
341
+ end if ;
172
342
173
343
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);
175
346
Members : constant Metadata_Array :=
176
- Convert_RI_Chain (Ridx, Original_Type);
347
+ Convert_RI_Chain (M, Ridx, Original_Type, Is_Union );
177
348
begin
178
349
-- At least in theory it seems that LLVM may replace
179
350
-- the object entirely, so don't assume Result will be
180
351
-- the same, and be sure to clear it from the cache.
181
352
Result := Replace_Composite_Elements (DI_Builder, Result, Members);
182
353
354
+ if Original_Type /= TE then
355
+ Clear_Debug_Metadata (Original_Type);
356
+ Set_Debug_Metadata (Original_Type, Result);
357
+ end if ;
183
358
Clear_Debug_Metadata (TE);
359
+
184
360
return Result;
185
361
end ;
186
362
0 commit comments