forked from micropython/micropython
-
Notifications
You must be signed in to change notification settings - Fork 4
/
emitndebug.c
285 lines (246 loc) · 10.6 KB
/
emitndebug.c
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
// native-debug specific stuff
#include "py/mpconfig.h"
#if MICROPY_EMIT_NATIVE_DEBUG
#include "py/asmbase.h"
#include "py/nativeglue.h"
#define asm_debug_printf(as, fmt, ...) \
do { \
if (as->base.pass == MP_ASM_PASS_EMIT) { \
if (fmt[0] != 'E') { \
mp_printf(MICROPY_EMIT_NATIVE_DEBUG_PRINTER, " "); \
} \
if (as->base.suppress) { \
mp_printf(MICROPY_EMIT_NATIVE_DEBUG_PRINTER, "dead_code "); \
} \
mp_printf(MICROPY_EMIT_NATIVE_DEBUG_PRINTER, fmt, __VA_ARGS__); \
} \
} while (0)
enum {
ASM_DEBUG_REG_R00,
ASM_DEBUG_REG_R01,
ASM_DEBUG_REG_R02,
ASM_DEBUG_REG_R03,
ASM_DEBUG_REG_R04,
ASM_DEBUG_REG_R05,
ASM_DEBUG_REG_R06,
ASM_DEBUG_REG_R07,
ASM_DEBUG_REG_R08,
ASM_DEBUG_REG_R09,
ASM_DEBUG_REG_R10,
ASM_DEBUG_REG_R11,
};
typedef struct _asm_debug_t {
mp_asm_base_t base;
} asm_debug_t;
static const char *const reg_name_table[] = {
"r_ret",
"r_arg1",
"r_arg2",
"r_arg3",
"r_arg4",
"r_temp0",
"r_temp1",
"r_temp2",
"r_local1",
"r_local2",
"r_local3",
"r_fun_table",
};
static const char *const fun_name_table[MP_F_NUMBER_OF] = {
[MP_F_CONVERT_OBJ_TO_NATIVE] = "convert_obj_to_native",
[MP_F_CONVERT_NATIVE_TO_OBJ] = "convert_native_to_obj",
[MP_F_NATIVE_SWAP_GLOBALS] = "native_swap_globals",
[MP_F_LOAD_NAME] = "load_name",
[MP_F_LOAD_GLOBAL] = "load_global",
[MP_F_LOAD_BUILD_CLASS] = "load_build_class",
[MP_F_LOAD_ATTR] = "load_attr",
[MP_F_LOAD_METHOD] = "load_method",
[MP_F_LOAD_SUPER_METHOD] = "load_super_method",
[MP_F_STORE_NAME] = "store_name",
[MP_F_STORE_GLOBAL] = "store_global",
[MP_F_STORE_ATTR] = "store_attr",
[MP_F_OBJ_SUBSCR] = "obj_subscr",
[MP_F_OBJ_IS_TRUE] = "obj_is_true",
[MP_F_UNARY_OP] = "unary_op",
[MP_F_BINARY_OP] = "binary_op",
[MP_F_BUILD_TUPLE] = "build_tuple",
[MP_F_BUILD_LIST] = "build_list",
[MP_F_BUILD_MAP] = "build_map",
[MP_F_BUILD_SET] = "build_set",
[MP_F_STORE_SET] = "store_set",
[MP_F_LIST_APPEND] = "list_append",
[MP_F_STORE_MAP] = "store_map",
[MP_F_MAKE_FUNCTION_FROM_PROTO_FUN] = "make_function_from_proto_fun",
[MP_F_NATIVE_CALL_FUNCTION_N_KW] = "native_call_function_n_kw",
[MP_F_CALL_METHOD_N_KW] = "call_method_n_kw",
[MP_F_CALL_METHOD_N_KW_VAR] = "call_method_n_kw_var",
[MP_F_NATIVE_GETITER] = "native_getiter",
[MP_F_NATIVE_ITERNEXT] = "native_iternext",
[MP_F_NLR_PUSH] = "nlr_push",
[MP_F_NLR_POP] = "nlr_pop",
[MP_F_NATIVE_RAISE] = "native_raise",
[MP_F_IMPORT_NAME] = "import_name",
[MP_F_IMPORT_FROM] = "import_from",
[MP_F_IMPORT_ALL] = "import_all",
[MP_F_NEW_SLICE] = "new_slice",
[MP_F_UNPACK_SEQUENCE] = "unpack_sequence",
[MP_F_UNPACK_EX] = "unpack_ex",
[MP_F_DELETE_NAME] = "delete_name",
[MP_F_DELETE_GLOBAL] = "delete_global",
[MP_F_NEW_CLOSURE] = "new_closure",
[MP_F_ARG_CHECK_NUM_SIG] = "arg_check_num_sig",
[MP_F_SETUP_CODE_STATE] = "setup_code_state",
[MP_F_SMALL_INT_FLOOR_DIVIDE] = "small_int_floor_divide",
[MP_F_SMALL_INT_MODULO] = "small_int_modulo",
[MP_F_NATIVE_YIELD_FROM] = "native_yield_from",
[MP_F_SETJMP] = "setjmp",
};
static void asm_debug_end_pass(asm_debug_t *as) {
(void)as;
}
static void asm_debug_entry(asm_debug_t *as, int num_locals) {
asm_debug_printf(as, "ENTRY(num_locals=%d)\n", num_locals);
}
static void asm_debug_exit(asm_debug_t *as) {
asm_debug_printf(as, "EXIT(%u)\n", 0);
}
static void asm_debug_fun(asm_debug_t *as, const char *op, int fun_idx) {
asm_debug_printf(as, "%s(%s)\n", op, fun_name_table[fun_idx]);
}
static void asm_debug_reg(asm_debug_t *as, const char *op, int reg) {
asm_debug_printf(as, "%s(%s)\n", op, reg_name_table[reg]);
}
static void asm_debug_label(asm_debug_t *as, const char *op, unsigned int label) {
asm_debug_printf(as, "%s(label_%u)\n", op, label);
}
static void asm_debug_reg_imm(asm_debug_t *as, const char *op, int reg, int imm) {
asm_debug_printf(as, "%s(%s, %d=0x%x)\n", op, reg_name_table[reg], imm, imm);
}
#if !MICROPY_PERSISTENT_CODE_SAVE
static void asm_debug_reg_qstr(asm_debug_t *as, const char *op, int reg, int qst) {
asm_debug_printf(as, "%s(%s, %s)\n", op, reg_name_table[reg], qstr_str(qst));
}
#endif
static void asm_debug_reg_reg(asm_debug_t *as, const char *op, int reg1, int reg2) {
asm_debug_printf(as, "%s(%s, %s)\n", op, reg_name_table[reg1], reg_name_table[reg2]);
}
static void asm_debug_reg_local(asm_debug_t *as, const char *op, int reg, unsigned int local) {
asm_debug_printf(as, "%s(%s, local_%u)\n", op, reg_name_table[reg], local);
}
static void asm_debug_reg_label(asm_debug_t *as, const char *op, int reg, unsigned int label) {
asm_debug_printf(as, "%s(%s, label_%u)\n", op, reg_name_table[reg], label);
}
static void asm_debug_local_reg(asm_debug_t *as, const char *op, int local, int reg) {
asm_debug_printf(as, "%s(local_%d, %s)\n", op, local, reg_name_table[reg]);
}
static void asm_debug_reg_label_bool(asm_debug_t *as, const char *op, int reg, unsigned int label, bool b) {
asm_debug_printf(as, "%s(%s, label_%u, %s)\n", op, reg_name_table[reg], label, b ? "true" : "false");
}
static void asm_debug_reg_reg_offset(asm_debug_t *as, const char *op, int reg1, int reg2, int offset) {
asm_debug_printf(as, "%s(%s, %s, %d)\n", op, reg_name_table[reg1], reg_name_table[reg2], offset);
}
static void asm_debug_reg_reg_label(asm_debug_t *as, const char *op, int reg1, int reg2, unsigned int label) {
asm_debug_printf(as, "%s(%s, %s, label_%u)\n", op, reg_name_table[reg1], reg_name_table[reg2], label);
}
static void asm_debug_setcc_reg_reg_reg(asm_debug_t *as, int op, int reg1, int reg2, int reg3) {
asm_debug_printf(as, "setcc(%d, %s, %s, %s)\n", op, reg_name_table[reg1], reg_name_table[reg2], reg_name_table[reg3]);
}
// The following macros provide a (mostly) arch-independent API to
// generate native code, and are used by the native emitter.
#define ASM_WORD_SIZE (8)
#define REG_RET ASM_DEBUG_REG_R00
#define REG_ARG_1 ASM_DEBUG_REG_R01
#define REG_ARG_2 ASM_DEBUG_REG_R02
#define REG_ARG_3 ASM_DEBUG_REG_R03
#define REG_ARG_4 ASM_DEBUG_REG_R04
#define REG_TEMP0 ASM_DEBUG_REG_R05
#define REG_TEMP1 ASM_DEBUG_REG_R06
#define REG_TEMP2 ASM_DEBUG_REG_R07
#define REG_LOCAL_1 ASM_DEBUG_REG_R08
#define REG_LOCAL_2 ASM_DEBUG_REG_R09
#define REG_LOCAL_3 ASM_DEBUG_REG_R10
#define REG_LOCAL_NUM (3)
// Holds a pointer to mp_fun_table
#define REG_FUN_TABLE ASM_DEBUG_REG_R11
#define ASM_T asm_debug_t
#define ASM_END_PASS asm_debug_end_pass
#define ASM_ENTRY(as, num_locals) \
asm_debug_entry(as, num_locals)
#define ASM_EXIT(as) \
asm_debug_exit(as)
#define ASM_JUMP(as, label) \
asm_debug_label(as, "jump", label)
#define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \
asm_debug_reg_label_bool(as, "jump_if_reg_zero", reg, label, bool_test)
#define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \
asm_debug_reg_label_bool(as, "jump_if_reg_nonzero", reg, label, bool_test)
#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
asm_debug_reg_reg_label(as, "jump_if_reg_eq", reg1, reg2, label)
#define ASM_JUMP_REG(as, reg) \
asm_debug_reg(as, "jump_reg", reg)
#define ASM_CALL_IND(as, idx) \
asm_debug_fun(as, "call_ind", idx)
#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) \
asm_debug_local_reg(as, "mov_local_reg", local_num, reg_src)
#define ASM_MOV_REG_IMM(as, reg_dest, imm) \
asm_debug_reg_imm(as, "mov_reg_imm", reg_dest, imm)
#define ASM_MOV_REG_QSTR(as, reg_dest, qst) \
asm_debug_reg_qstr(as, "mov_reg_qstr", reg_dest, qst)
#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) \
asm_debug_reg_local(as, "mov_reg_local", reg_dest, local_num)
#define ASM_MOV_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "mov_reg_reg", reg_dest, reg_src)
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) \
asm_debug_reg_local(as, "mov_reg_local_addr", reg_dest, local_num)
#define ASM_MOV_REG_PCREL(as, reg_dest, label) \
asm_debug_reg_label(as, "mov_reg_pcrel", reg_dest, label)
#define ASM_NOT_REG(as, reg_dest) \
asm_debug_reg(as, "not", reg_dest)
#define ASM_NEG_REG(as, reg_dest) \
asm_debug_reg(as, "neg", reg_dest)
#define ASM_LSL_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "lsl", reg_dest, reg_src)
#define ASM_LSR_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "lsr", reg_dest, reg_src)
#define ASM_ASR_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "asr", reg_dest, reg_src)
#define ASM_OR_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "or", reg_dest, reg_src)
#define ASM_XOR_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "xor", reg_dest, reg_src)
#define ASM_AND_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "and", reg_dest, reg_src)
#define ASM_ADD_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "add", reg_dest, reg_src)
#define ASM_SUB_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "sub", reg_dest, reg_src)
#define ASM_MUL_REG_REG(as, reg_dest, reg_src) \
asm_debug_reg_reg(as, "mul", reg_dest, reg_src)
#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) \
asm_debug_reg_reg(as, "load", reg_dest, reg_base)
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) \
asm_debug_reg_reg_offset(as, "load", reg_dest, reg_base, word_offset)
#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) \
asm_debug_reg_reg(as, "load8", reg_dest, reg_base)
#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) \
asm_debug_reg_reg(as, "load16", reg_dest, reg_base)
#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) \
asm_debug_reg_reg_offset(as, "load16", reg_dest, reg_base, uint16_offset)
#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) \
asm_debug_reg_reg(as, "load32", reg_dest, reg_base)
#define ASM_STORE_REG_REG(as, reg_src, reg_base) \
asm_debug_reg_reg(as, "store", reg_src, reg_base)
#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) \
asm_debug_reg_reg_offset(as, "store", reg_src, reg_base, word_offset)
#define ASM_STORE8_REG_REG(as, reg_src, reg_base) \
asm_debug_reg_reg(as, "store8", reg_src, reg_base)
#define ASM_STORE16_REG_REG(as, reg_src, reg_base) \
asm_debug_reg_reg(as, "store16", reg_src, reg_base)
#define ASM_STORE32_REG_REG(as, reg_src, reg_base) \
asm_debug_reg_reg(as, "store32", reg_src, reg_base)
// Word indices of REG_LOCAL_x in nlr_buf_t
#define NLR_BUF_IDX_LOCAL_1 (5) // rbx
#define N_DEBUG (1)
#define EXPORT_FUN(name) emit_native_debug_##name
#include "py/emitnative.c"
#endif