summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/asmbase.c6
-rw-r--r--py/compile.c3
-rw-r--r--py/emit.h3
-rw-r--r--py/emitnative.c6
-rw-r--r--py/emitndebug.c285
-rw-r--r--py/mpconfig.h2
-rw-r--r--py/persistentcode.h1
-rw-r--r--py/py.cmake1
-rw-r--r--py/py.mk1
9 files changed, 306 insertions, 2 deletions
diff --git a/py/asmbase.c b/py/asmbase.c
index cf64e3f3d0..3fce543a7f 100644
--- a/py/asmbase.c
+++ b/py/asmbase.c
@@ -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
@@ -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
}
}
diff --git a/py/compile.c b/py/compile.c
index 9b012f8787..3429e384c0 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -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
@@ -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
diff --git a/py/emit.h b/py/emit.h
index 0c5019f07a..9aad6ebafb 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -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;
@@ -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);
@@ -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);
diff --git a/py/emitnative.c b/py/emitnative.c
index 99e5a24c1b..9d3f698b25 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -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]
@@ -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
@@ -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
diff --git a/py/emitndebug.c b/py/emitndebug.c
new file mode 100644
index 0000000000..bd896a75c8
--- /dev/null
+++ b/py/emitndebug.c
@@ -0,0 +1,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
diff --git a/py/mpconfig.h b/py/mpconfig.h
index efb30ac04d..bc6bf75fe5 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -412,7 +412,7 @@
#endif
// Convenience definition for whether any native emitter is enabled
-#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN || MICROPY_EMIT_RV32)
+#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN || MICROPY_EMIT_RV32 || MICROPY_EMIT_NATIVE_DEBUG)
// Some architectures cannot read byte-wise from executable memory. In this case
// the prelude for a native function (which usually sits after the machine code)
diff --git a/py/persistentcode.h b/py/persistentcode.h
index 3f3c67764d..f0b7f70f7d 100644
--- a/py/persistentcode.h
+++ b/py/persistentcode.h
@@ -98,6 +98,7 @@ enum {
MP_NATIVE_ARCH_XTENSA,
MP_NATIVE_ARCH_XTENSAWIN,
MP_NATIVE_ARCH_RV32IMC,
+ MP_NATIVE_ARCH_DEBUG, // this entry should always be last
};
enum {
diff --git a/py/py.cmake b/py/py.cmake
index f47661c409..ccd0577c38 100644
--- a/py/py.cmake
+++ b/py/py.cmake
@@ -26,6 +26,7 @@ set(MICROPY_SOURCE_PY
${MICROPY_PY_DIR}/emitinlinethumb.c
${MICROPY_PY_DIR}/emitinlinextensa.c
${MICROPY_PY_DIR}/emitnarm.c
+ ${MICROPY_PY_DIR}/emitndebug.c
${MICROPY_PY_DIR}/emitnrv32.c
${MICROPY_PY_DIR}/emitnthumb.c
${MICROPY_PY_DIR}/emitnx64.c
diff --git a/py/py.mk b/py/py.mk
index 0b429f9efe..cd9392edbb 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -116,6 +116,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\
emitnxtensawin.o \
asmrv32.o \
emitnrv32.o \
+ emitndebug.o \
formatfloat.o \
parsenumbase.o \
parsenum.o \