Skip to content

Commit

Permalink
py/emitndebug: Add native debug emitter.
Browse files Browse the repository at this point in the history
This emitter prints out pseudo-machine instructions, instead of the usual
output of the native emitter.  It can be enabled on any port via
`MICROPY_EMIT_NATIVE_DEBUG` (make sure other native emitters are disabled)
but the easiest way to use it is with mpy-cross:

    $ mpy-cross -march=debug file.py

Signed-off-by: Damien George <[email protected]>
  • Loading branch information
dpgeorge committed Jun 21, 2024
1 parent e2ae03e commit 9dbc787
Show file tree
Hide file tree
Showing 11 changed files with 315 additions and 4 deletions.
7 changes: 5 additions & 2 deletions mpy-cross/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static void stdout_print_strn(void *env, const char *str, size_t len) {
(void)dummy;
}

static const mp_print_t mp_stdout_print = {NULL, stdout_print_strn};
const mp_print_t mp_stdout_print = {NULL, stdout_print_strn};

static void stderr_print_strn(void *env, const char *str, size_t len) {
(void)env;
Expand Down Expand Up @@ -130,7 +130,7 @@ static int usage(char **argv) {
"Target specific options:\n"
"-msmall-int-bits=number : set the maximum bits used to encode a small-int\n"
"-march=<arch> : set architecture for native emitter;\n"
" x86, x64, armv6, armv6m, armv7m, armv7em, armv7emsp, armv7emdp, xtensa, xtensawin, rv32imc\n"
" x86, x64, armv6, armv6m, armv7m, armv7em, armv7emsp, armv7emdp, xtensa, xtensawin, rv32imc, debug\n"
"\n"
"Implementation specific options:\n", argv[0]
);
Expand Down Expand Up @@ -316,6 +316,9 @@ MP_NOINLINE int main_(int argc, char **argv) {
} else if (strcmp(arch, "rv32imc") == 0) {
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_RV32IMC;
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_RV32I;
} else if (strcmp(arch, "debug") == 0) {
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_DEBUG;
mp_dynamic_compiler.nlr_buf_num_regs = 0;
} else if (strcmp(arch, "host") == 0) {
#if defined(__i386__) || defined(_M_IX86)
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86;
Expand Down
4 changes: 4 additions & 0 deletions mpy-cross/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
#define MICROPY_EMIT_INLINE_XTENSA (1)
#define MICROPY_EMIT_XTENSAWIN (1)
#define MICROPY_EMIT_RV32 (1)
#define MICROPY_EMIT_NATIVE_DEBUG (1)
#define MICROPY_EMIT_NATIVE_DEBUG_PRINTER (&mp_stdout_print)

#define MICROPY_DYNAMIC_COMPILER (1)
#define MICROPY_COMP_CONST_FOLDING (1)
Expand Down Expand Up @@ -164,3 +166,5 @@ typedef int ssize_t;
typedef mp_off_t off_t;

#endif

extern const struct _mp_print_t mp_stdout_print;
6 changes: 6 additions & 0 deletions py/asmbase.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "py/obj.h"
#include "py/misc.h"
#include "py/asmbase.h"
#include "py/persistentcode.h"

#if MICROPY_EMIT_MACHINE_CODE

Expand Down Expand Up @@ -91,6 +92,11 @@ void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) {
} else {
// ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
assert(as->label_offsets[label] == as->code_offset);
#if MICROPY_DYNAMIC_COMPILER && MICROPY_EMIT_NATIVE_DEBUG
if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_DEBUG) {
mp_printf(MICROPY_EMIT_NATIVE_DEBUG_PRINTER, "label(label_%u)\n", (unsigned int)label);
}
#endif
}
}

Expand Down
3 changes: 3 additions & 0 deletions py/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ static const emit_method_table_t *emit_native_table[] = {
&emit_native_xtensa_method_table,
&emit_native_xtensawin_method_table,
&emit_native_rv32_method_table,
&emit_native_debug_method_table,
};

#elif MICROPY_EMIT_NATIVE
Expand All @@ -121,6 +122,8 @@ static const emit_method_table_t *emit_native_table[] = {
#define NATIVE_EMITTER(f) emit_native_xtensawin_##f
#elif MICROPY_EMIT_RV32
#define NATIVE_EMITTER(f) emit_native_rv32_##f
#elif MICROPY_EMIT_NATIVE_DEBUG
#define NATIVE_EMITTER(f) emit_native_debug_##f
#else
#error "unknown native emitter"
#endif
Expand Down
3 changes: 3 additions & 0 deletions py/emit.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ extern const emit_method_table_t emit_native_arm_method_table;
extern const emit_method_table_t emit_native_xtensa_method_table;
extern const emit_method_table_t emit_native_xtensawin_method_table;
extern const emit_method_table_t emit_native_rv32_method_table;
extern const emit_method_table_t emit_native_debug_method_table;

extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops;
extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops;
Expand All @@ -215,6 +216,7 @@ emit_t *emit_native_arm_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot,
emit_t *emit_native_xtensa_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels);
emit_t *emit_native_xtensawin_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels);
emit_t *emit_native_rv32_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels);
emit_t *emit_native_debug_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels);

void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels);

Expand All @@ -226,6 +228,7 @@ void emit_native_arm_free(emit_t *emit);
void emit_native_xtensa_free(emit_t *emit);
void emit_native_xtensawin_free(emit_t *emit);
void emit_native_rv32_free(emit_t *emit);
void emit_native_debug_free(emit_t *emit);

void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope);
bool mp_emit_bc_end_pass(emit_t *emit);
Expand Down
6 changes: 5 additions & 1 deletion py/emitnative.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
#endif

// wrapper around everything in this file
#if N_X64 || N_X86 || N_THUMB || N_ARM || N_XTENSA || N_XTENSAWIN || N_RV32
#if N_X64 || N_X86 || N_THUMB || N_ARM || N_XTENSA || N_XTENSAWIN || N_RV32 || N_DEBUG

// C stack layout for native functions:
// 0: nlr_buf_t [optional]
Expand Down Expand Up @@ -348,6 +348,8 @@ static void emit_native_mov_reg_state_addr(emit_t *emit, int reg_dest, int local
static void emit_native_mov_reg_qstr(emit_t *emit, int arg_reg, qstr qst) {
#if MICROPY_PERSISTENT_CODE_SAVE
ASM_LOAD16_REG_REG_OFFSET(emit->as, arg_reg, REG_QSTR_TABLE, mp_emit_common_use_qstr(emit->emit_common, qst));
#elif defined(ASM_MOV_REG_QSTR)
ASM_MOV_REG_QSTR(emit->as, arg_reg, qst);
#else
ASM_MOV_REG_IMM(emit->as, arg_reg, qst);
#endif
Expand Down Expand Up @@ -2604,6 +2606,8 @@ static void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
default:
break;
}
#elif N_DEBUG
asm_debug_setcc_reg_reg_reg(emit->as, op_idx, REG_RET, REG_ARG_2, reg_rhs);
#else
#error not implemented
#endif
Expand Down
Loading

0 comments on commit 9dbc787

Please sign in to comment.