microPython的源码解析之 emitinlinethumb.c

MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.

microPython Python最小内核源码解析
这段代码是一个嵌入式汇编器的C语言实现,用于生成Thumb指令集的汇编代码。Thumb指令集是ARM处理器的一种16位指令集,它允许在单个16位或32位指令中执行操作,从而节省内存并提高代码密度。

#include <stdint.h> // 包含标准整数类型定义
#include <stdio.h> // 包含标准输入输出函数
#include <string.h> // 包含字符串操作函数
#include <stdarg.h> // 包含可变参数列表宏
#include <assert.h> // 包含断言宏

// 包含MicroPython特定的头文件
#include "py/emit.h"
#include "py/asmthumb.h"

// 如果定义了MICROPY_EMIT_INLINE_THUMB,则编译以下代码
#if MICROPY_EMIT_INLINE_THUMB

// 定义一个枚举类型pn_kind_t,包含所有可能的解析节点类型
typedef enum {
   
// 定义具有编译函数的规则
#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
#define DEF_RULE_NC(rule, kind, ...) PN_##rule,
    #include "py/grammar.h" // 包含MicroPython语法规则
#undef DEF_RULE
#undef DEF_RULE_NC
    PN_const_object, // 特殊的节点,用于表示一个常量Python对象
// 定义没有编译函数的规则
#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...) PN_##rule,
    #include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
} pn_kind_t;

// 定义一个结构体emit_inline_asm_t,用于存储内联汇编的上下文信息
struct _emit_inline_asm_t {
   
    asm_thumb_t as; // 存储Thumb汇编器的上下文
    uint16_t pass; // 当前编译通过的编号
    mp_obj_t *error_slot; // 存储错误信息的对象指针
    mp_uint_t max_num_labels; // 最大标签数量
    qstr *label_lookup; // 标签查找表
};

// 如果定义了MICROPY_DYNAMIC_COMPILER,则编译以下代码
#if MICROPY_DYNAMIC_COMPILER

// 检查是否可以在当前架构下使用浮点数
static inline bool emit_inline_thumb_allow_float(emit_inline_asm_t *emit) {
   
    return MP_NATIVE_ARCH_ARMV7EMSP <= mp_dynamic_compiler.native_arch
           && mp_dynamic_compiler.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP;
}

// 如果没有定义MICROPY_DYNAMIC_COMPILER,则使用预定义的宏
#else

static inline bool emit_inline_thumb_allow_float(emit_inline_asm_t *emit) {
   
    return MICROPY_EMIT_INLINE_THUMB_FLOAT;
}

#endif

// 定义一个函数,用于生成错误信息
static void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, mp_rom_error_text_t msg) {
   
    *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
}

// 定义一个函数,用于设置错误异常
static void emit_inline_thumb_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) {
   
    *emit->error_slot = exc;
}

// 定义一个函数,用于创建一个新的内联汇编上下文
emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels) {
   
    // 分配内存并初始化新的内联汇编上下文
    emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t);
    memset(&emit->as, 0, sizeof(emit->as));
    mp_asm_base_init(&emit->as.base, max_num_labels);
    emit->max_num_labels = max_num_labels;
    emit->label_lookup = m_new(qstr, max_num_labels);
    return emit;
}

// 定义一个函数,用于释放内联汇编上下文占用的内存
void emit_inline_thumb_free(emit_inline_asm_t *emit) {
   
    m_del(qstr, emit->label_lookup, emit->max_num_labels);
    mp_asm_base_deinit(&emit->as.base, false);
    m_del_obj(emit_inline_asm_t, emit);
}

// 定义一个函数,用于开始一个新的编译通过
static void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) {
   
    // 设置当前通过编号和错误槽,初始化标签查找表
    emit->pass = pass;
    emit->error_slot = error_slot;
    if (emit->pass == MP_PASS_CODE_SIZE) {
   
        memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr));
    }
    mp_asm_base_start_pass(&emit->as.base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE);
    asm_thumb_entry(&emit->as, 0);
}

// 定义一个函数,用于结束当前的编译通过
static void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) {
   
    // 退出Thumb汇编器并结束当前的编译通过
    asm_thumb_exit(&emit->as);
    asm_thumb_end_pass(&emit->as);
}

// 定义一个函数,用于计算参数的数量
static mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) {
   
    // 检查参数数量是否超过4个,并确保每个参数都是按顺序的寄存器r0到r3
    if (n_params > 4) {
   
        emit_inline_thumb_error_msg(emit, MP_ERROR_TEXT("can only have up to 4 parameters to Thumb assembly"));
        return 0;
    }
    for (mp_uint_t i = 0; i < n_params; i++) {
   
        if (!MP_PARSE_NODE_IS_ID(pn_params[i])) {
   
            emit_inline_thumb_error_msg(emit, MP_ERROR_TEXT("parameters must be registers in sequence r0 to r3"));
            return 0;
        }
        const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i]));
        if (!(strlen(p) == 2 && p[0] == 'r' && (mp_uint_t)p[1] == '0' + i)) {
   
            emit_inline_thumb_error_msg(emit, MP_ERROR_TEXT("parameters must be registers in sequence r0 to r3"));
            return 0;
        }
    }
    return n_params;
}

// 定义一个函数,用于标记标签
static bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) {
   
    assert(label_num < emit->max_num_labels); // 确保标签编号在范围内
    if (emit->pass == MP_PASS_CODE_SIZE) {
    // 在代码大小计算阶段检查重复标签
        // 遍历标签查找表,查找是否存在重复的标签
        for (uint i = 0; i < emit->max_num_labels; i++) {
   
            if (emit->label_lookup
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

openwin_top

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值