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
/*
* jit-rules.h - Rules that define the characteristics of the back-end.
*
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
*
* This file is part of the libjit library.
*
* The libjit library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
* The libjit library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the libjit library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef _JIT_RULES_H
#define _JIT_RULES_H
#include "jit-config.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Information about a register.
*/
typedef struct
{
const char *name; /* Name of the register, for debugging */
short cpu_reg; /* CPU register number */
short other_reg; /* Other register for a "long" pair, or -1 */
int flags; /* Flags that define the register type */
} jit_reginfo_t;
/*
* Register information flags.
*/
#define JIT_REG_WORD (1 << 0) /* Can be used for word values */
#define JIT_REG_LONG (1 << 1) /* Can be used for long values */
#define JIT_REG_FLOAT32 (1 << 2) /* Can be used for float32 values */
#define JIT_REG_FLOAT64 (1 << 3) /* Can be used for float64 values */
#define JIT_REG_NFLOAT (1 << 4) /* Can be used for nfloat values */
#define JIT_REG_FRAME (1 << 5) /* Contains frame pointer */
#define JIT_REG_STACK_PTR (1 << 6) /* Contains CPU stack pointer */
#define JIT_REG_FIXED (1 << 7) /* Fixed use; not for allocation */
#define JIT_REG_CALL_USED (1 << 8) /* Destroyed by a call */
#define JIT_REG_IN_STACK (1 << 9) /* Middle of stack-like allocation */
#define JIT_REG_GLOBAL (1 << 10) /* Candidate for global allocation */
#define JIT_REG_ALL (JIT_REG_WORD | JIT_REG_LONG \
| JIT_REG_FLOAT32 | JIT_REG_FLOAT64 \
| JIT_REG_NFLOAT)
/*
* Include definitions that are specific to the backend.
*/
#if defined(JIT_BACKEND_INTERP)
# include "jit-rules-interp.h"
#elif defined(JIT_BACKEND_ALPHA)
# include "jit-rules-alpha.h"
#elif defined(JIT_BACKEND_ARM)
# include "jit-rules-arm.h"
#elif defined(JIT_BACKEND_X86)
# include "jit-rules-x86.h"
#elif defined(JIT_BACKEND_X86_64)
# include "jit-rules-x86-64.h"
#else
# error "unknown jit backend type"
#endif
/*
* The information blocks for all registers in the system.
*/
extern jit_reginfo_t const _jit_reg_info[JIT_NUM_REGS];
/*
* Macros for getting register information
*/
/* Get register name. */
#define jit_reg_name(reg) (_jit_reg_info[reg].name)
/* Get register flags. */
#define jit_reg_flags(reg) (_jit_reg_info[reg].flags)
/* Get CPU register number for machine instruction encoding. */
#define jit_reg_code(reg) (_jit_reg_info[reg].cpu_reg)
/* Given the first register of a register pair get the other one. */
#define jit_reg_other_reg(reg) (_jit_reg_info[reg].other_reg)
/* Given a register find if a value of the specified type requires
* a register pair. Return the other register of the pair if it is
* required and return -1 otherwise. */
#if defined(JIT_NATIVE_INT32) && !defined(JIT_BACKEND_INTERP)
# define jit_reg_get_pair(type,reg) _jit_reg_get_pair(type, reg)
#else
# define jit_reg_get_pair(type,reg) (-1)
#endif
/*
* Manipulate register usage masks. The backend may override these
* definitions if it has more registers than can fit in a "jit_uint".
*/
#if !defined(jit_regused_init)
typedef jit_uint jit_regused_t;
#define jit_regused_init (0)
#define jit_regused_init_used (~0)
#define jit_reg_is_used(mask,reg) (((mask) & (((jit_uint)1) << (reg))) != 0)
#define jit_reg_set_used(mask,reg) ((mask) |= (((jit_uint)1) << (reg)))
#define jit_reg_clear_used(mask,reg) ((mask) &= ~(((jit_uint)1) << (reg)))
#endif /* !defined(jit_regused_init) */
/*
* Information about a register's contents.
*/
#define JIT_MAX_REG_VALUES 8
typedef struct jit_regcontents jit_regcontents_t;
struct jit_regcontents
{
/* List of values that are currently stored in this register */
jit_value_t values[JIT_MAX_REG_VALUES];
int num_values;
/* Current age of this register. Older registers are reclaimed first */
int age;
/* Flag that indicates if this register is holding the first
word of a double-word long value (32-bit platforms only) */
char is_long_start;
/* Flag that indicates if this register is holding the second
word of a double-word long value (32-bit platforms only) */
char is_long_end;
/* Flag that indicates if the register holds a valid value,
but there are no actual "jit_value_t" objects associated */
char used_for_temp;
};
/*
* Code generation information.
*/
typedef struct jit_gencode *jit_gencode_t;
struct jit_gencode
{
jit_context_t context; /* Context this position is attached to */
unsigned char *ptr; /* Current code pointer */
unsigned char *mem_start; /* Available space start */
unsigned char *mem_limit; /* Available space limit */
unsigned char *code_start; /* Real code start */
unsigned char *code_end; /* Real code end */
jit_regused_t permanent; /* Permanently allocated global regs */
jit_regused_t touched; /* All registers that were touched */
jit_regused_t inhibit; /* Temporarily inhibited registers */
jit_regcontents_t contents[JIT_NUM_REGS]; /* Contents of each register */
int current_age; /* Current age value for registers */
#ifdef JIT_REG_STACK
int reg_stack_top; /* Current register stack top */
#endif
#ifdef jit_extra_gen_state
jit_extra_gen_state; /* CPU-specific extra information */
#endif
void *epilog_fixup; /* Fixup list for function epilogs */
int stack_changed; /* Stack top changed since entry */
jit_varint_encoder_t offset_encoder; /* Bytecode offset encoder */
};
/*
* ELF machine type and ABI information.
*/
typedef struct jit_elf_info jit_elf_info_t;
struct jit_elf_info
{
int machine;
int abi;
int abi_version;
};
/*
* External function defintions.
*/
/*
* Determine if there is sufficient space in the code cache.
* If not throws JIT_RESULT_CACHE_FULL exception.
*/
void _jit_gen_check_space(jit_gencode_t gen, int space);
/*
* Allocate a memory chunk for data.
*/
void *_jit_gen_alloc(jit_gencode_t gen, unsigned long size);
void _jit_init_backend(void);
void _jit_gen_get_elf_info(jit_elf_info_t *info);
int _jit_create_entry_insns(jit_function_t func);
int _jit_create_call_setup_insns
(jit_function_t func, jit_type_t signature,
jit_value_t *args, unsigned int num_args,
int is_nested, int nesting_level, jit_value_t *struct_return, int flags);
int _jit_setup_indirect_pointer(jit_function_t func, jit_value_t value);
int _jit_create_call_return_insns
(jit_function_t func, jit_type_t signature,
jit_value_t *args, unsigned int num_args,
jit_value_t return_value, int is_nested);
int _jit_opcode_is_supported(int opcode);
void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf);
void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func);
void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func);
void _jit_gen_spill_reg(jit_gencode_t gen, int reg,
int other_reg, jit_value_t value);
void _jit_gen_free_reg(jit_gencode_t gen, int reg,
int other_reg, int value_used);
void _jit_gen_load_value
(jit_gencode_t gen, int reg, int other_reg, jit_value_t value);
void _jit_gen_spill_global(jit_gencode_t gen, int reg, jit_value_t value);
void _jit_gen_load_global(jit_gencode_t gen, int reg, jit_value_t value);
void _jit_gen_exch_top(jit_gencode_t gen, int reg);
void _jit_gen_move_top(jit_gencode_t gen, int reg);
void _jit_gen_spill_top(jit_gencode_t gen, int reg, jit_value_t value, int pop);
void _jit_gen_fix_value(jit_value_t value);
void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
jit_block_t block, jit_insn_t insn);
void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block);
void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block);
int _jit_gen_is_global_candidate(jit_type_t type);
#if defined(JIT_NATIVE_INT32) && !defined(JIT_BACKEND_INTERP)
int _jit_reg_get_pair(jit_type_t type, int reg);
#endif
/*
* Determine the byte number within a "jit_int" where the low
* order byte can be found.
*/
int _jit_int_lowest_byte(void);
/*
* Determine the byte number within a "jit_int" where the low
* order short can be found.
*/
int _jit_int_lowest_short(void);
/*
* Determine the byte number within a "jit_nint" where the low
* order byte can be found.
*/
int _jit_nint_lowest_byte(void);
/*
* Determine the byte number within a "jit_nint" where the low
* order short can be found.
*/
int _jit_nint_lowest_short(void);
/*
* Determine the byte number within a "jit_nint" where the low
* order int can be found.
*/
int _jit_nint_lowest_int(void);
#ifdef __cplusplus
};
#endif
#endif /* _JIT_RULES_H */