2 Copyright (C) 2001-2009, Parrot Foundation.
7 src/exec.c - Generate an object file
19 #include <parrot/parrot.h>
20 #ifdef HAVE_COMPUTED_GOTO
21 # include <parrot/oplib/core_ops_cgp.h>
22 #endif /* HAVE_COMPUTED_GOTO */
23 #include "parrot/exec.h"
28 #include "exec_save.h"
29 #include "parrot/compiler.h"
31 /* HEADERIZER HFILE: include/parrot/exec.h */
33 /* HEADERIZER BEGIN: static */
34 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
36 static void add_data_member(
37 ARGMOD(Parrot_exec_objfile_t
*obj
),
38 ARGIN_NULLOK(const void *src
),
40 __attribute__nonnull__(1)
43 static void exec_init(ARGIN(Parrot_exec_objfile_t
*obj
))
44 __attribute__nonnull__(1);
46 static int symbol_list_find(
47 ARGIN(const Parrot_exec_objfile_t
*obj
),
48 ARGIN(const char *symbol
))
49 __attribute__nonnull__(1)
50 __attribute__nonnull__(2);
52 #define ASSERT_ARGS_add_data_member __attribute__unused__ int _ASSERT_ARGS_CHECK = \
53 PARROT_ASSERT_ARG(obj)
54 #define ASSERT_ARGS_exec_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
55 PARROT_ASSERT_ARG(obj)
56 #define ASSERT_ARGS_symbol_list_find __attribute__unused__ int _ASSERT_ARGS_CHECK = \
57 PARROT_ASSERT_ARG(obj) \
58 || PARROT_ASSERT_ARG(symbol)
59 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
60 /* HEADERIZER END: static */
63 * Parrot_exec_run must be 0 while the program runs.
64 * It will be set to 2 inside eval (s. eval.pmc)
65 * to switch to runops_jit (s. interpreter.c:runops_exec()).
66 * Must be 1 while starting the compiled code to have Parrot_new()
67 * return the address of the global interpreter (s. interpreter.c)
68 * and PackFile_ConstTable_unpack use the global const_table (s. packfile.c).
69 * Must also be 1 while generating the executable.
72 int Parrot_exec_run
= 0;
76 =item C<void Parrot_exec(PARROT_INTERP, opcode_t *pc, opcode_t *code_start,
79 Call the jit to get the program code. Adds the members of the data
80 section. And emits the executable.
87 Parrot_exec(PARROT_INTERP
, ARGIN(opcode_t
*pc
),
88 ARGIN(opcode_t
*code_start
), ARGIN(opcode_t
*code_end
))
90 ASSERT_ARGS(Parrot_exec
)
96 Parrot_jit_info_t
*jit_info
;
98 Parrot_exec_objfile_t
* const obj
=
99 mem_allocate_zeroed_typed(Parrot_exec_objfile_t
);
101 obj
->bytecode_header_size
=
102 (interp
->code
->base
.file_offset
+ 4) * sizeof (opcode_t
);
103 jit_info
= parrot_build_asm(interp
, code_start
, code_end
,
106 /* TODO Go zero the calls to jited opcodes. */
107 /* Place the program code in the data section. */
109 add_data_member(obj
, interp
->code
->base
.pf
->src
,
110 interp
->code
->base
.pf
->size
);
112 add_data_member(obj
, jit_info
->arena
.op_map
, (jit_info
->arena
.map_size
+1) *
113 sizeof (opcode_t
*));
115 add_data_member(obj
, NULL
, interp
->code
->const_table
->const_count
*
116 sizeof (PackFile_Constant
));
120 j
= (int)((op_func_t
*)interp
->op_lib
->op_func_table
)[2] - j
;
121 k
= (int *)interp
->code
->prederef
.code
;
122 for (i
= 0; i
< (int)interp
->code
->base
.size
; i
++) {
126 add_data_member(obj
, interp
->code
->prederef
.code
,
127 interp
->code
->base
.size
* sizeof (void *));
129 /* bytecode_offset */
130 bhs
= obj
->bytecode_header_size
/ sizeof (opcode_t
);
131 add_data_member(obj
, &bhs
, 4);
133 obj
->text
.code
= jit_info
->arena
.start
;
134 obj
->text
.size
= jit_info
->arena
.size
;
137 obj
->text
.size
+= (4 - obj
->text
.size
% 4);
138 obj
->data
.size
+= (4 - obj
->data
.size
% 4);
140 output
= interp
->output_file
?
141 interp
->output_file
: "exec_output.o";
142 Parrot_exec_save(interp
, obj
, output
);
147 =item C<static void add_data_member(Parrot_exec_objfile_t *obj, const void *src,
150 Adds a member to the data section, storing the size of it at
151 C<< obj->data_size[N] >>.
158 add_data_member(ARGMOD(Parrot_exec_objfile_t
*obj
),
159 ARGIN_NULLOK(const void *src
), size_t len
)
161 ASSERT_ARGS(add_data_member
)
164 if (obj
->data
.size
== 0) {
165 obj
->data
.code
= (char *)mem_sys_allocate(len
);
166 obj
->data_size
= (int *)mem_sys_allocate(sizeof (int));
170 obj
->data
.code
= (char *)mem_sys_realloc(obj
->data
.code
,
171 obj
->data
.size
+ len
);
172 nds
= (int *)mem_sys_realloc(obj
->data_size
, (obj
->data_count
+ 2) *
174 obj
->data_size
= nds
;
177 cp
= obj
->data
.code
+ obj
->data
.size
;
179 memcpy(cp
, src
, len
);
182 obj
->data_size
[obj
->data_count
++] = len
;
183 obj
->data
.size
+= len
;
188 =item C<static void exec_init(Parrot_exec_objfile_t *obj)>
190 Initialize the obj structure.
197 exec_init(ARGIN(Parrot_exec_objfile_t
*obj
))
199 ASSERT_ARGS(exec_init
)
200 obj
->text_rellocation_table
= (Parrot_exec_rellocation_t
*)
201 mem_sys_allocate_zeroed(sizeof (Parrot_exec_rellocation_t
));
202 obj
->data_rellocation_table
= (Parrot_exec_rellocation_t
*)
203 mem_sys_allocate_zeroed(sizeof (Parrot_exec_rellocation_t
));
204 obj
->symbol_table
= (Parrot_exec_symbol_t
*)
205 mem_sys_allocate_zeroed(sizeof (Parrot_exec_symbol_t
));
208 obj
->symbol_list_size
= 4;
210 obj
->symbol_list_size
= 0;
213 obj
->symbol_list_size
= 0;
215 Parrot_exec_add_symbol(obj
, "program_code", STYPE_GDATA
);
216 Parrot_exec_add_symbol(obj
, "opcode_map", STYPE_GDATA
);
217 Parrot_exec_add_symbol(obj
, "const_table", STYPE_GDATA
);
219 Parrot_exec_add_symbol(obj
, "exec_prederef_code", STYPE_GDATA
);
221 Parrot_exec_add_symbol(obj
, "bytecode_offset", STYPE_GDATA
);
222 Parrot_exec_add_symbol(obj
, "run_compiled", STYPE_FUNC
);
227 =item C<int Parrot_exec_add_symbol(Parrot_exec_objfile_t *obj, const char
230 Adds a symbol to the object file.
237 Parrot_exec_add_symbol(ARGMOD(Parrot_exec_objfile_t
*obj
),
238 ARGIN(const char *symbol
), int stype
)
240 ASSERT_ARGS(Parrot_exec_add_symbol
)
242 int symbol_number
= symbol_list_find(obj
, symbol
);
243 if (symbol_number
== -1) {
244 Parrot_exec_symbol_t
*new_symbol
;
246 symbol_number
= obj
->symbol_count
;
247 new_symbol
= (Parrot_exec_symbol_t
*)mem_sys_realloc(obj
->symbol_table
,
248 (size_t)(obj
->symbol_count
+ 1) * sizeof (Parrot_exec_symbol_t
));
249 obj
->symbol_table
= new_symbol
;
251 new_symbol
= &obj
->symbol_table
[obj
->symbol_count
++];
252 new_symbol
->offset_list
= obj
->symbol_list_size
;
253 new_symbol
->symbol
= symbol
;
254 obj
->symbol_list_size
+= strlen(symbol
);
255 #if defined(EXEC_A_OUT) || defined(EXEC_COFF)
256 /* for the trailing "_" */
257 obj
->symbol_list_size
++;
259 if (stype
!= STYPE_GCC
)
260 obj
->symbol_list_size
++;
261 if (stype
== STYPE_COM
) {
262 new_symbol
->type
= STYPE_COM
;
263 new_symbol
->value
= sizeof (Interp
);
266 new_symbol
->type
= stype
;
267 new_symbol
->value
= 0;
270 return symbol_number
;
275 =item C<int * Parrot_exec_add_text_rellocation_reg(Parrot_exec_objfile_t *obj,
276 char *nptr, const char *var, int offset, int disp)>
278 Adds a register's text rellocation to the object file. Wrapper
279 around C<Parrot_exec_add_text_rellocation>.
281 Returns pointer to offset.
288 PARROT_CAN_RETURN_NULL
290 Parrot_exec_add_text_rellocation_reg(ARGIN(Parrot_exec_objfile_t
*obj
),
291 ARGIN(char *nptr
), ARGIN(const char *var
), int offset
, int disp
)
293 ASSERT_ARGS(Parrot_exec_add_text_rellocation_reg
)
294 Parrot_exec_add_text_rellocation(obj
, nptr
, RTYPE_COM
, var
, disp
);
295 return (int *)offset
;
300 =item C<void Parrot_exec_add_text_rellocation_func(Parrot_exec_objfile_t *obj,
301 char *nptr, const char *func_name)>
303 Adds a function's text rellocation to the object file. Wrapper
304 around C<Parrot_exec_add_text_rellocation>.
312 Parrot_exec_add_text_rellocation_func(ARGIN(Parrot_exec_objfile_t
*obj
),
313 ARGIN(char *nptr
), ARGIN(const char *func_name
))
315 ASSERT_ARGS(Parrot_exec_add_text_rellocation_func
)
316 Parrot_exec_add_text_rellocation(obj
, nptr
, RTYPE_FUNC
, func_name
, 1);
321 =item C<void Parrot_exec_add_text_rellocation(Parrot_exec_objfile_t *obj, char
322 *nptr, int type, const char *symbol, int disp)>
324 Adds a text rellocation to the object file.
332 Parrot_exec_add_text_rellocation(ARGIN(Parrot_exec_objfile_t
*obj
), ARGIN(char *nptr
),
333 int type
, ARGIN(const char *symbol
), int disp
)
335 ASSERT_ARGS(Parrot_exec_add_text_rellocation
)
338 Parrot_exec_rellocation_t
* new_relloc
= (Parrot_exec_rellocation_t
*)
339 mem_sys_realloc(obj
->text_rellocation_table
,
340 (size_t)(obj
->text_rellocation_count
+ 1) *
341 sizeof (Parrot_exec_rellocation_t
));
343 obj
->text_rellocation_table
= new_relloc
;
344 new_relloc
= &obj
->text_rellocation_table
[obj
->text_rellocation_count
++];
348 symbol_number
= Parrot_exec_add_symbol(obj
, symbol
, STYPE_UND
);
351 symbol_number
= Parrot_exec_add_symbol(obj
, symbol
, STYPE_COM
);
355 symbol_number
= Parrot_exec_add_symbol(obj
, symbol
, STYPE_GDATA
);
363 new_relloc
->offset
= (int)(addr
- obj
->text
.code
);
364 new_relloc
->symbol_number
= symbol_number
;
365 new_relloc
->type
= type
;
370 =item C<static int symbol_list_find(const Parrot_exec_objfile_t *obj, const char
373 Returns the index of C<symbol> in the symbol list. Returns -1 if it is
376 Used by C<Parrot_exec_add_symbol()>.
383 symbol_list_find(ARGIN(const Parrot_exec_objfile_t
*obj
), ARGIN(const char *symbol
))
385 ASSERT_ARGS(symbol_list_find
)
388 for (i
= 0; i
< obj
->symbol_count
; i
++)
389 if (STREQ(symbol
, obj
->symbol_table
[i
].symbol
))
400 F<include/parrot/exec.h>, F<src/exec_cpu.c>, F<src/exec_save.h>
401 and F<src/exec_start.c>.
405 Initial version by Daniel Grunblatt on 2003.6.9.
414 * c-file-style: "parrot"
416 * vim: expandtab shiftwidth=4: