MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.
microPython Python最小内核源码解析
以下是对代码中英文注释的翻译和补充,以及重新输出的代码:
#include <stdio.h>
#include <string.h>
#include <assert.h>
// 包含 MicroPython 发射(emit)相关的头文件
#include "py/emit.h"
#include "py/nativeglue.h"
#include "py/objfun.h"
#include "py/objstr.h"
// 调试信息打印,当启用详细调试模式时
#if MICROPY_DEBUG_VERBOSE // 打印调试信息
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else // 不打印调试信息
#define DEBUG_printf(...) (void)0
#endif
// 各种架构下的 C 栈布局
#if N_X64 || N_X86 || N_THUMB || N_ARM || N_XTENSA || N_XTENSAWIN
// 原生函数的 C 栈布局:
// 0: nlr_buf_t [可选]
// return_value [可选字]
// exc_handler_unwind [可选字]
// emit->code_state_start: mp_code_state_native_t
// emit->stack_start: Python 对象栈 | emit->n_state
// locals (reversed, L0 在末尾)
//
// 原生生成器函数的 C 栈布局:
// 0=emit->stack_start: nlr_buf_t
// return_value
// exc_handler_unwind [可选字]
//
// viper 函数的 C 栈布局:
// 0: nlr_buf_t [可选]
// return_value [可选字]
// exc_handler_unwind [可选字]
// emit->code_state_start: fun_obj, old_globals [可选]
// emit->stack_start: Python 对象栈 | emit->n_state
// locals (reversed, L0 在末尾)
// (L0-L2 可能在寄存器中)
// 原生发射器需要知道以下 C 结构体的大小和偏移(在目标平台上)
#if MICROPY_DYNAMIC_COMPILER
#define SIZEOF_NLR_BUF (2 + mp_dynamic_compiler.nlr_buf_num_regs + 1) // 保守估计,如果启用了 MICROPY_ENABLE_PYSTACK
#else
#define SIZEOF_NLR_BUF (sizeof(nlr_buf_t) / sizeof(uintptr_t))
#endif
#define SIZEOF_CODE_STATE (sizeof(mp_code_state_native_t) / sizeof(uintptr_t))
#define OFFSETOF_CODE_STATE_STATE (offsetof(mp_code_state_native_t, state) / sizeof(uintptr_t))
#define OFFSETOF_CODE_STATE_FUN_BC (offsetof(mp_code_state_native_t, fun_bc) / sizeof(uintptr_t))
#define OFFSETOF_CODE_STATE_IP (offsetof(mp_code_state_native_t, ip) / sizeof(uintptr_t))
#define OFFSETOF_CODE_STATE_SP (offsetof(mp_code_state_native_t, sp) / sizeof(uintptr_t))
#define OFFSETOF_CODE_STATE_N_STATE (offsetof(mp_code_state_native_t, n_state) / sizeof(uintptr_t))
#define OFFSETOF_OBJ_FUN_BC_CONTEXT (offsetof(mp_obj_fun_bc_t, context) / sizeof(uintptr_t))
#define OFFSETOF_OBJ_FUN_BC_CHILD_TABLE (offsetof(mp_obj_fun_bc_t, child_table) / sizeof(uintptr_t))
#define OFFSETOF_OBJ_FUN_BC_BYTECODE (offsetof(mp_obj_fun_bc_t, bytecode) / sizeof(uintptr_t))
#define OFFSETOF_MODULE_CONTEXT_QSTR_TABLE (offsetof(mp_module_context_t, constants.qstr_table) / sizeof(uintptr_t))
#define OFFSETOF_MODULE_CONTEXT_OBJ_TABLE (offsetof(mp_module_context_t, constants.obj_table) / sizeof(uintptr_t))
#define OFFSETOF_MODULE_CONTEXT_GLOBALS (offsetof(mp_module_context_t, module.globals) / sizeof(uintptr_t))
// 如果尚未定义,则将父参数设置为与子调用寄存器相同
#ifndef REG_PARENT_RET
#define REG_PARENT_RET REG_RET
#define REG_PARENT_ARG_1 REG_ARG_1
#define REG_PARENT_ARG_2 REG_ARG_2
#define REG_PARENT_ARG_3 REG_ARG_3
#define REG_PARENT_ARG_4 REG_ARG_4
#endif
// nlr_buf_t.ret_val 的字索引
#define NLR_BUF_IDX_RET_VAL (1)
// viper 函数是否需要访问 fun_obj
#define NEED_FUN_OBJ(emit) ((emit)->scope->exc_stack_size > 0 \
|| ((emit)->scope->scope_flags & (MP_SCOPE_FLAG_REFGLOBALS | MP_SCOPE_FLAG_HASCONSTS)))
// 原生/viper 函数是否需要用异常处理器包装
#define NEED_GLOBAL_EXC_HANDLER(emit) ((emit)->scope->exc_stack_size > 0 \
|| ((emit)->scope->scope_flags & (MP_SCOPE_FLAG_GENERATOR | MP_SCOPE_FLAG_REFGLOBALS)))
// 是否需要一个槽来存储 LOCAL_IDX_EXC_HANDLER_UNWIND
#define NEED_EXC_HANDLER_UNWIND(emit) ((emit)->scope->exc_stack_size > 0)
// 是否可以使用寄存器来存储局部变量(只有在没有异常处理器的情况下才为真,因为否则 nlr_jump 会将寄存器恢复到函数开始时的状态,局部变量的更新将会丢失)
#define CAN_USE_REGS_FOR_LOCALS(emit) ((emit)->scope->exc_stack_size == 0 && !(emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR))
// 本地 C 栈中各种变量的索引
#define LOCAL_IDX_EXC_VAL(emit) (NLR_BUF_IDX_RET_VAL)
#define LOCAL_IDX_EXC_HANDLER_PC(emit) (NLR_BUF_IDX_LOCAL_1)
#define LOCAL_IDX_EXC_HANDLER_UNWIND(emit) (SIZEOF_NLR_BUF + 1) // 这需要一个独立的变量,不在 nlr_buf_t 中
#define LOCAL_IDX_RET_VAL(emit) (SIZEOF_NLR_BUF) // 当 NEED_GLOBAL_EXC_HANDLER 为真时需要
#define LOCAL_IDX_FUN_OBJ(emit) ((emit)->code_state_start + OFFSETOF_CODE_STATE_FUN_BC)
#define LOCAL_IDX_OLD_GLOBALS(emit) ((emit)->code_state_start + OFFSETOF_CODE_STATE_IP)
#define LOCAL_IDX_GEN_PC(emit) ((emit)->code_state_start + OFFSETOF_CODE_STATE_IP)
#define LOCAL_IDX_LOCAL_VAR(emit, local_num) ((emit)->stack_start + (emit)->n_state - 1 - (local_num))
#if MICROPY_PERSISTENT_CODE_SAVE
// 当启用保存原生代码到 .mpy 文件的能力时:
// - Qstrs 通过 qstr_table 间接访问,REG_LOCAL_3 始终指向 qstr_table。
// - 在生成器中不使用寄存器来存储局部变量,REG_LOCAL_2 指向生成器状态。
// - 最多有 2 个寄存器保存局部变量(参见 CAN_USE_REGS_FOR_LOCALS 了解何时可能)。
#define REG_GENERATOR_STATE (REG_LOCAL_2)
#define REG_QSTR_TABLE (REG_LOCAL_3)
#define MAX_REGS_FOR_LOCAL_VARS (2)
static const uint8_t reg_local_table[MAX_REGS_FOR_LOCAL_VARS] = {
REG_LOCAL_1, REG_LOCAL_2};
#else
// 当未启用保存原生代码到 .mpy 文件的能力时:
// - Qstrs 值直接写入机器代码。
// - 在生成器中不使用寄存器来存储局部变量,REG_LOCAL_3 指向生成器状态。
// - 最多有 3 个寄存器保存局部变量(参见 CAN_USE_REGS_FOR_LOCALS 了解何时可能)。
#define REG_GENERATOR_STATE (REG_LOCAL_3)
#define MAX_REGS_FOR_LOCAL_VARS (3)
static const uint8_t reg_local_table[MAX_REGS_FOR_LOCAL_VARS] = {
REG_LOCAL_1, REG_LOCAL_2, REG_LOCAL_3};
#endif
#define REG_LOCAL_LAST (reg_local_table[MAX_REGS_FOR_LOCAL_VARS - 1])
#define EMIT_NATIVE_VIPER_TYPE_ERROR(emit, ...) do {
\
*emit->error_slot = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, __VA_ARGS__); \
} while (0)
// 堆栈信息类型
typedef enum {
STACK_VALUE,
STACK_REG,
STACK_IMM,
} stack_info_kind_t;
// 这些枚举必须是不同的,并且最低 4 位必须对应正确的 MP_NATIVE_TYPE_xxx 值
typedef enum {
VTYPE_PYOBJ = 0x00 | MP_NATIVE_TYPE_OBJ,
VTYPE_BOOL = 0x00 | MP_NATIVE_TYPE_BOOL,
VTYPE_INT = 0x00 | MP_NATIVE_TYPE_INT,
VTYPE_UINT = 0x00 | MP_NATIVE_TYPE_UINT,
VTYPE_PTR = 0x00 | MP_NATIVE_TYPE_PTR,
VTYPE_PTR8 = 0x00 | MP_NATIVE_TYPE_PTR8,
VTYPE_PTR16 = 0x00 | MP_NATIVE_TYPE_PTR16,
VTYPE_PTR32 = 0x00 | MP_NATIVE_TYPE_PTR32,
VTYPE_PTR_NONE = 0x50 | MP_NATIVE_TYPE_PTR,
VTYPE_UNBOUND = 0x60 | MP_NATIVE_TYPE_OBJ,
VTYPE_BUILTIN_CAST = 0x70 | MP_NATIVE_TYPE_OBJ,
} vtype_kind_t;
// 将 vtype 转换为 qstr
static qstr vtype_to_qstr(vtype_kind_t vtype) {
switch (vtype) {
case VTYPE_PYOBJ:
return MP_QSTR_object;
case VTYPE_BOOL:
return MP_QSTR_bool;
case VTYPE_INT:
return MP_QSTR_int;
case VTYPE_UINT:
return MP_QSTR_uint;
case VTYPE_PTR:
return MP_QSTR_ptr;
case VTYPE_PTR8:
return MP_QSTR_ptr8;
case VTYPE_PTR16:
return MP_QSTR_ptr16;
case VTYPE_PTR32:
return MP_QSTR_ptr32;
case VTYPE_PTR_NONE:
default:
return MP_QSTR_None;
}
}
// 堆栈信息结构体
typedef struct _stack_info_t {
vtype_kind_t vtype; // 值类型
stack_info_kind_t kind; // 堆栈信息类型
union {
int u_reg;
mp_int_t u_imm;
} data; // 数据
} stack_info_t;
// 异常栈条目结构体
typedef struct _exc_stack_entry_t {
uint16_t label : 15; // 标签
uint16_t is_finally : 1; // 是否为 finally 块
uint16_t unwind_label : 15; // 展开标签
uint16_t is_active : 1; // 是否激活
} exc_stack_entry_t;
// 发射器结构体
struct _emit_t {
mp_emit_common_t *emit_common; // 通用发射器
mp_obj_t *error_slot; // 错误槽
uint *label_slot; // 标签槽
uint exit_label; // 退出标签
int pass; // 遍历次数
bool do_viper_types; // 是否使用 viper 类型
mp_uint_t local_vtype_alloc; // 本地变量类型分配
vtype_kind_t *local_vtype; // 本地变量类型
mp_uint_t stack_info_alloc; // 堆栈信息分配
stack_info_t *stack_info; // 堆栈信息
vtype_kind_t saved_stack_vtype; // 保存的堆栈值类型
size_t exc_stack_alloc; // 异常栈分配
size_t exc_stack_size; // 异常栈大小
exc_stack_entry_t *exc_stack; // 异常栈
int prelude_offset; // 前奏偏移
int prelude_ptr_index; // 前奏指针索引
int start_offset; // 开始偏移
int n_state; // 状态数量
uint16_t code_state_start; // 代码状态起始
uint16_t stack_start; // 栈起始
int stack_size; // 栈大小
uint16_t n_info; // 信息数量
uint16_t n_cell; // 单元格数量
scope_t *scope; // 作用域
ASM_T *as; // 汇编对象
};
// 从对象中加载寄存器
static void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj);
// 进入原生全局异常处理
static void emit_native_global_exc_entry(emit_t *emit);
// 退出原生全局异常处理
static void emit_native_global_exc_exit(emit_t *emit);
// 加载常量对象
static void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj);
emit_t *EXPORT_FUN(new)(mp_emit_common_t * emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels) {
// 创建并初始化新的发射器
emit_t *emit = m_new0(emit_t, 1);
emit->emit_common = emit_common;
emit->error_slot = error_slot;
emit->label_slot = label_slot;
emit->stack_info_alloc = 8;
emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc);
emit->exc_stack_alloc = 8;
emit->exc_stack = m_new(exc_stack_entry_t, emit->exc_stack_alloc);
emit->as = m_new0(ASM_T, 1);
mp_asm_base_init(&emit->as->base, max_num_labels);
return emit;
}
// 释放发射器资源
void EXPORT_FUN(free)(emit_t * emit) {
mp_asm_base_deinit(&emit->as->base, false);
m_del_obj(ASM_T, emit->as);
m_del(exc_stack_entry_t, emit->exc_stack, emit->exc_stack_alloc);
m_del(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc);
m_del(stack_info_t, emit->stack_info, emit->stack_info_alloc);
m_del_obj(emit_t, emit);
}
// 调用带有立即数参数的函数
static void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg);
// 将寄存器移动到常量
static void emit_native_mov_reg_const(emit_t *emit, int reg_dest, int const_val) {
ASM_LOAD_REG_REG_OFFSET(emit->as, reg_dest, REG_FUN_TABLE, const_val);
}
// 将本地变量从寄存器移动到状态
static void emit_native_mov_state_reg(emit_t *emit, int local_num, int reg_src) {
if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
ASM_STORE_REG_REG_OFFSET(emit->as, reg_src, REG_GENERATOR_STATE, local_num);
} else {
ASM_MOV_LOCAL_REG(emit->as, local_num, reg_src);
}
}
// 将状态从寄存器移动到本地变量
static void emit_native_mov_reg_state(emit_t *emit, int reg_dest, int local_num) {
if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
ASM_LOAD_REG_REG_OFFSET(emit->as, reg_dest, REG_GENERATOR_STATE, local_num);
} else {
ASM_MOV_REG_LOCAL(emit->as, reg_dest, local_num);
}
}
// 将状态地址从寄存器移动到本地变量
static void emit_native_mov_reg_state_addr(emit_t *emit, int reg_dest, int local_num) {
if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
ASM_MOV_REG_IMM(emit->as, reg_dest, local_num * ASM_WORD_SIZE);
ASM_ADD_REG_REG(emit->as, reg_dest, REG_GENERATOR_STATE);
} else {
ASM_MOV_REG_LOCAL_ADDR(emit->as, reg_dest, local_num);
}
}
// 将 qstr 从寄存器移动到本地变量
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));
#else
ASM_MOV_REG_IMM(emit->as, arg_reg, qst);
#endif
}
// 将 qstr 对象从寄存器移动到本地变量
static void emit_native_mov_reg_qstr_obj(emit_t *emit, int reg_dest, qstr qst) {
#if MICROPY_PERSISTENT_CODE_SAVE
emit_load_reg_with_object(emit, reg_dest, MP_OBJ_NEW_QSTR(qst));
#else
ASM_MOV_REG_IMM(emit->as, reg_dest, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));
#endif
}
// 通过寄存器移动状态中的立即数
#define emit_native_mov_state_imm_via(emit, local_num, imm, reg_temp) \
do {
\
ASM_MOV_REG_IMM((emit)->as, (reg_temp), (imm)); \
emit_native_mov_state_reg((emit), (local_num), (reg_temp)); \
} while (false)
// 开始一个新的作用域遍历
static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope);
emit->pass = pass;
emit->do_viper_types = scope->emit_options == MP_EMIT_OPT_VIPER;
emit->stack_size = 0;
emit->scope = scope;
// 为本地变量分配类型跟踪内存
if (emit->local_vtype_alloc < scope->num_locals) {
emit->local_vtype = m_renew(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc, scope->num_locals);
emit->local_vtype_alloc = scope->num_locals;
}
// 设置参数的默认类型
mp_uint_t num_args = emit->scope->num_pos_args + emit->scope->num_kwonly_args;
if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {
num_args += 1;
}
if (scope->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) {
num_args += 1;
}
for (mp_uint_t i = 0; i < num_args; i++) {
emit->local_vtype[i] = VTYPE_PYOBJ;
}
// 为参数设置 viper 类型
if (emit->do_viper_types) {
for (int i = 0; i < emit->scope->id_info_len; ++i) {
id_info_t *id = &emit->scope->id_info[i];
if (id->flags & ID_FLAG_IS_PARAM) {
assert(id->local_num < emit->local_vtype_alloc);
emit->local_vtype[id->local_num] = id->flags >> ID_FLAG_VIPER_TYPE_POS;
}
}
}
// 本地变量开始时未绑定,类型未知
for (mp_uint_t i = num_args; i < emit->local_vtype_alloc; i++) {
emit->local_vtype[i] = emit->do_viper_types ? VTYPE_UNBOUND : VTYPE_PYOBJ;
}
// 堆栈上的值开始时未绑定
for (mp_uint_t i = 0; i < emit->stack_info_alloc; i++) {
emit->stack_info[i].kind = STACK_VALUE;
emit->stack_info[i].vtype = VTYPE_UNBOUND;
}
mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
// 生成函数入口代码
// 计算代码状态的起始位置(mp_code_state_native_t 或 viper 的简化版本)
emit->code_state_start = 0;
if (NEED_GLOBAL_EXC_HANDLER(emit)) {
emit->code_state_start = SIZEOF_NLR_BUF; // 为 nlr_buf_t 保留
emit->code_state_start += 1; // 为 return_value 保留
if (NEED_EXC_HANDLER_UNWIND(emit)) {
emit->code_state_start += 1;
}
}
size_t fun_table_off = mp_emit_common_use_const_obj(emit->emit_common, MP_OBJ_FROM_PTR(&mp_fun_table));
if (emit->do_viper_types) {
// 计算状态大小(局部变量加上堆栈)
// n_state 计算所有堆栈和局部变量,即使在寄存器中的也算
emit->n_state = scope->num_locals + scope->stack_size;
int num_locals_in_regs = 0;
if (CAN_USE_REGS_FOR_LOCALS(emit)) {
num_locals_in_regs = scope->num_locals;
if (num_locals_in_regs > MAX_REGS_FOR_LOCAL_VARS) {
num_locals_in_regs = MAX_REGS_FOR_LOCAL_VARS;
}
// 需要一个寄存器用于 REG_LOCAL_LAST(见下文)
if (scope->num_pos_args >= MAX_REGS_FOR_LOCAL_VARS + 1) {
--num_locals_in_regs;
}
}
// 计算局部变量和 Python 堆栈在 C 栈中的起始位置
if (NEED_GLOBAL_EXC_HANDLER(emit)) {
// 为函数对象和旧全局变量保留 2 个字
emit->stack_start = emit->code_state_start + 2;
} else if (scope->scope_flags & MP_SCOPE_FLAG_HASCONSTS) {
// 为函数对象保留 1 个字,用于访问常量表
emit->stack_start = emit->code_state_start + 1;
} else {
emit->stack_start = emit->code_state_start + 0;
}
// 函数入口
ASM_ENTRY(emit->as, emit->stack_start + emit->n_state - num_locals_in_regs);
#if N_X86
asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1);
#endif
// 将 REG_FUN_TABLE 载入 mp_fun_table 指针,该指针在 const_table 中找到
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
#if MICROPY_PERSISTENT_CODE_SAVE
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
#endif
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, fun_table_off);
// 将函数对象(作为第一个参数传递)存储到堆栈上,如果需要的话
if (NEED_FUN_OBJ(emit)) {
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1);
}
// 将 n_args 放入 REG_ARG_1,n_kw 放入 REG_ARG_2,args 数组放入 REG_LOCAL_LAST
#if N_X86
asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_1);
asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_2);
asm_x86_mov_arg_to_r32(emit->as, 3, REG_LOCAL_LAST);
#else
ASM_MOV_REG_REG(emit->as, REG_ARG_1, REG_PARENT_ARG_2);
ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_PARENT_ARG_3);
ASM_MOV_REG_REG(emit->as, REG_LOCAL_LAST, REG_PARENT_ARG_4);
#endif
// 检查参数数量是否与此函数匹配,如果不匹配则调用 mp_arg_check_num_sig
ASM_JUMP_IF_REG_NONZERO(emit->as, REG_ARG_2, *emit->label_slot + 4, true);
ASM_MOV_REG_IMM(emit->as, REG_ARG_3, scope->num_pos_args);
ASM_JUMP_IF_REG_EQ(emit->as, REG_ARG_1, REG_ARG_3, *emit->label_slot + 5);
mp_asm_base_label_assign(&emit->as->base, *emit->label_slot + 4);
ASM_MOV_REG_IMM(emit->as, REG_ARG_3, MP_OBJ_FUN_MAKE_SIG(scope->num_pos_args, scope->num_pos_args, false));
ASM_CALL_IND(emit->as, MP_F_ARG_CHECK_NUM_SIG);
mp_asm_base_label_assign(&emit->as->base, *emit->label_slot + 5);
// 将参数存储到局部变量中(寄存器或堆栈),如果需要则转换为本地类型
for (int i = 0; i < emit->scope->num_pos_args; i++) {
int r = REG_ARG_1;
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_ARG_1, REG_LOCAL_LAST, i);
if (emit->local_vtype[i] != VTYPE_PYOBJ) {
emit_call_with_imm_arg(emit, MP_F_CONVERT_OBJ_TO_NATIVE, emit->local_vtype[i], REG_ARG_2);
r = REG_RET;
}
// REG_LOCAL_LAST 指向 args 数组,因此如果还需要它,请不要覆盖它
if (i < MAX_REGS_FOR_LOCAL_VARS && CAN_USE_REGS_FOR_LOCALS(emit) && (i != MAX_REGS_FOR_LOCAL_VARS - 1 || emit->scope->num_pos_args == MAX_REGS_FOR_LOCAL_VARS)) {
ASM_MOV_REG_REG(emit->as, reg_local_table[i], r);
} else {
emit_native_mov_state_reg(emit, LOCAL_IDX_LOCAL_VAR(emit, i), r);
}
}
// 如果这个寄存器不能再写入,则从堆栈中获取局部变量并放回 REG_LOCAL_LAST
if (emit->scope->num_pos_args >= MAX_REGS_FOR_LOCAL_VARS + 1 && CAN_USE_REGS_FOR_LOCALS(emit)) {
ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_LAST, LOCAL_IDX_LOCAL_VAR(emit, MAX_REGS_FOR_LOCAL_VARS - 1));
}
emit_native_global_exc_entry(emit);
} else {
// 计算状态大小(局部变量加上堆栈)
emit->n_state = scope->num_locals + scope->stack_size;
// 在第一个机器字中存储一个索引,用于函数的前奏。
// 这在运行时由 mp_obj_fun_native_get_prelude_ptr() 使用。
mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_ptr_index);
if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->start_offset);
ASM_ENTRY(emit->as, emit->code_state_start);
// 为 REG_GENERATOR_STATE 指向的状态重置状态大小
emit->code_state_start = 0;
emit->stack_start = SIZEOF_CODE_STATE;
// 将代码状态的地址放入 REG_GENERATOR_STATE
#if N_X86
asm_x86_mov_arg_to_r32(emit->as, 0, REG_GENERATOR_STATE);
#else
ASM_MOV_REG_REG(emit->as, REG_GENERATOR_STATE, REG_PARENT_ARG_1);
#endif
// 将抛出值放入 LOCAL_IDX_EXC_VAL 槽,用于 yield/yield-from
#if N_X86
asm_x86_mov_arg_to_r32(emit->as, 1, REG_PARENT_ARG_2);
#endif
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_PARENT_ARG_2);
// 将 REG_FUN_TABLE 载入 mp_fun_table 指针,该指针在 const_table 中找到
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, LOCAL_IDX_FUN_OBJ(emit));
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_OBJ_FUN_BC_CONTEXT);
#if MICROPY_PERSISTENT_CODE_SAVE
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_TEMP0, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
#endif
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_TEMP0, fun_table_off);
} else {
// 本地变量和堆栈在 code_state 结构之后开始
emit->stack_start = emit->code_state_start + SIZEOF_CODE_STATE;
// 为 code_state 结构分配 C 栈空间,其中包括状态
ASM_ENTRY(emit->as, emit->stack_start + emit->n_state);
// 准备传入的参数以调用 mp_setup_code_state
#if N_X86
asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1);
asm_x86_mov_arg_to_r32(emit->as, 1, REG_PARENT_ARG_2);
asm_x86_mov_arg_to_r32(emit->as, 2, REG_PARENT_ARG_3);
asm_x86_mov_arg_to_r32(emit->as, 3, REG_PARENT_ARG_4);
#endif
// 将 REG_FUN_TABLE 载入 mp_fun_table 指针,该指针在 const_table 中找到
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONTEXT);
#if MICROPY_PERSISTENT_CODE_SAVE
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_QSTR_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_QSTR_TABLE);
#endif
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, OFFSETOF_MODULE_CONTEXT_OBJ_TABLE);
ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_FUN_TABLE, fun_table_off);
// 设置 code_state.fun_bc
ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1);
// 设置 code_state.n_state(仅在小端目标上有效,因为 n_state 是 uint16_t)
emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_N_STATE, emit->n_state, REG_ARG_1);
// 将 code_state 的地址放入第一个参数
ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, emit->code_state_start);
// 如果需要,复制接下来的 3 个参数
#if REG_ARG_2 != REG_PARENT_ARG_2
ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_PARENT_ARG_2);
#endif
#if REG_ARG_3 != REG_PARENT_ARG_3
ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_PARENT_ARG_3);
#endif
#if REG_ARG_4 != REG_PARENT_ARG_4
ASM_MOV_REG_REG(emit->as, REG_ARG_4, REG_PARENT_ARG_4);
#endif
// 调用 mp_setup_code_state 准备 code_state 结构
#if N_THUMB
asm_thumb_bl_ind(emit->as, MP_F_SETUP_CODE_STATE, ASM_THUMB_REG_R4);
#elif N_ARM
asm_arm_bl_ind(emit->as, MP_F_SETUP_CODE_STATE, ASM_ARM_REG_R4);
#else
ASM_CALL_IND(emit->as, MP_F_SETUP_CODE_STATE);
#endif
}
emit_native_global_exc_entry(emit);
// 仅当没有异常处理器时,将一些局部变量缓存到寄存器中
if (CAN_USE_REGS_FOR_LOCALS(emit)) {
for (int i = 0; i < MAX_REGS_FOR_LOCAL_VARS && i < scope->num_locals; ++i) {
ASM_MOV_REG_LOCAL(emit->as, reg_local_table[i], LOCAL_IDX_LOCAL_VAR(emit, i));
}
}
// 设置闭包变量的类型
for (mp_uint_t i = 0; i < scope->id_info_len; i++) {
id_info_t *id = &scope->id_info[i];
if (id->kind == ID_INFO_KIND_CELL) {
emit->local_vtype[id->local_num] = VTYPE_PYOBJ;
}
}
}
}
// 将字节写入代码信息
static inline void emit_native_write_code_info_byte(emit_t *emit, byte val) {
mp_asm_base_data(&emit->as->base, 1, val);
}
// 将 qstr 写入代码信息
static inline void emit_native_write_code_info_qstr(emit_t *emit, qstr qst) {
mp_encode_uint(&emit->as->base, mp_asm_base_get_cur_to_write_bytes, mp_emit_common_use_qstr(emit->emit_common, qst));
}
// 结束一个作用域遍历
static bool emit_native_end_pass(emit_t *emit) {
emit_native_global_exc_exit(emit);
if (!emit->do_viper_types) {
emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base);
emit->prelude_ptr_index = emit->emit_common->ct_cur_child;
size_t n_state = emit->n_state;
size_t n_exc_stack = 0; // 原生代码不需要异常栈
MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, emit->scope, emit_native_write_code_info_byte, emit);
size_t n_info = emit->n_info;
size_t n_cell = emit->n_cell;
MP_BC_PRELUDE_SIZE_ENCODE(n_info, n_cell, emit_native_write_code_info_byte, emit);
// 字节码前奏:源信息(函数和参数 qstrs)
size_t info_start = mp_asm_base_get_code_pos(&emit->as->base);
emit_native_write_code_info_qstr(emit, emit->scope->simple_name);
for (int i = 0; i < emit->scope->num_pos_args + emit->scope->num_kwonly_args; i++) {
qstr qst = MP_QSTR__star_;
for (int j = 0; j < emit->scope->id_info_len; ++j) {
id_info_t *id = &emit->scope->id_info[j];
if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) {
qst = id->qst;
break;
}
}
emit_native_write_code_info_qstr(emit, qst);
}
emit->n_info = mp_asm_base_get_code_pos(&emit->as->base) - info_start;
// 字节码前奏:初始化闭包变量
size_t cell_start = mp_asm_base_get_code_pos(&emit->as->base);
for (int i = 0; i < emit->scope->id_info_len; i++) {
id_info_t *id = &emit->scope->id_info[i];
if (id->kind == ID_INFO_KIND_CELL) {
assert(id->local_num <= 255);
mp_asm_base_data(&emit->as->base, 1, id->local_num); // 写入应转换为单元格的局部变量
}
}
emit->n_cell = mp_asm_base_get_code_pos(&emit->as->base) - cell_start;
}
ASM_END_PASS(emit->as);
// 检查堆栈大小是否恢复到零
assert(emit->stack_size == 0);
assert(emit->exc_stack_size == 0);
if (emit->pass == MP_PASS_EMIT) {
void *f = mp_asm_base_get_code(&emit->as->base);
mp_uint_t f_len = mp_asm_base_get_code_size(&emit->as->base);
mp_raw_code_t **children = emit