1 |
281 |
jeremybenn |
------------------------------------------------------------------------------
|
2 |
|
|
-- --
|
3 |
|
|
-- GNAT COMPILER COMPONENTS --
|
4 |
|
|
-- --
|
5 |
|
|
-- E X P _ P A K D --
|
6 |
|
|
-- --
|
7 |
|
|
-- B o d y --
|
8 |
|
|
-- --
|
9 |
|
|
-- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
|
10 |
|
|
-- --
|
11 |
|
|
-- GNAT is free software; you can redistribute it and/or modify it under --
|
12 |
|
|
-- terms of the GNU General Public License as published by the Free Soft- --
|
13 |
|
|
-- ware Foundation; either version 3, or (at your option) any later ver- --
|
14 |
|
|
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
|
15 |
|
|
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
|
16 |
|
|
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
|
17 |
|
|
-- for more details. You should have received a copy of the GNU General --
|
18 |
|
|
-- Public License distributed with GNAT; see file COPYING3. If not, go to --
|
19 |
|
|
-- http://www.gnu.org/licenses for a complete copy of the license. --
|
20 |
|
|
-- --
|
21 |
|
|
-- GNAT was originally developed by the GNAT team at New York University. --
|
22 |
|
|
-- Extensive contributions were provided by Ada Core Technologies Inc. --
|
23 |
|
|
-- --
|
24 |
|
|
------------------------------------------------------------------------------
|
25 |
|
|
|
26 |
|
|
with Atree; use Atree;
|
27 |
|
|
with Checks; use Checks;
|
28 |
|
|
with Einfo; use Einfo;
|
29 |
|
|
with Errout; use Errout;
|
30 |
|
|
with Exp_Dbug; use Exp_Dbug;
|
31 |
|
|
with Exp_Util; use Exp_Util;
|
32 |
|
|
with Layout; use Layout;
|
33 |
|
|
with Namet; use Namet;
|
34 |
|
|
with Nlists; use Nlists;
|
35 |
|
|
with Nmake; use Nmake;
|
36 |
|
|
with Opt; use Opt;
|
37 |
|
|
with Rtsfind; use Rtsfind;
|
38 |
|
|
with Sem; use Sem;
|
39 |
|
|
with Sem_Aux; use Sem_Aux;
|
40 |
|
|
with Sem_Ch3; use Sem_Ch3;
|
41 |
|
|
with Sem_Ch8; use Sem_Ch8;
|
42 |
|
|
with Sem_Ch13; use Sem_Ch13;
|
43 |
|
|
with Sem_Eval; use Sem_Eval;
|
44 |
|
|
with Sem_Res; use Sem_Res;
|
45 |
|
|
with Sem_Util; use Sem_Util;
|
46 |
|
|
with Sinfo; use Sinfo;
|
47 |
|
|
with Snames; use Snames;
|
48 |
|
|
with Stand; use Stand;
|
49 |
|
|
with Targparm; use Targparm;
|
50 |
|
|
with Tbuild; use Tbuild;
|
51 |
|
|
with Ttypes; use Ttypes;
|
52 |
|
|
with Uintp; use Uintp;
|
53 |
|
|
|
54 |
|
|
package body Exp_Pakd is
|
55 |
|
|
|
56 |
|
|
---------------------------
|
57 |
|
|
-- Endian Considerations --
|
58 |
|
|
---------------------------
|
59 |
|
|
|
60 |
|
|
-- As described in the specification, bit numbering in a packed array
|
61 |
|
|
-- is consistent with bit numbering in a record representation clause,
|
62 |
|
|
-- and hence dependent on the endianness of the machine:
|
63 |
|
|
|
64 |
|
|
-- For little-endian machines, element zero is at the right hand end
|
65 |
|
|
-- (low order end) of a bit field.
|
66 |
|
|
|
67 |
|
|
-- For big-endian machines, element zero is at the left hand end
|
68 |
|
|
-- (high order end) of a bit field.
|
69 |
|
|
|
70 |
|
|
-- The shifts that are used to right justify a field therefore differ
|
71 |
|
|
-- in the two cases. For the little-endian case, we can simply use the
|
72 |
|
|
-- bit number (i.e. the element number * element size) as the count for
|
73 |
|
|
-- a right shift. For the big-endian case, we have to subtract the shift
|
74 |
|
|
-- count from an appropriate constant to use in the right shift. We use
|
75 |
|
|
-- rotates instead of shifts (which is necessary in the store case to
|
76 |
|
|
-- preserve other fields), and we expect that the backend will be able
|
77 |
|
|
-- to change the right rotate into a left rotate, avoiding the subtract,
|
78 |
|
|
-- if the architecture provides such an instruction.
|
79 |
|
|
|
80 |
|
|
----------------------------------------------
|
81 |
|
|
-- Entity Tables for Packed Access Routines --
|
82 |
|
|
----------------------------------------------
|
83 |
|
|
|
84 |
|
|
-- For the cases of component size = 3,5-7,9-15,17-31,33-63 we call
|
85 |
|
|
-- library routines. This table is used to obtain the entity for the
|
86 |
|
|
-- proper routine.
|
87 |
|
|
|
88 |
|
|
type E_Array is array (Int range 01 .. 63) of RE_Id;
|
89 |
|
|
|
90 |
|
|
-- Array of Bits_nn entities. Note that we do not use library routines
|
91 |
|
|
-- for the 8-bit and 16-bit cases, but we still fill in the table, using
|
92 |
|
|
-- entries from System.Unsigned, because we also use this table for
|
93 |
|
|
-- certain special unchecked conversions in the big-endian case.
|
94 |
|
|
|
95 |
|
|
Bits_Id : constant E_Array :=
|
96 |
|
|
(01 => RE_Bits_1,
|
97 |
|
|
02 => RE_Bits_2,
|
98 |
|
|
03 => RE_Bits_03,
|
99 |
|
|
04 => RE_Bits_4,
|
100 |
|
|
05 => RE_Bits_05,
|
101 |
|
|
06 => RE_Bits_06,
|
102 |
|
|
07 => RE_Bits_07,
|
103 |
|
|
08 => RE_Unsigned_8,
|
104 |
|
|
09 => RE_Bits_09,
|
105 |
|
|
10 => RE_Bits_10,
|
106 |
|
|
11 => RE_Bits_11,
|
107 |
|
|
12 => RE_Bits_12,
|
108 |
|
|
13 => RE_Bits_13,
|
109 |
|
|
14 => RE_Bits_14,
|
110 |
|
|
15 => RE_Bits_15,
|
111 |
|
|
16 => RE_Unsigned_16,
|
112 |
|
|
17 => RE_Bits_17,
|
113 |
|
|
18 => RE_Bits_18,
|
114 |
|
|
19 => RE_Bits_19,
|
115 |
|
|
20 => RE_Bits_20,
|
116 |
|
|
21 => RE_Bits_21,
|
117 |
|
|
22 => RE_Bits_22,
|
118 |
|
|
23 => RE_Bits_23,
|
119 |
|
|
24 => RE_Bits_24,
|
120 |
|
|
25 => RE_Bits_25,
|
121 |
|
|
26 => RE_Bits_26,
|
122 |
|
|
27 => RE_Bits_27,
|
123 |
|
|
28 => RE_Bits_28,
|
124 |
|
|
29 => RE_Bits_29,
|
125 |
|
|
30 => RE_Bits_30,
|
126 |
|
|
31 => RE_Bits_31,
|
127 |
|
|
32 => RE_Unsigned_32,
|
128 |
|
|
33 => RE_Bits_33,
|
129 |
|
|
34 => RE_Bits_34,
|
130 |
|
|
35 => RE_Bits_35,
|
131 |
|
|
36 => RE_Bits_36,
|
132 |
|
|
37 => RE_Bits_37,
|
133 |
|
|
38 => RE_Bits_38,
|
134 |
|
|
39 => RE_Bits_39,
|
135 |
|
|
40 => RE_Bits_40,
|
136 |
|
|
41 => RE_Bits_41,
|
137 |
|
|
42 => RE_Bits_42,
|
138 |
|
|
43 => RE_Bits_43,
|
139 |
|
|
44 => RE_Bits_44,
|
140 |
|
|
45 => RE_Bits_45,
|
141 |
|
|
46 => RE_Bits_46,
|
142 |
|
|
47 => RE_Bits_47,
|
143 |
|
|
48 => RE_Bits_48,
|
144 |
|
|
49 => RE_Bits_49,
|
145 |
|
|
50 => RE_Bits_50,
|
146 |
|
|
51 => RE_Bits_51,
|
147 |
|
|
52 => RE_Bits_52,
|
148 |
|
|
53 => RE_Bits_53,
|
149 |
|
|
54 => RE_Bits_54,
|
150 |
|
|
55 => RE_Bits_55,
|
151 |
|
|
56 => RE_Bits_56,
|
152 |
|
|
57 => RE_Bits_57,
|
153 |
|
|
58 => RE_Bits_58,
|
154 |
|
|
59 => RE_Bits_59,
|
155 |
|
|
60 => RE_Bits_60,
|
156 |
|
|
61 => RE_Bits_61,
|
157 |
|
|
62 => RE_Bits_62,
|
158 |
|
|
63 => RE_Bits_63);
|
159 |
|
|
|
160 |
|
|
-- Array of Get routine entities. These are used to obtain an element
|
161 |
|
|
-- from a packed array. The N'th entry is used to obtain elements from
|
162 |
|
|
-- a packed array whose component size is N. RE_Null is used as a null
|
163 |
|
|
-- entry, for the cases where a library routine is not used.
|
164 |
|
|
|
165 |
|
|
Get_Id : constant E_Array :=
|
166 |
|
|
(01 => RE_Null,
|
167 |
|
|
02 => RE_Null,
|
168 |
|
|
03 => RE_Get_03,
|
169 |
|
|
04 => RE_Null,
|
170 |
|
|
05 => RE_Get_05,
|
171 |
|
|
06 => RE_Get_06,
|
172 |
|
|
07 => RE_Get_07,
|
173 |
|
|
08 => RE_Null,
|
174 |
|
|
09 => RE_Get_09,
|
175 |
|
|
10 => RE_Get_10,
|
176 |
|
|
11 => RE_Get_11,
|
177 |
|
|
12 => RE_Get_12,
|
178 |
|
|
13 => RE_Get_13,
|
179 |
|
|
14 => RE_Get_14,
|
180 |
|
|
15 => RE_Get_15,
|
181 |
|
|
16 => RE_Null,
|
182 |
|
|
17 => RE_Get_17,
|
183 |
|
|
18 => RE_Get_18,
|
184 |
|
|
19 => RE_Get_19,
|
185 |
|
|
20 => RE_Get_20,
|
186 |
|
|
21 => RE_Get_21,
|
187 |
|
|
22 => RE_Get_22,
|
188 |
|
|
23 => RE_Get_23,
|
189 |
|
|
24 => RE_Get_24,
|
190 |
|
|
25 => RE_Get_25,
|
191 |
|
|
26 => RE_Get_26,
|
192 |
|
|
27 => RE_Get_27,
|
193 |
|
|
28 => RE_Get_28,
|
194 |
|
|
29 => RE_Get_29,
|
195 |
|
|
30 => RE_Get_30,
|
196 |
|
|
31 => RE_Get_31,
|
197 |
|
|
32 => RE_Null,
|
198 |
|
|
33 => RE_Get_33,
|
199 |
|
|
34 => RE_Get_34,
|
200 |
|
|
35 => RE_Get_35,
|
201 |
|
|
36 => RE_Get_36,
|
202 |
|
|
37 => RE_Get_37,
|
203 |
|
|
38 => RE_Get_38,
|
204 |
|
|
39 => RE_Get_39,
|
205 |
|
|
40 => RE_Get_40,
|
206 |
|
|
41 => RE_Get_41,
|
207 |
|
|
42 => RE_Get_42,
|
208 |
|
|
43 => RE_Get_43,
|
209 |
|
|
44 => RE_Get_44,
|
210 |
|
|
45 => RE_Get_45,
|
211 |
|
|
46 => RE_Get_46,
|
212 |
|
|
47 => RE_Get_47,
|
213 |
|
|
48 => RE_Get_48,
|
214 |
|
|
49 => RE_Get_49,
|
215 |
|
|
50 => RE_Get_50,
|
216 |
|
|
51 => RE_Get_51,
|
217 |
|
|
52 => RE_Get_52,
|
218 |
|
|
53 => RE_Get_53,
|
219 |
|
|
54 => RE_Get_54,
|
220 |
|
|
55 => RE_Get_55,
|
221 |
|
|
56 => RE_Get_56,
|
222 |
|
|
57 => RE_Get_57,
|
223 |
|
|
58 => RE_Get_58,
|
224 |
|
|
59 => RE_Get_59,
|
225 |
|
|
60 => RE_Get_60,
|
226 |
|
|
61 => RE_Get_61,
|
227 |
|
|
62 => RE_Get_62,
|
228 |
|
|
63 => RE_Get_63);
|
229 |
|
|
|
230 |
|
|
-- Array of Get routine entities to be used in the case where the packed
|
231 |
|
|
-- array is itself a component of a packed structure, and therefore may
|
232 |
|
|
-- not be fully aligned. This only affects the even sizes, since for the
|
233 |
|
|
-- odd sizes, we do not get any fixed alignment in any case.
|
234 |
|
|
|
235 |
|
|
GetU_Id : constant E_Array :=
|
236 |
|
|
(01 => RE_Null,
|
237 |
|
|
02 => RE_Null,
|
238 |
|
|
03 => RE_Get_03,
|
239 |
|
|
04 => RE_Null,
|
240 |
|
|
05 => RE_Get_05,
|
241 |
|
|
06 => RE_GetU_06,
|
242 |
|
|
07 => RE_Get_07,
|
243 |
|
|
08 => RE_Null,
|
244 |
|
|
09 => RE_Get_09,
|
245 |
|
|
10 => RE_GetU_10,
|
246 |
|
|
11 => RE_Get_11,
|
247 |
|
|
12 => RE_GetU_12,
|
248 |
|
|
13 => RE_Get_13,
|
249 |
|
|
14 => RE_GetU_14,
|
250 |
|
|
15 => RE_Get_15,
|
251 |
|
|
16 => RE_Null,
|
252 |
|
|
17 => RE_Get_17,
|
253 |
|
|
18 => RE_GetU_18,
|
254 |
|
|
19 => RE_Get_19,
|
255 |
|
|
20 => RE_GetU_20,
|
256 |
|
|
21 => RE_Get_21,
|
257 |
|
|
22 => RE_GetU_22,
|
258 |
|
|
23 => RE_Get_23,
|
259 |
|
|
24 => RE_GetU_24,
|
260 |
|
|
25 => RE_Get_25,
|
261 |
|
|
26 => RE_GetU_26,
|
262 |
|
|
27 => RE_Get_27,
|
263 |
|
|
28 => RE_GetU_28,
|
264 |
|
|
29 => RE_Get_29,
|
265 |
|
|
30 => RE_GetU_30,
|
266 |
|
|
31 => RE_Get_31,
|
267 |
|
|
32 => RE_Null,
|
268 |
|
|
33 => RE_Get_33,
|
269 |
|
|
34 => RE_GetU_34,
|
270 |
|
|
35 => RE_Get_35,
|
271 |
|
|
36 => RE_GetU_36,
|
272 |
|
|
37 => RE_Get_37,
|
273 |
|
|
38 => RE_GetU_38,
|
274 |
|
|
39 => RE_Get_39,
|
275 |
|
|
40 => RE_GetU_40,
|
276 |
|
|
41 => RE_Get_41,
|
277 |
|
|
42 => RE_GetU_42,
|
278 |
|
|
43 => RE_Get_43,
|
279 |
|
|
44 => RE_GetU_44,
|
280 |
|
|
45 => RE_Get_45,
|
281 |
|
|
46 => RE_GetU_46,
|
282 |
|
|
47 => RE_Get_47,
|
283 |
|
|
48 => RE_GetU_48,
|
284 |
|
|
49 => RE_Get_49,
|
285 |
|
|
50 => RE_GetU_50,
|
286 |
|
|
51 => RE_Get_51,
|
287 |
|
|
52 => RE_GetU_52,
|
288 |
|
|
53 => RE_Get_53,
|
289 |
|
|
54 => RE_GetU_54,
|
290 |
|
|
55 => RE_Get_55,
|
291 |
|
|
56 => RE_GetU_56,
|
292 |
|
|
57 => RE_Get_57,
|
293 |
|
|
58 => RE_GetU_58,
|
294 |
|
|
59 => RE_Get_59,
|
295 |
|
|
60 => RE_GetU_60,
|
296 |
|
|
61 => RE_Get_61,
|
297 |
|
|
62 => RE_GetU_62,
|
298 |
|
|
63 => RE_Get_63);
|
299 |
|
|
|
300 |
|
|
-- Array of Set routine entities. These are used to assign an element
|
301 |
|
|
-- of a packed array. The N'th entry is used to assign elements for
|
302 |
|
|
-- a packed array whose component size is N. RE_Null is used as a null
|
303 |
|
|
-- entry, for the cases where a library routine is not used.
|
304 |
|
|
|
305 |
|
|
Set_Id : constant E_Array :=
|
306 |
|
|
(01 => RE_Null,
|
307 |
|
|
02 => RE_Null,
|
308 |
|
|
03 => RE_Set_03,
|
309 |
|
|
04 => RE_Null,
|
310 |
|
|
05 => RE_Set_05,
|
311 |
|
|
06 => RE_Set_06,
|
312 |
|
|
07 => RE_Set_07,
|
313 |
|
|
08 => RE_Null,
|
314 |
|
|
09 => RE_Set_09,
|
315 |
|
|
10 => RE_Set_10,
|
316 |
|
|
11 => RE_Set_11,
|
317 |
|
|
12 => RE_Set_12,
|
318 |
|
|
13 => RE_Set_13,
|
319 |
|
|
14 => RE_Set_14,
|
320 |
|
|
15 => RE_Set_15,
|
321 |
|
|
16 => RE_Null,
|
322 |
|
|
17 => RE_Set_17,
|
323 |
|
|
18 => RE_Set_18,
|
324 |
|
|
19 => RE_Set_19,
|
325 |
|
|
20 => RE_Set_20,
|
326 |
|
|
21 => RE_Set_21,
|
327 |
|
|
22 => RE_Set_22,
|
328 |
|
|
23 => RE_Set_23,
|
329 |
|
|
24 => RE_Set_24,
|
330 |
|
|
25 => RE_Set_25,
|
331 |
|
|
26 => RE_Set_26,
|
332 |
|
|
27 => RE_Set_27,
|
333 |
|
|
28 => RE_Set_28,
|
334 |
|
|
29 => RE_Set_29,
|
335 |
|
|
30 => RE_Set_30,
|
336 |
|
|
31 => RE_Set_31,
|
337 |
|
|
32 => RE_Null,
|
338 |
|
|
33 => RE_Set_33,
|
339 |
|
|
34 => RE_Set_34,
|
340 |
|
|
35 => RE_Set_35,
|
341 |
|
|
36 => RE_Set_36,
|
342 |
|
|
37 => RE_Set_37,
|
343 |
|
|
38 => RE_Set_38,
|
344 |
|
|
39 => RE_Set_39,
|
345 |
|
|
40 => RE_Set_40,
|
346 |
|
|
41 => RE_Set_41,
|
347 |
|
|
42 => RE_Set_42,
|
348 |
|
|
43 => RE_Set_43,
|
349 |
|
|
44 => RE_Set_44,
|
350 |
|
|
45 => RE_Set_45,
|
351 |
|
|
46 => RE_Set_46,
|
352 |
|
|
47 => RE_Set_47,
|
353 |
|
|
48 => RE_Set_48,
|
354 |
|
|
49 => RE_Set_49,
|
355 |
|
|
50 => RE_Set_50,
|
356 |
|
|
51 => RE_Set_51,
|
357 |
|
|
52 => RE_Set_52,
|
358 |
|
|
53 => RE_Set_53,
|
359 |
|
|
54 => RE_Set_54,
|
360 |
|
|
55 => RE_Set_55,
|
361 |
|
|
56 => RE_Set_56,
|
362 |
|
|
57 => RE_Set_57,
|
363 |
|
|
58 => RE_Set_58,
|
364 |
|
|
59 => RE_Set_59,
|
365 |
|
|
60 => RE_Set_60,
|
366 |
|
|
61 => RE_Set_61,
|
367 |
|
|
62 => RE_Set_62,
|
368 |
|
|
63 => RE_Set_63);
|
369 |
|
|
|
370 |
|
|
-- Array of Set routine entities to be used in the case where the packed
|
371 |
|
|
-- array is itself a component of a packed structure, and therefore may
|
372 |
|
|
-- not be fully aligned. This only affects the even sizes, since for the
|
373 |
|
|
-- odd sizes, we do not get any fixed alignment in any case.
|
374 |
|
|
|
375 |
|
|
SetU_Id : constant E_Array :=
|
376 |
|
|
(01 => RE_Null,
|
377 |
|
|
02 => RE_Null,
|
378 |
|
|
03 => RE_Set_03,
|
379 |
|
|
04 => RE_Null,
|
380 |
|
|
05 => RE_Set_05,
|
381 |
|
|
06 => RE_SetU_06,
|
382 |
|
|
07 => RE_Set_07,
|
383 |
|
|
08 => RE_Null,
|
384 |
|
|
09 => RE_Set_09,
|
385 |
|
|
10 => RE_SetU_10,
|
386 |
|
|
11 => RE_Set_11,
|
387 |
|
|
12 => RE_SetU_12,
|
388 |
|
|
13 => RE_Set_13,
|
389 |
|
|
14 => RE_SetU_14,
|
390 |
|
|
15 => RE_Set_15,
|
391 |
|
|
16 => RE_Null,
|
392 |
|
|
17 => RE_Set_17,
|
393 |
|
|
18 => RE_SetU_18,
|
394 |
|
|
19 => RE_Set_19,
|
395 |
|
|
20 => RE_SetU_20,
|
396 |
|
|
21 => RE_Set_21,
|
397 |
|
|
22 => RE_SetU_22,
|
398 |
|
|
23 => RE_Set_23,
|
399 |
|
|
24 => RE_SetU_24,
|
400 |
|
|
25 => RE_Set_25,
|
401 |
|
|
26 => RE_SetU_26,
|
402 |
|
|
27 => RE_Set_27,
|
403 |
|
|
28 => RE_SetU_28,
|
404 |
|
|
29 => RE_Set_29,
|
405 |
|
|
30 => RE_SetU_30,
|
406 |
|
|
31 => RE_Set_31,
|
407 |
|
|
32 => RE_Null,
|
408 |
|
|
33 => RE_Set_33,
|
409 |
|
|
34 => RE_SetU_34,
|
410 |
|
|
35 => RE_Set_35,
|
411 |
|
|
36 => RE_SetU_36,
|
412 |
|
|
37 => RE_Set_37,
|
413 |
|
|
38 => RE_SetU_38,
|
414 |
|
|
39 => RE_Set_39,
|
415 |
|
|
40 => RE_SetU_40,
|
416 |
|
|
41 => RE_Set_41,
|
417 |
|
|
42 => RE_SetU_42,
|
418 |
|
|
43 => RE_Set_43,
|
419 |
|
|
44 => RE_SetU_44,
|
420 |
|
|
45 => RE_Set_45,
|
421 |
|
|
46 => RE_SetU_46,
|
422 |
|
|
47 => RE_Set_47,
|
423 |
|
|
48 => RE_SetU_48,
|
424 |
|
|
49 => RE_Set_49,
|
425 |
|
|
50 => RE_SetU_50,
|
426 |
|
|
51 => RE_Set_51,
|
427 |
|
|
52 => RE_SetU_52,
|
428 |
|
|
53 => RE_Set_53,
|
429 |
|
|
54 => RE_SetU_54,
|
430 |
|
|
55 => RE_Set_55,
|
431 |
|
|
56 => RE_SetU_56,
|
432 |
|
|
57 => RE_Set_57,
|
433 |
|
|
58 => RE_SetU_58,
|
434 |
|
|
59 => RE_Set_59,
|
435 |
|
|
60 => RE_SetU_60,
|
436 |
|
|
61 => RE_Set_61,
|
437 |
|
|
62 => RE_SetU_62,
|
438 |
|
|
63 => RE_Set_63);
|
439 |
|
|
|
440 |
|
|
-----------------------
|
441 |
|
|
-- Local Subprograms --
|
442 |
|
|
-----------------------
|
443 |
|
|
|
444 |
|
|
procedure Compute_Linear_Subscript
|
445 |
|
|
(Atyp : Entity_Id;
|
446 |
|
|
N : Node_Id;
|
447 |
|
|
Subscr : out Node_Id);
|
448 |
|
|
-- Given a constrained array type Atyp, and an indexed component node
|
449 |
|
|
-- N referencing an array object of this type, build an expression of
|
450 |
|
|
-- type Standard.Integer representing the zero-based linear subscript
|
451 |
|
|
-- value. This expression includes any required range checks.
|
452 |
|
|
|
453 |
|
|
procedure Convert_To_PAT_Type (Aexp : Node_Id);
|
454 |
|
|
-- Given an expression of a packed array type, builds a corresponding
|
455 |
|
|
-- expression whose type is the implementation type used to represent
|
456 |
|
|
-- the packed array. Aexp is analyzed and resolved on entry and on exit.
|
457 |
|
|
|
458 |
|
|
function Known_Aligned_Enough (Obj : Node_Id; Csiz : Nat) return Boolean;
|
459 |
|
|
-- There are two versions of the Set routines, the ones used when the
|
460 |
|
|
-- object is known to be sufficiently well aligned given the number of
|
461 |
|
|
-- bits, and the ones used when the object is not known to be aligned.
|
462 |
|
|
-- This routine is used to determine which set to use. Obj is a reference
|
463 |
|
|
-- to the object, and Csiz is the component size of the packed array.
|
464 |
|
|
-- True is returned if the alignment of object is known to be sufficient,
|
465 |
|
|
-- defined as 1 for odd bit sizes, 4 for bit sizes divisible by 4, and
|
466 |
|
|
-- 2 otherwise.
|
467 |
|
|
|
468 |
|
|
function Make_Shift_Left (N : Node_Id; S : Node_Id) return Node_Id;
|
469 |
|
|
-- Build a left shift node, checking for the case of a shift count of zero
|
470 |
|
|
|
471 |
|
|
function Make_Shift_Right (N : Node_Id; S : Node_Id) return Node_Id;
|
472 |
|
|
-- Build a right shift node, checking for the case of a shift count of zero
|
473 |
|
|
|
474 |
|
|
function RJ_Unchecked_Convert_To
|
475 |
|
|
(Typ : Entity_Id;
|
476 |
|
|
Expr : Node_Id) return Node_Id;
|
477 |
|
|
-- The packed array code does unchecked conversions which in some cases
|
478 |
|
|
-- may involve non-discrete types with differing sizes. The semantics of
|
479 |
|
|
-- such conversions is potentially endian dependent, and the effect we
|
480 |
|
|
-- want here for such a conversion is to do the conversion in size as
|
481 |
|
|
-- though numeric items are involved, and we extend or truncate on the
|
482 |
|
|
-- left side. This happens naturally in the little-endian case, but in
|
483 |
|
|
-- the big endian case we can get left justification, when what we want
|
484 |
|
|
-- is right justification. This routine does the unchecked conversion in
|
485 |
|
|
-- a stepwise manner to ensure that it gives the expected result. Hence
|
486 |
|
|
-- the name (RJ = Right justified). The parameters Typ and Expr are as
|
487 |
|
|
-- for the case of a normal Unchecked_Convert_To call.
|
488 |
|
|
|
489 |
|
|
procedure Setup_Enumeration_Packed_Array_Reference (N : Node_Id);
|
490 |
|
|
-- This routine is called in the Get and Set case for arrays that are
|
491 |
|
|
-- packed but not bit-packed, meaning that they have at least one
|
492 |
|
|
-- subscript that is of an enumeration type with a non-standard
|
493 |
|
|
-- representation. This routine modifies the given node to properly
|
494 |
|
|
-- reference the corresponding packed array type.
|
495 |
|
|
|
496 |
|
|
procedure Setup_Inline_Packed_Array_Reference
|
497 |
|
|
(N : Node_Id;
|
498 |
|
|
Atyp : Entity_Id;
|
499 |
|
|
Obj : in out Node_Id;
|
500 |
|
|
Cmask : out Uint;
|
501 |
|
|
Shift : out Node_Id);
|
502 |
|
|
-- This procedure performs common processing on the N_Indexed_Component
|
503 |
|
|
-- parameter given as N, whose prefix is a reference to a packed array.
|
504 |
|
|
-- This is used for the get and set when the component size is 1,2,4
|
505 |
|
|
-- or for other component sizes when the packed array type is a modular
|
506 |
|
|
-- type (i.e. the cases that are handled with inline code).
|
507 |
|
|
--
|
508 |
|
|
-- On entry:
|
509 |
|
|
--
|
510 |
|
|
-- N is the N_Indexed_Component node for the packed array reference
|
511 |
|
|
--
|
512 |
|
|
-- Atyp is the constrained array type (the actual subtype has been
|
513 |
|
|
-- computed if necessary to obtain the constraints, but this is still
|
514 |
|
|
-- the original array type, not the Packed_Array_Type value).
|
515 |
|
|
--
|
516 |
|
|
-- Obj is the object which is to be indexed. It is always of type Atyp.
|
517 |
|
|
--
|
518 |
|
|
-- On return:
|
519 |
|
|
--
|
520 |
|
|
-- Obj is the object containing the desired bit field. It is of type
|
521 |
|
|
-- Unsigned, Long_Unsigned, or Long_Long_Unsigned, and is either the
|
522 |
|
|
-- entire value, for the small static case, or the proper selected byte
|
523 |
|
|
-- from the array in the large or dynamic case. This node is analyzed
|
524 |
|
|
-- and resolved on return.
|
525 |
|
|
--
|
526 |
|
|
-- Shift is a node representing the shift count to be used in the
|
527 |
|
|
-- rotate right instruction that positions the field for access.
|
528 |
|
|
-- This node is analyzed and resolved on return.
|
529 |
|
|
--
|
530 |
|
|
-- Cmask is a mask corresponding to the width of the component field.
|
531 |
|
|
-- Its value is 2 ** Csize - 1 (e.g. 2#1111# for component size of 4).
|
532 |
|
|
--
|
533 |
|
|
-- Note: in some cases the call to this routine may generate actions
|
534 |
|
|
-- (for handling multi-use references and the generation of the packed
|
535 |
|
|
-- array type on the fly). Such actions are inserted into the tree
|
536 |
|
|
-- directly using Insert_Action.
|
537 |
|
|
|
538 |
|
|
------------------------------
|
539 |
|
|
-- Compute_Linear_Subscript --
|
540 |
|
|
------------------------------
|
541 |
|
|
|
542 |
|
|
procedure Compute_Linear_Subscript
|
543 |
|
|
(Atyp : Entity_Id;
|
544 |
|
|
N : Node_Id;
|
545 |
|
|
Subscr : out Node_Id)
|
546 |
|
|
is
|
547 |
|
|
Loc : constant Source_Ptr := Sloc (N);
|
548 |
|
|
Oldsub : Node_Id;
|
549 |
|
|
Newsub : Node_Id;
|
550 |
|
|
Indx : Node_Id;
|
551 |
|
|
Styp : Entity_Id;
|
552 |
|
|
|
553 |
|
|
begin
|
554 |
|
|
Subscr := Empty;
|
555 |
|
|
|
556 |
|
|
-- Loop through dimensions
|
557 |
|
|
|
558 |
|
|
Indx := First_Index (Atyp);
|
559 |
|
|
Oldsub := First (Expressions (N));
|
560 |
|
|
|
561 |
|
|
while Present (Indx) loop
|
562 |
|
|
Styp := Etype (Indx);
|
563 |
|
|
Newsub := Relocate_Node (Oldsub);
|
564 |
|
|
|
565 |
|
|
-- Get expression for the subscript value. First, if Do_Range_Check
|
566 |
|
|
-- is set on a subscript, then we must do a range check against the
|
567 |
|
|
-- original bounds (not the bounds of the packed array type). We do
|
568 |
|
|
-- this by introducing a subtype conversion.
|
569 |
|
|
|
570 |
|
|
if Do_Range_Check (Newsub)
|
571 |
|
|
and then Etype (Newsub) /= Styp
|
572 |
|
|
then
|
573 |
|
|
Newsub := Convert_To (Styp, Newsub);
|
574 |
|
|
end if;
|
575 |
|
|
|
576 |
|
|
-- Now evolve the expression for the subscript. First convert
|
577 |
|
|
-- the subscript to be zero based and of an integer type.
|
578 |
|
|
|
579 |
|
|
-- Case of integer type, where we just subtract to get lower bound
|
580 |
|
|
|
581 |
|
|
if Is_Integer_Type (Styp) then
|
582 |
|
|
|
583 |
|
|
-- If length of integer type is smaller than standard integer,
|
584 |
|
|
-- then we convert to integer first, then do the subtract
|
585 |
|
|
|
586 |
|
|
-- Integer (subscript) - Integer (Styp'First)
|
587 |
|
|
|
588 |
|
|
if Esize (Styp) < Esize (Standard_Integer) then
|
589 |
|
|
Newsub :=
|
590 |
|
|
Make_Op_Subtract (Loc,
|
591 |
|
|
Left_Opnd => Convert_To (Standard_Integer, Newsub),
|
592 |
|
|
Right_Opnd =>
|
593 |
|
|
Convert_To (Standard_Integer,
|
594 |
|
|
Make_Attribute_Reference (Loc,
|
595 |
|
|
Prefix => New_Occurrence_Of (Styp, Loc),
|
596 |
|
|
Attribute_Name => Name_First)));
|
597 |
|
|
|
598 |
|
|
-- For larger integer types, subtract first, then convert to
|
599 |
|
|
-- integer, this deals with strange long long integer bounds.
|
600 |
|
|
|
601 |
|
|
-- Integer (subscript - Styp'First)
|
602 |
|
|
|
603 |
|
|
else
|
604 |
|
|
Newsub :=
|
605 |
|
|
Convert_To (Standard_Integer,
|
606 |
|
|
Make_Op_Subtract (Loc,
|
607 |
|
|
Left_Opnd => Newsub,
|
608 |
|
|
Right_Opnd =>
|
609 |
|
|
Make_Attribute_Reference (Loc,
|
610 |
|
|
Prefix => New_Occurrence_Of (Styp, Loc),
|
611 |
|
|
Attribute_Name => Name_First)));
|
612 |
|
|
end if;
|
613 |
|
|
|
614 |
|
|
-- For the enumeration case, we have to use 'Pos to get the value
|
615 |
|
|
-- to work with before subtracting the lower bound.
|
616 |
|
|
|
617 |
|
|
-- Integer (Styp'Pos (subscr)) - Integer (Styp'Pos (Styp'First));
|
618 |
|
|
|
619 |
|
|
-- This is not quite right for bizarre cases where the size of the
|
620 |
|
|
-- enumeration type is > Integer'Size bits due to rep clause ???
|
621 |
|
|
|
622 |
|
|
else
|
623 |
|
|
pragma Assert (Is_Enumeration_Type (Styp));
|
624 |
|
|
|
625 |
|
|
Newsub :=
|
626 |
|
|
Make_Op_Subtract (Loc,
|
627 |
|
|
Left_Opnd => Convert_To (Standard_Integer,
|
628 |
|
|
Make_Attribute_Reference (Loc,
|
629 |
|
|
Prefix => New_Occurrence_Of (Styp, Loc),
|
630 |
|
|
Attribute_Name => Name_Pos,
|
631 |
|
|
Expressions => New_List (Newsub))),
|
632 |
|
|
|
633 |
|
|
Right_Opnd =>
|
634 |
|
|
Convert_To (Standard_Integer,
|
635 |
|
|
Make_Attribute_Reference (Loc,
|
636 |
|
|
Prefix => New_Occurrence_Of (Styp, Loc),
|
637 |
|
|
Attribute_Name => Name_Pos,
|
638 |
|
|
Expressions => New_List (
|
639 |
|
|
Make_Attribute_Reference (Loc,
|
640 |
|
|
Prefix => New_Occurrence_Of (Styp, Loc),
|
641 |
|
|
Attribute_Name => Name_First)))));
|
642 |
|
|
end if;
|
643 |
|
|
|
644 |
|
|
Set_Paren_Count (Newsub, 1);
|
645 |
|
|
|
646 |
|
|
-- For the first subscript, we just copy that subscript value
|
647 |
|
|
|
648 |
|
|
if No (Subscr) then
|
649 |
|
|
Subscr := Newsub;
|
650 |
|
|
|
651 |
|
|
-- Otherwise, we must multiply what we already have by the current
|
652 |
|
|
-- stride and then add in the new value to the evolving subscript.
|
653 |
|
|
|
654 |
|
|
else
|
655 |
|
|
Subscr :=
|
656 |
|
|
Make_Op_Add (Loc,
|
657 |
|
|
Left_Opnd =>
|
658 |
|
|
Make_Op_Multiply (Loc,
|
659 |
|
|
Left_Opnd => Subscr,
|
660 |
|
|
Right_Opnd =>
|
661 |
|
|
Make_Attribute_Reference (Loc,
|
662 |
|
|
Attribute_Name => Name_Range_Length,
|
663 |
|
|
Prefix => New_Occurrence_Of (Styp, Loc))),
|
664 |
|
|
Right_Opnd => Newsub);
|
665 |
|
|
end if;
|
666 |
|
|
|
667 |
|
|
-- Move to next subscript
|
668 |
|
|
|
669 |
|
|
Next_Index (Indx);
|
670 |
|
|
Next (Oldsub);
|
671 |
|
|
end loop;
|
672 |
|
|
end Compute_Linear_Subscript;
|
673 |
|
|
|
674 |
|
|
-------------------------
|
675 |
|
|
-- Convert_To_PAT_Type --
|
676 |
|
|
-------------------------
|
677 |
|
|
|
678 |
|
|
-- The PAT is always obtained from the actual subtype
|
679 |
|
|
|
680 |
|
|
procedure Convert_To_PAT_Type (Aexp : Node_Id) is
|
681 |
|
|
Act_ST : Entity_Id;
|
682 |
|
|
|
683 |
|
|
begin
|
684 |
|
|
Convert_To_Actual_Subtype (Aexp);
|
685 |
|
|
Act_ST := Underlying_Type (Etype (Aexp));
|
686 |
|
|
Create_Packed_Array_Type (Act_ST);
|
687 |
|
|
|
688 |
|
|
-- Just replace the etype with the packed array type. This works because
|
689 |
|
|
-- the expression will not be further analyzed, and Gigi considers the
|
690 |
|
|
-- two types equivalent in any case.
|
691 |
|
|
|
692 |
|
|
-- This is not strictly the case ??? If the reference is an actual in
|
693 |
|
|
-- call, the expansion of the prefix is delayed, and must be reanalyzed,
|
694 |
|
|
-- see Reset_Packed_Prefix. On the other hand, if the prefix is a simple
|
695 |
|
|
-- array reference, reanalysis can produce spurious type errors when the
|
696 |
|
|
-- PAT type is replaced again with the original type of the array. Same
|
697 |
|
|
-- for the case of a dereference. The following is correct and minimal,
|
698 |
|
|
-- but the handling of more complex packed expressions in actuals is
|
699 |
|
|
-- confused. Probably the problem only remains for actuals in calls.
|
700 |
|
|
|
701 |
|
|
Set_Etype (Aexp, Packed_Array_Type (Act_ST));
|
702 |
|
|
|
703 |
|
|
if Is_Entity_Name (Aexp)
|
704 |
|
|
or else
|
705 |
|
|
(Nkind (Aexp) = N_Indexed_Component
|
706 |
|
|
and then Is_Entity_Name (Prefix (Aexp)))
|
707 |
|
|
or else Nkind (Aexp) = N_Explicit_Dereference
|
708 |
|
|
then
|
709 |
|
|
Set_Analyzed (Aexp);
|
710 |
|
|
end if;
|
711 |
|
|
end Convert_To_PAT_Type;
|
712 |
|
|
|
713 |
|
|
------------------------------
|
714 |
|
|
-- Create_Packed_Array_Type --
|
715 |
|
|
------------------------------
|
716 |
|
|
|
717 |
|
|
procedure Create_Packed_Array_Type (Typ : Entity_Id) is
|
718 |
|
|
Loc : constant Source_Ptr := Sloc (Typ);
|
719 |
|
|
Ctyp : constant Entity_Id := Component_Type (Typ);
|
720 |
|
|
Csize : constant Uint := Component_Size (Typ);
|
721 |
|
|
|
722 |
|
|
Ancest : Entity_Id;
|
723 |
|
|
PB_Type : Entity_Id;
|
724 |
|
|
PASize : Uint;
|
725 |
|
|
Decl : Node_Id;
|
726 |
|
|
PAT : Entity_Id;
|
727 |
|
|
Len_Dim : Node_Id;
|
728 |
|
|
Len_Expr : Node_Id;
|
729 |
|
|
Len_Bits : Uint;
|
730 |
|
|
Bits_U1 : Node_Id;
|
731 |
|
|
PAT_High : Node_Id;
|
732 |
|
|
Btyp : Entity_Id;
|
733 |
|
|
Lit : Node_Id;
|
734 |
|
|
|
735 |
|
|
procedure Install_PAT;
|
736 |
|
|
-- This procedure is called with Decl set to the declaration for the
|
737 |
|
|
-- packed array type. It creates the type and installs it as required.
|
738 |
|
|
|
739 |
|
|
procedure Set_PB_Type;
|
740 |
|
|
-- Sets PB_Type to Packed_Bytes{1,2,4} as required by the alignment
|
741 |
|
|
-- requirements (see documentation in the spec of this package).
|
742 |
|
|
|
743 |
|
|
-----------------
|
744 |
|
|
-- Install_PAT --
|
745 |
|
|
-----------------
|
746 |
|
|
|
747 |
|
|
procedure Install_PAT is
|
748 |
|
|
Pushed_Scope : Boolean := False;
|
749 |
|
|
|
750 |
|
|
begin
|
751 |
|
|
-- We do not want to put the declaration we have created in the tree
|
752 |
|
|
-- since it is often hard, and sometimes impossible to find a proper
|
753 |
|
|
-- place for it (the impossible case arises for a packed array type
|
754 |
|
|
-- with bounds depending on the discriminant, a declaration cannot
|
755 |
|
|
-- be put inside the record, and the reference to the discriminant
|
756 |
|
|
-- cannot be outside the record).
|
757 |
|
|
|
758 |
|
|
-- The solution is to analyze the declaration while temporarily
|
759 |
|
|
-- attached to the tree at an appropriate point, and then we install
|
760 |
|
|
-- the resulting type as an Itype in the packed array type field of
|
761 |
|
|
-- the original type, so that no explicit declaration is required.
|
762 |
|
|
|
763 |
|
|
-- Note: the packed type is created in the scope of its parent
|
764 |
|
|
-- type. There are at least some cases where the current scope
|
765 |
|
|
-- is deeper, and so when this is the case, we temporarily reset
|
766 |
|
|
-- the scope for the definition. This is clearly safe, since the
|
767 |
|
|
-- first use of the packed array type will be the implicit
|
768 |
|
|
-- reference from the corresponding unpacked type when it is
|
769 |
|
|
-- elaborated.
|
770 |
|
|
|
771 |
|
|
if Is_Itype (Typ) then
|
772 |
|
|
Set_Parent (Decl, Associated_Node_For_Itype (Typ));
|
773 |
|
|
else
|
774 |
|
|
Set_Parent (Decl, Declaration_Node (Typ));
|
775 |
|
|
end if;
|
776 |
|
|
|
777 |
|
|
if Scope (Typ) /= Current_Scope then
|
778 |
|
|
Push_Scope (Scope (Typ));
|
779 |
|
|
Pushed_Scope := True;
|
780 |
|
|
end if;
|
781 |
|
|
|
782 |
|
|
Set_Is_Itype (PAT, True);
|
783 |
|
|
Set_Packed_Array_Type (Typ, PAT);
|
784 |
|
|
Analyze (Decl, Suppress => All_Checks);
|
785 |
|
|
|
786 |
|
|
if Pushed_Scope then
|
787 |
|
|
Pop_Scope;
|
788 |
|
|
end if;
|
789 |
|
|
|
790 |
|
|
-- Set Esize and RM_Size to the actual size of the packed object
|
791 |
|
|
-- Do not reset RM_Size if already set, as happens in the case of
|
792 |
|
|
-- a modular type.
|
793 |
|
|
|
794 |
|
|
if Unknown_Esize (PAT) then
|
795 |
|
|
Set_Esize (PAT, PASize);
|
796 |
|
|
end if;
|
797 |
|
|
|
798 |
|
|
if Unknown_RM_Size (PAT) then
|
799 |
|
|
Set_RM_Size (PAT, PASize);
|
800 |
|
|
end if;
|
801 |
|
|
|
802 |
|
|
Adjust_Esize_Alignment (PAT);
|
803 |
|
|
|
804 |
|
|
-- Set remaining fields of packed array type
|
805 |
|
|
|
806 |
|
|
Init_Alignment (PAT);
|
807 |
|
|
Set_Parent (PAT, Empty);
|
808 |
|
|
Set_Associated_Node_For_Itype (PAT, Typ);
|
809 |
|
|
Set_Is_Packed_Array_Type (PAT, True);
|
810 |
|
|
Set_Original_Array_Type (PAT, Typ);
|
811 |
|
|
|
812 |
|
|
-- We definitely do not want to delay freezing for packed array
|
813 |
|
|
-- types. This is of particular importance for the itypes that
|
814 |
|
|
-- are generated for record components depending on discriminants
|
815 |
|
|
-- where there is no place to put the freeze node.
|
816 |
|
|
|
817 |
|
|
Set_Has_Delayed_Freeze (PAT, False);
|
818 |
|
|
Set_Has_Delayed_Freeze (Etype (PAT), False);
|
819 |
|
|
|
820 |
|
|
-- If we did allocate a freeze node, then clear out the reference
|
821 |
|
|
-- since it is obsolete (should we delete the freeze node???)
|
822 |
|
|
|
823 |
|
|
Set_Freeze_Node (PAT, Empty);
|
824 |
|
|
Set_Freeze_Node (Etype (PAT), Empty);
|
825 |
|
|
end Install_PAT;
|
826 |
|
|
|
827 |
|
|
-----------------
|
828 |
|
|
-- Set_PB_Type --
|
829 |
|
|
-----------------
|
830 |
|
|
|
831 |
|
|
procedure Set_PB_Type is
|
832 |
|
|
begin
|
833 |
|
|
-- If the user has specified an explicit alignment for the
|
834 |
|
|
-- type or component, take it into account.
|
835 |
|
|
|
836 |
|
|
if Csize <= 2 or else Csize = 4 or else Csize mod 2 /= 0
|
837 |
|
|
or else Alignment (Typ) = 1
|
838 |
|
|
or else Component_Alignment (Typ) = Calign_Storage_Unit
|
839 |
|
|
then
|
840 |
|
|
PB_Type := RTE (RE_Packed_Bytes1);
|
841 |
|
|
|
842 |
|
|
elsif Csize mod 4 /= 0
|
843 |
|
|
or else Alignment (Typ) = 2
|
844 |
|
|
then
|
845 |
|
|
PB_Type := RTE (RE_Packed_Bytes2);
|
846 |
|
|
|
847 |
|
|
else
|
848 |
|
|
PB_Type := RTE (RE_Packed_Bytes4);
|
849 |
|
|
end if;
|
850 |
|
|
end Set_PB_Type;
|
851 |
|
|
|
852 |
|
|
-- Start of processing for Create_Packed_Array_Type
|
853 |
|
|
|
854 |
|
|
begin
|
855 |
|
|
-- If we already have a packed array type, nothing to do
|
856 |
|
|
|
857 |
|
|
if Present (Packed_Array_Type (Typ)) then
|
858 |
|
|
return;
|
859 |
|
|
end if;
|
860 |
|
|
|
861 |
|
|
-- If our immediate ancestor subtype is constrained, and it already
|
862 |
|
|
-- has a packed array type, then just share the same type, since the
|
863 |
|
|
-- bounds must be the same. If the ancestor is not an array type but
|
864 |
|
|
-- a private type, as can happen with multiple instantiations, create
|
865 |
|
|
-- a new packed type, to avoid privacy issues.
|
866 |
|
|
|
867 |
|
|
if Ekind (Typ) = E_Array_Subtype then
|
868 |
|
|
Ancest := Ancestor_Subtype (Typ);
|
869 |
|
|
|
870 |
|
|
if Present (Ancest)
|
871 |
|
|
and then Is_Array_Type (Ancest)
|
872 |
|
|
and then Is_Constrained (Ancest)
|
873 |
|
|
and then Present (Packed_Array_Type (Ancest))
|
874 |
|
|
then
|
875 |
|
|
Set_Packed_Array_Type (Typ, Packed_Array_Type (Ancest));
|
876 |
|
|
return;
|
877 |
|
|
end if;
|
878 |
|
|
end if;
|
879 |
|
|
|
880 |
|
|
-- We preset the result type size from the size of the original array
|
881 |
|
|
-- type, since this size clearly belongs to the packed array type. The
|
882 |
|
|
-- size of the conceptual unpacked type is always set to unknown.
|
883 |
|
|
|
884 |
|
|
PASize := RM_Size (Typ);
|
885 |
|
|
|
886 |
|
|
-- Case of an array where at least one index is of an enumeration
|
887 |
|
|
-- type with a non-standard representation, but the component size
|
888 |
|
|
-- is not appropriate for bit packing. This is the case where we
|
889 |
|
|
-- have Is_Packed set (we would never be in this unit otherwise),
|
890 |
|
|
-- but Is_Bit_Packed_Array is false.
|
891 |
|
|
|
892 |
|
|
-- Note that if the component size is appropriate for bit packing,
|
893 |
|
|
-- then the circuit for the computation of the subscript properly
|
894 |
|
|
-- deals with the non-standard enumeration type case by taking the
|
895 |
|
|
-- Pos anyway.
|
896 |
|
|
|
897 |
|
|
if not Is_Bit_Packed_Array (Typ) then
|
898 |
|
|
|
899 |
|
|
-- Here we build a declaration:
|
900 |
|
|
|
901 |
|
|
-- type tttP is array (index1, index2, ...) of component_type
|
902 |
|
|
|
903 |
|
|
-- where index1, index2, are the index types. These are the same
|
904 |
|
|
-- as the index types of the original array, except for the non-
|
905 |
|
|
-- standard representation enumeration type case, where we have
|
906 |
|
|
-- two subcases.
|
907 |
|
|
|
908 |
|
|
-- For the unconstrained array case, we use
|
909 |
|
|
|
910 |
|
|
-- Natural range <>
|
911 |
|
|
|
912 |
|
|
-- For the constrained case, we use
|
913 |
|
|
|
914 |
|
|
-- Natural range Enum_Type'Pos (Enum_Type'First) ..
|
915 |
|
|
-- Enum_Type'Pos (Enum_Type'Last);
|
916 |
|
|
|
917 |
|
|
PAT :=
|
918 |
|
|
Make_Defining_Identifier (Loc,
|
919 |
|
|
Chars => New_External_Name (Chars (Typ), 'P'));
|
920 |
|
|
|
921 |
|
|
Set_Packed_Array_Type (Typ, PAT);
|
922 |
|
|
|
923 |
|
|
declare
|
924 |
|
|
Indexes : constant List_Id := New_List;
|
925 |
|
|
Indx : Node_Id;
|
926 |
|
|
Indx_Typ : Entity_Id;
|
927 |
|
|
Enum_Case : Boolean;
|
928 |
|
|
Typedef : Node_Id;
|
929 |
|
|
|
930 |
|
|
begin
|
931 |
|
|
Indx := First_Index (Typ);
|
932 |
|
|
|
933 |
|
|
while Present (Indx) loop
|
934 |
|
|
Indx_Typ := Etype (Indx);
|
935 |
|
|
|
936 |
|
|
Enum_Case := Is_Enumeration_Type (Indx_Typ)
|
937 |
|
|
and then Has_Non_Standard_Rep (Indx_Typ);
|
938 |
|
|
|
939 |
|
|
-- Unconstrained case
|
940 |
|
|
|
941 |
|
|
if not Is_Constrained (Typ) then
|
942 |
|
|
if Enum_Case then
|
943 |
|
|
Indx_Typ := Standard_Natural;
|
944 |
|
|
end if;
|
945 |
|
|
|
946 |
|
|
Append_To (Indexes, New_Occurrence_Of (Indx_Typ, Loc));
|
947 |
|
|
|
948 |
|
|
-- Constrained case
|
949 |
|
|
|
950 |
|
|
else
|
951 |
|
|
if not Enum_Case then
|
952 |
|
|
Append_To (Indexes, New_Occurrence_Of (Indx_Typ, Loc));
|
953 |
|
|
|
954 |
|
|
else
|
955 |
|
|
Append_To (Indexes,
|
956 |
|
|
Make_Subtype_Indication (Loc,
|
957 |
|
|
Subtype_Mark =>
|
958 |
|
|
New_Occurrence_Of (Standard_Natural, Loc),
|
959 |
|
|
Constraint =>
|
960 |
|
|
Make_Range_Constraint (Loc,
|
961 |
|
|
Range_Expression =>
|
962 |
|
|
Make_Range (Loc,
|
963 |
|
|
Low_Bound =>
|
964 |
|
|
Make_Attribute_Reference (Loc,
|
965 |
|
|
Prefix =>
|
966 |
|
|
New_Occurrence_Of (Indx_Typ, Loc),
|
967 |
|
|
Attribute_Name => Name_Pos,
|
968 |
|
|
Expressions => New_List (
|
969 |
|
|
Make_Attribute_Reference (Loc,
|
970 |
|
|
Prefix =>
|
971 |
|
|
New_Occurrence_Of (Indx_Typ, Loc),
|
972 |
|
|
Attribute_Name => Name_First))),
|
973 |
|
|
|
974 |
|
|
High_Bound =>
|
975 |
|
|
Make_Attribute_Reference (Loc,
|
976 |
|
|
Prefix =>
|
977 |
|
|
New_Occurrence_Of (Indx_Typ, Loc),
|
978 |
|
|
Attribute_Name => Name_Pos,
|
979 |
|
|
Expressions => New_List (
|
980 |
|
|
Make_Attribute_Reference (Loc,
|
981 |
|
|
Prefix =>
|
982 |
|
|
New_Occurrence_Of (Indx_Typ, Loc),
|
983 |
|
|
Attribute_Name => Name_Last)))))));
|
984 |
|
|
|
985 |
|
|
end if;
|
986 |
|
|
end if;
|
987 |
|
|
|
988 |
|
|
Next_Index (Indx);
|
989 |
|
|
end loop;
|
990 |
|
|
|
991 |
|
|
if not Is_Constrained (Typ) then
|
992 |
|
|
Typedef :=
|
993 |
|
|
Make_Unconstrained_Array_Definition (Loc,
|
994 |
|
|
Subtype_Marks => Indexes,
|
995 |
|
|
Component_Definition =>
|
996 |
|
|
Make_Component_Definition (Loc,
|
997 |
|
|
Aliased_Present => False,
|
998 |
|
|
Subtype_Indication =>
|
999 |
|
|
New_Occurrence_Of (Ctyp, Loc)));
|
1000 |
|
|
|
1001 |
|
|
else
|
1002 |
|
|
Typedef :=
|
1003 |
|
|
Make_Constrained_Array_Definition (Loc,
|
1004 |
|
|
Discrete_Subtype_Definitions => Indexes,
|
1005 |
|
|
Component_Definition =>
|
1006 |
|
|
Make_Component_Definition (Loc,
|
1007 |
|
|
Aliased_Present => False,
|
1008 |
|
|
Subtype_Indication =>
|
1009 |
|
|
New_Occurrence_Of (Ctyp, Loc)));
|
1010 |
|
|
end if;
|
1011 |
|
|
|
1012 |
|
|
Decl :=
|
1013 |
|
|
Make_Full_Type_Declaration (Loc,
|
1014 |
|
|
Defining_Identifier => PAT,
|
1015 |
|
|
Type_Definition => Typedef);
|
1016 |
|
|
end;
|
1017 |
|
|
|
1018 |
|
|
-- Set type as packed array type and install it
|
1019 |
|
|
|
1020 |
|
|
Set_Is_Packed_Array_Type (PAT);
|
1021 |
|
|
Install_PAT;
|
1022 |
|
|
return;
|
1023 |
|
|
|
1024 |
|
|
-- Case of bit-packing required for unconstrained array. We create
|
1025 |
|
|
-- a subtype that is equivalent to use Packed_Bytes{1,2,4} as needed.
|
1026 |
|
|
|
1027 |
|
|
elsif not Is_Constrained (Typ) then
|
1028 |
|
|
PAT :=
|
1029 |
|
|
Make_Defining_Identifier (Loc,
|
1030 |
|
|
Chars => Make_Packed_Array_Type_Name (Typ, Csize));
|
1031 |
|
|
|
1032 |
|
|
Set_Packed_Array_Type (Typ, PAT);
|
1033 |
|
|
Set_PB_Type;
|
1034 |
|
|
|
1035 |
|
|
Decl :=
|
1036 |
|
|
Make_Subtype_Declaration (Loc,
|
1037 |
|
|
Defining_Identifier => PAT,
|
1038 |
|
|
Subtype_Indication => New_Occurrence_Of (PB_Type, Loc));
|
1039 |
|
|
Install_PAT;
|
1040 |
|
|
return;
|
1041 |
|
|
|
1042 |
|
|
-- Remaining code is for the case of bit-packing for constrained array
|
1043 |
|
|
|
1044 |
|
|
-- The name of the packed array subtype is
|
1045 |
|
|
|
1046 |
|
|
-- ttt___Xsss
|
1047 |
|
|
|
1048 |
|
|
-- where sss is the component size in bits and ttt is the name of
|
1049 |
|
|
-- the parent packed type.
|
1050 |
|
|
|
1051 |
|
|
else
|
1052 |
|
|
PAT :=
|
1053 |
|
|
Make_Defining_Identifier (Loc,
|
1054 |
|
|
Chars => Make_Packed_Array_Type_Name (Typ, Csize));
|
1055 |
|
|
|
1056 |
|
|
Set_Packed_Array_Type (Typ, PAT);
|
1057 |
|
|
|
1058 |
|
|
-- Build an expression for the length of the array in bits.
|
1059 |
|
|
-- This is the product of the length of each of the dimensions
|
1060 |
|
|
|
1061 |
|
|
declare
|
1062 |
|
|
J : Nat := 1;
|
1063 |
|
|
|
1064 |
|
|
begin
|
1065 |
|
|
Len_Expr := Empty; -- suppress junk warning
|
1066 |
|
|
|
1067 |
|
|
loop
|
1068 |
|
|
Len_Dim :=
|
1069 |
|
|
Make_Attribute_Reference (Loc,
|
1070 |
|
|
Attribute_Name => Name_Length,
|
1071 |
|
|
Prefix => New_Occurrence_Of (Typ, Loc),
|
1072 |
|
|
Expressions => New_List (
|
1073 |
|
|
Make_Integer_Literal (Loc, J)));
|
1074 |
|
|
|
1075 |
|
|
if J = 1 then
|
1076 |
|
|
Len_Expr := Len_Dim;
|
1077 |
|
|
|
1078 |
|
|
else
|
1079 |
|
|
Len_Expr :=
|
1080 |
|
|
Make_Op_Multiply (Loc,
|
1081 |
|
|
Left_Opnd => Len_Expr,
|
1082 |
|
|
Right_Opnd => Len_Dim);
|
1083 |
|
|
end if;
|
1084 |
|
|
|
1085 |
|
|
J := J + 1;
|
1086 |
|
|
exit when J > Number_Dimensions (Typ);
|
1087 |
|
|
end loop;
|
1088 |
|
|
end;
|
1089 |
|
|
|
1090 |
|
|
-- Temporarily attach the length expression to the tree and analyze
|
1091 |
|
|
-- and resolve it, so that we can test its value. We assume that the
|
1092 |
|
|
-- total length fits in type Integer. This expression may involve
|
1093 |
|
|
-- discriminants, so we treat it as a default/per-object expression.
|
1094 |
|
|
|
1095 |
|
|
Set_Parent (Len_Expr, Typ);
|
1096 |
|
|
Preanalyze_Spec_Expression (Len_Expr, Standard_Long_Long_Integer);
|
1097 |
|
|
|
1098 |
|
|
-- Use a modular type if possible. We can do this if we have
|
1099 |
|
|
-- static bounds, and the length is small enough, and the length
|
1100 |
|
|
-- is not zero. We exclude the zero length case because the size
|
1101 |
|
|
-- of things is always at least one, and the zero length object
|
1102 |
|
|
-- would have an anomalous size.
|
1103 |
|
|
|
1104 |
|
|
if Compile_Time_Known_Value (Len_Expr) then
|
1105 |
|
|
Len_Bits := Expr_Value (Len_Expr) * Csize;
|
1106 |
|
|
|
1107 |
|
|
-- Check for size known to be too large
|
1108 |
|
|
|
1109 |
|
|
if Len_Bits >
|
1110 |
|
|
Uint_2 ** (Standard_Integer_Size - 1) * System_Storage_Unit
|
1111 |
|
|
then
|
1112 |
|
|
if System_Storage_Unit = 8 then
|
1113 |
|
|
Error_Msg_N
|
1114 |
|
|
("packed array size cannot exceed " &
|
1115 |
|
|
"Integer''Last bytes", Typ);
|
1116 |
|
|
else
|
1117 |
|
|
Error_Msg_N
|
1118 |
|
|
("packed array size cannot exceed " &
|
1119 |
|
|
"Integer''Last storage units", Typ);
|
1120 |
|
|
end if;
|
1121 |
|
|
|
1122 |
|
|
-- Reset length to arbitrary not too high value to continue
|
1123 |
|
|
|
1124 |
|
|
Len_Expr := Make_Integer_Literal (Loc, 65535);
|
1125 |
|
|
Analyze_And_Resolve (Len_Expr, Standard_Long_Long_Integer);
|
1126 |
|
|
end if;
|
1127 |
|
|
|
1128 |
|
|
-- We normally consider small enough to mean no larger than the
|
1129 |
|
|
-- value of System_Max_Binary_Modulus_Power, checking that in the
|
1130 |
|
|
-- case of values longer than word size, we have long shifts.
|
1131 |
|
|
|
1132 |
|
|
if Len_Bits > 0
|
1133 |
|
|
and then
|
1134 |
|
|
(Len_Bits <= System_Word_Size
|
1135 |
|
|
or else (Len_Bits <= System_Max_Binary_Modulus_Power
|
1136 |
|
|
and then Support_Long_Shifts_On_Target))
|
1137 |
|
|
|
1138 |
|
|
-- Also test for alignment given. If an alignment is given which
|
1139 |
|
|
-- is smaller than the natural modular alignment, force the array
|
1140 |
|
|
-- of bytes representation to accommodate the alignment.
|
1141 |
|
|
|
1142 |
|
|
and then
|
1143 |
|
|
(No (Alignment_Clause (Typ))
|
1144 |
|
|
or else
|
1145 |
|
|
Alignment (Typ) >= ((Len_Bits + System_Storage_Unit)
|
1146 |
|
|
/ System_Storage_Unit))
|
1147 |
|
|
then
|
1148 |
|
|
-- We can use the modular type, it has the form:
|
1149 |
|
|
|
1150 |
|
|
-- subtype tttPn is btyp
|
1151 |
|
|
-- range 0 .. 2 ** ((Typ'Length (1)
|
1152 |
|
|
-- * ... * Typ'Length (n)) * Csize) - 1;
|
1153 |
|
|
|
1154 |
|
|
-- The bounds are statically known, and btyp is one of the
|
1155 |
|
|
-- unsigned types, depending on the length.
|
1156 |
|
|
|
1157 |
|
|
if Len_Bits <= Standard_Short_Short_Integer_Size then
|
1158 |
|
|
Btyp := RTE (RE_Short_Short_Unsigned);
|
1159 |
|
|
|
1160 |
|
|
elsif Len_Bits <= Standard_Short_Integer_Size then
|
1161 |
|
|
Btyp := RTE (RE_Short_Unsigned);
|
1162 |
|
|
|
1163 |
|
|
elsif Len_Bits <= Standard_Integer_Size then
|
1164 |
|
|
Btyp := RTE (RE_Unsigned);
|
1165 |
|
|
|
1166 |
|
|
elsif Len_Bits <= Standard_Long_Integer_Size then
|
1167 |
|
|
Btyp := RTE (RE_Long_Unsigned);
|
1168 |
|
|
|
1169 |
|
|
else
|
1170 |
|
|
Btyp := RTE (RE_Long_Long_Unsigned);
|
1171 |
|
|
end if;
|
1172 |
|
|
|
1173 |
|
|
Lit := Make_Integer_Literal (Loc, 2 ** Len_Bits - 1);
|
1174 |
|
|
Set_Print_In_Hex (Lit);
|
1175 |
|
|
|
1176 |
|
|
Decl :=
|
1177 |
|
|
Make_Subtype_Declaration (Loc,
|
1178 |
|
|
Defining_Identifier => PAT,
|
1179 |
|
|
Subtype_Indication =>
|
1180 |
|
|
Make_Subtype_Indication (Loc,
|
1181 |
|
|
Subtype_Mark => New_Occurrence_Of (Btyp, Loc),
|
1182 |
|
|
|
1183 |
|
|
Constraint =>
|
1184 |
|
|
Make_Range_Constraint (Loc,
|
1185 |
|
|
Range_Expression =>
|
1186 |
|
|
Make_Range (Loc,
|
1187 |
|
|
Low_Bound =>
|
1188 |
|
|
Make_Integer_Literal (Loc, 0),
|
1189 |
|
|
High_Bound => Lit))));
|
1190 |
|
|
|
1191 |
|
|
if PASize = Uint_0 then
|
1192 |
|
|
PASize := Len_Bits;
|
1193 |
|
|
end if;
|
1194 |
|
|
|
1195 |
|
|
Install_PAT;
|
1196 |
|
|
return;
|
1197 |
|
|
end if;
|
1198 |
|
|
end if;
|
1199 |
|
|
|
1200 |
|
|
-- Could not use a modular type, for all other cases, we build
|
1201 |
|
|
-- a packed array subtype:
|
1202 |
|
|
|
1203 |
|
|
-- subtype tttPn is
|
1204 |
|
|
-- System.Packed_Bytes{1,2,4} (0 .. (Bits + 7) / 8 - 1);
|
1205 |
|
|
|
1206 |
|
|
-- Bits is the length of the array in bits
|
1207 |
|
|
|
1208 |
|
|
Set_PB_Type;
|
1209 |
|
|
|
1210 |
|
|
Bits_U1 :=
|
1211 |
|
|
Make_Op_Add (Loc,
|
1212 |
|
|
Left_Opnd =>
|
1213 |
|
|
Make_Op_Multiply (Loc,
|
1214 |
|
|
Left_Opnd =>
|
1215 |
|
|
Make_Integer_Literal (Loc, Csize),
|
1216 |
|
|
Right_Opnd => Len_Expr),
|
1217 |
|
|
|
1218 |
|
|
Right_Opnd =>
|
1219 |
|
|
Make_Integer_Literal (Loc, 7));
|
1220 |
|
|
|
1221 |
|
|
Set_Paren_Count (Bits_U1, 1);
|
1222 |
|
|
|
1223 |
|
|
PAT_High :=
|
1224 |
|
|
Make_Op_Subtract (Loc,
|
1225 |
|
|
Left_Opnd =>
|
1226 |
|
|
Make_Op_Divide (Loc,
|
1227 |
|
|
Left_Opnd => Bits_U1,
|
1228 |
|
|
Right_Opnd => Make_Integer_Literal (Loc, 8)),
|
1229 |
|
|
Right_Opnd => Make_Integer_Literal (Loc, 1));
|
1230 |
|
|
|
1231 |
|
|
Decl :=
|
1232 |
|
|
Make_Subtype_Declaration (Loc,
|
1233 |
|
|
Defining_Identifier => PAT,
|
1234 |
|
|
Subtype_Indication =>
|
1235 |
|
|
Make_Subtype_Indication (Loc,
|
1236 |
|
|
Subtype_Mark => New_Occurrence_Of (PB_Type, Loc),
|
1237 |
|
|
Constraint =>
|
1238 |
|
|
Make_Index_Or_Discriminant_Constraint (Loc,
|
1239 |
|
|
Constraints => New_List (
|
1240 |
|
|
Make_Range (Loc,
|
1241 |
|
|
Low_Bound =>
|
1242 |
|
|
Make_Integer_Literal (Loc, 0),
|
1243 |
|
|
High_Bound =>
|
1244 |
|
|
Convert_To (Standard_Integer, PAT_High))))));
|
1245 |
|
|
|
1246 |
|
|
Install_PAT;
|
1247 |
|
|
|
1248 |
|
|
-- Currently the code in this unit requires that packed arrays
|
1249 |
|
|
-- represented by non-modular arrays of bytes be on a byte
|
1250 |
|
|
-- boundary for bit sizes handled by System.Pack_nn units.
|
1251 |
|
|
-- That's because these units assume the array being accessed
|
1252 |
|
|
-- starts on a byte boundary.
|
1253 |
|
|
|
1254 |
|
|
if Get_Id (UI_To_Int (Csize)) /= RE_Null then
|
1255 |
|
|
Set_Must_Be_On_Byte_Boundary (Typ);
|
1256 |
|
|
end if;
|
1257 |
|
|
end if;
|
1258 |
|
|
end Create_Packed_Array_Type;
|
1259 |
|
|
|
1260 |
|
|
-----------------------------------
|
1261 |
|
|
-- Expand_Bit_Packed_Element_Set --
|
1262 |
|
|
-----------------------------------
|
1263 |
|
|
|
1264 |
|
|
procedure Expand_Bit_Packed_Element_Set (N : Node_Id) is
|
1265 |
|
|
Loc : constant Source_Ptr := Sloc (N);
|
1266 |
|
|
Lhs : constant Node_Id := Name (N);
|
1267 |
|
|
|
1268 |
|
|
Ass_OK : constant Boolean := Assignment_OK (Lhs);
|
1269 |
|
|
-- Used to preserve assignment OK status when assignment is rewritten
|
1270 |
|
|
|
1271 |
|
|
Rhs : Node_Id := Expression (N);
|
1272 |
|
|
-- Initially Rhs is the right hand side value, it will be replaced
|
1273 |
|
|
-- later by an appropriate unchecked conversion for the assignment.
|
1274 |
|
|
|
1275 |
|
|
Obj : Node_Id;
|
1276 |
|
|
Atyp : Entity_Id;
|
1277 |
|
|
PAT : Entity_Id;
|
1278 |
|
|
Ctyp : Entity_Id;
|
1279 |
|
|
Csiz : Int;
|
1280 |
|
|
Cmask : Uint;
|
1281 |
|
|
|
1282 |
|
|
Shift : Node_Id;
|
1283 |
|
|
-- The expression for the shift value that is required
|
1284 |
|
|
|
1285 |
|
|
Shift_Used : Boolean := False;
|
1286 |
|
|
-- Set True if Shift has been used in the generated code at least
|
1287 |
|
|
-- once, so that it must be duplicated if used again
|
1288 |
|
|
|
1289 |
|
|
New_Lhs : Node_Id;
|
1290 |
|
|
New_Rhs : Node_Id;
|
1291 |
|
|
|
1292 |
|
|
Rhs_Val_Known : Boolean;
|
1293 |
|
|
Rhs_Val : Uint;
|
1294 |
|
|
-- If the value of the right hand side as an integer constant is
|
1295 |
|
|
-- known at compile time, Rhs_Val_Known is set True, and Rhs_Val
|
1296 |
|
|
-- contains the value. Otherwise Rhs_Val_Known is set False, and
|
1297 |
|
|
-- the Rhs_Val is undefined.
|
1298 |
|
|
|
1299 |
|
|
function Get_Shift return Node_Id;
|
1300 |
|
|
-- Function used to get the value of Shift, making sure that it
|
1301 |
|
|
-- gets duplicated if the function is called more than once.
|
1302 |
|
|
|
1303 |
|
|
---------------
|
1304 |
|
|
-- Get_Shift --
|
1305 |
|
|
---------------
|
1306 |
|
|
|
1307 |
|
|
function Get_Shift return Node_Id is
|
1308 |
|
|
begin
|
1309 |
|
|
-- If we used the shift value already, then duplicate it. We
|
1310 |
|
|
-- set a temporary parent in case actions have to be inserted.
|
1311 |
|
|
|
1312 |
|
|
if Shift_Used then
|
1313 |
|
|
Set_Parent (Shift, N);
|
1314 |
|
|
return Duplicate_Subexpr_No_Checks (Shift);
|
1315 |
|
|
|
1316 |
|
|
-- If first time, use Shift unchanged, and set flag for first use
|
1317 |
|
|
|
1318 |
|
|
else
|
1319 |
|
|
Shift_Used := True;
|
1320 |
|
|
return Shift;
|
1321 |
|
|
end if;
|
1322 |
|
|
end Get_Shift;
|
1323 |
|
|
|
1324 |
|
|
-- Start of processing for Expand_Bit_Packed_Element_Set
|
1325 |
|
|
|
1326 |
|
|
begin
|
1327 |
|
|
pragma Assert (Is_Bit_Packed_Array (Etype (Prefix (Lhs))));
|
1328 |
|
|
|
1329 |
|
|
Obj := Relocate_Node (Prefix (Lhs));
|
1330 |
|
|
Convert_To_Actual_Subtype (Obj);
|
1331 |
|
|
Atyp := Etype (Obj);
|
1332 |
|
|
PAT := Packed_Array_Type (Atyp);
|
1333 |
|
|
Ctyp := Component_Type (Atyp);
|
1334 |
|
|
Csiz := UI_To_Int (Component_Size (Atyp));
|
1335 |
|
|
|
1336 |
|
|
-- We convert the right hand side to the proper subtype to ensure
|
1337 |
|
|
-- that an appropriate range check is made (since the normal range
|
1338 |
|
|
-- check from assignment will be lost in the transformations). This
|
1339 |
|
|
-- conversion is analyzed immediately so that subsequent processing
|
1340 |
|
|
-- can work with an analyzed Rhs (and e.g. look at its Etype)
|
1341 |
|
|
|
1342 |
|
|
-- If the right-hand side is a string literal, create a temporary for
|
1343 |
|
|
-- it, constant-folding is not ready to wrap the bit representation
|
1344 |
|
|
-- of a string literal.
|
1345 |
|
|
|
1346 |
|
|
if Nkind (Rhs) = N_String_Literal then
|
1347 |
|
|
declare
|
1348 |
|
|
Decl : Node_Id;
|
1349 |
|
|
begin
|
1350 |
|
|
Decl :=
|
1351 |
|
|
Make_Object_Declaration (Loc,
|
1352 |
|
|
Defining_Identifier =>
|
1353 |
|
|
Make_Defining_Identifier (Loc, New_Internal_Name ('T')),
|
1354 |
|
|
Object_Definition => New_Occurrence_Of (Ctyp, Loc),
|
1355 |
|
|
Expression => New_Copy_Tree (Rhs));
|
1356 |
|
|
|
1357 |
|
|
Insert_Actions (N, New_List (Decl));
|
1358 |
|
|
Rhs := New_Occurrence_Of (Defining_Identifier (Decl), Loc);
|
1359 |
|
|
end;
|
1360 |
|
|
end if;
|
1361 |
|
|
|
1362 |
|
|
Rhs := Convert_To (Ctyp, Rhs);
|
1363 |
|
|
Set_Parent (Rhs, N);
|
1364 |
|
|
|
1365 |
|
|
-- If we are building the initialization procedure for a packed array,
|
1366 |
|
|
-- and Initialize_Scalars is enabled, each component assignment is an
|
1367 |
|
|
-- out-of-range value by design. Compile this value without checks,
|
1368 |
|
|
-- because a call to the array init_proc must not raise an exception.
|
1369 |
|
|
|
1370 |
|
|
if Within_Init_Proc
|
1371 |
|
|
and then Initialize_Scalars
|
1372 |
|
|
then
|
1373 |
|
|
Analyze_And_Resolve (Rhs, Ctyp, Suppress => All_Checks);
|
1374 |
|
|
else
|
1375 |
|
|
Analyze_And_Resolve (Rhs, Ctyp);
|
1376 |
|
|
end if;
|
1377 |
|
|
|
1378 |
|
|
-- Case of component size 1,2,4 or any component size for the modular
|
1379 |
|
|
-- case. These are the cases for which we can inline the code.
|
1380 |
|
|
|
1381 |
|
|
if Csiz = 1 or else Csiz = 2 or else Csiz = 4
|
1382 |
|
|
or else (Present (PAT) and then Is_Modular_Integer_Type (PAT))
|
1383 |
|
|
then
|
1384 |
|
|
Setup_Inline_Packed_Array_Reference (Lhs, Atyp, Obj, Cmask, Shift);
|
1385 |
|
|
|
1386 |
|
|
-- The statement to be generated is:
|
1387 |
|
|
|
1388 |
|
|
-- Obj := atyp!((Obj and Mask1) or (shift_left (rhs, shift)))
|
1389 |
|
|
|
1390 |
|
|
-- where mask1 is obtained by shifting Cmask left Shift bits
|
1391 |
|
|
-- and then complementing the result.
|
1392 |
|
|
|
1393 |
|
|
-- the "and Mask1" is omitted if rhs is constant and all 1 bits
|
1394 |
|
|
|
1395 |
|
|
-- the "or ..." is omitted if rhs is constant and all 0 bits
|
1396 |
|
|
|
1397 |
|
|
-- rhs is converted to the appropriate type
|
1398 |
|
|
|
1399 |
|
|
-- The result is converted back to the array type, since
|
1400 |
|
|
-- otherwise we lose knowledge of the packed nature.
|
1401 |
|
|
|
1402 |
|
|
-- Determine if right side is all 0 bits or all 1 bits
|
1403 |
|
|
|
1404 |
|
|
if Compile_Time_Known_Value (Rhs) then
|
1405 |
|
|
Rhs_Val := Expr_Rep_Value (Rhs);
|
1406 |
|
|
Rhs_Val_Known := True;
|
1407 |
|
|
|
1408 |
|
|
-- The following test catches the case of an unchecked conversion
|
1409 |
|
|
-- of an integer literal. This results from optimizing aggregates
|
1410 |
|
|
-- of packed types.
|
1411 |
|
|
|
1412 |
|
|
elsif Nkind (Rhs) = N_Unchecked_Type_Conversion
|
1413 |
|
|
and then Compile_Time_Known_Value (Expression (Rhs))
|
1414 |
|
|
then
|
1415 |
|
|
Rhs_Val := Expr_Rep_Value (Expression (Rhs));
|
1416 |
|
|
Rhs_Val_Known := True;
|
1417 |
|
|
|
1418 |
|
|
else
|
1419 |
|
|
Rhs_Val := No_Uint;
|
1420 |
|
|
Rhs_Val_Known := False;
|
1421 |
|
|
end if;
|
1422 |
|
|
|
1423 |
|
|
-- Some special checks for the case where the right hand value
|
1424 |
|
|
-- is known at compile time. Basically we have to take care of
|
1425 |
|
|
-- the implicit conversion to the subtype of the component object.
|
1426 |
|
|
|
1427 |
|
|
if Rhs_Val_Known then
|
1428 |
|
|
|
1429 |
|
|
-- If we have a biased component type then we must manually do
|
1430 |
|
|
-- the biasing, since we are taking responsibility in this case
|
1431 |
|
|
-- for constructing the exact bit pattern to be used.
|
1432 |
|
|
|
1433 |
|
|
if Has_Biased_Representation (Ctyp) then
|
1434 |
|
|
Rhs_Val := Rhs_Val - Expr_Rep_Value (Type_Low_Bound (Ctyp));
|
1435 |
|
|
end if;
|
1436 |
|
|
|
1437 |
|
|
-- For a negative value, we manually convert the twos complement
|
1438 |
|
|
-- value to a corresponding unsigned value, so that the proper
|
1439 |
|
|
-- field width is maintained. If we did not do this, we would
|
1440 |
|
|
-- get too many leading sign bits later on.
|
1441 |
|
|
|
1442 |
|
|
if Rhs_Val < 0 then
|
1443 |
|
|
Rhs_Val := 2 ** UI_From_Int (Csiz) + Rhs_Val;
|
1444 |
|
|
end if;
|
1445 |
|
|
end if;
|
1446 |
|
|
|
1447 |
|
|
-- Now create copies removing side effects. Note that in some
|
1448 |
|
|
-- complex cases, this may cause the fact that we have already
|
1449 |
|
|
-- set a packed array type on Obj to get lost. So we save the
|
1450 |
|
|
-- type of Obj, and make sure it is reset properly.
|
1451 |
|
|
|
1452 |
|
|
declare
|
1453 |
|
|
T : constant Entity_Id := Etype (Obj);
|
1454 |
|
|
begin
|
1455 |
|
|
New_Lhs := Duplicate_Subexpr (Obj, True);
|
1456 |
|
|
New_Rhs := Duplicate_Subexpr_No_Checks (Obj);
|
1457 |
|
|
Set_Etype (Obj, T);
|
1458 |
|
|
Set_Etype (New_Lhs, T);
|
1459 |
|
|
Set_Etype (New_Rhs, T);
|
1460 |
|
|
end;
|
1461 |
|
|
|
1462 |
|
|
-- First we deal with the "and"
|
1463 |
|
|
|
1464 |
|
|
if not Rhs_Val_Known or else Rhs_Val /= Cmask then
|
1465 |
|
|
declare
|
1466 |
|
|
Mask1 : Node_Id;
|
1467 |
|
|
Lit : Node_Id;
|
1468 |
|
|
|
1469 |
|
|
begin
|
1470 |
|
|
if Compile_Time_Known_Value (Shift) then
|
1471 |
|
|
Mask1 :=
|
1472 |
|
|
Make_Integer_Literal (Loc,
|
1473 |
|
|
Modulus (Etype (Obj)) - 1 -
|
1474 |
|
|
(Cmask * (2 ** Expr_Value (Get_Shift))));
|
1475 |
|
|
Set_Print_In_Hex (Mask1);
|
1476 |
|
|
|
1477 |
|
|
else
|
1478 |
|
|
Lit := Make_Integer_Literal (Loc, Cmask);
|
1479 |
|
|
Set_Print_In_Hex (Lit);
|
1480 |
|
|
Mask1 :=
|
1481 |
|
|
Make_Op_Not (Loc,
|
1482 |
|
|
Right_Opnd => Make_Shift_Left (Lit, Get_Shift));
|
1483 |
|
|
end if;
|
1484 |
|
|
|
1485 |
|
|
New_Rhs :=
|
1486 |
|
|
Make_Op_And (Loc,
|
1487 |
|
|
Left_Opnd => New_Rhs,
|
1488 |
|
|
Right_Opnd => Mask1);
|
1489 |
|
|
end;
|
1490 |
|
|
end if;
|
1491 |
|
|
|
1492 |
|
|
-- Then deal with the "or"
|
1493 |
|
|
|
1494 |
|
|
if not Rhs_Val_Known or else Rhs_Val /= 0 then
|
1495 |
|
|
declare
|
1496 |
|
|
Or_Rhs : Node_Id;
|
1497 |
|
|
|
1498 |
|
|
procedure Fixup_Rhs;
|
1499 |
|
|
-- Adjust Rhs by bias if biased representation for components
|
1500 |
|
|
-- or remove extraneous high order sign bits if signed.
|
1501 |
|
|
|
1502 |
|
|
procedure Fixup_Rhs is
|
1503 |
|
|
Etyp : constant Entity_Id := Etype (Rhs);
|
1504 |
|
|
|
1505 |
|
|
begin
|
1506 |
|
|
-- For biased case, do the required biasing by simply
|
1507 |
|
|
-- converting to the biased subtype (the conversion
|
1508 |
|
|
-- will generate the required bias).
|
1509 |
|
|
|
1510 |
|
|
if Has_Biased_Representation (Ctyp) then
|
1511 |
|
|
Rhs := Convert_To (Ctyp, Rhs);
|
1512 |
|
|
|
1513 |
|
|
-- For a signed integer type that is not biased, generate
|
1514 |
|
|
-- a conversion to unsigned to strip high order sign bits.
|
1515 |
|
|
|
1516 |
|
|
elsif Is_Signed_Integer_Type (Ctyp) then
|
1517 |
|
|
Rhs := Unchecked_Convert_To (RTE (Bits_Id (Csiz)), Rhs);
|
1518 |
|
|
end if;
|
1519 |
|
|
|
1520 |
|
|
-- Set Etype, since it can be referenced before the
|
1521 |
|
|
-- node is completely analyzed.
|
1522 |
|
|
|
1523 |
|
|
Set_Etype (Rhs, Etyp);
|
1524 |
|
|
|
1525 |
|
|
-- We now need to do an unchecked conversion of the
|
1526 |
|
|
-- result to the target type, but it is important that
|
1527 |
|
|
-- this conversion be a right justified conversion and
|
1528 |
|
|
-- not a left justified conversion.
|
1529 |
|
|
|
1530 |
|
|
Rhs := RJ_Unchecked_Convert_To (Etype (Obj), Rhs);
|
1531 |
|
|
|
1532 |
|
|
end Fixup_Rhs;
|
1533 |
|
|
|
1534 |
|
|
begin
|
1535 |
|
|
if Rhs_Val_Known
|
1536 |
|
|
and then Compile_Time_Known_Value (Get_Shift)
|
1537 |
|
|
then
|
1538 |
|
|
Or_Rhs :=
|
1539 |
|
|
Make_Integer_Literal (Loc,
|
1540 |
|
|
Rhs_Val * (2 ** Expr_Value (Get_Shift)));
|
1541 |
|
|
Set_Print_In_Hex (Or_Rhs);
|
1542 |
|
|
|
1543 |
|
|
else
|
1544 |
|
|
-- We have to convert the right hand side to Etype (Obj).
|
1545 |
|
|
-- A special case arises if what we have now is a Val
|
1546 |
|
|
-- attribute reference whose expression type is Etype (Obj).
|
1547 |
|
|
-- This happens for assignments of fields from the same
|
1548 |
|
|
-- array. In this case we get the required right hand side
|
1549 |
|
|
-- by simply removing the inner attribute reference.
|
1550 |
|
|
|
1551 |
|
|
if Nkind (Rhs) = N_Attribute_Reference
|
1552 |
|
|
and then Attribute_Name (Rhs) = Name_Val
|
1553 |
|
|
and then Etype (First (Expressions (Rhs))) = Etype (Obj)
|
1554 |
|
|
then
|
1555 |
|
|
Rhs := Relocate_Node (First (Expressions (Rhs)));
|
1556 |
|
|
Fixup_Rhs;
|
1557 |
|
|
|
1558 |
|
|
-- If the value of the right hand side is a known integer
|
1559 |
|
|
-- value, then just replace it by an untyped constant,
|
1560 |
|
|
-- which will be properly retyped when we analyze and
|
1561 |
|
|
-- resolve the expression.
|
1562 |
|
|
|
1563 |
|
|
elsif Rhs_Val_Known then
|
1564 |
|
|
|
1565 |
|
|
-- Note that Rhs_Val has already been normalized to
|
1566 |
|
|
-- be an unsigned value with the proper number of bits.
|
1567 |
|
|
|
1568 |
|
|
Rhs :=
|
1569 |
|
|
Make_Integer_Literal (Loc, Rhs_Val);
|
1570 |
|
|
|
1571 |
|
|
-- Otherwise we need an unchecked conversion
|
1572 |
|
|
|
1573 |
|
|
else
|
1574 |
|
|
Fixup_Rhs;
|
1575 |
|
|
end if;
|
1576 |
|
|
|
1577 |
|
|
Or_Rhs := Make_Shift_Left (Rhs, Get_Shift);
|
1578 |
|
|
end if;
|
1579 |
|
|
|
1580 |
|
|
if Nkind (New_Rhs) = N_Op_And then
|
1581 |
|
|
Set_Paren_Count (New_Rhs, 1);
|
1582 |
|
|
end if;
|
1583 |
|
|
|
1584 |
|
|
New_Rhs :=
|
1585 |
|
|
Make_Op_Or (Loc,
|
1586 |
|
|
Left_Opnd => New_Rhs,
|
1587 |
|
|
Right_Opnd => Or_Rhs);
|
1588 |
|
|
end;
|
1589 |
|
|
end if;
|
1590 |
|
|
|
1591 |
|
|
-- Now do the rewrite
|
1592 |
|
|
|
1593 |
|
|
Rewrite (N,
|
1594 |
|
|
Make_Assignment_Statement (Loc,
|
1595 |
|
|
Name => New_Lhs,
|
1596 |
|
|
Expression =>
|
1597 |
|
|
Unchecked_Convert_To (Etype (New_Lhs), New_Rhs)));
|
1598 |
|
|
Set_Assignment_OK (Name (N), Ass_OK);
|
1599 |
|
|
|
1600 |
|
|
-- All other component sizes for non-modular case
|
1601 |
|
|
|
1602 |
|
|
else
|
1603 |
|
|
-- We generate
|
1604 |
|
|
|
1605 |
|
|
-- Set_nn (Arr'address, Subscr, Bits_nn!(Rhs))
|
1606 |
|
|
|
1607 |
|
|
-- where Subscr is the computed linear subscript
|
1608 |
|
|
|
1609 |
|
|
declare
|
1610 |
|
|
Bits_nn : constant Entity_Id := RTE (Bits_Id (Csiz));
|
1611 |
|
|
Set_nn : Entity_Id;
|
1612 |
|
|
Subscr : Node_Id;
|
1613 |
|
|
Atyp : Entity_Id;
|
1614 |
|
|
|
1615 |
|
|
begin
|
1616 |
|
|
if No (Bits_nn) then
|
1617 |
|
|
|
1618 |
|
|
-- Error, most likely High_Integrity_Mode restriction
|
1619 |
|
|
|
1620 |
|
|
return;
|
1621 |
|
|
end if;
|
1622 |
|
|
|
1623 |
|
|
-- Acquire proper Set entity. We use the aligned or unaligned
|
1624 |
|
|
-- case as appropriate.
|
1625 |
|
|
|
1626 |
|
|
if Known_Aligned_Enough (Obj, Csiz) then
|
1627 |
|
|
Set_nn := RTE (Set_Id (Csiz));
|
1628 |
|
|
else
|
1629 |
|
|
Set_nn := RTE (SetU_Id (Csiz));
|
1630 |
|
|
end if;
|
1631 |
|
|
|
1632 |
|
|
-- Now generate the set reference
|
1633 |
|
|
|
1634 |
|
|
Obj := Relocate_Node (Prefix (Lhs));
|
1635 |
|
|
Convert_To_Actual_Subtype (Obj);
|
1636 |
|
|
Atyp := Etype (Obj);
|
1637 |
|
|
Compute_Linear_Subscript (Atyp, Lhs, Subscr);
|
1638 |
|
|
|
1639 |
|
|
-- Below we must make the assumption that Obj is
|
1640 |
|
|
-- at least byte aligned, since otherwise its address
|
1641 |
|
|
-- cannot be taken. The assumption holds since the
|
1642 |
|
|
-- only arrays that can be misaligned are small packed
|
1643 |
|
|
-- arrays which are implemented as a modular type, and
|
1644 |
|
|
-- that is not the case here.
|
1645 |
|
|
|
1646 |
|
|
Rewrite (N,
|
1647 |
|
|
Make_Procedure_Call_Statement (Loc,
|
1648 |
|
|
Name => New_Occurrence_Of (Set_nn, Loc),
|
1649 |
|
|
Parameter_Associations => New_List (
|
1650 |
|
|
Make_Attribute_Reference (Loc,
|
1651 |
|
|
Prefix => Obj,
|
1652 |
|
|
Attribute_Name => Name_Address),
|
1653 |
|
|
Subscr,
|
1654 |
|
|
Unchecked_Convert_To (Bits_nn,
|
1655 |
|
|
Convert_To (Ctyp, Rhs)))));
|
1656 |
|
|
|
1657 |
|
|
end;
|
1658 |
|
|
end if;
|
1659 |
|
|
|
1660 |
|
|
Analyze (N, Suppress => All_Checks);
|
1661 |
|
|
end Expand_Bit_Packed_Element_Set;
|
1662 |
|
|
|
1663 |
|
|
-------------------------------------
|
1664 |
|
|
-- Expand_Packed_Address_Reference --
|
1665 |
|
|
-------------------------------------
|
1666 |
|
|
|
1667 |
|
|
procedure Expand_Packed_Address_Reference (N : Node_Id) is
|
1668 |
|
|
Loc : constant Source_Ptr := Sloc (N);
|
1669 |
|
|
Ploc : Source_Ptr;
|
1670 |
|
|
Pref : Node_Id;
|
1671 |
|
|
Expr : Node_Id;
|
1672 |
|
|
Term : Node_Id;
|
1673 |
|
|
Atyp : Entity_Id;
|
1674 |
|
|
Subscr : Node_Id;
|
1675 |
|
|
|
1676 |
|
|
begin
|
1677 |
|
|
Pref := Prefix (N);
|
1678 |
|
|
Expr := Empty;
|
1679 |
|
|
|
1680 |
|
|
-- We build up an expression serially that has the form
|
1681 |
|
|
|
1682 |
|
|
-- outer_object'Address
|
1683 |
|
|
-- + (linear-subscript * component_size for each array reference
|
1684 |
|
|
-- + field'Bit_Position for each record field
|
1685 |
|
|
-- + ...
|
1686 |
|
|
-- + ...) / Storage_Unit;
|
1687 |
|
|
|
1688 |
|
|
-- Some additional conversions are required to deal with the addition
|
1689 |
|
|
-- operation, which is not normally visible to generated code.
|
1690 |
|
|
|
1691 |
|
|
loop
|
1692 |
|
|
Ploc := Sloc (Pref);
|
1693 |
|
|
|
1694 |
|
|
if Nkind (Pref) = N_Indexed_Component then
|
1695 |
|
|
Convert_To_Actual_Subtype (Prefix (Pref));
|
1696 |
|
|
Atyp := Etype (Prefix (Pref));
|
1697 |
|
|
Compute_Linear_Subscript (Atyp, Pref, Subscr);
|
1698 |
|
|
|
1699 |
|
|
Term :=
|
1700 |
|
|
Make_Op_Multiply (Ploc,
|
1701 |
|
|
Left_Opnd => Subscr,
|
1702 |
|
|
Right_Opnd =>
|
1703 |
|
|
Make_Attribute_Reference (Ploc,
|
1704 |
|
|
Prefix => New_Occurrence_Of (Atyp, Ploc),
|
1705 |
|
|
Attribute_Name => Name_Component_Size));
|
1706 |
|
|
|
1707 |
|
|
elsif Nkind (Pref) = N_Selected_Component then
|
1708 |
|
|
Term :=
|
1709 |
|
|
Make_Attribute_Reference (Ploc,
|
1710 |
|
|
Prefix => Selector_Name (Pref),
|
1711 |
|
|
Attribute_Name => Name_Bit_Position);
|
1712 |
|
|
|
1713 |
|
|
else
|
1714 |
|
|
exit;
|
1715 |
|
|
end if;
|
1716 |
|
|
|
1717 |
|
|
Term := Convert_To (RTE (RE_Integer_Address), Term);
|
1718 |
|
|
|
1719 |
|
|
if No (Expr) then
|
1720 |
|
|
Expr := Term;
|
1721 |
|
|
|
1722 |
|
|
else
|
1723 |
|
|
Expr :=
|
1724 |
|
|
Make_Op_Add (Ploc,
|
1725 |
|
|
Left_Opnd => Expr,
|
1726 |
|
|
Right_Opnd => Term);
|
1727 |
|
|
end if;
|
1728 |
|
|
|
1729 |
|
|
Pref := Prefix (Pref);
|
1730 |
|
|
end loop;
|
1731 |
|
|
|
1732 |
|
|
Rewrite (N,
|
1733 |
|
|
Unchecked_Convert_To (RTE (RE_Address),
|
1734 |
|
|
Make_Op_Add (Loc,
|
1735 |
|
|
Left_Opnd =>
|
1736 |
|
|
Unchecked_Convert_To (RTE (RE_Integer_Address),
|
1737 |
|
|
Make_Attribute_Reference (Loc,
|
1738 |
|
|
Prefix => Pref,
|
1739 |
|
|
Attribute_Name => Name_Address)),
|
1740 |
|
|
|
1741 |
|
|
Right_Opnd =>
|
1742 |
|
|
Make_Op_Divide (Loc,
|
1743 |
|
|
Left_Opnd => Expr,
|
1744 |
|
|
Right_Opnd =>
|
1745 |
|
|
Make_Integer_Literal (Loc, System_Storage_Unit)))));
|
1746 |
|
|
|
1747 |
|
|
Analyze_And_Resolve (N, RTE (RE_Address));
|
1748 |
|
|
end Expand_Packed_Address_Reference;
|
1749 |
|
|
|
1750 |
|
|
------------------------------------
|
1751 |
|
|
-- Expand_Packed_Boolean_Operator --
|
1752 |
|
|
------------------------------------
|
1753 |
|
|
|
1754 |
|
|
-- This routine expands "a op b" for the packed cases
|
1755 |
|
|
|
1756 |
|
|
procedure Expand_Packed_Boolean_Operator (N : Node_Id) is
|
1757 |
|
|
Loc : constant Source_Ptr := Sloc (N);
|
1758 |
|
|
Typ : constant Entity_Id := Etype (N);
|
1759 |
|
|
L : constant Node_Id := Relocate_Node (Left_Opnd (N));
|
1760 |
|
|
R : constant Node_Id := Relocate_Node (Right_Opnd (N));
|
1761 |
|
|
|
1762 |
|
|
Ltyp : Entity_Id;
|
1763 |
|
|
Rtyp : Entity_Id;
|
1764 |
|
|
PAT : Entity_Id;
|
1765 |
|
|
|
1766 |
|
|
begin
|
1767 |
|
|
Convert_To_Actual_Subtype (L);
|
1768 |
|
|
Convert_To_Actual_Subtype (R);
|
1769 |
|
|
|
1770 |
|
|
Ensure_Defined (Etype (L), N);
|
1771 |
|
|
Ensure_Defined (Etype (R), N);
|
1772 |
|
|
|
1773 |
|
|
Apply_Length_Check (R, Etype (L));
|
1774 |
|
|
|
1775 |
|
|
Ltyp := Etype (L);
|
1776 |
|
|
Rtyp := Etype (R);
|
1777 |
|
|
|
1778 |
|
|
-- Deal with silly case of XOR where the subcomponent has a range
|
1779 |
|
|
-- True .. True where an exception must be raised.
|
1780 |
|
|
|
1781 |
|
|
if Nkind (N) = N_Op_Xor then
|
1782 |
|
|
Silly_Boolean_Array_Xor_Test (N, Rtyp);
|
1783 |
|
|
end if;
|
1784 |
|
|
|
1785 |
|
|
-- Now that that silliness is taken care of, get packed array type
|
1786 |
|
|
|
1787 |
|
|
Convert_To_PAT_Type (L);
|
1788 |
|
|
Convert_To_PAT_Type (R);
|
1789 |
|
|
|
1790 |
|
|
PAT := Etype (L);
|
1791 |
|
|
|
1792 |
|
|
-- For the modular case, we expand a op b into
|
1793 |
|
|
|
1794 |
|
|
-- rtyp!(pat!(a) op pat!(b))
|
1795 |
|
|
|
1796 |
|
|
-- where rtyp is the Etype of the left operand. Note that we do not
|
1797 |
|
|
-- convert to the base type, since this would be unconstrained, and
|
1798 |
|
|
-- hence not have a corresponding packed array type set.
|
1799 |
|
|
|
1800 |
|
|
-- Note that both operands must be modular for this code to be used
|
1801 |
|
|
|
1802 |
|
|
if Is_Modular_Integer_Type (PAT)
|
1803 |
|
|
and then
|
1804 |
|
|
Is_Modular_Integer_Type (Etype (R))
|
1805 |
|
|
then
|
1806 |
|
|
declare
|
1807 |
|
|
P : Node_Id;
|
1808 |
|
|
|
1809 |
|
|
begin
|
1810 |
|
|
if Nkind (N) = N_Op_And then
|
1811 |
|
|
P := Make_Op_And (Loc, L, R);
|
1812 |
|
|
|
1813 |
|
|
elsif Nkind (N) = N_Op_Or then
|
1814 |
|
|
P := Make_Op_Or (Loc, L, R);
|
1815 |
|
|
|
1816 |
|
|
else -- Nkind (N) = N_Op_Xor
|
1817 |
|
|
P := Make_Op_Xor (Loc, L, R);
|
1818 |
|
|
end if;
|
1819 |
|
|
|
1820 |
|
|
Rewrite (N, Unchecked_Convert_To (Ltyp, P));
|
1821 |
|
|
end;
|
1822 |
|
|
|
1823 |
|
|
-- For the array case, we insert the actions
|
1824 |
|
|
|
1825 |
|
|
-- Result : Ltype;
|
1826 |
|
|
|
1827 |
|
|
-- System.Bit_Ops.Bit_And/Or/Xor
|
1828 |
|
|
-- (Left'Address,
|
1829 |
|
|
-- Ltype'Length * Ltype'Component_Size;
|
1830 |
|
|
-- Right'Address,
|
1831 |
|
|
-- Rtype'Length * Rtype'Component_Size
|
1832 |
|
|
-- Result'Address);
|
1833 |
|
|
|
1834 |
|
|
-- where Left and Right are the Packed_Bytes{1,2,4} operands and
|
1835 |
|
|
-- the second argument and fourth arguments are the lengths of the
|
1836 |
|
|
-- operands in bits. Then we replace the expression by a reference
|
1837 |
|
|
-- to Result.
|
1838 |
|
|
|
1839 |
|
|
-- Note that if we are mixing a modular and array operand, everything
|
1840 |
|
|
-- works fine, since we ensure that the modular representation has the
|
1841 |
|
|
-- same physical layout as the array representation (that's what the
|
1842 |
|
|
-- left justified modular stuff in the big-endian case is about).
|
1843 |
|
|
|
1844 |
|
|
else
|
1845 |
|
|
declare
|
1846 |
|
|
Result_Ent : constant Entity_Id :=
|
1847 |
|
|
Make_Defining_Identifier (Loc,
|
1848 |
|
|
Chars => New_Internal_Name ('T'));
|
1849 |
|
|
|
1850 |
|
|
E_Id : RE_Id;
|
1851 |
|
|
|
1852 |
|
|
begin
|
1853 |
|
|
if Nkind (N) = N_Op_And then
|
1854 |
|
|
E_Id := RE_Bit_And;
|
1855 |
|
|
|
1856 |
|
|
elsif Nkind (N) = N_Op_Or then
|
1857 |
|
|
E_Id := RE_Bit_Or;
|
1858 |
|
|
|
1859 |
|
|
else -- Nkind (N) = N_Op_Xor
|
1860 |
|
|
E_Id := RE_Bit_Xor;
|
1861 |
|
|
end if;
|
1862 |
|
|
|
1863 |
|
|
Insert_Actions (N, New_List (
|
1864 |
|
|
|
1865 |
|
|
Make_Object_Declaration (Loc,
|
1866 |
|
|
Defining_Identifier => Result_Ent,
|
1867 |
|
|
Object_Definition => New_Occurrence_Of (Ltyp, Loc)),
|
1868 |
|
|
|
1869 |
|
|
Make_Procedure_Call_Statement (Loc,
|
1870 |
|
|
Name => New_Occurrence_Of (RTE (E_Id), Loc),
|
1871 |
|
|
Parameter_Associations => New_List (
|
1872 |
|
|
|
1873 |
|
|
Make_Byte_Aligned_Attribute_Reference (Loc,
|
1874 |
|
|
Prefix => L,
|
1875 |
|
|
Attribute_Name => Name_Address),
|
1876 |
|
|
|
1877 |
|
|
Make_Op_Multiply (Loc,
|
1878 |
|
|
Left_Opnd =>
|
1879 |
|
|
Make_Attribute_Reference (Loc,
|
1880 |
|
|
Prefix =>
|
1881 |
|
|
New_Occurrence_Of
|
1882 |
|
|
(Etype (First_Index (Ltyp)), Loc),
|
1883 |
|
|
Attribute_Name => Name_Range_Length),
|
1884 |
|
|
|
1885 |
|
|
Right_Opnd =>
|
1886 |
|
|
Make_Integer_Literal (Loc, Component_Size (Ltyp))),
|
1887 |
|
|
|
1888 |
|
|
Make_Byte_Aligned_Attribute_Reference (Loc,
|
1889 |
|
|
Prefix => R,
|
1890 |
|
|
Attribute_Name => Name_Address),
|
1891 |
|
|
|
1892 |
|
|
Make_Op_Multiply (Loc,
|
1893 |
|
|
Left_Opnd =>
|
1894 |
|
|
Make_Attribute_Reference (Loc,
|
1895 |
|
|
Prefix =>
|
1896 |
|
|
New_Occurrence_Of
|
1897 |
|
|
(Etype (First_Index (Rtyp)), Loc),
|
1898 |
|
|
Attribute_Name => Name_Range_Length),
|
1899 |
|
|
|
1900 |
|
|
Right_Opnd =>
|
1901 |
|
|
Make_Integer_Literal (Loc, Component_Size (Rtyp))),
|
1902 |
|
|
|
1903 |
|
|
Make_Byte_Aligned_Attribute_Reference (Loc,
|
1904 |
|
|
Prefix => New_Occurrence_Of (Result_Ent, Loc),
|
1905 |
|
|
Attribute_Name => Name_Address)))));
|
1906 |
|
|
|
1907 |
|
|
Rewrite (N,
|
1908 |
|
|
New_Occurrence_Of (Result_Ent, Loc));
|
1909 |
|
|
end;
|
1910 |
|
|
end if;
|
1911 |
|
|
|
1912 |
|
|
Analyze_And_Resolve (N, Typ, Suppress => All_Checks);
|
1913 |
|
|
end Expand_Packed_Boolean_Operator;
|
1914 |
|
|
|
1915 |
|
|
-------------------------------------
|
1916 |
|
|
-- Expand_Packed_Element_Reference --
|
1917 |
|
|
-------------------------------------
|
1918 |
|
|
|
1919 |
|
|
procedure Expand_Packed_Element_Reference (N : Node_Id) is
|
1920 |
|
|
Loc : constant Source_Ptr := Sloc (N);
|
1921 |
|
|
Obj : Node_Id;
|
1922 |
|
|
Atyp : Entity_Id;
|
1923 |
|
|
PAT : Entity_Id;
|
1924 |
|
|
Ctyp : Entity_Id;
|
1925 |
|
|
Csiz : Int;
|
1926 |
|
|
Shift : Node_Id;
|
1927 |
|
|
Cmask : Uint;
|
1928 |
|
|
Lit : Node_Id;
|
1929 |
|
|
Arg : Node_Id;
|
1930 |
|
|
|
1931 |
|
|
begin
|
1932 |
|
|
-- If not bit packed, we have the enumeration case, which is easily
|
1933 |
|
|
-- dealt with (just adjust the subscripts of the indexed component)
|
1934 |
|
|
|
1935 |
|
|
-- Note: this leaves the result as an indexed component, which is
|
1936 |
|
|
-- still a variable, so can be used in the assignment case, as is
|
1937 |
|
|
-- required in the enumeration case.
|
1938 |
|
|
|
1939 |
|
|
if not Is_Bit_Packed_Array (Etype (Prefix (N))) then
|
1940 |
|
|
Setup_Enumeration_Packed_Array_Reference (N);
|
1941 |
|
|
return;
|
1942 |
|
|
end if;
|
1943 |
|
|
|
1944 |
|
|
-- Remaining processing is for the bit-packed case
|
1945 |
|
|
|
1946 |
|
|
Obj := Relocate_Node (Prefix (N));
|
1947 |
|
|
Convert_To_Actual_Subtype (Obj);
|
1948 |
|
|
Atyp := Etype (Obj);
|
1949 |
|
|
PAT := Packed_Array_Type (Atyp);
|
1950 |
|
|
Ctyp := Component_Type (Atyp);
|
1951 |
|
|
Csiz := UI_To_Int (Component_Size (Atyp));
|
1952 |
|
|
|
1953 |
|
|
-- Case of component size 1,2,4 or any component size for the modular
|
1954 |
|
|
-- case. These are the cases for which we can inline the code.
|
1955 |
|
|
|
1956 |
|
|
if Csiz = 1 or else Csiz = 2 or else Csiz = 4
|
1957 |
|
|
or else (Present (PAT) and then Is_Modular_Integer_Type (PAT))
|
1958 |
|
|
then
|
1959 |
|
|
Setup_Inline_Packed_Array_Reference (N, Atyp, Obj, Cmask, Shift);
|
1960 |
|
|
Lit := Make_Integer_Literal (Loc, Cmask);
|
1961 |
|
|
Set_Print_In_Hex (Lit);
|
1962 |
|
|
|
1963 |
|
|
-- We generate a shift right to position the field, followed by a
|
1964 |
|
|
-- masking operation to extract the bit field, and we finally do an
|
1965 |
|
|
-- unchecked conversion to convert the result to the required target.
|
1966 |
|
|
|
1967 |
|
|
-- Note that the unchecked conversion automatically deals with the
|
1968 |
|
|
-- bias if we are dealing with a biased representation. What will
|
1969 |
|
|
-- happen is that we temporarily generate the biased representation,
|
1970 |
|
|
-- but almost immediately that will be converted to the original
|
1971 |
|
|
-- unbiased component type, and the bias will disappear.
|
1972 |
|
|
|
1973 |
|
|
Arg :=
|
1974 |
|
|
Make_Op_And (Loc,
|
1975 |
|
|
Left_Opnd => Make_Shift_Right (Obj, Shift),
|
1976 |
|
|
Right_Opnd => Lit);
|
1977 |
|
|
|
1978 |
|
|
-- We needed to analyze this before we do the unchecked convert
|
1979 |
|
|
-- below, but we need it temporarily attached to the tree for
|
1980 |
|
|
-- this analysis (hence the temporary Set_Parent call).
|
1981 |
|
|
|
1982 |
|
|
Set_Parent (Arg, Parent (N));
|
1983 |
|
|
Analyze_And_Resolve (Arg);
|
1984 |
|
|
|
1985 |
|
|
Rewrite (N,
|
1986 |
|
|
RJ_Unchecked_Convert_To (Ctyp, Arg));
|
1987 |
|
|
|
1988 |
|
|
-- All other component sizes for non-modular case
|
1989 |
|
|
|
1990 |
|
|
else
|
1991 |
|
|
-- We generate
|
1992 |
|
|
|
1993 |
|
|
-- Component_Type!(Get_nn (Arr'address, Subscr))
|
1994 |
|
|
|
1995 |
|
|
-- where Subscr is the computed linear subscript
|
1996 |
|
|
|
1997 |
|
|
declare
|
1998 |
|
|
Get_nn : Entity_Id;
|
1999 |
|
|
Subscr : Node_Id;
|
2000 |
|
|
|
2001 |
|
|
begin
|
2002 |
|
|
-- Acquire proper Get entity. We use the aligned or unaligned
|
2003 |
|
|
-- case as appropriate.
|
2004 |
|
|
|
2005 |
|
|
if Known_Aligned_Enough (Obj, Csiz) then
|
2006 |
|
|
Get_nn := RTE (Get_Id (Csiz));
|
2007 |
|
|
else
|
2008 |
|
|
Get_nn := RTE (GetU_Id (Csiz));
|
2009 |
|
|
end if;
|
2010 |
|
|
|
2011 |
|
|
-- Now generate the get reference
|
2012 |
|
|
|
2013 |
|
|
Compute_Linear_Subscript (Atyp, N, Subscr);
|
2014 |
|
|
|
2015 |
|
|
-- Below we make the assumption that Obj is at least byte
|
2016 |
|
|
-- aligned, since otherwise its address cannot be taken.
|
2017 |
|
|
-- The assumption holds since the only arrays that can be
|
2018 |
|
|
-- misaligned are small packed arrays which are implemented
|
2019 |
|
|
-- as a modular type, and that is not the case here.
|
2020 |
|
|
|
2021 |
|
|
Rewrite (N,
|
2022 |
|
|
Unchecked_Convert_To (Ctyp,
|
2023 |
|
|
Make_Function_Call (Loc,
|
2024 |
|
|
Name => New_Occurrence_Of (Get_nn, Loc),
|
2025 |
|
|
Parameter_Associations => New_List (
|
2026 |
|
|
Make_Attribute_Reference (Loc,
|
2027 |
|
|
Prefix => Obj,
|
2028 |
|
|
Attribute_Name => Name_Address),
|
2029 |
|
|
Subscr))));
|
2030 |
|
|
end;
|
2031 |
|
|
end if;
|
2032 |
|
|
|
2033 |
|
|
Analyze_And_Resolve (N, Ctyp, Suppress => All_Checks);
|
2034 |
|
|
|
2035 |
|
|
end Expand_Packed_Element_Reference;
|
2036 |
|
|
|
2037 |
|
|
----------------------
|
2038 |
|
|
-- Expand_Packed_Eq --
|
2039 |
|
|
----------------------
|
2040 |
|
|
|
2041 |
|
|
-- Handles expansion of "=" on packed array types
|
2042 |
|
|
|
2043 |
|
|
procedure Expand_Packed_Eq (N : Node_Id) is
|
2044 |
|
|
Loc : constant Source_Ptr := Sloc (N);
|
2045 |
|
|
L : constant Node_Id := Relocate_Node (Left_Opnd (N));
|
2046 |
|
|
R : constant Node_Id := Relocate_Node (Right_Opnd (N));
|
2047 |
|
|
|
2048 |
|
|
LLexpr : Node_Id;
|
2049 |
|
|
RLexpr : Node_Id;
|
2050 |
|
|
|
2051 |
|
|
Ltyp : Entity_Id;
|
2052 |
|
|
Rtyp : Entity_Id;
|
2053 |
|
|
PAT : Entity_Id;
|
2054 |
|
|
|
2055 |
|
|
begin
|
2056 |
|
|
Convert_To_Actual_Subtype (L);
|
2057 |
|
|
Convert_To_Actual_Subtype (R);
|
2058 |
|
|
Ltyp := Underlying_Type (Etype (L));
|
2059 |
|
|
Rtyp := Underlying_Type (Etype (R));
|
2060 |
|
|
|
2061 |
|
|
Convert_To_PAT_Type (L);
|
2062 |
|
|
Convert_To_PAT_Type (R);
|
2063 |
|
|
PAT := Etype (L);
|
2064 |
|
|
|
2065 |
|
|
LLexpr :=
|
2066 |
|
|
Make_Op_Multiply (Loc,
|
2067 |
|
|
Left_Opnd =>
|
2068 |
|
|
Make_Attribute_Reference (Loc,
|
2069 |
|
|
Prefix => New_Occurrence_Of (Ltyp, Loc),
|
2070 |
|
|
Attribute_Name => Name_Length),
|
2071 |
|
|
Right_Opnd =>
|
2072 |
|
|
Make_Integer_Literal (Loc, Component_Size (Ltyp)));
|
2073 |
|
|
|
2074 |
|
|
RLexpr :=
|
2075 |
|
|
Make_Op_Multiply (Loc,
|
2076 |
|
|
Left_Opnd =>
|
2077 |
|
|
Make_Attribute_Reference (Loc,
|
2078 |
|
|
Prefix => New_Occurrence_Of (Rtyp, Loc),
|
2079 |
|
|
Attribute_Name => Name_Length),
|
2080 |
|
|
Right_Opnd =>
|
2081 |
|
|
Make_Integer_Literal (Loc, Component_Size (Rtyp)));
|
2082 |
|
|
|
2083 |
|
|
-- For the modular case, we transform the comparison to:
|
2084 |
|
|
|
2085 |
|
|
-- Ltyp'Length = Rtyp'Length and then PAT!(L) = PAT!(R)
|
2086 |
|
|
|
2087 |
|
|
-- where PAT is the packed array type. This works fine, since in the
|
2088 |
|
|
-- modular case we guarantee that the unused bits are always zeroes.
|
2089 |
|
|
-- We do have to compare the lengths because we could be comparing
|
2090 |
|
|
-- two different subtypes of the same base type.
|
2091 |
|
|
|
2092 |
|
|
if Is_Modular_Integer_Type (PAT) then
|
2093 |
|
|
Rewrite (N,
|
2094 |
|
|
Make_And_Then (Loc,
|
2095 |
|
|
Left_Opnd =>
|
2096 |
|
|
Make_Op_Eq (Loc,
|
2097 |
|
|
Left_Opnd => LLexpr,
|
2098 |
|
|
Right_Opnd => RLexpr),
|
2099 |
|
|
|
2100 |
|
|
Right_Opnd =>
|
2101 |
|
|
Make_Op_Eq (Loc,
|
2102 |
|
|
Left_Opnd => L,
|
2103 |
|
|
Right_Opnd => R)));
|
2104 |
|
|
|
2105 |
|
|
-- For the non-modular case, we call a runtime routine
|
2106 |
|
|
|
2107 |
|
|
-- System.Bit_Ops.Bit_Eq
|
2108 |
|
|
-- (L'Address, L_Length, R'Address, R_Length)
|
2109 |
|
|
|
2110 |
|
|
-- where PAT is the packed array type, and the lengths are the lengths
|
2111 |
|
|
-- in bits of the original packed arrays. This routine takes care of
|
2112 |
|
|
-- not comparing the unused bits in the last byte.
|
2113 |
|
|
|
2114 |
|
|
else
|
2115 |
|
|
Rewrite (N,
|
2116 |
|
|
Make_Function_Call (Loc,
|
2117 |
|
|
Name => New_Occurrence_Of (RTE (RE_Bit_Eq), Loc),
|
2118 |
|
|
Parameter_Associations => New_List (
|
2119 |
|
|
Make_Byte_Aligned_Attribute_Reference (Loc,
|
2120 |
|
|
Prefix => L,
|
2121 |
|
|
Attribute_Name => Name_Address),
|
2122 |
|
|
|
2123 |
|
|
LLexpr,
|
2124 |
|
|
|
2125 |
|
|
Make_Byte_Aligned_Attribute_Reference (Loc,
|
2126 |
|
|
Prefix => R,
|
2127 |
|
|
Attribute_Name => Name_Address),
|
2128 |
|
|
|
2129 |
|
|
RLexpr)));
|
2130 |
|
|
end if;
|
2131 |
|
|
|
2132 |
|
|
Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
|
2133 |
|
|
end Expand_Packed_Eq;
|
2134 |
|
|
|
2135 |
|
|
-----------------------
|
2136 |
|
|
-- Expand_Packed_Not --
|
2137 |
|
|
-----------------------
|
2138 |
|
|
|
2139 |
|
|
-- Handles expansion of "not" on packed array types
|
2140 |
|
|
|
2141 |
|
|
procedure Expand_Packed_Not (N : Node_Id) is
|
2142 |
|
|
Loc : constant Source_Ptr := Sloc (N);
|
2143 |
|
|
Typ : constant Entity_Id := Etype (N);
|
2144 |
|
|
Opnd : constant Node_Id := Relocate_Node (Right_Opnd (N));
|
2145 |
|
|
|
2146 |
|
|
Rtyp : Entity_Id;
|
2147 |
|
|
PAT : Entity_Id;
|
2148 |
|
|
Lit : Node_Id;
|
2149 |
|
|
|
2150 |
|
|
begin
|
2151 |
|
|
Convert_To_Actual_Subtype (Opnd);
|
2152 |
|
|
Rtyp := Etype (Opnd);
|
2153 |
|
|
|
2154 |
|
|
-- Deal with silly False..False and True..True subtype case
|
2155 |
|
|
|
2156 |
|
|
Silly_Boolean_Array_Not_Test (N, Rtyp);
|
2157 |
|
|
|
2158 |
|
|
-- Now that the silliness is taken care of, get packed array type
|
2159 |
|
|
|
2160 |
|
|
Convert_To_PAT_Type (Opnd);
|
2161 |
|
|
PAT := Etype (Opnd);
|
2162 |
|
|
|
2163 |
|
|
-- For the case where the packed array type is a modular type,
|
2164 |
|
|
-- not A expands simply into:
|
2165 |
|
|
|
2166 |
|
|
-- rtyp!(PAT!(A) xor mask)
|
2167 |
|
|
|
2168 |
|
|
-- where PAT is the packed array type, and mask is a mask of all
|
2169 |
|
|
-- one bits of length equal to the size of this packed type and
|
2170 |
|
|
-- rtyp is the actual subtype of the operand
|
2171 |
|
|
|
2172 |
|
|
Lit := Make_Integer_Literal (Loc, 2 ** RM_Size (PAT) - 1);
|
2173 |
|
|
Set_Print_In_Hex (Lit);
|
2174 |
|
|
|
2175 |
|
|
if not Is_Array_Type (PAT) then
|
2176 |
|
|
Rewrite (N,
|
2177 |
|
|
Unchecked_Convert_To (Rtyp,
|
2178 |
|
|
Make_Op_Xor (Loc,
|
2179 |
|
|
Left_Opnd => Opnd,
|
2180 |
|
|
Right_Opnd => Lit)));
|
2181 |
|
|
|
2182 |
|
|
-- For the array case, we insert the actions
|
2183 |
|
|
|
2184 |
|
|
-- Result : Typ;
|
2185 |
|
|
|
2186 |
|
|
-- System.Bit_Ops.Bit_Not
|
2187 |
|
|
-- (Opnd'Address,
|
2188 |
|
|
-- Typ'Length * Typ'Component_Size;
|
2189 |
|
|
-- Result'Address);
|
2190 |
|
|
|
2191 |
|
|
-- where Opnd is the Packed_Bytes{1,2,4} operand and the second
|
2192 |
|
|
-- argument is the length of the operand in bits. Then we replace
|
2193 |
|
|
-- the expression by a reference to Result.
|
2194 |
|
|
|
2195 |
|
|
else
|
2196 |
|
|
declare
|
2197 |
|
|
Result_Ent : constant Entity_Id :=
|
2198 |
|
|
Make_Defining_Identifier (Loc,
|
2199 |
|
|
Chars => New_Internal_Name ('T'));
|
2200 |
|
|
|
2201 |
|
|
begin
|
2202 |
|
|
Insert_Actions (N, New_List (
|
2203 |
|
|
|
2204 |
|
|
Make_Object_Declaration (Loc,
|
2205 |
|
|
Defining_Identifier => Result_Ent,
|
2206 |
|
|
Object_Definition => New_Occurrence_Of (Rtyp, Loc)),
|
2207 |
|
|
|
2208 |
|
|
Make_Procedure_Call_Statement (Loc,
|
2209 |
|
|
Name => New_Occurrence_Of (RTE (RE_Bit_Not), Loc),
|
2210 |
|
|
Parameter_Associations => New_List (
|
2211 |
|
|
|
2212 |
|
|
Make_Byte_Aligned_Attribute_Reference (Loc,
|
2213 |
|
|
Prefix => Opnd,
|
2214 |
|
|
Attribute_Name => Name_Address),
|
2215 |
|
|
|
2216 |
|
|
Make_Op_Multiply (Loc,
|
2217 |
|
|
Left_Opnd =>
|
2218 |
|
|
Make_Attribute_Reference (Loc,
|
2219 |
|
|
Prefix =>
|
2220 |
|
|
New_Occurrence_Of
|
2221 |
|
|
(Etype (First_Index (Rtyp)), Loc),
|
2222 |
|
|
Attribute_Name => Name_Range_Length),
|
2223 |
|
|
|
2224 |
|
|
Right_Opnd =>
|
2225 |
|
|
Make_Integer_Literal (Loc, Component_Size (Rtyp))),
|
2226 |
|
|
|
2227 |
|
|
Make_Byte_Aligned_Attribute_Reference (Loc,
|
2228 |
|
|
Prefix => New_Occurrence_Of (Result_Ent, Loc),
|
2229 |
|
|
Attribute_Name => Name_Address)))));
|
2230 |
|
|
|
2231 |
|
|
Rewrite (N,
|
2232 |
|
|
New_Occurrence_Of (Result_Ent, Loc));
|
2233 |
|
|
end;
|
2234 |
|
|
end if;
|
2235 |
|
|
|
2236 |
|
|
Analyze_And_Resolve (N, Typ, Suppress => All_Checks);
|
2237 |
|
|
|
2238 |
|
|
end Expand_Packed_Not;
|
2239 |
|
|
|
2240 |
|
|
-------------------------------------
|
2241 |
|
|
-- Involves_Packed_Array_Reference --
|
2242 |
|
|
-------------------------------------
|
2243 |
|
|
|
2244 |
|
|
function Involves_Packed_Array_Reference (N : Node_Id) return Boolean is
|
2245 |
|
|
begin
|
2246 |
|
|
if Nkind (N) = N_Indexed_Component
|
2247 |
|
|
and then Is_Bit_Packed_Array (Etype (Prefix (N)))
|
2248 |
|
|
then
|
2249 |
|
|
return True;
|
2250 |
|
|
|
2251 |
|
|
elsif Nkind (N) = N_Selected_Component then
|
2252 |
|
|
return Involves_Packed_Array_Reference (Prefix (N));
|
2253 |
|
|
|
2254 |
|
|
else
|
2255 |
|
|
return False;
|
2256 |
|
|
end if;
|
2257 |
|
|
end Involves_Packed_Array_Reference;
|
2258 |
|
|
|
2259 |
|
|
--------------------------
|
2260 |
|
|
-- Known_Aligned_Enough --
|
2261 |
|
|
--------------------------
|
2262 |
|
|
|
2263 |
|
|
function Known_Aligned_Enough (Obj : Node_Id; Csiz : Nat) return Boolean is
|
2264 |
|
|
Typ : constant Entity_Id := Etype (Obj);
|
2265 |
|
|
|
2266 |
|
|
function In_Partially_Packed_Record (Comp : Entity_Id) return Boolean;
|
2267 |
|
|
-- If the component is in a record that contains previous packed
|
2268 |
|
|
-- components, consider it unaligned because the back-end might
|
2269 |
|
|
-- choose to pack the rest of the record. Lead to less efficient code,
|
2270 |
|
|
-- but safer vis-a-vis of back-end choices.
|
2271 |
|
|
|
2272 |
|
|
--------------------------------
|
2273 |
|
|
-- In_Partially_Packed_Record --
|
2274 |
|
|
--------------------------------
|
2275 |
|
|
|
2276 |
|
|
function In_Partially_Packed_Record (Comp : Entity_Id) return Boolean is
|
2277 |
|
|
Rec_Type : constant Entity_Id := Scope (Comp);
|
2278 |
|
|
Prev_Comp : Entity_Id;
|
2279 |
|
|
|
2280 |
|
|
begin
|
2281 |
|
|
Prev_Comp := First_Entity (Rec_Type);
|
2282 |
|
|
while Present (Prev_Comp) loop
|
2283 |
|
|
if Is_Packed (Etype (Prev_Comp)) then
|
2284 |
|
|
return True;
|
2285 |
|
|
|
2286 |
|
|
elsif Prev_Comp = Comp then
|
2287 |
|
|
return False;
|
2288 |
|
|
end if;
|
2289 |
|
|
|
2290 |
|
|
Next_Entity (Prev_Comp);
|
2291 |
|
|
end loop;
|
2292 |
|
|
|
2293 |
|
|
return False;
|
2294 |
|
|
end In_Partially_Packed_Record;
|
2295 |
|
|
|
2296 |
|
|
-- Start of processing for Known_Aligned_Enough
|
2297 |
|
|
|
2298 |
|
|
begin
|
2299 |
|
|
-- Odd bit sizes don't need alignment anyway
|
2300 |
|
|
|
2301 |
|
|
if Csiz mod 2 = 1 then
|
2302 |
|
|
return True;
|
2303 |
|
|
|
2304 |
|
|
-- If we have a specified alignment, see if it is sufficient, if not
|
2305 |
|
|
-- then we can't possibly be aligned enough in any case.
|
2306 |
|
|
|
2307 |
|
|
elsif Known_Alignment (Etype (Obj)) then
|
2308 |
|
|
-- Alignment required is 4 if size is a multiple of 4, and
|
2309 |
|
|
-- 2 otherwise (e.g. 12 bits requires 4, 10 bits requires 2)
|
2310 |
|
|
|
2311 |
|
|
if Alignment (Etype (Obj)) < 4 - (Csiz mod 4) then
|
2312 |
|
|
return False;
|
2313 |
|
|
end if;
|
2314 |
|
|
end if;
|
2315 |
|
|
|
2316 |
|
|
-- OK, alignment should be sufficient, if object is aligned
|
2317 |
|
|
|
2318 |
|
|
-- If object is strictly aligned, then it is definitely aligned
|
2319 |
|
|
|
2320 |
|
|
if Strict_Alignment (Typ) then
|
2321 |
|
|
return True;
|
2322 |
|
|
|
2323 |
|
|
-- Case of subscripted array reference
|
2324 |
|
|
|
2325 |
|
|
elsif Nkind (Obj) = N_Indexed_Component then
|
2326 |
|
|
|
2327 |
|
|
-- If we have a pointer to an array, then this is definitely
|
2328 |
|
|
-- aligned, because pointers always point to aligned versions.
|
2329 |
|
|
|
2330 |
|
|
if Is_Access_Type (Etype (Prefix (Obj))) then
|
2331 |
|
|
return True;
|
2332 |
|
|
|
2333 |
|
|
-- Otherwise, go look at the prefix
|
2334 |
|
|
|
2335 |
|
|
else
|
2336 |
|
|
return Known_Aligned_Enough (Prefix (Obj), Csiz);
|
2337 |
|
|
end if;
|
2338 |
|
|
|
2339 |
|
|
-- Case of record field
|
2340 |
|
|
|
2341 |
|
|
elsif Nkind (Obj) = N_Selected_Component then
|
2342 |
|
|
|
2343 |
|
|
-- What is significant here is whether the record type is packed
|
2344 |
|
|
|
2345 |
|
|
if Is_Record_Type (Etype (Prefix (Obj)))
|
2346 |
|
|
and then Is_Packed (Etype (Prefix (Obj)))
|
2347 |
|
|
then
|
2348 |
|
|
return False;
|
2349 |
|
|
|
2350 |
|
|
-- Or the component has a component clause which might cause
|
2351 |
|
|
-- the component to become unaligned (we can't tell if the
|
2352 |
|
|
-- backend is doing alignment computations).
|
2353 |
|
|
|
2354 |
|
|
elsif Present (Component_Clause (Entity (Selector_Name (Obj)))) then
|
2355 |
|
|
return False;
|
2356 |
|
|
|
2357 |
|
|
elsif In_Partially_Packed_Record (Entity (Selector_Name (Obj))) then
|
2358 |
|
|
return False;
|
2359 |
|
|
|
2360 |
|
|
-- In all other cases, go look at prefix
|
2361 |
|
|
|
2362 |
|
|
else
|
2363 |
|
|
return Known_Aligned_Enough (Prefix (Obj), Csiz);
|
2364 |
|
|
end if;
|
2365 |
|
|
|
2366 |
|
|
elsif Nkind (Obj) = N_Type_Conversion then
|
2367 |
|
|
return Known_Aligned_Enough (Expression (Obj), Csiz);
|
2368 |
|
|
|
2369 |
|
|
-- For a formal parameter, it is safer to assume that it is not
|
2370 |
|
|
-- aligned, because the formal may be unconstrained while the actual
|
2371 |
|
|
-- is constrained. In this situation, a small constrained packed
|
2372 |
|
|
-- array, represented in modular form, may be unaligned.
|
2373 |
|
|
|
2374 |
|
|
elsif Is_Entity_Name (Obj) then
|
2375 |
|
|
return not Is_Formal (Entity (Obj));
|
2376 |
|
|
else
|
2377 |
|
|
|
2378 |
|
|
-- If none of the above, must be aligned
|
2379 |
|
|
return True;
|
2380 |
|
|
end if;
|
2381 |
|
|
end Known_Aligned_Enough;
|
2382 |
|
|
|
2383 |
|
|
---------------------
|
2384 |
|
|
-- Make_Shift_Left --
|
2385 |
|
|
---------------------
|
2386 |
|
|
|
2387 |
|
|
function Make_Shift_Left (N : Node_Id; S : Node_Id) return Node_Id is
|
2388 |
|
|
Nod : Node_Id;
|
2389 |
|
|
|
2390 |
|
|
begin
|
2391 |
|
|
if Compile_Time_Known_Value (S) and then Expr_Value (S) = 0 then
|
2392 |
|
|
return N;
|
2393 |
|
|
else
|
2394 |
|
|
Nod :=
|
2395 |
|
|
Make_Op_Shift_Left (Sloc (N),
|
2396 |
|
|
Left_Opnd => N,
|
2397 |
|
|
Right_Opnd => S);
|
2398 |
|
|
Set_Shift_Count_OK (Nod, True);
|
2399 |
|
|
return Nod;
|
2400 |
|
|
end if;
|
2401 |
|
|
end Make_Shift_Left;
|
2402 |
|
|
|
2403 |
|
|
----------------------
|
2404 |
|
|
-- Make_Shift_Right --
|
2405 |
|
|
----------------------
|
2406 |
|
|
|
2407 |
|
|
function Make_Shift_Right (N : Node_Id; S : Node_Id) return Node_Id is
|
2408 |
|
|
Nod : Node_Id;
|
2409 |
|
|
|
2410 |
|
|
begin
|
2411 |
|
|
if Compile_Time_Known_Value (S) and then Expr_Value (S) = 0 then
|
2412 |
|
|
return N;
|
2413 |
|
|
else
|
2414 |
|
|
Nod :=
|
2415 |
|
|
Make_Op_Shift_Right (Sloc (N),
|
2416 |
|
|
Left_Opnd => N,
|
2417 |
|
|
Right_Opnd => S);
|
2418 |
|
|
Set_Shift_Count_OK (Nod, True);
|
2419 |
|
|
return Nod;
|
2420 |
|
|
end if;
|
2421 |
|
|
end Make_Shift_Right;
|
2422 |
|
|
|
2423 |
|
|
-----------------------------
|
2424 |
|
|
-- RJ_Unchecked_Convert_To --
|
2425 |
|
|
-----------------------------
|
2426 |
|
|
|
2427 |
|
|
function RJ_Unchecked_Convert_To
|
2428 |
|
|
(Typ : Entity_Id;
|
2429 |
|
|
Expr : Node_Id) return Node_Id
|
2430 |
|
|
is
|
2431 |
|
|
Source_Typ : constant Entity_Id := Etype (Expr);
|
2432 |
|
|
Target_Typ : constant Entity_Id := Typ;
|
2433 |
|
|
|
2434 |
|
|
Src : Node_Id := Expr;
|
2435 |
|
|
|
2436 |
|
|
Source_Siz : Nat;
|
2437 |
|
|
Target_Siz : Nat;
|
2438 |
|
|
|
2439 |
|
|
begin
|
2440 |
|
|
Source_Siz := UI_To_Int (RM_Size (Source_Typ));
|
2441 |
|
|
Target_Siz := UI_To_Int (RM_Size (Target_Typ));
|
2442 |
|
|
|
2443 |
|
|
-- First step, if the source type is not a discrete type, then we
|
2444 |
|
|
-- first convert to a modular type of the source length, since
|
2445 |
|
|
-- otherwise, on a big-endian machine, we get left-justification.
|
2446 |
|
|
-- We do it for little-endian machines as well, because there might
|
2447 |
|
|
-- be junk bits that are not cleared if the type is not numeric.
|
2448 |
|
|
|
2449 |
|
|
if Source_Siz /= Target_Siz
|
2450 |
|
|
and then not Is_Discrete_Type (Source_Typ)
|
2451 |
|
|
then
|
2452 |
|
|
Src := Unchecked_Convert_To (RTE (Bits_Id (Source_Siz)), Src);
|
2453 |
|
|
end if;
|
2454 |
|
|
|
2455 |
|
|
-- In the big endian case, if the lengths of the two types differ,
|
2456 |
|
|
-- then we must worry about possible left justification in the
|
2457 |
|
|
-- conversion, and avoiding that is what this is all about.
|
2458 |
|
|
|
2459 |
|
|
if Bytes_Big_Endian and then Source_Siz /= Target_Siz then
|
2460 |
|
|
|
2461 |
|
|
-- Next step. If the target is not a discrete type, then we first
|
2462 |
|
|
-- convert to a modular type of the target length, since
|
2463 |
|
|
-- otherwise, on a big-endian machine, we get left-justification.
|
2464 |
|
|
|
2465 |
|
|
if not Is_Discrete_Type (Target_Typ) then
|
2466 |
|
|
Src := Unchecked_Convert_To (RTE (Bits_Id (Target_Siz)), Src);
|
2467 |
|
|
end if;
|
2468 |
|
|
end if;
|
2469 |
|
|
|
2470 |
|
|
-- And now we can do the final conversion to the target type
|
2471 |
|
|
|
2472 |
|
|
return Unchecked_Convert_To (Target_Typ, Src);
|
2473 |
|
|
end RJ_Unchecked_Convert_To;
|
2474 |
|
|
|
2475 |
|
|
----------------------------------------------
|
2476 |
|
|
-- Setup_Enumeration_Packed_Array_Reference --
|
2477 |
|
|
----------------------------------------------
|
2478 |
|
|
|
2479 |
|
|
-- All we have to do here is to find the subscripts that correspond
|
2480 |
|
|
-- to the index positions that have non-standard enumeration types
|
2481 |
|
|
-- and insert a Pos attribute to get the proper subscript value.
|
2482 |
|
|
|
2483 |
|
|
-- Finally the prefix must be uncheck converted to the corresponding
|
2484 |
|
|
-- packed array type.
|
2485 |
|
|
|
2486 |
|
|
-- Note that the component type is unchanged, so we do not need to
|
2487 |
|
|
-- fiddle with the types (Gigi always automatically takes the packed
|
2488 |
|
|
-- array type if it is set, as it will be in this case).
|
2489 |
|
|
|
2490 |
|
|
procedure Setup_Enumeration_Packed_Array_Reference (N : Node_Id) is
|
2491 |
|
|
Pfx : constant Node_Id := Prefix (N);
|
2492 |
|
|
Typ : constant Entity_Id := Etype (N);
|
2493 |
|
|
Exprs : constant List_Id := Expressions (N);
|
2494 |
|
|
Expr : Node_Id;
|
2495 |
|
|
|
2496 |
|
|
begin
|
2497 |
|
|
-- If the array is unconstrained, then we replace the array
|
2498 |
|
|
-- reference with its actual subtype. This actual subtype will
|
2499 |
|
|
-- have a packed array type with appropriate bounds.
|
2500 |
|
|
|
2501 |
|
|
if not Is_Constrained (Packed_Array_Type (Etype (Pfx))) then
|
2502 |
|
|
Convert_To_Actual_Subtype (Pfx);
|
2503 |
|
|
end if;
|
2504 |
|
|
|
2505 |
|
|
Expr := First (Exprs);
|
2506 |
|
|
while Present (Expr) loop
|
2507 |
|
|
declare
|
2508 |
|
|
Loc : constant Source_Ptr := Sloc (Expr);
|
2509 |
|
|
Expr_Typ : constant Entity_Id := Etype (Expr);
|
2510 |
|
|
|
2511 |
|
|
begin
|
2512 |
|
|
if Is_Enumeration_Type (Expr_Typ)
|
2513 |
|
|
and then Has_Non_Standard_Rep (Expr_Typ)
|
2514 |
|
|
then
|
2515 |
|
|
Rewrite (Expr,
|
2516 |
|
|
Make_Attribute_Reference (Loc,
|
2517 |
|
|
Prefix => New_Occurrence_Of (Expr_Typ, Loc),
|
2518 |
|
|
Attribute_Name => Name_Pos,
|
2519 |
|
|
Expressions => New_List (Relocate_Node (Expr))));
|
2520 |
|
|
Analyze_And_Resolve (Expr, Standard_Natural);
|
2521 |
|
|
end if;
|
2522 |
|
|
end;
|
2523 |
|
|
|
2524 |
|
|
Next (Expr);
|
2525 |
|
|
end loop;
|
2526 |
|
|
|
2527 |
|
|
Rewrite (N,
|
2528 |
|
|
Make_Indexed_Component (Sloc (N),
|
2529 |
|
|
Prefix =>
|
2530 |
|
|
Unchecked_Convert_To (Packed_Array_Type (Etype (Pfx)), Pfx),
|
2531 |
|
|
Expressions => Exprs));
|
2532 |
|
|
|
2533 |
|
|
Analyze_And_Resolve (N, Typ);
|
2534 |
|
|
|
2535 |
|
|
end Setup_Enumeration_Packed_Array_Reference;
|
2536 |
|
|
|
2537 |
|
|
-----------------------------------------
|
2538 |
|
|
-- Setup_Inline_Packed_Array_Reference --
|
2539 |
|
|
-----------------------------------------
|
2540 |
|
|
|
2541 |
|
|
procedure Setup_Inline_Packed_Array_Reference
|
2542 |
|
|
(N : Node_Id;
|
2543 |
|
|
Atyp : Entity_Id;
|
2544 |
|
|
Obj : in out Node_Id;
|
2545 |
|
|
Cmask : out Uint;
|
2546 |
|
|
Shift : out Node_Id)
|
2547 |
|
|
is
|
2548 |
|
|
Loc : constant Source_Ptr := Sloc (N);
|
2549 |
|
|
PAT : Entity_Id;
|
2550 |
|
|
Otyp : Entity_Id;
|
2551 |
|
|
Csiz : Uint;
|
2552 |
|
|
Osiz : Uint;
|
2553 |
|
|
|
2554 |
|
|
begin
|
2555 |
|
|
Csiz := Component_Size (Atyp);
|
2556 |
|
|
|
2557 |
|
|
Convert_To_PAT_Type (Obj);
|
2558 |
|
|
PAT := Etype (Obj);
|
2559 |
|
|
|
2560 |
|
|
Cmask := 2 ** Csiz - 1;
|
2561 |
|
|
|
2562 |
|
|
if Is_Array_Type (PAT) then
|
2563 |
|
|
Otyp := Component_Type (PAT);
|
2564 |
|
|
Osiz := Component_Size (PAT);
|
2565 |
|
|
|
2566 |
|
|
else
|
2567 |
|
|
Otyp := PAT;
|
2568 |
|
|
|
2569 |
|
|
-- In the case where the PAT is a modular type, we want the actual
|
2570 |
|
|
-- size in bits of the modular value we use. This is neither the
|
2571 |
|
|
-- Object_Size nor the Value_Size, either of which may have been
|
2572 |
|
|
-- reset to strange values, but rather the minimum size. Note that
|
2573 |
|
|
-- since this is a modular type with full range, the issue of
|
2574 |
|
|
-- biased representation does not arise.
|
2575 |
|
|
|
2576 |
|
|
Osiz := UI_From_Int (Minimum_Size (Otyp));
|
2577 |
|
|
end if;
|
2578 |
|
|
|
2579 |
|
|
Compute_Linear_Subscript (Atyp, N, Shift);
|
2580 |
|
|
|
2581 |
|
|
-- If the component size is not 1, then the subscript must be
|
2582 |
|
|
-- multiplied by the component size to get the shift count.
|
2583 |
|
|
|
2584 |
|
|
if Csiz /= 1 then
|
2585 |
|
|
Shift :=
|
2586 |
|
|
Make_Op_Multiply (Loc,
|
2587 |
|
|
Left_Opnd => Make_Integer_Literal (Loc, Csiz),
|
2588 |
|
|
Right_Opnd => Shift);
|
2589 |
|
|
end if;
|
2590 |
|
|
|
2591 |
|
|
-- If we have the array case, then this shift count must be broken
|
2592 |
|
|
-- down into a byte subscript, and a shift within the byte.
|
2593 |
|
|
|
2594 |
|
|
if Is_Array_Type (PAT) then
|
2595 |
|
|
|
2596 |
|
|
declare
|
2597 |
|
|
New_Shift : Node_Id;
|
2598 |
|
|
|
2599 |
|
|
begin
|
2600 |
|
|
-- We must analyze shift, since we will duplicate it
|
2601 |
|
|
|
2602 |
|
|
Set_Parent (Shift, N);
|
2603 |
|
|
Analyze_And_Resolve
|
2604 |
|
|
(Shift, Standard_Integer, Suppress => All_Checks);
|
2605 |
|
|
|
2606 |
|
|
-- The shift count within the word is
|
2607 |
|
|
-- shift mod Osiz
|
2608 |
|
|
|
2609 |
|
|
New_Shift :=
|
2610 |
|
|
Make_Op_Mod (Loc,
|
2611 |
|
|
Left_Opnd => Duplicate_Subexpr (Shift),
|
2612 |
|
|
Right_Opnd => Make_Integer_Literal (Loc, Osiz));
|
2613 |
|
|
|
2614 |
|
|
-- The subscript to be used on the PAT array is
|
2615 |
|
|
-- shift / Osiz
|
2616 |
|
|
|
2617 |
|
|
Obj :=
|
2618 |
|
|
Make_Indexed_Component (Loc,
|
2619 |
|
|
Prefix => Obj,
|
2620 |
|
|
Expressions => New_List (
|
2621 |
|
|
Make_Op_Divide (Loc,
|
2622 |
|
|
Left_Opnd => Duplicate_Subexpr (Shift),
|
2623 |
|
|
Right_Opnd => Make_Integer_Literal (Loc, Osiz))));
|
2624 |
|
|
|
2625 |
|
|
Shift := New_Shift;
|
2626 |
|
|
end;
|
2627 |
|
|
|
2628 |
|
|
-- For the modular integer case, the object to be manipulated is
|
2629 |
|
|
-- the entire array, so Obj is unchanged. Note that we will reset
|
2630 |
|
|
-- its type to PAT before returning to the caller.
|
2631 |
|
|
|
2632 |
|
|
else
|
2633 |
|
|
null;
|
2634 |
|
|
end if;
|
2635 |
|
|
|
2636 |
|
|
-- The one remaining step is to modify the shift count for the
|
2637 |
|
|
-- big-endian case. Consider the following example in a byte:
|
2638 |
|
|
|
2639 |
|
|
-- xxxxxxxx bits of byte
|
2640 |
|
|
-- vvvvvvvv bits of value
|
2641 |
|
|
-- 33221100 little-endian numbering
|
2642 |
|
|
-- 00112233 big-endian numbering
|
2643 |
|
|
|
2644 |
|
|
-- Here we have the case of 2-bit fields
|
2645 |
|
|
|
2646 |
|
|
-- For the little-endian case, we already have the proper shift
|
2647 |
|
|
-- count set, e.g. for element 2, the shift count is 2*2 = 4.
|
2648 |
|
|
|
2649 |
|
|
-- For the big endian case, we have to adjust the shift count,
|
2650 |
|
|
-- computing it as (N - F) - shift, where N is the number of bits
|
2651 |
|
|
-- in an element of the array used to implement the packed array,
|
2652 |
|
|
-- F is the number of bits in a source level array element, and
|
2653 |
|
|
-- shift is the count so far computed.
|
2654 |
|
|
|
2655 |
|
|
if Bytes_Big_Endian then
|
2656 |
|
|
Shift :=
|
2657 |
|
|
Make_Op_Subtract (Loc,
|
2658 |
|
|
Left_Opnd => Make_Integer_Literal (Loc, Osiz - Csiz),
|
2659 |
|
|
Right_Opnd => Shift);
|
2660 |
|
|
end if;
|
2661 |
|
|
|
2662 |
|
|
Set_Parent (Shift, N);
|
2663 |
|
|
Set_Parent (Obj, N);
|
2664 |
|
|
Analyze_And_Resolve (Obj, Otyp, Suppress => All_Checks);
|
2665 |
|
|
Analyze_And_Resolve (Shift, Standard_Integer, Suppress => All_Checks);
|
2666 |
|
|
|
2667 |
|
|
-- Make sure final type of object is the appropriate packed type
|
2668 |
|
|
|
2669 |
|
|
Set_Etype (Obj, Otyp);
|
2670 |
|
|
|
2671 |
|
|
end Setup_Inline_Packed_Array_Reference;
|
2672 |
|
|
|
2673 |
|
|
end Exp_Pakd;
|