[TT #871] Add rand as a dynop, with tests
[parrot.git] / src / exec.c
blobef54d21cb73bf4f6009dc825aa1a15970250ebef
1 /*
2 Copyright (C) 2001-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/exec.c - Generate an object file
9 =head1 DESCRIPTION
11 =head2 Functions
13 =over 4
15 =cut
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"
24 #include "jit.h"
25 #define JIT_EMIT 1
26 #include "jit_emit.h"
27 #include "exec_dep.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),
39 size_t len)
40 __attribute__nonnull__(1)
41 FUNC_MODIFIES(*obj);
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,
77 opcode_t *code_end)>
79 Call the jit to get the program code. Adds the members of the data
80 section. And emits the executable.
82 =cut
86 void
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)
91 #ifdef JIT_CGP
92 int i, j *k;
93 #endif
94 const char *output;
95 long bhs;
96 Parrot_jit_info_t *jit_info;
98 Parrot_exec_objfile_t * const obj =
99 mem_allocate_zeroed_typed(Parrot_exec_objfile_t);
100 exec_init(obj);
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,
104 obj, JIT_CODE_FILE);
106 /* TODO Go zero the calls to jited opcodes. */
107 /* Place the program code in the data section. */
108 /* program_code */
109 add_data_member(obj, interp->code->base.pf->src,
110 interp->code->base.pf->size);
111 /* opcode_map */
112 add_data_member(obj, jit_info->arena.op_map, (jit_info->arena.map_size+1) *
113 sizeof (opcode_t *));
114 /* const_table */
115 add_data_member(obj, NULL, interp->code->const_table->const_count *
116 sizeof (PackFile_Constant));
117 #ifdef JIT_CGP
118 /* prederef_code */
119 j = (int)cgp_core;
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++) {
123 if (k[i] != j)
124 k[i] = 0;
126 add_data_member(obj, interp->code->prederef.code,
127 interp->code->base.size * sizeof (void *));
128 #endif /* JIT_CGP */
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;
136 /* PAD */
137 obj->text.size += (4 - obj->text.size % 4);
138 obj->data.size += (4 - obj->data.size % 4);
139 offset_fixup(obj);
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,
148 size_t len)>
150 Adds a member to the data section, storing the size of it at
151 C<< obj->data_size[N] >>.
153 =cut
157 static void
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)
162 char *cp;
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));
168 else {
169 int *nds;
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) *
173 sizeof (int));
174 obj->data_size = nds;
177 cp = obj->data.code + obj->data.size;
178 if (src)
179 memcpy(cp, src, len);
180 else
181 memset(cp, 0, 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.
192 =cut
196 static void
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));
206 /* size of table */
207 #ifdef PARROT_I386
208 obj->symbol_list_size = 4;
209 #else
210 obj->symbol_list_size = 0;
211 #endif
212 #ifdef EXEC_ELF
213 obj->symbol_list_size = 0;
214 #endif
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);
218 #ifdef JIT_CGP
219 Parrot_exec_add_symbol(obj, "exec_prederef_code", STYPE_GDATA);
220 #endif /* JIT_CGP */
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
228 *symbol, int stype)>
230 Adds a symbol to the object file.
232 =cut
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++;
258 #endif
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);
265 else {
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.
283 =cut
287 PARROT_EXPORT
288 PARROT_CAN_RETURN_NULL
289 int *
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>.
306 =cut
310 PARROT_EXPORT
311 void
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.
326 =cut
330 PARROT_EXPORT
331 void
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)
336 int symbol_number;
337 char *addr;
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++];
346 switch (type) {
347 case RTYPE_FUNC:
348 symbol_number = Parrot_exec_add_symbol(obj, symbol, STYPE_UND);
349 break;
350 case RTYPE_COM:
351 symbol_number = Parrot_exec_add_symbol(obj, symbol, STYPE_COM);
352 break;
353 case RTYPE_DATA:
354 case RTYPE_DATA1:
355 symbol_number = Parrot_exec_add_symbol(obj, symbol, STYPE_GDATA);
356 break;
357 default:
358 symbol_number = 0;
359 break;
362 addr = nptr + disp;
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
371 *symbol)>
373 Returns the index of C<symbol> in the symbol list. Returns -1 if it is
374 not in the list.
376 Used by C<Parrot_exec_add_symbol()>.
378 =cut
382 static int
383 symbol_list_find(ARGIN(const Parrot_exec_objfile_t *obj), ARGIN(const char *symbol))
385 ASSERT_ARGS(symbol_list_find)
386 int i;
388 for (i = 0; i < obj->symbol_count; i++)
389 if (STREQ(symbol, obj->symbol_table[i].symbol))
390 return i;
391 return -1;
396 =back
398 =head1 SEE ALSO
400 F<include/parrot/exec.h>, F<src/exec_cpu.c>, F<src/exec_save.h>
401 and F<src/exec_start.c>.
403 =head1 HISTORY
405 Initial version by Daniel Grunblatt on 2003.6.9.
407 =cut
413 * Local variables:
414 * c-file-style: "parrot"
415 * End:
416 * vim: expandtab shiftwidth=4: