diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index 8b54a77..bfd47dc 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -285,7 +285,6 @@ struct scc_ast_expr { } cond; // 函数调用 struct { - const char *name; scc_ast_expr_t *callee; scc_ast_expr_vec_t args; } call; diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index 02daca5..1a96136 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -20,12 +20,9 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, case SCC_AST_TYPE_POINTER: { scc_ir_type_init(&ir_type, SCC_IR_TYPE_PTR); - // 创建指向类型并添加到程序类型列表 scc_ir_type_ref_t pointee_type = scc_ast2ir_type(ctx, ast_type->pointer.pointee); - // 注意:我们需要找到一种合适的方式来存储类型信息 - // 目前的IR设计中类型信息应该直接存储在类型结构中 ir_type.data.pointer.base = pointee_type; break; } @@ -33,11 +30,9 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, case SCC_AST_TYPE_ARRAY: { scc_ir_type_init(&ir_type, SCC_IR_TYPE_ARRAY); - // 创建元素类型并添加到程序类型列表 scc_ir_type_ref_t element_type = scc_ast2ir_type(ctx, ast_type->array.element); - // 将类型添加到程序的类型容器中 ir_type.data.array.base = element_type; // TODO: 处理数组大小表达式 ir_type.data.array.len = 0; // 暂时设为0 @@ -267,22 +262,20 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, scc_ir_node_ref_vec_t args; scc_vec_init(args); - // 检查参数是否为空 - if (expr->call.args.data != null) { - scc_vec_foreach(expr->call.args, i) { - scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i); - scc_ir_node_ref_t arg_node; - arg_node = scc_ast2ir_expr(ctx, arg_expr, false); - scc_vec_push(args, arg_node); - } + scc_vec_foreach(expr->call.args, i) { + scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i); + scc_ir_node_ref_t arg_node; + arg_node = scc_ast2ir_expr(ctx, arg_expr, false); + scc_vec_push(args, arg_node); } // 创建调用节点(需要查找函数定义) - // TODO: 需要符号表查找函数 - scc_ir_node_ref_t func = - scc_ir_builder_call(&ctx->builder, 0, args.data, args.size); + scc_ir_func_ref_t func = (scc_ir_node_ref_t)(usize)scc_hashtable_get( + &ctx->symtab, expr->call.callee->identifier._target->name); + scc_ir_node_ref_t node = + scc_ir_builder_call(&ctx->builder, func, args.data, args.size); scc_vec_free(args); - return func; + return node; } // SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标 @@ -316,6 +309,7 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, // FIXME hack hashtable scc_ir_node_ref_t in = (scc_ir_node_ref_t)(usize)scc_hashtable_get( &ctx->node2ir, expr->identifier._target); + Assert(in != 0); if (is_lvalue) { return in; } else { @@ -548,14 +542,38 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { } case SCC_AST_DECL_FUNC: { - scc_ir_type_ref_t func_type = scc_ast2ir_type(ctx, decl->func.type); + scc_ir_type_ref_t func_type_ref = scc_ast2ir_type(ctx, decl->func.type); + scc_ir_func_ref_t func_ref = + (usize)scc_hashtable_get(&ctx->symtab, decl->name); + if (func_ref == 0) { + func_ref = + scc_ir_builder_func(&ctx->builder, func_type_ref, decl->name); + scc_hashtable_set(&ctx->symtab, decl->name, + (void *)(usize)func_ref); + scc_vec_push(ctx->builder.cprog.func_decls, func_ref); + } + if (decl->func.body == null) { // function decl break; } - // TODO params name - scc_ir_builder_begin_func(&ctx->builder, decl->name, func_type, null); + + scc_ir_builder_begin_func(&ctx->builder, func_ref, null); + scc_ir_func_t *func = scc_ir_ctx_get_func(&ctx->builder.ctx, func_ref); + Assert(func != null); scc_ir_builder_begin_bblock(&ctx->builder, "entry"); + scc_vec_foreach(decl->func.type->function.params, i) { + scc_ast_decl_t *param = + scc_vec_at(decl->func.type->function.params, i); + + scc_ir_node_ref_t param_node_ref = scc_vec_at(func->params, i); + scc_ir_node_t *param_node = + scc_ir_ctx_get_node(&ctx->builder.ctx, param_node_ref); + Assert(param_node != null); + param_node->name = param->name; + scc_hashtable_set(&ctx->node2ir, param, + (void *)(usize)param_node_ref); + } scc_ast2ir_stmt(ctx, decl->func.body); scc_ir_builder_end_bblock(&ctx->builder); scc_ir_builder_end_func(&ctx->builder); @@ -607,4 +625,6 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi) { ctx->abi = abi; scc_ir_builder_init(&ctx->builder); scc_hashtable_init(&ctx->node2ir, scc_hash_node, scc_cmp_node); + scc_hashtable_init(&ctx->symtab, (scc_hashtable_hash_func_t)scc_strhash32, + (scc_hashtable_equal_func_t)scc_strcmp); } diff --git a/libs/ir/include/ir_builder.h b/libs/ir/include/ir_builder.h index a788cf9..5d734b0 100644 --- a/libs/ir/include/ir_builder.h +++ b/libs/ir/include/ir_builder.h @@ -19,6 +19,7 @@ typedef struct scc_ir_builder scc_ir_builder_t; struct scc_ir_builder { scc_ir_cprog_ctx_t ctx; /**< 核心上下文 */ scc_ir_cprog_t cprog; + scc_hashtable_t func_decl_set; // 当前构建位置 scc_ir_func_ref_t current_func; /**< 当前正在构建的函数 */ scc_ir_bblock_ref_t current_bblock; /**< 当前基本块 */ @@ -34,17 +35,19 @@ void scc_ir_builder_init(scc_ir_builder_t *builder); */ 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); + /** * @brief 开始构建函数 - * @param name 函数名 - * @param type 函数类型 + * @param func_ref 函数引用 * @param param_names 参数名列表(可为NULL) - * @return 函数引用 + * @return void */ -scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder, - const char *name, - scc_ir_type_ref_t type, - const char **param_names); +void scc_ir_builder_begin_func(scc_ir_builder_t *builder, + scc_ir_func_ref_t func_ref, + const char **param_names); /** * @brief 结束当前函数的构建 @@ -93,6 +96,10 @@ scc_ir_node_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder, scc_ir_type_ref_t type, const char *name); +scc_ir_node_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); + /** * @brief 创建load指令 * @param ptr 指针操作数 diff --git a/libs/ir/include/ir_ctx.h b/libs/ir/include/ir_ctx.h index 6518858..ecf4b57 100644 --- a/libs/ir/include/ir_ctx.h +++ b/libs/ir/include/ir_ctx.h @@ -29,12 +29,6 @@ typedef struct { // 常量池(常量键 -> 节点引用) scc_hashtable_t const_pool; - - // 内置类型缓存 - scc_ir_type_ref_t builtin_i32; - scc_ir_type_ref_t builtin_i1; - scc_ir_type_ref_t builtin_void; - scc_ir_node_ref_t builtin_zero_i32; } scc_ir_cprog_ctx_t; /** diff --git a/libs/ir/include/ir_def.h b/libs/ir/include/ir_def.h index 2127c2c..47ed31a 100644 --- a/libs/ir/include/ir_def.h +++ b/libs/ir/include/ir_def.h @@ -207,7 +207,7 @@ struct scc_ir_node { scc_ir_bblock_ref_t target_bblock; } jump; struct { - scc_ir_func_ref_t callee; + scc_ir_func_ref_t callee; // TODO function pointer call scc_ir_node_ref_vec_t args; } call; struct { @@ -217,9 +217,9 @@ struct scc_ir_node { }; typedef struct scc_ir_cprog { - scc_ir_node_ref_vec_t global_vals; - scc_ir_func_ref_vec_t func_defs; - scc_ir_node_ref_vec_t func_decls; + scc_ir_node_ref_vec_t global_vals; /* 全局变量 */ + scc_ir_func_ref_vec_t func_defs; /* 所有函数定义 */ + scc_ir_func_ref_vec_t func_decls; /* 所有函数包括定义的声明 */ } scc_ir_cprog_t; #endif /* __SCC_IR_DEF_H__ */ diff --git a/libs/ir/src/ir_builder.c b/libs/ir/src/ir_builder.c index 117a4f4..440e116 100644 --- a/libs/ir/src/ir_builder.c +++ b/libs/ir/src/ir_builder.c @@ -14,33 +14,44 @@ void scc_ir_builder_drop(scc_ir_builder_t *builder) { scc_ir_ctx_drop(&builder->ctx); } -scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder, - const char *name, - scc_ir_type_ref_t type, - const char **param_names) { - scc_ir_func_t func = {0}; - - // 初始化参数和基本块向量 - func.name = name; - func.type = type; +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_func_t func = { + .name = name, + .type = type_ref, + }; scc_vec_init(func.params); scc_vec_init(func.bblocks); - // 创建函数并设置为当前函数 scc_ir_func_ref_t func_ref = scc_ir_ctx_new_func(&builder->ctx, &func); + return func_ref; +} + +void scc_ir_builder_begin_func(scc_ir_builder_t *builder, + scc_ir_func_ref_t func_ref, + const char **param_names) { + // 创建函数并设置为当前函数 builder->current_func = func_ref; - // 如果提供了参数名称,则创建参数节点 - if (param_names == null) { - return func_ref; - } - scc_ir_func_t *func_ptr = scc_ir_ctx_get_func(&builder->ctx, func_ref); - scc_ir_type_t *func_type = scc_ir_ctx_get_type(&builder->ctx, type); + scc_ir_type_t *func_type = + scc_ir_ctx_get_type(&builder->ctx, func_ptr->type); if (func_type == null || func_type->tag != SCC_IR_TYPE_FUNC) { LOG_ERROR("Invalid function type"); - return func_ref; + return; + } + + if (func_ptr == null) { + LOG_ERROR("Invalid function reference"); + return; + } + + if (scc_vec_size(func_ptr->bblocks) != 0 || + scc_vec_size(func_ptr->params) != 0) { + LOG_FATAL("Multiple function definitions"); + return; } scc_vec_foreach(func_type->data.function.params, i) { @@ -48,9 +59,10 @@ scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder, scc_vec_at(func_type->data.function.params, i); scc_ir_node_t param_node = {0}; - param_node.tag = SCC_IR_NODE_NULL; // 参数节点标记 + param_node.tag = SCC_IR_NODE_FUNC_ARG_REF; // 参数节点标记 param_node.type = param_type; - param_node.name = param_names[i]; + param_node.name = param_names ? param_names[i] : null; + param_node.data.arg_ref.idx = i; scc_vec_init(param_node.used_by); scc_ir_node_ref_t param_ref = @@ -58,7 +70,7 @@ scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder, scc_vec_push(func_ptr->params, param_ref); } - return func_ref; + return; } void scc_ir_builder_end_func(scc_ir_builder_t *builder) { @@ -144,6 +156,21 @@ scc_ir_node_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder, return node_ref; } +scc_ir_node_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_node_t node = {0}; + node.tag = SCC_IR_NODE_FUNC_ARG_REF; + node.type = type; + node.name = name; + node.data.arg_ref.idx = arg_idx; + + scc_ir_node_ref_t node_ref = scc_ir_ctx_new_node(&builder->ctx, &node); + // 添加到当前基本块 + scc_ir_builder_add_instr(builder, node_ref); + return node_ref; +} + scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder, scc_ir_node_ref_t target) { scc_ir_node_t load_node = {0}; diff --git a/libs/ir/src/ir_ctx.c b/libs/ir/src/ir_ctx.c index 788910e..d872cd8 100644 --- a/libs/ir/src/ir_ctx.c +++ b/libs/ir/src/ir_ctx.c @@ -213,20 +213,7 @@ scc_ir_type_ref_t scc_ir_ctx_new_type(scc_ir_cprog_ctx_t *ctx, return (scc_ir_type_ref_t)(uintptr_t)existing; } - // 创建新类型 - unsigned new_uid = ctx->type_uid++; - scc_vec_push(ctx->types, *type); - - // 添加到UID映射 - usize idx = ctx->types.size - 1; - scc_hashtable_set(&ctx->uid2types, &new_uid, (void *)idx); - - // 添加到去重表 - scc_hashtable_set(&ctx->type_uniquing, - &ctx->types.data[idx], // 使用向量中的地址作为键 - (void *)(uintptr_t)new_uid); - - return new_uid; + CREATE_ENTITY(ctx, ctx->types, type_uid, type, uid2types); } scc_ir_node_ref_t scc_ir_ctx_new_node(scc_ir_cprog_ctx_t *ctx, @@ -292,11 +279,12 @@ scc_ir_func_t *scc_ir_ctx_get_func(scc_ir_cprog_ctx_t *ctx, #undef GET_ENTITY_INDEX -// 内置类型和常量缓存 -static scc_ir_type_ref_t cached_i32_type = 0; -static scc_ir_node_ref_t cached_zero_const = 0; +// // 内置类型和常量缓存 +// static scc_ir_type_ref_t cached_i32_type = 0; +// static scc_ir_node_ref_t cached_zero_const = 0; scc_ir_type_ref_t scc_ir_ctx_get_builtin_i32(scc_ir_cprog_ctx_t *ctx) { + scc_ir_type_ref_t cached_i32_type = 0; if (cached_i32_type == 0) { scc_ir_type_t i32_type = {.tag = SCC_IR_TYPE_I32}; cached_i32_type = scc_ir_ctx_new_type(ctx, &i32_type); @@ -305,6 +293,7 @@ scc_ir_type_ref_t scc_ir_ctx_get_builtin_i32(scc_ir_cprog_ctx_t *ctx) { } scc_ir_node_ref_t scc_ir_ctx_get_builtin_zero(scc_ir_cprog_ctx_t *ctx) { + scc_ir_node_ref_t cached_zero_const = 0; if (cached_zero_const == 0) { scc_ir_node_t zero_node = {.tag = SCC_IR_NODE_CONST_INT, .type = scc_ir_ctx_get_builtin_i32(ctx), @@ -333,7 +322,7 @@ scc_ir_node_ref_t scc_ir_ctx_get_i32_const(scc_ir_cprog_ctx_t *ctx, i32 value) { .type = scc_ir_ctx_get_builtin_i32(ctx), .data.const_int.int32 = value}; - const_node.name = ""; + const_node.name = null; return scc_ir_ctx_new_node(ctx, &const_node); } diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c index 863df1a..ef0c4e0 100644 --- a/libs/ir/src/ir_dump.c +++ b/libs/ir/src/ir_dump.c @@ -13,12 +13,25 @@ // 获取IR节点类型的字符串表示 static const char *get_node_type_str(scc_ir_node_tag_t tag) { static const char *node_types[] = { - [SCC_IR_NODE_NULL] = "Null", [SCC_IR_NODE_CONST_INT] = "ConstInt", - [SCC_IR_NODE_ALLOC] = "Alloc", [SCC_IR_NODE_LOAD] = "Load", - [SCC_IR_NODE_STORE] = "Store", [SCC_IR_NODE_GET_PTR] = "GetElementPtr", - [SCC_IR_NODE_OP] = "Op", [SCC_IR_NODE_BRANCH] = "Branch", - [SCC_IR_NODE_JUMP] = "Jump", [SCC_IR_NODE_CALL] = "Call", - [SCC_IR_NODE_RET] = "Return", + [SCC_IR_NODE_NULL] = "Null", + [SCC_IR_NODE_CONST_INT] = "ConstInt", + [SCC_IR_NODE_CONST_UINT] = "ConstUint", + [SCC_IR_NODE_CONST_FLOAT] = "ConstFloat", + [SCC_IR_NODE_CONV] = "Convert", ///< 类型转换 + [SCC_IR_NODE_FUNC_ARG_REF] = "FuncArgRef", ///< 函数参数引用 + [SCC_IR_NODE_BLOCK_ARG_REF] = "BlockArgRef", ///< 基本块参数引用 + [SCC_IR_NODE_ALLOC] = "Alloc", ///< 分配内存(stack) + [SCC_IR_NODE_GLOBAL_ALLOC] = "GlobalAlloc", ///< 全局分配(bss) + [SCC_IR_NODE_LOAD] = "Load", ///< 加载数据 + [SCC_IR_NODE_STORE] = "Store", ///< 存储数据 + [SCC_IR_NODE_GET_PTR] = "GetPtr", ///< 获取指针 + [SCC_IR_NODE_GET_ELEM_PTR] = + "GetElemPtr", ///< 获取元素指针(used by array) + [SCC_IR_NODE_OP] = "Op", ///< 二元运算 + [SCC_IR_NODE_BRANCH] = "Branch", ///< 有条件分支 + [SCC_IR_NODE_JUMP] = "Jump", ///< 无条件跳转 + [SCC_IR_NODE_CALL] = "Call", ///< 调用函数 + [SCC_IR_NODE_RET] = "Ret", ///< 函数返回 }; if (tag >= 0 && (usize)tag < sizeof(node_types) / sizeof(node_types[0]) && @@ -713,10 +726,10 @@ void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx, args_remaining = sizeof(args_buf) - (args_p - args_buf); } - format_node_ref_or_value(ctx, node_name, sizeof(node_name), - node->data.call.callee); - - p += scc_snprintf(p, remaining, "call @%s(%s)", node_name, args_buf); + scc_ir_func_t *func = + scc_ir_ctx_get_func(ctx->ir_ctx, node->data.call.callee); + p += scc_snprintf(p, remaining, "call @%s(%s)", + func ? func->name : null, args_buf); break; } @@ -731,6 +744,11 @@ void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx, } break; + case SCC_IR_NODE_FUNC_ARG_REF: { + p += scc_snprintf(p, remaining, "arg[%zu]", node->data.arg_ref.idx); + break; + } + default: p += scc_snprintf(p, remaining, "<%s node %u>", get_node_type_str(node->tag), node_ref); @@ -796,7 +814,7 @@ void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx, if (i > 0) PRINT_NODE(ctx->dump_ctx, ", "); scc_ir_node_ref_t param_ref = scc_vec_at(func->params, i); - PRINT_NODE(ctx->dump_ctx, "%%"); + PRINT_NODE(ctx->dump_ctx, "%"); scc_ir_node_t *param_node = scc_ir_ctx_get_node(ctx->ir_ctx, param_ref); if (param_node && param_node->name && param_node->name[0] != '\0') { @@ -813,11 +831,8 @@ void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx, PRINT_NODE(ctx->dump_ctx, "()"); } - // 如果有返回类型 - if (func->type != 0) { - PRINT_NODE(ctx->dump_ctx, " -> "); - scc_ir_dump_type_linear(ctx, func->type); - } + PRINT_NODE(ctx->dump_ctx, ": "); + scc_ir_dump_type_linear(ctx, func->type); PRINT_NODE(ctx->dump_ctx, " {\n"); @@ -833,6 +848,13 @@ void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx, // 线性输出整个程序 void scc_ir_dump_cprog_linear(scc_ir_dump_ctx_t *ctx) { + scc_vec_foreach(ctx->cprog->func_decls, i) { + scc_ir_func_ref_t func_decl = scc_vec_at(ctx->cprog->func_decls, i); + scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_decl); + Assert(func != null); + if (scc_vec_size(func->bblocks) == 0) + scc_ir_dump_func_linear(ctx, func_decl); + } scc_vec_foreach(ctx->cprog->func_defs, i) { scc_ir_dump_func_linear(ctx, scc_vec_at(ctx->cprog->func_defs, i)); } diff --git a/libs/ir2mcode/include/reg_alloc.h b/libs/ir2mcode/include/reg_alloc.h index e073a0c..0555709 100644 --- a/libs/ir2mcode/include/reg_alloc.h +++ b/libs/ir2mcode/include/reg_alloc.h @@ -7,6 +7,7 @@ typedef enum { SCC_REG_KIND_UNDEF, + SCC_REG_KIND_FUNC_ARG, SCC_REG_KIND_GPR, ///< 通用寄存器(整数) SCC_REG_KIND_FPR, ///< 浮点数寄存器 SCC_REG_KIND_STACK, ///< 栈 diff --git a/libs/ir2mcode/include/scc_ir2mcode.h b/libs/ir2mcode/include/scc_ir2mcode.h index 9b49258..28c43b6 100644 --- a/libs/ir2mcode/include/scc_ir2mcode.h +++ b/libs/ir2mcode/include/scc_ir2mcode.h @@ -12,6 +12,8 @@ typedef struct { scc_mcode_t mcode; sccf_builder_t builder; + // FIXME + usize stack_size; scc_reg_alloc_t reg_alloc; scc_hashtable_t *noderef2regloc; } scc_ir2mcode_ctx_t; diff --git a/libs/ir2mcode/src/ir2amd64.c b/libs/ir2mcode/src/ir2amd64.c index a8faa60..1b35389 100644 --- a/libs/ir2mcode/src/ir2amd64.c +++ b/libs/ir2mcode/src/ir2amd64.c @@ -4,7 +4,7 @@ #include static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc, - scc_ir_bblock_ref_t node_ref) { + scc_ir_node_ref_t node_ref) { Assert(ctx != null && loc != null); scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref); if (node == null) { @@ -27,6 +27,17 @@ static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc, case SCC_IR_NODE_CONST_FLOAT: TODO(); break; + case SCC_IR_NODE_FUNC_ARG_REF: { + scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_ctx, node->type); + Assert(type != 0); + scc_reg_loc_t arg_loc; + // arg_loc.kind = SCC_REG_KIND_FUNC_ARG; + // arg_loc.idx = node->data.arg_ref.idx; + arg_loc.kind = SCC_REG_KIND_STACK; + arg_loc.idx = 8 * node->data.arg_ref.idx; + *loc = arg_loc; + return; + } default: idx = (usize)scc_hashtable_get(ctx->noderef2regloc, (void *)(usize)node_ref); @@ -47,8 +58,9 @@ static void load_value_to_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, int reg) { } break; case SCC_REG_KIND_STACK: + // FIXME -8 for rdp scc_mcode_amd64_mov_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP, - -loc->idx); + -loc->idx - 8); break; case SCC_REG_KIND_IMM: scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->idx); // 或 imm32 @@ -67,7 +79,8 @@ static void store_value_from_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, } break; case SCC_REG_KIND_STACK: - scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx, + // FIXME -8 for rdp + scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx - 8, reg); break; case SCC_REG_KIND_IMM: @@ -95,13 +108,16 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, } switch (node->tag) { - case SCC_IR_NODE_CONV: ///< 类型转换 - case SCC_IR_NODE_FUNC_ARG_REF: ///< 函数参数引用 - case SCC_IR_NODE_BLOCK_ARG_REF: ///< 基本块参数引用 + case SCC_IR_NODE_CONV: ///< 类型转换 LOG_FATAL("Unsupported node type: %d", node->tag); break; - case SCC_IR_NODE_ALLOC: ///< 分配内存(stack) - case SCC_IR_NODE_GLOBAL_ALLOC: ///< 全局分配(bss) + ///< 函数参数引用 + case SCC_IR_NODE_FUNC_ARG_REF: + ///< ABI + break; + case SCC_IR_NODE_BLOCK_ARG_REF: ///< 基本块参数引用 + case SCC_IR_NODE_ALLOC: ///< 分配内存(stack) + case SCC_IR_NODE_GLOBAL_ALLOC: ///< 全局分配(bss) break; case SCC_IR_NODE_LOAD: ///< 加载数据 { @@ -127,7 +143,8 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, case SCC_IR_NODE_GET_PTR: ///< 获取指针 case SCC_IR_NODE_GET_ELEM_PTR: ///< 获取元素指针(used by array) TODO(); - case SCC_IR_NODE_OP: ///< 二元运算 + ///< 二元运算 + case SCC_IR_NODE_OP: { scc_reg_loc_t loc_lhs; parse_location(ctx, &loc_lhs, node->data.op.lhs); scc_reg_loc_t loc_rhs; @@ -216,6 +233,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, // 将 RAX 中的结果存储到 res 位置 store_value_from_reg(&ctx->mcode, &loc_res, SCC_AMD64_RAX); break; + } ///< 有条件分支 case SCC_IR_NODE_BRANCH: { scc_reg_loc_t loc; @@ -257,7 +275,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, R9 不稳定的 第四个整型自变量 */ scc_vec_foreach(node->data.call.args, i) { - parse_location(ctx, &loc, node->data.branch.cond); + parse_location(ctx, &loc, scc_vec_at(node->data.call.args, i)); if (i == 0) { load_value_to_reg(&ctx->mcode, &loc, SCC_AMD64_RCX); } else if (i == 1) { @@ -280,9 +298,22 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, } scc_mcode_amd64_call_rel32(&ctx->mcode, 0); + usize sym_idx = sccf_builder_get_symbol_idx(&ctx->builder, func->name); + Assert(sym_idx != 0); + sccf_builder_add_reloc(&ctx->builder, + (sccf_reloc_t){ + .reloc_type = SCCF_RELOC_TYPE_REL, + .offset = scc_vec_size(ctx->mcode.mcode) - 4, + .addend = 4, + .sect_type = SCCF_SECT_CODE, + .sym_idx = sym_idx, + }); // 处理返回值 - scc_ir_type_t *ret_type = scc_ir_ctx_get_type(ctx->ir_ctx, node->type); + scc_ir_type_t *func_type = scc_ir_ctx_get_type(ctx->ir_ctx, func->type); + Assert(func_type); + scc_ir_type_t *ret_type = + scc_ir_ctx_get_type(ctx->ir_ctx, func_type->data.function.ret_type); if (ret_type && ret_type->tag != SCC_IR_TYPE_VOID) { parse_location(ctx, &loc, node_ref); store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_RAX); @@ -296,12 +327,13 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, parse_location(ctx, &loc, node->data.ret.ret_val); load_value_to_reg(&ctx->mcode, &loc, SCC_AMD64_RAX); } - scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RSP, SCC_AMD64_RBP); + scc_mcode_amd64_add_rsp_imm32(&ctx->mcode, ctx->stack_size); scc_mcode_amd64_pop_r64(&ctx->mcode, SCC_AMD64_RBP); scc_mcode_amd64_ret(&ctx->mcode); break; } default: + LOG_FATAL("unknown node type: %d", node->tag); UNREACHABLE(); break; } @@ -325,7 +357,9 @@ static int equal_func(const void *key1, const void *key2) { static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) { ctx->noderef2regloc = scc_reg_alloc(&ctx->reg_alloc, func); // 对齐到 16 字节 - usize stack_size = (ctx->reg_alloc.alloc_stack_size + 15) & ~15; + // FIXME + ctx->stack_size += 8; ///< for rbp + ctx->stack_size = (ctx->reg_alloc.alloc_stack_size + 15) & ~15; usize bblock_cnt = scc_vec_size(func->bblocks); usize *bblock_offsets = scc_calloc(bblock_cnt, sizeof(usize)); @@ -341,8 +375,28 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) { scc_vec_init(patches); scc_mcode_amd64_push_r64(&ctx->mcode, SCC_AMD64_RBP); - scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RBP, SCC_AMD64_RSP); - scc_mcode_amd64_sub_rsp_imm32(&ctx->mcode, stack_size); + scc_mcode_amd64_sub_rsp_imm32(&ctx->mcode, ctx->stack_size); + scc_mcode_amd64_lea_r64_m64_disp32(&ctx->mcode, SCC_AMD64_RBP, + SCC_AMD64_RSP, ctx->stack_size); + scc_reg_loc_t loc; + scc_vec_foreach(func->params, i) { + // scc_ir_node_t *param = + // scc_ir_ctx_get_node(ctx->ir_ctx, ); + scc_ir_node_ref_t node_ref = scc_vec_at(func->params, i); + parse_location(ctx, &loc, node_ref); + if (i == 0) { + store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_RCX); + } else if (i == 1) { + store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_RDX); + } else if (i == 2) { + store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_R8); + } else if (i == 3) { + store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_R9); + } else { + LOG_FATAL("not support more than 4 args"); + } + // scc_mcode_amd64_push_r64(); + } for (usize i = 0; i < scc_vec_size(func->bblocks); i++) { scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i); @@ -367,12 +421,8 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) { usize target_off = bblock_offsets[target_id]; usize next_off = p->pos; i32 rel = (i32)(target_off - next_off); - // 写入到指令的偏移字段(小端) + // FIXME 写入到指令的偏移字段(小端) *(u32 *)(&buf[p->pos - 4]) = rel; - // buf[p->pos + 1] = (u8)(rel >> 0); - // buf[p->pos + 2] = (u8)(rel >> 8); - // buf[p->pos + 3] = (u8)(rel >> 16); - // buf[p->pos + 4] = (u8)(rel >> 24); } scc_free(bblock_offsets); scc_vec_free(patches); @@ -382,6 +432,39 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) { void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_with_stack, ctx->ir_ctx); + scc_vec_foreach(ctx->cprog->func_decls, i) { + scc_ir_node_ref_t func_ref = scc_vec_at(ctx->cprog->func_decls, i); + scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref); + if (!func) { + LOG_ERROR("invalid function reference"); + return; + } + + sccf_sym_t sym = {0}; + if (scc_vec_size(func->bblocks)) { + sym = (sccf_sym_t){ + .sccf_sect_offset = 0, + .sccf_sect_type = SCCF_SECT_CODE, + .sccf_sym_bind = SCCF_SYM_BIND_GLOBAL, + .sccf_sym_size = 0, + .sccf_sym_type = SCCF_SYM_TYPE_FUNC, + .sccf_sym_vis = SCCF_SYM_VIS_DEFAULT, + }; + } else { + sym = (sccf_sym_t){ + .sccf_sect_offset = 0, + .sccf_sect_type = SCCF_SECT_NONE, + .sccf_sym_bind = SCCF_SYM_BIND_GLOBAL, + .sccf_sym_size = 0, + .sccf_sym_type = SCCF_SYM_TYPE_EXTERN, + .sccf_sym_vis = SCCF_SYM_VIS_DEFAULT, + }; + } + usize sym_idx = + sccf_builder_add_symbol(&ctx->builder, func->name, &sym); + Assert(sym_idx != 0); + } + scc_vec_foreach(ctx->cprog->func_defs, i) { scc_ir_node_ref_t func_ref = scc_vec_at(ctx->cprog->func_defs, i); scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref); @@ -389,16 +472,10 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { LOG_ERROR("invalid function reference"); return; } - sccf_sym_t sym = { - .sccf_sect_offset = scc_vec_size(ctx->mcode.mcode), - .sccf_sect_type = SCCF_SECT_CODE, - .sccf_sym_bind = SCCF_SYM_BIND_GLOBAL, - .sccf_sym_size = 0, - .sccf_sym_type = SCCF_SYM_TYPE_FUNC, - .sccf_sym_vis = SCCF_SYM_VIS_DEFAULT, - }; - sccf_builder_add_symbol(&ctx->builder, func->name, &sym); - + sccf_sym_t *sym = + sccf_builder_get_symbol_unsafe(&ctx->builder, func->name); + Assert(sym != null); + sym->sccf_sect_offset = scc_vec_size(ctx->mcode.mcode); parse_function(ctx, func); } sccf_sect_data_t text_section; @@ -409,4 +486,28 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { sccf_sect_data_t data_section; scc_vec_init(data_section); sccf_builder_add_data_section(&ctx->builder, &data_section); + + u8 *buf = scc_vec_unsafe_get_data(ctx->mcode.mcode); + scc_vec_foreach(ctx->builder.relocs, i) { + sccf_reloc_t *reloc = &scc_vec_at(ctx->builder.relocs, i); + if (reloc->sym_idx == 0) { + Panic("relocate to an invalid symbol"); + } + sccf_sym_t *sym = &scc_vec_at(ctx->builder.symtab, reloc->sym_idx); + if (sym->sccf_sym_type != SCCF_SYM_TYPE_EXTERN) { + Assert(reloc->reloc_type == SCCF_RELOC_TYPE_REL); + + Assert(sym->sccf_sect_type == SCCF_SECT_CODE); + Assert(sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC); + i64 target_off = sym->sccf_sect_offset; + i64 next_off = reloc->offset + reloc->addend; + i32 rel = (i32)(target_off - next_off); + // FIXME 写入到指令的偏移字段(小端) + *(i32 *)(&buf[reloc->offset]) = rel; + + reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY; + } + } + // FIXME + ctx->builder.entry_symbol_name = "main"; } diff --git a/libs/ir2mcode/src/reg_alloc.c b/libs/ir2mcode/src/reg_alloc.c index e846856..024b72f 100644 --- a/libs/ir2mcode/src/reg_alloc.c +++ b/libs/ir2mcode/src/reg_alloc.c @@ -23,7 +23,17 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, scc_hashtable_drop(&ctx->node_ref2reg_loc); scc_vec_free(ctx->reg_loc_vec); scc_vec_init(ctx->reg_loc_vec); + scc_reg_loc_t loc; + scc_vec_foreach(func->params, i) { + scc_ir_node_ref_t node_ref = scc_vec_at(func->params, i); + loc.kind = SCC_REG_KIND_FUNC_ARG; + loc.idx = i; + ctx->alloc_stack_size += 8; + scc_hashtable_set(&ctx->node_ref2reg_loc, (void *)(usize)node_ref, + (void *)scc_vec_size(ctx->reg_loc_vec)); + break; + } scc_vec_foreach(func->bblocks, i) { scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i); scc_ir_bblock_t *bblock = @@ -33,8 +43,6 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, scc_ir_node_ref_t node_ref = scc_vec_at(bblock->instrs, j); scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref); Assert(node != null); - - scc_reg_loc_t loc; loc.kind = SCC_REG_KIND_UNDEF; switch (node->tag) { case SCC_IR_NODE_LOAD: @@ -51,8 +59,12 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, break; } case SCC_IR_NODE_CALL: { - scc_ir_type_t *ret_type = - scc_ir_ctx_get_type(ctx->ir_ctx, node->type); + // 处理返回值 + scc_ir_type_t *func_type = + scc_ir_ctx_get_type(ctx->ir_ctx, func->type); + Assert(func_type); + scc_ir_type_t *ret_type = scc_ir_ctx_get_type( + ctx->ir_ctx, func_type->data.function.ret_type); if (ret_type && ret_type->tag != SCC_IR_TYPE_VOID) { loc.kind = SCC_REG_KIND_STACK; loc.idx = ctx->alloc_stack_size; diff --git a/libs/sccf/include/sccf.h b/libs/sccf/include/sccf.h index 145c83f..7df435a 100644 --- a/libs/sccf/include/sccf.h +++ b/libs/sccf/include/sccf.h @@ -74,8 +74,9 @@ typedef enum { /** 重定位类型 */ typedef enum { - SCCF_RELOC_ABS = 1, ///< 绝对地址 - SCCF_RELOC_REL = 2, ///< 相对地址 + SCCF_RELOC_TYPE_EMPTY = 0, ///< 空展位符 + SCCF_RELOC_TYPE_ABS = 1, ///< 绝对地址 + SCCF_RELOC_TYPE_REL = 2, ///< 相对地址 } sccf_reloc_type_t; /** @@ -121,11 +122,11 @@ typedef struct { * @brief SCCF重定向条目 */ typedef struct { - sccf_enum_t type; ///< 重定位类型 - sccf_enum_t sect_type; ///< 需要重定位的段类型(代码段/数据段) - sccf_size_t sym_idx; ///< 符号索引(重定向指向的符号) - sccf_size_t offset; ///< 在段中的偏移量(用于重定向的地址) - sccf_isize_t addend; ///< 加数(用于获取相对位置时PC的额外值) + sccf_enum_t reloc_type; ///< 重定位类型 + sccf_enum_t sect_type; ///< 需要重定位的段类型(代码段/数据段) + sccf_size_t sym_idx; ///< 符号索引(重定向指向的符号) + sccf_size_t offset; ///< 在段中的偏移量(用于重定向的地址) + sccf_isize_t addend; ///< 加数(用于获取相对位置时PC的额外值) } sccf_reloc_t; /** diff --git a/libs/sccf/include/sccf_builder.h b/libs/sccf/include/sccf_builder.h index 13c182c..81fa1f4 100644 --- a/libs/sccf/include/sccf_builder.h +++ b/libs/sccf/include/sccf_builder.h @@ -7,6 +7,7 @@ typedef struct { sccf_t sccf; int aligned; + const char *entry_symbol_name; sccf_strtab_t strtab; sccf_reloc_vec_t relocs; sccf_sym_vec_t symtab; @@ -19,10 +20,16 @@ void sccf_builder_init(sccf_builder_t *builder); 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 sccf_sym_t * -sccf_builder_get_symbol_unsafe(sccf_builder_t *builder, usize idx) { +sccf_builder_get_symbol_unsafe(sccf_builder_t *builder, const char *name) { + usize idx = sccf_builder_get_symbol_idx(builder, name); + if (idx == 0) { + return null; + } return &scc_vec_at(builder->symtab, idx); } + void sccf_builder_add_reloc(sccf_builder_t *builder, sccf_reloc_t reloc); /** diff --git a/libs/sccf/src/sccf_builder.c b/libs/sccf/src/sccf_builder.c index 2b9168b..25d1a32 100644 --- a/libs/sccf/src/sccf_builder.c +++ b/libs/sccf/src/sccf_builder.c @@ -13,6 +13,8 @@ void sccf_builder_init(sccf_builder_t *builder) { scc_vec_init(builder->relocs); scc_vec_init(builder->symtab); + builder->entry_symbol_name = null; + ///< Push null scc_vec_push(builder->strtab, (char)'\0'); ///< Push null @@ -23,21 +25,26 @@ usize sccf_builder_add_symbol(sccf_builder_t *builder, const char *name, sccf_sym_t *sym) { usize offset = 0; offset = (usize)scc_hashtable_get(&builder->str2offset, name); + const char *key = &scc_vec_at(builder->strtab, offset); if (offset == 0) { offset = scc_vec_size(builder->strtab); - scc_hashtable_set(&builder->str2offset, name, (void *)offset); while (*name) { scc_vec_push(builder->strtab, *name); name++; } scc_vec_push(builder->strtab, '\0'); + + key = &scc_vec_at(builder->strtab, offset); + scc_hashtable_set(&builder->str2offset, key, (void *)offset); } sym->name_offset = offset; usize sym_idx = scc_vec_size(builder->symtab); - offset = (usize)scc_hashtable_get(&builder->str2sym, name); + offset = (usize)scc_hashtable_get(&builder->str2sym, key); if (offset == 0) { - scc_hashtable_set(&builder->str2sym, name, (void *)sym_idx); + scc_hashtable_set(&builder->str2sym, key, (void *)sym_idx); + } else { + LOG_ERROR("symbol %s already exists", key); } scc_vec_push(builder->symtab, *sym); return sym_idx; @@ -62,9 +69,19 @@ void sccf_builder_add_section(sccf_builder_t *builder, } const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) { - // TODO symtab strtab reloc - // sccf_sect_header_t symtab_header; - // sccf_sect_data_t symtab_data; + if (builder->entry_symbol_name == null) { + builder->sccf.header.entry_point = 0; + } else { + sccf_sym_t *sym = + sccf_builder_get_symbol_unsafe(builder, builder->entry_symbol_name); + if (sym == null || sym->sccf_sect_type != SCCF_SECT_CODE) { + LOG_ERROR("entry symbol %s not found"); + builder->sccf.header.entry_point = 0; + } else { + builder->sccf.header.entry_point = sym->sccf_sect_offset; + } + } + sccf_sect_header_t sect_header; if (scc_vec_size(builder->strtab)) { sect_header = (sccf_sect_header_t){ diff --git a/libs/target/sccf2target/src/sccf2pe.c b/libs/target/sccf2target/src/sccf2pe.c index daa7ca8..2c74c73 100644 --- a/libs/target/sccf2target/src/sccf2pe.c +++ b/libs/target/sccf2target/src/sccf2pe.c @@ -167,7 +167,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { scc_pe_buffer_t idata_buffer = scc_pe_construct_idata(&idata_builder, &idata_range); - u32 entry_point_offset = 0; + u32 entry_point_offset = sccf->header.entry_point; u64 base_address = 0x140000000; u32 entry_point = code_range.virual_address + entry_point_offset; scc_pe_config_t config = (scc_pe_config_t){ @@ -197,6 +197,9 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { scc_vec_foreach(relocs, i) { sccf_reloc_t *reloc = &scc_vec_at(relocs, i); + if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) { + continue; + } sccf_sym_t *sym = &scc_vec_at(symtab, reloc->sym_idx); const char *name = &scc_vec_at(strtab, sym->name_offset); @@ -212,7 +215,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { } Assert(rva != 0); - if (reloc->type == SCCF_RELOC_ABS) { + if (reloc->reloc_type == SCCF_RELOC_TYPE_ABS) { TODO(); } Assert(reloc->sect_type == SCCF_SECT_CODE); diff --git a/libs/target/sccf2target/tests/test_sccf2pe_run.c b/libs/target/sccf2target/tests/test_sccf2pe_run.c index 67ec264..a56ea79 100644 --- a/libs/target/sccf2target/tests/test_sccf2pe_run.c +++ b/libs/target/sccf2target/tests/test_sccf2pe_run.c @@ -51,16 +51,18 @@ int main() { .sccf_sym_type = SCCF_SYM_TYPE_EXTERN, .sccf_sym_vis = SCCF_SYM_VIS_DEFAULT, }); - sccf_builder_add_reloc(&builder, (sccf_reloc_t){.addend = 4, - .offset = 7, - .sect_type = SCCF_SECT_CODE, - .sym_idx = str_idx, - .type = SCCF_RELOC_REL}); - sccf_builder_add_reloc(&builder, (sccf_reloc_t){.addend = 4, - .offset = 13, - .sect_type = SCCF_SECT_CODE, - .sym_idx = puts_idx, - .type = SCCF_RELOC_REL}); + sccf_builder_add_reloc(&builder, + (sccf_reloc_t){.addend = 4, + .offset = 7, + .sect_type = SCCF_SECT_CODE, + .sym_idx = str_idx, + .reloc_type = SCCF_RELOC_TYPE_REL}); + sccf_builder_add_reloc(&builder, + (sccf_reloc_t){.addend = 4, + .offset = 13, + .sect_type = SCCF_SECT_CODE, + .sym_idx = puts_idx, + .reloc_type = SCCF_RELOC_TYPE_REL}); const sccf_t *sccf = sccf_builder_to_sccf(&builder); scc_pe_builder_t pe_builder;