2 Copyright (C) 2001-2008, The Perl Foundation.
3 This program is free software. It is subject to the same license as
9 src/packfile.c - Parrot PackFile API
13 =head2 PackFile Manipulation Functions
15 This file contains all the functions required for the processing of the
16 structure of a PackFile. It is not intended to understand the byte code
17 stream itself, but merely to dissect and reconstruct data from the
18 various segments. See F<docs/parrotbyte.pod> for information about the
19 structure of the frozen bytecode.
27 #include "parrot/parrot.h"
28 #include "parrot/embed.h"
29 #include "parrot/packfile.h"
31 #include "../compilers/imcc/imc.h"
32 #include "packfile.str"
34 /* HEADERIZER HFILE: include/parrot/packfile.h */
36 /* HEADERIZER BEGIN: static */
37 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
39 static void byte_code_destroy(SHIM_INTERP
, ARGMOD(PackFile_Segment
*self
))
40 __attribute__nonnull__(2)
43 PARROT_WARN_UNUSED_RESULT
44 PARROT_CANNOT_RETURN_NULL
45 static PackFile_Segment
* byte_code_new(SHIM_INTERP
,
47 SHIM(const char *name
),
50 PARROT_WARN_UNUSED_RESULT
51 PARROT_CANNOT_RETURN_NULL
52 static PackFile_Constant
* clone_constant(PARROT_INTERP
,
53 ARGIN(PackFile_Constant
*old_const
))
54 __attribute__nonnull__(1)
55 __attribute__nonnull__(2);
57 static void const_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
58 __attribute__nonnull__(1)
59 __attribute__nonnull__(2)
63 PARROT_CANNOT_RETURN_NULL
64 static PackFile_Segment
* const_new(SHIM_INTERP
,
66 SHIM(const char *name
),
69 PARROT_WARN_UNUSED_RESULT
70 PARROT_CANNOT_RETURN_NULL
71 static PackFile_Segment
* create_seg(PARROT_INTERP
,
72 ARGMOD(PackFile_Directory
*dir
),
74 ARGIN(const char *name
),
75 ARGIN(const char *file_name
),
77 __attribute__nonnull__(1)
78 __attribute__nonnull__(2)
79 __attribute__nonnull__(4)
80 __attribute__nonnull__(5)
83 static void default_destroy(ARGMOD(PackFile_Segment
*self
))
84 __attribute__nonnull__(1)
87 static void default_dump(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
88 __attribute__nonnull__(1)
89 __attribute__nonnull__(2);
91 PARROT_WARN_UNUSED_RESULT
92 PARROT_CANNOT_RETURN_NULL
93 static opcode_t
* default_pack(
94 ARGIN(const PackFile_Segment
*self
),
95 ARGOUT(opcode_t
*dest
))
96 __attribute__nonnull__(1)
97 __attribute__nonnull__(2)
100 static size_t default_packed_size(ARGIN(const PackFile_Segment
*self
))
101 __attribute__nonnull__(1);
103 PARROT_WARN_UNUSED_RESULT
104 PARROT_CAN_RETURN_NULL
105 static const opcode_t
* default_unpack(
106 ARGMOD(PackFile_Segment
*self
),
107 ARGIN(const opcode_t
*cursor
))
108 __attribute__nonnull__(1)
109 __attribute__nonnull__(2)
110 FUNC_MODIFIES(*self
);
112 static void directory_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
113 __attribute__nonnull__(1)
114 __attribute__nonnull__(2)
115 FUNC_MODIFIES(*self
);
117 static void directory_dump(PARROT_INTERP
,
118 ARGIN(const PackFile_Segment
*self
))
119 __attribute__nonnull__(1)
120 __attribute__nonnull__(2);
122 PARROT_WARN_UNUSED_RESULT
123 PARROT_CANNOT_RETURN_NULL
124 static PackFile_Segment
* directory_new(SHIM_INTERP
,
126 SHIM(const char *name
),
129 PARROT_WARN_UNUSED_RESULT
130 PARROT_CANNOT_RETURN_NULL
131 static opcode_t
* directory_pack(PARROT_INTERP
,
132 ARGIN(PackFile_Segment
*self
),
133 ARGOUT(opcode_t
*cursor
))
134 __attribute__nonnull__(1)
135 __attribute__nonnull__(2)
136 __attribute__nonnull__(3)
137 FUNC_MODIFIES(*cursor
);
139 static size_t directory_packed_size(PARROT_INTERP
,
140 ARGMOD(PackFile_Segment
*self
))
141 __attribute__nonnull__(1)
142 __attribute__nonnull__(2)
143 FUNC_MODIFIES(*self
);
145 PARROT_WARN_UNUSED_RESULT
146 PARROT_CANNOT_RETURN_NULL
147 static const opcode_t
* directory_unpack(PARROT_INTERP
,
148 ARGMOD(PackFile_Segment
*segp
),
149 ARGIN(const opcode_t
*cursor
))
150 __attribute__nonnull__(1)
151 __attribute__nonnull__(2)
152 __attribute__nonnull__(3)
153 FUNC_MODIFIES(*segp
);
155 PARROT_WARN_UNUSED_RESULT
156 PARROT_CAN_RETURN_NULL
157 static PMC
* do_1_sub_pragma(PARROT_INTERP
,
158 ARGMOD(PMC
*sub_pmc
),
159 pbc_action_enum_t action
)
160 __attribute__nonnull__(1)
161 __attribute__nonnull__(2)
162 FUNC_MODIFIES(*sub_pmc
);
164 static INTVAL
find_const_iter(PARROT_INTERP
,
165 ARGIN(PackFile_Segment
*seg
),
166 ARGIN_NULLOK(void *user_data
))
167 __attribute__nonnull__(1)
168 __attribute__nonnull__(2);
170 PARROT_WARN_UNUSED_RESULT
171 PARROT_CANNOT_RETURN_NULL
172 static PackFile_Constant
** find_constants(PARROT_INTERP
,
173 ARGIN(PackFile_ConstTable
*ct
))
174 __attribute__nonnull__(1)
175 __attribute__nonnull__(2);
177 PARROT_WARN_UNUSED_RESULT
178 PARROT_CAN_RETURN_NULL
179 static PackFile_FixupEntry
* find_fixup(
180 ARGMOD(PackFile_FixupTable
*ft
),
182 ARGIN(const char *name
))
183 __attribute__nonnull__(1)
184 __attribute__nonnull__(3)
187 static INTVAL
find_fixup_iter(PARROT_INTERP
,
188 ARGIN(PackFile_Segment
*seg
),
189 ARGIN(void *user_data
))
190 __attribute__nonnull__(1)
191 __attribute__nonnull__(2)
192 __attribute__nonnull__(3);
194 static void fixup_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
195 __attribute__nonnull__(1)
196 __attribute__nonnull__(2)
197 FUNC_MODIFIES(*self
);
199 PARROT_WARN_UNUSED_RESULT
200 PARROT_CANNOT_RETURN_NULL
201 static PackFile_Segment
* fixup_new(SHIM_INTERP
,
203 SHIM(const char *name
),
206 PARROT_WARN_UNUSED_RESULT
207 PARROT_CANNOT_RETURN_NULL
208 static opcode_t
* fixup_pack(PARROT_INTERP
,
209 ARGIN(PackFile_Segment
*self
),
210 ARGOUT(opcode_t
*cursor
))
211 __attribute__nonnull__(1)
212 __attribute__nonnull__(2)
213 __attribute__nonnull__(3)
214 FUNC_MODIFIES(*cursor
);
216 static size_t fixup_packed_size(PARROT_INTERP
,
217 ARGMOD(PackFile_Segment
*self
))
218 __attribute__nonnull__(1)
219 __attribute__nonnull__(2)
220 FUNC_MODIFIES(*self
);
222 PARROT_WARN_UNUSED_RESULT
223 PARROT_CAN_RETURN_NULL
224 static const opcode_t
* fixup_unpack(PARROT_INTERP
,
225 ARGIN(PackFile_Segment
*seg
),
226 ARGIN(const opcode_t
*cursor
))
227 __attribute__nonnull__(1)
228 __attribute__nonnull__(2)
229 __attribute__nonnull__(3);
231 static void make_code_pointers(ARGMOD(PackFile_Segment
*seg
))
232 __attribute__nonnull__(1)
235 static void mark_1_seg(PARROT_INTERP
, ARGMOD(PackFile_ConstTable
*ct
))
236 __attribute__nonnull__(1)
237 __attribute__nonnull__(2)
240 PARROT_WARN_UNUSED_RESULT
241 PARROT_CAN_RETURN_NULL
242 static PackFile
* PackFile_append_pbc(PARROT_INTERP
,
243 ARGIN_NULLOK(const char *filename
))
244 __attribute__nonnull__(1);
246 static void PackFile_set_header(ARGOUT(PackFile_Header
*header
))
247 __attribute__nonnull__(1)
248 FUNC_MODIFIES(*header
);
250 static void pf_debug_destroy(SHIM_INTERP
, ARGMOD(PackFile_Segment
*self
))
251 __attribute__nonnull__(2)
252 FUNC_MODIFIES(*self
);
254 static void pf_debug_dump(PARROT_INTERP
,
255 ARGIN(const PackFile_Segment
*self
))
256 __attribute__nonnull__(1)
257 __attribute__nonnull__(2);
259 PARROT_WARN_UNUSED_RESULT
260 PARROT_CANNOT_RETURN_NULL
261 static PackFile_Segment
* pf_debug_new(SHIM_INTERP
,
263 SHIM(const char *name
),
266 PARROT_WARN_UNUSED_RESULT
267 PARROT_CANNOT_RETURN_NULL
268 static opcode_t
* pf_debug_pack(SHIM_INTERP
,
269 ARGMOD(PackFile_Segment
*self
),
270 ARGOUT(opcode_t
*cursor
))
271 __attribute__nonnull__(2)
272 __attribute__nonnull__(3)
274 FUNC_MODIFIES(*cursor
);
276 static size_t pf_debug_packed_size(SHIM_INTERP
,
277 ARGIN(PackFile_Segment
*self
))
278 __attribute__nonnull__(2);
280 PARROT_WARN_UNUSED_RESULT
281 PARROT_CANNOT_RETURN_NULL
282 static const opcode_t
* pf_debug_unpack(PARROT_INTERP
,
283 ARGOUT(PackFile_Segment
*self
),
284 ARGIN(const opcode_t
*cursor
))
285 __attribute__nonnull__(1)
286 __attribute__nonnull__(2)
287 __attribute__nonnull__(3)
288 FUNC_MODIFIES(*self
);
290 static void pf_register_standard_funcs(PARROT_INTERP
, ARGMOD(PackFile
*pf
))
291 __attribute__nonnull__(1)
292 __attribute__nonnull__(2)
295 PARROT_IGNORABLE_RESULT
296 PARROT_CAN_RETURN_NULL
297 static PMC
* run_sub(PARROT_INTERP
, ARGIN(PMC
*sub_pmc
))
298 __attribute__nonnull__(1)
299 __attribute__nonnull__(2);
301 static void segment_init(
302 ARGOUT(PackFile_Segment
*self
),
304 ARGIN(const char *name
))
305 __attribute__nonnull__(1)
306 __attribute__nonnull__(2)
307 __attribute__nonnull__(3)
308 FUNC_MODIFIES(*self
);
310 static void sort_segs(ARGMOD(PackFile_Directory
*dir
))
311 __attribute__nonnull__(1)
314 static int sub_pragma(PARROT_INTERP
,
315 pbc_action_enum_t action
,
316 ARGIN(const PMC
*sub_pmc
))
317 __attribute__nonnull__(1)
318 __attribute__nonnull__(3);
320 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
321 /* HEADERIZER END: static */
324 extern int Parrot_exec_run
;
327 #define TRACE_PACKFILE 0
329 #define ROUND_16(val) (((val) & 0xf) ? 16 - ((val) & 0xf) : 0)
330 #define ALIGN_16(st, cursor) \
331 (cursor) += ROUND_16((const char *)(cursor) - (const char *)(st))/sizeof (opcode_t)
335 =item C<void PackFile_destroy>
337 Delete a C<PackFile>.
345 PackFile_destroy(PARROT_INTERP
, ARGMOD_NULLOK(PackFile
*pf
))
348 PIO_eprintf(NULL
, "PackFile_destroy: pf == NULL!\n");
352 #ifdef PARROT_HAS_HEADER_SYSMMAN
353 if (pf
->is_mmap_ped
) {
355 /* Cast the result to void to avoid a warning with
356 * some not-so-standard mmap headers, see RT#56110
358 munmap((void *)PARROT_const_cast(opcode_t
*, pf
->src
), pf
->size
);
362 mem_sys_free(pf
->header
);
364 mem_sys_free(pf
->dirp
);
366 PackFile_Segment_destroy(interp
, &pf
->directory
.base
);
373 =item C<static void make_code_pointers>
375 Make compat/shorthand pointers.
377 The first segments read are the default segments.
384 make_code_pointers(ARGMOD(PackFile_Segment
*seg
))
386 PackFile
* const pf
= seg
->pf
;
391 pf
->cur_cs
= (PackFile_ByteCode
*)seg
;
394 if (!pf
->cur_cs
->fixups
) {
395 pf
->cur_cs
->fixups
= (PackFile_FixupTable
*)seg
;
396 pf
->cur_cs
->fixups
->code
= pf
->cur_cs
;
400 if (!pf
->cur_cs
->const_table
) {
401 pf
->cur_cs
->const_table
= (PackFile_ConstTable
*)seg
;
402 pf
->cur_cs
->const_table
->code
= pf
->cur_cs
;
406 if (memcmp(seg
->name
, "PIC_idx", 7) == 0)
407 pf
->cur_cs
->pic_index
= seg
;
410 pf
->cur_cs
->debugs
= (PackFile_Debug
*)seg
;
411 pf
->cur_cs
->debugs
->code
= pf
->cur_cs
;
421 =item C<static int sub_pragma>
423 Check B<sub_pmc>'s pragmas (e.g. flags like C<:load>, C<:main>, etc.) returning
424 1 if the sub should be run for C<action>, a C<pbc_action_enum_t>.
431 sub_pragma(PARROT_INTERP
, pbc_action_enum_t action
, ARGIN(const PMC
*sub_pmc
))
434 int pragmas
= PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_MASK
435 & ~SUB_FLAG_IS_OUTER
;
437 if (!pragmas
&& !Sub_comp_INIT_TEST(sub_pmc
))
443 /* denote MAIN entry in first loaded PASM */
444 if (interp
->resume_flag
& RESUME_INITIAL
)
447 /* :init functions need to be called at MAIN time, so return 1 */
448 if (Sub_comp_INIT_TEST(sub_pmc
)) /* symreg.h:P_INIT */
453 if (pragmas
& SUB_FLAG_PF_LOAD
) /* symreg.h:P_LOAD */
460 if (pragmas
& (SUB_FLAG_PF_IMMEDIATE
| SUB_FLAG_PF_POSTCOMP
))
469 =item C<static PMC* run_sub>
471 Run the B<sub_pmc> due to its B<:load>, B<:immediate>, ... pragma
477 PARROT_IGNORABLE_RESULT
478 PARROT_CAN_RETURN_NULL
480 run_sub(PARROT_INTERP
, ARGIN(PMC
*sub_pmc
))
482 const INTVAL old
= interp
->run_core
;
486 * turn off JIT and prederef - both would act on the whole
487 * PackFile which isn't worth the effort - probably
489 if (interp
->run_core
!= PARROT_CGOTO_CORE
490 && interp
->run_core
!= PARROT_SLOW_CORE
491 && interp
->run_core
!= PARROT_FAST_CORE
)
492 interp
->run_core
= PARROT_FAST_CORE
;
494 CONTEXT(interp
)->constants
= interp
->code
->const_table
->constants
;
496 retval
= (PMC
*)Parrot_runops_fromc_args(interp
, sub_pmc
, "P");
497 interp
->run_core
= old
;
505 =item C<static PMC* do_1_sub_pragma>
507 Run autoloaded or immediate bytecode, mark MAIN subroutine entry
513 PARROT_WARN_UNUSED_RESULT
514 PARROT_CAN_RETURN_NULL
516 do_1_sub_pragma(PARROT_INTERP
, ARGMOD(PMC
*sub_pmc
), pbc_action_enum_t action
)
518 Parrot_sub
const *sub
= PMC_sub(sub_pmc
);
522 /* run IMMEDIATE sub */
523 if (PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_IMMEDIATE
) {
524 void *lo_var_ptr
= interp
->lo_var_ptr
;
527 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_IMMEDIATE
;
528 result
= run_sub(interp
, sub_pmc
);
531 * reset initial flag so MAIN detection works
532 * and reset lo_var_ptr to prev
534 interp
->resume_flag
= RESUME_INITIAL
;
535 interp
->lo_var_ptr
= lo_var_ptr
;
540 /* run POSTCOMP sub */
541 if (PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_POSTCOMP
) {
542 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_POSTCOMP
;
543 run_sub(interp
, sub_pmc
);
545 /* reset initial flag so MAIN detection works */
546 interp
->resume_flag
= RESUME_INITIAL
;
552 if (PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_LOAD
) {
553 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_LOAD
;
555 /* if loaded no need for init */
556 Sub_comp_INIT_CLEAR(sub_pmc
);
557 run_sub(interp
, sub_pmc
);
561 if (PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_MAIN
) {
562 if ((interp
->resume_flag
& RESUME_INITIAL
)
563 && interp
->resume_offset
== 0) {
564 const ptrdiff_t code
= (ptrdiff_t) sub
->seg
->base
.data
;
565 void *ptr
= VTABLE_get_pointer(interp
, sub_pmc
);
567 interp
->resume_offset
= ((ptrdiff_t)ptr
- code
)
568 / sizeof (opcode_t
*);
570 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_MAIN
;
571 CONTEXT(interp
)->current_sub
= sub_pmc
;
574 /* XXX which warn_class */
575 Parrot_warn(interp
, PARROT_WARNINGS_ALL_FLAG
,
576 ":main sub not allowed\n");
580 /* run :init tagged functions */
581 if (action
== PBC_MAIN
&& Sub_comp_INIT_TEST(sub_pmc
)) {
582 /* if loaded no need for init */
583 Sub_comp_INIT_CLEAR(sub_pmc
);
585 /* if inited no need for load */
586 PObj_get_FLAGS(sub_pmc
) &= ~SUB_FLAG_PF_LOAD
;
588 run_sub(interp
, sub_pmc
);
589 interp
->resume_flag
= RESUME_INITIAL
;
599 =item C<static void mark_1_seg>
601 While the PMCs should be constant, their possible contents such as
602 properties aren't constructed const, so we have to mark them.
609 mark_1_seg(PARROT_INTERP
, ARGMOD(PackFile_ConstTable
*ct
))
612 PackFile_Constant
** const constants
= find_constants(interp
, ct
);
614 for (i
= 0; i
< ct
->const_count
; i
++) {
615 if (constants
[i
]->type
== PFC_PMC
) {
616 PMC
* const pmc
= constants
[i
]->u
.key
;
618 pobject_lives(interp
, (PObj
*)pmc
);
626 =item C<static INTVAL find_const_iter>
628 RT#48260: Not yet documented!!!
635 find_const_iter(PARROT_INTERP
, ARGIN(PackFile_Segment
*seg
),
636 ARGIN_NULLOK(void *user_data
))
638 if (seg
->type
== PF_DIR_SEG
)
639 PackFile_map_segments(interp
, (const PackFile_Directory
*)seg
,
640 find_const_iter
, user_data
);
641 else if (seg
->type
== PF_CONST_SEG
)
642 mark_1_seg(interp
, (PackFile_ConstTable
*)seg
);
650 =item C<void mark_const_subs>
652 RT#48260: Not yet documented!!!
659 mark_const_subs(PARROT_INTERP
)
661 PackFile_Directory
*dir
;
663 PackFile
* const self
= interp
->initial_pf
;
668 /* locate top level dir */
669 dir
= &self
->directory
;
671 /* iterate over all dir/segs */
672 PackFile_map_segments(interp
, dir
, find_const_iter
, NULL
);
678 =item C<void do_sub_pragmas>
680 C<action> is one of C<PBC_PBC>, C<PBC_LOADED>, C<PBC_INIT>, or C<PBC_MAIN>.
681 Also store the C<eval_pmc> in the sub structure, so that the eval PMC is kept
682 alive by living subs.
690 do_sub_pragmas(PARROT_INTERP
, ARGIN(PackFile_ByteCode
*self
),
691 pbc_action_enum_t action
, ARGIN_NULLOK(PMC
*eval_pmc
))
694 PackFile_FixupTable
* const ft
= self
->fixups
;
695 PackFile_ConstTable
* const ct
= self
->const_table
;
698 PIO_eprintf(NULL
, "PackFile: do_sub_pragmas (action=%d)\n", action
);
701 for (i
= 0; i
< ft
->fixup_count
; i
++) {
702 switch (ft
->fixups
[i
]->type
) {
706 * offset is an index into the const_table holding the Sub PMC
708 const opcode_t ci
= ft
->fixups
[i
]->offset
;
711 if (ci
< 0 || ci
>= ct
->const_count
)
712 real_exception(interp
, NULL
, 1,
713 "Illegal fixup offset (%d) in enum_fixup_sub");
715 sub_pmc
= ct
->constants
[ci
]->u
.key
;
716 PMC_sub(sub_pmc
)->eval_pmc
= eval_pmc
;
718 if (((PObj_get_FLAGS(sub_pmc
) & SUB_FLAG_PF_MASK
)
719 || (Sub_comp_get_FLAGS(sub_pmc
) & SUB_COMP_FLAG_MASK
))
720 && sub_pragma(interp
, action
, sub_pmc
)) {
721 PMC
* const result
= do_1_sub_pragma(interp
,
724 /* replace Sub PMC with computation results */
725 if (action
== PBC_IMMEDIATE
&& !PMC_IS_NULL(result
)) {
726 ft
->fixups
[i
]->type
= enum_fixup_none
;
727 ct
->constants
[ci
]->u
.key
= result
;
732 case enum_fixup_label
:
733 /* fill in current bytecode seg */
734 ft
->fixups
[i
]->seg
= self
;
745 =item C<opcode_t PackFile_unpack>
747 Unpack a C<PackFile> from a block of memory, ensuring the the magic number is
748 valid, the bytecode version can be read by this Parrot and doing any endian
749 and word size transforms that are required.
751 Returns size of unpacked if everything is OK, else zero (0).
758 PARROT_WARN_UNUSED_RESULT
760 PackFile_unpack(PARROT_INTERP
, ARGMOD(PackFile
*self
),
761 ARGIN(const opcode_t
*packed
), size_t packed_size
)
763 PackFile_Header
* const header
= self
->header
;
764 const opcode_t
*cursor
;
765 int header_read_length
;
769 self
->size
= packed_size
;
771 /* Extract the header. */
772 memcpy(header
, packed
, PACKFILE_HEADER_BYTES
);
774 /* Ensure the magic is correct. */
775 if (memcmp(header
->magic
, "\376PBC\r\n\032\n", 8) != 0) {
776 PIO_eprintf(NULL
, "PackFile_unpack: "
777 "This is not a valid Parrot bytecode file\n");
781 /* Ensure the bytecode version is one we can read. Currently, we only
782 * support bytecode versions matching the current one. */
783 if (header
->bc_major
!= PARROT_PBC_MAJOR
784 && header
->bc_minor
!= PARROT_PBC_MINOR
) {
785 PIO_eprintf(NULL
, "PackFile_unpack: This Parrot cannot read bytecode "
786 "files with version %d.%d.\n", header
->bc_major
, header
->bc_minor
);
790 /* Check wordsize, byte order and floating point number type are valid. */
791 if (header
->wordsize
!= 4 && header
->wordsize
!= 8) {
792 PIO_eprintf(NULL
, "PackFile_unpack: Invalid wordsize %d\n",
797 if (header
->byteorder
!= 0 && header
->byteorder
!= 1) {
798 PIO_eprintf(NULL
, "PackFile_unpack: Invalid byte ordering %d\n",
803 if (header
->floattype
!= 0 && header
->floattype
!= 1) {
804 PIO_eprintf(NULL
, "PackFile_unpack: Invalid floattype %d\n",
809 /* Describe what was read for debugging. */
811 PIO_eprintf(NULL
, "PackFile_unpack: Wordsize %d.\n", header
->wordsize
);
812 PIO_eprintf(NULL
, "PackFile_unpack: Floattype %d (%s).\n",
815 "x86 little endian 12 byte long double" :
816 "IEEE-754 8 byte double");
817 PIO_eprintf(NULL
, "PackFile_unpack: Byteorder %d (%sendian).\n",
818 header
->byteorder
, header
->byteorder
? "big " : "little-");
821 /* Check the UUID type is valid and, if needed, read a UUID. */
822 if (header
->uuid_type
== 0) {
823 /* No UUID; fine, nothing more to do. */
825 else if (header
->uuid_type
== 1) {
826 /* Read in the UUID. We'll put it in a NULL-terminated string, just in
827 * case pepole use it that way. */
828 header
->uuid_data
= (unsigned char *)
829 mem_sys_allocate(header
->uuid_size
+ 1);
831 memcpy(header
->uuid_data
, packed
+ PACKFILE_HEADER_BYTES
,
835 header
->uuid_data
[header
->uuid_size
] = 0;
838 /* Don't know this UUID type. */
839 PIO_eprintf(NULL
, "PackFile_unpack: Invalid UUID type %d\n",
843 /* Set cursor to position after what we've read, allowing for padding to a
844 * 16 byte boundary. */
845 header_read_length
= PACKFILE_HEADER_BYTES
+ header
->uuid_size
;
846 header_read_length
+= header_read_length
% 16 ?
847 16 - header_read_length
% 16 : 0;
848 cursor
= packed
+ (header_read_length
/ sizeof (opcode_t
));
850 /* Set what transforms we need to do when reading the rest of the file. */
851 PackFile_assign_transforms(self
);
853 /* Directory format. */
854 header
->dir_format
= PF_fetch_opcode(self
, &cursor
);
856 if (header
->dir_format
!= PF_DIR_FORMAT
) {
857 PIO_eprintf(NULL
, "PackFile_unpack: Dir format was %d not %d\n",
858 header
->dir_format
, PF_DIR_FORMAT
);
863 padding
= PF_fetch_opcode(self
, &cursor
);
864 padding
= PF_fetch_opcode(self
, &cursor
);
865 padding
= PF_fetch_opcode(self
, &cursor
);
869 PIO_eprintf(NULL
, "PackFile_unpack: Directory read, offset %d.\n",
870 (INTVAL
)cursor
- (INTVAL
)packed
);
873 self
->directory
.base
.file_offset
= (INTVAL
)cursor
- (INTVAL
)self
->src
;
875 /* now unpack dir, which unpacks its contents ... */
876 Parrot_block_GC_mark(interp
);
877 cursor
= PackFile_Segment_unpack(interp
,
878 &self
->directory
.base
, cursor
);
879 Parrot_unblock_GC_mark(interp
);
881 #ifdef PARROT_HAS_HEADER_SYSMMAN
882 if (self
->is_mmap_ped
883 && (self
->need_endianize
|| self
->need_wordsize
)) {
885 /* Cast the result to void to avoid a warning with
886 * some not-so-standard mmap headers, see RT#56110
888 munmap((void *)PARROT_const_cast(opcode_t
*, self
->src
), self
->size
);
889 self
->is_mmap_ped
= 0;
894 PIO_eprintf(NULL
, "PackFile_unpack: Unpack done.\n");
897 return cursor
- packed
;
903 =item C<INTVAL PackFile_map_segments>
905 For each segment in the directory C<dir> the callback function C<callback> is
906 called. The pointer C<user_data> is included in each call.
908 If a callback returns non-zero the processing of segments is stopped,
909 and this value is returned.
917 PackFile_map_segments(PARROT_INTERP
, ARGIN(const PackFile_Directory
*dir
),
918 PackFile_map_segments_func_t callback
,
919 ARGIN_NULLOK(void *user_data
))
923 for (i
= 0; i
< dir
->num_segments
; i
++) {
924 const INTVAL ret
= callback(interp
, dir
->segments
[i
], user_data
);
935 =item C<INTVAL PackFile_add_segment>
937 Adds the Segment C<seg> to the directory C<dir>. The PackFile becomes the
938 owner of the segment; it gets destroyed when the packfile does.
946 PackFile_add_segment(SHIM_INTERP
, ARGMOD(PackFile_Directory
*dir
),
947 ARGIN(PackFile_Segment
*seg
))
949 mem_realloc_n_typed(dir
->segments
, dir
->num_segments
+1, PackFile_Segment
*);
950 dir
->segments
[dir
->num_segments
] = seg
;
960 =item C<PackFile_Segment * PackFile_find_segment>
962 Finds the segment with the name C<name> in the C<PackFile_Directory> if
963 C<sub_dir> is true, directories are searched recursively. The segment is
964 returned, but its still owned by the C<PackFile>.
971 PARROT_WARN_UNUSED_RESULT
972 PARROT_CAN_RETURN_NULL
974 PackFile_find_segment(PARROT_INTERP
, ARGIN_NULLOK(PackFile_Directory
*dir
),
975 ARGIN(const char *name
), int sub_dir
)
980 for (i
= 0; i
< dir
->num_segments
; i
++) {
981 PackFile_Segment
*seg
= dir
->segments
[i
];
984 if (STREQ(seg
->name
, name
))
987 if (sub_dir
&& seg
->type
== PF_DIR_SEG
) {
988 seg
= PackFile_find_segment(interp
,
989 (PackFile_Directory
*)seg
, name
, sub_dir
);
1004 =item C<PackFile_Segment * PackFile_remove_segment_by_name>
1006 Finds and removes the segment with name C<name> in the C<PackFile_Directory>.
1007 The segment is returned and must be destroyed by the user.
1014 PARROT_WARN_UNUSED_RESULT
1015 PARROT_CAN_RETURN_NULL
1017 PackFile_remove_segment_by_name(SHIM_INTERP
, ARGMOD(PackFile_Directory
*dir
),
1018 ARGIN(const char *name
))
1022 for (i
= 0; i
< dir
->num_segments
; i
++) {
1023 PackFile_Segment
* const seg
= dir
->segments
[i
];
1024 if (STREQ(seg
->name
, name
)) {
1025 dir
->num_segments
--;
1027 if (i
!= dir
->num_segments
) {
1028 /* We're not the last segment, so we need to move things */
1029 memmove(&dir
->segments
[i
], &dir
->segments
[i
+1],
1030 (dir
->num_segments
- i
) * sizeof (PackFile_Segment
*));
1045 =head2 PackFile Structure Functions
1049 =item C<static void PackFile_set_header>
1051 Fill a C<PackFile> header with system specific data.
1058 PackFile_set_header(ARGOUT(PackFile_Header
*header
))
1060 memcpy(header
->magic
, "\376PBC\r\n\032\n", 8);
1061 header
->wordsize
= sizeof (opcode_t
);
1062 header
->byteorder
= PARROT_BIGENDIAN
;
1063 header
->major
= PARROT_MAJOR_VERSION
;
1064 header
->minor
= PARROT_MINOR_VERSION
;
1065 header
->patch
= PARROT_PATCH_VERSION
;
1066 header
->bc_major
= PARROT_PBC_MAJOR
;
1067 header
->bc_minor
= PARROT_PBC_MINOR
;
1068 #if NUMVAL_SIZE == 8
1069 header
->floattype
= 0;
1071 header
->floattype
= 1;
1078 =item C<PackFile * PackFile_new>
1080 Allocate a new empty C<PackFile> and setup the directory.
1084 +----------+----------+----------+----------+
1087 +----------+----------+----------+----------+
1089 +----------+----------+----------+----------+
1090 | number of directory items |
1091 +----------+----------+----------+----------+
1093 followed by a sequence of items
1095 +----------+----------+----------+----------+
1097 +----------+----------+----------+----------+
1099 | ... '\0' padding bytes |
1100 +----------+----------+----------+----------+
1101 | Offset in the file |
1102 +----------+----------+----------+----------+
1103 | Size of the segment |
1104 +----------+----------+----------+----------+
1106 "name" is a NUL-terminated c-string encoded in plain ASCII.
1108 Segment types are defined in F<include/parrot/packfile.h>.
1110 Offset and size are in C<opcode_t>.
1112 A Segment Header has these entries:
1114 - op_count total ops of segment incl. this count
1115 - itype internal type of segment
1116 - id internal id e.g code seg nr
1117 - size size of following op array, 0 if none
1118 * data possibly empty data, or e.g. byte code
1125 PARROT_WARN_UNUSED_RESULT
1126 PARROT_CANNOT_RETURN_NULL
1128 PackFile_new(PARROT_INTERP
, INTVAL is_mapped
)
1130 PackFile
* const pf
= mem_allocate_zeroed_typed(PackFile
);
1131 pf
->header
= mem_allocate_zeroed_typed(PackFile_Header
);
1132 pf
->is_mmap_ped
= is_mapped
;
1134 /* fill header with system specific data */
1135 PackFile_set_header(pf
->header
);
1137 /* Other fields empty for now */
1139 pf_register_standard_funcs(interp
, pf
);
1141 /* create the master directory, all subirs go there */
1142 pf
->directory
.base
.pf
= pf
;
1143 pf
->dirp
= (PackFile_Directory
*)
1144 PackFile_Segment_new_seg(interp
, &pf
->directory
,
1145 PF_DIR_SEG
, DIRECTORY_SEGMENT_NAME
, 0);
1146 pf
->directory
= *pf
->dirp
;
1148 pf
->fetch_op
= (packfile_fetch_op_t
)NULL
;
1149 pf
->fetch_iv
= (packfile_fetch_iv_t
)NULL
;
1150 pf
->fetch_nv
= (packfile_fetch_nv_t
)NULL
;
1158 =item C<PackFile * PackFile_new_dummy>
1160 Create a new (initial) dummy PackFile. This is necessary if the interpreter
1161 doesn't load any bytecode but instead uses C<Parrot_compile_string>.
1168 PARROT_WARN_UNUSED_RESULT
1169 PARROT_CAN_RETURN_NULL
1171 PackFile_new_dummy(PARROT_INTERP
, ARGIN(const char *name
))
1173 PackFile
* const pf
= PackFile_new(interp
, 0);
1174 /* XXX PackFile_new needs to die on NULL, or else we have to check here */
1176 interp
->initial_pf
= pf
;
1177 interp
->code
= pf
->cur_cs
= PF_create_default_segs(interp
, name
, 1);
1185 =item C<INTVAL PackFile_funcs_register>
1187 Register the C<pack>/C<unpack>/... functions for a packfile type.
1195 PackFile_funcs_register(SHIM_INTERP
, ARGOUT(PackFile
*pf
), UINTVAL type
,
1196 const PackFile_funcs funcs
)
1198 /* TODO dynamic registering */
1199 pf
->PackFuncs
[type
] = funcs
;
1206 =item C<static const opcode_t * default_unpack>
1208 The default unpack function.
1214 PARROT_WARN_UNUSED_RESULT
1215 PARROT_CAN_RETURN_NULL
1216 static const opcode_t
*
1217 default_unpack(ARGMOD(PackFile_Segment
*self
), ARGIN(const opcode_t
*cursor
))
1219 DECL_CONST_CAST_OF(opcode_t
);
1221 self
->op_count
= PF_fetch_opcode(self
->pf
, &cursor
);
1222 self
->itype
= PF_fetch_opcode(self
->pf
, &cursor
);
1223 self
->id
= PF_fetch_opcode(self
->pf
, &cursor
);
1224 self
->size
= PF_fetch_opcode(self
->pf
, &cursor
);
1226 if (self
->size
== 0)
1229 /* if the packfile is mmap()ed just point to it if we don't
1230 * need any fetch transforms */
1231 if (self
->pf
->is_mmap_ped
1232 && !self
->pf
->need_endianize
1233 && !self
->pf
->need_wordsize
) {
1234 self
->data
= PARROT_const_cast(opcode_t
*, cursor
);
1235 cursor
+= self
->size
;
1239 /* else allocate mem */
1240 self
->data
= mem_allocate_n_typed(self
->size
, opcode_t
);
1243 PIO_eprintf(NULL
, "PackFile_unpack: Unable to allocate data memory!\n");
1248 if (!self
->pf
->need_endianize
&& !self
->pf
->need_wordsize
) {
1249 mem_sys_memcopy(self
->data
, cursor
, self
->size
* sizeof (opcode_t
));
1250 cursor
+= self
->size
;
1254 for (i
= 0; i
< (int)self
->size
; i
++) {
1255 self
->data
[i
] = PF_fetch_opcode(self
->pf
, &cursor
);
1257 PIO_eprintf(NULL
, "op[#%d] %u\n", i
, self
->data
[i
]);
1268 =item C<void default_dump_header>
1270 The default dump header function.
1277 default_dump_header(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
1279 PIO_printf(interp
, "%s => [ # offs 0x%x(%d)",
1280 self
->name
, (int)self
->file_offset
, (int)self
->file_offset
);
1281 PIO_printf(interp
, " = op_count %d, itype %d, id %d, size %d, ...",
1282 (int)self
->op_count
, (int)self
->itype
,
1283 (int)self
->id
, (int)self
->size
);
1289 =item C<static void default_dump>
1291 The default dump function.
1298 default_dump(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
1300 size_t i
= self
->data
? 0: self
->file_offset
+ 4;
1302 default_dump_header(interp
, self
);
1305 PIO_printf(interp
, "\n %04x: ", (int) i
);
1307 for (; i
< (self
->data
? self
->size
:
1308 self
->file_offset
+ self
->op_count
); i
++) {
1311 PIO_printf(interp
, "\n %04x: ", (int) i
);
1313 PIO_printf(interp
, "%08lx ", (unsigned long)
1314 self
->data
? self
->data
[i
] : self
->pf
->src
[i
]);
1317 PIO_printf(interp
, "\n]\n");
1323 =item C<static void pf_register_standard_funcs>
1325 Called from within C<PackFile_new()> register the standard functions.
1332 pf_register_standard_funcs(PARROT_INTERP
, ARGMOD(PackFile
*pf
))
1334 PackFile_funcs dirf
= {
1337 directory_packed_size
,
1343 PackFile_funcs defaultf
= {
1344 PackFile_Segment_new
,
1345 (PackFile_Segment_destroy_func_t
) NULLfunc
,
1346 (PackFile_Segment_packed_size_func_t
) NULLfunc
,
1347 (PackFile_Segment_pack_func_t
) NULLfunc
,
1348 (PackFile_Segment_unpack_func_t
) NULLfunc
,
1352 PackFile_funcs fixupf
= {
1361 PackFile_funcs constf
= {
1364 PackFile_ConstTable_pack_size
,
1365 PackFile_ConstTable_pack
,
1366 PackFile_ConstTable_unpack
,
1370 PackFile_funcs bytef
= {
1373 (PackFile_Segment_packed_size_func_t
) NULLfunc
,
1374 (PackFile_Segment_pack_func_t
) NULLfunc
,
1375 (PackFile_Segment_unpack_func_t
) NULLfunc
,
1379 const PackFile_funcs debugf
= {
1382 pf_debug_packed_size
,
1387 PackFile_funcs_register(interp
, pf
, PF_DIR_SEG
, dirf
);
1388 PackFile_funcs_register(interp
, pf
, PF_UNKNOWN_SEG
, defaultf
);
1389 PackFile_funcs_register(interp
, pf
, PF_FIXUP_SEG
, fixupf
);
1390 PackFile_funcs_register(interp
, pf
, PF_CONST_SEG
, constf
);
1391 PackFile_funcs_register(interp
, pf
, PF_BYTEC_SEG
, bytef
);
1392 PackFile_funcs_register(interp
, pf
, PF_DEBUG_SEG
, debugf
);
1400 =item C<PackFile_Segment * PackFile_Segment_new_seg>
1402 Create a new segment.
1409 PARROT_WARN_UNUSED_RESULT
1410 PARROT_CANNOT_RETURN_NULL
1412 PackFile_Segment_new_seg(PARROT_INTERP
, ARGMOD(PackFile_Directory
*dir
),
1413 UINTVAL type
, ARGIN(const char *name
), int add
)
1415 PackFile
* const pf
= dir
->base
.pf
;
1416 const PackFile_Segment_new_func_t f
= pf
->PackFuncs
[type
].new_seg
;
1417 PackFile_Segment
* const seg
= (f
)(interp
, pf
, name
, add
);
1419 segment_init(seg
, pf
, name
);
1423 PackFile_add_segment(interp
, dir
, seg
);
1431 =item C<static PackFile_Segment * create_seg>
1433 RT#48260: Not yet documented!!!
1439 PARROT_WARN_UNUSED_RESULT
1440 PARROT_CANNOT_RETURN_NULL
1441 static PackFile_Segment
*
1442 create_seg(PARROT_INTERP
, ARGMOD(PackFile_Directory
*dir
), pack_file_types t
,
1443 ARGIN(const char *name
), ARGIN(const char *file_name
), int add
)
1445 PackFile_Segment
*seg
;
1447 const size_t len
= strlen(name
) + strlen(file_name
) + 2;
1448 char * const buf
= (char *)mem_sys_allocate(len
);
1450 snprintf(buf
, len
, "%s_%s", name
, file_name
);
1451 seg
= PackFile_Segment_new_seg(interp
, dir
, t
, buf
, add
);
1459 =item C<PackFile_ByteCode * PF_create_default_segs>
1461 Create bytecode, constant, and fixup segment for C<file_nam>. If C<add> is
1462 true, the current packfile becomes the owner of these segments by adding the
1463 segments to the directory.
1470 PARROT_WARN_UNUSED_RESULT
1471 PARROT_CANNOT_RETURN_NULL
1473 PF_create_default_segs(PARROT_INTERP
, ARGIN(const char *file_name
), int add
)
1475 PackFile
* const pf
= interp
->initial_pf
;
1476 PackFile_ByteCode
* const cur_cs
=
1477 (PackFile_ByteCode
*)create_seg(interp
, &pf
->directory
,
1478 PF_BYTEC_SEG
, BYTE_CODE_SEGMENT_NAME
, file_name
, add
);
1481 (PackFile_FixupTable
*)create_seg(interp
, &pf
->directory
,
1482 PF_FIXUP_SEG
, FIXUP_TABLE_SEGMENT_NAME
, file_name
, add
);
1484 cur_cs
->fixups
->code
= cur_cs
;
1486 cur_cs
->const_table
=
1487 (PackFile_ConstTable
*)create_seg(interp
, &pf
->directory
,
1488 PF_CONST_SEG
, CONSTANT_SEGMENT_NAME
, file_name
, add
);
1490 cur_cs
->const_table
->code
= cur_cs
;
1492 cur_cs
->pic_index
= create_seg(interp
, &pf
->directory
,
1493 PF_UNKNOWN_SEG
, "PIC_idx", file_name
, add
);
1501 =item C<void PackFile_Segment_destroy>
1503 RT#48260: Not yet documented!!!
1511 PackFile_Segment_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
1513 const PackFile_Segment_destroy_func_t f
=
1514 self
->pf
->PackFuncs
[self
->type
].destroy
;
1519 /* destroy self after specific */
1520 default_destroy(self
);
1526 =item C<size_t PackFile_Segment_packed_size>
1528 RT#48260: Not yet documented!!!
1536 PackFile_Segment_packed_size(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
))
1538 size_t size
= default_packed_size(self
);
1539 const size_t align
= 16 / sizeof (opcode_t
);
1540 PackFile_Segment_packed_size_func_t f
=
1541 self
->pf
->PackFuncs
[self
->type
].packed_size
;
1544 size
+= (f
)(interp
, self
);
1547 if (align
&& size
% align
)
1548 size
+= (align
- size
% align
);
1556 =item C<opcode_t * PackFile_Segment_pack>
1558 RT#48260: Not yet documented!!!
1565 PARROT_WARN_UNUSED_RESULT
1566 PARROT_CANNOT_RETURN_NULL
1568 PackFile_Segment_pack(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
),
1569 ARGIN(opcode_t
*cursor
))
1571 const size_t align
= 16 / sizeof (opcode_t
);
1572 PackFile_Segment_pack_func_t f
=
1573 self
->pf
->PackFuncs
[self
->type
].pack
;
1575 cursor
= default_pack(self
, cursor
);
1578 cursor
= (f
)(interp
, self
, cursor
);
1580 if (align
&& (cursor
- self
->pf
->src
) % align
)
1581 cursor
+= align
- (cursor
- self
->pf
->src
) % align
;
1589 =item C<const opcode_t * PackFile_Segment_unpack>
1591 All all these functions call the related C<default_*> function.
1593 If a special is defined this gets called after.
1600 PARROT_WARN_UNUSED_RESULT
1601 PARROT_CAN_RETURN_NULL
1603 PackFile_Segment_unpack(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
),
1604 ARGIN(const opcode_t
*cursor
))
1606 PackFile_Segment_unpack_func_t f
= self
->pf
->PackFuncs
[self
->type
].unpack
;
1608 cursor
= default_unpack(self
, cursor
);
1614 cursor
= (f
)(interp
, self
, cursor
);
1619 ALIGN_16(self
->pf
->src
, cursor
);
1626 =item C<void PackFile_Segment_dump>
1628 Dumps the segment C<self>.
1636 PackFile_Segment_dump(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
))
1638 self
->pf
->PackFuncs
[self
->type
].dump(interp
, self
);
1646 =head2 Standard Directory Functions
1650 =item C<static PackFile_Segment * directory_new>
1652 Returns a new C<PackFile_Directory> cast as a C<PackFile_Segment>.
1658 PARROT_WARN_UNUSED_RESULT
1659 PARROT_CANNOT_RETURN_NULL
1660 static PackFile_Segment
*
1661 directory_new(SHIM_INTERP
, SHIM(PackFile
*pf
), SHIM(const char *name
), SHIM(int add
))
1664 return (PackFile_Segment
*)mem_allocate_zeroed_typed(PackFile_Directory
);
1670 =item C<static void directory_dump>
1672 Dumps the directory C<self>.
1679 directory_dump(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
1681 const PackFile_Directory
* const dir
= (const PackFile_Directory
*) self
;
1684 default_dump_header(interp
, self
);
1686 PIO_printf(interp
, "\n\t# %d segments\n", dir
->num_segments
);
1688 for (i
= 0; i
< dir
->num_segments
; i
++) {
1689 const PackFile_Segment
* const seg
= dir
->segments
[i
];
1693 "\ttype %d\t%s\t", (int)seg
->type
, seg
->name
);
1695 " offs 0x%x(0x%x)\top_count %d\n",
1696 (int)seg
->file_offset
,
1697 (int)seg
->file_offset
* sizeof (opcode_t
),
1698 (int)seg
->op_count
);
1701 PIO_printf(interp
, "]\n");
1703 for (i
= 0; i
< dir
->num_segments
; i
++)
1704 PackFile_Segment_dump(interp
, dir
->segments
[i
]);
1710 =item C<static const opcode_t * directory_unpack>
1712 Unpacks the directory.
1718 PARROT_WARN_UNUSED_RESULT
1719 PARROT_CANNOT_RETURN_NULL
1720 static const opcode_t
*
1721 directory_unpack(PARROT_INTERP
, ARGMOD(PackFile_Segment
*segp
), ARGIN(const opcode_t
*cursor
))
1723 PackFile_Directory
* const dir
= (PackFile_Directory
*) segp
;
1724 PackFile
* const pf
= dir
->base
.pf
;
1725 const opcode_t
*pos
;
1728 dir
->num_segments
= PF_fetch_opcode(pf
, &cursor
);
1729 mem_realloc_n_typed(dir
->segments
, dir
->num_segments
, PackFile_Segment
*);
1731 for (i
= 0; i
< dir
->num_segments
; i
++) {
1732 PackFile_Segment
*seg
;
1737 UINTVAL type
= PF_fetch_opcode(pf
, &cursor
);
1739 if (type
>= PF_MAX_SEG
)
1740 type
= PF_UNKNOWN_SEG
;
1743 PIO_eprintf(NULL
, "Segment type %d.\n", type
);
1746 name
= PF_fetch_cstring(pf
, &cursor
);
1749 PIO_eprintf(NULL
, "Segment name \"%s\".\n", name
);
1753 seg
= PackFile_Segment_new_seg(interp
, dir
, type
, name
, 0);
1756 seg
->file_offset
= PF_fetch_opcode(pf
, &cursor
);
1757 seg
->op_count
= PF_fetch_opcode(pf
, &cursor
);
1759 if (pf
->need_wordsize
) {
1760 #if OPCODE_T_SIZE == 8
1761 if (pf
->header
->wordsize
== 4)
1762 pos
= pf
->src
+ seg
->file_offset
/ 2;
1764 if (pf
->header
->wordsize
== 8)
1765 pos
= pf
->src
+ seg
->file_offset
* 2;
1769 pos
= pf
->src
+ seg
->file_offset
;
1771 opcode
= PF_fetch_opcode(pf
, &pos
);
1773 if (seg
->op_count
!= opcode
) {
1775 "%s: Size in directory %d doesn't match size %d "
1776 "at offset 0x%x\n", seg
->name
, (int)seg
->op_count
,
1777 (int)opcode
, (int)seg
->file_offset
);
1781 PackFile_Segment
*last
= dir
->segments
[i
-1];
1782 if (last
->file_offset
+ last
->op_count
!= seg
->file_offset
) {
1783 fprintf(stderr
, "%s: sections are not back to back\n",
1788 make_code_pointers(seg
);
1790 /* store the segment */
1791 dir
->segments
[i
] = seg
;
1795 ALIGN_16(pf
->src
, cursor
);
1797 /* and now unpack contents of dir */
1798 for (i
= 0; cursor
&& i
< dir
->num_segments
; i
++) {
1799 const opcode_t
* const csave
= cursor
;
1801 /* check len again */
1802 size_t tmp
= PF_fetch_opcode(pf
, &cursor
);
1804 /* keep gcc -O silent */
1808 pos
= PackFile_Segment_unpack(interp
, dir
->segments
[i
], cursor
);
1811 fprintf(stderr
, "PackFile_unpack segment '%s' failed\n",
1812 dir
->segments
[i
]->name
);
1816 if (pf
->need_wordsize
) {
1817 #if OPCODE_T_SIZE == 8
1818 if (pf
->header
->wordsize
== 4)
1819 delta
= (pos
- cursor
) * 2;
1821 if (pf
->header
->wordsize
== 8)
1822 delta
= (pos
- cursor
) / 2;
1826 delta
= pos
- cursor
;
1828 if ((size_t)delta
!= tmp
|| dir
->segments
[i
]->op_count
!= tmp
)
1829 fprintf(stderr
, "PackFile_unpack segment '%s' directory length %d "
1830 "length in file %d needed %d for unpack\n",
1831 dir
->segments
[i
]->name
,
1832 (int)dir
->segments
[i
]->op_count
, (int)tmp
,
1843 =item C<static void directory_destroy>
1845 Destroys the directory.
1852 directory_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
1854 PackFile_Directory
* const dir
= (PackFile_Directory
*)self
;
1857 for (i
= 0; i
< dir
->num_segments
; i
++)
1858 PackFile_Segment_destroy(interp
, dir
->segments
[i
]);
1860 if (dir
->segments
) {
1861 mem_sys_free(dir
->segments
);
1862 dir
->segments
= NULL
;
1869 =item C<static void sort_segs>
1871 Sorts the segments in C<dir>.
1878 sort_segs(ARGMOD(PackFile_Directory
*dir
))
1880 const size_t num_segs
= dir
->num_segments
;
1881 PackFile_Segment
*seg
= dir
->segments
[0];
1883 if (seg
->type
!= PF_BYTEC_SEG
) {
1886 for (i
= 1; i
< num_segs
; i
++) {
1887 PackFile_Segment
* const s2
= dir
->segments
[i
];
1888 if (s2
->type
== PF_BYTEC_SEG
) {
1889 dir
->segments
[0] = s2
;
1890 dir
->segments
[i
] = seg
;
1896 seg
= dir
->segments
[1];
1898 if (seg
->type
!= PF_FIXUP_SEG
) {
1901 for (i
= 2; i
< num_segs
; i
++) {
1902 PackFile_Segment
* const s2
= dir
->segments
[i
];
1903 if (s2
->type
== PF_FIXUP_SEG
) {
1904 dir
->segments
[1] = s2
;
1905 dir
->segments
[i
] = seg
;
1915 =item C<static size_t directory_packed_size>
1917 Returns the size of the directory minus the value returned by
1918 C<default_packed_size()>.
1925 directory_packed_size(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
1927 PackFile_Directory
* const dir
= (PackFile_Directory
*)self
;
1928 const size_t align
= 16 / sizeof (opcode_t
);
1931 /* need bytecode, fixup, other segs ... */
1934 /* number of segments + default, we need it for the offsets */
1935 size
= 1 + default_packed_size(self
);
1937 for (i
= 0; i
< dir
->num_segments
; i
++) {
1938 /* type, offset, size */
1940 size
+= PF_size_cstring(dir
->segments
[i
]->name
);
1944 if (align
&& size
% align
)
1945 size
+= (align
- size
% align
);
1947 for (i
= 0; i
< dir
->num_segments
; i
++) {
1950 dir
->segments
[i
]->file_offset
= size
+ self
->file_offset
;
1952 PackFile_Segment_packed_size(interp
, dir
->segments
[i
]);
1953 dir
->segments
[i
]->op_count
= seg_size
;
1957 self
->op_count
= size
;
1959 /* subtract default, it is added in PackFile_Segment_packed_size */
1960 return size
- default_packed_size(self
);
1966 =item C<static opcode_t * directory_pack>
1968 Packs the directory C<self>.
1974 PARROT_WARN_UNUSED_RESULT
1975 PARROT_CANNOT_RETURN_NULL
1977 directory_pack(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
), ARGOUT(opcode_t
*cursor
))
1979 PackFile_Directory
* const dir
= (PackFile_Directory
*)self
;
1982 const size_t num_segs
= dir
->num_segments
;
1984 *cursor
++ = num_segs
;
1986 for (i
= 0; i
< num_segs
; i
++) {
1987 const PackFile_Segment
* const seg
= dir
->segments
[i
];
1988 *cursor
++ = seg
->type
;
1989 cursor
= PF_store_cstring(cursor
, seg
->name
);
1990 *cursor
++ = seg
->file_offset
;
1991 *cursor
++ = seg
->op_count
;
1993 align
= 16/sizeof (opcode_t
);
1994 if (align
&& (cursor
- self
->pf
->src
) % align
)
1995 cursor
+= align
- (cursor
- self
->pf
->src
) % align
;
1997 /* now pack all segments into new format */
1998 for (i
= 0; i
< dir
->num_segments
; i
++) {
1999 PackFile_Segment
* const seg
= dir
->segments
[i
];
2001 cursor
= PackFile_Segment_pack(interp
, seg
, cursor
);
2011 =head2 C<PackFile_Segment> Functions
2015 =item C<static void segment_init>
2017 Initializes the segment C<self>.
2024 segment_init(ARGOUT(PackFile_Segment
*self
), ARGIN(PackFile
*pf
),
2025 ARGIN(const char *name
))
2028 self
->type
= PF_UNKNOWN_SEG
;
2029 self
->file_offset
= 0;
2035 self
->name
= str_dup(name
);
2040 =item C<PackFile_Segment * PackFile_Segment_new>
2042 Create a new default section.
2049 PARROT_WARN_UNUSED_RESULT
2050 PARROT_CANNOT_RETURN_NULL
2052 PackFile_Segment_new(SHIM_INTERP
, SHIM(PackFile
*pf
), SHIM(const char *name
), SHIM(int add
))
2054 PackFile_Segment
* const seg
= mem_allocate_typed(PackFile_Segment
);
2063 =head2 Default Function Implementations
2065 The default functions are called before the segment specific functions
2066 and can read a block of C<opcode_t> data.
2070 =item C<static void default_destroy>
2072 The default destroy function.
2079 default_destroy(ARGMOD(PackFile_Segment
*self
))
2081 if (!self
->pf
->is_mmap_ped
&& self
->data
) {
2082 mem_sys_free(self
->data
);
2086 mem_sys_free(self
->name
);
2094 =item C<static size_t default_packed_size>
2096 Returns the default size of the segment C<self>.
2103 default_packed_size(ARGIN(const PackFile_Segment
*self
))
2105 /* op_count, itype, id, size */
2106 /* XXX There should be a constant defining this 4, and why */
2107 /* This is the 2nd place in the file that has this */
2108 return 4 + self
->size
;
2113 =item C<static opcode_t * default_pack>
2115 Performs the default pack.
2121 PARROT_WARN_UNUSED_RESULT
2122 PARROT_CANNOT_RETURN_NULL
2124 default_pack(ARGIN(const PackFile_Segment
*self
), ARGOUT(opcode_t
*dest
))
2126 *dest
++ = self
->op_count
;
2127 *dest
++ = self
->itype
;
2129 *dest
++ = self
->size
;
2131 STRUCT_COPY_N(dest
, self
->data
, self
->size
);
2132 return dest
+ self
->size
;
2143 =item C<static void byte_code_destroy>
2145 Destroys the C<PackFile_ByteCode> segment C<self>.
2152 byte_code_destroy(SHIM_INTERP
, ARGMOD(PackFile_Segment
*self
))
2154 PackFile_ByteCode
* const byte_code
= (PackFile_ByteCode
*)self
;
2157 Parrot_destroy_jit(byte_code
->jit_info
);
2159 parrot_PIC_destroy(byte_code
);
2160 if (byte_code
->prederef
.code
) {
2161 Parrot_free_memalign(byte_code
->prederef
.code
);
2162 byte_code
->prederef
.code
= NULL
;
2163 if (byte_code
->prederef
.branches
) {
2164 mem_sys_free(byte_code
->prederef
.branches
);
2165 byte_code
->prederef
.branches
= NULL
;
2168 byte_code
->fixups
= NULL
;
2169 byte_code
->const_table
= NULL
;
2170 byte_code
->pic_index
= NULL
;
2171 byte_code
->debugs
= NULL
;
2176 =item C<static PackFile_Segment * byte_code_new>
2178 New C<PackFile_ByteCode> segment.
2180 C<pf> and C<add> are ignored.
2186 PARROT_WARN_UNUSED_RESULT
2187 PARROT_CANNOT_RETURN_NULL
2188 static PackFile_Segment
*
2189 byte_code_new(SHIM_INTERP
, SHIM(PackFile
*pf
), SHIM(const char *name
), SHIM(int add
))
2191 PackFile_ByteCode
* const byte_code
= mem_allocate_zeroed_typed(PackFile_ByteCode
);
2193 return (PackFile_Segment
*) byte_code
;
2204 =item C<static void pf_debug_destroy>
2206 Destroys the C<PackFile_Debug> segment C<self>.
2213 pf_debug_destroy(SHIM_INTERP
, ARGMOD(PackFile_Segment
*self
))
2215 PackFile_Debug
* const debug
= (PackFile_Debug
*) self
;
2218 /* Free each mapping. */
2219 for (i
= 0; i
< debug
->num_mappings
; i
++)
2220 mem_sys_free(debug
->mappings
[i
]);
2222 /* Free mappings pointer array. */
2223 mem_sys_free(debug
->mappings
);
2224 debug
->mappings
= NULL
;
2225 debug
->num_mappings
= 0;
2230 =item C<static PackFile_Segment * pf_debug_new>
2232 Returns a new C<PackFile_Debug> segment.
2234 C<pf> and C<add> ignored.
2240 PARROT_WARN_UNUSED_RESULT
2241 PARROT_CANNOT_RETURN_NULL
2242 static PackFile_Segment
*
2243 pf_debug_new(SHIM_INTERP
, SHIM(PackFile
*pf
), SHIM(const char *name
), SHIM(int add
))
2245 PackFile_Debug
* const debug
= mem_allocate_zeroed_typed(PackFile_Debug
);
2247 debug
->mappings
= mem_allocate_typed(PackFile_DebugMapping
*);
2248 debug
->mappings
[0] = NULL
;
2250 return (PackFile_Segment
*)debug
;
2255 =item C<static size_t pf_debug_packed_size>
2257 Returns the size of the C<PackFile_Debug> segment's filename in
2265 pf_debug_packed_size(SHIM_INTERP
, ARGIN(PackFile_Segment
*self
))
2267 PackFile_Debug
* const debug
= (PackFile_Debug
*)self
;
2271 /* Size of mappings count. */
2274 /* Size of entries in mappings list. */
2275 for (i
= 0; i
< debug
->num_mappings
; i
++) {
2276 /* Bytecode offset and mapping type */
2279 /* Mapping specific stuff. */
2280 switch (debug
->mappings
[i
]->mapping_type
) {
2281 case PF_DEBUGMAPPINGTYPE_FILENAME
:
2282 case PF_DEBUGMAPPINGTYPE_SOURCESEG
:
2285 case PF_DEBUGMAPPINGTYPE_NONE
:
2296 =item C<static opcode_t * pf_debug_pack>
2298 Pack the debug segment.
2304 PARROT_WARN_UNUSED_RESULT
2305 PARROT_CANNOT_RETURN_NULL
2307 pf_debug_pack(SHIM_INTERP
, ARGMOD(PackFile_Segment
*self
), ARGOUT(opcode_t
*cursor
))
2309 PackFile_Debug
* const debug
= (PackFile_Debug
*)self
;
2311 const int n
= debug
->num_mappings
;
2313 /* Store number of mappings. */
2316 /* Now store each mapping. */
2317 for (i
= 0; i
< n
; i
++) {
2318 /* Bytecode offset and mapping type */
2319 *cursor
++ = debug
->mappings
[i
]->offset
;
2320 *cursor
++ = debug
->mappings
[i
]->mapping_type
;
2322 /* Mapping specific stuff. */
2323 switch (debug
->mappings
[i
]->mapping_type
) {
2324 case PF_DEBUGMAPPINGTYPE_FILENAME
:
2325 *cursor
++ = debug
->mappings
[i
]->u
.filename
;
2327 case PF_DEBUGMAPPINGTYPE_SOURCESEG
:
2328 *cursor
++ = debug
->mappings
[i
]->u
.source_seg
;
2330 case PF_DEBUGMAPPINGTYPE_NONE
:
2341 =item C<static const opcode_t * pf_debug_unpack>
2343 Unpack a debug segment into a PackFile_Debug structure.
2349 PARROT_WARN_UNUSED_RESULT
2350 PARROT_CANNOT_RETURN_NULL
2351 static const opcode_t
*
2352 pf_debug_unpack(PARROT_INTERP
, ARGOUT(PackFile_Segment
*self
), ARGIN(const opcode_t
*cursor
))
2354 PackFile_Debug
* const debug
= (PackFile_Debug
*)self
;
2355 PackFile_ByteCode
*code
;
2358 /* For some reason, we store the source file name in the segment
2359 name. So we can't find the bytecode seg without knowing the filename.
2360 But with the new scheme we can have many file names. For now, just
2361 base this on the name of the debug segment. */
2362 char *code_name
= NULL
;
2365 /* Number of mappings. */
2366 debug
->num_mappings
= PF_fetch_opcode(self
->pf
, &cursor
);
2368 /* Allocate space for mappings vector. */
2369 mem_realloc_n_typed(debug
->mappings
, debug
->num_mappings
+1, PackFile_DebugMapping
*);
2371 /* Read in each mapping. */
2372 for (i
= 0; i
< debug
->num_mappings
; i
++) {
2373 /* Allocate struct and get offset and mapping type. */
2374 debug
->mappings
[i
] = mem_allocate_typed(PackFile_DebugMapping
);
2375 debug
->mappings
[i
]->offset
= PF_fetch_opcode(self
->pf
, &cursor
);
2376 debug
->mappings
[i
]->mapping_type
= PF_fetch_opcode(self
->pf
, &cursor
);
2378 /* Read mapping specific stuff. */
2379 switch (debug
->mappings
[i
]->mapping_type
) {
2380 case PF_DEBUGMAPPINGTYPE_FILENAME
:
2381 debug
->mappings
[i
]->u
.filename
=
2382 PF_fetch_opcode(self
->pf
, &cursor
);
2384 case PF_DEBUGMAPPINGTYPE_SOURCESEG
:
2385 debug
->mappings
[i
]->u
.source_seg
=
2386 PF_fetch_opcode(self
->pf
, &cursor
);
2388 case PF_DEBUGMAPPINGTYPE_NONE
:
2395 * find seg e.g. CODE_DB => CODE
2398 code_name
= str_dup(debug
->base
.name
);
2399 str_len
= strlen(code_name
);
2400 code_name
[str_len
- 3] = 0;
2401 code
= (PackFile_ByteCode
*)PackFile_find_segment(interp
,
2402 self
->dir
, code_name
, 0);
2403 if (!code
|| code
->base
.type
!= PF_BYTEC_SEG
) {
2404 real_exception(interp
, NULL
, 1, "Code '%s' not found for debug segment '%s'\n",
2405 code_name
, self
->name
);
2407 code
->debugs
= debug
;
2409 mem_sys_free(code_name
);
2416 =item C<static void pf_debug_dump>
2418 Dumps a debug segment to a human readable form.
2425 pf_debug_dump(PARROT_INTERP
, ARGIN(const PackFile_Segment
*self
))
2429 const PackFile_Debug
* const debug
= (const PackFile_Debug
*)self
;
2431 default_dump_header(interp
, self
);
2433 PIO_printf(interp
, "\n mappings => [\n");
2434 for (i
= 0; i
< debug
->num_mappings
; i
++) {
2435 PIO_printf(interp
, " #%d\n [\n", i
);
2436 PIO_printf(interp
, " OFFSET => %d,\n",
2437 debug
->mappings
[i
]->offset
);
2438 switch (debug
->mappings
[i
]->mapping_type
) {
2439 case PF_DEBUGMAPPINGTYPE_NONE
:
2440 PIO_printf(interp
, " MAPPINGTYPE => NONE\n");
2442 case PF_DEBUGMAPPINGTYPE_FILENAME
:
2446 PIO_printf(interp
, " MAPPINGTYPE => FILENAME,\n");
2447 filename
= string_to_cstring(interp
, PF_CONST(debug
->code
,
2448 debug
->mappings
[i
]->u
.filename
)->u
.string
);
2449 PIO_printf(interp
, " FILENAME => %s\n", filename
);
2450 string_cstring_free(filename
);
2453 case PF_DEBUGMAPPINGTYPE_SOURCESEG
:
2454 PIO_printf(interp
, " MAPPINGTYPE => SOURCESEG,\n");
2455 PIO_printf(interp
, " SOURCESEG => %d\n",
2456 debug
->mappings
[i
]->u
.source_seg
);
2461 PIO_printf(interp
, " ],\n");
2464 PIO_printf(interp
, " ]\n");
2466 j
= self
->data
? 0: self
->file_offset
+ 4;
2468 PIO_printf(interp
, "\n %04x: ", (int) j
);
2470 for (; j
< (self
->data
? self
->size
:
2471 self
->file_offset
+ self
->op_count
); j
++) {
2473 PIO_printf(interp
, "\n %04x: ", (int) j
);
2475 PIO_printf(interp
, "%08lx ", (unsigned long)
2476 self
->data
? self
->data
[j
] : self
->pf
->src
[j
]);
2478 PIO_printf(interp
, "\n]\n");
2483 =item C<PackFile_Debug * Parrot_new_debug_seg>
2485 Create and append (or resize) a new debug seg for a code segment.
2492 PARROT_WARN_UNUSED_RESULT
2493 PARROT_CANNOT_RETURN_NULL
2495 Parrot_new_debug_seg(PARROT_INTERP
, ARGMOD(PackFile_ByteCode
*cs
), size_t size
)
2497 PackFile_Debug
*debug
;
2499 if (cs
->debugs
) { /* it exists already, resize it */
2501 mem_realloc_n_typed(debug
->base
.data
, size
, opcode_t
);
2503 else { /* create one */
2504 const size_t len
= strlen(cs
->base
.name
) + 4;
2505 char * const name
= (char *)mem_sys_allocate(len
);
2506 const int add
= (interp
->code
&& interp
->code
->base
.dir
);
2507 PackFile_Directory
* const dir
=
2509 ? interp
->code
->base
.dir
2512 : &interp
->initial_pf
->directory
;
2514 snprintf(name
, len
, "%s_DB", cs
->base
.name
);
2515 debug
= (PackFile_Debug
*)PackFile_Segment_new_seg(interp
, dir
, PF_DEBUG_SEG
, name
, add
);
2518 debug
->base
.data
= mem_allocate_n_zeroed_typed(size
, opcode_t
);
2522 debug
->base
.size
= size
;
2528 =item C<void Parrot_debug_add_mapping>
2530 Add a bytecode offset to filename/source segment mapping. mapping_type may be
2531 one of PF_DEBUGMAPPINGTYPE_NONE (in which case the last two parameters are
2532 ignored), PF_DEBUGMAPPINGTYPE_FILENAME (in which case filename must be given)
2533 or PF_DEBUGMAPPINGTYPE_SOURCESEG (in which case source_seg should contains the
2534 number of the source segment in question).
2542 Parrot_debug_add_mapping(PARROT_INTERP
, ARGMOD(PackFile_Debug
*debug
),
2543 opcode_t offset
, int mapping_type
,
2544 ARGIN(const char *filename
), int source_seg
)
2546 PackFile_DebugMapping
*mapping
;
2547 PackFile_ConstTable
* const ct
= debug
->code
->const_table
;
2550 /* Allocate space for the extra entry. */
2551 mem_realloc_n_typed(debug
->mappings
, debug
->num_mappings
+1, PackFile_DebugMapping
*);
2553 /* Can it just go on the end? */
2554 if (debug
->num_mappings
== 0 ||
2555 offset
>= debug
->mappings
[debug
->num_mappings
- 1]->offset
)
2557 insert_pos
= debug
->num_mappings
;
2560 /* Find the right place and shift stuff that's after it. */
2562 for (i
= 0; i
< debug
->num_mappings
; i
++) {
2563 if (debug
->mappings
[i
]->offset
> offset
) {
2565 memmove(debug
->mappings
+ i
+ 1, debug
->mappings
+ i
,
2566 debug
->num_mappings
- i
);
2572 /* Set up new entry and insert it. */
2573 mapping
= mem_allocate_typed(PackFile_DebugMapping
);
2574 mapping
->offset
= offset
;
2575 mapping
->mapping_type
= mapping_type
;
2577 switch (mapping_type
) {
2578 case PF_DEBUGMAPPINGTYPE_FILENAME
:
2580 PackFile_Constant
*fnconst
;
2582 /* Need to put filename in constants table. */
2583 ct
->const_count
= ct
->const_count
+ 1;
2584 mem_realloc_n_typed(ct
->constants
, ct
->const_count
, PackFile_Constant
*);
2585 fnconst
= PackFile_Constant_new(interp
);
2586 fnconst
->type
= PFC_STRING
;
2587 fnconst
->u
.string
= string_make_direct(interp
, filename
,
2588 strlen(filename
), PARROT_DEFAULT_ENCODING
,
2589 PARROT_DEFAULT_CHARSET
, PObj_constant_FLAG
);
2590 ct
->constants
[ct
->const_count
- 1] = fnconst
;
2591 mapping
->u
.filename
= ct
->const_count
- 1;
2594 case PF_DEBUGMAPPINGTYPE_SOURCESEG
:
2595 mapping
->u
.source_seg
= source_seg
;
2597 case PF_DEBUGMAPPINGTYPE_NONE
:
2602 debug
->mappings
[insert_pos
] = mapping
;
2603 debug
->num_mappings
= debug
->num_mappings
+ 1;
2608 =item C<STRING * Parrot_debug_pc_to_filename>
2610 Take a position in the bytecode and return the filename of the source for
2618 PARROT_WARN_UNUSED_RESULT
2619 PARROT_CANNOT_RETURN_NULL
2621 Parrot_debug_pc_to_filename(PARROT_INTERP
, ARGIN(const PackFile_Debug
*debug
), opcode_t pc
)
2623 /* Look through mappings until we find one that maps the passed
2626 for (i
= 0; i
< debug
->num_mappings
; i
++) {
2627 /* If this is the last mapping or the current position is
2628 between this mapping and the next one, return a filename. */
2629 if (i
+ 1 == debug
->num_mappings
||
2630 (debug
->mappings
[i
]->offset
<= pc
&&
2631 debug
->mappings
[i
+1]->offset
> pc
))
2633 switch (debug
->mappings
[i
]->mapping_type
) {
2634 case PF_DEBUGMAPPINGTYPE_NONE
:
2635 return string_from_literal(interp
,
2637 case PF_DEBUGMAPPINGTYPE_FILENAME
:
2638 return PF_CONST(debug
->code
,
2639 debug
->mappings
[i
]->u
.filename
)->u
.string
;
2640 case PF_DEBUGMAPPINGTYPE_SOURCESEG
:
2641 return string_from_literal(interp
,
2649 /* Otherwise, no mappings = no filename. */
2650 return string_from_literal(interp
, "(unknown file)");
2655 =item C<void Parrot_switch_to_cs_by_nr>
2657 Switch to byte code segment number C<seg>.
2665 Parrot_switch_to_cs_by_nr(PARROT_INTERP
, opcode_t seg
)
2667 const PackFile_Directory
* const dir
= interp
->code
->base
.dir
;
2668 const size_t num_segs
= dir
->num_segments
;
2672 /* TODO make an index of code segments for faster look up */
2673 for (i
= n
= 0; i
< num_segs
; i
++) {
2674 if (dir
->segments
[i
]->type
== PF_BYTEC_SEG
) {
2676 Parrot_switch_to_cs(interp
, (PackFile_ByteCode
*)
2677 dir
->segments
[i
], 1);
2683 real_exception(interp
, NULL
, 1, "Segment number %d not found\n", (int) seg
);
2688 =item C<PackFile_ByteCode * Parrot_switch_to_cs>
2690 Switch to a byte code segment C<new_cs>, returning the old segment.
2697 PARROT_IGNORABLE_RESULT
2698 PARROT_CANNOT_RETURN_NULL
2700 Parrot_switch_to_cs(PARROT_INTERP
, ARGIN(PackFile_ByteCode
*new_cs
), int really
)
2702 PackFile_ByteCode
* const cur_cs
= interp
->code
;
2705 real_exception(interp
, NULL
, NO_PREV_CS
, "No code segment to switch to\n");
2707 /* compiling source code uses this function too,
2708 * which gives misleading trace messages
2710 if (really
&& Interp_trace_TEST(interp
, PARROT_TRACE_SUB_CALL_FLAG
)) {
2711 Interp
* const tracer
= interp
->debugger
?
2712 interp
->debugger
: interp
;
2713 PIO_eprintf(tracer
, "*** switching to %s\n",
2716 interp
->code
= new_cs
;
2717 CONTEXT(interp
)->constants
=
2718 really
? find_constants(interp
, new_cs
->const_table
) :
2719 new_cs
->const_table
->constants
;
2720 /* new_cs->const_table->constants; */
2721 CONTEXT(interp
)->pred_offset
=
2722 new_cs
->base
.data
- (opcode_t
*) new_cs
->prederef
.code
;
2724 prepare_for_run(interp
);
2730 =item C<static PackFile_Constant * clone_constant>
2732 RT#48260: Not yet documented!!!
2738 PARROT_WARN_UNUSED_RESULT
2739 PARROT_CANNOT_RETURN_NULL
2740 static PackFile_Constant
*
2741 clone_constant(PARROT_INTERP
, ARGIN(PackFile_Constant
*old_const
))
2743 STRING
* const _sub
= interp
->vtables
[enum_class_Sub
]->whoami
;
2745 if (old_const
->type
== PFC_PMC
2746 && VTABLE_isa(interp
, old_const
->u
.key
, _sub
)) {
2749 PackFile_Constant
* const ret
= mem_allocate_typed(PackFile_Constant
);
2751 ret
->type
= old_const
->type
;
2753 old_sub
= old_const
->u
.key
;
2754 new_sub
= Parrot_thaw_constants(interp
,
2755 Parrot_freeze(interp
, old_sub
));
2757 PMC_sub(new_sub
)->seg
= PMC_sub(old_sub
)->seg
;
2759 /* Vtable overrides and methods were already cloned, so don't reclone them. */
2760 if (PMC_sub(new_sub
)->vtable_index
== -1
2761 && !(PMC_sub(old_sub
)->comp_flags
& SUB_COMP_FLAG_METHOD
)) {
2762 Parrot_store_sub_in_namespace(interp
, new_sub
);
2765 ret
->u
.key
= new_sub
;
2776 =item C<static PackFile_Constant ** find_constants>
2778 Find the constant table associated with a thread. For now, we need to copy
2779 constant tables because some entries aren't really constant; e.g.
2780 subroutines need to reference namespace pointers.
2786 PARROT_WARN_UNUSED_RESULT
2787 PARROT_CANNOT_RETURN_NULL
2788 static PackFile_Constant
**
2789 find_constants(PARROT_INTERP
, ARGIN(PackFile_ConstTable
*ct
))
2791 if (!n_interpreters
|| !interp
->thread_data
||
2792 interp
->thread_data
->tid
== 0) {
2793 return ct
->constants
;
2797 PackFile_Constant
**new_consts
;
2799 PARROT_ASSERT(interp
->thread_data
);
2801 if (!interp
->thread_data
->const_tables
) {
2802 interp
->thread_data
->const_tables
= mem_allocate_typed(Hash
);
2803 parrot_new_pointer_hash(interp
,
2804 &interp
->thread_data
->const_tables
);
2807 tables
= interp
->thread_data
->const_tables
;
2808 new_consts
= (PackFile_Constant
**)parrot_hash_get(interp
, tables
, ct
);
2811 /* need to construct it */
2812 INTVAL
const num_consts
= ct
->const_count
;
2813 PackFile_Constant
** const old_consts
= ct
->constants
;
2816 new_consts
= (PackFile_Constant
**)mem_sys_allocate(
2817 sizeof (PackFile_Constant
*) * num_consts
);
2819 for (i
= 0; i
< num_consts
; ++i
) {
2820 new_consts
[i
] = clone_constant(interp
, old_consts
[i
]);
2823 parrot_hash_put(interp
, tables
, ct
, new_consts
);
2832 =item C<void Parrot_destroy_constants>
2834 RT#48260: Not yet documented!!!
2842 Parrot_destroy_constants(PARROT_INTERP
)
2846 if (!interp
->thread_data
) {
2850 hash
= interp
->thread_data
->const_tables
;
2856 for (i
= 0; i
<= hash
->mask
; ++i
) {
2857 HashBucket
*bucket
= hash
->bi
[i
];
2859 PackFile_ConstTable
* const table
=
2860 (PackFile_ConstTable
*)bucket
->key
;
2861 PackFile_Constant
** const orig_consts
= table
->constants
;
2862 PackFile_Constant
** const consts
=
2863 (PackFile_Constant
**) bucket
->value
;
2864 INTVAL
const const_count
= table
->const_count
;
2867 for (i
= 0; i
< const_count
; ++i
) {
2868 if (consts
[i
] != orig_consts
[i
]) {
2869 mem_sys_free(consts
[i
]);
2872 mem_sys_free(consts
);
2873 bucket
= bucket
->next
;
2877 parrot_hash_destroy(interp
, hash
);
2884 =head2 PackFile FixupTable Structure Functions
2888 =item C<void PackFile_FixupTable_clear>
2890 Clear a PackFile FixupTable.
2898 PackFile_FixupTable_clear(PARROT_INTERP
, ARGMOD(PackFile_FixupTable
*self
))
2902 PIO_eprintf(interp
, "PackFile_FixupTable_clear: self == NULL!\n");
2906 for (i
= 0; i
< self
->fixup_count
; i
++) {
2907 mem_sys_free(self
->fixups
[i
]->name
);
2908 self
->fixups
[i
]->name
= NULL
;
2909 mem_sys_free(self
->fixups
[i
]);
2910 self
->fixups
[i
] = NULL
;
2913 if (self
->fixup_count
) {
2914 mem_sys_free(self
->fixups
);
2915 self
->fixups
= NULL
;
2918 self
->fixups
= NULL
;
2919 self
->fixup_count
= 0;
2926 =item C<static void fixup_destroy>
2928 Just calls C<PackFile_FixupTable_clear()> with C<self>.
2935 fixup_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
2937 PackFile_FixupTable
* const ft
= (PackFile_FixupTable
*)self
;
2938 PackFile_FixupTable_clear(interp
, ft
);
2943 =item C<static size_t fixup_packed_size>
2945 I<What does this do?>
2947 RT#48260: Not yet documented!!!
2954 fixup_packed_size(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
2956 PackFile_FixupTable
* const ft
= (PackFile_FixupTable
*)self
;
2960 size
= 1; /* fixup_count */
2961 for (i
= 0; i
< ft
->fixup_count
; i
++) {
2962 size
++; /* fixup_entry type */
2963 switch (ft
->fixups
[i
]->type
) {
2964 case enum_fixup_label
:
2965 case enum_fixup_sub
:
2966 size
+= PF_size_cstring(ft
->fixups
[i
]->name
);
2967 size
++; /* offset */
2969 case enum_fixup_none
:
2972 real_exception(interp
, NULL
, 1, "Unknown fixup type\n");
2980 =item C<static opcode_t * fixup_pack>
2982 I<What does this do?>
2984 RT#48260: Not yet documented!!!
2990 PARROT_WARN_UNUSED_RESULT
2991 PARROT_CANNOT_RETURN_NULL
2993 fixup_pack(PARROT_INTERP
, ARGIN(PackFile_Segment
*self
), ARGOUT(opcode_t
*cursor
))
2995 PackFile_FixupTable
* const ft
= (PackFile_FixupTable
*)self
;
2998 *cursor
++ = ft
->fixup_count
;
2999 for (i
= 0; i
< ft
->fixup_count
; i
++) {
3000 *cursor
++ = (opcode_t
) ft
->fixups
[i
]->type
;
3001 switch (ft
->fixups
[i
]->type
) {
3002 case enum_fixup_label
:
3003 case enum_fixup_sub
:
3004 cursor
= PF_store_cstring(cursor
, ft
->fixups
[i
]->name
);
3005 *cursor
++ = ft
->fixups
[i
]->offset
;
3007 case enum_fixup_none
:
3010 real_exception(interp
, NULL
, 1, "Unknown fixup type\n");
3018 =item C<static PackFile_Segment * fixup_new>
3020 Returns a new C<PackFile_FixupTable> segment.
3026 PARROT_WARN_UNUSED_RESULT
3027 PARROT_CANNOT_RETURN_NULL
3028 static PackFile_Segment
*
3029 fixup_new(SHIM_INTERP
, SHIM(PackFile
*pf
), SHIM(const char *name
), SHIM(int add
))
3031 PackFile_FixupTable
* const fixup
= mem_allocate_zeroed_typed(PackFile_FixupTable
);
3033 return (PackFile_Segment
*) fixup
;
3038 =item C<static const opcode_t * fixup_unpack>
3040 Unpack a PackFile FixupTable from a block of memory.
3042 Returns one (1) if everything is OK, else zero (0).
3048 PARROT_WARN_UNUSED_RESULT
3049 PARROT_CAN_RETURN_NULL
3050 static const opcode_t
*
3051 fixup_unpack(PARROT_INTERP
, ARGIN(PackFile_Segment
*seg
), ARGIN(const opcode_t
*cursor
))
3055 PackFile_FixupTable
* const self
= (PackFile_FixupTable
*)seg
;
3058 PIO_eprintf(interp
, "PackFile_FixupTable_unpack: self == NULL!\n");
3062 PackFile_FixupTable_clear(interp
, self
);
3065 self
->fixup_count
= PF_fetch_opcode(pf
, &cursor
);
3067 if (self
->fixup_count
) {
3068 self
->fixups
= (PackFile_FixupEntry
**)mem_sys_allocate_zeroed(
3069 self
->fixup_count
* sizeof (PackFile_FixupEntry
*));
3071 if (!self
->fixups
) {
3073 "PackFile_FixupTable_unpack: Could not allocate "
3074 "memory for array!\n");
3075 self
->fixup_count
= 0;
3080 for (i
= 0; i
< self
->fixup_count
; i
++) {
3081 PackFile_FixupEntry
* const entry
=
3083 mem_allocate_typed(PackFile_FixupEntry
);
3084 entry
->type
= PF_fetch_opcode(pf
, &cursor
);
3085 switch (entry
->type
) {
3086 case enum_fixup_label
:
3087 case enum_fixup_sub
:
3088 entry
->name
= PF_fetch_cstring(pf
, &cursor
);
3089 entry
->offset
= PF_fetch_opcode(pf
, &cursor
);
3091 case enum_fixup_none
:
3095 "PackFile_FixupTable_unpack: Unknown fixup type %d!\n",
3106 =item C<void PackFile_FixupTable_new_entry>
3108 I<What does this do?>
3110 RT#48260: Not yet documented!!!
3118 PackFile_FixupTable_new_entry(PARROT_INTERP
,
3119 ARGIN(const char *label
), INTVAL type
, opcode_t offs
)
3121 PackFile_FixupTable
*self
= interp
->code
->fixups
;
3125 self
= (PackFile_FixupTable
*) PackFile_Segment_new_seg(
3127 interp
->code
->base
.dir
, PF_FIXUP_SEG
,
3128 FIXUP_TABLE_SEGMENT_NAME
, 1);
3129 interp
->code
->fixups
= self
;
3130 self
->code
= interp
->code
;
3132 i
= self
->fixup_count
++;
3133 mem_realloc_n_typed(self
->fixups
, self
->fixup_count
, PackFile_FixupEntry
*);
3135 self
->fixups
[i
] = mem_allocate_typed(PackFile_FixupEntry
);
3136 self
->fixups
[i
]->type
= type
;
3137 self
->fixups
[i
]->name
= str_dup(label
);
3138 self
->fixups
[i
]->offset
= offs
;
3139 self
->fixups
[i
]->seg
= self
->code
;
3144 =item C<static PackFile_FixupEntry * find_fixup>
3146 Finds the fix-up entry for C<name> and returns it.
3152 PARROT_WARN_UNUSED_RESULT
3153 PARROT_CAN_RETURN_NULL
3154 static PackFile_FixupEntry
*
3155 find_fixup(ARGMOD(PackFile_FixupTable
*ft
), INTVAL type
, ARGIN(const char *name
))
3158 for (i
= 0; i
< ft
->fixup_count
; i
++) {
3159 if ((INTVAL
)((enum_fixup_t
)ft
->fixups
[i
]->type
) == type
&&
3160 STREQ(ft
->fixups
[i
]->name
, name
)) {
3161 ft
->fixups
[i
]->seg
= ft
->code
;
3162 return ft
->fixups
[i
];
3170 =item C<static INTVAL find_fixup_iter>
3172 I<What does this do?>
3174 RT#48260: Not yet documented!!!
3181 find_fixup_iter(PARROT_INTERP
, ARGIN(PackFile_Segment
*seg
), ARGIN(void *user_data
))
3183 if (seg
->type
== PF_DIR_SEG
) {
3184 if (PackFile_map_segments(interp
, (PackFile_Directory
*)seg
,
3185 find_fixup_iter
, user_data
))
3188 else if (seg
->type
== PF_FIXUP_SEG
) {
3189 PackFile_FixupEntry
** const e
= (PackFile_FixupEntry
**)user_data
;
3190 PackFile_FixupEntry
* const fe
= (PackFile_FixupEntry
*)find_fixup(
3191 (PackFile_FixupTable
*) seg
, (*e
)->type
, (*e
)->name
);
3202 =item C<PackFile_FixupEntry * PackFile_find_fixup_entry>
3204 I<What does this do?>
3206 RT#48260: Not yet documented!!!
3213 PARROT_WARN_UNUSED_RESULT
3214 PARROT_CAN_RETURN_NULL
3215 PackFile_FixupEntry
*
3216 PackFile_find_fixup_entry(PARROT_INTERP
, INTVAL type
, ARGIN(char *name
))
3218 /* TODO make a hash of all fixups */
3219 PackFile_Directory
* const dir
= interp
->code
->base
.dir
;
3220 PackFile_FixupEntry
* const ep
= mem_allocate_typed(PackFile_FixupEntry
);
3225 found
= PackFile_map_segments(interp
, dir
, find_fixup_iter
, (void *) ep
);
3226 return found
? ep
: NULL
;
3233 =head2 PackFile ConstTable Structure Functions
3237 =item C<void PackFile_ConstTable_clear>
3239 Clear the C<PackFile_ConstTable> C<self>.
3247 PackFile_ConstTable_clear(PARROT_INTERP
, ARGMOD(PackFile_ConstTable
*self
))
3251 for (i
= 0; i
< self
->const_count
; i
++) {
3252 PackFile_Constant_destroy(interp
, self
->constants
[i
]);
3253 self
->constants
[i
] = NULL
;
3256 if (self
->constants
) {
3257 mem_sys_free(self
->constants
);
3258 self
->constants
= NULL
;
3261 self
->const_count
= 0;
3267 PackFile_Constant
*exec_const_table
;
3272 =item C<const opcode_t * PackFile_ConstTable_unpack>
3274 Unpack a PackFile ConstTable from a block of memory. The format is:
3276 opcode_t const_count
3279 Returns cursor if everything is OK, else zero (0).
3286 PARROT_WARN_UNUSED_RESULT
3287 PARROT_CAN_RETURN_NULL
3289 PackFile_ConstTable_unpack(PARROT_INTERP
, ARGOUT(PackFile_Segment
*seg
),
3290 ARGIN(const opcode_t
*cursor
))
3293 PackFile_ConstTable
* const self
= (PackFile_ConstTable
*)seg
;
3294 PackFile
* const pf
= seg
->pf
;
3296 PackFile_ConstTable_clear(interp
, self
);
3298 self
->const_count
= PF_fetch_opcode(pf
, &cursor
);
3302 "PackFile_ConstTable_unpack: Unpacking %ld constants\n",
3306 if (self
->const_count
== 0) {
3310 self
->constants
= (PackFile_Constant
**)mem_sys_allocate_zeroed(
3311 self
->const_count
* sizeof (PackFile_Constant
*));
3313 if (!self
->constants
) {
3315 "PackFile_ConstTable_unpack: Could not allocate "
3316 "memory for array!\n");
3317 self
->const_count
= 0;
3321 for (i
= 0; i
< self
->const_count
; i
++) {
3324 "PackFile_ConstTable_unpack(): Unpacking constant %ld\n", i
);
3328 if (Parrot_exec_run
)
3329 self
->constants
[i
] = &exec_const_table
[i
];
3332 self
->constants
[i
] = PackFile_Constant_new(interp
);
3334 cursor
= PackFile_Constant_unpack(interp
, self
, self
->constants
[i
],
3342 =item C<static PackFile_Segment * const_new>
3344 Returns a new C<PackFile_ConstTable> segment.
3351 PARROT_CANNOT_RETURN_NULL
3352 static PackFile_Segment
*
3353 const_new(SHIM_INTERP
, SHIM(PackFile
*pf
), SHIM(const char *name
), SHIM(int add
))
3355 PackFile_ConstTable
* const const_table
= mem_allocate_zeroed_typed(PackFile_ConstTable
);
3357 return (PackFile_Segment
*)const_table
;
3362 =item C<static void const_destroy>
3364 Destroys the C<PackFile_ConstTable> C<self>.
3371 const_destroy(PARROT_INTERP
, ARGMOD(PackFile_Segment
*self
))
3373 PackFile_ConstTable
* const ct
= (PackFile_ConstTable
*)self
;
3375 PackFile_ConstTable_clear(interp
, ct
);
3382 =head2 PackFile Constant Structure Functions
3386 =item C<PackFile_Constant * PackFile_Constant_new>
3388 Allocate a new empty PackFile Constant.
3390 This is only here so we can make a new one and then do an unpack.
3398 PARROT_CANNOT_RETURN_NULL
3400 PackFile_Constant_new(SHIM_INTERP
)
3402 PackFile_Constant
* const self
=
3403 mem_allocate_zeroed_typed(PackFile_Constant
);
3405 self
->type
= PFC_NONE
;
3412 =item C<void PackFile_Constant_destroy>
3414 Delete the C<PackFile_Constant> C<self>.
3416 Don't delete C<PMC>s or C<STRING>s, they are destroyed via DOD/GC.
3424 PackFile_Constant_destroy(SHIM_INTERP
, ARGMOD_NULLOK(PackFile_Constant
*self
))
3431 =item C<size_t PackFile_Constant_pack_size>
3433 Determine the size of the buffer needed in order to pack the PackFile
3434 Constant into a contiguous region of memory.
3441 PARROT_WARN_UNUSED_RESULT
3443 PackFile_Constant_pack_size(PARROT_INTERP
, ARGIN(const PackFile_Constant
*self
))
3449 switch (self
->type
) {
3452 packed_size
= PF_size_number();
3456 packed_size
= PF_size_string(self
->u
.string
);
3462 for (component
= self
->u
.key
; component
;
3463 component
= (PMC
*)PMC_data(component
))
3468 component
= self
->u
.key
; /* the pmc (Sub, ...) */
3471 * TODO create either
3472 * a) a frozen_size freeze entry or
3473 * b) change packout.c so that component size isn't needed
3475 image
= Parrot_freeze(interp
, component
);
3476 packed_size
= PF_size_string(image
);
3481 "Constant_packed_size: Unrecognized type '%c'!\n",
3486 /* Tack on space for the initial type field */
3487 return packed_size
+ 1;
3492 =item C<const opcode_t * PackFile_Constant_unpack>
3494 Unpack a PackFile Constant from a block of memory. The format is:
3499 Returns cursor if everything is OK, else zero (0).
3506 PARROT_WARN_UNUSED_RESULT
3507 PARROT_CAN_RETURN_NULL
3509 PackFile_Constant_unpack(PARROT_INTERP
, ARGIN(PackFile_ConstTable
*constt
),
3510 ARGOUT(PackFile_Constant
*self
), ARGIN(const opcode_t
*cursor
))
3512 PackFile
* const pf
= constt
->base
.pf
;
3513 const opcode_t type
= PF_fetch_opcode(pf
, &cursor
);
3515 /* #define TRACE_PACKFILE 1 */
3517 PIO_eprintf(NULL
, "PackFile_Constant_unpack(): Type is %ld ('%c')...\n",
3523 self
->u
.number
= PF_fetch_number(pf
, &cursor
);
3524 self
->type
= PFC_NUMBER
;
3528 self
->u
.string
= PF_fetch_string(interp
, pf
, &cursor
);
3529 self
->type
= PFC_STRING
;
3533 cursor
= PackFile_Constant_unpack_key(interp
, constt
,
3538 cursor
= PackFile_Constant_unpack_pmc(interp
, constt
,
3543 "Constant_unpack: Unrecognized type '%c' during unpack!\n",
3552 =item C<const opcode_t * PackFile_Constant_unpack_pmc>
3554 Unpack a constant PMC.
3561 PARROT_WARN_UNUSED_RESULT
3562 PARROT_CANNOT_RETURN_NULL
3564 PackFile_Constant_unpack_pmc(PARROT_INTERP
, ARGIN(PackFile_ConstTable
*constt
),
3565 ARGMOD(PackFile_Constant
*self
), ARGIN(const opcode_t
*cursor
))
3567 PackFile
* const pf
= constt
->base
.pf
;
3568 STRING
*image
, *_sub
;
3572 * thawing the PMC needs the real packfile in place
3574 PackFile_ByteCode
* const cs_save
= interp
->code
;
3575 interp
->code
= pf
->cur_cs
;
3577 image
= PF_fetch_string(interp
, pf
, &cursor
);
3579 * TODO use thaw_constants
3580 * current issue: a constant Sub with attached properties
3581 * doesn't DOD mark the properties
3582 * for a constant PMC *all* contents have to be in the constant pools
3584 pmc
= Parrot_thaw(interp
, image
);
3586 /* place item in const_table */
3587 self
->type
= PFC_PMC
;
3590 _sub
= CONST_STRING(interp
, "Sub"); /* CONST_STRING */
3591 if (VTABLE_isa(interp
, pmc
, _sub
)) {
3593 * finally place the sub into some namespace stash
3594 * XXX place this code in Sub.thaw ?
3596 Parrot_store_sub_in_namespace(interp
, pmc
);
3601 interp
->code
= cs_save
;
3607 =item C<const opcode_t * PackFile_Constant_unpack_key>
3609 Unpack a PackFile Constant from a block of memory. The format consists
3610 of a sequence of key atoms, each with the following format:
3615 Returns cursor if everything is OK, else zero (0).
3622 PARROT_WARN_UNUSED_RESULT
3623 PARROT_CAN_RETURN_NULL
3625 PackFile_Constant_unpack_key(PARROT_INTERP
, ARGIN(PackFile_ConstTable
*constt
),
3626 ARGMOD(PackFile_Constant
*self
), ARGIN(const opcode_t
*cursor
))
3628 PackFile
* const pf
= constt
->base
.pf
;
3629 int pmc_enum
= enum_class_Key
;
3631 INTVAL components
= (INTVAL
)PF_fetch_opcode(pf
, &cursor
);
3635 while (components
-- > 0) {
3636 opcode_t type
= PF_fetch_opcode(pf
, &cursor
);
3637 const opcode_t slice_bits
= type
& PF_VT_SLICE_BITS
;
3640 type
&= ~PF_VT_SLICE_BITS
;
3641 if (!head
&& slice_bits
) {
3642 pmc_enum
= enum_class_Slice
;
3646 = constant_pmc_new_noinit(interp
, pmc_enum
);
3647 tail
= (PMC
*)PMC_data(tail
);
3650 head
= tail
= constant_pmc_new_noinit(interp
, pmc_enum
);
3653 VTABLE_init(interp
, tail
);
3655 op
= PF_fetch_opcode(pf
, &cursor
);
3658 key_set_integer(interp
, tail
, op
);
3661 key_set_number(interp
, tail
, constt
->constants
[op
]->u
.number
);
3664 key_set_string(interp
, tail
, constt
->constants
[op
]->u
.string
);
3667 key_set_register(interp
, tail
, op
, KEY_integer_FLAG
);
3670 key_set_register(interp
, tail
, op
, KEY_number_FLAG
);
3673 key_set_register(interp
, tail
, op
, KEY_string_FLAG
);
3676 key_set_register(interp
, tail
, op
, KEY_pmc_FLAG
);
3682 if (slice_bits
& PF_VT_START_SLICE
)
3683 PObj_get_FLAGS(tail
) |= KEY_start_slice_FLAG
;
3684 if (slice_bits
& PF_VT_END_SLICE
)
3685 PObj_get_FLAGS(tail
) |= KEY_end_slice_FLAG
;
3686 if (slice_bits
& (PF_VT_START_ZERO
| PF_VT_END_INF
))
3687 PObj_get_FLAGS(tail
) |= KEY_inf_slice_FLAG
;
3691 self
->type
= PFC_KEY
;
3699 =item C<static PackFile * PackFile_append_pbc>
3701 Read a PBC and append it to the current directory
3702 Fixup sub addresses in newly loaded bytecode and run :load subs.
3708 PARROT_WARN_UNUSED_RESULT
3709 PARROT_CAN_RETURN_NULL
3711 PackFile_append_pbc(PARROT_INTERP
, ARGIN_NULLOK(const char *filename
))
3713 PackFile
* const pf
= Parrot_readbc(interp
, filename
);
3716 PackFile_add_segment(interp
, &interp
->initial_pf
->directory
,
3717 &pf
->directory
.base
);
3718 do_sub_pragmas(interp
, pf
->cur_cs
, PBC_LOADED
, NULL
);
3724 =item C<void Parrot_load_bytecode>
3726 Load and append a bytecode, IMC or PASM file into interpreter.
3728 Load some bytecode (PASM, PIR, PBC ...) and append it to the current
3736 * intermediate hook during changes
3741 Parrot_load_bytecode(PARROT_INTERP
, ARGIN(STRING
*file_str
))
3744 STRING
*wo_ext
, *ext
, *pbc
, *path
;
3745 enum_runtime_ft file_type
;
3746 PMC
*is_loaded_hash
;
3748 parrot_split_path_ext(interp
, file_str
, &wo_ext
, &ext
);
3749 /* check if wo_ext is loaded */
3750 is_loaded_hash
= VTABLE_get_pmc_keyed_int(interp
,
3751 interp
->iglobals
, IGLOBALS_PBC_LIBS
);
3752 if (VTABLE_exists_keyed_str(interp
, is_loaded_hash
, wo_ext
))
3754 pbc
= CONST_STRING(interp
, "pbc");
3755 if (string_equal(interp
, ext
, pbc
) == 0)
3756 file_type
= PARROT_RUNTIME_FT_PBC
;
3758 file_type
= PARROT_RUNTIME_FT_SOURCE
;
3760 path
= Parrot_locate_runtime_file_str(interp
, file_str
, file_type
);
3762 real_exception(interp
, NULL
, E_LibraryNotLoadedError
,
3763 "\"load_bytecode\" couldn't find file '%Ss'", file_str
);
3764 /* remember wo_ext => full_path mapping */
3765 VTABLE_set_string_keyed_str(interp
, is_loaded_hash
,
3767 filename
= string_to_cstring(interp
, path
);
3768 if (file_type
== PARROT_RUNTIME_FT_PBC
) {
3769 PackFile
*pf
= PackFile_append_pbc(interp
, filename
);
3770 string_cstring_free(filename
);
3773 real_exception(interp
, NULL
, 1,
3774 "Unable to append PBC to the current directory");
3778 PackFile_ByteCode
* const cs
=
3779 (PackFile_ByteCode
*)IMCC_compile_file_s(interp
,
3781 string_cstring_free(filename
);
3784 do_sub_pragmas(interp
, cs
, PBC_LOADED
, NULL
);
3786 real_exception(interp
, NULL
, E_LibraryNotLoadedError
,
3787 "compiler returned NULL ByteCode '%Ss' - %Ss", file_str
, err
);
3793 =item C<void PackFile_fixup_subs>
3795 Run :load or :immediate subroutines for the current code segment.
3796 If C<eval> is given, set this is the owner of the subroutines.
3804 PackFile_fixup_subs(PARROT_INTERP
, pbc_action_enum_t what
, ARGIN_NULLOK(PMC
*eval
))
3806 do_sub_pragmas(interp
, interp
->code
, what
, eval
);
3815 Rework by Melvin; new bytecode format, make bytecode portable. (Do
3816 endian conversion and wordsize transforms on the fly.)
3818 leo applied and modified Juergen Boemmels packfile patch giving an
3819 extensible packfile format with directory reworked again, with common
3820 chunks (C<default_*>).
3822 2003.11.21 leo: moved low level item fetch routines to new
3832 * c-file-style: "parrot"
3834 * vim: expandtab shiftwidth=4: