/
jit.h
340 lines (290 loc) · 11.2 KB
/
jit.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
/*
* Copyright (C) 2001-2007, Parrot Foundation.
*/
/*
* jit.h
*
* $Id$
*/
#ifndef PARROT_JIT_H_GUARD
#define PARROT_JIT_H_GUARD
#if EXEC_CAPABLE
# include "parrot/exec.h"
#endif
typedef void (*jit_f)(PARROT_INTERP, opcode_t *pc);
void Parrot_destroy_jit(void *);
/* Parrot_jit_fixup_t
* Platform generic fixup information
*
* type: The type of fixup.
* native_offset: Where to apply the fixup.
* skip: Skip instructions after the target.
* param: Fixup specific data.
*/
typedef struct Parrot_jit_fixup *Parrot_jit_fixup_ptr;
typedef struct Parrot_jit_fixup {
int type;
ptrdiff_t native_offset;
char skip;
char dummy[3]; /* For alignment ??? XXX */
union { /* What has to align with what? */
opcode_t opcode;
void (*fptr)(void);
} param;
Parrot_jit_fixup_ptr next;
} Parrot_jit_fixup_t;
/* Parrot_jit_opmap_t
* Hold native code offsets/addresses
*
* ptr: Pointer to native code
* offset: Offset of native code from arena.start
*/
typedef union {
void *ptr;
ptrdiff_t offset;
} Parrot_jit_opmap_t;
enum {
JIT_BRANCH_NO, /* The opcode doesn't branch */
JIT_BRANCH_TARGET, /* The opcode is a branch target */
JIT_BRANCH_SOURCE /* The opcode is a branch source */
};
/* Parrot_jit_arena_t
* Holds pointers to the native code of one or more sections.
*
* start: Start of current native code segment.
* size: The size of the arena in bytes
* op_map: Maps opcode offsets to native code.
* map_size: The size of the map in bytes.
* fixups: List of fixups.
*/
typedef struct Parrot_jit_arena_t {
char *start;
ptrdiff_t size;
Parrot_jit_opmap_t *op_map;
unsigned long map_size;
Parrot_jit_fixup_t *fixups;
} Parrot_jit_arena_t;
/* Parrot_jit_optimizer_section_t
* The bytecode will be divided in sections depending on the
* program structure.
*
* begin: Points where sections begins in the bytecode.
* end: Points where sections ends in the bytecode.
* arena: The first arena for this section, or NULL if the
* section is in the arena inlined in jit_info.
* ru[4]: register_usage_t per [IPSN]
* maps: Total maps done.
* jit_op_count: How many opcodes are jitted.
* op_count: Opcodes in this section.
* load_size: The size of the register load instructions to be
* skipped in an in-section branch.
* isjit: If this section is a jitted one or not.
* block: block number of section
* branch_target: The section where execution continues if this section
* ends at a branch source the targeted section is used.
*/
typedef struct Parrot_jit_optimizer_section *Parrot_jit_optimizer_section_ptr;
/* reg_count: An array with one position for each register
* holding the number of times each register is used in the
* section.
* reg_usage: An array with the registers sorted by the usage.
* reg_dir: If the register needs to be loaded or saved.
* registers_used: count of used registers
*/
typedef struct Parrot_jit_register_usage_t {
int reg_count[NUM_REGISTERS];
unsigned int reg_usage[NUM_REGISTERS];
char reg_dir[NUM_REGISTERS];
int registers_used;
} Parrot_jit_register_usage_t;
typedef struct Parrot_jit_optimizer_section {
opcode_t *begin;
opcode_t *end;
Parrot_jit_register_usage_t ru[4];
Parrot_jit_arena_t *arena;
unsigned int maps;
unsigned int jit_op_count;
unsigned int op_count;
ptrdiff_t load_size;
char isjit;
char done;
char ins_count;
char dummy; /* For alignment ??? XXX */
int block; /* What has to align with what? */
Parrot_jit_optimizer_section_ptr branch_target;
Parrot_jit_optimizer_section_ptr prev;
Parrot_jit_optimizer_section_ptr next;
} Parrot_jit_optimizer_section_t;
/* Parrot_jit_optimizer_section_t
* All the information related to optimizing the bytecode.
*
* sections: A pointer to the first section.
* cur_section: Pointer to the current section.
* map_branch: A pointer to an array with the size of the bytecode
* where the positions of the opcodes will have a value
* indicating if the opcode is a branch target, source
* or isn't related with a control flow opcode at all,
* and which register was allocated for each opcode
* argument if any.
* has_unpredictable_jump: XXX need to define how to handle this.
*/
typedef struct Parrot_jit_optimizer_t {
Parrot_jit_optimizer_section_t *sections;
Parrot_jit_optimizer_section_t *cur_section;
char *map_branch;
opcode_t **branch_list;
unsigned char has_unpredictable_jump;
unsigned char dummy[3]; /* For alignment ??? XXX */
} Parrot_jit_optimizer_t; /* What has to align with what? */
/* Parrot_jit_constant_pool_t
* Constants pool information.
*
*/
typedef struct Parrot_jit_constant_pool_t {
long frames_used;
long cur_used;
char *cur_const;
INTVAL *slot_ptr;
} Parrot_jit_constant_pool_t;
typedef enum {
JIT_CODE_FILE,
JIT_CODE_SUB,
JIT_CODE_SUB_REGS_ONLY,
/* size */
JIT_CODE_TYPES,
/* special cases */
JIT_CODE_RECURSIVE = 0x10,
JIT_CODE_SUB_REGS_ONLY_REC = JIT_CODE_SUB_REGS_ONLY|JIT_CODE_RECURSIVE
} enum_jit_code_type;
/* Parrot_jit_info_t
* All the information needed to jit the bytecode will be here.
*
* prev_op: The previous opcode in this section.
* cur_op: The current opcode during the build process.
* op_i: Opcode index.
* native_ptr: Current pointer to native code.
* arena: The arena inlined, this will be the only one used in cases
* where there is a way to load an immediate.
* optimizer: Optimizer information.
* constant_pool: The constant pool information.
*/
typedef struct Parrot_jit_info_t {
opcode_t *prev_op;
opcode_t *cur_op;
opcode_t op_i;
char *native_ptr;
Parrot_jit_arena_t arena;
Parrot_jit_optimizer_t *optimizer;
Parrot_jit_constant_pool_t *constant_pool;
INTVAL code_type;
int flags;
const struct jit_arch_info_t *arch_info;
int n_args;
#if EXEC_CAPABLE
Parrot_exec_objfile_t *objfile;
#else
void *objfile;
#endif /* EXEC_CAPABLE */
} Parrot_jit_info_t;
#define Parrot_jit_fixup_target(jit_info, fixup) \
((jit_info)->arena.start + (fixup)->native_offset)
typedef void (*jit_fn_t)(Parrot_jit_info_t *jit_info,
PARROT_INTERP);
/* Parrot_jit_fn_info_t
* The table of opcodes.
*
* jit_fn_t: A pointer to the function that emits code for the opcode
* or to the C funtion if the opcode is not jitted.
* extcall: If the opcode makes an external call to a C funtion.
* also used for vtable functions, extcall is #of vtable func
*/
typedef struct Parrot_jit_fn_info_t {
jit_fn_t fn;
int extcall;
} Parrot_jit_fn_info_t;
PARROT_DATA Parrot_jit_fn_info_t *op_jit;
extern Parrot_jit_fn_info_t op_exec[];
PARROT_EXPORT void Parrot_jit_newfixup(Parrot_jit_info_t *jit_info);
void Parrot_jit_cpcf_op(Parrot_jit_info_t *jit_info,
PARROT_INTERP);
void Parrot_jit_normal_op(Parrot_jit_info_t *jit_info,
PARROT_INTERP);
void Parrot_jit_restart_op(Parrot_jit_info_t *jit_info,
PARROT_INTERP);
void Parrot_exec_cpcf_op(Parrot_jit_info_t *jit_info,
PARROT_INTERP);
void Parrot_exec_normal_op(Parrot_jit_info_t *jit_info,
PARROT_INTERP);
void Parrot_exec_restart_op(Parrot_jit_info_t *jit_info,
PARROT_INTERP);
/*
* interface functions for the register save/restore code
* with offsets relative to the base register (obtained by
* Parrot_jit_emit_get_base_reg_no)
*/
void Parrot_jit_emit_mov_mr_n_offs(
Interp *, int base_reg, size_t offs, int src_reg);
void Parrot_jit_emit_mov_mr_offs(
Interp *, int base_reg, size_t offs, int src_reg);
void Parrot_jit_emit_mov_rm_n_offs(
Interp *, int dst_reg, int base_reg, size_t offs);
void Parrot_jit_emit_mov_rm_offs(
Interp *, int dst_reg, int base_reg, size_t offs);
/*
* interface to architecture specific details
*/
typedef void (*jit_arch_f)(Parrot_jit_info_t *, Interp *);
typedef struct jit_arch_regs {
/*
* begin function - emit ABI call prologue
*/
jit_arch_f jit_begin;
int n_mapped_I;
int n_preserved_I;
const char *map_I;
int n_mapped_F;
int n_preserved_F;
const char *map_F;
} jit_arch_regs;
typedef void (*mov_RM_f)(PARROT_INTERP, Parrot_jit_info_t *,
int cpu_reg, int base_reg, INTVAL offs);
typedef void (*mov_MR_f)(PARROT_INTERP, Parrot_jit_info_t *,
int base_reg, INTVAL offs, int cpu_reg);
typedef struct jit_arch_info_t {
/* CPU <- Parrot reg move functions */
mov_RM_f mov_RM_i;
mov_RM_f mov_RM_n;
/* Parrot <- CPU reg move functions */
mov_MR_f mov_MR_i;
mov_MR_f mov_MR_n;
/* fixup branches and calls after codegen */
jit_arch_f jit_dofixup;
/* flush caches */
jit_arch_f jit_flush_cache;
/* register mapping info */
const jit_arch_regs regs[JIT_CODE_TYPES];
} jit_arch_info;
/*
* interface to create JIT code
*/
Parrot_jit_info_t *
parrot_build_asm(PARROT_INTERP,
opcode_t *code_start, opcode_t *code_end,
void *objfile, INTVAL);
/*
* NCI interface
*/
void *Parrot_jit_build_call_func(Interp *, PMC *, STRING *, int *);
/* custom pmc callback functions */
void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv);
PMC* Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv);
struct jit_buffer_private_data {
int size;
};
#endif /* PARROT_JIT_H_GUARD */
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/