2 Copyright (C) 2001-2010, Parrot Foundation.
3 This program is free software. It is subject to the same license as
9 src/packfile.c - Parrot PackFile API
13 This file contains all the functions required for the processing of the
14 structure of a PackFile. It is not intended to understand the byte code
15 stream itself, but merely to dissect and reconstruct data from the
16 various segments. See F<docs/pdds/pdd13_bytecode.pod> for information
17 about the structure of the frozen bytecode.
19 =head2 PackFile Manipulation Functions
27 #include "parrot/parrot.h"
28 #include "parrot/embed.h"
29 #include "parrot/extend.h"
30 #include "parrot/packfile.h"
31 #include "parrot/runcore_api.h"
32 #include "../compilers/imcc/imc.h"
33 #include "packfile.str"
34 #include "pmc/pmc_sub.h"
35 #include "pmc/pmc_key.h"
36 #include "pmc/pmc_callcontext.h"
38 /* HEADERIZER HFILE: include/parrot/packfile.h */
40 /* HEADERIZER BEGIN: static */
41 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
43 static void byte_code_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
44 __attribute__nonnull__(1)
45 __attribute__nonnull__(2)
48 PARROT_WARN_UNUSED_RESULT
49 PARROT_CANNOT_RETURN_NULL
50 static PackFile_Segment
* byte_code_new(PARROT_INTERP
,
54 __attribute__nonnull__(1);
56 PARROT_WARN_UNUSED_RESULT
57 PARROT_CANNOT_RETURN_NULL
58 static PackFile_Constant
* clone_constant(PARROT_INTERP
,
59 ARGIN(PackFile_Constant
*old_const
))
60 __attribute__nonnull__(1)
61 __attribute__nonnull__(2);
63 static void compile_or_load_file(PARROT_INTERP
,
65 enum_runtime_ft file_type
)
66 __attribute__nonnull__(1)
67 __attribute__nonnull__(2);
69 static void const_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
70 __attribute__nonnull__(1)
71 __attribute__nonnull__(2)
75 PARROT_CANNOT_RETURN_NULL
76 static PackFile_Segment
* const_new(PARROT_INTERP
,
80 __attribute__nonnull__(1);
82 PARROT_WARN_UNUSED_RESULT
83 PARROT_CANNOT_RETURN_NULL
84 static PackFile_Segment
* create_seg(PARROT_INTERP
,
85 ARGMOD(PackFile_Directory
*dir
),
88 ARGIN(STRING
*file_name
),
90 __attribute__nonnull__(1)
91 __attribute__nonnull__(2)
92 __attribute__nonnull__(4)
93 __attribute__nonnull__(5)
96 static void default_destroy(PARROT_INTERP
,
97 ARGFREE_NOTNULL(PackFile_Segment
*self
))
98 __attribute__nonnull__(1)
99 __attribute__nonnull__(2);
101 static void default_dump(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
102 __attribute__nonnull__(1)
103 __attribute__nonnull__(2);
105 PARROT_WARN_UNUSED_RESULT
106 PARROT_CANNOT_RETURN_NULL
107 static opcode_t
* default_pack(
108 ARGIN(const PackFile_Segment
*self
),
109 ARGOUT(opcode_t
*dest
))
110 __attribute__nonnull__(1)
111 __attribute__nonnull__(2)
112 FUNC_MODIFIES(*dest
);
114 static size_t default_packed_size(ARGIN(const PackFile_Segment
*self
))
115 __attribute__nonnull__(1);
117 PARROT_WARN_UNUSED_RESULT
118 PARROT_CAN_RETURN_NULL
119 static const opcode_t
* default_unpack(PARROT_INTERP
,
120 ARGMOD(PackFile_Segment
*self
),
121 ARGIN(const opcode_t
*cursor
))
122 __attribute__nonnull__(1)
123 __attribute__nonnull__(2)
124 __attribute__nonnull__(3)
125 FUNC_MODIFIES(*self
);
127 static void directory_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
128 __attribute__nonnull__(1)
129 __attribute__nonnull__(2)
130 FUNC_MODIFIES(*self
);
132 static void directory_dump(PARROT_INTERP
,
133 ARGIN(const PackFile_Segment
*self
))
134 __attribute__nonnull__(1)
135 __attribute__nonnull__(2);
137 PARROT_WARN_UNUSED_RESULT
138 PARROT_CANNOT_RETURN_NULL
139 static PackFile_Segment
* directory_new(PARROT_INTERP
,
143 __attribute__nonnull__(1);
145 PARROT_WARN_UNUSED_RESULT
146 PARROT_CANNOT_RETURN_NULL
147 static opcode_t
* directory_pack(PARROT_INTERP
,
148 ARGIN(PackFile_Segment
*self
),
149 ARGOUT(opcode_t
*cursor
))
150 __attribute__nonnull__(1)
151 __attribute__nonnull__(2)
152 __attribute__nonnull__(3)
153 FUNC_MODIFIES(*cursor
);
155 PARROT_WARN_UNUSED_RESULT
156 static size_t directory_packed_size(PARROT_INTERP
,
157 ARGMOD(PackFile_Segment
*self
))
158 __attribute__nonnull__(1)
159 __attribute__nonnull__(2)
160 FUNC_MODIFIES(*self
);
162 PARROT_WARN_UNUSED_RESULT
163 PARROT_CANNOT_RETURN_NULL
164 static const opcode_t
* directory_unpack(PARROT_INTERP
,
165 ARGMOD(PackFile_Segment
*segp
),
166 ARGIN(const opcode_t
*cursor
))
167 __attribute__nonnull__(1)
168 __attribute__nonnull__(2)
169 __attribute__nonnull__(3)
170 FUNC_MODIFIES(*segp
);
172 PARROT_WARN_UNUSED_RESULT
173 PARROT_CAN_RETURN_NULL
174 static PMC
* do_1_sub_pragma(PARROT_INTERP
,
175 ARGMOD(PMC
*sub_pmc
),
176 pbc_action_enum_t action
)
177 __attribute__nonnull__(1)
178 __attribute__nonnull__(2)
179 FUNC_MODIFIES(*sub_pmc
);
181 static INTVAL
find_const_iter(PARROT_INTERP
,
182 ARGIN(PackFile_Segment
*seg
),
183 ARGIN_NULLOK(void *user_data
))
184 __attribute__nonnull__(1)
185 __attribute__nonnull__(2);
187 PARROT_WARN_UNUSED_RESULT
188 PARROT_CANNOT_RETURN_NULL
189 static PackFile_Constant
** find_constants(PARROT_INTERP
,
190 ARGIN(PackFile_ConstTable
*ct
))
191 __attribute__nonnull__(1)
192 __attribute__nonnull__(2);
194 PARROT_WARN_UNUSED_RESULT
195 PARROT_CAN_RETURN_NULL
196 static PackFile_FixupEntry
* find_fixup(
197 ARGMOD(PackFile_FixupTable
*ft
),
199 ARGIN(const char *name
))
200 __attribute__nonnull__(1)
201 __attribute__nonnull__(3)
204 static INTVAL
find_fixup_iter(PARROT_INTERP
,
205 ARGIN(PackFile_Segment
*seg
),
206 ARGIN(void *user_data
))
207 __attribute__nonnull__(1)
208 __attribute__nonnull__(2)
209 __attribute__nonnull__(3);
211 static void fixup_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
212 __attribute__nonnull__(1)
213 __attribute__nonnull__(2)
214 FUNC_MODIFIES(*self
);
216 PARROT_WARN_UNUSED_RESULT
217 PARROT_CANNOT_RETURN_NULL
218 static PackFile_Segment
* fixup_new(PARROT_INTERP
,
222 __attribute__nonnull__(1);
224 PARROT_WARN_UNUSED_RESULT
225 PARROT_CANNOT_RETURN_NULL
226 static opcode_t
* fixup_pack(PARROT_INTERP
,
227 ARGIN(PackFile_Segment
*self
),
228 ARGOUT(opcode_t
*cursor
))
229 __attribute__nonnull__(1)
230 __attribute__nonnull__(2)
231 __attribute__nonnull__(3)
232 FUNC_MODIFIES(*cursor
);
234 static size_t fixup_packed_size(PARROT_INTERP
,
235 ARGMOD(PackFile_Segment
*self
))
236 __attribute__nonnull__(1)
237 __attribute__nonnull__(2)
238 FUNC_MODIFIES(*self
);
240 PARROT_WARN_UNUSED_RESULT
241 PARROT_CAN_RETURN_NULL
242 static const opcode_t
* fixup_unpack(PARROT_INTERP
,
243 ARGIN(PackFile_Segment
*seg
),
244 ARGIN(const opcode_t
*cursor
))
245 __attribute__nonnull__(1)
246 __attribute__nonnull__(2)
247 __attribute__nonnull__(3);
249 PARROT_CANNOT_RETURN_NULL
250 static PMC
* make_annotation_value_pmc(PARROT_INTERP
,
251 ARGIN(PackFile_Annotations
*self
),
254 __attribute__nonnull__(1)
255 __attribute__nonnull__(2);
257 static void make_code_pointers(ARGMOD(PackFile_Segment
*seg
))
258 __attribute__nonnull__(1)
261 static void mark_1_seg(PARROT_INTERP
, ARGMOD(PackFile_ConstTable
*ct
))
262 __attribute__nonnull__(1)
263 __attribute__nonnull__(2)
266 PARROT_WARN_UNUSED_RESULT
267 PARROT_CAN_RETURN_NULL
268 static PackFile
* PackFile_append_pbc(PARROT_INTERP
,
269 ARGIN_NULLOK(const char *filename
))
270 __attribute__nonnull__(1);
272 static void PackFile_set_header(ARGOUT(PackFile_Header
*header
))
273 __attribute__nonnull__(1)
274 FUNC_MODIFIES(*header
);
276 static void pf_debug_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
277 __attribute__nonnull__(1)
278 __attribute__nonnull__(2)
279 FUNC_MODIFIES(*self
);
281 static void pf_debug_dump(PARROT_INTERP
,
282 ARGIN(const PackFile_Segment
*self
))
283 __attribute__nonnull__(1)
284 __attribute__nonnull__(2);
286 PARROT_WARN_UNUSED_RESULT
287 PARROT_CANNOT_RETURN_NULL
288 static PackFile_Segment
* pf_debug_new(PARROT_INTERP
,
292 __attribute__nonnull__(1);
294 PARROT_WARN_UNUSED_RESULT
295 PARROT_CANNOT_RETURN_NULL
296 static opcode_t
* pf_debug_pack(PARROT_INTERP
,
297 ARGMOD(PackFile_Segment
*self
),
298 ARGOUT(opcode_t
*cursor
))
299 __attribute__nonnull__(1)
300 __attribute__nonnull__(2)
301 __attribute__nonnull__(3)
303 FUNC_MODIFIES(*cursor
);
305 static size_t pf_debug_packed_size(SHIM_INTERP
,
306 ARGIN(PackFile_Segment
*self
))
307 __attribute__nonnull__(2);
309 PARROT_WARN_UNUSED_RESULT
310 PARROT_CANNOT_RETURN_NULL
311 static const opcode_t
* pf_debug_unpack(PARROT_INTERP
,
312 ARGOUT(PackFile_Segment
*self
),
313 ARGIN(const opcode_t
*cursor
))
314 __attribute__nonnull__(1)
315 __attribute__nonnull__(2)
316 __attribute__nonnull__(3)
317 FUNC_MODIFIES(*self
);
319 static void pf_register_standard_funcs(PARROT_INTERP
, ARGMOD(PackFile
*pf
))
320 __attribute__nonnull__(1)
321 __attribute__nonnull__(2)
324 PARROT_IGNORABLE_RESULT
325 PARROT_CAN_RETURN_NULL
326 static PMC
* run_sub(PARROT_INTERP
, ARGIN(PMC
*sub_pmc
))
327 __attribute__nonnull__(1)
328 __attribute__nonnull__(2);
330 static void segment_init(PARROT_INTERP
,
331 ARGOUT(PackFile_Segment
*self
),
334 __attribute__nonnull__(1)
335 __attribute__nonnull__(2)
336 __attribute__nonnull__(3)
337 __attribute__nonnull__(4)
338 FUNC_MODIFIES(*self
);
340 static void sort_segs(ARGMOD(PackFile_Directory
*dir
))
341 __attribute__nonnull__(1)
344 static int sub_pragma(PARROT_INTERP
,
345 pbc_action_enum_t action
,
346 ARGIN(const PMC
*sub_pmc
))
347 __attribute__nonnull__(1)
348 __attribute__nonnull__(3);
350 #define ASSERT_ARGS_byte_code_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
351 PARROT_ASSERT_ARG(interp) \
352 , PARROT_ASSERT_ARG(self))
353 #define ASSERT_ARGS_byte_code_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
354 PARROT_ASSERT_ARG(interp))
355 #define ASSERT_ARGS_clone_constant __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
356 PARROT_ASSERT_ARG(interp) \
357 , PARROT_ASSERT_ARG(old_const))
358 #define ASSERT_ARGS_compile_or_load_file __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
359 PARROT_ASSERT_ARG(interp) \
360 , PARROT_ASSERT_ARG(path))
361 #define ASSERT_ARGS_const_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
362 PARROT_ASSERT_ARG(interp) \
363 , PARROT_ASSERT_ARG(self))
364 #define ASSERT_ARGS_const_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
365 PARROT_ASSERT_ARG(interp))
366 #define ASSERT_ARGS_create_seg __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
367 PARROT_ASSERT_ARG(interp) \
368 , PARROT_ASSERT_ARG(dir) \
369 , PARROT_ASSERT_ARG(name) \
370 , PARROT_ASSERT_ARG(file_name))
371 #define ASSERT_ARGS_default_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
372 PARROT_ASSERT_ARG(interp) \
373 , PARROT_ASSERT_ARG(self))
374 #define ASSERT_ARGS_default_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
375 PARROT_ASSERT_ARG(interp) \
376 , PARROT_ASSERT_ARG(self))
377 #define ASSERT_ARGS_default_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
378 PARROT_ASSERT_ARG(self) \
379 , PARROT_ASSERT_ARG(dest))
380 #define ASSERT_ARGS_default_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
381 PARROT_ASSERT_ARG(self))
382 #define ASSERT_ARGS_default_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
383 PARROT_ASSERT_ARG(interp) \
384 , PARROT_ASSERT_ARG(self) \
385 , PARROT_ASSERT_ARG(cursor))
386 #define ASSERT_ARGS_directory_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
387 PARROT_ASSERT_ARG(interp) \
388 , PARROT_ASSERT_ARG(self))
389 #define ASSERT_ARGS_directory_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
390 PARROT_ASSERT_ARG(interp) \
391 , PARROT_ASSERT_ARG(self))
392 #define ASSERT_ARGS_directory_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
393 PARROT_ASSERT_ARG(interp))
394 #define ASSERT_ARGS_directory_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
395 PARROT_ASSERT_ARG(interp) \
396 , PARROT_ASSERT_ARG(self) \
397 , PARROT_ASSERT_ARG(cursor))
398 #define ASSERT_ARGS_directory_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
399 PARROT_ASSERT_ARG(interp) \
400 , PARROT_ASSERT_ARG(self))
401 #define ASSERT_ARGS_directory_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
402 PARROT_ASSERT_ARG(interp) \
403 , PARROT_ASSERT_ARG(segp) \
404 , PARROT_ASSERT_ARG(cursor))
405 #define ASSERT_ARGS_do_1_sub_pragma __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
406 PARROT_ASSERT_ARG(interp) \
407 , PARROT_ASSERT_ARG(sub_pmc))
408 #define ASSERT_ARGS_find_const_iter __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
409 PARROT_ASSERT_ARG(interp) \
410 , PARROT_ASSERT_ARG(seg))
411 #define ASSERT_ARGS_find_constants __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
412 PARROT_ASSERT_ARG(interp) \
413 , PARROT_ASSERT_ARG(ct))
414 #define ASSERT_ARGS_find_fixup __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
415 PARROT_ASSERT_ARG(ft) \
416 , PARROT_ASSERT_ARG(name))
417 #define ASSERT_ARGS_find_fixup_iter __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
418 PARROT_ASSERT_ARG(interp) \
419 , PARROT_ASSERT_ARG(seg) \
420 , PARROT_ASSERT_ARG(user_data))
421 #define ASSERT_ARGS_fixup_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
422 PARROT_ASSERT_ARG(interp) \
423 , PARROT_ASSERT_ARG(self))
424 #define ASSERT_ARGS_fixup_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
425 PARROT_ASSERT_ARG(interp))
426 #define ASSERT_ARGS_fixup_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
427 PARROT_ASSERT_ARG(interp) \
428 , PARROT_ASSERT_ARG(self) \
429 , PARROT_ASSERT_ARG(cursor))
430 #define ASSERT_ARGS_fixup_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
431 PARROT_ASSERT_ARG(interp) \
432 , PARROT_ASSERT_ARG(self))
433 #define ASSERT_ARGS_fixup_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
434 PARROT_ASSERT_ARG(interp) \
435 , PARROT_ASSERT_ARG(seg) \
436 , PARROT_ASSERT_ARG(cursor))
437 #define ASSERT_ARGS_make_annotation_value_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
438 PARROT_ASSERT_ARG(interp) \
439 , PARROT_ASSERT_ARG(self))
440 #define ASSERT_ARGS_make_code_pointers __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
441 PARROT_ASSERT_ARG(seg))
442 #define ASSERT_ARGS_mark_1_seg __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
443 PARROT_ASSERT_ARG(interp) \
444 , PARROT_ASSERT_ARG(ct))
445 #define ASSERT_ARGS_PackFile_append_pbc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
446 PARROT_ASSERT_ARG(interp))
447 #define ASSERT_ARGS_PackFile_set_header __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
448 PARROT_ASSERT_ARG(header))
449 #define ASSERT_ARGS_pf_debug_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
450 PARROT_ASSERT_ARG(interp) \
451 , PARROT_ASSERT_ARG(self))
452 #define ASSERT_ARGS_pf_debug_dump __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
453 PARROT_ASSERT_ARG(interp) \
454 , PARROT_ASSERT_ARG(self))
455 #define ASSERT_ARGS_pf_debug_new __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
456 PARROT_ASSERT_ARG(interp))
457 #define ASSERT_ARGS_pf_debug_pack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
458 PARROT_ASSERT_ARG(interp) \
459 , PARROT_ASSERT_ARG(self) \
460 , PARROT_ASSERT_ARG(cursor))
461 #define ASSERT_ARGS_pf_debug_packed_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
462 PARROT_ASSERT_ARG(self))
463 #define ASSERT_ARGS_pf_debug_unpack __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
464 PARROT_ASSERT_ARG(interp) \
465 , PARROT_ASSERT_ARG(self) \
466 , PARROT_ASSERT_ARG(cursor))
467 #define ASSERT_ARGS_pf_register_standard_funcs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
468 PARROT_ASSERT_ARG(interp) \
469 , PARROT_ASSERT_ARG(pf))
470 #define ASSERT_ARGS_run_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
471 PARROT_ASSERT_ARG(interp) \
472 , PARROT_ASSERT_ARG(sub_pmc))
473 #define ASSERT_ARGS_segment_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
474 PARROT_ASSERT_ARG(interp) \
475 , PARROT_ASSERT_ARG(self) \
476 , PARROT_ASSERT_ARG(pf) \
477 , PARROT_ASSERT_ARG(name))
478 #define ASSERT_ARGS_sort_segs __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
479 PARROT_ASSERT_ARG(dir))
480 #define ASSERT_ARGS_sub_pragma __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
481 PARROT_ASSERT_ARG(interp) \
482 , PARROT_ASSERT_ARG(sub_pmc))
483 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
484 /* HEADERIZER END: static */
490 1 op - Size of theop array
491 See pdd13_bytecode: Packfile Segment Header
493 #define SEGMENT_HEADER_SIZE 4
495 /* offset not in ptr diff, but in byte */
496 #define OFFS(pf, cursor) ((pf) ? ((const char *)(cursor) - (const char *)((pf)->src)) : 0)
498 * Possible values for ALIGN_16
501 * e.g. reading 4 byte wordsize on 8 byte wordsize: possible ptrs end in 0 4 8 c.
502 * offs(c)/8 => 4/8 = 0 => impossible to align with 8 byte ptr.
503 * Limitation TT #254: ALIGN_16 may only be used native, e.g. in the writer,
504 * but not with 64bit reading 32bit!
506 #define ROUND_16(val) (((val) & 0xf) ? 16 - ((val) & 0xf) : 0)
507 #define ALIGN_16(pf, cursor) \
508 (cursor) += ROUND_16(OFFS(pf, cursor))/sizeof (opcode_t)
509 /* pad to 16 in bytes */
510 #define PAD_16_B(size) ((size) % 16 ? 16 - (size) % 16 : 0)
516 =item C<void Parrot_trace_eprintf(const char *s, ...)>
518 Print out an error message. Passes arguments directly to C<vfprintf>.
525 Parrot_trace_eprintf(ARGIN(const char *s
), ...)
527 ASSERT_ARGS(Parrot_trace_eprintf
)
530 vfprintf(stderr
, s
, args
);
538 =item C<void PackFile_destroy(PARROT_INTERP, PackFile *pf)>
540 Deletes a C<PackFile>.
548 PackFile_destroy(PARROT_INTERP
, ARGMOD(PackFile
*pf
))
550 ASSERT_ARGS(PackFile_destroy
)
552 #ifdef PARROT_HAS_HEADER_SYSMMAN
553 if (pf
->is_mmap_ped
) {
555 /* Cast the result to void to avoid a warning with
556 * some not-so-standard mmap headers
558 munmap((void *)PARROT_const_cast(opcode_t
*, pf
->src
), pf
->size
);
562 mem_gc_free(interp
, pf
->header
);
564 mem_gc_free(interp
, pf
->dirp
);
566 PackFile_Segment_destroy(interp
, &pf
->directory
.base
);
573 =item C<static void make_code_pointers(PackFile_Segment *seg)>
575 Makes compact/shorthand pointers.
577 The first segments read are the default segments.
584 make_code_pointers(ARGMOD(PackFile_Segment
*seg
))
586 ASSERT_ARGS(make_code_pointers
)
587 PackFile
* const pf
= seg
->pf
;
592 pf
->cur_cs
= (PackFile_ByteCode
*)seg
;
595 if (!pf
->cur_cs
->fixups
) {
596 pf
->cur_cs
->fixups
= (PackFile_FixupTable
*)seg
;
597 pf
->cur_cs
->fixups
->code
= pf
->cur_cs
;
601 if (!pf
->cur_cs
->const_table
) {
602 pf
->cur_cs
->const_table
= (PackFile_ConstTable
*)seg
;
603 pf
->cur_cs
->const_table
->code
= pf
->cur_cs
;
609 pf
->cur_cs
->debugs
= (PackFile_Debug
*)seg
;
610 pf
->cur_cs
->debugs
->code
= pf
->cur_cs
;
620 =item C<static int sub_pragma(PARROT_INTERP, pbc_action_enum_t action, const PMC
623 Checks B<sub_pmc>'s pragmas (e.g. flags like C<:load>, C<:main>, etc.)
624 returning 1 if the sub should be run for C<action>, a C<pbc_action_enum_t>.
631 sub_pragma(PARROT_INTERP
, pbc_action_enum_t action
, ARGIN(const PMC
*sub_pmc
))
633 ASSERT_ARGS(sub_pragma
)
635 /* Note: the const casting is only needed because of the
636 * internal details of the Sub_comp macros.
637 * The assumption is that the TEST versions are in fact const,
638 * so the casts are safe.
639 * These casts are a quick fix to allow parrot build with c++,
640 * a refactor of the macros will be a cleaner solution. */
642 Parrot_Sub_attributes
*sub
;
644 const int pragmas
= PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_MASK
645 & ~SUB_FLAG_IS_OUTER
;
646 PMC_get_sub(interp
, PARROT_const_cast(PMC
*, sub_pmc
), sub
);
647 if (!pragmas
&& !Sub_comp_INIT_TEST(sub
))
653 /* denote MAIN entry in first loaded PASM */
654 if (interp
->resume_flag
& RESUME_INITIAL
)
657 /* :init functions need to be called at MAIN time, so return 1 */
658 /* symreg.h:P_INIT */
659 if (Sub_comp_INIT_TEST(sub
))
664 /* symreg.h:P_LOAD */
665 if (pragmas
& SUB_FLAG_PF_LOAD
)
672 if (pragmas
& (SUB_FLAG_PF_IMMEDIATE
| SUB_FLAG_PF_POSTCOMP
))
681 =item C<static PMC* run_sub(PARROT_INTERP, PMC *sub_pmc)>
683 Runs the B<sub_pmc> due to its B<:load>, B<:immediate>, ... pragma
689 PARROT_IGNORABLE_RESULT
690 PARROT_CAN_RETURN_NULL
692 run_sub(PARROT_INTERP
, ARGIN(PMC
*sub_pmc
))
695 Parrot_runcore_t
*old_core
= interp
->run_core
;
696 PMC
*retval
= PMCNULL
;
698 Parrot_pcc_set_constants(interp
, CURRENT_CONTEXT(interp
),
699 interp
->code
->const_table
->constants
);
701 Parrot_pcc_invoke_sub_from_c_args(interp
, sub_pmc
, "->P", &retval
);
702 interp
->run_core
= old_core
;
710 =item C<static PMC* do_1_sub_pragma(PARROT_INTERP, PMC *sub_pmc,
711 pbc_action_enum_t action)>
713 Runs autoloaded or immediate bytecode, marking the MAIN subroutine entry.
719 PARROT_WARN_UNUSED_RESULT
720 PARROT_CAN_RETURN_NULL
722 do_1_sub_pragma(PARROT_INTERP
, ARGMOD(PMC
*sub_pmc
), pbc_action_enum_t action
)
724 ASSERT_ARGS(do_1_sub_pragma
)
725 Parrot_Sub_attributes
*sub
;
726 PMC_get_sub(interp
, sub_pmc
, sub
);
730 /* run IMMEDIATE sub */
731 if (PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_IMMEDIATE
) {
732 void *lo_var_ptr
= interp
->lo_var_ptr
;
735 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_IMMEDIATE
;
736 result
= run_sub(interp
, sub_pmc
);
738 /* reset initial flag so MAIN detection works
739 * and reset lo_var_ptr to prev */
740 interp
->resume_flag
= RESUME_INITIAL
;
741 interp
->lo_var_ptr
= lo_var_ptr
;
746 /* run POSTCOMP sub */
747 if (PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_POSTCOMP
) {
748 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_POSTCOMP
;
749 run_sub(interp
, sub_pmc
);
751 /* reset initial flag so MAIN detection works */
752 interp
->resume_flag
= RESUME_INITIAL
;
758 if (PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_LOAD
) {
759 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_LOAD
;
761 /* if loaded no need for init */
762 Sub_comp_INIT_CLEAR(sub
);
763 run_sub(interp
, sub_pmc
);
767 if (PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_MAIN
) {
768 if ((interp
->resume_flag
& RESUME_INITIAL
)
769 && interp
->resume_offset
== 0) {
770 void *ptr
= VTABLE_get_pointer(interp
, sub_pmc
);
771 const ptrdiff_t code
= (ptrdiff_t) sub
->seg
->base
.data
;
773 interp
->resume_offset
= ((ptrdiff_t)ptr
- code
)
774 / sizeof (opcode_t
*);
776 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_MAIN
;
777 Parrot_pcc_set_sub(interp
, CURRENT_CONTEXT(interp
), sub_pmc
);
780 Parrot_warn(interp
, PARROT_WARNINGS_ALL_FLAG
,
781 ":main sub not allowed\n");
785 /* run :init tagged functions */
786 if (action
== PBC_MAIN
&& Sub_comp_INIT_TEST(sub
)) {
787 /* if loaded no need for init */
788 Sub_comp_INIT_CLEAR(sub
);
790 /* if inited no need for load */
791 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_LOAD
;
793 run_sub(interp
, sub_pmc
);
794 interp
->resume_flag
= RESUME_INITIAL
;
805 =item C<static void mark_1_seg(PARROT_INTERP, PackFile_ConstTable *ct)>
807 While the PMCs should be constant, their possible contents such as
808 properties aren't constructed const, so we have to mark them.
815 mark_1_seg(PARROT_INTERP
, ARGMOD(PackFile_ConstTable
*ct
))
817 ASSERT_ARGS(mark_1_seg
)
818 PackFile_Constant
** const constants
= find_constants(interp
, ct
);
821 for (i
= 0; i
< ct
->const_count
; ++i
) {
824 switch (constants
[i
]->type
) {
827 pmc
= constants
[i
]->u
.key
;
828 Parrot_gc_mark_PMC_alive(interp
, pmc
);
831 string
= constants
[i
]->u
.string
;
832 Parrot_gc_mark_STRING_alive(interp
, string
);
844 =item C<static INTVAL find_const_iter(PARROT_INTERP, PackFile_Segment *seg, void
847 Iterates over a PackFile_Directory, marking any constant segments. Internal
855 find_const_iter(PARROT_INTERP
, ARGIN(PackFile_Segment
*seg
),
856 ARGIN_NULLOK(void *user_data
))
858 ASSERT_ARGS(find_const_iter
)
859 if (seg
->type
== PF_DIR_SEG
)
860 PackFile_map_segments(interp
, (const PackFile_Directory
*)seg
,
861 find_const_iter
, user_data
);
862 else if (seg
->type
== PF_CONST_SEG
)
863 mark_1_seg(interp
, (PackFile_ConstTable
*)seg
);
871 =item C<void mark_const_subs(PARROT_INTERP)>
873 Iterates over all directories and PackFile_Segments, finding and marking any
881 mark_const_subs(PARROT_INTERP
)
883 ASSERT_ARGS(mark_const_subs
)
884 PackFile_Directory
*dir
;
886 PackFile
* const self
= interp
->initial_pf
;
891 /* locate top level dir */
892 dir
= &self
->directory
;
894 /* iterate over all dir/segs */
895 PackFile_map_segments(interp
, dir
, find_const_iter
, NULL
);
901 =item C<void do_sub_pragmas(PARROT_INTERP, PackFile_ByteCode *self,
902 pbc_action_enum_t action, PMC *eval_pmc)>
904 C<action> is one of C<PBC_PBC>, C<PBC_LOADED>, C<PBC_INIT>, or C<PBC_MAIN>.
905 These determine which subs get executed at this point. Some rules:
907 :immediate subs always execute immediately
908 :postcomp subs always execute immediately
909 :main subs execute when we have the PBC_MAIN or PBC_PBC actions
910 :init subs execute when :main does
911 :load subs execute on PBC_LOAD
913 Also store the C<eval_pmc> in the sub structure, so that the eval PMC is kept
914 alive by living subs.
922 do_sub_pragmas(PARROT_INTERP
, ARGIN(PackFile_ByteCode
*self
),
923 pbc_action_enum_t action
, ARGIN_NULLOK(PMC
*eval_pmc
))
925 ASSERT_ARGS(do_sub_pragmas
)
926 PackFile_FixupTable
* const ft
= self
->fixups
;
927 PackFile_ConstTable
* const ct
= self
->const_table
;
930 TRACE_PRINTF(("PackFile: do_sub_pragmas (action=%d)\n", action
));
932 for (i
= 0; i
< ft
->fixup_count
; ++i
) {
933 switch (ft
->fixups
[i
].type
) {
936 /* offset is an index into const_table holding the Sub PMC */
938 Parrot_Sub_attributes
*sub
;
939 const opcode_t ci
= ft
->fixups
[i
].offset
;
941 if (ci
< 0 || ci
>= ct
->const_count
)
942 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
943 "Illegal fixup offset (%d) in enum_fixup_sub");
945 sub_pmc
= ct
->constants
[ci
]->u
.key
;
946 PMC_get_sub(interp
, sub_pmc
, sub
);
947 sub
->eval_pmc
= eval_pmc
;
949 if (((PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_MASK
)
950 || (Sub_comp_get_FLAGS(sub
) & SUB_COMP_FLAG_MASK
))
951 && sub_pragma(interp
, action
, sub_pmc
)) {
952 PMC
* const result
= do_1_sub_pragma(interp
, sub_pmc
,
955 /* replace Sub PMC with computation results */
956 if (action
== PBC_IMMEDIATE
&& !PMC_IS_NULL(result
)) {
957 ft
->fixups
[i
].type
= enum_fixup_none
;
958 ct
->constants
[ci
]->u
.key
= result
;
973 =item C<opcode_t PackFile_unpack(PARROT_INTERP, PackFile *self, const opcode_t
974 *packed, size_t packed_size)>
976 Unpacks a C<PackFile> from a block of memory, ensuring that the magic number is
977 valid and that Parrot can read this bytecode version, Parrot, and performing
978 any required endian and word size transforms.
980 Returns size of unpacked opcodes if everything is okay, else zero (0).
987 PARROT_WARN_UNUSED_RESULT
989 PackFile_unpack(PARROT_INTERP
, ARGMOD(PackFile
*self
),
990 ARGIN(const opcode_t
*packed
), size_t packed_size
)
992 ASSERT_ARGS(PackFile_unpack
)
993 PackFile_Header
* const header
= self
->header
;
994 const opcode_t
*cursor
;
995 int header_read_length
;
998 PackFile
* const pf
= self
;
1001 if (packed_size
< PACKFILE_HEADER_BYTES
) {
1002 Parrot_io_eprintf(NULL
, "PackFile_unpack: "
1003 "Buffer length %d is shorter than PACKFILE_HEADER_BYTES %d\n",
1004 packed_size
, PACKFILE_HEADER_BYTES
);
1009 self
->size
= packed_size
;
1011 /* Extract the header. */
1012 memcpy(header
, packed
, PACKFILE_HEADER_BYTES
);
1014 /* Ensure the magic is correct. */
1015 if (memcmp(header
->magic
, "\376PBC\r\n\032\n", 8) != 0) {
1016 Parrot_io_eprintf(NULL
, "PackFile_unpack: "
1017 "This is not a valid Parrot bytecode file\n");
1021 /* Ensure the bytecode version is one we can read. Currently, we only
1022 * support bytecode versions matching the current one.
1024 * tools/dev/pbc_header.pl --upd t/native_pbc/(ASTERISK).pbc
1025 * stamps version and fingerprint in the native tests.
1026 * NOTE: (ASTERISK) is *, we don't want to fool the C preprocessor. */
1027 if (header
->bc_major
!= PARROT_PBC_MAJOR
1028 || header
->bc_minor
!= PARROT_PBC_MINOR
) {
1029 Parrot_io_eprintf(NULL
, "PackFile_unpack: This Parrot cannot read "
1030 "bytecode files with version %d.%d.\n",
1031 header
->bc_major
, header
->bc_minor
);
1032 if (!(self
->options
& PFOPT_UTILS
))
1036 /* Check wordsize, byte order and floating point number type are valid. */
1037 if (header
->wordsize
!= 4 && header
->wordsize
!= 8) {
1038 Parrot_io_eprintf(NULL
, "PackFile_unpack: Invalid wordsize %d\n",
1043 if (header
->byteorder
!= 0 && header
->byteorder
!= 1) {
1044 Parrot_io_eprintf(NULL
, "PackFile_unpack: Invalid byte ordering %d\n",
1049 if (header
->floattype
> FLOATTYPE_MAX
) {
1050 Parrot_io_eprintf(NULL
, "PackFile_unpack: Invalid floattype %d\n",
1055 /* Describe what was read for debugging. */
1056 TRACE_PRINTF(("PackFile_unpack: Wordsize %d.\n", header
->wordsize
));
1057 TRACE_PRINTF(("PackFile_unpack: Floattype %d (%s).\n",
1059 header
->floattype
== FLOATTYPE_8
1061 : header
->floattype
== FLOATTYPE_16
1063 : FLOATTYPE_12_NAME
));
1064 TRACE_PRINTF(("PackFile_unpack: Byteorder %d (%sendian).\n",
1065 header
->byteorder
, header
->byteorder
? "big " : "little-"));
1067 /* Check the UUID type is valid and, if needed, read a UUID. */
1068 if (header
->uuid_type
== 0) {
1069 /* No UUID; fine, nothing more to do. */
1071 else if (header
->uuid_type
== 1) {
1072 if (packed_size
< (size_t) PACKFILE_HEADER_BYTES
+ header
->uuid_size
) {
1073 Parrot_io_eprintf(NULL
, "PackFile_unpack: "
1074 "Buffer length %d is shorter than PACKFILE_HEADER_BYTES + uuid_size %d\n",
1075 packed_size
, PACKFILE_HEADER_BYTES
+ header
->uuid_size
);
1080 /* Read in the UUID. We'll put it in a NULL-terminated string, just in
1081 * case people use it that way. */
1082 header
->uuid_data
= mem_gc_allocate_n_typed(interp
,
1083 header
->uuid_size
+ 1, unsigned char);
1085 memcpy(header
->uuid_data
, packed
+ PACKFILE_HEADER_BYTES
,
1088 /* NULL terminate */
1089 header
->uuid_data
[header
->uuid_size
] = '\0';
1092 /* Don't know this UUID type. */
1093 Parrot_io_eprintf(NULL
, "PackFile_unpack: Invalid UUID type %d\n",
1096 /* Set cursor to position after what we've read, allowing for padding to a
1097 * 16 byte boundary. */
1098 header_read_length
= PACKFILE_HEADER_BYTES
+ header
->uuid_size
;
1099 header_read_length
+= PAD_16_B(header_read_length
);
1100 cursor
= packed
+ (header_read_length
/ sizeof (opcode_t
));
1101 TRACE_PRINTF(("PackFile_unpack: pad=%d\n",
1102 (char *)cursor
- (char *)packed
));
1104 /* Set what transforms we need to do when reading the rest of the file. */
1105 PackFile_assign_transforms(self
);
1107 if (self
->options
& PFOPT_PMC_FREEZE_ONLY
)
1108 return cursor
- packed
;
1110 /* Directory format. */
1111 header
->dir_format
= PF_fetch_opcode(self
, &cursor
);
1113 if (header
->dir_format
!= PF_DIR_FORMAT
) {
1114 Parrot_io_eprintf(NULL
, "PackFile_unpack: Dir format was %d not %d\n",
1115 header
->dir_format
, PF_DIR_FORMAT
);
1120 TRACE_PRINTF(("PackFile_unpack: 3 words padding.\n"));
1121 padding
= PF_fetch_opcode(self
, &cursor
);
1122 padding
= PF_fetch_opcode(self
, &cursor
);
1123 padding
= PF_fetch_opcode(self
, &cursor
);
1126 TRACE_PRINTF(("PackFile_unpack: Directory read, offset %d.\n",
1127 (INTVAL
)cursor
- (INTVAL
)packed
));
1128 self
->directory
.base
.file_offset
= (INTVAL
)cursor
- (INTVAL
)self
->src
;
1129 if (self
->options
& PFOPT_HEADERONLY
)
1130 return cursor
- packed
;
1132 /* now unpack dir, which unpacks its contents ... */
1133 Parrot_block_GC_mark(interp
);
1134 cursor
= PackFile_Segment_unpack(interp
,
1135 &self
->directory
.base
, cursor
);
1136 Parrot_unblock_GC_mark(interp
);
1138 #ifdef PARROT_HAS_HEADER_SYSMMAN
1139 if (self
->is_mmap_ped
1140 && (self
->need_endianize
|| self
->need_wordsize
)) {
1142 /* Cast the result to void to avoid a warning with
1143 * some not-so-standard mmap headers
1145 munmap((void *)PARROT_const_cast(opcode_t
*, self
->src
), self
->size
);
1146 self
->is_mmap_ped
= 0;
1150 TRACE_PRINTF(("PackFile_unpack: Unpack done.\n"));
1152 return cursor
- packed
;
1158 =item C<INTVAL PackFile_map_segments(PARROT_INTERP, const PackFile_Directory
1159 *dir, PackFile_map_segments_func_t callback, void *user_data)>
1161 Calls the callback function C<callback> for each segment in the directory
1162 C<dir> called. The pointer C<user_data> is included in each call.
1164 If a callback returns non-zero, segment processing stops, returning this value.
1172 PackFile_map_segments(PARROT_INTERP
, ARGIN(const PackFile_Directory
*dir
),
1173 PackFile_map_segments_func_t callback
,
1174 ARGIN_NULLOK(void *user_data
))
1176 ASSERT_ARGS(PackFile_map_segments
)
1179 for (i
= 0; i
< dir
->num_segments
; ++i
) {
1180 const INTVAL ret
= callback(interp
, dir
->segments
[i
], user_data
);
1191 =item C<void PackFile_add_segment(PARROT_INTERP, PackFile_Directory *dir,
1192 PackFile_Segment *seg)>
1194 Adds the Segment C<seg> to the directory C<dir>. The PackFile becomes the
1195 owner of the segment; it gets destroyed when the PackFile does.
1203 PackFile_add_segment(PARROT_INTERP
, ARGMOD(PackFile_Directory
*dir
),
1204 ARGMOD(PackFile_Segment
*seg
))
1206 ASSERT_ARGS(PackFile_add_segment
)
1207 dir
->segments
= mem_gc_realloc_n_typed_zeroed(interp
, dir
->segments
,
1208 dir
->num_segments
+ 1, dir
->num_segments
, PackFile_Segment
*);
1209 dir
->segments
[dir
->num_segments
] = seg
;
1210 ++dir
->num_segments
;
1219 =item C<PackFile_Segment * PackFile_find_segment(PARROT_INTERP,
1220 PackFile_Directory *dir, const STRING *name, int sub_dir)>
1222 Finds the segment with the name C<name> in the C<PackFile_Directory> if
1223 C<sub_dir> is true, searches directories recursively. The returned segment is
1224 still owned by the C<PackFile>.
1231 PARROT_WARN_UNUSED_RESULT
1232 PARROT_CAN_RETURN_NULL
1234 PackFile_find_segment(PARROT_INTERP
, ARGIN_NULLOK(PackFile_Directory
*dir
),
1235 ARGIN(const STRING
*name
), int sub_dir
)
1237 ASSERT_ARGS(PackFile_find_segment
)
1241 for (i
= 0; i
< dir
->num_segments
; ++i
) {
1242 PackFile_Segment
*seg
= dir
->segments
[i
];
1245 if (Parrot_str_equal(interp
, seg
->name
, name
))
1248 if (sub_dir
&& seg
->type
== PF_DIR_SEG
) {
1249 seg
= PackFile_find_segment(interp
,
1250 (PackFile_Directory
*)seg
, name
, sub_dir
);
1265 =item C<PackFile_Segment * PackFile_remove_segment_by_name(PARROT_INTERP,
1266 PackFile_Directory *dir, STRING *name)>
1268 Finds, removes, and returns the segment with name C<name> in the
1269 C<PackFile_Directory>. The caller is responsible for destroying the segment.
1276 PARROT_WARN_UNUSED_RESULT
1277 PARROT_CAN_RETURN_NULL
1279 PackFile_remove_segment_by_name(PARROT_INTERP
, ARGMOD(PackFile_Directory
*dir
),
1280 ARGIN(STRING
*name
))
1282 ASSERT_ARGS(PackFile_remove_segment_by_name
)
1285 for (i
= 0; i
< dir
->num_segments
; ++i
) {
1286 PackFile_Segment
* const seg
= dir
->segments
[i
];
1287 if (Parrot_str_equal(interp
, seg
->name
, name
)) {
1288 dir
->num_segments
--;
1290 if (i
!= dir
->num_segments
) {
1291 /* We're not the last segment, so we need to move things */
1292 memmove(&dir
->segments
[i
], &dir
->segments
[i
+1],
1293 (dir
->num_segments
- i
) * sizeof (PackFile_Segment
*));
1308 =head2 PackFile Structure Functions
1312 =item C<static void PackFile_set_header(PackFile_Header *header)>
1314 Fills a C<PackFile> header with system specific data.
1321 PackFile_set_header(ARGOUT(PackFile_Header
*header
))
1323 ASSERT_ARGS(PackFile_set_header
)
1324 memcpy(header
->magic
, "\376PBC\r\n\032\n", 8);
1325 header
->wordsize
= sizeof (opcode_t
);
1326 header
->byteorder
= PARROT_BIGENDIAN
;
1327 header
->major
= PARROT_MAJOR_VERSION
;
1328 header
->minor
= PARROT_MINOR_VERSION
;
1329 header
->patch
= PARROT_PATCH_VERSION
;
1330 header
->bc_major
= PARROT_PBC_MAJOR
;
1331 header
->bc_minor
= PARROT_PBC_MINOR
;
1332 #if NUMVAL_SIZE == 8
1333 header
->floattype
= FLOATTYPE_8
;
1335 # if (NUMVAL_SIZE == 12) && !PARROT_BIGENDIAN
1336 header
->floattype
= FLOATTYPE_12
;
1338 # if (NUMVAL_SIZE == 16)
1339 header
->floattype
= FLOATTYPE_16
;
1341 exit_fatal(1, "PackFile_set_header: Unsupported floattype NUMVAL_SIZE=%d,"
1342 " PARROT_BIGENDIAN=%s\n", NUMVAL_SIZE
,
1343 PARROT_BIGENDIAN
? "big-endian" : "little-endian");
1352 =item C<PackFile * PackFile_new(PARROT_INTERP, INTVAL is_mapped)>
1354 Allocates a new empty C<PackFile> and sets up the directory.
1358 +----------+----------+----------+----------+
1361 +----------+----------+----------+----------+
1363 +----------+----------+----------+----------+
1364 | number of directory items |
1365 +----------+----------+----------+----------+
1367 followed by a sequence of items
1369 +----------+----------+----------+----------+
1371 +----------+----------+----------+----------+
1373 | ... '\0' padding bytes |
1374 +----------+----------+----------+----------+
1375 | Offset in the file |
1376 +----------+----------+----------+----------+
1377 | Size of the segment |
1378 +----------+----------+----------+----------+
1380 "name" is a NUL-terminated c-string encoded in plain ASCII.
1382 Segment types are defined in F<include/parrot/packfile.h>.
1384 Offset and size are in C<opcode_t>.
1386 A Segment Header has these entries:
1388 - op_count total ops of segment incl. this count
1389 - itype internal type of segment
1390 - id internal id e.g code seg nr
1391 - size size of following op array, 0 if none
1392 * data possibly empty data, or e.g. byte code
1399 PARROT_WARN_UNUSED_RESULT
1400 PARROT_CANNOT_RETURN_NULL
1402 PackFile_new(PARROT_INTERP
, INTVAL is_mapped
)
1404 ASSERT_ARGS(PackFile_new
)
1405 PackFile
* const pf
= mem_gc_allocate_zeroed_typed(interp
, PackFile
);
1406 pf
->header
= mem_gc_allocate_zeroed_typed(interp
, PackFile_Header
);
1407 pf
->is_mmap_ped
= is_mapped
;
1408 pf
->options
= PFOPT_NONE
;
1410 /* fill header with system specific data */
1411 PackFile_set_header(pf
->header
);
1413 /* Other fields empty for now */
1415 pf_register_standard_funcs(interp
, pf
);
1417 /* create the master directory, all subirs go there */
1418 pf
->directory
.base
.pf
= pf
;
1419 pf
->dirp
= (PackFile_Directory
*)
1420 PackFile_Segment_new_seg(interp
, &pf
->directory
,
1421 PF_DIR_SEG
, DIRECTORY_SEGMENT_NAME
, 0);
1422 pf
->directory
= *pf
->dirp
;
1424 pf
->fetch_op
= (packfile_fetch_op_t
)NULL
;
1425 pf
->fetch_iv
= (packfile_fetch_iv_t
)NULL
;
1426 pf
->fetch_nv
= (packfile_fetch_nv_t
)NULL
;
1434 =item C<PackFile * PackFile_new_dummy(PARROT_INTERP, STRING *name)>
1436 Creates a new (initial) dummy PackFile. This is necessary if the interpreter
1437 doesn't load any bytecode but instead uses C<Parrot_compile_string>.
1444 PARROT_WARN_UNUSED_RESULT
1445 PARROT_CAN_RETURN_NULL
1447 PackFile_new_dummy(PARROT_INTERP
, ARGIN(STRING
*name
))
1449 ASSERT_ARGS(PackFile_new_dummy
)
1451 PackFile
* const pf
= PackFile_new(interp
, 0);
1452 interp
->initial_pf
= pf
;
1453 interp
->code
= pf
->cur_cs
1454 = PF_create_default_segs(interp
, name
, 1);
1462 =item C<void PackFile_funcs_register(PARROT_INTERP, PackFile *pf, UINTVAL type,
1463 const PackFile_funcs funcs)>
1465 Registers the C<pack>/C<unpack>/... functions for a packfile type.
1473 PackFile_funcs_register(SHIM_INTERP
, ARGOUT(PackFile
*pf
), UINTVAL type
,
1474 const PackFile_funcs funcs
)
1476 ASSERT_ARGS(PackFile_funcs_register
)
1477 pf
->PackFuncs
[type
] = funcs
;
1483 =item C<static const opcode_t * default_unpack(PARROT_INTERP, PackFile_Segment
1484 *self, const opcode_t *cursor)>
1486 Unpacks a PackFile given a cursor into PBC. This is the default unpack.
1492 PARROT_WARN_UNUSED_RESULT
1493 PARROT_CAN_RETURN_NULL
1494 static const opcode_t
*
1495 default_unpack(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
), ARGIN(const opcode_t
*cursor
))
1497 ASSERT_ARGS(default_unpack
)
1498 DECL_CONST_CAST_OF(opcode_t
);
1500 PackFile
* const pf
= self
->pf
;
1503 self
->op_count
= PF_fetch_opcode(self
->pf
, &cursor
);
1504 self
->itype
= PF_fetch_opcode(self
->pf
, &cursor
);
1505 self
->id
= PF_fetch_opcode(self
->pf
, &cursor
);
1506 self
->size
= PF_fetch_opcode(self
->pf
, &cursor
);
1507 TRACE_PRINTF_VAL(("default_unpack: op_count=%d, itype=%d, id=%d, size=%d.\n",
1508 self
->op_count
, self
->itype
, self
->id
, self
->size
));
1510 if (self
->size
== 0)
1513 /* if the packfile is mmap()ed just point to it if we don't
1514 * need any fetch transforms */
1515 if (self
->pf
->is_mmap_ped
1516 && !self
->pf
->need_endianize
1517 && !self
->pf
->need_wordsize
) {
1518 self
->data
= PARROT_const_cast(opcode_t
*, cursor
);
1519 cursor
+= self
->size
;
1523 /* else allocate mem */
1524 self
->data
= mem_gc_allocate_n_typed(interp
, self
->size
, opcode_t
);
1527 Parrot_io_eprintf(NULL
, "PackFile_unpack: Unable to allocate data memory!\n");
1532 if (!self
->pf
->need_endianize
&& !self
->pf
->need_wordsize
) {
1533 mem_sys_memcopy(self
->data
, cursor
, self
->size
* sizeof (opcode_t
));
1534 cursor
+= self
->size
;
1538 TRACE_PRINTF(("default_unpack: pre-fetch %d ops into data\n",
1540 for (i
= 0; i
< (int)self
->size
; ++i
) {
1541 self
->data
[i
] = PF_fetch_opcode(self
->pf
, &cursor
);
1542 TRACE_PRINTF(("default_unpack: transformed op[#%d]/%d %u\n",
1543 i
, self
->size
, self
->data
[i
]));
1553 =item C<void default_dump_header(PARROT_INTERP, const PackFile_Segment *self)>
1555 Dumps the header of a given PackFile_Segment.
1562 default_dump_header(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
1564 ASSERT_ARGS(default_dump_header
)
1565 Parrot_io_printf(interp
, "%Ss => [ # offs 0x%x(%d)",
1566 self
->name
, (int)self
->file_offset
, (int)self
->file_offset
);
1567 Parrot_io_printf(interp
, " = op_count %d, itype %d, id %d, size %d, ...",
1568 (int)self
->op_count
, (int)self
->itype
,
1569 (int)self
->id
, (int)self
->size
);
1575 =item C<static void default_dump(PARROT_INTERP, const PackFile_Segment *self)>
1577 Dumps a PackFile_Segment.
1584 default_dump(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
1586 ASSERT_ARGS(default_dump
)
1587 size_t i
= self
->data
? 0: self
->file_offset
+ SEGMENT_HEADER_SIZE
;
1589 default_dump_header(interp
, self
);
1592 Parrot_io_printf(interp
, "\n %04x: ", (int) i
);
1594 for (; i
< (self
->data
? self
->size
:
1595 self
->file_offset
+ self
->op_count
); ++i
) {
1598 Parrot_io_printf(interp
, "\n %04x: ", (int) i
);
1600 Parrot_io_printf(interp
, "%08lx ", (unsigned long)
1601 self
->data
? self
->data
[i
] : self
->pf
->src
[i
]);
1604 Parrot_io_printf(interp
, "\n]\n");
1610 =item C<static void pf_register_standard_funcs(PARROT_INTERP, PackFile *pf)>
1612 Registers a PackFile's functions; called from within C<PackFile_new()>.
1619 pf_register_standard_funcs(PARROT_INTERP
, ARGMOD(PackFile
*pf
))
1621 ASSERT_ARGS(pf_register_standard_funcs
)
1622 PackFile_funcs dirf
= {
1625 directory_packed_size
,
1631 PackFile_funcs defaultf
= {
1632 PackFile_Segment_new
,
1633 (PackFile_Segment_destroy_func_t
) NULLfunc
,
1634 (PackFile_Segment_packed_size_func_t
) NULLfunc
,
1635 (PackFile_Segment_pack_func_t
) NULLfunc
,
1636 (PackFile_Segment_unpack_func_t
) NULLfunc
,
1640 PackFile_funcs fixupf
= {
1649 PackFile_funcs constf
= {
1652 PackFile_ConstTable_pack_size
,
1653 PackFile_ConstTable_pack
,
1654 PackFile_ConstTable_unpack
,
1658 PackFile_funcs bytef
= {
1661 (PackFile_Segment_packed_size_func_t
) NULLfunc
,
1662 (PackFile_Segment_pack_func_t
) NULLfunc
,
1663 (PackFile_Segment_unpack_func_t
) NULLfunc
,
1667 const PackFile_funcs debugf
= {
1670 pf_debug_packed_size
,
1676 const PackFile_funcs annotationf
= {
1677 PackFile_Annotations_new
,
1678 PackFile_Annotations_destroy
,
1679 PackFile_Annotations_packed_size
,
1680 PackFile_Annotations_pack
,
1681 PackFile_Annotations_unpack
,
1682 PackFile_Annotations_dump
1685 PackFile_funcs_register(interp
, pf
, PF_DIR_SEG
, dirf
);
1686 PackFile_funcs_register(interp
, pf
, PF_UNKNOWN_SEG
, defaultf
);
1687 PackFile_funcs_register(interp
, pf
, PF_FIXUP_SEG
, fixupf
);
1688 PackFile_funcs_register(interp
, pf
, PF_CONST_SEG
, constf
);
1689 PackFile_funcs_register(interp
, pf
, PF_BYTEC_SEG
, bytef
);
1690 PackFile_funcs_register(interp
, pf
, PF_DEBUG_SEG
, debugf
);
1691 PackFile_funcs_register(interp
, pf
, PF_ANNOTATIONS_SEG
, annotationf
);
1699 =item C<PackFile_Segment * PackFile_Segment_new_seg(PARROT_INTERP,
1700 PackFile_Directory *dir, UINTVAL type, STRING *name, int add)>
1702 Creates a new segment in the given PackFile_Directory of the given C<type> with
1703 the given C<name>. If C<add> is true, adds the segment to the directory.
1710 PARROT_WARN_UNUSED_RESULT
1711 PARROT_CANNOT_RETURN_NULL
1713 PackFile_Segment_new_seg(PARROT_INTERP
, ARGMOD(PackFile_Directory
*dir
),
1714 UINTVAL type
, ARGIN(STRING
*name
), int add
)
1716 ASSERT_ARGS(PackFile_Segment_new_seg
)
1717 PackFile
* const pf
= dir
->base
.pf
;
1718 const PackFile_Segment_new_func_t f
= pf
->PackFuncs
[type
].new_seg
;
1719 PackFile_Segment
* const seg
= (f
)(interp
, pf
, name
, add
);
1721 segment_init(interp
, seg
, pf
, name
);
1725 PackFile_add_segment(interp
, dir
, seg
);
1733 =item C<static PackFile_Segment * create_seg(PARROT_INTERP, PackFile_Directory
1734 *dir, pack_file_types t, STRING *name, STRING *file_name, int add)>
1736 Creates a new PackFile_Segment for the given C<file_name>. See
1737 C<PackFile_Segment_new_seg()> for the other arguments.
1743 PARROT_WARN_UNUSED_RESULT
1744 PARROT_CANNOT_RETURN_NULL
1745 static PackFile_Segment
*
1746 create_seg(PARROT_INTERP
, ARGMOD(PackFile_Directory
*dir
), pack_file_types t
,
1747 ARGIN(STRING
*name
), ARGIN(STRING
*file_name
), int add
)
1749 ASSERT_ARGS(create_seg
)
1750 PackFile_Segment
*seg
;
1753 seg_name
= Parrot_sprintf_c(interp
, "%Ss_%Ss", name
, file_name
);
1754 seg
= PackFile_Segment_new_seg(interp
, dir
, t
, seg_name
, add
);
1761 =item C<PackFile_ByteCode * PF_create_default_segs(PARROT_INTERP, STRING
1762 *file_name, int add)>
1764 Creates the bytecode, constant, and fixup segments for C<file_name>. If C<add>
1765 is true, the current packfile becomes the owner of these segments by adding the
1766 segments to the directory.
1773 PARROT_WARN_UNUSED_RESULT
1774 PARROT_CANNOT_RETURN_NULL
1776 PF_create_default_segs(PARROT_INTERP
, ARGIN(STRING
*file_name
), int add
)
1778 ASSERT_ARGS(PF_create_default_segs
)
1779 PackFile
* const pf
= interp
->initial_pf
;
1780 PackFile_ByteCode
* const cur_cs
=
1781 (PackFile_ByteCode
*)create_seg(interp
, &pf
->directory
,
1782 PF_BYTEC_SEG
, BYTE_CODE_SEGMENT_NAME
, file_name
, add
);
1785 (PackFile_FixupTable
*)create_seg(interp
, &pf
->directory
,
1786 PF_FIXUP_SEG
, FIXUP_TABLE_SEGMENT_NAME
, file_name
, add
);
1788 cur_cs
->fixups
->code
= cur_cs
;
1790 cur_cs
->const_table
=
1791 (PackFile_ConstTable
*)create_seg(interp
, &pf
->directory
,
1792 PF_CONST_SEG
, CONSTANT_SEGMENT_NAME
, file_name
, add
);
1794 cur_cs
->const_table
->code
= cur_cs
;
1802 =item C<void PackFile_Segment_destroy(PARROT_INTERP, PackFile_Segment *self)>
1804 Destroys the given PackFile_Segment.
1812 PackFile_Segment_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
1814 ASSERT_ARGS(PackFile_Segment_destroy
)
1815 const PackFile_Segment_destroy_func_t f
=
1816 self
->pf
->PackFuncs
[self
->type
].destroy
;
1821 /* destroy self after specific */
1822 default_destroy(interp
, self
);
1828 =item C<size_t PackFile_Segment_packed_size(PARROT_INTERP, PackFile_Segment
1831 Returns the size of the given segment, when packed, taking into account padding
1840 PackFile_Segment_packed_size(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
))
1842 ASSERT_ARGS(PackFile_Segment_packed_size
)
1843 size_t size
= default_packed_size(self
);
1844 const size_t align
= 16 / sizeof (opcode_t
);
1845 PackFile_Segment_packed_size_func_t f
=
1846 self
->pf
->PackFuncs
[self
->type
].packed_size
;
1849 size
+= (f
)(interp
, self
);
1852 if (align
&& size
% align
)
1853 size
+= (align
- size
% align
);
1861 =item C<opcode_t * PackFile_Segment_pack(PARROT_INTERP, PackFile_Segment *self,
1864 Packs a PackFile_Segment, returning a cursor to the start of the results.
1871 PARROT_WARN_UNUSED_RESULT
1872 PARROT_CANNOT_RETURN_NULL
1874 PackFile_Segment_pack(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
),
1875 ARGIN(opcode_t
*cursor
))
1877 ASSERT_ARGS(PackFile_Segment_pack
)
1878 /*const size_t align = 16 / sizeof (opcode_t);*/
1879 PackFile_Segment_pack_func_t f
=
1880 self
->pf
->PackFuncs
[self
->type
].pack
;
1881 opcode_t
* old_cursor
; /* Used for filling padding with 0 */
1883 PackFile
* const pf
= self
->pf
;
1886 cursor
= default_pack(self
, cursor
);
1889 cursor
= (f
)(interp
, self
, cursor
);
1891 TRACE_PRINTF_ALIGN(("-ALIGN_16: offset=0x%x src=0x%x cursor=0x%x\n",
1892 OFFS(pf
, cursor
), pf
->src
, cursor
));
1893 old_cursor
= cursor
;
1894 ALIGN_16(self
->pf
, cursor
);
1895 /* fill padding with zeros */
1896 while (old_cursor
!= cursor
)
1899 /*if (align && (cursor - self->pf->src) % align)
1900 cursor += align - (cursor - self->pf->src) % align;*/
1901 TRACE_PRINTF_ALIGN(("+ALIGN_16: offset=0x%x src=0x%x cursor=0x%x\n",
1902 OFFS(pf
, cursor
), pf
->src
, cursor
));
1910 =item C<const opcode_t * PackFile_Segment_unpack(PARROT_INTERP, PackFile_Segment
1911 *self, const opcode_t *cursor)>
1913 Unpacks a PackFile_Segment, returning a cursor to the results on success and
1916 All all these functions call the related C<default_*> function.
1918 If a special is defined this gets called after.
1925 PARROT_WARN_UNUSED_RESULT
1926 PARROT_CAN_RETURN_NULL
1928 PackFile_Segment_unpack(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
),
1929 ARGIN(const opcode_t
*cursor
))
1931 ASSERT_ARGS(PackFile_Segment_unpack
)
1932 PackFile_Segment_unpack_func_t f
= self
->pf
->PackFuncs
[self
->type
].unpack
;
1935 PackFile
* const pf
= self
->pf
;
1938 cursor
= default_unpack(interp
, self
, cursor
);
1944 TRACE_PRINTF(("PackFile_Segment_unpack: special\n"));
1946 cursor
= (f
)(interp
, self
, cursor
);
1951 offs
= OFFS(self
->pf
, cursor
);
1952 TRACE_PRINTF_ALIGN(("-S ALIGN_16: offset=0x%x src=0x%x cursor=0x%x\n",
1953 offs
, self
->pf
->src
, cursor
));
1954 offs
+= PAD_16_B(offs
);
1955 cursor
= self
->pf
->src
+ offs
/(sizeof (opcode_t
));
1956 TRACE_PRINTF_ALIGN(("+S ALIGN_16: offset=0x%x src=0x%x cursor=0x%x\n",
1957 offs
, self
->pf
->src
, cursor
));
1964 =item C<void PackFile_Segment_dump(PARROT_INTERP, PackFile_Segment *self)>
1966 Dumps the segment C<self>.
1974 PackFile_Segment_dump(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
))
1976 ASSERT_ARGS(PackFile_Segment_dump
)
1977 self
->pf
->PackFuncs
[self
->type
].dump(interp
, self
);
1985 =head2 Standard Directory Functions
1989 =item C<static PackFile_Segment * directory_new(PARROT_INTERP, PackFile *pf,
1990 STRING *name, int add)>
1992 Returns a new C<PackFile_Directory> cast as a C<PackFile_Segment>.
1998 PARROT_WARN_UNUSED_RESULT
1999 PARROT_CANNOT_RETURN_NULL
2000 static PackFile_Segment
*
2001 directory_new(PARROT_INTERP
, SHIM(PackFile
*pf
), SHIM(STRING
*name
), SHIM(int add
))
2003 ASSERT_ARGS(directory_new
)
2005 return (PackFile_Segment
*)mem_gc_allocate_zeroed_typed(interp
, PackFile_Directory
);
2011 =item C<static void directory_dump(PARROT_INTERP, const PackFile_Segment *self)>
2013 Dumps the directory C<self>.
2020 directory_dump(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
2022 ASSERT_ARGS(directory_dump
)
2023 const PackFile_Directory
* const dir
= (const PackFile_Directory
*) self
;
2026 default_dump_header(interp
, self
);
2028 Parrot_io_printf(interp
, "\n\t# %d segments\n", dir
->num_segments
);
2030 for (i
= 0; i
< dir
->num_segments
; ++i
) {
2031 const PackFile_Segment
* const seg
= dir
->segments
[i
];
2033 Parrot_io_printf(interp
,
2034 "\ttype %d\t%Ss\t", (int)seg
->type
, seg
->name
);
2036 Parrot_io_printf(interp
,
2037 " offs 0x%x(0x%x)\top_count %d\n",
2038 (int)seg
->file_offset
,
2039 (int)seg
->file_offset
* sizeof (opcode_t
),
2040 (int)seg
->op_count
);
2043 Parrot_io_printf(interp
, "]\n");
2045 for (i
= 0; i
< dir
->num_segments
; ++i
)
2046 PackFile_Segment_dump(interp
, dir
->segments
[i
]);
2052 =item C<static const opcode_t * directory_unpack(PARROT_INTERP, PackFile_Segment
2053 *segp, const opcode_t *cursor)>
2055 Unpacks the directory from the provided cursor.
2061 PARROT_WARN_UNUSED_RESULT
2062 PARROT_CANNOT_RETURN_NULL
2063 static const opcode_t
*
2064 directory_unpack(PARROT_INTERP
, ARGMOD(PackFile_Segment
*segp
), ARGIN(const opcode_t
*cursor
))
2066 ASSERT_ARGS(directory_unpack
)
2067 PackFile_Directory
* const dir
= (PackFile_Directory
*)segp
;
2068 PackFile
* const pf
= dir
->base
.pf
;
2069 const opcode_t
*pos
;
2074 dir
->num_segments
= PF_fetch_opcode(pf
, &cursor
);
2075 TRACE_PRINTF(("directory_unpack: %ld num_segments\n", dir
->num_segments
));
2076 dir
->segments
= mem_gc_allocate_n_zeroed_typed(interp
,
2077 dir
->num_segments
, PackFile_Segment
*);
2079 for (i
= 0; i
< dir
->num_segments
; ++i
) {
2080 PackFile_Segment
*seg
;
2086 UINTVAL type
= PF_fetch_opcode(pf
, &cursor
);
2087 if (type
>= PF_MAX_SEG
)
2088 type
= PF_UNKNOWN_SEG
;
2090 TRACE_PRINTF_VAL(("Segment type %d.\n", type
));
2093 buf
= PF_fetch_cstring(interp
, pf
, &cursor
);
2094 TRACE_PRINTF_VAL(("Segment name \"%s\".\n", name
));
2097 name
= Parrot_str_new(interp
, buf
, strlen(buf
));
2098 seg
= PackFile_Segment_new_seg(interp
, dir
, type
, name
, 0);
2099 mem_gc_free(interp
, buf
);
2101 seg
->file_offset
= PF_fetch_opcode(pf
, &cursor
);
2102 TRACE_PRINTF_VAL(("Segment file_offset %ld.\n", seg
->file_offset
));
2104 seg
->op_count
= PF_fetch_opcode(pf
, &cursor
);
2105 TRACE_PRINTF_VAL(("Segment op_count %ld.\n", seg
->op_count
));
2107 if (pf
->need_wordsize
) {
2108 #if OPCODE_T_SIZE == 8
2109 if (pf
->header
->wordsize
== 4)
2110 pos
= pf
->src
+ seg
->file_offset
/ 2;
2112 if (pf
->header
->wordsize
== 8)
2113 pos
= pf
->src
+ seg
->file_offset
* 2;
2116 fprintf(stderr
, "directory_unpack failed: invalid wordsize %d\n",
2117 (int)pf
->header
->wordsize
);
2120 TRACE_PRINTF_VAL(("Segment offset: new pos 0x%x "
2121 "(src=0x%x cursor=0x%x).\n",
2122 OFFS(pf
, pos
), pf
->src
, cursor
));
2125 pos
= pf
->src
+ seg
->file_offset
;
2127 opcode
= PF_fetch_opcode(pf
, &pos
);
2129 if (seg
->op_count
!= opcode
) {
2130 Parrot_io_eprintf(interp
,
2131 "%Ss: Size in directory %d doesn't match size %d "
2132 "at offset 0x%x\n", seg
->name
, (int)seg
->op_count
,
2133 (int)opcode
, (int)seg
->file_offset
);
2137 PackFile_Segment
*last
= dir
->segments
[i
- 1];
2138 if (last
->file_offset
+ last
->op_count
!= seg
->file_offset
)
2139 fprintf(stderr
, "section: sections are not back to back\n");
2142 make_code_pointers(seg
);
2144 /* store the segment */
2145 dir
->segments
[i
] = seg
;
2149 offs
= OFFS(pf
, cursor
);
2150 TRACE_PRINTF_ALIGN(("-ALIGN_16: offset=0x%x src=0x%x cursor=0x%x\n",
2151 offs
, pf
->src
, cursor
));
2152 offs
+= PAD_16_B(offs
);
2153 cursor
= pf
->src
+ offs
/(sizeof (opcode_t
));
2154 TRACE_PRINTF_ALIGN(("+ALIGN_16: offset=0x%x src=0x%x cursor=0x%x\n",
2155 offs
, pf
->src
, cursor
));
2157 /* and now unpack contents of dir */
2158 for (i
= 0; cursor
&& i
< dir
->num_segments
; ++i
) {
2159 const opcode_t
* const csave
= cursor
;
2161 /* check len again */
2162 size_t tmp
= PF_fetch_opcode(pf
, &cursor
);
2164 /* keep gcc -O silent */
2168 TRACE_PRINTF_VAL(("PackFile_Segment_unpack [%d] tmp len=%d.\n", i
, tmp
));
2169 pos
= PackFile_Segment_unpack(interp
, dir
->segments
[i
], cursor
);
2172 Parrot_io_eprintf(interp
, "PackFile_unpack segment '%Ss' failed\n",
2173 dir
->segments
[i
]->name
);
2177 TRACE_PRINTF_VAL(("PackFile_Segment_unpack ok. pos=0x%x\n", pos
));
2180 /* FIXME bug on 64bit reading 32bit lurking here! TT #254 */
2181 if (pf
->need_wordsize
) {
2182 #if OPCODE_T_SIZE == 8
2183 if (pf
->header
->wordsize
== 4)
2184 delta
= (pos
- cursor
) * 2;
2186 if (pf
->header
->wordsize
== 8)
2187 delta
= (pos
- cursor
) / 2;
2191 delta
= pos
- cursor
;
2193 TRACE_PRINTF_VAL((" delta=%d, pos=0x%x, cursor=0x%x\n",
2194 delta
, pos
, cursor
));
2196 if ((size_t)delta
!= tmp
|| dir
->segments
[i
]->op_count
!= tmp
)
2197 Parrot_io_eprintf(interp
, "PackFile_unpack segment '%Ss' directory length %d "
2198 "length in file %d needed %d for unpack\n",
2199 dir
->segments
[i
]->name
,
2200 (int)dir
->segments
[i
]->op_count
, (int)tmp
,
2211 =item C<static void directory_destroy(PARROT_INTERP, PackFile_Segment *self)>
2213 Destroys the directory.
2220 directory_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
2222 ASSERT_ARGS(directory_destroy
)
2223 PackFile_Directory
* const dir
= (PackFile_Directory
*)self
;
2226 for (i
= 0; i
< dir
->num_segments
; ++i
) {
2227 PackFile_Segment
*segment
= dir
->segments
[i
];
2228 /* Prevent repeated destruction */
2229 dir
->segments
[i
] = NULL
;
2231 if (segment
&& segment
!= self
)
2232 PackFile_Segment_destroy(interp
, segment
);
2235 if (dir
->segments
) {
2236 mem_gc_free(interp
, dir
->segments
);
2237 dir
->segments
= NULL
;
2238 dir
->num_segments
= 0;
2245 =item C<static void sort_segs(PackFile_Directory *dir)>
2247 Sorts the segments in C<dir>.
2254 sort_segs(ARGMOD(PackFile_Directory
*dir
))
2256 ASSERT_ARGS(sort_segs
)
2257 const size_t num_segs
= dir
->num_segments
;
2258 PackFile_Segment
*seg
= dir
->segments
[0];
2260 if (seg
->type
!= PF_BYTEC_SEG
) {
2263 for (i
= 1; i
< num_segs
; ++i
) {
2264 PackFile_Segment
* const s2
= dir
->segments
[i
];
2265 if (s2
->type
== PF_BYTEC_SEG
) {
2266 dir
->segments
[0] = s2
;
2267 dir
->segments
[i
] = seg
;
2273 seg
= dir
->segments
[1];
2275 if (seg
->type
!= PF_FIXUP_SEG
) {
2278 for (i
= 2; i
< num_segs
; ++i
) {
2279 PackFile_Segment
* const s2
= dir
->segments
[i
];
2280 if (s2
->type
== PF_FIXUP_SEG
) {
2281 dir
->segments
[1] = s2
;
2282 dir
->segments
[i
] = seg
;
2289 * Temporary? hack to put ConstantTable in front of other segments.
2290 * This is useful for Annotations because we ensure that constants used
2291 * for keys already available during unpack.
2293 seg
= dir
->segments
[2];
2295 if (seg
->type
!= PF_CONST_SEG
) {
2298 for (i
= 3; i
< num_segs
; ++i
) {
2299 PackFile_Segment
* const s2
= dir
->segments
[i
];
2300 if (s2
->type
== PF_CONST_SEG
) {
2301 dir
->segments
[2] = s2
;
2302 dir
->segments
[i
] = seg
;
2312 =item C<static size_t directory_packed_size(PARROT_INTERP, PackFile_Segment
2315 Returns the size of the directory minus the value returned by
2316 C<default_packed_size()>.
2322 PARROT_WARN_UNUSED_RESULT
2324 directory_packed_size(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
2326 ASSERT_ARGS(directory_packed_size
)
2327 PackFile_Directory
* const dir
= (PackFile_Directory
*)self
;
2328 const size_t align
= 16 / sizeof (opcode_t
);
2331 /* need bytecode, fixup, other segs ... */
2334 /* number of segments + default, we need it for the offsets */
2335 size
= 1 + default_packed_size(self
);
2337 for (i
= 0; i
< dir
->num_segments
; ++i
) {
2338 char * const name
= Parrot_str_to_cstring(interp
, dir
->segments
[i
]->name
);
2339 /* type, offset, size */
2341 size
+= PF_size_cstring(name
);
2342 Parrot_str_free_cstring(name
);
2346 if (align
&& size
% align
)
2347 size
+= (align
- size
% align
);
2349 for (i
= 0; i
< dir
->num_segments
; ++i
) {
2352 dir
->segments
[i
]->file_offset
= size
+ self
->file_offset
;
2354 PackFile_Segment_packed_size(interp
, dir
->segments
[i
]);
2355 dir
->segments
[i
]->op_count
= seg_size
;
2359 self
->op_count
= size
;
2361 /* subtract default, it is added in PackFile_Segment_packed_size */
2362 return size
- default_packed_size(self
);
2368 =item C<static opcode_t * directory_pack(PARROT_INTERP, PackFile_Segment *self,
2371 Packs the directory C<self>, using the given cursor.
2377 PARROT_WARN_UNUSED_RESULT
2378 PARROT_CANNOT_RETURN_NULL
2380 directory_pack(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
), ARGOUT(opcode_t
*cursor
))
2382 ASSERT_ARGS(directory_pack
)
2383 PackFile_Directory
* const dir
= (PackFile_Directory
*)self
;
2384 const size_t num_segs
= dir
->num_segments
;
2385 /*const size_t align = 16/sizeof (opcode_t);*/
2387 PackFile
* const pf
= self
->pf
;
2388 opcode_t
* old_cursor
; /* Used for filling padding with 0 */
2390 *cursor
++ = num_segs
;
2392 for (i
= 0; i
< num_segs
; i
++) {
2393 const PackFile_Segment
* const seg
= dir
->segments
[i
];
2394 char * const name
= Parrot_str_to_cstring(interp
, seg
->name
);
2396 *cursor
++ = seg
->type
;
2397 cursor
= PF_store_cstring(cursor
, name
);
2398 *cursor
++ = seg
->file_offset
;
2399 *cursor
++ = seg
->op_count
;
2400 Parrot_str_free_cstring(name
);
2403 TRACE_PRINTF_ALIGN(("-ALIGN_16: offset=0x%x src=0x%x cursor=0x%x\n",
2404 OFFS(pf
, cursor
), pf
->src
, cursor
));
2405 old_cursor
= cursor
;
2406 ALIGN_16(pf
, cursor
);
2407 /* fill padding with zeros */
2408 while (old_cursor
!= cursor
)
2410 TRACE_PRINTF_ALIGN(("+ALIGN_16: offset=0x%x src=0x%x cursor=0x%x\n",
2411 OFFS(pf
, cursor
), pf
->src
, cursor
));
2412 /*if (align && (cursor - self->pf->src) % align)
2413 cursor += align - (cursor - self->pf->src) % align;*/
2415 /* now pack all segments into new format */
2416 for (i
= 0; i
< dir
->num_segments
; ++i
) {
2417 PackFile_Segment
* const seg
= dir
->segments
[i
];
2418 cursor
= PackFile_Segment_pack(interp
, seg
, cursor
);
2429 =head2 C<PackFile_Segment> Functions
2433 =item C<static void segment_init(PARROT_INTERP, PackFile_Segment *self, PackFile
2436 Initializes the segment C<self> with the provided PackFile and the given name.
2437 Note that this duplicates the given name.
2444 segment_init(PARROT_INTERP
, ARGOUT(PackFile_Segment
*self
), ARGIN(PackFile
*pf
),
2445 ARGIN(STRING
*name
))
2447 ASSERT_ARGS(segment_init
)
2449 self
->type
= PF_UNKNOWN_SEG
;
2450 self
->file_offset
= 0;
2462 =item C<PackFile_Segment * PackFile_Segment_new(PARROT_INTERP, PackFile *pf,
2463 STRING *name, int add)>
2465 Creates a new default section.
2472 PARROT_WARN_UNUSED_RESULT
2473 PARROT_CANNOT_RETURN_NULL
2475 PackFile_Segment_new(PARROT_INTERP
, SHIM(PackFile
*pf
), SHIM(STRING
*name
), SHIM(int add
))
2477 ASSERT_ARGS(PackFile_Segment_new
)
2478 PackFile_Segment
* const seg
= mem_gc_allocate_zeroed_typed(interp
, PackFile_Segment
);
2488 =head2 Default Function Implementations
2490 The default functions are called before the segment specific functions
2491 and can read a block of C<opcode_t> data.
2495 =item C<static void default_destroy(PARROT_INTERP, PackFile_Segment *self)>
2497 The default destroy function. Destroys a PackFile_Segment.
2504 default_destroy(PARROT_INTERP
, ARGFREE_NOTNULL(PackFile_Segment
*self
))
2506 ASSERT_ARGS(default_destroy
)
2507 if (!self
->pf
->is_mmap_ped
&& self
->data
) {
2508 mem_gc_free(interp
, self
->data
);
2512 mem_gc_free(interp
, self
);
2518 =item C<static size_t default_packed_size(const PackFile_Segment *self)>
2520 Returns the default size of the segment C<self>.
2527 default_packed_size(ARGIN(const PackFile_Segment
*self
))
2529 ASSERT_ARGS(default_packed_size
)
2530 return SEGMENT_HEADER_SIZE
+ self
->size
;
2536 =item C<static opcode_t * default_pack(const PackFile_Segment *self, opcode_t
2539 Performs the default pack.
2545 PARROT_WARN_UNUSED_RESULT
2546 PARROT_CANNOT_RETURN_NULL
2548 default_pack(ARGIN(const PackFile_Segment
*self
), ARGOUT(opcode_t
*dest
))
2550 ASSERT_ARGS(default_pack
)
2551 *dest
++ = self
->op_count
;
2552 *dest
++ = self
->itype
;
2554 *dest
++ = self
->size
;
2557 STRUCT_COPY_N(dest
, self
->data
, self
->size
);
2559 return dest
+ self
->size
;
2571 =item C<static void byte_code_destroy(PARROT_INTERP, PackFile_Segment *self)>
2573 Destroys the C<PackFile_ByteCode> segment C<self>.
2580 byte_code_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
2582 ASSERT_ARGS(byte_code_destroy
)
2583 PackFile_ByteCode
* const byte_code
= (PackFile_ByteCode
*)self
;
2585 byte_code
->fixups
= NULL
;
2586 byte_code
->const_table
= NULL
;
2587 byte_code
->debugs
= NULL
;
2593 =item C<static PackFile_Segment * byte_code_new(PARROT_INTERP, PackFile *pf,
2594 STRING *name, int add)>
2596 Creates a new C<PackFile_ByteCode> segment. Ignores C<pf>, C<name>, and C<add>.
2602 PARROT_WARN_UNUSED_RESULT
2603 PARROT_CANNOT_RETURN_NULL
2604 static PackFile_Segment
*
2605 byte_code_new(PARROT_INTERP
, SHIM(PackFile
*pf
), SHIM(STRING
*name
), SHIM(int add
))
2607 ASSERT_ARGS(byte_code_new
)
2608 PackFile_ByteCode
* const byte_code
= mem_gc_allocate_zeroed_typed(interp
, PackFile_ByteCode
);
2610 return (PackFile_Segment
*) byte_code
;
2622 =item C<static void pf_debug_destroy(PARROT_INTERP, PackFile_Segment *self)>
2624 Destroys the C<PackFile_Debug> segment C<self>.
2631 pf_debug_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
2633 ASSERT_ARGS(pf_debug_destroy
)
2634 PackFile_Debug
* const debug
= (PackFile_Debug
*) self
;
2636 /* Free mappings pointer array. */
2637 mem_gc_free(interp
, debug
->mappings
);
2638 debug
->mappings
= NULL
;
2639 debug
->num_mappings
= 0;
2645 =item C<static PackFile_Segment * pf_debug_new(PARROT_INTERP, PackFile *pf,
2646 STRING *name, int add)>
2648 Creates and returns a new C<PackFile_Debug> segment. Ignores C<pf>, C<name>,
2655 PARROT_WARN_UNUSED_RESULT
2656 PARROT_CANNOT_RETURN_NULL
2657 static PackFile_Segment
*
2658 pf_debug_new(PARROT_INTERP
, SHIM(PackFile
*pf
), SHIM(STRING
*name
), SHIM(int add
))
2660 ASSERT_ARGS(pf_debug_new
)
2661 PackFile_Debug
* const debug
= mem_gc_allocate_zeroed_typed(interp
, PackFile_Debug
);
2663 /* don't create initial mappings here; they'll get overwritten later */
2665 return (PackFile_Segment
*)debug
;
2671 =item C<static size_t pf_debug_packed_size(PARROT_INTERP, PackFile_Segment
2674 Returns the size of the C<PackFile_Debug> segment's filename in C<opcode_t>
2682 pf_debug_packed_size(SHIM_INTERP
, ARGIN(PackFile_Segment
*self
))
2684 ASSERT_ARGS(pf_debug_packed_size
)
2685 PackFile_Debug
* const debug
= (PackFile_Debug
*)self
;
2687 return (debug
->num_mappings
*2) + 1;
2693 =item C<static opcode_t * pf_debug_pack(PARROT_INTERP, PackFile_Segment *self,
2696 Packs the debug segment, using the given cursor.
2702 PARROT_WARN_UNUSED_RESULT
2703 PARROT_CANNOT_RETURN_NULL
2705 pf_debug_pack(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
), ARGOUT(opcode_t
*cursor
))
2707 ASSERT_ARGS(pf_debug_pack
)
2708 PackFile_Debug
* const debug
= (PackFile_Debug
*)self
;
2709 const int n
= debug
->num_mappings
;
2712 if (n
> 0 && debug
->mappings
== NULL
)
2713 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_MALFORMED_PACKFILE
,
2714 "No mappings but non zero num mappings(%I)", n
);
2716 /* Store number of mappings. */
2719 /* Now store each mapping. */
2720 for (i
= 0; i
< n
; ++i
) {
2721 /* Bytecode offset and filename. */
2722 *cursor
++ = debug
->mappings
[i
].offset
;
2723 *cursor
++ = debug
->mappings
[i
].filename
;
2732 =item C<static const opcode_t * pf_debug_unpack(PARROT_INTERP, PackFile_Segment
2733 *self, const opcode_t *cursor)>
2735 Unpacks a debug segment into a PackFile_Debug structure, given the cursor.
2741 PARROT_WARN_UNUSED_RESULT
2742 PARROT_CANNOT_RETURN_NULL
2743 static const opcode_t
*
2744 pf_debug_unpack(PARROT_INTERP
, ARGOUT(PackFile_Segment
*self
), ARGIN(const opcode_t
*cursor
))
2746 ASSERT_ARGS(pf_debug_unpack
)
2747 PackFile_Debug
* const debug
= (PackFile_Debug
*)self
;
2748 PackFile_ByteCode
*code
;
2751 /* For some reason, we store the source file name in the segment
2752 name. So we can't find the bytecode seg without knowing the filename.
2753 But with the new scheme we can have many file names. For now, just
2754 base this on the name of the debug segment. */
2755 STRING
*code_name
= NULL
;
2758 /* Number of mappings. */
2759 debug
->num_mappings
= PF_fetch_opcode(self
->pf
, &cursor
);
2761 /* Allocate space for mappings vector. */
2762 debug
->mappings
= mem_gc_allocate_n_zeroed_typed(interp
,
2763 debug
->num_mappings
, PackFile_DebugFilenameMapping
);
2765 /* Read in each mapping. */
2766 for (i
= 0; i
< debug
->num_mappings
; ++i
) {
2767 /* Get offset and filename type. */
2768 debug
->mappings
[i
].offset
= PF_fetch_opcode(self
->pf
, &cursor
);
2769 debug
->mappings
[i
].filename
= PF_fetch_opcode(self
->pf
, &cursor
);
2772 /* find seg e.g. CODE_DB => CODE and attach it */
2773 str_len
= Parrot_str_length(interp
, debug
->base
.name
);
2774 code_name
= Parrot_str_substr(interp
, debug
->base
.name
, 0, str_len
- 3);
2775 code
= (PackFile_ByteCode
*)PackFile_find_segment(interp
, self
->dir
, code_name
, 0);
2777 if (!code
|| code
->base
.type
!= PF_BYTEC_SEG
) {
2778 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
2779 "Code '%Ss' not found for debug segment '%Ss'\n",
2780 code_name
, self
->name
);
2783 code
->debugs
= debug
;
2792 =item C<static void pf_debug_dump(PARROT_INTERP, const PackFile_Segment *self)>
2794 Dumps a debug segment to a human readable form.
2801 pf_debug_dump(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
2803 ASSERT_ARGS(pf_debug_dump
)
2804 const PackFile_Debug
* const debug
= (const PackFile_Debug
*)self
;
2808 default_dump_header(interp
, self
);
2810 Parrot_io_printf(interp
, "\n mappings => [\n");
2811 for (i
= 0; i
< debug
->num_mappings
; ++i
) {
2812 Parrot_io_printf(interp
, " #%d\n [\n", i
);
2813 Parrot_io_printf(interp
, " OFFSET => %d,\n",
2814 debug
->mappings
[i
].offset
);
2815 Parrot_io_printf(interp
, " FILENAME => %Ss\n",
2816 PF_CONST(debug
->code
, debug
->mappings
[i
].filename
)->u
.string
);
2817 Parrot_io_printf(interp
, " ],\n");
2820 Parrot_io_printf(interp
, " ]\n");
2826 =item C<PackFile_Debug * Parrot_new_debug_seg(PARROT_INTERP, PackFile_ByteCode
2829 Creates and appends (or resizes) a new debug seg for a code segment. Uses the
2830 given size as its size.
2837 PARROT_WARN_UNUSED_RESULT
2838 PARROT_CANNOT_RETURN_NULL
2840 Parrot_new_debug_seg(PARROT_INTERP
, ARGMOD(PackFile_ByteCode
*cs
), size_t size
)
2842 ASSERT_ARGS(Parrot_new_debug_seg
)
2843 PackFile_Debug
*debug
;
2845 /* it exists already, resize it */
2848 debug
->base
.data
= mem_gc_realloc_n_typed(interp
, debug
->base
.data
, size
, opcode_t
);
2853 const int add
= (interp
->code
&& interp
->code
->base
.dir
);
2854 PackFile_Directory
* const dir
= add
2855 ? interp
->code
->base
.dir
2858 : &interp
->initial_pf
->directory
;
2860 name
= Parrot_sprintf_c(interp
, "%Ss_DB", cs
->base
.name
);
2861 debug
= (PackFile_Debug
*)PackFile_Segment_new_seg(interp
, dir
,
2862 PF_DEBUG_SEG
, name
, add
);
2864 debug
->base
.data
= mem_gc_allocate_n_zeroed_typed(interp
, size
, opcode_t
);
2869 debug
->base
.size
= size
;
2877 =item C<void Parrot_debug_add_mapping(PARROT_INTERP, PackFile_Debug *debug,
2878 opcode_t offset, const char *filename)>
2880 Adds a bytecode offset to a filename mapping for a PackFile_Debug.
2888 Parrot_debug_add_mapping(PARROT_INTERP
, ARGMOD(PackFile_Debug
*debug
),
2889 opcode_t offset
, ARGIN(const char *filename
))
2891 ASSERT_ARGS(Parrot_debug_add_mapping
)
2892 PackFile_ConstTable
* const ct
= debug
->code
->const_table
;
2894 opcode_t prev_filename_n
;
2895 STRING
*filename_pstr
;
2897 /* If the previous mapping has the same filename, don't record it. */
2898 if (debug
->num_mappings
) {
2899 prev_filename_n
= debug
->mappings
[debug
->num_mappings
-1].filename
;
2900 filename_pstr
= Parrot_str_new(interp
, filename
, 0);
2901 if (ct
->constants
[prev_filename_n
]->type
== PFC_STRING
&&
2902 Parrot_str_equal(interp
, filename_pstr
,
2903 ct
->constants
[prev_filename_n
]->u
.string
)) {
2908 /* Allocate space for the extra entry. */
2909 debug
->mappings
= mem_gc_realloc_n_typed(interp
,
2910 debug
->mappings
, debug
->num_mappings
+ 1,
2911 PackFile_DebugFilenameMapping
);
2913 /* Can it just go on the end? */
2914 if (debug
->num_mappings
== 0
2915 || offset
>= debug
->mappings
[debug
->num_mappings
- 1].offset
)
2916 insert_pos
= debug
->num_mappings
;
2918 /* Find the right place and shift stuff that's after it. */
2921 for (i
= 0; i
< debug
->num_mappings
; ++i
) {
2922 if (debug
->mappings
[i
].offset
> offset
) {
2924 memmove(debug
->mappings
+ i
+ 1, debug
->mappings
+ i
,
2925 debug
->num_mappings
- i
);
2931 /* Need to put filename in constants table. */
2933 /* Set up new entry and insert it. */
2934 PackFile_DebugFilenameMapping
*mapping
= debug
->mappings
+ insert_pos
;
2935 STRING
*namestr
= Parrot_str_new_init(interp
, filename
, strlen(filename
),
2936 PARROT_DEFAULT_ENCODING
, PARROT_DEFAULT_CHARSET
, 0);
2937 size_t count
= ct
->const_count
;
2940 mapping
->offset
= offset
;
2942 /* Check if there is already a constant with this filename */
2943 for (i
= 0; i
< count
; ++i
) {
2944 if (ct
->constants
[i
]->type
== PFC_STRING
&&
2945 Parrot_str_equal(interp
, namestr
, ct
->constants
[i
]->u
.string
))
2949 /* There is one, use it */
2953 /* Not found, create a new one */
2954 PackFile_Constant
*fnconst
;
2955 ct
->const_count
= ct
->const_count
+ 1;
2956 ct
->constants
= mem_gc_realloc_n_typed_zeroed(interp
, ct
->constants
,
2957 ct
->const_count
, ct
->const_count
- 1, PackFile_Constant
*);
2959 fnconst
= PackFile_Constant_new(interp
);
2960 fnconst
->type
= PFC_STRING
;
2961 fnconst
->u
.string
= Parrot_str_new_init(interp
, filename
, strlen(filename
),
2962 PARROT_DEFAULT_ENCODING
, PARROT_DEFAULT_CHARSET
,
2963 PObj_constant_FLAG
);
2964 ct
->constants
[ct
->const_count
- 1] = fnconst
;
2967 /* Set the mapped value */
2968 mapping
->filename
= count
;
2969 debug
->num_mappings
= debug
->num_mappings
+ 1;
2976 =item C<STRING * Parrot_debug_pc_to_filename(PARROT_INTERP, const PackFile_Debug
2977 *debug, opcode_t pc)>
2979 Returns the filename of the source for the given position in the bytecode.
2986 PARROT_WARN_UNUSED_RESULT
2987 PARROT_CANNOT_RETURN_NULL
2989 Parrot_debug_pc_to_filename(PARROT_INTERP
, ARGIN(const PackFile_Debug
*debug
),
2992 ASSERT_ARGS(Parrot_debug_pc_to_filename
)
2993 /* Look through mappings until we find one that maps the passed
2997 for (i
= 0; i
< debug
->num_mappings
; ++i
) {
2998 /* If this is the last mapping or the current position is
2999 between this mapping and the next one, return a filename. */
3000 if (i
+ 1 == debug
->num_mappings
3001 || (debug
->mappings
[i
].offset
<= pc
3002 && debug
->mappings
[i
+ 1].offset
> pc
))
3003 return PF_CONST(debug
->code
,
3004 debug
->mappings
[i
].filename
)->u
.string
;
3007 /* Otherwise, no mappings == no filename. */
3008 return CONST_STRING(interp
, "(unknown file)");
3014 =item C<void Parrot_switch_to_cs_by_nr(PARROT_INTERP, opcode_t seg)>
3016 Switches the current bytecode segment to the segment keyed by number C<seg>.
3024 Parrot_switch_to_cs_by_nr(PARROT_INTERP
, opcode_t seg
)
3026 ASSERT_ARGS(Parrot_switch_to_cs_by_nr
)
3027 const PackFile_Directory
* const dir
= interp
->code
->base
.dir
;
3028 const size_t num_segs
= dir
->num_segments
;
3033 /* TODO make an index of code segments for faster look up */
3034 for (i
= n
= 0; i
< num_segs
; ++i
) {
3035 if (dir
->segments
[i
]->type
== PF_BYTEC_SEG
) {
3037 Parrot_switch_to_cs(interp
, (PackFile_ByteCode
*)
3038 dir
->segments
[i
], 1);
3045 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
3046 "Segment number %d not found\n", (int)seg
);
3052 =item C<PackFile_ByteCode * Parrot_switch_to_cs(PARROT_INTERP, PackFile_ByteCode
3053 *new_cs, int really)>
3055 Switches to a bytecode segment C<new_cs>, returning the old segment.
3062 PARROT_IGNORABLE_RESULT
3063 PARROT_CANNOT_RETURN_NULL
3065 Parrot_switch_to_cs(PARROT_INTERP
, ARGIN(PackFile_ByteCode
*new_cs
), int really
)
3067 ASSERT_ARGS(Parrot_switch_to_cs
)
3068 PackFile_ByteCode
* const cur_cs
= interp
->code
;
3071 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_NO_PREV_CS
,
3072 "No code segment to switch to\n");
3074 /* compiling source code uses this function too,
3075 * which gives misleading trace messages */
3076 if (really
&& Interp_trace_TEST(interp
, PARROT_TRACE_SUB_CALL_FLAG
)) {
3077 Interp
* const tracer
= interp
->pdb
&& interp
->pdb
->debugger
3078 ? interp
->pdb
->debugger
3080 Parrot_io_eprintf(tracer
, "*** switching to %s\n", new_cs
->base
.name
);
3083 interp
->code
= new_cs
;
3084 Parrot_pcc_set_constants(interp
, CURRENT_CONTEXT(interp
), really
3085 ? find_constants(interp
, new_cs
->const_table
)
3086 : new_cs
->const_table
->constants
);
3089 prepare_for_run(interp
);
3097 =item C<static PackFile_Constant * clone_constant(PARROT_INTERP,
3098 PackFile_Constant *old_const)>
3100 Clones a constant (at least, if it's a Sub PMC), returning the clone.
3106 PARROT_WARN_UNUSED_RESULT
3107 PARROT_CANNOT_RETURN_NULL
3108 static PackFile_Constant
*
3109 clone_constant(PARROT_INTERP
, ARGIN(PackFile_Constant
*old_const
))
3111 ASSERT_ARGS(clone_constant
)
3112 STRING
* const _sub
= CONST_STRING(interp
, "Sub");
3114 if (old_const
->type
== PFC_PMC
3115 && VTABLE_isa(interp
, old_const
->u
.key
, _sub
)) {
3116 PMC
*old_sub_pmc
, *new_sub_pmc
;
3117 Parrot_Sub_attributes
*old_sub
, *new_sub
;
3118 PackFile_Constant
* const ret
= mem_gc_allocate_zeroed_typed(interp
,
3121 ret
->type
= old_const
->type
;
3122 old_sub_pmc
= old_const
->u
.key
;
3123 new_sub_pmc
= Parrot_thaw_constants(interp
, Parrot_freeze(interp
, old_sub_pmc
));
3125 PMC_get_sub(interp
, new_sub_pmc
, new_sub
);
3126 PMC_get_sub(interp
, old_sub_pmc
, old_sub
);
3127 new_sub
->seg
= old_sub
->seg
;
3129 /* Vtable overrides and methods were already cloned, so don't reclone them. */
3130 if (new_sub
->vtable_index
== -1
3131 && !(old_sub
->comp_flags
& SUB_COMP_FLAG_METHOD
))
3132 Parrot_store_sub_in_namespace(interp
, new_sub_pmc
);
3134 ret
->u
.key
= new_sub_pmc
;
3145 =item C<static PackFile_Constant ** find_constants(PARROT_INTERP,
3146 PackFile_ConstTable *ct)>
3148 Finds the constant table associated with a thread. For now, we need to copy
3149 constant tables because some entries aren't really constant; e.g. subroutines
3150 need to refer to namespace pointers.
3156 PARROT_WARN_UNUSED_RESULT
3157 PARROT_CANNOT_RETURN_NULL
3158 static PackFile_Constant
**
3159 find_constants(PARROT_INTERP
, ARGIN(PackFile_ConstTable
*ct
))
3161 ASSERT_ARGS(find_constants
)
3163 || !interp
->thread_data
3164 || interp
->thread_data
->tid
== 0)
3165 return ct
->constants
;
3168 PackFile_Constant
**new_consts
;
3170 PARROT_ASSERT(interp
->thread_data
);
3172 if (!interp
->thread_data
->const_tables
) {
3173 interp
->thread_data
->const_tables
= parrot_new_pointer_hash(interp
);
3176 tables
= interp
->thread_data
->const_tables
;
3177 new_consts
= (PackFile_Constant
**)parrot_hash_get(interp
, tables
, ct
);
3180 /* need to construct it */
3181 PackFile_Constant
** const old_consts
= ct
->constants
;
3182 INTVAL
const num_consts
= ct
->const_count
;
3185 new_consts
= mem_gc_allocate_n_zeroed_typed(interp
,
3186 num_consts
, PackFile_Constant
*);
3188 for (i
= 0; i
< num_consts
; ++i
)
3189 new_consts
[i
] = clone_constant(interp
, old_consts
[i
]);
3191 parrot_hash_put(interp
, tables
, ct
, new_consts
);
3201 =item C<void Parrot_destroy_constants(PARROT_INTERP)>
3203 Destroys the constants for an interpreter.
3211 Parrot_destroy_constants(PARROT_INTERP
)
3213 ASSERT_ARGS(Parrot_destroy_constants
)
3217 if (!interp
->thread_data
)
3220 hash
= interp
->thread_data
->const_tables
;
3225 for (i
= 0; i
<= hash
->mask
; ++i
) {
3226 HashBucket
*bucket
= hash
->bi
[i
];
3229 PackFile_ConstTable
* const table
=
3230 (PackFile_ConstTable
*)bucket
->key
;
3231 PackFile_Constant
** const orig_consts
= table
->constants
;
3232 PackFile_Constant
** const consts
=
3233 (PackFile_Constant
**) bucket
->value
;
3236 for (j
= 0; j
< table
->const_count
; ++j
) {
3237 if (consts
[j
] != orig_consts
[j
])
3238 mem_gc_free(interp
, consts
[j
]);
3241 mem_gc_free(interp
, consts
);
3242 bucket
= bucket
->next
;
3246 parrot_hash_destroy(interp
, hash
);
3254 =head2 PackFile FixupTable Structure Functions
3258 =item C<void PackFile_FixupTable_clear(PARROT_INTERP, PackFile_FixupTable
3261 Clears a PackFile FixupTable.
3269 PackFile_FixupTable_clear(PARROT_INTERP
, ARGMOD(PackFile_FixupTable
*self
))
3271 ASSERT_ARGS(PackFile_FixupTable_clear
)
3274 Parrot_io_eprintf(interp
, "PackFile_FixupTable_clear: self == NULL!\n");
3278 if (self
->fixup_count
) {
3280 for (i
= 0; i
< self
->fixup_count
; ++i
) {
3281 mem_gc_free(interp
, self
->fixups
[i
].name
);
3282 self
->fixups
[i
].name
= NULL
;
3284 mem_gc_free(interp
, self
->fixups
);
3286 self
->fixups
= NULL
;
3287 self
->fixup_count
= 0;
3295 =item C<static void fixup_destroy(PARROT_INTERP, PackFile_Segment *self)>
3297 Calls C<PackFile_FixupTable_clear()> with C<self>.
3304 fixup_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
3306 ASSERT_ARGS(fixup_destroy
)
3307 PackFile_FixupTable
* const ft
= (PackFile_FixupTable
*)self
;
3308 PackFile_FixupTable_clear(interp
, ft
);
3314 =item C<static size_t fixup_packed_size(PARROT_INTERP, PackFile_Segment *self)>
3316 I<What does this do?>
3323 fixup_packed_size(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
3325 ASSERT_ARGS(fixup_packed_size
)
3326 PackFile_FixupTable
* const ft
= (PackFile_FixupTable
*)self
;
3330 for (i
= 0; i
< ft
->fixup_count
; ++i
) {
3331 /* fixup_entry type */
3333 switch (ft
->fixups
[i
].type
) {
3334 case enum_fixup_sub
:
3335 size
+= PF_size_cstring(ft
->fixups
[i
].name
);
3336 ++size
; /* offset */
3338 case enum_fixup_none
:
3341 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
3342 "Unknown fixup type\n");
3352 =item C<static opcode_t * fixup_pack(PARROT_INTERP, PackFile_Segment *self,
3355 Packs the fixup table for a given packfile.
3361 PARROT_WARN_UNUSED_RESULT
3362 PARROT_CANNOT_RETURN_NULL
3364 fixup_pack(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
), ARGOUT(opcode_t
*cursor
))
3366 ASSERT_ARGS(fixup_pack
)
3367 PackFile_FixupTable
* const ft
= (PackFile_FixupTable
*)self
;
3370 *cursor
++ = ft
->fixup_count
;
3372 for (i
= 0; i
< ft
->fixup_count
; ++i
) {
3373 *cursor
++ = (opcode_t
) ft
->fixups
[i
].type
;
3374 switch (ft
->fixups
[i
].type
) {
3375 case enum_fixup_sub
:
3376 cursor
= PF_store_cstring(cursor
, ft
->fixups
[i
].name
);
3377 *cursor
++ = ft
->fixups
[i
].offset
;
3379 case enum_fixup_none
:
3382 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
3383 "Unknown fixup type\n");
3393 =item C<static PackFile_Segment * fixup_new(PARROT_INTERP, PackFile *pf, STRING
3396 Returns a new C<PackFile_FixupTable> segment.
3402 PARROT_WARN_UNUSED_RESULT
3403 PARROT_CANNOT_RETURN_NULL
3404 static PackFile_Segment
*
3405 fixup_new(PARROT_INTERP
, SHIM(PackFile
*pf
), SHIM(STRING
*name
), SHIM(int add
))
3407 ASSERT_ARGS(fixup_new
)
3408 PackFile_FixupTable
* const fixup
= mem_gc_allocate_zeroed_typed(interp
,
3409 PackFile_FixupTable
);
3411 return (PackFile_Segment
*) fixup
;
3417 =item C<static const opcode_t * fixup_unpack(PARROT_INTERP, PackFile_Segment
3418 *seg, const opcode_t *cursor)>
3420 Unpacks a PackFile FixupTable from a block of memory, given a cursor.
3422 Returns one (1) if everything is okay, else zero (0).
3428 PARROT_WARN_UNUSED_RESULT
3429 PARROT_CAN_RETURN_NULL
3430 static const opcode_t
*
3431 fixup_unpack(PARROT_INTERP
, ARGIN(PackFile_Segment
*seg
), ARGIN(const opcode_t
*cursor
))
3433 ASSERT_ARGS(fixup_unpack
)
3434 PackFile_FixupTable
* const self
= (PackFile_FixupTable
*)seg
;
3439 Parrot_io_eprintf(interp
,
3440 "PackFile_FixupTable_unpack: self == NULL!\n");
3444 PackFile_FixupTable_clear(interp
, self
);
3447 self
->fixup_count
= PF_fetch_opcode(pf
, &cursor
);
3449 TRACE_PRINTF(("PackFile_FixupTable_unpack(): %ld entries\n",
3450 self
->fixup_count
));
3452 if (self
->fixup_count
) {
3453 self
->fixups
= mem_gc_allocate_n_zeroed_typed(interp
,
3454 self
->fixup_count
, PackFile_FixupEntry
);
3456 if (!self
->fixups
) {
3457 Parrot_io_eprintf(interp
,
3458 "PackFile_FixupTable_unpack: Could not allocate "
3459 "memory for array!\n");
3460 self
->fixup_count
= 0;
3465 for (i
= 0; i
< self
->fixup_count
; ++i
) {
3466 PackFile_FixupEntry
* const entry
= self
->fixups
+ i
;
3468 entry
->type
= PF_fetch_opcode(pf
, &cursor
);
3470 switch (entry
->type
) {
3471 case enum_fixup_sub
:
3472 entry
->name
= PF_fetch_cstring(interp
, pf
, &cursor
);
3473 entry
->offset
= PF_fetch_opcode(pf
, &cursor
);
3474 TRACE_PRINTF_VAL(("PackFile_FixupTable_unpack(): type %d, "
3475 "name %s, offset %ld\n",
3476 entry
->type
, entry
->name
, entry
->offset
));
3478 case enum_fixup_none
:
3481 Parrot_io_eprintf(interp
,
3482 "PackFile_FixupTable_unpack: Unknown fixup type %d!\n",
3494 =item C<void PackFile_FixupTable_new_entry(PARROT_INTERP, const char *label,
3495 INTVAL type, opcode_t offs)>
3497 Adds a new fix-up entry with label and type. Creates a new PackFile FixupTable
3506 PackFile_FixupTable_new_entry(PARROT_INTERP
,
3507 ARGIN(const char *label
), INTVAL type
, opcode_t offs
)
3509 ASSERT_ARGS(PackFile_FixupTable_new_entry
)
3510 PackFile_FixupTable
*self
= interp
->code
->fixups
;
3514 self
= (PackFile_FixupTable
*) PackFile_Segment_new_seg(
3515 interp
, interp
->code
->base
.dir
, PF_FIXUP_SEG
,
3516 FIXUP_TABLE_SEGMENT_NAME
, 1);
3518 interp
->code
->fixups
= self
;
3519 self
->code
= interp
->code
;
3522 i
= self
->fixup_count
++;
3523 self
->fixups
= mem_gc_realloc_n_typed_zeroed(interp
,
3524 self
->fixups
, self
->fixup_count
, i
, PackFile_FixupEntry
);
3526 self
->fixups
[i
].type
= type
;
3527 self
->fixups
[i
].name
= mem_sys_strdup(label
);
3528 self
->fixups
[i
].offset
= offs
;
3534 =item C<static PackFile_FixupEntry * find_fixup(PackFile_FixupTable *ft, INTVAL
3535 type, const char *name)>
3537 Finds the fix-up entry in a given FixupTable C<ft> for C<type> and C<name> and
3540 This ignores directories. For a recursive version see
3541 C<PackFile_find_fixup_entry()>.
3547 PARROT_WARN_UNUSED_RESULT
3548 PARROT_CAN_RETURN_NULL
3549 static PackFile_FixupEntry
*
3550 find_fixup(ARGMOD(PackFile_FixupTable
*ft
), INTVAL type
, ARGIN(const char *name
))
3552 ASSERT_ARGS(find_fixup
)
3554 for (i
= 0; i
< ft
->fixup_count
; ++i
) {
3555 if ((INTVAL
)((enum_fixup_t
)ft
->fixups
[i
].type
) == type
3556 && STREQ(ft
->fixups
[i
].name
, name
)) {
3557 return ft
->fixups
+ i
;
3567 =item C<static INTVAL find_fixup_iter(PARROT_INTERP, PackFile_Segment *seg, void
3570 Internal iterator for C<PackFile_find_fixup_entry>; recurses into directories.
3577 find_fixup_iter(PARROT_INTERP
, ARGIN(PackFile_Segment
*seg
), ARGIN(void *user_data
))
3579 ASSERT_ARGS(find_fixup_iter
)
3580 if (seg
->type
== PF_DIR_SEG
) {
3581 if (PackFile_map_segments(interp
, (PackFile_Directory
*)seg
,
3582 find_fixup_iter
, user_data
))
3585 else if (seg
->type
== PF_FIXUP_SEG
) {
3586 PackFile_FixupEntry
** const e
= (PackFile_FixupEntry
**)user_data
;
3587 PackFile_FixupEntry
* const fe
= (PackFile_FixupEntry
*)find_fixup(
3588 (PackFile_FixupTable
*) seg
, (*e
)->type
, (*e
)->name
);
3602 =item C<PackFile_FixupEntry * PackFile_find_fixup_entry(PARROT_INTERP, INTVAL
3605 Searches the whole PackFile recursively for a fix-up entry with the given
3606 C<type> and C<name>, and returns the found entry or NULL.
3608 This also recurses into directories, compared to the simplier C<find_fixup>
3609 which just searches one PackFile_FixupTable.
3616 PARROT_WARN_UNUSED_RESULT
3617 PARROT_CAN_RETURN_NULL
3618 PackFile_FixupEntry
*
3619 PackFile_find_fixup_entry(PARROT_INTERP
, INTVAL type
, ARGIN(char *name
))
3621 ASSERT_ARGS(PackFile_find_fixup_entry
)
3623 /* TODO make a hash of all fixups */
3624 PackFile_Directory
* const dir
= interp
->code
->base
.dir
;
3625 PackFile_FixupEntry
* const ep
= mem_gc_allocate_zeroed_typed(interp
, PackFile_FixupEntry
);
3630 if (PackFile_map_segments(interp
, dir
, find_fixup_iter
, (void *) ep
))
3641 =head2 PackFile ConstTable Structure Functions
3645 =item C<void PackFile_ConstTable_clear(PARROT_INTERP, PackFile_ConstTable
3648 Clear the C<PackFile_ConstTable> C<self>.
3656 PackFile_ConstTable_clear(PARROT_INTERP
, ARGMOD(PackFile_ConstTable
*self
))
3658 ASSERT_ARGS(PackFile_ConstTable_clear
)
3661 for (i
= 0; i
< self
->const_count
; ++i
) {
3662 PackFile_Constant_destroy(interp
, self
->constants
[i
]);
3663 self
->constants
[i
] = NULL
;
3666 if (self
->constants
) {
3667 mem_gc_free(interp
, self
->constants
);
3668 self
->constants
= NULL
;
3671 self
->const_count
= 0;
3679 =item C<const opcode_t * PackFile_ConstTable_unpack(PARROT_INTERP,
3680 PackFile_Segment *seg, const opcode_t *cursor)>
3682 Unpacks a PackFile ConstTable from a block of memory. The format is:
3684 opcode_t const_count
3687 Returns cursor if everything is OK, else zero (0).
3694 PARROT_WARN_UNUSED_RESULT
3695 PARROT_CAN_RETURN_NULL
3697 PackFile_ConstTable_unpack(PARROT_INTERP
, ARGIN(PackFile_Segment
*seg
),
3698 ARGIN(const opcode_t
*cursor
))
3700 ASSERT_ARGS(PackFile_ConstTable_unpack
)
3701 PackFile_ConstTable
* const self
= (PackFile_ConstTable
*)seg
;
3702 PackFile
* const pf
= seg
->pf
;
3705 PackFile_ConstTable_clear(interp
, self
);
3707 self
->const_count
= PF_fetch_opcode(pf
, &cursor
);
3709 TRACE_PRINTF(("PackFile_ConstTable_unpack: Unpacking %ld constants\n",
3710 self
->const_count
));
3712 if (self
->const_count
== 0)
3715 self
->constants
= mem_gc_allocate_n_zeroed_typed(interp
, self
->const_count
,
3716 PackFile_Constant
*);
3718 if (!self
->constants
) {
3719 Parrot_io_eprintf(interp
,
3720 "PackFile_ConstTable_unpack: Could not allocate memory for array!\n");
3721 self
->const_count
= 0;
3725 for (i
= 0; i
< self
->const_count
; ++i
) {
3726 TRACE_PRINTF(("PackFile_ConstTable_unpack(): Unpacking constant %ld/%ld\n",
3727 i
, self
->const_count
));
3728 self
->constants
[i
] = PackFile_Constant_new(interp
);
3730 cursor
= PackFile_Constant_unpack(interp
, self
, self
->constants
[i
],
3740 =item C<static PackFile_Segment * const_new(PARROT_INTERP, PackFile *pf, STRING
3743 Returns a new C<PackFile_ConstTable> segment.
3750 PARROT_CANNOT_RETURN_NULL
3751 static PackFile_Segment
*
3752 const_new(PARROT_INTERP
, SHIM(PackFile
*pf
), SHIM(STRING
*name
), SHIM(int add
))
3754 ASSERT_ARGS(const_new
)
3755 PackFile_ConstTable
* const const_table
=
3756 mem_gc_allocate_zeroed_typed(interp
, PackFile_ConstTable
);
3758 return (PackFile_Segment
*)const_table
;
3764 =item C<static void const_destroy(PARROT_INTERP, PackFile_Segment *self)>
3766 Destroys the C<PackFile_ConstTable> C<self>.
3773 const_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
3775 ASSERT_ARGS(const_destroy
)
3776 PackFile_ConstTable
* const ct
= (PackFile_ConstTable
*)self
;
3777 PackFile_ConstTable_clear(interp
, ct
);
3785 =head2 PackFile Constant Structure Functions
3789 =item C<PackFile_Constant * PackFile_Constant_new(PARROT_INTERP)>
3791 Allocates a new empty PackFile Constant.
3793 This is only here so we can make a new one and then do an unpack.
3801 PARROT_CANNOT_RETURN_NULL
3803 PackFile_Constant_new(PARROT_INTERP
)
3805 ASSERT_ARGS(PackFile_Constant_new
)
3806 PackFile_Constant
* const self
= mem_gc_allocate_typed(interp
,
3809 self
->type
= PFC_NONE
;
3817 =item C<void PackFile_Constant_destroy(PARROT_INTERP, PackFile_Constant *self)>
3819 Deletes the C<PackFile_Constant> C<self>.
3821 Don't delete C<PMC>s or C<STRING>s. The GC will claim them.
3829 PackFile_Constant_destroy(PARROT_INTERP
, ARGMOD_NULLOK(PackFile_Constant
*self
))
3831 ASSERT_ARGS(PackFile_Constant_destroy
)
3832 mem_gc_free(interp
, self
);
3838 =item C<size_t PackFile_Constant_pack_size(PARROT_INTERP, const
3839 PackFile_Constant *self, const PackFile_ConstTable *ct)>
3841 Determines the size of the buffer needed in order to pack the PackFile Constant
3842 into a contiguous region of memory.
3849 PARROT_WARN_UNUSED_RESULT
3851 PackFile_Constant_pack_size(PARROT_INTERP
, ARGIN(const PackFile_Constant
*self
), ARGIN(const
3852 PackFile_ConstTable
*ct
))
3854 ASSERT_ARGS(PackFile_Constant_pack_size
)
3858 switch (self
->type
) {
3860 packed_size
= PF_size_number();
3864 packed_size
= PF_size_string(self
->u
.string
);
3870 for (component
= self
->u
.key
; component
;){
3872 GETATTR_Key_next_key(interp
, component
, component
);
3877 component
= self
->u
.key
; /* the pmc (Sub, ...) */
3878 packed_size
= PF_size_strlen(Parrot_freeze_pbc_size(interp
, component
, ct
));
3882 Parrot_io_eprintf(NULL
,
3883 "Constant_packed_size: Unrecognized type '%c'!\n",
3888 /* Tack on space for the initial type field */
3889 return packed_size
+ 1;
3895 =item C<const opcode_t * PackFile_Constant_unpack(PARROT_INTERP,
3896 PackFile_ConstTable *constt, PackFile_Constant *self, const opcode_t *cursor)>
3898 Unpacks a PackFile Constant from a block of memory. The format is:
3903 Returns cursor if everything is okay, else NULL.
3910 PARROT_WARN_UNUSED_RESULT
3911 PARROT_CAN_RETURN_NULL
3913 PackFile_Constant_unpack(PARROT_INTERP
, ARGIN(PackFile_ConstTable
*constt
),
3914 ARGOUT(PackFile_Constant
*self
), ARGIN(const opcode_t
*cursor
))
3916 ASSERT_ARGS(PackFile_Constant_unpack
)
3917 PackFile
* const pf
= constt
->base
.pf
;
3918 const opcode_t type
= PF_fetch_opcode(pf
, &cursor
);
3920 TRACE_PRINTF(("PackFile_Constant_unpack(): Type is %ld ('%c')...\n",
3925 self
->u
.number
= PF_fetch_number(pf
, &cursor
);
3926 self
->type
= PFC_NUMBER
;
3930 self
->u
.string
= PF_fetch_string(interp
, pf
, &cursor
);
3931 self
->type
= PFC_STRING
;
3935 cursor
= PackFile_Constant_unpack_key(interp
, constt
, self
, cursor
);
3939 cursor
= PackFile_Constant_unpack_pmc(interp
, constt
, self
, cursor
);
3942 Parrot_io_eprintf(NULL
,
3943 "Constant_unpack: Unrecognized type '%c' during unpack!\n",
3954 =item C<const opcode_t * PackFile_Constant_unpack_pmc(PARROT_INTERP,
3955 PackFile_ConstTable *constt, PackFile_Constant *self, const opcode_t *cursor)>
3957 Unpacks a constant PMC.
3964 PARROT_WARN_UNUSED_RESULT
3965 PARROT_CANNOT_RETURN_NULL
3967 PackFile_Constant_unpack_pmc(PARROT_INTERP
, ARGIN(PackFile_ConstTable
*constt
),
3968 ARGMOD(PackFile_Constant
*self
), ARGIN(const opcode_t
*cursor
))
3970 ASSERT_ARGS(PackFile_Constant_unpack_pmc
)
3971 PackFile
* const pf
= constt
->base
.pf
;
3972 STRING
*_sub
= CONST_STRING(interp
, "Sub");
3976 /* thawing the PMC needs the real packfile in place */
3977 PackFile_ByteCode
* const cs_save
= interp
->code
;
3978 interp
->code
= pf
->cur_cs
;
3979 image
= PF_fetch_string(interp
, pf
, &cursor
);
3981 pmc
= Parrot_thaw_pbc(interp
, image
, constt
);
3983 /* place item in const_table */
3984 self
->type
= PFC_PMC
;
3987 /* finally place the sub into some namespace stash
3988 * XXX place this code in Sub.thaw ? */
3989 if (VTABLE_isa(interp
, pmc
, _sub
))
3990 Parrot_store_sub_in_namespace(interp
, pmc
);
3993 interp
->code
= cs_save
;
4001 =item C<const opcode_t * PackFile_Constant_unpack_key(PARROT_INTERP,
4002 PackFile_ConstTable *constt, PackFile_Constant *self, const opcode_t *cursor)>
4004 Unpacks a PackFile Constant from a block of memory. The format consists of a
4005 sequence of key atoms, each with the following format:
4010 Returns cursor if everything is OK, else NULL.
4017 PARROT_WARN_UNUSED_RESULT
4018 PARROT_CAN_RETURN_NULL
4020 PackFile_Constant_unpack_key(PARROT_INTERP
, ARGIN(PackFile_ConstTable
*constt
),
4021 ARGMOD(PackFile_Constant
*self
), ARGIN(const opcode_t
*cursor
))
4023 ASSERT_ARGS(PackFile_Constant_unpack_key
)
4024 PackFile
* const pf
= constt
->base
.pf
;
4027 INTVAL components
= (INTVAL
)PF_fetch_opcode(pf
, &cursor
);
4028 int pmc_enum
= enum_class_Key
;
4030 while (components
-- > 0) {
4031 opcode_t type
= PF_fetch_opcode(pf
, &cursor
);
4035 SETATTR_Key_next_key(interp
, tail
, Parrot_pmc_new_constant(interp
, pmc_enum
));
4036 GETATTR_Key_next_key(interp
, tail
, tail
);
4039 head
= tail
= Parrot_pmc_new_constant(interp
, pmc_enum
);
4041 op
= PF_fetch_opcode(pf
, &cursor
);
4045 key_set_integer(interp
, tail
, op
);
4048 key_set_number(interp
, tail
, constt
->constants
[op
]->u
.number
);
4051 key_set_string(interp
, tail
, constt
->constants
[op
]->u
.string
);
4054 key_set_register(interp
, tail
, op
, KEY_integer_FLAG
);
4057 key_set_register(interp
, tail
, op
, KEY_number_FLAG
);
4060 key_set_register(interp
, tail
, op
, KEY_string_FLAG
);
4063 key_set_register(interp
, tail
, op
, KEY_pmc_FLAG
);
4070 self
->type
= PFC_KEY
;
4079 =item C<PackFile_Segment * PackFile_Annotations_new(PARROT_INTERP, struct
4080 PackFile *pf, STRING *name, int add)>
4082 Creates a new annotations segment structure. Ignores the parameters C<name> and
4089 PARROT_CANNOT_RETURN_NULL
4091 PackFile_Annotations_new(PARROT_INTERP
, SHIM(struct PackFile
*pf
),
4092 SHIM(STRING
*name
), SHIM(int add
))
4094 ASSERT_ARGS(PackFile_Annotations_new
)
4096 /* Allocate annotations structure; create it all zeroed, and we will
4097 * allocate memory for each of the arrays on demand. */
4098 PackFile_Annotations
* const seg
= mem_gc_allocate_zeroed_typed(interp
,
4099 PackFile_Annotations
);
4100 return (PackFile_Segment
*) seg
;
4106 =item C<void PackFile_Annotations_destroy(PARROT_INTERP, PackFile_Segment *seg)>
4108 Frees all memory associated with an annotations segment.
4115 PackFile_Annotations_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*seg
))
4117 ASSERT_ARGS(PackFile_Annotations_destroy
)
4118 PackFile_Annotations
*self
= (PackFile_Annotations
*)seg
;
4121 /* Free any keys. */
4123 mem_gc_free(interp
, self
->keys
);
4125 /* Free any groups. */
4127 mem_gc_free(interp
, self
->groups
);
4129 /* Free any entries. */
4131 mem_gc_free(interp
, self
->entries
);
4137 =item C<size_t PackFile_Annotations_packed_size(PARROT_INTERP, PackFile_Segment
4140 Computes the number of opcode_ts needed to store the passed annotations
4147 PARROT_WARN_UNUSED_RESULT
4149 PackFile_Annotations_packed_size(SHIM_INTERP
, ARGIN(PackFile_Segment
*seg
))
4151 ASSERT_ARGS(PackFile_Annotations_packed_size
)
4152 const PackFile_Annotations
* const self
= (PackFile_Annotations
*)seg
;
4153 return 3 /* Counts. */
4154 + self
->num_keys
* 2 /* Keys. */
4155 + self
->num_groups
* 2 /* Groups. */
4156 + self
->num_entries
* 3; /* Entries. */
4162 =item C<opcode_t * PackFile_Annotations_pack(PARROT_INTERP, PackFile_Segment
4163 *seg, opcode_t *cursor)>
4165 Packs this segment into bytecode.
4171 PARROT_WARN_UNUSED_RESULT
4172 PARROT_CANNOT_RETURN_NULL
4174 PackFile_Annotations_pack(SHIM_INTERP
, ARGIN(PackFile_Segment
*seg
),
4175 ARGMOD(opcode_t
*cursor
))
4177 ASSERT_ARGS(PackFile_Annotations_pack
)
4178 const PackFile_Annotations
* const self
= (PackFile_Annotations
*)seg
;
4181 /* Write key count and any keys. */
4182 *cursor
++ = self
->num_keys
;
4184 for (i
= 0; i
< self
->num_keys
; ++i
) {
4185 const PackFile_Annotations_Key
* const key
= self
->keys
+ i
;
4186 *cursor
++ = key
->name
;
4187 *cursor
++ = key
->type
;
4190 /* Write group count and any groups. */
4191 *cursor
++ = self
->num_groups
;
4193 for (i
= 0; i
< self
->num_groups
; ++i
) {
4194 const PackFile_Annotations_Group
* const group
= self
->groups
+ i
;
4195 *cursor
++ = group
->bytecode_offset
;
4196 *cursor
++ = group
->entries_offset
;
4199 /* Write entry count and any entries. */
4200 *cursor
++ = self
->num_entries
;
4202 for (i
= 0; i
< self
->num_entries
; ++i
) {
4203 const PackFile_Annotations_Entry
* const entry
= self
->entries
+ i
;
4204 *cursor
++ = entry
->bytecode_offset
;
4205 *cursor
++ = entry
->key
;
4206 *cursor
++ = entry
->value
;
4215 =item C<const opcode_t * PackFile_Annotations_unpack(PARROT_INTERP,
4216 PackFile_Segment *seg, const opcode_t *cursor)>
4218 Unpacks this segment from the bytecode.
4224 PARROT_CANNOT_RETURN_NULL
4226 PackFile_Annotations_unpack(PARROT_INTERP
, ARGMOD(PackFile_Segment
*seg
),
4227 ARGIN(const opcode_t
*cursor
))
4229 ASSERT_ARGS(PackFile_Annotations_unpack
)
4230 PackFile_Annotations
* const self
= (PackFile_Annotations
*)seg
;
4231 PackFile_ByteCode
*code
;
4234 PackFile
* const pf
= seg
->pf
;
4239 self
->num_keys
= PF_fetch_opcode(seg
->pf
, &cursor
);
4241 TRACE_PRINTF(("PackFile_Annotations_unpack: Unpacking %ld keys\n",
4244 self
->keys
= mem_gc_allocate_n_zeroed_typed(interp
,
4245 self
->num_keys
, PackFile_Annotations_Key
);
4247 for (i
= 0; i
< self
->num_keys
; ++i
) {
4248 PackFile_Annotations_Key
* const key
= self
->keys
+ i
;
4249 key
->name
= PF_fetch_opcode(seg
->pf
, &cursor
);
4250 key
->type
= PF_fetch_opcode(seg
->pf
, &cursor
);
4251 TRACE_PRINTF_VAL(("PackFile_Annotations_unpack: key[%d]/%d name=%s type=%d\n",
4252 i
, self
->num_keys
, key
->name
, key
->type
));
4255 /* Unpack groups. */
4256 self
->num_groups
= PF_fetch_opcode(seg
->pf
, &cursor
);
4257 self
->groups
= mem_gc_allocate_n_zeroed_typed(interp
,
4258 self
->num_groups
, PackFile_Annotations_Group
);
4260 for (i
= 0; i
< self
->num_groups
; ++i
) {
4261 PackFile_Annotations_Group
* const group
= self
->groups
+ i
;
4262 group
->bytecode_offset
= PF_fetch_opcode(seg
->pf
, &cursor
);
4263 group
->entries_offset
= PF_fetch_opcode(seg
->pf
, &cursor
);
4265 "PackFile_Annotations_unpack: group[%d]/%d bytecode_offset=%d entries_offset=%d\n",
4266 i
, self
->num_groups
, group
->bytecode_offset
,
4267 group
->entries_offset
));
4270 /* Unpack entries. */
4271 self
->num_entries
= PF_fetch_opcode(seg
->pf
, &cursor
);
4272 self
->entries
= mem_gc_allocate_n_zeroed_typed(interp
,
4273 self
->num_entries
, PackFile_Annotations_Entry
);
4274 for (i
= 0; i
< self
->num_entries
; ++i
) {
4275 PackFile_Annotations_Entry
* const entry
= self
->entries
+ i
;
4276 entry
->bytecode_offset
= PF_fetch_opcode(seg
->pf
, &cursor
);
4277 entry
->key
= PF_fetch_opcode(seg
->pf
, &cursor
);
4278 entry
->value
= PF_fetch_opcode(seg
->pf
, &cursor
);
4281 /* Need to associate this segment with the applicable code segment. */
4282 str_len
= Parrot_str_length(interp
, self
->base
.name
);
4283 code_name
= Parrot_str_substr(interp
, self
->base
.name
, 0, str_len
- 4);
4284 code
= (PackFile_ByteCode
*)PackFile_find_segment(interp
,
4285 self
->base
.dir
, code_name
, 0);
4287 if (!code
|| code
->base
.type
!= PF_BYTEC_SEG
) {
4288 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
4289 "Code '%s' not found for annotations segment '%s'\n",
4290 code_name
, self
->base
.name
);
4294 code
->annotations
= self
;
4302 =item C<void PackFile_Annotations_dump(PARROT_INTERP, const PackFile_Segment
4305 Produces a dump of the annotations segment.
4312 PackFile_Annotations_dump(PARROT_INTERP
, ARGIN(const PackFile_Segment
*seg
))
4314 ASSERT_ARGS(PackFile_Annotations_dump
)
4315 const PackFile_Annotations
* const self
= (const PackFile_Annotations
*)seg
;
4318 default_dump_header(interp
, (const PackFile_Segment
*)self
);
4321 Parrot_io_printf(interp
, "\n keys => [\n");
4322 for (i
= 0; i
< self
->num_keys
; ++i
) {
4323 const PackFile_Annotations_Key
* const key
= self
->keys
+ i
;
4324 Parrot_io_printf(interp
, " #%d\n [\n", i
);
4325 Parrot_io_printf(interp
, " NAME => %Ss\n",
4326 PF_CONST(self
->code
, key
->name
)->u
.string
);
4327 Parrot_io_printf(interp
, " TYPE => %s\n",
4328 key
->type
== PF_ANNOTATION_KEY_TYPE_INT
? "integer" :
4329 key
->type
== PF_ANNOTATION_KEY_TYPE_STR
? "string" :
4330 key
->type
== PF_ANNOTATION_KEY_TYPE_NUM
? "number" :
4332 Parrot_io_printf(interp
, " ],\n");
4335 Parrot_io_printf(interp
, " ],\n");
4338 Parrot_io_printf(interp
, "\n groups => [\n");
4339 for (i
= 0; i
< self
->num_groups
; ++i
) {
4340 const PackFile_Annotations_Group
* const group
= self
->groups
+ i
;
4341 Parrot_io_printf(interp
, " #%d\n [\n", i
);
4342 Parrot_io_printf(interp
, " BYTECODE_OFFSET => %d\n",
4343 group
->bytecode_offset
);
4344 Parrot_io_printf(interp
, " ENTRIES_OFFSET => %d\n",
4345 group
->entries_offset
);
4346 Parrot_io_printf(interp
, " ],\n");
4349 Parrot_io_printf(interp
, " ],\n");
4352 Parrot_io_printf(interp
, "\n entries => [\n");
4354 for (i
= 0; i
< self
->num_entries
; ++i
) {
4355 const PackFile_Annotations_Entry
* const entry
= self
->entries
+ i
;
4356 Parrot_io_printf(interp
, " #%d\n [\n", i
);
4357 Parrot_io_printf(interp
, " BYTECODE_OFFSET => %d\n",
4358 entry
->bytecode_offset
);
4359 Parrot_io_printf(interp
, " KEY => %d\n",
4361 Parrot_io_printf(interp
, " VALUE => %d\n",
4363 Parrot_io_printf(interp
, " ],\n");
4366 Parrot_io_printf(interp
, " ],\n");
4367 Parrot_io_printf(interp
, "],\n");
4373 =item C<void PackFile_Annotations_add_group(PARROT_INTERP, PackFile_Annotations
4374 *self, opcode_t offset)>
4376 Starts a new bytecode annotation group. Takes the offset in the bytecode where
4377 the new annotations group starts.
4384 PackFile_Annotations_add_group(PARROT_INTERP
, ARGMOD(PackFile_Annotations
*self
),
4387 ASSERT_ARGS(PackFile_Annotations_add_group
)
4388 PackFile_Annotations_Group
*group
;
4390 /* Allocate extra space for the group in the groups array. */
4392 self
->groups
= mem_gc_realloc_n_typed_zeroed(interp
, self
->groups
,
4393 1 + self
->num_groups
, self
->num_groups
, PackFile_Annotations_Group
);
4395 self
->groups
= mem_gc_allocate_n_typed(interp
,
4396 1 + self
->num_groups
, PackFile_Annotations_Group
);
4398 /* Store details. */
4399 group
= self
->groups
+ self
->num_groups
;
4400 group
->bytecode_offset
= offset
;
4401 group
->entries_offset
= self
->num_entries
;
4403 /* Increment group count. */
4410 =item C<void PackFile_Annotations_add_entry(PARROT_INTERP, PackFile_Annotations
4411 *self, opcode_t offset, opcode_t key, opcode_t type, opcode_t value)>
4413 Adds a new bytecode annotation entry. Takes the annotations segment to add the
4414 entry to, the current bytecode offset (assumed to be the greatest one so far in
4415 the currently active group), the annotation key (as an index into the constats
4416 table), the annotation value type (one of PF_ANNOTATION_KEY_TYPE_INT,
4417 PF_ANNOTATION_KEY_TYPE_STR or PF_ANNOTATION_KEY_TYPE_NUM) and the value. The
4418 value will be an integer literal in the case of type being
4419 PF_ANNOTATION_KEY_TYPE_INT, or an index into the constants table otherwise.
4426 PackFile_Annotations_add_entry(PARROT_INTERP
, ARGMOD(PackFile_Annotations
*self
),
4427 opcode_t offset
, opcode_t key
, opcode_t type
, opcode_t value
)
4429 ASSERT_ARGS(PackFile_Annotations_add_entry
)
4430 /* See if we already have this key. */
4431 STRING
* const key_name
= PF_CONST(self
->code
, key
)->u
.string
;
4432 opcode_t key_id
= -1;
4435 for (i
= 0; i
< self
->num_keys
; ++i
) {
4436 STRING
* const test_key
= PF_CONST(self
->code
, self
->keys
[i
].name
)->u
.string
;
4437 if (Parrot_str_equal(interp
, test_key
, key_name
)) {
4444 /* We do have it. Add key entry. */
4446 self
->keys
= mem_gc_realloc_n_typed_zeroed(interp
, self
->keys
,
4447 1 + self
->num_keys
, self
->num_keys
, PackFile_Annotations_Key
);
4449 self
->keys
= mem_gc_allocate_n_typed(interp
,
4450 1 + self
->num_keys
, PackFile_Annotations_Key
);
4452 key_id
= self
->num_keys
;
4456 self
->keys
[key_id
].name
= key
;
4457 self
->keys
[key_id
].type
= type
;
4460 /* Ensure key types are compatible. */
4461 if (self
->keys
[key_id
].type
!= type
)
4462 Parrot_ex_throw_from_c_args(interp
, NULL
,
4463 EXCEPTION_INVALID_OPERATION
,
4464 "Annotations with different types of value used for key '%S'\n",
4468 /* Add annotations entry. */
4470 self
->entries
= mem_gc_realloc_n_typed(interp
, self
->entries
,
4471 1 + self
->num_entries
, PackFile_Annotations_Entry
);
4473 self
->entries
= mem_gc_allocate_n_typed(interp
,
4474 1 + self
->num_entries
, PackFile_Annotations_Entry
);
4476 self
->entries
[self
->num_entries
].bytecode_offset
= offset
;
4477 self
->entries
[self
->num_entries
].key
= key_id
;
4478 self
->entries
[self
->num_entries
].value
= value
;
4480 ++self
->num_entries
;
4486 =item C<static PMC * make_annotation_value_pmc(PARROT_INTERP,
4487 PackFile_Annotations *self, INTVAL type, opcode_t value)>
4489 Makes a PMC of the right type holding the value. Helper for
4490 C<PackFile_Annotations_lookup()>.
4496 PARROT_CANNOT_RETURN_NULL
4498 make_annotation_value_pmc(PARROT_INTERP
, ARGIN(PackFile_Annotations
*self
),
4499 INTVAL type
, opcode_t value
)
4501 ASSERT_ARGS(make_annotation_value_pmc
)
4505 case PF_ANNOTATION_KEY_TYPE_INT
:
4506 result
= Parrot_pmc_new_init_int(interp
, enum_class_Integer
, value
);
4508 case PF_ANNOTATION_KEY_TYPE_NUM
:
4509 result
= Parrot_pmc_new(interp
, enum_class_Float
);
4510 VTABLE_set_number_native(interp
, result
,
4511 PF_CONST(self
->code
, value
)->u
.number
);
4514 result
= Parrot_pmc_new(interp
, enum_class_String
);
4515 VTABLE_set_string_native(interp
, result
,
4516 PF_CONST(self
->code
, value
)->u
.string
);
4525 =item C<PMC * PackFile_Annotations_lookup(PARROT_INTERP, PackFile_Annotations
4526 *self, opcode_t offset, STRING *key)>
4528 Looks up the annotation(s) in force at the given bytecode offset. If just one
4529 particular annotation is required, it can be passed as key, and the value will
4530 be returned (or a NULL PMC if no annotation of that name is in force).
4531 Otherwise, a Hash will be returned of the all annotations. If there are none in
4532 force, an empty hash will be returned.
4538 PARROT_CANNOT_RETURN_NULL
4540 PackFile_Annotations_lookup(PARROT_INTERP
, ARGIN(PackFile_Annotations
*self
),
4541 opcode_t offset
, ARGIN_NULLOK(STRING
*key
))
4543 ASSERT_ARGS(PackFile_Annotations_lookup
)
4545 INTVAL start_entry
= 0;
4548 /* If we have a key, look up its ID; if we don't find one. */
4549 opcode_t key_id
= -1;
4551 if (!STRING_IS_NULL(key
)) {
4552 for (i
= 0; i
< self
->num_keys
; ++i
) {
4553 STRING
* const test_key
= PF_CONST(self
->code
, self
->keys
[i
].name
)->u
.string
;
4554 if (Parrot_str_equal(interp
, test_key
, key
)) {
4564 /* Use groups to find search start point. */
4565 for (i
= 0; i
< self
->num_groups
; ++i
)
4566 if (offset
< self
->groups
[i
].bytecode_offset
)
4569 start_entry
= self
->groups
[i
].entries_offset
;
4572 /* Look through entries, storing what we find by key and tracking those
4573 * that we have values for. */
4574 opcode_t
*latest_values
= mem_gc_allocate_n_zeroed_typed(interp
,
4575 self
->num_keys
, opcode_t
);
4576 opcode_t
*have_values
= mem_gc_allocate_n_zeroed_typed(interp
,
4577 self
->num_keys
, opcode_t
);
4579 for (i
= start_entry
; i
< self
->num_entries
; ++i
) {
4580 if (self
->entries
[i
].bytecode_offset
>= offset
)
4583 latest_values
[self
->entries
[i
].key
] = self
->entries
[i
].value
;
4584 have_values
[self
->entries
[i
].key
] = 1;
4587 /* Create hash of values we have. */
4588 result
= Parrot_pmc_new(interp
, enum_class_Hash
);
4590 for (i
= 0; i
< self
->num_keys
; ++i
) {
4591 if (have_values
[i
]) {
4592 STRING
* const key_name
= PF_CONST(self
->code
, self
->keys
[i
].name
)->u
.string
;
4593 VTABLE_set_pmc_keyed_str(interp
, result
, key_name
,
4594 make_annotation_value_pmc(interp
, self
, self
->keys
[i
].type
,
4599 mem_gc_free(interp
, latest_values
);
4600 mem_gc_free(interp
, have_values
);
4603 /* Look for latest applicable value of the key. */
4604 opcode_t latest_value
= 0;
4605 opcode_t found_value
= 0;
4607 for (i
= start_entry
; i
< self
->num_entries
; ++i
) {
4608 if (self
->entries
[i
].bytecode_offset
>= offset
)
4611 if (self
->entries
[i
].key
== key_id
) {
4612 latest_value
= self
->entries
[i
].value
;
4617 /* Did we find anything? */
4621 result
= make_annotation_value_pmc(interp
, self
,
4622 self
->keys
[key_id
].type
, latest_value
);
4630 =item C<static void compile_or_load_file(PARROT_INTERP, STRING *path,
4631 enum_runtime_ft file_type)>
4633 Either load a bytecode file and append it to the current packfile directory, or
4634 compile a PIR or PASM file from source.
4641 compile_or_load_file(PARROT_INTERP
, ARGIN(STRING
*path
),
4642 enum_runtime_ft file_type
)
4644 ASSERT_ARGS(compile_or_load_file
)
4645 char * const filename
= Parrot_str_to_cstring(interp
, path
);
4647 UINTVAL regs_used
[] = { 2, 2, 2, 2 }; /* Arbitrary values */
4648 const int parrot_hll_id
= 0;
4649 PMC
* context
= Parrot_push_context(interp
, regs_used
);
4650 Parrot_pcc_set_HLL(interp
, context
, parrot_hll_id
);
4651 Parrot_pcc_set_namespace(interp
, context
,
4652 Parrot_get_HLL_namespace(interp
, parrot_hll_id
));
4654 if (file_type
== PARROT_RUNTIME_FT_PBC
) {
4655 PackFile
* const pf
= PackFile_append_pbc(interp
, filename
);
4656 Parrot_str_free_cstring(filename
);
4659 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
4660 "Unable to append PBC to the current directory");
4662 mem_gc_free(interp
, pf
->header
);
4664 mem_gc_free(interp
, pf
->dirp
);
4666 /* no need to free pf here, as directory_destroy will get it */
4670 PackFile_ByteCode
* const cs
=
4671 (PackFile_ByteCode
*)IMCC_compile_file_s(interp
,
4673 Parrot_str_free_cstring(filename
);
4676 do_sub_pragmas(interp
, cs
, PBC_LOADED
, NULL
);
4678 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_LIBRARY_ERROR
,
4679 "compiler returned NULL ByteCode '%Ss' - %Ss", path
, err
);
4682 Parrot_pop_context(interp
);
4687 =item C<void Parrot_load_language(PARROT_INTERP, STRING *lang_name)>
4689 Load the compiler libraries for a given high-level language into the
4698 Parrot_load_language(PARROT_INTERP
, ARGIN_NULLOK(STRING
*lang_name
))
4700 ASSERT_ARGS(Parrot_load_language
)
4701 STRING
*wo_ext
, *file_str
, *path
, *pbc
;
4702 STRING
*found_path
, *found_ext
;
4704 enum_runtime_ft file_type
;
4705 PMC
*is_loaded_hash
;
4707 if (STRING_IS_NULL(lang_name
))
4708 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_LIBRARY_ERROR
,
4709 "\"load_language\" no language name");
4711 /* Full path to language library is "abc/abc.pbc". */
4712 pbc
= CONST_STRING(interp
, "pbc");
4713 wo_ext
= Parrot_str_concat(interp
, lang_name
, CONST_STRING(interp
, "/"));
4714 wo_ext
= Parrot_str_concat(interp
, wo_ext
, lang_name
);
4715 file_str
= Parrot_str_concat(interp
, wo_ext
, CONST_STRING(interp
, "."));
4716 file_str
= Parrot_str_concat(interp
, file_str
, pbc
);
4718 /* Check if the language is already loaded */
4719 is_loaded_hash
= VTABLE_get_pmc_keyed_int(interp
,
4720 interp
->iglobals
, IGLOBALS_PBC_LIBS
);
4721 if (VTABLE_exists_keyed_str(interp
, is_loaded_hash
, wo_ext
))
4724 file_type
= PARROT_RUNTIME_FT_LANG
;
4726 path
= Parrot_locate_runtime_file_str(interp
, file_str
, file_type
);
4728 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_LIBRARY_ERROR
,
4729 "\"load_language\" couldn't find a compiler module for the language '%Ss'", lang_name
);
4731 /* remember wo_ext => full_path mapping */
4732 VTABLE_set_string_keyed_str(interp
, is_loaded_hash
,
4735 /* Add the include and dynext paths to the global search */
4737 /* Get the base path of the located module */
4738 parrot_split_path_ext(interp
, path
, &found_path
, &found_ext
);
4739 name_length
= Parrot_str_length(interp
, lang_name
);
4740 found_path
= Parrot_str_substr(interp
, found_path
, 0,
4741 Parrot_str_length(interp
, found_path
)-name_length
);
4743 Parrot_lib_add_path(interp
, Parrot_str_concat(interp
, found_path
, CONST_STRING(interp
, "include/")),
4744 PARROT_LIB_PATH_INCLUDE
);
4745 Parrot_lib_add_path(interp
, Parrot_str_concat(interp
, found_path
, CONST_STRING(interp
, "dynext/")),
4746 PARROT_LIB_PATH_DYNEXT
);
4747 Parrot_lib_add_path(interp
, Parrot_str_concat(interp
, found_path
, CONST_STRING(interp
, "library/")),
4748 PARROT_LIB_PATH_LIBRARY
);
4751 /* Check if the file found was actually a bytecode file (.pbc extension) or
4752 * a source file (.pir or .pasm extension. */
4754 if (Parrot_str_equal(interp
, found_ext
, pbc
))
4755 file_type
= PARROT_RUNTIME_FT_PBC
;
4757 file_type
= PARROT_RUNTIME_FT_SOURCE
;
4759 compile_or_load_file(interp
, path
, file_type
);
4764 =item C<static PackFile * PackFile_append_pbc(PARROT_INTERP, const char
4767 Reads and appends a PBC it to the current directory. Fixes up sub addresses in
4768 newly loaded bytecode and runs C<:load> subs.
4774 PARROT_WARN_UNUSED_RESULT
4775 PARROT_CAN_RETURN_NULL
4777 PackFile_append_pbc(PARROT_INTERP
, ARGIN_NULLOK(const char *filename
))
4779 ASSERT_ARGS(PackFile_append_pbc
)
4780 PackFile
* const pf
= Parrot_pbc_read(interp
, filename
, 0);
4783 /* An embedder can try to load_bytecode without having an initial_pf */
4784 if (!interp
->initial_pf
) {
4785 interp
->initial_pf
= PackFile_new_dummy(interp
, CONST_STRING(interp
, "dummy"));
4786 /* PackFile_new_dummy must never fail */
4787 PARROT_ASSERT(interp
->initial_pf
);
4789 PackFile_add_segment(interp
, &interp
->initial_pf
->directory
,
4790 &pf
->directory
.base
);
4792 do_sub_pragmas(interp
, pf
->cur_cs
, PBC_LOADED
, NULL
);
4801 =item C<void Parrot_load_bytecode(PARROT_INTERP, Parrot_String file_str)>
4803 Load a bytecode, PIR, or PASM file into the interpreter.
4809 /* intermediate hook during changes */
4812 Parrot_load_bytecode(PARROT_INTERP
, ARGIN_NULLOK(Parrot_String file_str
))
4814 ASSERT_ARGS(Parrot_load_bytecode
)
4815 STRING
*wo_ext
, *ext
, *pbc
, *path
;
4816 STRING
*found_path
, *found_ext
;
4817 PMC
*is_loaded_hash
;
4818 enum_runtime_ft file_type
;
4820 if (STRING_IS_NULL(file_str
))
4821 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_LIBRARY_ERROR
,
4822 "\"load_bytecode\" no file name");
4824 parrot_split_path_ext(interp
, file_str
, &wo_ext
, &ext
);
4826 /* check if wo_ext is loaded */
4827 is_loaded_hash
= VTABLE_get_pmc_keyed_int(interp
,
4828 interp
->iglobals
, IGLOBALS_PBC_LIBS
);
4830 if (VTABLE_exists_keyed_str(interp
, is_loaded_hash
, wo_ext
))
4833 pbc
= CONST_STRING(interp
, "pbc");
4835 if (Parrot_str_equal(interp
, ext
, pbc
))
4836 file_type
= PARROT_RUNTIME_FT_PBC
;
4838 file_type
= PARROT_RUNTIME_FT_SOURCE
;
4840 path
= Parrot_locate_runtime_file_str(interp
, file_str
, file_type
);
4842 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_LIBRARY_ERROR
,
4843 "\"load_bytecode\" couldn't find file '%Ss'", file_str
);
4845 /* remember wo_ext => full_path mapping */
4846 VTABLE_set_string_keyed_str(interp
, is_loaded_hash
, wo_ext
, path
);
4848 parrot_split_path_ext(interp
, path
, &found_path
, &found_ext
);
4850 /* Check if the file found was actually a bytecode file (.pbc
4851 * extension) or a source file (.pir or .pasm extension). */
4853 if (Parrot_str_equal(interp
, found_ext
, pbc
))
4854 file_type
= PARROT_RUNTIME_FT_PBC
;
4856 file_type
= PARROT_RUNTIME_FT_SOURCE
;
4858 compile_or_load_file(interp
, path
, file_type
);
4864 =item C<void PackFile_fixup_subs(PARROT_INTERP, pbc_action_enum_t what, PMC
4867 Calls C<:load>, C<:init>, C<:main>, C<:immediate> and/or C<:postcomp>
4868 subroutines in the current packfile, depending on the value of C<action>.
4869 See C<do_sub_pragmas> for more details.
4877 PackFile_fixup_subs(PARROT_INTERP
, pbc_action_enum_t what
, ARGIN_NULLOK(PMC
*eval
))
4879 ASSERT_ARGS(PackFile_fixup_subs
)
4880 PARROT_CALLIN_START(interp
);
4881 do_sub_pragmas(interp
, interp
->code
, what
, eval
);
4882 PARROT_CALLIN_END(interp
);
4892 Parrot_readbc and Parrot_loadbc renamed. Trace macros, long double and
4893 64-bit conversion work by Reini Urban 2009.
4895 Rework by Melvin; new bytecode format, make bytecode portable. (Do
4896 endian conversion and wordsize transforms on the fly.)
4898 leo applied and modified Juergen Boemmels packfile patch giving an
4899 extensible packfile format with directory reworked again, with common
4900 chunks (C<default_*>).
4902 2003.11.21 leo: moved low level item fetch routines to new
4912 * c-file-style: "parrot"
4914 * vim: expandtab shiftwidth=4: