diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index 92f312b..3222b12 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -188,6 +188,7 @@ struct scc_ast_type { } record; struct { const char *name; + /// @brief 指向typedef的声明(可以间接找到typedef的指向的类型) scc_ast_decl_t *decl; } typedef_type; }; @@ -312,7 +313,9 @@ struct scc_ast_expr { // 复合字面量 struct { scc_ast_expr_t *base; + /// @brief 赋值语句的左值 scc_ast_expr_vec_t lhs_exprs; + /// @brief 赋值语句的右值 scc_ast_expr_vec_t rhs_exprs; } compound; // 字面量 @@ -429,10 +432,11 @@ struct scc_ast_decl { } param; // 结构体/联合/枚举声明 struct { + /// @brief 结构体/联合/枚举的字段 scc_ast_decl_vec_t fields; } record; - // typedef 声明 struct { + /// @brief 被 typedef 的类型 scc_ast_type_t *type; } typedef_decl; }; diff --git a/libs/ast2ir/include/scc_ast2ir.h b/libs/ast2ir/include/scc_ast2ir.h index af37a01..13de28f 100644 --- a/libs/ast2ir/include/scc_ast2ir.h +++ b/libs/ast2ir/include/scc_ast2ir.h @@ -19,13 +19,13 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx); void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, - scc_ast_translation_unit_t *tu); -void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl, + const scc_ast_translation_unit_t *tu); +void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, cbool is_global); -scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, - cbool is_lvalue); -void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt); +scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, + const scc_ast_expr_t *expr, cbool is_lvalue); +void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt); scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, - scc_ast_type_t *ast_type); + const scc_ast_type_t *ast_type); #endif /* __SCC_AST2IR_H__ */ diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index 62adf2d..e0fe233 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -5,7 +5,7 @@ #include static scc_ir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx, - scc_ast_type_t *ast_type) { + const scc_ast_type_t *ast_type) { scc_abi_type_layout_t layout; // 映射内置类型 ctx->abi->compute_type_layout(ctx->abi, ast_type, &layout); @@ -37,8 +37,100 @@ static inline void parse_lexme2const_int(const char *lexme, value->int64 = int_lit; } +// 辅助函数:计算数组实际长度(如果原长度为0) +static void resolve_array_length(scc_ast2ir_ctx_t *ctx, + const scc_ir_type_t *orig_array_type, + scc_ir_type_t *resolved_array_type, + const scc_ast_expr_t *init_expr) { + *resolved_array_type = *orig_array_type; // 拷贝 + Assert(orig_array_type->tag == SCC_IR_TYPE_ARRAY); + if (orig_array_type->data.array.len != 0) + return; // 长度已知,无需推断 + + usize new_len = 0; + switch (init_expr->base.type) { + case SCC_AST_EXPR_STRING_LITERAL: + // 字符串字面量:长度 = 字符串字符数 + 1('\0') + // TODO: L"" \n \r 计算 暂不支持 + new_len = scc_strlen(init_expr->literal.lexme) + 1; + break; + case SCC_AST_EXPR_COMPOUND: { + // 复合初始化:元素个数 = 初始化列表长度 + scc_vec_foreach(init_expr->compound.lhs_exprs, i) { + scc_ast_expr_t *elem = scc_vec_at(init_expr->compound.lhs_exprs, i); + // TODO: 支持嵌套的多维数组初始化(递归) + // 这里简化:只统计顶层元素个数,假设是一维数组 + new_len++; + } + break; + } + default: + Panic("unsupported initializer for zero-length array"); + } + resolved_array_type->data.array.len = new_len; +} + +// 辅助函数:生成数组初始化代码 +static void emit_array_initialization(scc_ast2ir_ctx_t *ctx, + scc_ir_value_ref_t array_ptr, + const scc_ir_type_t *array_type, + const scc_ast_expr_t *init_expr) { + Assert(array_type->tag == SCC_IR_TYPE_ARRAY); + scc_ir_type_ref_t elem_type_ref = array_type->data.array.base; + const scc_ir_type_t *elem_type = + scc_ir_module_get_type(ctx->builder.ctx.module, elem_type_ref); + usize array_len = array_type->data.array.len; + + // 字符串字面量初始化:直接 memcpy + if (init_expr->base.type == SCC_AST_EXPR_STRING_LITERAL) { + scc_ir_value_ref_t str_val = scc_ast2ir_expr(ctx, init_expr, false); + scc_ir_const_int_t len_const = {.int64 = array_len}; + scc_ir_value_ref_t len_ref = scc_ir_builder_const_int( + &ctx->builder, scc_ir_builder_type_u64(&ctx->builder), len_const); + scc_ir_builder_builtin_memcpy(&ctx->builder, array_ptr, str_val, + len_ref); + return; + } + + // 复合初始化:逐个元素 store + if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) { + Panic("unsupported initializer for array"); + } + + // 遍历初始化列表 + usize idx = 0; + scc_vec_foreach(init_expr->compound.rhs_exprs, i) { + scc_ast_expr_t *elem_expr = + scc_vec_at(init_expr->compound.rhs_exprs, i); + Assert(elem_expr != nullptr); + if (idx >= array_len) + break; // 防止溢出 + + // 生成元素地址:array_ptr + idx * elem_size + scc_ir_value_ref_t idx_val = scc_ir_builder_const_int( + &ctx->builder, scc_ir_builder_type_u64(&ctx->builder), + (scc_ir_const_int_t){.int64 = idx}); + scc_ir_value_ref_t elem_ptr = + scc_ir_builder_get_elem_ptr(&ctx->builder, array_ptr, idx_val); + + // 递归处理:如果元素本身是数组且初始化表达式是复合初始化,需要嵌套处理 + if (elem_type->tag == SCC_IR_TYPE_ARRAY && + elem_expr->base.type == SCC_AST_EXPR_COMPOUND) { + // 递归调用自身,但注意 elem_ptr 已经是子数组的首地址 + emit_array_initialization(ctx, elem_ptr, elem_type, elem_expr); + } else { + // 标量元素:计算右值并 store + scc_ir_value_ref_t val = scc_ast2ir_expr(ctx, elem_expr, false); + scc_ir_builder_store(&ctx->builder, elem_ptr, val); + } + idx++; + } + // 如果初始化列表元素少于数组长度,剩余元素默认零初始化(C 标准要求) + // 这里简单忽略,实际可生成 memset 循环,但为简化暂不处理 +} + scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, - scc_ast_type_t *ast_type) { + const scc_ast_type_t *ast_type) { if (ctx == nullptr || ast_type == nullptr) { LOG_ERROR("args is nullptr"); return 0; @@ -104,6 +196,7 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, scc_ir_type_init(&ir_type, ast_type->base.type == SCC_AST_TYPE_STRUCT ? SCC_IR_TYPE_STRUCT : SCC_IR_TYPE_UNION); + Assert(ast_type->record.decl != nullptr); scc_vec_foreach(ast_type->record.decl->record.fields, i) { scc_ast_decl_t *decl_field = scc_vec_at(ast_type->record.decl->record.fields, i); @@ -119,7 +212,9 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, ctx, &(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN, .builtin = SCC_AST_BUILTIN_TYPE_INT}); case SCC_AST_TYPE_TYPEDEF: - return 0; + // TODO maybe using cache + return scc_ast2ir_type(ctx, + ast_type->typedef_type.decl->typedef_decl.type); default: LOG_FATAL("Unsupported AST type: %d", ast_type->base.type); return 0; @@ -128,7 +223,7 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, } scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, - scc_ast_expr_t *expr, + const scc_ast_expr_t *expr, scc_ir_value_ref_t lhs, scc_ir_value_ref_t rhs) { // scc_ir_bblock_ref_t start_block = @@ -220,7 +315,8 @@ scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, * @param expr * @return scc_ir_value_ref_t */ -scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, +scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, + const scc_ast_expr_t *expr, cbool is_lvalue) { if (ctx == nullptr || expr == nullptr) { LOG_ERROR("args is nullptr"); @@ -466,7 +562,8 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, break; case SCC_AST_EXPR_PTR_MEMBER: break; - // SCC_AST_EXPR_CAST, // 类型转换 + case SCC_AST_EXPR_CAST: + break; case SCC_AST_EXPR_SIZE_OF: { scc_ir_const_int_t val; // FIXME @@ -577,7 +674,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, * @param ctx * @param stmt */ -void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) { +void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { if (stmt == nullptr) { return; } @@ -757,7 +854,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) { * @param ctx * @param decl */ -void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl, +void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, cbool is_global) { if (ctx == nullptr || decl == nullptr) { LOG_ERROR("Invalid argument"); @@ -766,58 +863,64 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl, switch (decl->base.type) { case SCC_AST_DECL_VAR: { - // 转换类型 - scc_ir_type_ref_t ir_type_ref = scc_ast2ir_type(ctx, decl->var.type); + // 1. 获取原始类型(可能数组长度为0) + scc_ir_type_ref_t orig_type_ref = scc_ast2ir_type(ctx, decl->var.type); + // 借用指针并拷贝类型(避免悬空) + const scc_ir_type_t *orig_type; + SCC_IR_BUILDER_BEGIN_BORROW( + &ctx->builder, orig_type, + scc_ir_module_get_type(ctx->builder.ctx.module, orig_type_ref)); + scc_ir_type_t final_type_desc = *orig_type; + SCC_IR_BUILDER_END_BORROW(&ctx->builder); - // 创建分配节点 - scc_ir_value_ref_t alloc_val_node = SCC_IR_REF_nullptr; + // 2. 如果是未知长度数组且有初始化,解析实际长度 + scc_ir_type_ref_t final_type_ref = orig_type_ref; + if (decl->var.init && final_type_desc.tag == SCC_IR_TYPE_ARRAY && + final_type_desc.data.array.len == 0) { + scc_ir_type_t tmp_type_desc; + resolve_array_length(ctx, &final_type_desc, &tmp_type_desc, + decl->var.init); + final_type_desc = tmp_type_desc; + final_type_ref = + scc_ir_builder_type(&ctx->builder, &final_type_desc); + // 此时 final_type_desc 中的长度已经确定 + } + + // 3. 分配变量(栈或全局) + scc_ir_value_ref_t alloc_val_node; if (is_global) { - // alloc_val_node = scc_ir_builder_global_alloca( - // &ctx->builder, ir_type_ref, decl->name); + // 全局变量:需要生成全局分配,当前代码暂未实现,保留 TODO + // alloc_val_node = scc_ir_builder_global_alloca(&ctx->builder, + // final_type_ref, decl->name); + // scc_vec_push(builder->cprog->global_vals, alloc_val_node); + // 这里先返回,后续补充 return; } else { - alloc_val_node = - scc_ir_builder_alloca(&ctx->builder, ir_type_ref, decl->name); + alloc_val_node = scc_ir_builder_alloca(&ctx->builder, + final_type_ref, decl->name); } - Assert(alloc_val_node != SCC_IR_REF_nullptr); - scc_hashtable_set(&ctx->ast2ir_cache, decl, (void *)(usize)alloc_val_node); - // 如果有初始化表达式 - if (!decl->var.init) { - break; - } - scc_ir_value_ref_t init_val_node = - scc_ast2ir_expr(ctx, decl->var.init, false); - Assert(init_val_node != SCC_IR_REF_nullptr); - - // FIXME array auto calucate size - scc_ir_type_t *ir_type = - scc_ir_module_get_type(ctx->builder.ctx.module, ir_type_ref); - if (ir_type->tag == SCC_IR_TYPE_ARRAY) { - if (ir_type->data.array.len == 0) { - scc_ast_expr_t *init_expr = decl->var.init; - if (init_expr->base.type == SCC_AST_EXPR_COMPOUND) { - Panic( - "TODO: init_expr->base.type == SCC_AST_EXPR_COMPOUND"); - } else if (init_expr->base.type == - SCC_AST_EXPR_STRING_LITERAL) { - ir_type->data.array.len = - scc_strlen(init_expr->literal.lexme) + 1; - - scc_ir_const_int_t len = {.int64 = ir_type->data.array.len}; - scc_ir_value_ref_t len_ref = scc_ir_builder_const_int( - &ctx->builder, scc_ir_builder_type_u64(&ctx->builder), - len); - scc_ir_builder_builtin_memcpy(&ctx->builder, alloc_val_node, - init_val_node, len_ref); - } else { - Panic("unknown init expr in array decl"); - } + // 4. 处理初始化 + if (decl->var.init) { + // 再次借用 final_type 以判断是否为数组 + const scc_ir_type_t *final_type; + SCC_IR_BUILDER_BEGIN_BORROW( + &ctx->builder, final_type, + scc_ir_module_get_type(ctx->builder.ctx.module, + final_type_ref)); + scc_ir_type_t type = *final_type; + SCC_IR_BUILDER_END_BORROW(&ctx->builder); + if (type.tag == SCC_IR_TYPE_ARRAY) { + emit_array_initialization(ctx, alloc_val_node, &type, + decl->var.init); + } else { + // 标量类型 + scc_ir_value_ref_t init_val = + scc_ast2ir_expr(ctx, decl->var.init, false); + scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val); } - } else { - scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node); } break; } @@ -881,8 +984,8 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl, .record.name = decl->name, }; scc_ir_type_ref_t type_ref = scc_ast2ir_type(ctx, &type); - scc_ir_builder_global_alloca(&ctx->builder, type_ref, - SCC_IR_REF_nullptr); + // scc_ir_builder_global_alloca(&ctx->builder, type_ref, + // SCC_IR_REF_nullptr); break; case SCC_AST_DECL_ENUM: scc_ir_const_int_t val; @@ -910,7 +1013,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl, } void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, - scc_ast_translation_unit_t *tu) { + const scc_ast_translation_unit_t *tu) { Assert(ctx != nullptr && tu != nullptr); scc_vec_foreach(tu->declarations, i) { diff --git a/libs/ir/include/ir_builder.h b/libs/ir/include/ir_builder.h index 28fd108..2105033 100644 --- a/libs/ir/include/ir_builder.h +++ b/libs/ir/include/ir_builder.h @@ -20,8 +20,41 @@ struct scc_ir_builder { scc_ir_ctx_t ctx; ///< 核心上下文 scc_ir_func_ref_t current_func; ///< 当前正在构建的函数 scc_ir_bblock_ref_t current_bblock; ///< 当前基本块 +#ifndef SCC_NO_DEBUG + int borrow_depth; + const char *dbg_file; + int dbg_line; +#endif }; +#ifndef SCC_NO_DEBUG +#define SCC_IR_BUILDER_BEGIN_BORROW(builder, ptr_var, ptr_expr) \ + do { \ + (builder)->borrow_depth++; \ + (builder)->dbg_file = __FILE__; \ + (builder)->dbg_line = __LINE__; \ + ptr_var = (ptr_expr); \ + } while (0) + +#define SCC_IR_BUILDER_END_BORROW(builder) \ + do { \ + (builder)->borrow_depth--; \ + } while (0) + +#define SCC_IR_BUILDER_CHECK_NO_BORROW(builder) \ + do { \ + if ((builder)->borrow_depth != 0) { \ + Panic("IR Builder: attempt to reallocate while borrowed at %s:%d", \ + (builder)->dbg_file, (builder)->dbg_line); \ + } \ + } while (0) +#else +#define SCC_IR_BUILDER_BEGIN_BORROW(builder, ptr_var, ptr_expr) \ + ptr_var = (ptr_expr) +#define SCC_IR_BUILDER_END_BORROW(builder) ((void)0) +#define SCC_IR_BUILDER_CHECK_NO_BORROW(builder) ((void)0) +#endif + /** * @brief 初始化 IR 构建器 */ @@ -110,52 +143,8 @@ scc_ir_builder_const_int(scc_ir_builder_t *builder, scc_ir_type_ref_t type, return scc_ir_module_add_value(&builder->cprog->module, &value); } -static inline scc_ir_value_ref_t -scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str, - usize len) { - scc_ir_type_ref_t u8_type = scc_ir_builder_type_u8(builder); - scc_ir_type_t array_type = { - .tag = SCC_IR_TYPE_ARRAY, - .data.array.base = u8_type, - .data.array.len = len - 1, // 包含 nullptr 结尾 - }; - scc_ir_type_ref_t array_type_ref = - scc_ir_ctx_get_type(&builder->ctx, &array_type); - - // 5. 创建聚合节点 - scc_ir_value_t const_array_value = { - .tag = SCC_IR_VALUE_TAG_CONST_ARRAY, - .type = array_type_ref, - .data.const_array.base_type = u8_type, - }; - char *buff = scc_malloc(len - 1); - Assert(buff); - // FIXME content to real string - for (usize i = 1; i < len - 1; i++) { - buff[i - 1] = str[i]; - } - buff[len - 2] = '\0'; - scc_vec_unsafe_from_buffer(const_array_value.data.const_array.fields, - (u8 *)buff, len - 1); - scc_ir_value_ref_t const_array_ref = - scc_ir_module_add_value(builder->ctx.module, &const_array_value); - Assert(const_array_ref != SCC_IR_REF_nullptr); - - // 3. 创建全局变量节点,类型为指针,初始值指向常量数组 - scc_ir_value_ref_t global_value_ref = - scc_ir_builder_global_alloca(builder, array_type_ref, const_array_ref); - // scc_hashtable_insert(builder); - - scc_ir_value_ref_t pointer_to_global_value = scc_ir_module_add_value( - builder->ctx.module, - &(scc_ir_value_t){ - .tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR, - .data.get_elem_ptr.src_addr = global_value_ref, - .data.get_elem_ptr.index = SCC_IR_VALUE_TAG_NULLPTR, - }); - scc_ir_builder_add_instr(builder, pointer_to_global_value); - return pointer_to_global_value; -} +scc_ir_value_ref_t scc_ir_builder_const_string(scc_ir_builder_t *builder, + const char *str, usize len); /** * @brief 开始构建函数 diff --git a/libs/ir/src/ir_builder.c b/libs/ir/src/ir_builder.c index a4182af..65f2d55 100644 --- a/libs/ir/src/ir_builder.c +++ b/libs/ir/src/ir_builder.c @@ -10,6 +10,11 @@ void scc_ir_builder_init(scc_ir_builder_t *builder, scc_ir_cprog_t *cprog) { builder->cprog = cprog; scc_ir_ctx_init(&builder->ctx, GET_MODULE(builder)); +#ifndef SCC_NO_DEBUG + builder->borrow_depth = 0; + builder->dbg_file = nullptr; + builder->dbg_line = 0; +#endif } void scc_ir_builder_drop(scc_ir_builder_t *builder) { @@ -19,6 +24,7 @@ void scc_ir_builder_drop(scc_ir_builder_t *builder) { scc_ir_func_ref_t scc_ir_builder_func(scc_ir_builder_t *builder, scc_ir_type_ref_t type_ref, const char *name) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_func_ref_t func_ref = scc_ir_ctx_declare_func(&builder->ctx, type_ref, name); scc_vec_push(builder->cprog->func_decls, func_ref); @@ -27,43 +33,108 @@ scc_ir_func_ref_t scc_ir_builder_func(scc_ir_builder_t *builder, scc_ir_type_ref_t scc_ir_builder_type(scc_ir_builder_t *builder, const scc_ir_type_t *type_desc) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); return scc_ir_ctx_get_type(&builder->ctx, type_desc); } +scc_ir_value_ref_t scc_ir_builder_const_string(scc_ir_builder_t *builder, + const char *str, usize len) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); + scc_ir_type_ref_t u8_type = scc_ir_builder_type_u8(builder); + scc_ir_type_t array_type = { + .tag = SCC_IR_TYPE_ARRAY, + .data.array.base = u8_type, + .data.array.len = len - 1, // 包含 nullptr 结尾 + }; + scc_ir_type_ref_t array_type_ref = + scc_ir_ctx_get_type(&builder->ctx, &array_type); + + // 5. 创建聚合节点 + scc_ir_value_t const_array_value = { + .tag = SCC_IR_VALUE_TAG_CONST_ARRAY, + .type = array_type_ref, + .data.const_array.base_type = u8_type, + }; + char *buff = scc_malloc(len - 1); + Assert(buff); + // FIXME content to real string + for (usize i = 1; i < len - 1; i++) { + buff[i - 1] = str[i]; + } + buff[len - 2] = '\0'; + scc_vec_unsafe_from_buffer(const_array_value.data.const_array.fields, + (u8 *)buff, len - 1); + scc_ir_value_ref_t const_array_ref = + scc_ir_module_add_value(builder->ctx.module, &const_array_value); + Assert(const_array_ref != SCC_IR_REF_nullptr); + + // 3. 创建全局变量节点,类型为指针,初始值指向常量数组 + scc_ir_value_ref_t global_value_ref = + scc_ir_builder_global_alloca(builder, array_type_ref, const_array_ref); + // scc_hashtable_insert(builder); + + scc_ir_value_ref_t pointer_to_global_value = scc_ir_module_add_value( + builder->ctx.module, + &(scc_ir_value_t){ + .tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR, + .data.get_elem_ptr.src_addr = global_value_ref, + .data.get_elem_ptr.index = SCC_IR_VALUE_TAG_NULLPTR, + }); + scc_ir_builder_add_instr(builder, pointer_to_global_value); + return pointer_to_global_value; +} + void scc_ir_builder_begin_func(scc_ir_builder_t *builder, scc_ir_func_ref_t func_ref, const char **param_names) { - // 创建函数并设置为当前函数 + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); builder->current_func = func_ref; - scc_ir_func_t *func_ptr = - scc_ir_module_get_func(GET_MODULE(builder), func_ref); - scc_ir_type_t *func_type = - scc_ir_module_get_type(GET_MODULE(builder), func_ptr->type); + // 借用 func_ptr 和 func_type 以获取参数类型列表 + scc_ir_func_t *func_ptr = nullptr; + scc_ir_type_t *func_type = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, func_ptr, + scc_ir_module_get_func(GET_MODULE(builder), func_ref)); + SCC_IR_BUILDER_BEGIN_BORROW( + builder, func_type, + scc_ir_module_get_type(GET_MODULE(builder), func_ptr->type)); if (func_type == nullptr || func_type->tag != SCC_IR_TYPE_FUNC) { LOG_ERROR("Invalid function type"); + SCC_IR_BUILDER_END_BORROW(builder); // func_type + SCC_IR_BUILDER_END_BORROW(builder); // func_ptr return; } - if (func_ptr == nullptr) { LOG_ERROR("Invalid function reference"); + SCC_IR_BUILDER_END_BORROW(builder); // func_type + SCC_IR_BUILDER_END_BORROW(builder); // func_ptr return; } - if (scc_vec_size(func_ptr->bblocks) != 0 || scc_vec_size(func_ptr->params) != 0) { LOG_FATAL("Multiple function definitions"); + SCC_IR_BUILDER_END_BORROW(builder); // func_type + SCC_IR_BUILDER_END_BORROW(builder); // func_ptr return; } scc_ir_type_ref_vec_t params = func_type->data.function.params; - func_type = nullptr; - scc_vec_foreach(params, i) { - scc_ir_type_ref_t param_type = scc_vec_at(params, i); + // 释放借用,因为下面要调用 add_value(可能 realloc) + SCC_IR_BUILDER_END_BORROW(builder); // func_type + SCC_IR_BUILDER_END_BORROW(builder); // func_ptr + // 预先分配所有参数值(临时数组,避免在循环中 push 到 func_ptr->params 时 + // func_ptr 失效) + usize param_count = scc_vec_size(params); + scc_ir_value_ref_t *param_refs = + scc_malloc(sizeof(scc_ir_value_ref_t) * param_count); + + for (usize i = 0; i < param_count; i++) { + scc_ir_type_ref_t param_type = scc_vec_at(params, i); scc_ir_value_t param_node = {0}; - param_node.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF; // 参数节点标记 + param_node.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF; param_node.type = scc_ir_module_add_type( GET_MODULE(builder), &(scc_ir_type_t){.tag = SCC_IR_TYPE_PTR, @@ -71,36 +142,48 @@ void scc_ir_builder_begin_func(scc_ir_builder_t *builder, param_node.name = param_names ? param_names[i] : nullptr; param_node.data.arg_ref.idx = i; scc_vec_init(param_node.used_by); - - scc_ir_value_ref_t param_ref = + param_refs[i] = scc_ir_module_add_value(GET_MODULE(builder), ¶m_node); - scc_vec_push(func_ptr->params, param_ref); } - return; + + // 重新借用 func_ptr 以添加参数到函数 + SCC_IR_BUILDER_BEGIN_BORROW( + builder, func_ptr, + scc_ir_module_get_func(GET_MODULE(builder), func_ref)); + for (usize i = 0; i < param_count; i++) { + scc_vec_push(func_ptr->params, param_refs[i]); + } + SCC_IR_BUILDER_END_BORROW(builder); // func_ptr } void scc_ir_builder_end_func(scc_ir_builder_t *builder) { - scc_ir_func_t *func_ptr = - scc_ir_module_get_func(GET_MODULE(builder), builder->current_func); + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); + scc_ir_func_t *func_ptr = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, func_ptr, + scc_ir_module_get_func(GET_MODULE(builder), builder->current_func)); if (func_ptr == nullptr) { LOG_FATAL("Invalid function reference"); + SCC_IR_BUILDER_END_BORROW(builder); return; } if (scc_vec_size(func_ptr->bblocks) == 0) { - // FIXME scc_vec_push(builder->cprog->func_decls, builder->current_func); } else { scc_vec_push(builder->cprog->func_defs, builder->current_func); } + SCC_IR_BUILDER_END_BORROW(builder); builder->current_func = 0; } scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder) { + // 只读操作,无需检查借用 return builder->current_func; } scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder, const char *label) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_bblock_t bblock = {0}; if (label) { bblock.label = label; @@ -109,27 +192,33 @@ scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder, scc_ir_bblock_ref_t bblock_ref = scc_ir_module_add_bblock(GET_MODULE(builder), &bblock); - scc_ir_func_t *current_func = - scc_ir_module_get_func(GET_MODULE(builder), builder->current_func); + // 将基本块添加到当前函数 + scc_ir_func_t *current_func = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, current_func, + scc_ir_module_get_func(GET_MODULE(builder), builder->current_func)); if (current_func) { scc_vec_push(current_func->bblocks, bblock_ref); } + SCC_IR_BUILDER_END_BORROW(builder); return bblock_ref; } scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder, const char *label) { - + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); builder->current_bblock = scc_ir_builder_bblock(builder, label); return builder->current_bblock; } void scc_ir_builder_end_bblock(scc_ir_builder_t *builder) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); builder->current_bblock = 0; } void scc_ir_builder_set_current_bblock(scc_ir_builder_t *builder, scc_ir_bblock_ref_t bblock) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); builder->current_bblock = bblock; } @@ -139,19 +228,23 @@ scc_ir_func_ref_t scc_ir_builder_current_bblock(scc_ir_builder_t *builder) { void scc_ir_builder_add_instr(scc_ir_builder_t *builder, scc_ir_value_ref_t instr) { - scc_ir_bblock_t *current_bblock = - scc_ir_module_get_bblock(GET_MODULE(builder), builder->current_bblock); + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); + scc_ir_bblock_t *current_bblock = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, current_bblock, + scc_ir_module_get_bblock(GET_MODULE(builder), builder->current_bblock)); if (current_bblock) { scc_vec_push(current_bblock->instrs, instr); } else { LOG_ERROR("Current basic block is not set"); } + SCC_IR_BUILDER_END_BORROW(builder); } scc_ir_value_ref_t scc_ir_builder_global_alloca(scc_ir_builder_t *builder, scc_ir_type_ref_t type, scc_ir_value_ref_t value) { - // FIXME MAYBE MEMORY LEAK + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); char *name = scc_malloc(32); scc_ir_value_ref_t global_value_ref = scc_ir_module_add_value( builder->ctx.module, &(scc_ir_value_t){ @@ -161,7 +254,6 @@ scc_ir_value_ref_t scc_ir_builder_global_alloca(scc_ir_builder_t *builder, .data.global_alloc.value = value, }); scc_snprintf(name, 32, "$G%u", global_value_ref); - scc_vec_push(builder->cprog->global_vals, global_value_ref); return global_value_ref; } @@ -169,6 +261,7 @@ scc_ir_value_ref_t scc_ir_builder_global_alloca(scc_ir_builder_t *builder, scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder, scc_ir_type_ref_t type, const char *name) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t alloc_node = {0}; alloc_node.tag = SCC_IR_VALUE_TAG_ALLOC; alloc_node.type = scc_ir_module_add_type( @@ -178,7 +271,6 @@ scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &alloc_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } @@ -187,6 +279,7 @@ scc_ir_value_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder, scc_ir_type_ref_t type, const char *name, usize arg_idx) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t value = {0}; value.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF; value.type = type; @@ -195,31 +288,36 @@ scc_ir_value_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &value); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder, scc_ir_value_ref_t target) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t load_node = {0}; load_node.tag = SCC_IR_VALUE_TAG_LOAD; load_node.data.load.target = target; - // 设置类型为指针指向的类型 - scc_ir_value_t *ptr_node = - scc_ir_module_get_value(GET_MODULE(builder), target); + // 借用 ptr_node 和 ptr_type 获取类型信息 + scc_ir_value_t *ptr_node = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, ptr_node, + scc_ir_module_get_value(GET_MODULE(builder), target)); if (ptr_node) { - scc_ir_type_t *ptr_type = - scc_ir_module_get_type(GET_MODULE(builder), ptr_node->type); + scc_ir_type_t *ptr_type = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, ptr_type, + scc_ir_module_get_type(GET_MODULE(builder), ptr_node->type)); if (ptr_type && ptr_type->tag == SCC_IR_TYPE_PTR) { load_node.type = ptr_type->data.pointer.base; } + SCC_IR_BUILDER_END_BORROW(builder); // ptr_type } + SCC_IR_BUILDER_END_BORROW(builder); // ptr_node scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &load_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } @@ -227,6 +325,7 @@ scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder, scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder, scc_ir_value_ref_t target, scc_ir_value_ref_t value) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); Assert(target != SCC_IR_REF_nullptr && value != SCC_IR_REF_nullptr); scc_ir_value_t store_node = {0}; store_node.tag = SCC_IR_VALUE_TAG_STORE; @@ -235,7 +334,6 @@ scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &store_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } @@ -243,35 +341,44 @@ scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder, scc_ir_value_ref_t scc_ir_builder_get_elem_ptr(scc_ir_builder_t *builder, scc_ir_value_ref_t target, scc_ir_value_ref_t index) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t get_ptr_node = {0}; get_ptr_node.tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR; get_ptr_node.data.get_elem_ptr.src_addr = target; get_ptr_node.data.get_elem_ptr.index = index; - // 类型应与源地址相同(都是指针) - scc_ir_type_t *type = - scc_ir_module_get_type_by_value(GET_MODULE(builder), target); - Assert(type != nullptr); - if (type->tag == SCC_IR_TYPE_PTR) { - scc_ir_type_t *base_type = scc_ir_module_get_type( - GET_MODULE(builder), type->data.pointer.base); + // 借用类型信息 + scc_ir_type_t *type_ref = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, type_ref, + scc_ir_module_get_type_by_value(GET_MODULE(builder), target)); + Assert(type_ref != nullptr); + scc_ir_type_t type = *type_ref; // 拷贝一份,避免后续借用 + SCC_IR_BUILDER_END_BORROW(builder); // type_ref + + if (type.tag == SCC_IR_TYPE_PTR) { + scc_ir_type_t *base_type = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, base_type, + scc_ir_module_get_type(GET_MODULE(builder), + type_ref->data.pointer.base)); if (base_type->tag == SCC_IR_TYPE_ARRAY) { - // FIXME GEP maybe multiple levels - get_ptr_node.type = scc_ir_builder_type( - builder, &(scc_ir_type_t){ - .tag = SCC_IR_TYPE_PTR, - .data.pointer.base = base_type->data.array.base, - }); + scc_ir_type_t type = (scc_ir_type_t){ + .tag = SCC_IR_TYPE_PTR, + .data.pointer.base = base_type->data.array.base, + }; + SCC_IR_BUILDER_END_BORROW(builder); // base_type + get_ptr_node.type = scc_ir_builder_type(builder, &type); } else { - get_ptr_node.type = scc_ir_builder_type(builder, type); + SCC_IR_BUILDER_END_BORROW(builder); // base_type + get_ptr_node.type = scc_ir_builder_type(builder, &type); } } else { - get_ptr_node.type = scc_ir_builder_type(builder, type); + get_ptr_node.type = scc_ir_builder_type(builder, &type); } scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &get_ptr_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } @@ -280,22 +387,24 @@ scc_ir_value_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder, scc_ir_op_type_t op, scc_ir_value_ref_t lhs, scc_ir_value_ref_t rhs) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t binop_node = {0}; binop_node.tag = SCC_IR_VALUE_TAG_OP; binop_node.data.op.op = op; binop_node.data.op.lhs = lhs; binop_node.data.op.rhs = rhs; - // 类型通常与操作数相同(对于算术运算) - scc_ir_value_t *lhs_node = - scc_ir_module_get_value(GET_MODULE(builder), lhs); + // 借用 lhs_node 获取类型 + scc_ir_value_t *lhs_node = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, lhs_node, scc_ir_module_get_value(GET_MODULE(builder), lhs)); if (lhs_node) { binop_node.type = lhs_node->type; } + SCC_IR_BUILDER_END_BORROW(builder); // lhs_node scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &binop_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } @@ -304,34 +413,29 @@ scc_ir_value_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder, scc_ir_op_type_t op, scc_ir_value_ref_t lhs, scc_ir_value_ref_t rhs) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t cmp_node = {0}; cmp_node.tag = SCC_IR_VALUE_TAG_OP; cmp_node.data.op.op = op; cmp_node.data.op.lhs = lhs; cmp_node.data.op.rhs = rhs; - - // 比较操作的结果通常是布尔值 - cmp_node.type = - 0; // FIXME scc_ir_module_get_builtin_i32(GET_MODULE(builder)); + cmp_node.type = 0; // FIXME scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &cmp_node); - - // 添加到当前基本块 scc_ir_builder_add_instr(builder, value_ref); - return value_ref; } scc_ir_value_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder, scc_ir_bblock_ref_t target) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t jump_node = {0}; jump_node.tag = SCC_IR_VALUE_TAG_JUMP; jump_node.data.jump.target_bblock = target; scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &jump_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } @@ -340,6 +444,7 @@ scc_ir_value_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder, scc_ir_value_ref_t cond, scc_ir_bblock_ref_t true_target, scc_ir_bblock_ref_t false_target) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t branch_node = {0}; branch_node.tag = SCC_IR_VALUE_TAG_BRANCH; branch_node.data.branch.cond = cond; @@ -348,7 +453,6 @@ scc_ir_value_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder, scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &branch_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } @@ -357,6 +461,7 @@ scc_ir_value_ref_t scc_ir_builder_call(scc_ir_builder_t *builder, scc_ir_func_ref_t callee, const scc_ir_value_ref_t *args, usize arg_count) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t call_node = {0}; call_node.tag = SCC_IR_VALUE_TAG_CALL; call_node.data.call.callee = callee; @@ -366,45 +471,50 @@ scc_ir_value_ref_t scc_ir_builder_call(scc_ir_builder_t *builder, scc_vec_push(call_node.data.call.args, args[i]); } - // 设置返回类型为被调用函数的返回类型 - scc_ir_func_t *callee_func = - scc_ir_module_get_func(GET_MODULE(builder), callee); + // 借用 callee_func 和 func_type 获取返回类型 + scc_ir_func_t *callee_func = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, callee_func, + scc_ir_module_get_func(GET_MODULE(builder), callee)); if (callee_func) { - scc_ir_type_t *func_type = - scc_ir_module_get_type(GET_MODULE(builder), callee_func->type); + scc_ir_type_t *func_type = nullptr; + SCC_IR_BUILDER_BEGIN_BORROW( + builder, func_type, + scc_ir_module_get_type(GET_MODULE(builder), callee_func->type)); if (func_type && func_type->tag == SCC_IR_TYPE_FUNC) { call_node.type = func_type->data.function.ret_type; } + SCC_IR_BUILDER_END_BORROW(builder); // func_type } + SCC_IR_BUILDER_END_BORROW(builder); // callee_func scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &call_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } scc_ir_value_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder, scc_ir_value_ref_t value) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t ret_node = {0}; ret_node.tag = SCC_IR_VALUE_TAG_RET; ret_node.data.ret.ret_val = value; scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &ret_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } scc_ir_value_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder) { + SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t ret_node = {0}; ret_node.tag = SCC_IR_VALUE_TAG_RET; - ret_node.data.ret.ret_val = 0; // 无返回值 + ret_node.data.ret.ret_val = 0; scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &ret_node); - scc_ir_builder_add_instr(builder, value_ref); return value_ref; } diff --git a/libs/ir2mcode/src/ir2amd64.c b/libs/ir2mcode/src/ir2amd64.c index 8d7c6af..d33f4f4 100644 --- a/libs/ir2mcode/src/ir2amd64.c +++ b/libs/ir2mcode/src/ir2amd64.c @@ -328,7 +328,7 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, } } else { // TODO - parse_value(ctx, value->data.get_elem_ptr.index, patches); + // parse_value(ctx, value->data.get_elem_ptr.index, patches); scc_reg_loc_t src_loc; scc_reg_loc_t idx_loc; @@ -337,8 +337,21 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, src_loc.kind = SCC_REG_KIND_STACK_ADDR; load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX); load_value_to_reg(ctx, &idx_loc, SCC_AMD64_RDX); + + // 获取 src_addr 所指向的类型的元素大小 + scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value( + GET_MODULE(ctx), value->data.get_elem_ptr.src_addr); + scc_ir_type_t *base_type = scc_ir_module_get_type( + GET_MODULE(ctx), ptr_type->data.pointer.base); + scc_ir_type_t ir_type = *base_type; + if (ir_type.tag == SCC_IR_TYPE_ARRAY) { + ir_type.tag = SCC_IR_TYPE_PTR; + } + int elem_size = scc_ir2mcode_type_width(GET_MODULE(ctx), &ir_type); + // 然后生成 LEA 时使用 scale = elem_size scc_mcode_amd64_lea_r64_m64_sib(&ctx->sect_mcode, SCC_AMD64_RAX, - SCC_AMD64_RAX, SCC_AMD64_RDX, 1, 0); + SCC_AMD64_RAX, SCC_AMD64_RDX, + elem_size, 0); } store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX); break; @@ -483,28 +496,36 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, ///< 调用函数 case SCC_IR_VALUE_TAG_CALL: { scc_reg_loc_t loc; - /* - ABI - RAX 不稳定的 返回值寄存器 - RCX 不稳定的 第一个整型自变量 - RDX 不稳定的 第二个整型自变量 - R8 不稳定的 第三个整型自变量 - R9 不稳定的 第四个整型自变量 - */ - scc_vec_foreach(value->data.call.args, i) { + usize nargs = scc_vec_size(value->data.call.args); + // 影子空间 32 字节 + 每个额外参数 8 字节(按 8 字节对齐) + usize stack_args_count = (nargs > 4) ? (nargs - 4) : 0; + usize stack_args_size = stack_args_count * 8; + usize total_stack_alloc = 32 + stack_args_size; + + // 调整栈指针(保持 16 字节对齐) + if (total_stack_alloc > 0) { + scc_mcode_amd64_sub_rsp_imm32(&ctx->sect_mcode, total_stack_alloc); + } + + // 处理寄存器参数(前 4 个) + for (usize i = 0; i < nargs && i < 4; i++) { parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i)); - if (i == 0) { - load_value_to_reg(ctx, &loc, SCC_AMD64_RCX); - } else if (i == 1) { - load_value_to_reg(ctx, &loc, SCC_AMD64_RDX); - } else if (i == 2) { - load_value_to_reg(ctx, &loc, SCC_AMD64_R8); - } else if (i == 3) { - load_value_to_reg(ctx, &loc, SCC_AMD64_R9); - } else { - LOG_FATAL("not support more than 4 args"); - } - // scc_mcode_amd64_push_r64(); + int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8, + SCC_AMD64_R9}; + load_value_to_reg(ctx, &loc, reg[i]); + } + + // 处理栈参数(第 5 个及以后) + // 从右向左依次写入栈(即最后一个参数放在最高地址) + for (usize i = 4; i < nargs; i++) { + scc_reg_loc_t loc; + parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i)); + // 加载到临时寄存器(如 RAX) + load_value_to_reg(ctx, &loc, SCC_AMD64_RAX); + // 计算栈偏移:影子空间(32) + (i-4)*8 + int offset = 32 + (i - 4) * 8; + scc_mcode_amd64_mov_m64_disp32_r64(&ctx->sect_mcode, SCC_AMD64_RSP, + offset, SCC_AMD64_RAX); } scc_ir_func_t *func = @@ -530,7 +551,10 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, .sect_type = SCCF_SECT_CODE, .sym_idx = sym_idx, }); - + // 恢复栈指针 + if (total_stack_alloc > 0) { + scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, total_stack_alloc); + } // 处理返回值 scc_ir_type_t *func_type = scc_ir_module_get_type(GET_MODULE(ctx), func->type); @@ -604,22 +628,22 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) { SCC_AMD64_RSP, ctx->stack_size); scc_reg_loc_t loc; scc_vec_foreach(func->params, i) { - // scc_ir_value_t *param = - // scc_ir_module_get_value(GET_MODULE(ctx), ); scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i); parse_location(ctx, &loc, node_ref); - if (i == 0) { - store_value_from_reg(ctx, &loc, SCC_AMD64_RCX); - } else if (i == 1) { - store_value_from_reg(ctx, &loc, SCC_AMD64_RDX); - } else if (i == 2) { - store_value_from_reg(ctx, &loc, SCC_AMD64_R8); - } else if (i == 3) { - store_value_from_reg(ctx, &loc, SCC_AMD64_R9); + if (i < 4) { + // 前 4 个参数:从寄存器存入槽位 + int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8, + SCC_AMD64_R9}; + store_value_from_reg(ctx, &loc, reg[i]); } else { - LOG_FATAL("not support more than 4 args"); + // 额外参数:从栈中加载到槽位 + // 偏移 = 16 (old rbp+retaddr) + 32 (shadow) + (i-4)*8 + int offset = 16 + 32 + (i - 4) * 8; + // 临时将栈值加载到 RAX,再存储到槽位 + scc_mcode_amd64_mov_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RBP, offset); + store_value_from_reg(ctx, &loc, SCC_AMD64_RAX); } - // scc_mcode_amd64_push_r64(); } for (usize i = 0; i < scc_vec_size(func->bblocks); i++) { @@ -759,6 +783,4 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { sccf_builder_add_text_section(ctx->builder, &text_section); sccf_builder_add_data_section(ctx->builder, &ctx->sect_data); - // FIXME maybe _entry and add crt - ctx->builder->entry_symbol_name = "main"; } diff --git a/libs/parser/src/parse_stmt.c b/libs/parser/src/parse_stmt.c index 126086e..fe2625c 100644 --- a/libs/parser/src/parse_stmt.c +++ b/libs/parser/src/parse_stmt.c @@ -247,6 +247,10 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser, } scc_ast_expr_t *expression = ast_parse_paren_expression(parser); + if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected semicolon after jump statement."); + } scc_ast_stmt_t *stmt = ast_stmt_alloc(); scc_ast_stmt_do_while_init(stmt, expression, statement, pos); return stmt; diff --git a/libs/sccf/include/sccf_builder.h b/libs/sccf/include/sccf_builder.h index 905038b..bbb005b 100644 --- a/libs/sccf/include/sccf_builder.h +++ b/libs/sccf/include/sccf_builder.h @@ -21,6 +21,11 @@ usize sccf_builder_add_symbol(sccf_builder_t *builder, const char *name, sccf_sym_t *sym); usize sccf_builder_get_symbol_idx(sccf_builder_t *builder, const char *name); +static inline void sccf_builder_set_entry_symbol_name(sccf_builder_t *builder, + const char *name) { + builder->entry_symbol_name = name ? name : "_scc_entry"; +} + static inline sccf_sym_t * sccf_builder_get_symbol_unsafe(sccf_builder_t *builder, const char *name) { usize idx = sccf_builder_get_symbol_idx(builder, name); diff --git a/libs/sccf/src/sccf_builder.c b/libs/sccf/src/sccf_builder.c index 2ebaab5..6f4dc4b 100644 --- a/libs/sccf/src/sccf_builder.c +++ b/libs/sccf/src/sccf_builder.c @@ -75,7 +75,9 @@ const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) { sccf_sym_t *sym = sccf_builder_get_symbol_unsafe(builder, builder->entry_symbol_name); if (sym == nullptr || sym->sccf_sect_type != SCCF_SECT_CODE) { - LOG_ERROR("entry symbol %s not found"); + LOG_ERROR( + "entry symbol %s not found, using 0 for entry point address", + builder->entry_symbol_name); builder->sccf.header.entry_point = 0; } else { builder->sccf.header.entry_point = sym->sccf_sect_offset; diff --git a/libs/target/sccf2target/src/sccf2pe.c b/libs/target/sccf2target/src/sccf2pe.c index 46704c1..23e56a5 100644 --- a/libs/target/sccf2target/src/sccf2pe.c +++ b/libs/target/sccf2target/src/sccf2pe.c @@ -66,7 +66,7 @@ static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx, const char *find_path) { (scc_hashtable_equal_func_t)scc_strcmp); scc_vec_init(ctx->idata_libs); ctx->find_path = find_path; - load_from_def(ctx, ctx->find_path, "ucrtbase.dll"); + load_from_def(ctx, ctx->find_path, "msvcrt.dll"); } static cbool pe_idata_get(pe_idata_lib_ctx_t *ctx, const char *name) { @@ -170,6 +170,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { scc_pe_construct_idata(&idata_builder, &idata_range); u32 entry_point_offset = sccf->header.entry_point; + Assert(entry_point_offset < scc_vec_size(*code_data)); u64 base_address = 0x140000000; u32 entry_point = code_range.virual_address + entry_point_offset; scc_pe_config_t config = (scc_pe_config_t){ diff --git a/src/config.h b/src/config.h index db81a15..1f13424 100644 --- a/src/config.h +++ b/src/config.h @@ -10,6 +10,7 @@ typedef struct { int verbose; scc_argparse_list_t include_paths; scc_argparse_list_t define_macros; + const char *entry_point_symbol; cbool emit_lex; cbool emit_pp; cbool emit_ast; @@ -28,6 +29,8 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, SCC_HINT_TARGET_DESC, SCC_HINT_VERBOSE, + SCC_HINT_ENTRY_POINT_SYMBOL, + SCC_HINT_EMIT_LEX, SCC_HINT_EMIT_PP, SCC_HINT_EMIT_AST, @@ -44,6 +47,9 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, [SCC_HINT_TARGET_DESC] = "Target description(eg. x86_64-pc-windows-msvc)", [SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)", + + [SCC_HINT_ENTRY_POINT_SYMBOL] = "Entry point symbol name", + [SCC_HINT_EMIT_LEX] = "Generate lexer sources tokens and exit", [SCC_HINT_EMIT_PP] = "Generate preprocessed tokens and exit", [SCC_HINT_EMIT_AST] = "Generate AST and exit", @@ -58,6 +64,9 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, [SCC_HINT_DEFINED_MACRO] = "定义宏", [SCC_HINT_TARGET_DESC] = "目标机器描述(eg. x86_64-pc-windows-msvc)", [SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)", + + [SCC_HINT_ENTRY_POINT_SYMBOL] = "入口点符号名称", + [SCC_HINT_EMIT_LEX] = "生成`源代码的词法单元`并退出", [SCC_HINT_EMIT_PP] = "生成`预处理后的词法单元`并退出", [SCC_HINT_EMIT_AST] = "生成`抽象语法树`并退出", @@ -110,6 +119,14 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, scc_argparse_spec_setup_list(&opt_define.spec, &(config->define_macros)); scc_argparse_cmd_add_opt(root, &opt_define); + // --entry-point-symbol (设置入口点符号名称) + scc_argparse_opt_t opt_entry_point_symbol; + scc_argparse_opt_init(&opt_entry_point_symbol, 0, "entry-point-symbol", + scc_hints[SCC_HINT_ENTRY_POINT_SYMBOL]); + scc_argparse_spec_setup_string(&opt_entry_point_symbol.spec, + &(config->entry_point_symbol)); + scc_argparse_cmd_add_opt(root, &opt_entry_point_symbol); + // --target scc_argparse_opt_t opt_target; scc_argparse_opt_init(&opt_target, 0, "target", diff --git a/src/main.c b/src/main.c index 2d38388..c4956ac 100644 --- a/src/main.c +++ b/src/main.c @@ -80,6 +80,7 @@ int main(int argc, const char **argv, const char **envp) { .input_file = nullptr, .verbose = 0, .output_file = nullptr, + .entry_point_symbol = nullptr, .emit_ast = false, .emit_ir = false, .target_description = "x86_64-pc-windows-msvc", @@ -243,6 +244,8 @@ sstream_drop: scc_ir2mcode(&ir2mcode_ctx); scc_ir2mcode_drop(&ir2mcode_ctx); + sccf_builder_set_entry_symbol_name(&sccf_builder, + config.entry_point_symbol); const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder); scc_pe_builder_t pe_builder; sccf2pe(&pe_builder, sccf); diff --git a/tests/simple/test.py b/tests/simple/test.py index c79f3ec..0be4fbc 100644 --- a/tests/simple/test.py +++ b/tests/simple/test.py @@ -36,7 +36,7 @@ def run_test(test_file, expected): exe_path = WORKSPACE / exe_filename # 1. 编译 - compile_cmd = [str(CC_PATH), str(test_file), "-o", exe_filename] + compile_cmd = [str(CC_PATH), str(test_file), "-o", exe_filename, "--entry-point-symbol", "main"] # 编译时关注 stderr 和返回码 _, compile_err, compile_ret = run_command(compile_cmd)