1 /*
2 Copyright (C) 2011-2015, Parrot Foundation.
3
4 =head1 NAME
5
6 src/packfile/segments.c - Segment Handling Routines
7
8 =head1 DESCRIPTION
9
10 Functions in this file represent behaviors for different PackFile segments.
11
12 =cut
13
14 */
15
16 /* HEADERIZER HFILE: include/parrot/packfile.h */
17
18 #include "parrot/parrot.h"
19 #include "pf_private.h"
20 #include "pmc/pmc_parrotlibrary.h"
21 #include "segments.str"
22
23 /* HEADERIZER BEGIN: static */
24 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
25
26 static void annotations_destroy(PARROT_INTERP,
27 ARGMOD(PackFile_Segment *seg))
28 __attribute__nonnull__(1)
29 __attribute__nonnull__(2)
30 FUNC_MODIFIES(*seg);
31
32 static void annotations_dump(PARROT_INTERP,
33 ARGIN(const PackFile_Segment *seg))
34 __attribute__nonnull__(1)
35 __attribute__nonnull__(2);
36
37 PARROT_CANNOT_RETURN_NULL
38 static PackFile_Segment * annotations_new(PARROT_INTERP)
39 __attribute__nonnull__(1);
40
41 PARROT_WARN_UNUSED_RESULT
42 PARROT_CANNOT_RETURN_NULL
43 static opcode_t * annotations_pack(PARROT_INTERP,
44 ARGIN(PackFile_Segment *seg),
45 ARGOUT(opcode_t *cursor))
46 __attribute__nonnull__(2)
47 __attribute__nonnull__(3)
48 FUNC_MODIFIES(*cursor);
49
50 PARROT_WARN_UNUSED_RESULT
51 PARROT_PURE_FUNCTION
52 static size_t annotations_packed_size(PARROT_INTERP,
53 ARGMOD(PackFile_Segment *seg))
54 __attribute__nonnull__(2)
55 FUNC_MODIFIES(*seg);
56
57 PARROT_CANNOT_RETURN_NULL
58 static const opcode_t * annotations_unpack(PARROT_INTERP,
59 ARGMOD(PackFile_Segment *seg),
60 ARGIN(const opcode_t *cursor))
61 __attribute__nonnull__(1)
62 __attribute__nonnull__(2)
63 __attribute__nonnull__(3)
64 FUNC_MODIFIES(*seg);
65
66 static void byte_code_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
67 __attribute__nonnull__(1)
68 __attribute__nonnull__(2)
69 FUNC_MODIFIES(*self);
70
71 PARROT_WARN_UNUSED_RESULT
72 PARROT_CANNOT_RETURN_NULL
73 static PackFile_Segment * byte_code_new(PARROT_INTERP)
74 __attribute__nonnull__(1);
75
76 PARROT_WARN_UNUSED_RESULT
77 PARROT_CANNOT_RETURN_NULL
78 static opcode_t * byte_code_pack(PARROT_INTERP,
79 ARGMOD(PackFile_Segment *self),
80 ARGOUT(opcode_t *cursor))
81 __attribute__nonnull__(2)
82 __attribute__nonnull__(3)
83 FUNC_MODIFIES(*self)
84 FUNC_MODIFIES(*cursor);
85
86 PARROT_WARN_UNUSED_RESULT
87 PARROT_PURE_FUNCTION
88 static size_t byte_code_packed_size(PARROT_INTERP,
89 ARGMOD(PackFile_Segment *self))
90 __attribute__nonnull__(2)
91 FUNC_MODIFIES(*self);
92
93 PARROT_WARN_UNUSED_RESULT
94 PARROT_CANNOT_RETURN_NULL
95 static const opcode_t * byte_code_unpack(PARROT_INTERP,
96 ARGMOD(PackFile_Segment *self),
97 ARGIN(const opcode_t *cursor))
98 __attribute__nonnull__(1)
99 __attribute__nonnull__(2)
100 __attribute__nonnull__(3)
101 FUNC_MODIFIES(*self);
102
103 static void const_clear(PARROT_INTERP, ARGMOD(PackFile_ConstTable *self))
104 __attribute__nonnull__(1)
105 __attribute__nonnull__(2)
106 FUNC_MODIFIES(*self);
107
108 static void const_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
109 __attribute__nonnull__(1)
110 __attribute__nonnull__(2)
111 FUNC_MODIFIES(*self);
112
113 PARROT_MALLOC
114 PARROT_CANNOT_RETURN_NULL
115 static PackFile_Segment * const_new(PARROT_INTERP)
116 __attribute__nonnull__(1);
117
118 PARROT_WARN_UNUSED_RESULT
119 PARROT_CAN_RETURN_NULL
120 static const opcode_t * const_unpack(PARROT_INTERP,
121 ARGMOD(PackFile_Segment *seg),
122 ARGIN(const opcode_t *cursor))
123 __attribute__nonnull__(1)
124 __attribute__nonnull__(2)
125 __attribute__nonnull__(3)
126 FUNC_MODIFIES(*seg);
127
128 PARROT_WARN_UNUSED_RESULT
129 PARROT_CANNOT_RETURN_NULL
130 static PMC * const_unpack_pmc(PARROT_INTERP,
131 ARGIN(PackFile_ConstTable *constt),
132 ARGIN(const opcode_t **cursor))
133 __attribute__nonnull__(1)
134 __attribute__nonnull__(2)
135 __attribute__nonnull__(3);
136
137 static void default_destroy(PARROT_INTERP,
138 ARGFREE_NOTNULL(PackFile_Segment *self))
139 __attribute__nonnull__(1)
140 __attribute__nonnull__(2);
141
142 static void default_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
143 __attribute__nonnull__(1)
144 __attribute__nonnull__(2);
145
146 PARROT_WARN_UNUSED_RESULT
147 PARROT_CANNOT_RETURN_NULL
148 static opcode_t * default_pack(
149 ARGIN(const PackFile_Segment *self),
150 ARGOUT(opcode_t *dest))
151 __attribute__nonnull__(1)
152 __attribute__nonnull__(2)
153 FUNC_MODIFIES(*dest);
154
155 PARROT_PURE_FUNCTION
156 PARROT_WARN_UNUSED_RESULT
157 static size_t default_packed_size(ARGIN(const PackFile_Segment *self))
158 __attribute__nonnull__(1);
159
160 PARROT_WARN_UNUSED_RESULT
161 PARROT_CAN_RETURN_NULL
162 static const opcode_t * default_unpack(PARROT_INTERP,
163 ARGMOD(PackFile_Segment *self),
164 ARGIN(const opcode_t *cursor))
165 __attribute__nonnull__(1)
166 __attribute__nonnull__(2)
167 __attribute__nonnull__(3)
168 FUNC_MODIFIES(*self);
169
170 static void directory_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
171 __attribute__nonnull__(1)
172 __attribute__nonnull__(2)
173 FUNC_MODIFIES(*self);
174
175 static void directory_dump(PARROT_INTERP,
176 ARGIN(const PackFile_Segment *self))
177 __attribute__nonnull__(1)
178 __attribute__nonnull__(2);
179
180 PARROT_WARN_UNUSED_RESULT
181 PARROT_CANNOT_RETURN_NULL
182 static PackFile_Segment * directory_new(PARROT_INTERP)
183 __attribute__nonnull__(1);
184
185 PARROT_WARN_UNUSED_RESULT
186 PARROT_CANNOT_RETURN_NULL
187 static opcode_t * directory_pack(PARROT_INTERP,
188 ARGMOD(PackFile_Segment *self),
189 ARGOUT(opcode_t *cursor))
190 __attribute__nonnull__(1)
191 __attribute__nonnull__(2)
192 __attribute__nonnull__(3)
193 FUNC_MODIFIES(*self)
194 FUNC_MODIFIES(*cursor);
195
196 PARROT_WARN_UNUSED_RESULT
197 static size_t directory_packed_size(PARROT_INTERP,
198 ARGMOD(PackFile_Segment *self))
199 __attribute__nonnull__(1)
200 __attribute__nonnull__(2)
201 FUNC_MODIFIES(*self);
202
203 PARROT_CAN_RETURN_NULL
204 PARROT_WARN_UNUSED_RESULT
205 static const opcode_t * directory_unpack(PARROT_INTERP,
206 ARGMOD(PackFile_Segment *segp),
207 ARGIN(const opcode_t *cursor))
208 __attribute__nonnull__(1)
209 __attribute__nonnull__(2)
210 __attribute__nonnull__(3)
211 FUNC_MODIFIES(*segp);
212
213 static void make_code_pointers(ARGMOD(PackFile_Segment *seg))
214 __attribute__nonnull__(1)
215 FUNC_MODIFIES(*seg);
216
217 static void pf_debug_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
218 __attribute__nonnull__(1)
219 __attribute__nonnull__(2)
220 FUNC_MODIFIES(*self);
221
222 static void pf_debug_dump(PARROT_INTERP,
223 ARGIN(const PackFile_Segment *self))
224 __attribute__nonnull__(1)
225 __attribute__nonnull__(2);
226
227 PARROT_WARN_UNUSED_RESULT
228 PARROT_CANNOT_RETURN_NULL
229 static PackFile_Segment * pf_debug_new(PARROT_INTERP)
230 __attribute__nonnull__(1);
231
232 PARROT_WARN_UNUSED_RESULT
233 PARROT_CANNOT_RETURN_NULL
234 static opcode_t * pf_debug_pack(PARROT_INTERP,
235 ARGMOD(PackFile_Segment *self),
236 ARGOUT(opcode_t *cursor))
237 __attribute__nonnull__(1)
238 __attribute__nonnull__(2)
239 __attribute__nonnull__(3)
240 FUNC_MODIFIES(*self)
241 FUNC_MODIFIES(*cursor);
242
243 static size_t pf_debug_packed_size(PARROT_INTERP,
244 ARGMOD(PackFile_Segment *self))
245 __attribute__nonnull__(2)
246 FUNC_MODIFIES(*self);
247
248 PARROT_WARN_UNUSED_RESULT
249 PARROT_CANNOT_RETURN_NULL
250 static const opcode_t * pf_debug_unpack(PARROT_INTERP,
251 ARGMOD(PackFile_Segment *self),
252 ARGIN(const opcode_t *cursor))
253 __attribute__nonnull__(1)
254 __attribute__nonnull__(2)
255 __attribute__nonnull__(3)
256 FUNC_MODIFIES(*self);
257
258 static void pf_register_funcs(
259 ARGMOD(PackFile *pf),
260 UINTVAL type,
261 const PackFile_funcs funcs)
262 __attribute__nonnull__(1)
263 FUNC_MODIFIES(*pf);
264
265 static void segment_init(
266 ARGOUT(PackFile_Segment *self),
267 ARGIN(PackFile *pf),
268 ARGIN(STRING *name))
269 __attribute__nonnull__(1)
270 __attribute__nonnull__(2)
271 __attribute__nonnull__(3)
272 FUNC_MODIFIES(*self);
273
274 PARROT_WARN_UNUSED_RESULT
275 PARROT_CANNOT_RETURN_NULL
276 static PackFile_Segment * segment_new(PARROT_INTERP)
277 __attribute__nonnull__(1);
278
279 static void sort_segs(ARGMOD(PackFile_Directory *dir))
280 __attribute__nonnull__(1)
281 FUNC_MODIFIES(*dir);
282
283 #define ASSERT_ARGS_annotations_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
284 PARROT_ASSERT_ARG(interp) \
285 , PARROT_ASSERT_ARG(seg))
286 #define ASSERT_ARGS_annotations_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
287 PARROT_ASSERT_ARG(interp) \
288 , PARROT_ASSERT_ARG(seg))
289 #define ASSERT_ARGS_annotations_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
290 PARROT_ASSERT_ARG(interp))
291 #define ASSERT_ARGS_annotations_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
292 PARROT_ASSERT_ARG(seg) \
293 , PARROT_ASSERT_ARG(cursor))
294 #define ASSERT_ARGS_annotations_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
295 PARROT_ASSERT_ARG(seg))
296 #define ASSERT_ARGS_annotations_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
297 PARROT_ASSERT_ARG(interp) \
298 , PARROT_ASSERT_ARG(seg) \
299 , PARROT_ASSERT_ARG(cursor))
300 #define ASSERT_ARGS_byte_code_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
301 PARROT_ASSERT_ARG(interp) \
302 , PARROT_ASSERT_ARG(self))
303 #define ASSERT_ARGS_byte_code_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
304 PARROT_ASSERT_ARG(interp))
305 #define ASSERT_ARGS_byte_code_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
306 PARROT_ASSERT_ARG(self) \
307 , PARROT_ASSERT_ARG(cursor))
308 #define ASSERT_ARGS_byte_code_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
309 PARROT_ASSERT_ARG(self))
310 #define ASSERT_ARGS_byte_code_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
311 PARROT_ASSERT_ARG(interp) \
312 , PARROT_ASSERT_ARG(self) \
313 , PARROT_ASSERT_ARG(cursor))
314 #define ASSERT_ARGS_const_clear __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
315 PARROT_ASSERT_ARG(interp) \
316 , PARROT_ASSERT_ARG(self))
317 #define ASSERT_ARGS_const_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
318 PARROT_ASSERT_ARG(interp) \
319 , PARROT_ASSERT_ARG(self))
320 #define ASSERT_ARGS_const_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
321 PARROT_ASSERT_ARG(interp))
322 #define ASSERT_ARGS_const_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
323 PARROT_ASSERT_ARG(interp) \
324 , PARROT_ASSERT_ARG(seg) \
325 , PARROT_ASSERT_ARG(cursor))
326 #define ASSERT_ARGS_const_unpack_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
327 PARROT_ASSERT_ARG(interp) \
328 , PARROT_ASSERT_ARG(constt) \
329 , PARROT_ASSERT_ARG(cursor))
330 #define ASSERT_ARGS_default_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
331 PARROT_ASSERT_ARG(interp) \
332 , PARROT_ASSERT_ARG(self))
333 #define ASSERT_ARGS_default_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
334 PARROT_ASSERT_ARG(interp) \
335 , PARROT_ASSERT_ARG(self))
336 #define ASSERT_ARGS_default_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
337 PARROT_ASSERT_ARG(self) \
338 , PARROT_ASSERT_ARG(dest))
339 #define ASSERT_ARGS_default_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
340 PARROT_ASSERT_ARG(self))
341 #define ASSERT_ARGS_default_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
342 PARROT_ASSERT_ARG(interp) \
343 , PARROT_ASSERT_ARG(self) \
344 , PARROT_ASSERT_ARG(cursor))
345 #define ASSERT_ARGS_directory_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
346 PARROT_ASSERT_ARG(interp) \
347 , PARROT_ASSERT_ARG(self))
348 #define ASSERT_ARGS_directory_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
349 PARROT_ASSERT_ARG(interp) \
350 , PARROT_ASSERT_ARG(self))
351 #define ASSERT_ARGS_directory_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
352 PARROT_ASSERT_ARG(interp))
353 #define ASSERT_ARGS_directory_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
354 PARROT_ASSERT_ARG(interp) \
355 , PARROT_ASSERT_ARG(self) \
356 , PARROT_ASSERT_ARG(cursor))
357 #define ASSERT_ARGS_directory_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
358 PARROT_ASSERT_ARG(interp) \
359 , PARROT_ASSERT_ARG(self))
360 #define ASSERT_ARGS_directory_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
361 PARROT_ASSERT_ARG(interp) \
362 , PARROT_ASSERT_ARG(segp) \
363 , PARROT_ASSERT_ARG(cursor))
364 #define ASSERT_ARGS_make_code_pointers __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
365 PARROT_ASSERT_ARG(seg))
366 #define ASSERT_ARGS_pf_debug_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
367 PARROT_ASSERT_ARG(interp) \
368 , PARROT_ASSERT_ARG(self))
369 #define ASSERT_ARGS_pf_debug_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
370 PARROT_ASSERT_ARG(interp) \
371 , PARROT_ASSERT_ARG(self))
372 #define ASSERT_ARGS_pf_debug_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
373 PARROT_ASSERT_ARG(interp))
374 #define ASSERT_ARGS_pf_debug_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
375 PARROT_ASSERT_ARG(interp) \
376 , PARROT_ASSERT_ARG(self) \
377 , PARROT_ASSERT_ARG(cursor))
378 #define ASSERT_ARGS_pf_debug_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
379 PARROT_ASSERT_ARG(self))
380 #define ASSERT_ARGS_pf_debug_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
381 PARROT_ASSERT_ARG(interp) \
382 , PARROT_ASSERT_ARG(self) \
383 , PARROT_ASSERT_ARG(cursor))
384 #define ASSERT_ARGS_pf_register_funcs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
385 PARROT_ASSERT_ARG(pf))
386 #define ASSERT_ARGS_segment_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
387 PARROT_ASSERT_ARG(self) \
388 , PARROT_ASSERT_ARG(pf) \
389 , PARROT_ASSERT_ARG(name))
390 #define ASSERT_ARGS_segment_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
391 PARROT_ASSERT_ARG(interp))
392 #define ASSERT_ARGS_sort_segs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
393 PARROT_ASSERT_ARG(dir))
394 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
395 /* HEADERIZER END: static */
396
397
398 /*
399
400 =head2 PackFile Segment Functions
401
402 =over 4
403
404 =item C<INTVAL Parrot_pf_map_segments(PARROT_INTERP, const PackFile_Directory
405 *dir, PackFile_map_segments_func_t callback, void *user_data)>
406
407 Calls the callback function C<callback> for each segment in the directory
408 C<dir> called. The pointer C<user_data> is included in each call.
409
410 If a callback returns non-zero, segment processing stops, returning this value.
411
412 =cut
413
414 */
415
416 PARROT_EXPORT
417 INTVAL
Parrot_pf_map_segments(PARROT_INTERP,ARGIN (const PackFile_Directory * dir),PackFile_map_segments_func_t callback,ARGIN_NULLOK (void * user_data))418 Parrot_pf_map_segments(PARROT_INTERP, ARGIN(const PackFile_Directory *dir),
419 PackFile_map_segments_func_t callback,
420 ARGIN_NULLOK(void *user_data))
421 {
422 ASSERT_ARGS(Parrot_pf_map_segments)
423 size_t i;
424
425 for (i = 0; i < dir->num_segments; ++i) {
426 const INTVAL ret = callback(interp, dir->segments[i], user_data);
427 if (ret)
428 return ret;
429 }
430
431 return 0;
432 }
433
434 /*
435
436 =item C<INTVAL PackFile_map_segments(PARROT_INTERP, const PackFile_Directory
437 *dir, PackFile_map_segments_func_t callback, void *user_data)>
438
439 Deprecated: This function should not be exposed as a part of the public API.
440 See TT #2140 for details.
441
442 =cut
443
444 */
445
446 PARROT_EXPORT
447 PARROT_DEPRECATED
448 INTVAL
PackFile_map_segments(PARROT_INTERP,ARGIN (const PackFile_Directory * dir),PackFile_map_segments_func_t callback,ARGIN_NULLOK (void * user_data))449 PackFile_map_segments(PARROT_INTERP, ARGIN(const PackFile_Directory *dir),
450 PackFile_map_segments_func_t callback,
451 ARGIN_NULLOK(void *user_data))
452 {
453 ASSERT_ARGS(PackFile_map_segments)
454 return Parrot_pf_map_segments(interp, dir, callback, user_data);
455 }
456
457 /*
458
459 =item C<void Parrot_pf_add_segment(PARROT_INTERP, PackFile_Directory *dir,
460 PackFile_Segment *seg)>
461
462 Adds the Segment C<seg> to the directory C<dir>. The PackFile becomes the
463 owner of the segment; it gets destroyed when the PackFile does.
464
465 =cut
466
467 */
468
469 PARROT_EXPORT
470 void
Parrot_pf_add_segment(PARROT_INTERP,ARGMOD (PackFile_Directory * dir),ARGMOD (PackFile_Segment * seg))471 Parrot_pf_add_segment(PARROT_INTERP, ARGMOD(PackFile_Directory *dir),
472 ARGMOD(PackFile_Segment *seg))
473 {
474 ASSERT_ARGS(Parrot_pf_add_segment)
475 dir->segments = mem_gc_realloc_n_typed_zeroed(interp, dir->segments,
476 dir->num_segments + 1, dir->num_segments, PackFile_Segment *);
477 dir->segments[dir->num_segments] = seg;
478 ++dir->num_segments;
479 seg->dir = dir;
480
481 return;
482 }
483
484 /*
485
486 =item C<void PackFile_add_segment(PARROT_INTERP, PackFile_Directory *dir,
487 PackFile_Segment *seg)>
488
489 Deprecated: Use C<Parrot_pf_add_segment> instead. TT #2140, GH #1170
490
491 =cut
492
493 */
494
495 PARROT_EXPORT
496 PARROT_DEPRECATED
497 void
PackFile_add_segment(PARROT_INTERP,ARGMOD (PackFile_Directory * dir),ARGMOD (PackFile_Segment * seg))498 PackFile_add_segment(PARROT_INTERP, ARGMOD(PackFile_Directory *dir),
499 ARGMOD(PackFile_Segment *seg))
500 {
501 ASSERT_ARGS(PackFile_add_segment)
502 Parrot_pf_add_segment(interp, dir, seg);
503 }
504
505 /*
506
507 =item C<PackFile_Segment * Parrot_pf_find_segment(PARROT_INTERP,
508 PackFile_Directory *dir, const STRING *name, int sub_dir)>
509
510 Finds the segment with the name C<name> in the C<PackFile_Directory> if
511 C<sub_dir> is true, searches directories recursively. The returned segment is
512 still owned by the C<PackFile>.
513
514 =cut
515
516 */
517
518 PARROT_EXPORT
519 PARROT_WARN_UNUSED_RESULT
520 PARROT_CAN_RETURN_NULL
521 PackFile_Segment *
Parrot_pf_find_segment(PARROT_INTERP,ARGIN_NULLOK (PackFile_Directory * dir),ARGIN (const STRING * name),int sub_dir)522 Parrot_pf_find_segment(PARROT_INTERP, ARGIN_NULLOK(PackFile_Directory *dir),
523 ARGIN(const STRING *name), int sub_dir)
524 {
525 ASSERT_ARGS(Parrot_pf_find_segment)
526 size_t i;
527
528 if (!dir)
529 return NULL;
530
531 for (i = 0; i < dir->num_segments; ++i) {
532 PackFile_Segment *seg = dir->segments[i];
533
534 if (!seg)
535 continue;
536
537 if (STRING_equal(interp, seg->name, name))
538 return seg;
539
540 if (sub_dir && seg->type == PF_DIR_SEG) {
541 seg = Parrot_pf_find_segment(interp,
542 (PackFile_Directory *)seg, name, sub_dir);
543
544 if (seg)
545 return seg;
546 }
547 }
548
549 return NULL;
550 }
551
552 /*
553
554 =item C<PackFile_Segment * PackFile_find_segment(PARROT_INTERP,
555 PackFile_Directory *dir, const STRING *name, int sub_dir)>
556
557 Finds the segment with the name C<name> in the C<PackFile_Directory> if
558 C<sub_dir> is true, searches directories recursively. The returned segment is
559 still owned by the C<PackFile>.
560
561 Deprecated: Use C<Parrot_pf_find_segment> instead.
562
563 =cut
564
565 */
566
567 PARROT_EXPORT
568 PARROT_WARN_UNUSED_RESULT
569 PARROT_CAN_RETURN_NULL
570 PARROT_DEPRECATED
571 PackFile_Segment *
PackFile_find_segment(PARROT_INTERP,ARGIN_NULLOK (PackFile_Directory * dir),ARGIN (const STRING * name),int sub_dir)572 PackFile_find_segment(PARROT_INTERP, ARGIN_NULLOK(PackFile_Directory *dir),
573 ARGIN(const STRING *name), int sub_dir)
574 {
575 ASSERT_ARGS(PackFile_find_segment)
576 return Parrot_pf_find_segment(interp, dir, name, sub_dir);
577 }
578
579 /*
580
581 =back
582
583 =head2 Private PackFile Segment Methods
584
585 =over 4
586
587 =item C<static void const_clear(PARROT_INTERP, PackFile_ConstTable *self)>
588
589 Clear the C<PackFile_ConstTable> C<self>.
590
591 =cut
592
593 */
594
595 static void
const_clear(PARROT_INTERP,ARGMOD (PackFile_ConstTable * self))596 const_clear(PARROT_INTERP, ARGMOD(PackFile_ConstTable *self))
597 {
598 ASSERT_ARGS(const_clear)
599
600 if (self->num.constants) {
601 mem_gc_free(interp, self->num.constants);
602 self->num.constants = NULL;
603 }
604
605 if (self->str.constants) {
606 mem_gc_free(interp, self->str.constants);
607 self->str.constants = NULL;
608 }
609
610 if (self->pmc.constants) {
611 mem_gc_free(interp, self->pmc.constants);
612 self->pmc.constants = NULL;
613 }
614
615 if (self->string_hash) {
616 Parrot_hash_destroy(interp, self->string_hash);
617 self->string_hash = NULL;
618 }
619
620 if (self->tag_map) {
621 mem_gc_free(interp, self->tag_map);
622 self->ntags = 0;
623 }
624
625 return;
626 }
627
628
629 /*
630
631 =item C<static const opcode_t * const_unpack(PARROT_INTERP, PackFile_Segment
632 *seg, const opcode_t *cursor)>
633
634 Unpacks a PackFile ConstTable from a block of memory. The format is:
635
636 opcode_t const_count
637 * constants
638
639 Returns cursor if everything is OK, else zero (0).
640
641 =cut
642
643 */
644
645 PARROT_WARN_UNUSED_RESULT
646 PARROT_CAN_RETURN_NULL
647 static const opcode_t *
const_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * seg),ARGIN (const opcode_t * cursor))648 const_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *seg),
649 ARGIN(const opcode_t *cursor))
650 {
651 ASSERT_ARGS(const_unpack)
652 STRING * const sub_str = CONST_STRING(interp, "Sub");
653 PackFile_ConstTable * const self = (PackFile_ConstTable *)seg;
654 PackFile * const pf = seg->pf;
655 opcode_t i;
656
657 const_clear(interp, self);
658
659 self->num.const_count = PF_fetch_opcode(pf, &cursor);
660 self->str.const_count = PF_fetch_opcode(pf, &cursor);
661 self->pmc.const_count = PF_fetch_opcode(pf, &cursor);
662
663 if (self->num.const_count) {
664 self->num.constants = mem_gc_allocate_n_zeroed_typed(interp,
665 self->num.const_count, FLOATVAL);
666 if (!self->num.constants)
667 goto err;
668 }
669
670 if (self->str.const_count) {
671 self->str.constants = mem_gc_allocate_n_zeroed_typed(interp,
672 self->str.const_count, STRING *);
673 if (!self->str.constants)
674 goto err;
675 }
676
677 if (self->pmc.const_count) {
678 self->pmc.constants = mem_gc_allocate_n_zeroed_typed(interp,
679 self->pmc.const_count, PMC *);
680 if (!self->pmc.constants)
681 goto err;
682 }
683
684 for (i = 0; i < self->num.const_count; i++)
685 self->num.constants[i] = PF_fetch_number(pf, &cursor);
686
687 for (i = 0; i < self->str.const_count; i++)
688 self->str.constants[i] = PF_fetch_string(interp, pf, &cursor);
689
690 for (i = 0; i < self->pmc.const_count; i++)
691 self->pmc.constants[i] = const_unpack_pmc(interp, self, &cursor);
692
693 for (i = 0; i < self->pmc.const_count; i++) {
694 /* XXX unpack returned the lists of all objects in the object graph
695 * must dereference the first object into the constant slot */
696 PMC * const pmc = self->pmc.constants[i]
697 = VTABLE_get_pmc_keyed_int(interp, self->pmc.constants[i], 0);
698
699 PObj_is_shared_SET(pmc); /* packfile constants will be shared among threads */
700
701 /* magically place subs into namespace stashes
702 * XXX make this explicit with :load subs in PBC */
703 if (VTABLE_isa(interp, pmc, sub_str))
704 Parrot_ns_store_sub(interp, pmc);
705 }
706
707 self->ntags = PF_fetch_opcode(pf, &cursor);
708 self->tag_map = mem_gc_allocate_n_zeroed_typed(interp, self->ntags, PackFile_ConstTagPair);
709 for (i = 0; i < self->ntags; i++) {
710 self->tag_map[i].tag_idx = PF_fetch_opcode(pf, &cursor);
711 self->tag_map[i].const_idx = PF_fetch_opcode(pf, &cursor);
712 }
713
714 return cursor;
715
716 err:
717 Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_ALLOCATION_ERROR,
718 "const_unpack: Could not allocate memory for array");
719 }
720
721
722 /*
723
724 =item C<static PackFile_Segment * const_new(PARROT_INTERP)>
725
726 Returns a new C<PackFile_ConstTable> segment.
727
728 =cut
729
730 */
731
732 PARROT_MALLOC
733 PARROT_CANNOT_RETURN_NULL
734 static PackFile_Segment *
const_new(PARROT_INTERP)735 const_new(PARROT_INTERP)
736 {
737 ASSERT_ARGS(const_new)
738 PackFile_ConstTable * const const_table =
739 mem_gc_allocate_zeroed_typed(interp, PackFile_ConstTable);
740
741 return (PackFile_Segment *)const_table;
742 }
743
744
745 /*
746
747 =item C<static void const_destroy(PARROT_INTERP, PackFile_Segment *self)>
748
749 Destroys the C<PackFile_ConstTable> C<self>.
750
751 =cut
752
753 */
754
755 static void
const_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))756 const_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
757 {
758 ASSERT_ARGS(const_destroy)
759 PackFile_ConstTable * const ct = (PackFile_ConstTable *)self;
760 const_clear(interp, ct);
761 }
762
763
764 /*
765
766 =item C<static PMC * const_unpack_pmc(PARROT_INTERP, PackFile_ConstTable
767 *constt, const opcode_t **cursor)>
768
769 Unpacks a constant PMC.
770
771 =cut
772
773 */
774
775 PARROT_WARN_UNUSED_RESULT
776 PARROT_CANNOT_RETURN_NULL
777 static PMC *
const_unpack_pmc(PARROT_INTERP,ARGIN (PackFile_ConstTable * constt),ARGIN (const opcode_t ** cursor))778 const_unpack_pmc(PARROT_INTERP, ARGIN(PackFile_ConstTable *constt),
779 ARGIN(const opcode_t **cursor))
780 {
781 ASSERT_ARGS(const_unpack_pmc)
782 PackFile * const pf = constt->base.pf;
783 PMC *pmc;
784 /* thawing the PMC needs the real packfile in place */
785 PackFile_ByteCode * const cs_save = interp->code;
786 interp->code = pf->cur_cs;
787 pmc = Parrot_thaw_pbc(interp, constt, cursor);
788 /* restore code */
789 interp->code = cs_save;
790
791 return pmc;
792 }
793
794
795 /*
796
797 =item C<static PackFile_Segment * annotations_new(PARROT_INTERP)>
798
799 Creates a new annotations segment structure.
800
801 =cut
802
803 */
804
805 PARROT_CANNOT_RETURN_NULL
806 static PackFile_Segment *
annotations_new(PARROT_INTERP)807 annotations_new(PARROT_INTERP)
808 {
809 ASSERT_ARGS(annotations_new)
810 /* Allocate annotations structure; create it all zeroed, and we will
811 * allocate memory for each of the arrays on demand. */
812 PackFile_Annotations * const seg = mem_gc_allocate_zeroed_typed(interp,
813 PackFile_Annotations);
814 return (PackFile_Segment *) seg;
815 }
816
817 /*
818
819 =item C<static void annotations_destroy(PARROT_INTERP, PackFile_Segment *seg)>
820
821 Frees all memory associated with an annotations segment.
822
823 =cut
824
825 */
826
827 static void
annotations_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * seg))828 annotations_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *seg))
829 {
830 ASSERT_ARGS(annotations_destroy)
831 PackFile_Annotations * const self = (PackFile_Annotations *)seg;
832
833 /* Free any keys. */
834 if (self->keys)
835 mem_gc_free(interp, self->keys);
836
837 self->keys = NULL;
838 }
839
840
841 /*
842
843 =item C<static size_t annotations_packed_size(PARROT_INTERP, PackFile_Segment
844 *seg)>
845
846 Computes the number of opcode_ts needed to store the passed annotations
847 segment.
848
849 =cut
850
851 */
852
853 PARROT_WARN_UNUSED_RESULT
854 PARROT_PURE_FUNCTION
855 static size_t
annotations_packed_size(SHIM_INTERP,ARGMOD (PackFile_Segment * seg))856 annotations_packed_size(SHIM_INTERP, ARGMOD(PackFile_Segment *seg))
857 {
858 ASSERT_ARGS(annotations_packed_size)
859 const PackFile_Annotations * const self = (PackFile_Annotations *)seg;
860 return 1 + self->num_keys * 4; /* keys and key count */
861 }
862
863
864 /*
865
866 =item C<static opcode_t * annotations_pack(PARROT_INTERP, PackFile_Segment *seg,
867 opcode_t *cursor)>
868
869 Packs this segment into bytecode.
870
871 =cut
872
873 */
874
875 PARROT_WARN_UNUSED_RESULT
876 PARROT_CANNOT_RETURN_NULL
877 static opcode_t *
annotations_pack(SHIM_INTERP,ARGIN (PackFile_Segment * seg),ARGOUT (opcode_t * cursor))878 annotations_pack(SHIM_INTERP, ARGIN(PackFile_Segment *seg),
879 ARGOUT(opcode_t *cursor))
880 {
881 ASSERT_ARGS(annotations_pack)
882 const PackFile_Annotations * const self = (PackFile_Annotations *)seg;
883 INTVAL i;
884
885 /* Write key count and any keys. */
886 *cursor++ = self->num_keys;
887
888 for (i = 0; i < self->num_keys; ++i) {
889 const PackFile_Annotations_Key * const key = self->keys + i;
890 *cursor++ = key->name;
891 *cursor++ = key->type;
892 *cursor++ = key->start;
893 *cursor++ = key->len;
894 }
895
896 return cursor;
897 }
898
899
900 /*
901
902 =item C<static const opcode_t * annotations_unpack(PARROT_INTERP,
903 PackFile_Segment *seg, const opcode_t *cursor)>
904
905 Unpacks this segment from the bytecode.
906
907 =cut
908
909 */
910
911 PARROT_CANNOT_RETURN_NULL
912 static const opcode_t *
annotations_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * seg),ARGIN (const opcode_t * cursor))913 annotations_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *seg),
914 ARGIN(const opcode_t *cursor))
915 {
916 ASSERT_ARGS(annotations_unpack)
917 PackFile_Annotations * const self = (PackFile_Annotations *)seg;
918 PackFile_ByteCode *code;
919 STRING *code_name;
920 INTVAL i, str_len;
921
922 /* Unpack keys. */
923 self->num_keys = PF_fetch_opcode(seg->pf, &cursor);
924
925 self->keys = mem_gc_allocate_n_zeroed_typed(interp,
926 self->num_keys, PackFile_Annotations_Key);
927
928 for (i = 0; i < self->num_keys; ++i) {
929 PackFile_Annotations_Key * const key = self->keys + i;
930 key->name = PF_fetch_opcode(seg->pf, &cursor);
931 key->type = (pf_ann_key_type_t)PF_fetch_opcode(seg->pf, &cursor);
932 key->start = PF_fetch_opcode(seg->pf, &cursor);
933 key->len = PF_fetch_opcode(seg->pf, &cursor);
934 }
935
936 /* Need to associate this segment with the applicable code segment. */
937 str_len = Parrot_str_length(interp, self->base.name);
938 code_name = STRING_substr(interp, self->base.name, 0, str_len - 4);
939 code = (PackFile_ByteCode *)Parrot_pf_find_segment(interp,
940 self->base.dir, code_name, 0);
941
942 if (!code || code->base.type != PF_BYTEC_SEG) {
943 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
944 "Code '%s' not found for annotations segment '%s'",
945 code_name, self->base.name);
946 }
947
948 self->code = code;
949 code->annotations = self;
950
951 return cursor;
952 }
953
954
955 /*
956
957 =item C<static void annotations_dump(PARROT_INTERP, const PackFile_Segment
958 *seg)>
959
960 Produces a dump of the annotations segment.
961
962 =cut
963
964 */
965
966 static void
annotations_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * seg))967 annotations_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *seg))
968 {
969 ASSERT_ARGS(annotations_dump)
970 const PackFile_Annotations * const self = (const PackFile_Annotations *)seg;
971 INTVAL i;
972 size_t j;
973
974 default_dump_header(interp, (const PackFile_Segment *)self);
975
976 /* Dump keys. */
977 Parrot_io_printf(interp, "\n [\n");
978 for (i = 0; i < self->num_keys; ++i) {
979 const PackFile_Annotations_Key * const key = &self->keys[i];
980 const size_t key_end = key->start + key->len;
981 Parrot_io_printf(interp, " #"INTVAL_FMT"\n [\n", i);
982 Parrot_io_printf(interp, " NAME => %Ss\n",
983 self->code->const_table->str.constants[key->name]);
984 Parrot_io_printf(interp, " TYPE => %s\n",
985 key->type == PF_ANNOTATION_KEY_TYPE_INT ? "integer" :
986 key->type == PF_ANNOTATION_KEY_TYPE_STR ? "string" :
987 key->type == PF_ANNOTATION_KEY_TYPE_PMC ? "pmc" :
988 "<ERROR>");
989 for (j = key->start; j < key_end; j++) {
990 Parrot_io_printf(interp, " [\n");
991 Parrot_io_printf(interp, " BYTECODE_OFFSET => %ld\n",
992 self->base.data[j * 2 + ANN_ENTRY_OFF]);
993 Parrot_io_printf(interp, " VALUE => %ld\n",
994 self->base.data[j * 2 + ANN_ENTRY_VAL]);
995 Parrot_io_printf(interp, " ],\n");
996 }
997 Parrot_io_printf(interp, " ],\n");
998 }
999
1000 Parrot_io_printf(interp, " ],\n");
1001 Parrot_io_printf(interp, "],\n");
1002 }
1003
1004 /*
1005
1006 =item C<static void pf_register_funcs(PackFile *pf, UINTVAL type, const
1007 PackFile_funcs funcs)>
1008
1009 Registers the C<pack>/C<unpack>/... functions for a packfile type.
1010
1011 =cut
1012
1013 */
1014
1015 static void
pf_register_funcs(ARGMOD (PackFile * pf),UINTVAL type,const PackFile_funcs funcs)1016 pf_register_funcs(ARGMOD(PackFile *pf), UINTVAL type,
1017 const PackFile_funcs funcs)
1018 {
1019 ASSERT_ARGS(pf_register_funcs)
1020 pf->PackFuncs[type] = funcs;
1021 }
1022
1023
1024 /*
1025
1026 =item C<static const opcode_t * default_unpack(PARROT_INTERP, PackFile_Segment
1027 *self, const opcode_t *cursor)>
1028
1029 Unpacks a PackFile given a cursor into PBC. This is the default unpack.
1030
1031 =cut
1032
1033 */
1034
1035 PARROT_WARN_UNUSED_RESULT
1036 PARROT_CAN_RETURN_NULL
1037 static const opcode_t *
default_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))1038 default_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGIN(const opcode_t *cursor))
1039 {
1040 ASSERT_ARGS(default_unpack)
1041 DECL_CONST_CAST_OF(opcode_t);
1042
1043 self->op_count = PF_fetch_opcode(self->pf, &cursor);
1044 self->itype = PF_fetch_opcode(self->pf, &cursor);
1045 self->id = PF_fetch_opcode(self->pf, &cursor);
1046 self->size = PF_fetch_opcode(self->pf, &cursor);
1047
1048 if (self->size == 0)
1049 return cursor;
1050
1051 /* if the packfile is mmap()ed just point to it if we don't
1052 * need any fetch transforms */
1053 if (self->pf->is_mmap_ped
1054 && !self->pf->need_endianize
1055 && !self->pf->need_wordsize) {
1056 self->data = PARROT_const_cast(opcode_t *, cursor);
1057 cursor += self->size;
1058 return cursor;
1059 }
1060
1061 /* else allocate mem */
1062 self->data = mem_gc_allocate_n_typed(interp, self->size, opcode_t);
1063
1064 if (!self->data) {
1065 Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_ALLOCATION_ERROR,
1066 "PackFile_unpack: Unable to allocate data memory");
1067 }
1068
1069 if (!self->pf->need_endianize && !self->pf->need_wordsize) {
1070 memcpy(self->data, cursor, self->size * sizeof (opcode_t));
1071 cursor += self->size;
1072 }
1073 else {
1074 int i;
1075 for (i = 0; i < (int)self->size; i++)
1076 self->data[i] = PF_fetch_opcode(self->pf, &cursor);
1077 }
1078
1079 return cursor;
1080 }
1081
1082
1083 /*
1084
1085 =item C<void default_dump_header(PARROT_INTERP, const PackFile_Segment *self)>
1086
1087 Dumps the header of a given PackFile_Segment.
1088
1089 =cut
1090
1091 */
1092
1093 void
default_dump_header(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1094 default_dump_header(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1095 {
1096 ASSERT_ARGS(default_dump_header)
1097 Parrot_io_printf(interp, "%Ss => [ # offs 0x%x(%d)",
1098 self->name, (int)self->file_offset, (int)self->file_offset);
1099 Parrot_io_printf(interp, " = op_count %d, itype %d, id %d, size %d, ...",
1100 (int)self->op_count, (int)self->itype,
1101 (int)self->id, (int)self->size);
1102 }
1103
1104
1105 /*
1106
1107 =item C<static void default_dump(PARROT_INTERP, const PackFile_Segment *self)>
1108
1109 Dumps a PackFile_Segment.
1110
1111 =cut
1112
1113 */
1114
1115 static void
default_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1116 default_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1117 {
1118 ASSERT_ARGS(default_dump)
1119 size_t i = self->data ? 0: self->file_offset + SEGMENT_HEADER_SIZE;
1120
1121 default_dump_header(interp, self);
1122
1123 if (i % 8)
1124 Parrot_io_printf(interp, "\n %04x: ", (int) i);
1125
1126 for (; i < (self->data ? self->size :
1127 self->file_offset + self->op_count); ++i) {
1128
1129 if (i % 8 == 0)
1130 Parrot_io_printf(interp, "\n %04x: ", (int) i);
1131
1132 Parrot_io_printf(interp, "%08lx ", (unsigned long)
1133 (self->data ? self->data[i] : self->pf->src[i]));
1134 }
1135
1136 Parrot_io_printf(interp, "\n]\n");
1137 }
1138
1139
1140 /*
1141
1142 =item C<void pf_register_standard_funcs(PackFile *pf)>
1143
1144 Registers a PackFile's functions; called from within C<Parrot_pf_new()>.
1145
1146 =cut
1147
1148 */
1149
1150 void
pf_register_standard_funcs(ARGMOD (PackFile * pf))1151 pf_register_standard_funcs(ARGMOD(PackFile *pf))
1152 {
1153 ASSERT_ARGS(pf_register_standard_funcs)
1154
1155 static const PackFile_funcs dirf = {
1156 directory_new,
1157 directory_destroy,
1158 directory_packed_size,
1159 directory_pack,
1160 directory_unpack,
1161 directory_dump
1162 };
1163
1164 static const PackFile_funcs defaultf = {
1165 segment_new,
1166 (PackFile_Segment_destroy_func_t) NULL,
1167 (PackFile_Segment_packed_size_func_t) NULL,
1168 (PackFile_Segment_pack_func_t) NULL,
1169 (PackFile_Segment_unpack_func_t) NULL,
1170 default_dump
1171 };
1172
1173 static const PackFile_funcs constf = {
1174 const_new,
1175 const_destroy,
1176 Parrot_pf_ConstTable_pack_size,
1177 Parrot_pf_ConstTable_pack,
1178 const_unpack,
1179 default_dump
1180 };
1181
1182 static const PackFile_funcs bytef = {
1183 byte_code_new,
1184 byte_code_destroy,
1185 byte_code_packed_size,
1186 byte_code_pack,
1187 byte_code_unpack,
1188 default_dump
1189 };
1190
1191 static const PackFile_funcs debugf = {
1192 pf_debug_new,
1193 pf_debug_destroy,
1194 pf_debug_packed_size,
1195 pf_debug_pack,
1196 pf_debug_unpack,
1197 pf_debug_dump
1198 };
1199
1200 static const PackFile_funcs annotationf = {
1201 annotations_new,
1202 annotations_destroy,
1203 annotations_packed_size,
1204 annotations_pack,
1205 annotations_unpack,
1206 annotations_dump
1207 };
1208
1209 pf_register_funcs(pf, PF_DIR_SEG, dirf);
1210 pf_register_funcs(pf, PF_UNKNOWN_SEG, defaultf);
1211 pf_register_funcs(pf, PF_CONST_SEG, constf);
1212 pf_register_funcs(pf, PF_BYTEC_SEG, bytef);
1213 pf_register_funcs(pf, PF_DEBUG_SEG, debugf);
1214 pf_register_funcs(pf, PF_ANNOTATIONS_SEG, annotationf);
1215
1216 return;
1217 }
1218
1219
1220 /*
1221
1222 =back
1223
1224 =head2 PackFile Segment Methods
1225
1226 =over 4
1227
1228 =item C<PackFile_Segment * Parrot_pf_new_segment(PARROT_INTERP,
1229 PackFile_Directory *dir, UINTVAL type, STRING *name, int add)>
1230
1231 Creates a new segment in the given PackFile_Directory of the given C<type> with
1232 the given C<name>. If C<add> is true, adds the segment to the directory.
1233
1234 =cut
1235
1236 */
1237
1238 PARROT_EXPORT
1239 PARROT_WARN_UNUSED_RESULT
1240 PARROT_CANNOT_RETURN_NULL
1241 PackFile_Segment *
Parrot_pf_new_segment(PARROT_INTERP,ARGMOD (PackFile_Directory * dir),UINTVAL type,ARGIN (STRING * name),int add)1242 Parrot_pf_new_segment(PARROT_INTERP, ARGMOD(PackFile_Directory *dir),
1243 UINTVAL type, ARGIN(STRING *name), int add)
1244 {
1245 ASSERT_ARGS(Parrot_pf_new_segment)
1246 PackFile * const pf = dir->base.pf;
1247 const PackFile_Segment_new_func_t f = pf->PackFuncs[type].new_seg;
1248 PackFile_Segment * const seg = (f)(interp);
1249
1250 segment_init(seg, pf, name);
1251 seg->type = type;
1252
1253 if (add)
1254 Parrot_pf_add_segment(interp, dir, seg);
1255
1256 return seg;
1257 }
1258
1259 /*
1260
1261 =item C<PackFile_Segment * PackFile_Segment_new_seg(PARROT_INTERP,
1262 PackFile_Directory *dir, UINTVAL type, STRING *name, int add)>
1263
1264 Deprecated: Use C<Parrot_pf_new_segment> instead. GH #1122
1265
1266 =cut
1267
1268 */
1269
1270 PARROT_EXPORT
1271 PARROT_DEPRECATED
1272 PARROT_WARN_UNUSED_RESULT
1273 PARROT_CANNOT_RETURN_NULL
1274 PackFile_Segment *
PackFile_Segment_new_seg(PARROT_INTERP,ARGMOD (PackFile_Directory * dir),UINTVAL type,ARGIN (STRING * name),int add)1275 PackFile_Segment_new_seg(PARROT_INTERP, ARGMOD(PackFile_Directory *dir),
1276 UINTVAL type, ARGIN(STRING *name), int add)
1277 {
1278 ASSERT_ARGS(PackFile_Segment_new_seg)
1279 return Parrot_pf_new_segment(interp, dir, type, name, add);
1280 }
1281
1282 /*
1283
1284 =item C<void Parrot_pf_destroy_segment(PARROT_INTERP, PackFile_Segment *self)>
1285
1286 Destroys the given PackFile_Segment.
1287
1288 =cut
1289
1290 */
1291
1292 PARROT_EXPORT
1293 void
Parrot_pf_destroy_segment(PARROT_INTERP,ARGMOD (PackFile_Segment * self))1294 Parrot_pf_destroy_segment(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
1295 {
1296 ASSERT_ARGS(Parrot_pf_destroy_segment)
1297 const PackFile_Segment_destroy_func_t f =
1298 self->pf->PackFuncs[self->type].destroy;
1299
1300 if (f)
1301 (f)(interp, self);
1302
1303 /* destroy self after specific */
1304 default_destroy(interp, self);
1305 }
1306
1307 /*
1308
1309 =item C<void PackFile_Segment_destroy(PARROT_INTERP, PackFile_Segment *self)>
1310
1311 Deprecated: Use C<Parrot_pf_destroy_segment> instead. See TT #2140
1312
1313 =cut
1314
1315 */
1316
1317 PARROT_EXPORT
1318 PARROT_DEPRECATED
1319 void
PackFile_Segment_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))1320 PackFile_Segment_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
1321 {
1322 ASSERT_ARGS(PackFile_Segment_destroy)
1323 Parrot_pf_destroy_segment(interp, self);
1324 }
1325
1326 /*
1327
1328 =item C<size_t pf_segment_packed_size(PARROT_INTERP, PackFile_Segment *self)>
1329
1330 Returns the size of the given segment, when packed, taking into account padding
1331 and alignment.
1332
1333 =cut
1334
1335 */
1336
1337 size_t
pf_segment_packed_size(PARROT_INTERP,ARGIN (PackFile_Segment * self))1338 pf_segment_packed_size(PARROT_INTERP, ARGIN(PackFile_Segment *self))
1339 {
1340 ASSERT_ARGS(pf_segment_packed_size)
1341 size_t size = default_packed_size(self);
1342 const size_t align = 16 / sizeof (opcode_t);
1343 PackFile_Segment_packed_size_func_t f =
1344 self->pf->PackFuncs[self->type].packed_size;
1345
1346 if (f)
1347 size += (f)(interp, self);
1348
1349 /* pad/align it */
1350 if (align && size % align)
1351 size += (align - size % align);
1352
1353 return size;
1354 }
1355
1356 /*
1357
1358 =item C<size_t PackFile_Segment_packed_size(PARROT_INTERP, PackFile_Segment
1359 *self)>
1360
1361 Deprecated: Use C<pf_segment_packed_size> instead. Will not be exported anymore.
1362 See TT #2140
1363
1364 =cut
1365
1366 */
1367
1368 PARROT_EXPORT
1369 PARROT_DEPRECATED
1370 size_t
PackFile_Segment_packed_size(PARROT_INTERP,ARGIN (PackFile_Segment * self))1371 PackFile_Segment_packed_size(PARROT_INTERP, ARGIN(PackFile_Segment *self))
1372 {
1373 ASSERT_ARGS(PackFile_Segment_packed_size)
1374 return pf_segment_packed_size(interp, self);
1375 }
1376
1377 /*
1378
1379 =item C<opcode_t * pf_segment_pack(PARROT_INTERP, PackFile_Segment *self,
1380 opcode_t *cursor)>
1381
1382 Packs a PackFile_Segment, returning a cursor to the start of the results.
1383
1384 =cut
1385
1386 */
1387
1388 PARROT_WARN_UNUSED_RESULT
1389 PARROT_CANNOT_RETURN_NULL
1390 opcode_t *
pf_segment_pack(PARROT_INTERP,ARGIN (PackFile_Segment * self),ARGIN (opcode_t * cursor))1391 pf_segment_pack(PARROT_INTERP, ARGIN(PackFile_Segment *self),
1392 ARGIN(opcode_t *cursor))
1393 {
1394 ASSERT_ARGS(pf_segment_pack)
1395 /*const size_t align = 16 / sizeof (opcode_t);*/
1396 PackFile_Segment_pack_func_t f =
1397 self->pf->PackFuncs[self->type].pack;
1398 opcode_t * old_cursor; /* Used for filling padding with 0 */
1399
1400 cursor = default_pack(self, cursor);
1401
1402 if (f)
1403 cursor = (f)(interp, self, cursor);
1404
1405 old_cursor = cursor;
1406 ALIGN_16(self->pf, cursor);
1407 /* fill padding with zeros */
1408 while (old_cursor != cursor)
1409 *old_cursor++ = 0;
1410
1411 /*if (align && (cursor - self->pf->src) % align)
1412 cursor += align - (cursor - self->pf->src) % align;*/
1413
1414 return cursor;
1415 }
1416
1417 /*
1418
1419 =item C<opcode_t * PackFile_Segment_pack(PARROT_INTERP, PackFile_Segment *self,
1420 opcode_t *cursor)>
1421
1422 Deprecated: Use C<pf_segment_pack> instead. Will not be exported anymore.
1423 See GH #1122
1424
1425 =cut
1426
1427 */
1428
1429 PARROT_EXPORT
1430 PARROT_DEPRECATED
1431 PARROT_WARN_UNUSED_RESULT
1432 PARROT_CANNOT_RETURN_NULL
1433 opcode_t *
PackFile_Segment_pack(PARROT_INTERP,ARGIN (PackFile_Segment * self),ARGIN (opcode_t * cursor))1434 PackFile_Segment_pack(PARROT_INTERP, ARGIN(PackFile_Segment *self),
1435 ARGIN(opcode_t *cursor))
1436 {
1437 ASSERT_ARGS(PackFile_Segment_pack)
1438 return pf_segment_pack(interp, self, cursor);
1439 }
1440
1441 /*
1442
1443 =item C<const opcode_t * pf_segment_unpack(PARROT_INTERP, PackFile_Segment
1444 *self, const opcode_t *cursor)>
1445
1446 Unpacks a PackFile_Segment, returning a cursor to the results on success and
1447 NULL otherwise.
1448
1449 All these functions call the related C<default_*> function.
1450
1451 If a special is defined this gets called after.
1452
1453 =cut
1454
1455 */
1456
1457 PARROT_WARN_UNUSED_RESULT
1458 PARROT_CAN_RETURN_NULL
1459 const opcode_t *
pf_segment_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))1460 pf_segment_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self),
1461 ARGIN(const opcode_t *cursor))
1462 {
1463 ASSERT_ARGS(pf_segment_unpack)
1464 PackFile_Segment_unpack_func_t f = self->pf->PackFuncs[self->type].unpack;
1465 int offs;
1466 cursor = default_unpack(interp, self, cursor);
1467
1468 if (!cursor)
1469 return NULL;
1470
1471 if (f) {
1472 cursor = (f)(interp, self, cursor);
1473 if (!cursor)
1474 return NULL;
1475 }
1476
1477 offs = OFFS(self->pf, cursor);
1478 offs += PAD_16_B(offs);
1479 cursor = self->pf->src + offs/(sizeof (opcode_t));
1480 return cursor;
1481 }
1482
1483 /*
1484
1485 =item C<const opcode_t * PackFile_Segment_unpack(PARROT_INTERP, PackFile_Segment
1486 *self, const opcode_t *cursor)>
1487
1488 Deprecated: Use C<pf_segment_unpack> instead. Will not be exported anymore. See TT #2140
1489 See GH #1122
1490
1491 =cut
1492
1493 */
1494
1495 PARROT_EXPORT
1496 PARROT_DEPRECATED
1497 PARROT_WARN_UNUSED_RESULT
1498 PARROT_CAN_RETURN_NULL
1499 const opcode_t *
PackFile_Segment_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))1500 PackFile_Segment_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self),
1501 ARGIN(const opcode_t *cursor))
1502 {
1503 ASSERT_ARGS(PackFile_Segment_unpack)
1504 return pf_segment_unpack(interp, self, cursor);
1505 }
1506
1507 /*
1508
1509 =item C<void Parrot_pf_dump_segment(PARROT_INTERP, const PackFile_Segment
1510 *self)>
1511
1512 Dumps the packfile segment C<self>.
1513
1514 =cut
1515
1516 */
1517
1518 PARROT_EXPORT
1519 void
Parrot_pf_dump_segment(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1520 Parrot_pf_dump_segment(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1521 {
1522 ASSERT_ARGS(Parrot_pf_dump_segment)
1523 self->pf->PackFuncs[self->type].dump(interp, self);
1524 }
1525
1526 /*
1527
1528 =item C<void PackFile_Segment_dump(PARROT_INTERP, const PackFile_Segment *self)>
1529
1530 Dumps the segment C<self>.
1531
1532 Deprecated: Will not be exported anymore. GH #1170
1533
1534 =cut
1535
1536 */
1537
1538 PARROT_EXPORT
1539 PARROT_DEPRECATED
1540 void
PackFile_Segment_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1541 PackFile_Segment_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1542 {
1543 ASSERT_ARGS(PackFile_Segment_dump)
1544 self->pf->PackFuncs[self->type].dump(interp, self);
1545 }
1546
1547 /*
1548
1549 =back
1550
1551 =head2 Standard Directory Functions
1552
1553 =over 4
1554
1555 =item C<static PackFile_Segment * directory_new(PARROT_INTERP)>
1556
1557 Returns a new C<PackFile_Directory> cast as a C<PackFile_Segment>.
1558
1559 =cut
1560
1561 */
1562
1563 PARROT_WARN_UNUSED_RESULT
1564 PARROT_CANNOT_RETURN_NULL
1565 static PackFile_Segment *
directory_new(PARROT_INTERP)1566 directory_new(PARROT_INTERP)
1567 {
1568 ASSERT_ARGS(directory_new)
1569
1570 return (PackFile_Segment *)mem_gc_allocate_zeroed_typed(interp, PackFile_Directory);
1571 }
1572
1573
1574 /*
1575
1576 =item C<static void directory_dump(PARROT_INTERP, const PackFile_Segment *self)>
1577
1578 Dumps the directory C<self>.
1579
1580 =cut
1581
1582 */
1583
1584 static void
directory_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * self))1585 directory_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
1586 {
1587 ASSERT_ARGS(directory_dump)
1588 const PackFile_Directory * const dir = (const PackFile_Directory *) self;
1589 size_t i;
1590
1591 default_dump_header(interp, self);
1592
1593 Parrot_io_printf(interp, "\n\t# "SIZE_FMT" segments\n", dir->num_segments);
1594
1595 for (i = 0; i < dir->num_segments; ++i) {
1596 const PackFile_Segment * const seg = dir->segments[i];
1597
1598 Parrot_io_printf(interp,
1599 "\ttype %d\t%Ss\t", (int)seg->type, seg->name);
1600
1601 Parrot_io_printf(interp,
1602 " offs 0x%lx(0x%lx)\top_count %ld\n",
1603 seg->file_offset,
1604 seg->file_offset * sizeof (opcode_t),
1605 seg->op_count);
1606 }
1607
1608 Parrot_io_printf(interp, "]\n");
1609
1610 for (i = 0; i < dir->num_segments; ++i)
1611 Parrot_pf_dump_segment(interp, dir->segments[i]);
1612 }
1613
1614
1615 /*
1616
1617 =item C<static const opcode_t * directory_unpack(PARROT_INTERP, PackFile_Segment
1618 *segp, const opcode_t *cursor)>
1619
1620 Unpacks the directory from the provided cursor.
1621
1622 =cut
1623
1624 */
1625
1626 PARROT_CAN_RETURN_NULL
1627 PARROT_WARN_UNUSED_RESULT
1628 static const opcode_t *
directory_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * segp),ARGIN (const opcode_t * cursor))1629 directory_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *segp), ARGIN(const opcode_t *cursor))
1630 {
1631 ASSERT_ARGS(directory_unpack)
1632 PackFile_Directory * const dir = (PackFile_Directory *)segp;
1633 PackFile * const pf = dir->base.pf;
1634 const opcode_t *pos;
1635 size_t i;
1636 int offs;
1637
1638 PARROT_ASSERT(pf);
1639 dir->num_segments = PF_fetch_opcode(pf, &cursor);
1640 dir->segments = mem_gc_allocate_n_zeroed_typed(interp,
1641 dir->num_segments, PackFile_Segment *);
1642
1643 for (i = 0; i < dir->num_segments; ++i) {
1644 PackFile_Segment *seg;
1645 STRING *name;
1646 size_t opcode;
1647
1648 /* get type */
1649 UINTVAL type = PF_fetch_opcode(pf, &cursor);
1650 if (type >= PF_MAX_SEG)
1651 type = PF_UNKNOWN_SEG;
1652
1653 /* get name */
1654 name = PF_fetch_string(interp, pf, &cursor);
1655
1656 /* create it */
1657 seg = Parrot_pf_new_segment(interp, dir, type, name, 0);
1658 seg->file_offset = PF_fetch_opcode(pf, &cursor);
1659 seg->op_count = PF_fetch_opcode(pf, &cursor);
1660
1661 if (pf->need_wordsize) {
1662 #if OPCODE_T_SIZE == 8
1663 if (pf->header->wordsize == 4)
1664 pos = pf->src + seg->file_offset / 2;
1665 #else
1666 if (pf->header->wordsize == 8)
1667 pos = pf->src + seg->file_offset * 2;
1668 #endif
1669 else {
1670 fprintf(stderr, "directory_unpack failed: invalid wordsize %d\n",
1671 (int)pf->header->wordsize);
1672 return NULL;
1673 }
1674 }
1675 else
1676 pos = pf->src + seg->file_offset;
1677
1678 opcode = PF_fetch_opcode(pf, &pos);
1679
1680 if (seg->op_count != opcode) {
1681 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
1682 "%Ss: Size in directory %d doesn't match size %d "
1683 "at offset 0x%x", seg->name, (int)seg->op_count,
1684 (int)opcode, (int)seg->file_offset);
1685 }
1686
1687 if (i) {
1688 PackFile_Segment *last = dir->segments[i - 1];
1689 if (last->file_offset + last->op_count != seg->file_offset)
1690 fprintf(stderr, "section: sections are not back to back\n");
1691 }
1692
1693 make_code_pointers(seg);
1694
1695 /* store the segment */
1696 dir->segments[i] = seg;
1697 seg->dir = dir;
1698 }
1699
1700 offs = OFFS(pf, cursor);
1701 offs += PAD_16_B(offs);
1702 cursor = pf->src + offs/(sizeof (opcode_t));
1703
1704 /* and now unpack contents of dir */
1705 for (i = 0; cursor && i < dir->num_segments; ++i) {
1706 const opcode_t * const csave = cursor;
1707
1708 /* check len again */
1709 const size_t tmp = PF_fetch_opcode(pf, &cursor);
1710
1711 /* keep gcc -O silent */
1712 size_t delta = 0;
1713
1714 cursor = csave;
1715 pos = pf_segment_unpack(interp, dir->segments[i], cursor);
1716
1717 if (!pos) {
1718 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
1719 "PackFile_unpack segment '%Ss' failed", dir->segments[i]->name);
1720 }
1721
1722 /* FIXME bug on 64bit reading 32bit lurking here! TT #254 */
1723 if (pf->need_wordsize) {
1724 #if OPCODE_T_SIZE == 8
1725 if (pf->header->wordsize == 4)
1726 delta = (pos - cursor) * 2;
1727 #else
1728 if (pf->header->wordsize == 8)
1729 delta = (pos - cursor) / 2;
1730 #endif
1731 }
1732 else
1733 delta = pos - cursor;
1734
1735 if (delta != tmp || dir->segments[i]->op_count != tmp)
1736 Parrot_io_eprintf(interp, "PackFile_unpack segment '%Ss' directory length %d "
1737 "length in file %d needed %d for unpack\n",
1738 dir->segments[i]->name,
1739 (int)dir->segments[i]->op_count, (int)tmp,
1740 (int)delta);
1741 cursor = pos;
1742 }
1743
1744 return cursor;
1745 }
1746
1747
1748 /*
1749
1750 =item C<static void directory_destroy(PARROT_INTERP, PackFile_Segment *self)>
1751
1752 Destroys the directory.
1753
1754 =cut
1755
1756 */
1757
1758 static void
directory_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))1759 directory_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
1760 {
1761 ASSERT_ARGS(directory_destroy)
1762 PackFile_Directory * const dir = (PackFile_Directory *)self;
1763 size_t i;
1764
1765 for (i = 0; i < dir->num_segments; ++i) {
1766 PackFile_Segment * const segment = dir->segments[i];
1767 /* Prevent repeated destruction */
1768 dir->segments[i] = NULL;
1769
1770 if (segment && segment != self)
1771 Parrot_pf_destroy_segment(interp, segment);
1772 }
1773
1774 if (dir->segments) {
1775 mem_gc_free(interp, dir->segments);
1776 dir->segments = NULL;
1777 dir->num_segments = 0;
1778 }
1779 }
1780
1781 /*
1782
1783 =item C<static void sort_segs(PackFile_Directory *dir)>
1784
1785 Sorts the segments in C<dir>.
1786
1787 =cut
1788
1789 */
1790
1791 static void
sort_segs(ARGMOD (PackFile_Directory * dir))1792 sort_segs(ARGMOD(PackFile_Directory *dir))
1793 {
1794 ASSERT_ARGS(sort_segs)
1795 const size_t num_segs = dir->num_segments;
1796 PackFile_Segment *seg = dir->segments[0];
1797
1798 if (seg->type != PF_BYTEC_SEG) {
1799 size_t i;
1800
1801 for (i = 1; i < num_segs; ++i) {
1802 PackFile_Segment * const s2 = dir->segments[i];
1803 if (s2->type == PF_BYTEC_SEG) {
1804 dir->segments[0] = s2;
1805 dir->segments[i] = seg;
1806 break;
1807 }
1808 }
1809 }
1810
1811
1812 /* XXX
1813 * Temporary? hack to put ConstantTable in front of other segments.
1814 * This is useful for Annotations because we ensure that constants used
1815 * for keys already available during unpack.
1816 */
1817 seg = dir->segments[1];
1818
1819 if (seg->type != PF_CONST_SEG) {
1820 size_t i;
1821
1822 for (i = 3; i < num_segs; ++i) {
1823 PackFile_Segment * const s2 = dir->segments[i];
1824 if (s2->type == PF_CONST_SEG) {
1825 dir->segments[2] = s2;
1826 dir->segments[i] = seg;
1827 break;
1828 }
1829 }
1830 }
1831 }
1832
1833
1834 /*
1835
1836 =item C<static size_t directory_packed_size(PARROT_INTERP, PackFile_Segment
1837 *self)>
1838
1839 Returns the size of the directory minus the value returned by
1840 C<default_packed_size()>.
1841
1842 =cut
1843
1844 */
1845
1846 PARROT_WARN_UNUSED_RESULT
1847 static size_t
directory_packed_size(PARROT_INTERP,ARGMOD (PackFile_Segment * self))1848 directory_packed_size(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
1849 {
1850 ASSERT_ARGS(directory_packed_size)
1851 PackFile_Directory * const dir = (PackFile_Directory *)self;
1852 const size_t align = 16 / sizeof (opcode_t);
1853 size_t size, i;
1854
1855 /* need bytecode, fixup, other segs ... */
1856 sort_segs(dir);
1857
1858 /* number of segments + default, we need it for the offsets */
1859 size = 1 + default_packed_size(self);
1860
1861 for (i = 0; i < dir->num_segments; ++i) {
1862 /* type, offset, size */
1863 size += 3;
1864 size += PF_size_string(dir->segments[i]->name);
1865 }
1866
1867 /* pad/align it */
1868 if (align && size % align)
1869 size += (align - size % align);
1870
1871 for (i = 0; i < dir->num_segments; ++i) {
1872 size_t seg_size;
1873
1874 dir->segments[i]->file_offset = size + self->file_offset;
1875 seg_size = pf_segment_packed_size(interp, dir->segments[i]);
1876 dir->segments[i]->op_count = seg_size;
1877 size += seg_size;
1878 }
1879
1880 self->op_count = size;
1881
1882 /* subtract default, it is added in PackFile_Segment_packed_size */
1883 return size - default_packed_size(self);
1884 }
1885
1886
1887 /*
1888
1889 =item C<static opcode_t * directory_pack(PARROT_INTERP, PackFile_Segment *self,
1890 opcode_t *cursor)>
1891
1892 Packs the directory C<self>, using the given cursor.
1893
1894 =cut
1895
1896 */
1897
1898 PARROT_WARN_UNUSED_RESULT
1899 PARROT_CANNOT_RETURN_NULL
1900 static opcode_t *
directory_pack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGOUT (opcode_t * cursor))1901 directory_pack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGOUT(opcode_t *cursor))
1902 {
1903 ASSERT_ARGS(directory_pack)
1904 PackFile_Directory * const dir = (PackFile_Directory *)self;
1905 const size_t num_segs = dir->num_segments;
1906 /*const size_t align = 16/sizeof (opcode_t);*/
1907 size_t i;
1908 PackFile * const pf = self->pf;
1909 opcode_t * old_cursor; /* Used for filling padding with 0 */
1910
1911 *cursor++ = num_segs;
1912
1913 for (i = 0; i < num_segs; i++) {
1914 const PackFile_Segment * const seg = dir->segments[i];
1915
1916 *cursor++ = seg->type;
1917 cursor = PF_store_string(cursor, seg->name);
1918 *cursor++ = seg->file_offset;
1919 *cursor++ = seg->op_count;
1920 }
1921
1922 old_cursor = cursor;
1923 ALIGN_16(pf, cursor);
1924 /* fill padding with zeros */
1925 while (old_cursor != cursor)
1926 *old_cursor++ = 0;
1927
1928 /*if (align && (cursor - self->pf->src) % align)
1929 cursor += align - (cursor - self->pf->src) % align;*/
1930
1931 /* now pack all segments into new format */
1932 for (i = 0; i < dir->num_segments; ++i) {
1933 PackFile_Segment * const seg = dir->segments[i];
1934 cursor = pf_segment_pack(interp, seg, cursor);
1935 }
1936
1937 return cursor;
1938 }
1939
1940
1941 /*
1942
1943 =back
1944
1945 =head2 C<PackFile_Segment> Functions
1946
1947 =over 4
1948
1949 =item C<static void segment_init(PackFile_Segment *self, PackFile *pf, STRING
1950 *name)>
1951
1952 Initializes the segment C<self> with the provided PackFile and the given name.
1953 Note that this duplicates the given name.
1954
1955 =cut
1956
1957 */
1958
1959 static void
segment_init(ARGOUT (PackFile_Segment * self),ARGIN (PackFile * pf),ARGIN (STRING * name))1960 segment_init(ARGOUT(PackFile_Segment *self), ARGIN(PackFile *pf),
1961 ARGIN(STRING *name))
1962 {
1963 ASSERT_ARGS(segment_init)
1964 self->pf = pf;
1965 self->type = PF_UNKNOWN_SEG;
1966 self->file_offset = 0;
1967 self->op_count = 0;
1968 self->itype = 0;
1969 self->size = 0;
1970 self->data = NULL;
1971 self->id = 0;
1972 self->name = name;
1973 }
1974
1975
1976 /*
1977
1978 =item C<static PackFile_Segment * segment_new(PARROT_INTERP)>
1979
1980 Creates a new default segment section for a packfile.
1981
1982 =cut
1983
1984 */
1985
1986 PARROT_WARN_UNUSED_RESULT
1987 PARROT_CANNOT_RETURN_NULL
1988 static PackFile_Segment *
segment_new(PARROT_INTERP)1989 segment_new(PARROT_INTERP)
1990 {
1991 ASSERT_ARGS(segment_new)
1992 PackFile_Segment * const seg = mem_gc_allocate_zeroed_typed(interp, PackFile_Segment);
1993
1994 return seg;
1995 }
1996
1997 /*
1998
1999 =item C<PackFile_Segment * PackFile_Segment_new(PARROT_INTERP)>
2000
2001 Creates a new default section.
2002
2003 Deprecated: Will not be exported anymore.
2004
2005 =cut
2006
2007 */
2008
2009 PARROT_EXPORT
2010 PARROT_DEPRECATED
2011 PARROT_WARN_UNUSED_RESULT
2012 PARROT_CANNOT_RETURN_NULL
2013 PackFile_Segment *
PackFile_Segment_new(PARROT_INTERP)2014 PackFile_Segment_new(PARROT_INTERP)
2015 {
2016 ASSERT_ARGS(PackFile_Segment_new)
2017 PackFile_Segment * const seg = mem_gc_allocate_zeroed_typed(interp, PackFile_Segment);
2018
2019 return seg;
2020 }
2021
2022 /*
2023
2024 =back
2025
2026 =head2 Default Function Implementations
2027
2028 The default functions are called before the segment specific functions
2029 and can read a block of C<opcode_t> data.
2030
2031 =over 4
2032
2033 =item C<static void default_destroy(PARROT_INTERP, PackFile_Segment *self)>
2034
2035 The default destroy function. Destroys a PackFile_Segment.
2036
2037 =cut
2038
2039 */
2040
2041 static void
default_destroy(PARROT_INTERP,ARGFREE_NOTNULL (PackFile_Segment * self))2042 default_destroy(PARROT_INTERP, ARGFREE_NOTNULL(PackFile_Segment *self))
2043 {
2044 ASSERT_ARGS(default_destroy)
2045 if (!self->pf->is_mmap_ped && self->data) {
2046 mem_gc_free(interp, self->data);
2047 self->data = NULL;
2048 }
2049
2050 mem_gc_free(interp, self);
2051 }
2052
2053
2054 /*
2055
2056 =item C<static size_t default_packed_size(const PackFile_Segment *self)>
2057
2058 Returns the default size of the segment C<self>.
2059
2060 =cut
2061
2062 */
2063
2064 PARROT_PURE_FUNCTION
2065 PARROT_WARN_UNUSED_RESULT
2066 static size_t
default_packed_size(ARGIN (const PackFile_Segment * self))2067 default_packed_size(ARGIN(const PackFile_Segment *self))
2068 {
2069 ASSERT_ARGS(default_packed_size)
2070 return SEGMENT_HEADER_SIZE + self->size;
2071 }
2072
2073
2074 /*
2075
2076 =item C<static opcode_t * default_pack(const PackFile_Segment *self, opcode_t
2077 *dest)>
2078
2079 Performs the default pack.
2080
2081 =cut
2082
2083 */
2084
2085 PARROT_WARN_UNUSED_RESULT
2086 PARROT_CANNOT_RETURN_NULL
2087 static opcode_t *
default_pack(ARGIN (const PackFile_Segment * self),ARGOUT (opcode_t * dest))2088 default_pack(ARGIN(const PackFile_Segment *self), ARGOUT(opcode_t *dest))
2089 {
2090 ASSERT_ARGS(default_pack)
2091 *dest++ = self->op_count;
2092 *dest++ = self->itype;
2093 *dest++ = self->id;
2094 *dest++ = self->size;
2095
2096 if (self->size)
2097 STRUCT_COPY_N(dest, self->data, self->size);
2098
2099 return dest + self->size;
2100 }
2101
2102 /*
2103
2104 =back
2105
2106 =head2 ByteCode
2107
2108 =over 4
2109
2110 =item C<static void byte_code_destroy(PARROT_INTERP, PackFile_Segment *self)>
2111
2112 Destroys the C<PackFile_ByteCode> segment C<self>.
2113
2114 =cut
2115
2116 */
2117
2118 static void
byte_code_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))2119 byte_code_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
2120 {
2121 ASSERT_ARGS(byte_code_destroy)
2122 PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
2123
2124 if (byte_code->op_func_table)
2125 mem_gc_free(interp, byte_code->op_func_table);
2126 if (byte_code->op_info_table)
2127 mem_gc_free(interp, byte_code->op_info_table);
2128 if (byte_code->op_mapping.libs) {
2129 const opcode_t n_libs = byte_code->op_mapping.n_libs;
2130 opcode_t i;
2131
2132 for (i = 0; i < n_libs; i++) {
2133 mem_gc_free(interp, byte_code->op_mapping.libs[i].table_ops);
2134 mem_gc_free(interp, byte_code->op_mapping.libs[i].lib_ops);
2135 }
2136
2137 mem_gc_free(interp, byte_code->op_mapping.libs);
2138 }
2139
2140 if (byte_code->libdeps)
2141 mem_gc_free(interp, byte_code->libdeps);
2142
2143 if (byte_code->annotations)
2144 annotations_destroy(interp, (PackFile_Segment *)byte_code->annotations);
2145
2146 byte_code->annotations = NULL;
2147 byte_code->const_table = NULL;
2148 byte_code->debugs = NULL;
2149 byte_code->op_func_table = NULL;
2150 byte_code->op_info_table = NULL;
2151 byte_code->op_mapping.libs = NULL;
2152 byte_code->libdeps = NULL;
2153 }
2154
2155
2156 /*
2157
2158 =item C<static PackFile_Segment * byte_code_new(PARROT_INTERP)>
2159
2160 Creates a new C<PackFile_ByteCode> segment.
2161
2162 =cut
2163
2164 */
2165
2166 PARROT_WARN_UNUSED_RESULT
2167 PARROT_CANNOT_RETURN_NULL
2168 static PackFile_Segment *
byte_code_new(PARROT_INTERP)2169 byte_code_new(PARROT_INTERP)
2170 {
2171 ASSERT_ARGS(byte_code_new)
2172 PackFile_ByteCode * const byte_code = mem_gc_allocate_zeroed_typed(interp, PackFile_ByteCode);
2173 byte_code->main_sub = -1;
2174
2175 return (PackFile_Segment *) byte_code;
2176 }
2177
2178 /*
2179
2180 =item C<static size_t byte_code_packed_size(PARROT_INTERP, PackFile_Segment
2181 *self)>
2182
2183 Computes the size in multiples of C<opcode_t> required to store the passed
2184 C<PackFile_ByteCode>.
2185
2186 =cut
2187
2188 */
2189
2190 PARROT_WARN_UNUSED_RESULT
2191 PARROT_PURE_FUNCTION
2192 static size_t
byte_code_packed_size(SHIM_INTERP,ARGMOD (PackFile_Segment * self))2193 byte_code_packed_size(SHIM_INTERP, ARGMOD(PackFile_Segment *self))
2194 {
2195 ASSERT_ARGS(byte_code_packed_size)
2196 PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
2197 size_t size;
2198 int i;
2199 unsigned int u;
2200
2201 size = 4; /* main_sub + op_count + n_libs + n_libdeps*/
2202
2203 for (u = 0; u < byte_code->n_libdeps; u++)
2204 size += PF_size_string(byte_code->libdeps[u]);
2205
2206 for (i = 0; i < byte_code->op_mapping.n_libs; i++) {
2207 PackFile_ByteCode_OpMappingEntry * const entry = &byte_code->op_mapping.libs[i];
2208
2209 /* dynoplib data */
2210 size += PF_size_cstring(entry->lib->name);
2211 size += 2; /* bc_major + bc_minor */
2212
2213 /* op entries */
2214 size += 1; /* n_ops */
2215 size += entry->n_ops * 2; /* lib_ops and table_ops */
2216 }
2217
2218 return size;
2219 }
2220
2221 /*
2222
2223 =item C<static opcode_t * byte_code_pack(PARROT_INTERP, PackFile_Segment *self,
2224 opcode_t *cursor)>
2225
2226 Stores the passed C<PackFile_ByteCode> segment in bytecode.
2227
2228 =cut
2229
2230 */
2231
2232 PARROT_WARN_UNUSED_RESULT
2233 PARROT_CANNOT_RETURN_NULL
2234 static opcode_t *
byte_code_pack(SHIM_INTERP,ARGMOD (PackFile_Segment * self),ARGOUT (opcode_t * cursor))2235 byte_code_pack(SHIM_INTERP, ARGMOD(PackFile_Segment *self), ARGOUT(opcode_t *cursor))
2236 {
2237 ASSERT_ARGS(byte_code_pack)
2238 const PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
2239 int i;
2240 unsigned int u;
2241
2242 *cursor++ = byte_code->main_sub;
2243
2244 *cursor++ = byte_code->n_libdeps;
2245 *cursor++ = byte_code->op_count;
2246 *cursor++ = byte_code->op_mapping.n_libs;
2247
2248 for (u = 0; u < byte_code->n_libdeps; u++)
2249 cursor = PF_store_string(cursor, byte_code->libdeps[u]);
2250
2251 for (i = 0; i < byte_code->op_mapping.n_libs; i++) {
2252 int j;
2253
2254 PackFile_ByteCode_OpMappingEntry * const entry = &byte_code->op_mapping.libs[i];
2255
2256 /* dynoplib data */
2257 cursor = PF_store_cstring(cursor, entry->lib->name);
2258 *cursor++ = entry->lib->bc_major_version;
2259 *cursor++ = entry->lib->bc_minor_version;
2260
2261 /* op entries */
2262 *cursor++ = entry->n_ops;
2263 for (j = 0; j < entry->n_ops; j++) {
2264 *cursor++ = entry->table_ops[j];
2265 *cursor++ = entry->lib_ops[j];
2266 }
2267 }
2268
2269 return cursor;
2270 }
2271
2272 /*
2273
2274 =item C<static const opcode_t * byte_code_unpack(PARROT_INTERP, PackFile_Segment
2275 *self, const opcode_t *cursor)>
2276
2277 Unpacks a bytecode segment into the passed C<PackFile_ByteCode>.
2278
2279 =cut
2280
2281 */
2282
2283 PARROT_WARN_UNUSED_RESULT
2284 PARROT_CANNOT_RETURN_NULL
2285 static const opcode_t *
byte_code_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))2286 byte_code_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGIN(const opcode_t *cursor))
2287 {
2288 ASSERT_ARGS(byte_code_unpack)
2289 PackFile_ByteCode * const byte_code = (PackFile_ByteCode *)self;
2290 int i;
2291 unsigned int u;
2292 size_t total_ops = 0;
2293
2294 byte_code->main_sub = PF_fetch_opcode(self->pf, &cursor);
2295
2296 byte_code->n_libdeps = PF_fetch_opcode(self->pf, &cursor);
2297 byte_code->libdeps = mem_gc_allocate_n_zeroed_typed(interp,
2298 byte_code->n_libdeps, STRING *);
2299
2300 byte_code->op_count = PF_fetch_opcode(self->pf, &cursor);
2301 byte_code->op_func_table = mem_gc_allocate_n_zeroed_typed(interp,
2302 byte_code->op_count, op_func_t);
2303 byte_code->op_info_table = mem_gc_allocate_n_zeroed_typed(interp,
2304 byte_code->op_count, op_info_t *);
2305
2306
2307 byte_code->op_mapping.n_libs = PF_fetch_opcode(self->pf, &cursor);
2308 byte_code->op_mapping.libs = mem_gc_allocate_n_zeroed_typed(interp,
2309 byte_code->op_mapping.n_libs,
2310 PackFile_ByteCode_OpMappingEntry);
2311
2312 for (u = 0; u < byte_code->n_libdeps; u++) {
2313 STRING * const libname = PF_fetch_string(interp, self->pf, &cursor);
2314 PMC * const lib_pmc = Parrot_dyn_load_lib(interp, libname, NULL);
2315 byte_code->libdeps[u] = libname;
2316 UNUSED(lib_pmc);
2317 }
2318
2319 for (i = 0; i < byte_code->op_mapping.n_libs; i++) {
2320 PackFile_ByteCode_OpMappingEntry * const entry = &byte_code->op_mapping.libs[i];
2321
2322 /* dynoplib data */
2323 {
2324 char * const lib_name = PF_fetch_cstring(interp, self->pf, &cursor);
2325 const opcode_t bc_major = PF_fetch_opcode(self->pf, &cursor);
2326 const opcode_t bc_minor = PF_fetch_opcode(self->pf, &cursor);
2327
2328 /* XXX
2329 * broken encapsulation => should make this data easier to access somehow
2330 */
2331 if (STREQ(lib_name, PARROT_CORE_OPLIB_NAME)) {
2332 entry->lib = PARROT_CORE_OPLIB_INIT(interp, 1);
2333 }
2334 else {
2335 PMC * const lib_pmc = Parrot_dyn_load_lib(interp,
2336 Parrot_str_new(interp, lib_name, 0),
2337 NULL);
2338 typedef op_lib_t *(*oplib_init_t)(PARROT_INTERP, long init);
2339 void *oplib_init;
2340 oplib_init_t fn;
2341 if (!VTABLE_get_bool(interp, lib_pmc))
2342 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR,
2343 "Could not load oplib `%s'", lib_name);
2344 GETATTR_ParrotLibrary_oplib_init(interp, lib_pmc, oplib_init);
2345 fn = (oplib_init_t)D2FPTR(oplib_init);
2346 entry->lib = fn(interp, 1);
2347 }
2348
2349
2350 mem_gc_free(interp, lib_name);
2351
2352 if (entry->lib->bc_major_version != bc_major
2353 || entry->lib->bc_minor_version != bc_minor)
2354 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR,
2355 "Incompatible versions of `%s' bytecode, possibly due to "
2356 "loading bytecode generated by an old version of Parrot. "
2357 "Found %d.%d but loaded %d.%d",
2358 entry->lib->name, bc_major, bc_minor,
2359 entry->lib->bc_major_version, entry->lib->bc_minor_version);
2360 }
2361
2362 /* op entries */
2363 {
2364 int j;
2365 total_ops += entry->n_ops = PF_fetch_opcode(self->pf, &cursor);
2366
2367 entry->table_ops = mem_gc_allocate_n_zeroed_typed(interp,
2368 entry->n_ops, opcode_t);
2369 entry->lib_ops = mem_gc_allocate_n_zeroed_typed(interp,
2370 entry->n_ops, opcode_t);
2371
2372 for (j = 0; j < entry->n_ops; j++) {
2373 opcode_t idx = PF_fetch_opcode(self->pf, &cursor);
2374 opcode_t op = PF_fetch_opcode(self->pf, &cursor);
2375
2376 if (0 > op || op >= entry->lib->op_count)
2377 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2378 "opcode index out of bounds on library `%s'. Found %d, expected 0 to %d",
2379 entry->lib->name, op, entry->lib->op_count - 1);
2380
2381 if (0 > idx || (size_t)idx >= byte_code->op_count)
2382 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2383 "op table index out of bounds for entry from library `%s'."
2384 " Found %d, expected 0 to %d",
2385 entry->lib->name, idx, byte_code->op_count - 1);
2386
2387 if (byte_code->op_func_table[idx])
2388 Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_MALFORMED_PACKFILE,
2389 "duplicate entries in optable");
2390
2391 entry->table_ops[j] = idx;
2392 entry->lib_ops[j] = op;
2393 byte_code->op_func_table[idx] = entry->lib->op_func_table[op];
2394 byte_code->op_info_table[idx] = &entry->lib->op_info_table[op];
2395 }
2396 }
2397 }
2398
2399 if (total_ops != byte_code->op_count)
2400 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2401 "wrong number of ops decoded for optable. Decoded %d, but expected %d",
2402 total_ops, byte_code->op_count);
2403
2404 return cursor;
2405 }
2406
2407 /*
2408
2409 =back
2410
2411 =head2 Debug Info
2412
2413 =over 4
2414
2415 =item C<static void pf_debug_destroy(PARROT_INTERP, PackFile_Segment *self)>
2416
2417 Destroys the C<PackFile_Debug> segment C<self>.
2418
2419 =cut
2420
2421 */
2422
2423 static void
pf_debug_destroy(PARROT_INTERP,ARGMOD (PackFile_Segment * self))2424 pf_debug_destroy(PARROT_INTERP, ARGMOD(PackFile_Segment *self))
2425 {
2426 ASSERT_ARGS(pf_debug_destroy)
2427 PackFile_Debug * const debug = (PackFile_Debug *) self;
2428
2429 /* Free mappings pointer array. */
2430 mem_gc_free(interp, debug->mappings);
2431 debug->mappings = NULL;
2432 debug->num_mappings = 0;
2433 }
2434
2435
2436 /*
2437
2438 =item C<static PackFile_Segment * pf_debug_new(PARROT_INTERP)>
2439
2440 Creates and returns a new C<PackFile_Debug> segment.
2441
2442 =cut
2443
2444 */
2445
2446 PARROT_WARN_UNUSED_RESULT
2447 PARROT_CANNOT_RETURN_NULL
2448 static PackFile_Segment *
pf_debug_new(PARROT_INTERP)2449 pf_debug_new(PARROT_INTERP)
2450 {
2451 ASSERT_ARGS(pf_debug_new)
2452 PackFile_Debug * const debug = mem_gc_allocate_zeroed_typed(interp, PackFile_Debug);
2453
2454 /* don't create initial mappings here; they'll get overwritten later */
2455
2456 return (PackFile_Segment *)debug;
2457 }
2458
2459
2460 /*
2461
2462 =item C<static size_t pf_debug_packed_size(PARROT_INTERP, PackFile_Segment
2463 *self)>
2464
2465 Returns the size of the C<PackFile_Debug> segment's filename in C<opcode_t>
2466 units.
2467
2468 =cut
2469
2470 */
2471
2472 static size_t
pf_debug_packed_size(SHIM_INTERP,ARGMOD (PackFile_Segment * self))2473 pf_debug_packed_size(SHIM_INTERP, ARGMOD(PackFile_Segment *self))
2474 {
2475 ASSERT_ARGS(pf_debug_packed_size)
2476 PackFile_Debug * const debug = (PackFile_Debug *)self;
2477
2478 return (debug->num_mappings*2) + 1;
2479 }
2480
2481
2482 /*
2483
2484 =item C<static opcode_t * pf_debug_pack(PARROT_INTERP, PackFile_Segment *self,
2485 opcode_t *cursor)>
2486
2487 Packs the debug segment, using the given cursor.
2488
2489 =cut
2490
2491 */
2492
2493 PARROT_WARN_UNUSED_RESULT
2494 PARROT_CANNOT_RETURN_NULL
2495 static opcode_t *
pf_debug_pack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGOUT (opcode_t * cursor))2496 pf_debug_pack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGOUT(opcode_t *cursor))
2497 {
2498 ASSERT_ARGS(pf_debug_pack)
2499 PackFile_Debug * const debug = (PackFile_Debug *)self;
2500 const int n = debug->num_mappings;
2501 int i;
2502
2503 if (n > 0 && debug->mappings == NULL)
2504 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2505 "No mappings but non zero num mappings(%I)", n);
2506
2507 /* Store number of mappings. */
2508 *cursor++ = n;
2509
2510 /* Now store each mapping. */
2511 for (i = 0; i < n; ++i) {
2512 /* Bytecode offset and filename. */
2513 *cursor++ = debug->mappings[i].offset;
2514 *cursor++ = debug->mappings[i].filename;
2515 }
2516
2517 return cursor;
2518 }
2519
2520
2521 /*
2522
2523 =item C<static const opcode_t * pf_debug_unpack(PARROT_INTERP, PackFile_Segment
2524 *self, const opcode_t *cursor)>
2525
2526 Unpacks a debug segment into a PackFile_Debug structure, given the cursor.
2527
2528 =cut
2529
2530 */
2531
2532 PARROT_WARN_UNUSED_RESULT
2533 PARROT_CANNOT_RETURN_NULL
2534 static const opcode_t *
pf_debug_unpack(PARROT_INTERP,ARGMOD (PackFile_Segment * self),ARGIN (const opcode_t * cursor))2535 pf_debug_unpack(PARROT_INTERP, ARGMOD(PackFile_Segment *self), ARGIN(const opcode_t *cursor))
2536 {
2537 ASSERT_ARGS(pf_debug_unpack)
2538 PackFile_Debug * const debug = (PackFile_Debug *)self;
2539 PackFile_ByteCode *code;
2540 int i;
2541
2542 /* For some reason, we store the source file name in the segment
2543 name. So we can't find the bytecode seg without knowing the filename.
2544 But with the new scheme we can have many file names. For now, just
2545 base this on the name of the debug segment. */
2546 STRING *code_name;
2547 size_t str_len;
2548
2549 /* Number of mappings. */
2550 debug->num_mappings = PF_fetch_opcode(self->pf, &cursor);
2551
2552 /* Allocate space for mappings vector. */
2553 debug->mappings = mem_gc_allocate_n_zeroed_typed(interp,
2554 debug->num_mappings, PackFile_DebugFilenameMapping);
2555
2556 /* Read in each mapping. */
2557 for (i = 0; i < debug->num_mappings; ++i) {
2558 /* Get offset and filename type. */
2559 debug->mappings[i].offset = PF_fetch_opcode(self->pf, &cursor);
2560 debug->mappings[i].filename = PF_fetch_opcode(self->pf, &cursor);
2561 }
2562
2563 /* find seg e.g. CODE_DB => CODE and attach it */
2564 str_len = Parrot_str_length(interp, debug->base.name);
2565 code_name = STRING_substr(interp, debug->base.name, 0, str_len - 3);
2566 code = (PackFile_ByteCode *)Parrot_pf_find_segment(interp, self->dir, code_name, 0);
2567
2568 if (!code || code->base.type != PF_BYTEC_SEG) {
2569 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
2570 "Code '%Ss' not found for debug segment '%Ss'",
2571 code_name, self->name);
2572 }
2573
2574 code->debugs = debug;
2575 debug->code = code;
2576
2577 return cursor;
2578 }
2579
2580
2581 /*
2582
2583 =item C<static void pf_debug_dump(PARROT_INTERP, const PackFile_Segment *self)>
2584
2585 Dumps a debug segment to a human readable form.
2586
2587 =cut
2588
2589 */
2590
2591 static void
pf_debug_dump(PARROT_INTERP,ARGIN (const PackFile_Segment * self))2592 pf_debug_dump(PARROT_INTERP, ARGIN(const PackFile_Segment *self))
2593 {
2594 ASSERT_ARGS(pf_debug_dump)
2595 const PackFile_Debug * const debug = (const PackFile_Debug *)self;
2596
2597 opcode_t i;
2598
2599 default_dump_header(interp, self);
2600
2601 Parrot_io_printf(interp, "\n mappings => [\n");
2602 for (i = 0; i < debug->num_mappings; ++i) {
2603 Parrot_io_printf(interp, " #%ld\n [\n", i);
2604 Parrot_io_printf(interp, " OFFSET => %ld,\n",
2605 debug->mappings[i].offset);
2606 Parrot_io_printf(interp, " FILENAME => %Ss\n",
2607 debug->code->const_table->str.constants[debug->mappings[i].filename]);
2608 Parrot_io_printf(interp, " ],\n");
2609 }
2610
2611 Parrot_io_printf(interp, " ]\n");
2612 }
2613
2614 /*
2615
2616 =item C<static void make_code_pointers(PackFile_Segment *seg)>
2617
2618 Makes compact/shorthand pointers.
2619
2620 The first segments read are the default segments.
2621
2622 =cut
2623
2624 */
2625
2626 static void
make_code_pointers(ARGMOD (PackFile_Segment * seg))2627 make_code_pointers(ARGMOD(PackFile_Segment *seg))
2628 {
2629 ASSERT_ARGS(make_code_pointers)
2630 PackFile * const pf = seg->pf;
2631
2632 switch (seg->type) {
2633 case PF_BYTEC_SEG:
2634 if (!pf->cur_cs)
2635 pf->cur_cs = (PackFile_ByteCode *)seg;
2636 break;
2637 case PF_CONST_SEG:
2638 if (!pf->cur_cs->const_table) {
2639 pf->cur_cs->const_table = (PackFile_ConstTable *)seg;
2640 pf->cur_cs->const_table->code = pf->cur_cs;
2641 }
2642 break;
2643 case PF_UNKNOWN_SEG:
2644 break;
2645 case PF_DEBUG_SEG:
2646 pf->cur_cs->debugs = (PackFile_Debug *)seg;
2647 pf->cur_cs->debugs->code = pf->cur_cs;
2648 break;
2649 default:
2650 break;
2651 }
2652 }
2653
2654 /*
2655
2656 =back
2657
2658 =cut
2659
2660 */
2661
2662 /*
2663 * Local variables:
2664 * c-file-style: "parrot"
2665 * End:
2666 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
2667 */
2668