From 0acea43e4ef069ec1bfb430a2e6b3c68034d684d Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Wed, 3 Jun 2026 17:34:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(argparse):=20=E6=94=AF=E6=8C=81=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E7=B1=BB=E5=9E=8B=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当参数指定为列表类型时,验证和处理逻辑现在会检查 vec_store 是否为空或大小为0,而不是检查 str_store。 fix(hir): 初始化聚合类型值的数据结构 在 HIR 值初始化过程中,为聚合类型添加适当的初始化逻辑, 确保其字段向量被正确初始化。 refactor(hir_builder): 优化指针类型创建和GEP操作实现 - 简化全局分配器中的指针类型创建代码 - 扩展 GEP 操作以支持结构体和联合体字段访问 - 添加字段偏移计算支持 feat(hir_dump): 增强HIR类型和值的线性转储功能 - 实现类型定义的线性转储输出 - 改进结构体和联合体的转储格式 - 优化聚合值的转储表示 perf(hir_layout): 优化类型布局计算性能 改进结构体、联合体和聚合类型的对齐和大小计算算法, 提高字段偏移计算的准确性。 fix(hir_module): 完善模块资源清理机制 在模块析构时正确释放结构体和联合体类型的字段向量内存。 docs(lir): 更新文档注释中的空值表示 将初始化数据参数的空值描述从 NULL 统一为 nullptr。 refactor(hir2lir): 改进HIR到LIR的类型转换逻辑 - 重构类型到LIR大小扩展的转换函数 - 修复STORE指令的类型推导逻辑 - 增强GEP指令的规模因子和偏移量计算 - 添加对结构体/联合体字段访问的支持 refactor(x86_isel): 优化x86-64地址加载指令生成 改进LOAD_ADDR指令生成,更好地支持结构体字段访问的零比例因子。 docs(ir2mcode): 统一空值表示文档注释 更新初始化数据参数的空值描述为nullptr。 refactor(lexer): 简化词法分析器非空白标记预览逻辑 优化非空白标记预览函数,减少不必要的标记消费和销毁操作。 --- libs/argparse/src/argparse.c | 28 ++- libs/ir/hir/src/scc_hir.c | 3 + libs/ir/hir/src/scc_hir_builder.c | 59 +++++-- libs/ir/hir/src/scc_hir_dump.c | 87 ++++++--- libs/ir/hir/src/scc_hir_layout.c | 40 +++-- libs/ir/hir/src/scc_hir_module.c | 10 +- libs/ir/lir/include/scc_lir_module.h | 2 +- libs/ir/lir/src/scc_hir2lir.c | 104 +++++++---- libs/ir/mir/src/arch/scc_x86_isel.c | 72 ++++---- libs/ir2mcode/src/scc_ir2sccf.c | 2 +- libs/lexer/include/scc_lexer_utils.h | 3 +- libs/parser/src/parse_expr.c | 52 ++++-- libs/parser/src/scc_sema.c | 166 +++++++++++++++++- libs/pproc/src/pproc_expand.c | 1 + libs/target/type_abi/include/scc_type_abi.h | 16 +- .../include/scc_type_abi_systemv_x64.h | 11 +- .../type_abi/include/scc_type_abi_win_x64.h | 4 +- 17 files changed, 486 insertions(+), 174 deletions(-) diff --git a/libs/argparse/src/argparse.c b/libs/argparse/src/argparse.c index 294da8e..24f9484 100644 --- a/libs/argparse/src/argparse.c +++ b/libs/argparse/src/argparse.c @@ -171,12 +171,20 @@ static int validate_and_cleanup(scc_argparse_context_t *ctx, scc_vec_foreach(ctx->current_cmd->args, i) { scc_argparse_arg_t *arg = &scc_vec_at(ctx->current_cmd->args, i); if (arg->spec.flag_required) { - // 检查是否已存储(非空) - if (arg->spec.store.str_store == nullptr || - *arg->spec.store.str_store == nullptr) { - errcode = SCC_ARGPARSE_ERR_MISSING_ARG; - ctx->err_ctx = arg->name; - goto END; + if (arg->spec.value_type == SCC_ARGPARSE_VAL_TYPE_LIST) { + if (arg->spec.store.vec_store == nullptr || + scc_vec_size(*arg->spec.store.vec_store) == 0) { + errcode = SCC_ARGPARSE_ERR_MISSING_ARG; + ctx->err_ctx = arg->name; + goto END; + } + } else { + if (arg->spec.store.str_store == nullptr || + *arg->spec.store.str_store == nullptr) { + errcode = SCC_ARGPARSE_ERR_MISSING_ARG; + ctx->err_ctx = arg->name; + goto END; + } } } } @@ -265,9 +273,13 @@ static int handle_positional_arg(scc_argparse_context_t *ctx, if (ctx->positional_index < (int)scc_vec_size(ctx->current_cmd->args)) { scc_argparse_arg_t *arg = &scc_vec_at(ctx->current_cmd->args, ctx->positional_index); - *arg->spec.store.str_store = ctx->result.value; + if (arg->spec.value_type == SCC_ARGPARSE_VAL_TYPE_LIST) { + scc_vec_push(*arg->spec.store.vec_store, ctx->result.value); + } else { + *arg->spec.store.str_store = ctx->result.value; + ctx->positional_index++; + } arg->spec.raw_value = ctx->result.value; - ctx->positional_index++; } else { ctx->parsing_done = true; return SCC_ARGPARSE_ERR_UNKNOWN_ARG; diff --git a/libs/ir/hir/src/scc_hir.c b/libs/ir/hir/src/scc_hir.c index f509725..51d5ff2 100644 --- a/libs/ir/hir/src/scc_hir.c +++ b/libs/ir/hir/src/scc_hir.c @@ -117,6 +117,9 @@ void scc_hir_value_init(scc_hir_value_t *in, const char *name, in->data.conv.operand = 0; in->data.conv.target_type = 0; break; + case SCC_HIR_VALUE_TAG_AGGREGATE: + scc_vec_init(in->data.aggregate.fields); + break; default: UNREACHABLE(); break; diff --git a/libs/ir/hir/src/scc_hir_builder.c b/libs/ir/hir/src/scc_hir_builder.c index 466dabc..d65e33b 100644 --- a/libs/ir/hir/src/scc_hir_builder.c +++ b/libs/ir/hir/src/scc_hir_builder.c @@ -492,10 +492,9 @@ scc_hir_value_ref_t scc_hir_builder_global_alloca(scc_hir_builder_t *builder, scc_hir_type_ref_t type, scc_hir_value_ref_t value) { SCC_HIR_BUILDER_CHECK_NO_BORROW(builder); - // 全局变量的实际类型是指向 type 的指针 - scc_hir_type_t ptr_type = {.tag = SCC_HIR_TYPE_PTR, - .data.pointer.base = type}; - scc_hir_type_ref_t ptr_type_ref = scc_hir_builder_type(builder, &ptr_type); + scc_hir_type_ref_t ptr_type_ref = scc_hir_builder_type( + builder, + &(scc_hir_type_t){.tag = SCC_HIR_TYPE_PTR, .data.pointer.base = type}); // FIXME char *name = scc_malloc(32); @@ -612,28 +611,52 @@ scc_hir_value_ref_t scc_hir_builder_get_elem_ptr(scc_hir_builder_t *builder, builder, type_ref, scc_hir_module_get_type_by_value(GET_MODULE(builder), target)); Assert(type_ref != nullptr); - scc_hir_type_t type = *type_ref; // 拷贝一份,避免后续借用 + scc_hir_type_t val_type = *type_ref; // 拷贝一份,避免后续借用 SCC_HIR_BUILDER_END_BORROW(builder); // type_ref - if (type.tag == SCC_HIR_TYPE_PTR) { + if (val_type.tag == SCC_HIR_TYPE_PTR) { + scc_hir_type_ref_t base_ref = val_type.data.pointer.base; scc_hir_type_t *base_type = nullptr; SCC_HIR_BUILDER_BEGIN_BORROW( builder, base_type, - scc_hir_module_get_type(GET_MODULE(builder), - type_ref->data.pointer.base)); - if (base_type->tag == SCC_HIR_TYPE_ARRAY) { - scc_hir_type_t type = (scc_hir_type_t){ - .tag = SCC_HIR_TYPE_PTR, - .data.pointer.base = base_type->data.array.base, - }; - SCC_HIR_BUILDER_END_BORROW(builder); // base_type - get_ptr_node.type = scc_hir_builder_type(builder, &type); + scc_hir_module_get_type(GET_MODULE(builder), base_ref)); + Assert(base_type != nullptr); + scc_hir_type_tag_t base_tag = base_type->tag; + + if (base_tag == SCC_HIR_TYPE_ARRAY) { + // 数组 GEP:返回指向元素类型的指针 + scc_hir_type_ref_t elem_ref = base_type->data.array.base; + SCC_HIR_BUILDER_END_BORROW(builder); + get_ptr_node.type = + scc_hir_builder_type(builder, &(scc_hir_type_t){ + .tag = SCC_HIR_TYPE_PTR, + .data.pointer.base = elem_ref, + }); + } else if (base_tag == SCC_HIR_TYPE_STRUCT || + base_tag == SCC_HIR_TYPE_UNION) { + // 结构体/联合体 GEP:index 是字段编号,返回指向字段类型的指针 + usize field_idx = 0; + scc_hir_value_t *idx_val = + scc_hir_module_get_value(GET_MODULE(builder), index); + if (idx_val && idx_val->tag == SCC_HIR_VALUE_TAG_INTEGER) { + field_idx = (usize)idx_val->data.integer.data.digit; + } + Assert(field_idx < scc_vec_size(base_type->data.aggregate.fields)); + scc_hir_type_ref_t field_ref = + scc_vec_at(base_type->data.aggregate.fields, field_idx); + SCC_HIR_BUILDER_END_BORROW(builder); + get_ptr_node.type = scc_hir_builder_type( + builder, &(scc_hir_type_t){ + .tag = SCC_HIR_TYPE_PTR, + .data.pointer.base = field_ref, + }); } else { - SCC_HIR_BUILDER_END_BORROW(builder); // base_type - get_ptr_node.type = scc_hir_builder_type(builder, &type); + // 其他类型:保持原指针类型 + SCC_HIR_BUILDER_END_BORROW(builder); + get_ptr_node.type = scc_hir_builder_type(builder, &val_type); } } else { - get_ptr_node.type = scc_hir_builder_type(builder, &type); + get_ptr_node.type = scc_hir_builder_type(builder, &val_type); } scc_hir_value_ref_t value_ref = diff --git a/libs/ir/hir/src/scc_hir_dump.c b/libs/ir/hir/src/scc_hir_dump.c index eccdeff..3780c06 100644 --- a/libs/ir/hir/src/scc_hir_dump.c +++ b/libs/ir/hir/src/scc_hir_dump.c @@ -79,17 +79,16 @@ static const char *get_type_tag_str(scc_hir_type_tag_t tag) { static void dump_type_linear_with_visited(scc_hir_dump_t *ctx, scc_hir_type_ref_t type_ref, - scc_hashtable_t *visited) { + scc_hashtable_t *visited, + cbool extened) { if (!ctx || !type_ref) { LOG_ERROR("invalid parameter"); return; } // 检查循环 if (scc_hashtable_get(visited, (void *)(usize)type_ref)) { - scc_tree_dump_append(ctx->dump_ctx, " "); - return; + extened = false; } - scc_hashtable_set(visited, (void *)(usize)type_ref, (void *)1); scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref); if (!type) { @@ -117,12 +116,14 @@ static void dump_type_linear_with_visited(scc_hir_dump_t *ctx, break; case SCC_HIR_TYPE_ARRAY: scc_tree_dump_append(ctx->dump_ctx, "["); - dump_type_linear_with_visited(ctx, type->data.array.base, visited); + dump_type_linear_with_visited(ctx, type->data.array.base, visited, + extened); scc_tree_dump_append_fmt(ctx->dump_ctx, ", %zu]", type->data.array.len); break; case SCC_HIR_TYPE_PTR: scc_tree_dump_append(ctx->dump_ctx, "*"); - dump_type_linear_with_visited(ctx, type->data.pointer.base, visited); + dump_type_linear_with_visited(ctx, type->data.pointer.base, visited, + extened); break; case SCC_HIR_TYPE_FUNC: scc_tree_dump_append(ctx->dump_ctx, "("); @@ -130,25 +131,39 @@ static void dump_type_linear_with_visited(scc_hir_dump_t *ctx, if (i > 0) scc_tree_dump_append(ctx->dump_ctx, ", "); dump_type_linear_with_visited( - ctx, scc_vec_at(type->data.function.params, i), visited); + ctx, scc_vec_at(type->data.function.params, i), visited, + extened); } if (type->data.function.ret_type) { scc_tree_dump_append(ctx->dump_ctx, ") -> "); dump_type_linear_with_visited(ctx, type->data.function.ret_type, - visited); + visited, extened); } else { scc_tree_dump_append(ctx->dump_ctx, ")"); } break; case SCC_HIR_TYPE_STRUCT: case SCC_HIR_TYPE_UNION: - scc_tree_dump_append_fmt(ctx->dump_ctx, "%s {", - type->tag == SCC_HIR_TYPE_STRUCT ? "struct" - : "union"); - for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) { - dump_type_linear_with_visited( - ctx, scc_vec_at(type->data.aggregate.fields, i), visited); - scc_tree_dump_append(ctx->dump_ctx, ";"); + scc_hashtable_set(visited, (void *)(usize)type_ref, (void *)1); + const char *tag_name = + type->tag == SCC_HIR_TYPE_STRUCT ? "struct" : "union"; + if (type->name) { + scc_tree_dump_append_fmt(ctx->dump_ctx, "%s %s {", tag_name, + type->name); + } else { + scc_tree_dump_append_fmt(ctx->dump_ctx, "%s T%u {", tag_name, + type_ref); + } + if (extened) { + for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); + i++) { + dump_type_linear_with_visited( + ctx, scc_vec_at(type->data.aggregate.fields, i), visited, + extened); + scc_tree_dump_append(ctx->dump_ctx, ";"); + } + } else { + scc_tree_dump_append(ctx->dump_ctx, "..."); } scc_tree_dump_append(ctx->dump_ctx, "}"); break; @@ -162,9 +177,29 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx, scc_hir_type_ref_t type_ref) { scc_hashtable_t visited; scc_hashtable_usize_init(&visited); - dump_type_linear_with_visited(ctx, type_ref, &visited); + dump_type_linear_with_visited(ctx, type_ref, &visited, false); scc_hashtable_drop(&visited); } +static void scc_hir_dump_types_linear(scc_hir_dump_t *ctx) { + scc_hir_module_t *module = GET_MODULE(ctx); + // 遍历所有类型(跳过索引0,保留给无效引用) + for (usize i = 1; i < scc_vec_size(module->types); i++) { + scc_hir_type_t *type = &module->types.data[i]; + if (type->tag == SCC_HIR_TYPE_unknown) + continue; + + scc_hashtable_t visited; + scc_hashtable_usize_init(&visited); + + scc_tree_dump_begin_line(ctx->dump_ctx); + scc_tree_dump_node(ctx->dump_ctx, "T%u", (unsigned)i); + scc_tree_dump_append(ctx->dump_ctx, " = "); + dump_type_linear_with_visited(ctx, (scc_hir_type_ref_t)i, &visited, + true); + + scc_hashtable_drop(&visited); + } +} static void format_ref_or_value(scc_hir_dump_t *ctx, scc_hir_value_ref_t value_ref) { @@ -249,12 +284,18 @@ void scc_hir_dump_value_linear(scc_hir_dump_t *ctx, // 值已经在 format 中输出,这里不需要再做 break; case SCC_HIR_VALUE_TAG_AGGREGATE: - // 聚合类型:递归输出每个元素(每个占一行) - scc_vec_foreach(value->data.aggregate.fields, i) { - scc_hir_dump_value_linear( - ctx, scc_vec_at(value->data.aggregate.fields, i)); - scc_tree_dump_append(ctx->dump_ctx, "\n"); + scc_tree_dump_append(ctx->dump_ctx, "{"); + if (scc_vec_size(value->data.aggregate.fields) > 0) { + scc_tree_dump_push(ctx->dump_ctx, true); + scc_vec_foreach(value->data.aggregate.fields, i) { + scc_tree_dump_begin_line(ctx->dump_ctx); + scc_hir_dump_value_linear( + ctx, scc_vec_at(value->data.aggregate.fields, i)); + } + scc_tree_dump_pop(ctx->dump_ctx); + scc_tree_dump_begin_line(ctx->dump_ctx); } + scc_tree_dump_append(ctx->dump_ctx, "}"); return; case SCC_HIR_VALUE_TAG_ALLOC: scc_tree_dump_append(ctx->dump_ctx, "alloc"); @@ -325,8 +366,9 @@ void scc_hir_dump_value_linear(scc_hir_dump_t *ctx, value->data.arg_ref.idx); break; case SCC_HIR_VALUE_TAG_GLOBAL_ALLOC: - scc_tree_dump_append_fmt(ctx->dump_ctx, "global %s", value->name); + scc_tree_dump_append_fmt(ctx->dump_ctx, "global %s:", value->name); scc_tree_dump_begin_line(ctx->dump_ctx); + scc_tree_dump_append(ctx->dump_ctx, " "); if (value->data.global_alloc.value) { scc_hir_dump_value_linear(ctx, value->data.global_alloc.value); } else { @@ -422,6 +464,7 @@ void scc_hir_dump_func_linear(scc_hir_dump_t *ctx, scc_hir_func_ref_t func_ref, } void scc_hir_dump_cprog_linear(scc_hir_dump_t *ctx) { + scc_hir_dump_types_linear(ctx); for (usize i = 0; i < scc_vec_size(ctx->cprog->global_vals); i++) { scc_tree_dump_begin_line(ctx->dump_ctx); scc_hir_dump_value_linear(ctx, scc_vec_at(ctx->cprog->global_vals, i)); diff --git a/libs/ir/hir/src/scc_hir_layout.c b/libs/ir/hir/src/scc_hir_layout.c index e08a783..e4a6184 100644 --- a/libs/ir/hir/src/scc_hir_layout.c +++ b/libs/ir/hir/src/scc_hir_layout.c @@ -45,7 +45,8 @@ int scc_hir_type_align(scc_hir_module_t *mod, scc_hir_type_ref_t ref, scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i); int fa_bits = scc_hir_type_align(mod, fr, abi); int fs_bits = scc_hir_type_size(mod, fr, abi); - int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; + int fa2_bits = + scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; if (fa2_bits > max_align_bits) max_align_bits = fa2_bits; } @@ -116,14 +117,16 @@ int scc_hir_type_size(scc_hir_module_t *mod, scc_hir_type_ref_t ref, scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, i); int fs_bits = scc_hir_type_size(mod, fr, abi); int fa_bits = scc_hir_type_align(mod, fr, abi); - int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; + int fa2_bits = + scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; offset_bits = SCC_ALIGN_UP(offset_bits, fa2_bits); offset_bits += fs_bits; if (fa2_bits > max_align_bits) max_align_bits = fa2_bits; } - return SCC_ALIGN_UP(offset_bits, - scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8); + return SCC_ALIGN_UP( + offset_bits, + scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8); } case SCC_HIR_TYPE_UNION: { @@ -137,8 +140,9 @@ int scc_hir_type_size(scc_hir_module_t *mod, scc_hir_type_ref_t ref, if (fa_bits > max_align_bits) max_align_bits = fa_bits; } - return SCC_ALIGN_UP(max_size_bits, - scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8); + return SCC_ALIGN_UP( + max_size_bits, + scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8); } default: @@ -149,8 +153,8 @@ int scc_hir_type_size(scc_hir_module_t *mod, scc_hir_type_ref_t ref, int scc_hir_field_offset(scc_hir_module_t *mod, scc_hir_type_ref_t ref, int field_idx, const scc_type_abi_t *abi) { scc_hir_type_t *type = scc_hir_module_get_type(mod, ref); - if (!type || (type->tag != SCC_HIR_TYPE_STRUCT && - type->tag != SCC_HIR_TYPE_UNION)) + if (!type || + (type->tag != SCC_HIR_TYPE_STRUCT && type->tag != SCC_HIR_TYPE_UNION)) return 0; if (type->tag == SCC_HIR_TYPE_UNION) @@ -162,10 +166,12 @@ int scc_hir_field_offset(scc_hir_module_t *mod, scc_hir_type_ref_t ref, return 0; for (int i = 0; i < count; i++) { - scc_hir_type_ref_t fr = scc_vec_at(type->data.aggregate.fields, (usize)i); + scc_hir_type_ref_t fr = + scc_vec_at(type->data.aggregate.fields, (usize)i); int fs_bits = scc_hir_type_size(mod, fr, abi); int fa_bits = scc_hir_type_align(mod, fr, abi); - int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; + int fa2_bits = + scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; offset_bits = SCC_ALIGN_UP(offset_bits, fa2_bits); if (i == field_idx) return offset_bits; @@ -178,9 +184,9 @@ scc_hir_aggregate_layout_t * scc_hir_aggregate_layout(scc_hir_module_t *mod, scc_hir_type_ref_t ref, const scc_type_abi_t *abi) { scc_hir_type_t *type = scc_hir_module_get_type(mod, ref); - if (!type || (type->tag != SCC_HIR_TYPE_STRUCT && - type->tag != SCC_HIR_TYPE_UNION)) - return NULL; + if (!type || + (type->tag != SCC_HIR_TYPE_STRUCT && type->tag != SCC_HIR_TYPE_UNION)) + return nullptr; int fc = (int)scc_vec_size(type->data.aggregate.fields); @@ -226,7 +232,8 @@ scc_hir_aggregate_layout(scc_hir_module_t *mod, scc_hir_type_ref_t ref, scc_vec_at(type->data.aggregate.fields, (usize)i); int fs_bits = scc_hir_type_size(mod, fr, abi); int fa_bits = scc_hir_type_align(mod, fr, abi); - int fa2_bits = scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; + int fa2_bits = + scc_type_abi_get_field_align(abi, fs_bits / 8, fa_bits / 8) * 8; offset_bits = SCC_ALIGN_UP(offset_bits, fa2_bits); al->fields[i].offset = offset_bits; @@ -238,8 +245,9 @@ scc_hir_aggregate_layout(scc_hir_module_t *mod, scc_hir_type_ref_t ref, max_align_bits = fa2_bits; } - al->size = SCC_ALIGN_UP(offset_bits, - scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8); + al->size = SCC_ALIGN_UP( + offset_bits, + scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8); al->align = scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8; return al; } diff --git a/libs/ir/hir/src/scc_hir_module.c b/libs/ir/hir/src/scc_hir_module.c index 2e713aa..2f910aa 100644 --- a/libs/ir/hir/src/scc_hir_module.c +++ b/libs/ir/hir/src/scc_hir_module.c @@ -46,8 +46,16 @@ void scc_hir_module_drop(scc_hir_module_t *ctx) { for (usize i = 1; i < ctx->types.size; i++) { scc_hir_type_t *type = &ctx->types.data[i]; - if (type->tag == SCC_HIR_TYPE_FUNC) { + switch (type->tag) { + case SCC_HIR_TYPE_FUNC: scc_vec_free(type->data.function.params); + break; + case SCC_HIR_TYPE_STRUCT: + case SCC_HIR_TYPE_UNION: + scc_vec_free(type->data.aggregate.fields); + break; + default: + break; } } diff --git a/libs/ir/lir/include/scc_lir_module.h b/libs/ir/lir/include/scc_lir_module.h index ceb3886..1983908 100644 --- a/libs/ir/lir/include/scc_lir_module.h +++ b/libs/ir/lir/include/scc_lir_module.h @@ -44,7 +44,7 @@ scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *lir_module, * @param mod 模块 * @param name 符号名 * @param kind 种类 (DATA 或 EXTERN) - * @param init_data 初始化数据 (若为 DATA 定义;若为 NULL 则零初始化) + * @param init_data 初始化数据 (若为 DATA 定义;若为 nullptr 则零初始化) * @param size 数据大小 (若为 EXTERN 可为 0) * @param align 对齐要求 * @param attr 属性 diff --git a/libs/ir/lir/src/scc_hir2lir.c b/libs/ir/lir/src/scc_hir2lir.c index cec0ae6..c198eed 100644 --- a/libs/ir/lir/src/scc_hir2lir.c +++ b/libs/ir/lir/src/scc_hir2lir.c @@ -38,8 +38,15 @@ static scc_lir_val_t ir_value_to_lir_operand(ir2lir_ctx_t *ctx, static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, scc_hir_value_ref_t value_ref); -static void ir_type_to_lir_size_ext(scc_hir_type_t *type, u8 *out_size, +static void ir_type_to_lir_size_ext(scc_hir_module_t *mod, + scc_hir_type_ref_t type_ref, u8 *out_size, scc_lir_ext_t *out_ext) { + scc_hir_type_t *type = scc_hir_module_get_type(mod, type_ref); + if (!type) { + *out_size = 0; + *out_ext = SCC_LIR_EXT_NONE; + return; + } switch (type->tag) { case SCC_HIR_TYPE_i8: *out_size = SCC_LIR_SIZE_8; @@ -90,6 +97,11 @@ static void ir_type_to_lir_size_ext(scc_hir_type_t *type, u8 *out_size, *out_size = 0; *out_ext = SCC_LIR_EXT_NONE; break; + case SCC_HIR_TYPE_STRUCT: + case SCC_HIR_TYPE_UNION: + *out_size = (u8)scc_hir_module_type_size(mod, type_ref); + *out_ext = SCC_LIR_EXT_NONE; + break; default: Panic("unsupported IR type in lowering at %d", type->tag); } @@ -311,12 +323,10 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, if (scc_hashtable_get(&ctx->value_to_vreg, (void *)(uintptr_t)value_ref)) return; - scc_hir_type_t *ty = scc_hir_module_get_type(ctx->hir_module, value->type); u8 size_bits = 0; scc_lir_ext_t ext = SCC_LIR_EXT_NONE; - if (ty != nullptr) { - ir_type_to_lir_size_ext(ty, &size_bits, &ext); - } + ir_type_to_lir_size_ext(ctx->hir_module, value->type, &size_bits, &ext); + scc_hir_type_t *ty = scc_hir_module_get_type(ctx->hir_module, value->type); bool is_float = (ext == SCC_LIR_EXT_FLOAT); int dst_vreg = get_vreg_for_value(ctx, value_ref); @@ -361,15 +371,11 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, /* 修复: 使用目标指针的元素类型确定 store 宽度而非源值类型 */ scc_hir_type_t *ptr_type = scc_hir_module_get_type_by_value( ctx->hir_module, value->data.store.target); + scc_hir_type_ref_t store_type = value->data.store.value; if (ptr_type && ptr_type->tag == SCC_HIR_TYPE_PTR) { - scc_hir_type_t *elem_type = scc_hir_module_get_type( - ctx->hir_module, ptr_type->data.pointer.base); - ir_type_to_lir_size_ext(elem_type, &size_bits, &ext); - } else { - ty = scc_hir_module_get_type_by_value(ctx->hir_module, - value->data.store.value); - ir_type_to_lir_size_ext(ty, &size_bits, &ext); + store_type = ptr_type->data.pointer.base; } + ir_type_to_lir_size_ext(ctx->hir_module, store_type, &size_bits, &ext); scc_lir_instr_t instr = {.op = SCC_LIR_STORE, .ext = ext, .size_bits = size_bits, @@ -378,25 +384,50 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, scc_lir_builder_add_instr(ctx, &instr); } break; case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: { - // 1. 获取基址和索引的 LIR 操作数 scc_lir_val_t base = ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.src_addr); scc_lir_val_t index = ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.index); - // 2. 获取元素类型和大小 - scc_hir_type_t *ptr_type = - scc_hir_module_get_type(ctx->hir_module, value->type); - scc_hir_type_ref_t pointee = SCC_CFG_ID_nullptr; - if (ptr_type->tag == SCC_HIR_TYPE_PTR) { - pointee = ptr_type->data.pointer.base; - } else if (ptr_type->tag == SCC_HIR_TYPE_ARRAY) { - // 数组名退化为指针,元素类型为数组的元素类型 - pointee = ptr_type->data.array.base; - } else { - Panic("GET_ELEM_PTR on non-pointer/array type"); + // 获取 src_addr 的原始指针类型,判断是否为结构体字段访问 + scc_hir_type_t *src_type = scc_hir_module_get_type_by_value( + ctx->hir_module, value->data.get_elem_ptr.src_addr); + int scale = 0, offset = 0; + + if (src_type && src_type->tag == SCC_HIR_TYPE_PTR) { + scc_hir_type_ref_t pointee_ref = src_type->data.pointer.base; + scc_hir_type_t *pointee = + scc_hir_module_get_type(ctx->hir_module, pointee_ref); + if (pointee && (pointee->tag == SCC_HIR_TYPE_STRUCT || + pointee->tag == SCC_HIR_TYPE_UNION)) { + // 结构体/联合体字段 GEP:使用字段字节偏移 + int field_idx = 0; + scc_hir_value_t *idx_val = scc_hir_module_get_value( + ctx->hir_module, value->data.get_elem_ptr.index); + if (idx_val && idx_val->tag == SCC_HIR_VALUE_TAG_INTEGER) { + field_idx = (int)idx_val->data.integer.data.digit; + } + offset = scc_hir_field_offset(ctx->hir_module, pointee_ref, + field_idx, ctx->hir_module->abi) / + 8; + } else if (pointee && pointee->tag == SCC_HIR_TYPE_ARRAY) { + // 数组 GEP:index * elem_size + scc_hir_type_ref_t elem_ref = pointee->data.array.base; + int elem_size_bits = + scc_hir_module_type_size(ctx->hir_module, elem_ref); + scale = elem_size_bits / 8; + } else { + // 其他类型:按元素大小缩放 + int elem_size_bits = + scc_hir_module_type_size(ctx->hir_module, pointee_ref); + scale = elem_size_bits / 8; + } + } else if (src_type && src_type->tag == SCC_HIR_TYPE_ARRAY) { + scc_hir_type_ref_t elem_ref = src_type->data.array.base; + int elem_size_bits = + scc_hir_module_type_size(ctx->hir_module, elem_ref); + scale = elem_size_bits / 8; } - int elem_size_bits = scc_hir_module_type_size(ctx->hir_module, pointee); int dst_vreg = get_vreg_for_value(ctx, value_ref); scc_lir_instr_t instr = { @@ -405,9 +436,8 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, .to = SCC_LIR_VREG(dst_vreg), .arg0 = base, .arg1 = index, - // FIXME - .metadata.addr.scale = elem_size_bits / 8, - .metadata.addr.offset = 0, + .metadata.addr.scale = scale, + .metadata.addr.offset = offset, }; scc_lir_builder_add_instr(ctx, &instr); } break; @@ -556,11 +586,10 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, } case SCC_HIR_BUILTIN_TAG_VA_ARG: { // 需要从类型中获取大小和对齐以及是否为浮点 - scc_hir_type_t *ty = - scc_hir_module_get_type(ctx->hir_module, b->func.va_arg.type); u8 size = 0; scc_lir_ext_t ext = SCC_LIR_EXT_NONE; - ir_type_to_lir_size_ext(ty, &size, &ext); + ir_type_to_lir_size_ext(ctx->hir_module, b->func.va_arg.type, &size, + &ext); bool is_float = (ext == SCC_LIR_EXT_FLOAT); scc_lir_val_t ap = ir_value_to_lir_operand(ctx, b->func.va_arg.ap); scc_lir_instr_t instr = { @@ -598,6 +627,13 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, } break; case SCC_HIR_VALUE_TAG_FUNC_ARG_REF: case SCC_HIR_VALUE_TAG_BLOCK_ARG_REF: + case SCC_HIR_VALUE_TAG_INTEGER: + case SCC_HIR_VALUE_TAG_DECIMAL: + case SCC_HIR_VALUE_TAG_NULLPTR: + case SCC_HIR_VALUE_TAG_ARRAY: + case SCC_HIR_VALUE_TAG_AGGREGATE: + case SCC_HIR_VALUE_TAG_GLOBAL_ALLOC: + // 常量/全局值:不需要生成指令,由 ir_value_to_lir_operand 处理 break; default: Panic("unsupported opcode %d", value->tag); @@ -672,7 +708,11 @@ void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) { &cprog->module, galloc->data.global_alloc.value); scc_lir_symbol_id_t id = SCC_CFG_ID_nullptr; - int size = scc_hir_module_type_size(&cprog->module, val->type); + scc_hir_type_t *gtype = + scc_hir_module_get_type(&cprog->module, galloc->type); + Assert(gtype->tag == SCC_HIR_TYPE_PTR); + int size = + scc_hir_module_type_size(&cprog->module, gtype->data.pointer.base); Assert(size > 0); if (val == nullptr) { // TODO char == 8 bit diff --git a/libs/ir/mir/src/arch/scc_x86_isel.c b/libs/ir/mir/src/arch/scc_x86_isel.c index 4f44aeb..63ebaea 100644 --- a/libs/ir/mir/src/arch/scc_x86_isel.c +++ b/libs/ir/mir/src/arch/scc_x86_isel.c @@ -266,58 +266,60 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, i64 offset) { usize size_bits = dst.size_bits; Assert(size_bits == 64); - // 前置断言:dst 必须是寄存器 Assert(dst.kind == SCC_X86_OPR_REG); - // scale 必须是 1,2,4,8 之一 - Assert(scale == 1 || scale == 2 || scale == 4 || scale == 8); // ---- 处理 base ---- scc_x86_operand_value_t base_reg = base; switch (base.kind) { - case SCC_X86_OPR_REG: { - base_reg = base; - } break; - case SCC_X86_OPR_RELOC: { + case SCC_X86_OPR_REG: + break; + case SCC_X86_OPR_RELOC: Assert(base.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL); base_reg = new_vreg_temp(isel, 64); scc_x86_emit_move(isel, base_reg, base); - } break; - case SCC_X86_OPR_MEM: { + break; + case SCC_X86_OPR_MEM: base_reg = new_vreg_temp(isel, 64); scc_x86_emit_move(isel, base_reg, base); - } break; - default: { + break; + default: Panic("Unsupported base kind %d in load_addr", base.kind); } - } - scc_x86_operand_value_t index_reg = index; - switch (index.kind) { - case SCC_X86_OPR_REG: { - index_reg = index; - } break; - case SCC_X86_OPR_RELOC: { - Assert(index.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL); - index_reg = new_vreg_temp(isel, 64); - scc_x86_emit_move(isel, index_reg, index); - } break; - case SCC_X86_OPR_MEM: { - index_reg = new_vreg_temp(isel, 64); - scc_x86_emit_move(isel, index_reg, index); - } break; - case SCC_X86_OPR_IMM: { - index_reg = new_vreg_temp(isel, index.size_bits); - scc_x86_emit_move(isel, index_reg, index); - } break; - default: { - Panic("Unsupported index kind %d in load_addr", base.kind); - } + // ---- 处理 index 和 scale ---- + // scale=0 表示 struct/union 字段 GEP:字段索引已被折叠进 offset, + // x86-64 SIB 不支持 scale=0,所以跳 index register,直接用 base+disp + scc_x86_reg_t index_reg = SCC_X86_REG_INVALID; + int sib_scale = 1; + if (scale != 0) { + Assert(scale == 1 || scale == 2 || scale == 4 || scale == 8); + sib_scale = scale; + switch (index.kind) { + case SCC_X86_OPR_REG: + index_reg = index.reg; + break; + case SCC_X86_OPR_RELOC: + Assert(index.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL); + index_reg = new_vreg_temp(isel, 64).reg; + scc_x86_emit_move(isel, scc_x86_op_preg(index_reg, 64), index); + break; + case SCC_X86_OPR_MEM: + index_reg = new_vreg_temp(isel, 64).reg; + scc_x86_emit_move(isel, scc_x86_op_preg(index_reg, 64), index); + break; + case SCC_X86_OPR_IMM: + index_reg = new_vreg_temp(isel, index.size_bits).reg; + scc_x86_emit_move(isel, scc_x86_op_preg(index_reg, 64), index); + break; + default: + Panic("Unsupported index kind %d in load_addr", index.kind); + } } scc_x86_operand_value_t mem_op = scc_x86_op_mem((scc_x86_mem_t){.base = base_reg.reg, - .index = index_reg.reg, - .scale = scale, + .index = index_reg, + .scale = sib_scale, .disp.displacement = offset, .disp.displacement_bits = 8}, size_bits); diff --git a/libs/ir2mcode/src/scc_ir2sccf.c b/libs/ir2mcode/src/scc_ir2sccf.c index f44ca4c..3d19bef 100644 --- a/libs/ir2mcode/src/scc_ir2sccf.c +++ b/libs/ir2mcode/src/scc_ir2sccf.c @@ -39,7 +39,7 @@ static inline void scc_ir_symbol_to_sect_data(const scc_cfg_symbol_t *symbol, scc_vec_push(*sect_data, meta->data.init_data[i]); } // struct { - // u8 *init_data; // 初始化数据(若为 NULL 则零初始化) + // u8 *init_data; // 初始化数据(若为 nullptr 则零初始化) // usize size; // 数据大小(字节) // int align; // 对齐要求 // } data; diff --git a/libs/lexer/include/scc_lexer_utils.h b/libs/lexer/include/scc_lexer_utils.h index 2c403cf..0349d0b 100644 --- a/libs/lexer/include/scc_lexer_utils.h +++ b/libs/lexer/include/scc_lexer_utils.h @@ -22,8 +22,7 @@ static inline cbool scc_lexer_peek_non_blank(scc_lexer_tok_ring_t *stream, scc_ring_peek(*stream, *out, ok); if (!ok || out->type != SCC_TOK_BLANK) break; - scc_ring_next_consume(*stream, *out, ok); - scc_lexer_tok_drop(out); + scc_ring_next(*stream, *out, ok); } return ok; } diff --git a/libs/parser/src/parse_expr.c b/libs/parser/src/parse_expr.c index dbab538..bc08ee2 100644 --- a/libs/parser/src/parse_expr.c +++ b/libs/parser/src/parse_expr.c @@ -481,7 +481,8 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { scc_ast_expr_t *operand = parse_cast_expression(parser); if (!operand) { // FIXME postfix-expression - scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module); + scc_ast_expr_t *expr = + SCC_AST_ALLOC_EXPR(parser->ast_module); // FIXME pos scc_ast_expr_lvalue_init(expr, type, type->base.loc); operand = scc_parse_initializer(parser, expr); @@ -681,7 +682,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { case SCC_TOK_L_PAREN: // left(args) { if (!scc_parser_next_consume(parser, nullptr)) - return left; + goto done; pos = left->base.loc; scc_ast_expr_vec_t args; scc_vec_init(args); @@ -719,7 +720,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { case SCC_TOK_DEREF: { scc_lexer_tok_t op_tok; if (!scc_parser_next_consume(parser, &op_tok)) - return left; + goto done; scc_lexer_tok_t ident_tok; if (!scc_parser_next_consume(parser, &ident_tok) || ident_tok.type != SCC_TOK_IDENT) { @@ -729,18 +730,22 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { parser_sync(parser); return nullptr; } - const char *name = scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&ident_tok.lexeme)); + const char *name = scc_ast_module_intern( + parser->ast_module, scc_str_as_cstr(&ident_tok.lexeme)); scc_ast_expr_t *member = SCC_AST_ALLOC_EXPR(parser->ast_module); Assert(member != nullptr); if (op_tok.type == SCC_TOK_DOT) { scc_ast_expr_member_init(member, left, name, ident_tok.loc); - } else { + } else if (op_tok.type == SCC_TOK_DEREF) { scc_ast_expr_ptr_member_init(member, left, name, ident_tok.loc); + } else { + UNREACHABLE(); } scc_lexer_tok_drop(&op_tok); left = member; + scc_parse_expr_sema(parser, member); break; } case SCC_TOK_ADD_ADD: // left++ @@ -748,7 +753,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { { scc_lexer_tok_t op_tok; if (!scc_parser_next_consume(parser, &op_tok)) - return left; + goto done; scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false); scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module); Assert(expr != nullptr); @@ -762,6 +767,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { } } done: + scc_parse_expr_sema(parser, left); return left; } @@ -787,8 +793,11 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return nullptr; expr = SCC_AST_ALLOC_EXPR(parser->ast_module); Assert(expr != nullptr); - scc_ast_expr_identifier_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), - tok.loc); + scc_ast_expr_identifier_init( + expr, + scc_ast_module_intern(parser->ast_module, + scc_str_as_cstr(&tok.lexeme)), + tok.loc); break; } case SCC_TOK_INT_LITERAL: { @@ -796,8 +805,11 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return nullptr; expr = SCC_AST_ALLOC_EXPR(parser->ast_module); Assert(expr != nullptr); - scc_ast_expr_literal_int_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), false, - tok.loc); + scc_ast_expr_literal_int_init( + expr, + scc_ast_module_intern(parser->ast_module, + scc_str_as_cstr(&tok.lexeme)), + false, tok.loc); break; } case SCC_TOK_FLOAT_LITERAL: { @@ -805,8 +817,11 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return nullptr; expr = SCC_AST_ALLOC_EXPR(parser->ast_module); Assert(expr != nullptr); - scc_ast_expr_literal_float_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), - false, tok.loc); + scc_ast_expr_literal_float_init( + expr, + scc_ast_module_intern(parser->ast_module, + scc_str_as_cstr(&tok.lexeme)), + false, tok.loc); break; } case SCC_TOK_CHAR_LITERAL: { @@ -814,8 +829,11 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return nullptr; expr = SCC_AST_ALLOC_EXPR(parser->ast_module); Assert(expr != nullptr); - scc_ast_expr_literal_char_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), - false, tok.loc); + scc_ast_expr_literal_char_init( + expr, + scc_ast_module_intern(parser->ast_module, + scc_str_as_cstr(&tok.lexeme)), + false, tok.loc); break; } case SCC_TOK_STRING_LITERAL: { @@ -835,13 +853,13 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { scc_str_append(&string, &tmp); } - const char *pooled_str = scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&string)); + const char *pooled_str = + scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&string)); scc_str_drop(&string); expr = SCC_AST_ALLOC_EXPR(parser->ast_module); Assert(expr != nullptr); // FIXME loc - scc_ast_expr_literal_string_init(expr, pooled_str, false, - tok.loc); + scc_ast_expr_literal_string_init(expr, pooled_str, false, tok.loc); break; } case SCC_TOK_L_PAREN: diff --git a/libs/parser/src/scc_sema.c b/libs/parser/src/scc_sema.c index 64a73c1..757a9fa 100644 --- a/libs/parser/src/scc_sema.c +++ b/libs/parser/src/scc_sema.c @@ -36,8 +36,8 @@ static void symtab_add_symbol(scc_sema_symtab_t *sema_symtab, if (scc_str_is_empty(&name)) { scc_sema_symtab_add_symbol(sema_symtab, decl->name, ast_node_ref); } else { - const char *pooled = scc_strpool_intern(&sema_symtab->name_pool, - scc_str_as_cstr(&name)); + const char *pooled = + scc_strpool_intern(&sema_symtab->name_pool, scc_str_as_cstr(&name)); scc_sema_symtab_add_symbol(sema_symtab, pooled, ast_node_ref); scc_str_drop(&name); } @@ -58,6 +58,100 @@ static void type_callback(scc_sema_ctx_t *sema_ctx, return; } +/* ---------- 类型解析辅助函数 (用于成员访问) ---------- */ + +// 从 qual_type 解析到底层的 struct/union 声明(跟随 typedef 链) +static scc_ast_decl_t *resolve_to_struct_decl(scc_ast_qual_type_t *type) { + if (!type) + return nullptr; + + // 跟随 typedef 链 + while (type->base.type == SCC_AST_TYPE_TYPEDEF) { + if (!type->type || !type->type->typedef_type.decl) + return nullptr; + if (type->type->typedef_type.decl->base.type != SCC_AST_DECL_TYPEDEF) + return nullptr; + type = type->type->typedef_type.decl->typedef_decl.type; + if (!type) + return nullptr; + } + + if (type->base.type == SCC_AST_TYPE_STRUCT || + type->base.type == SCC_AST_TYPE_UNION) { + if (type->type) + return type->type->record.decl; + } + return nullptr; +} + +// 从表达式中解析出其 qual_type(用于确定基表达式的类型) +static scc_ast_qual_type_t *resolve_expr_qual_type(scc_sema_ctx_t *sema_ctx, + scc_ast_expr_t *expr) { + if (!expr) + return nullptr; + + switch (expr->base.type) { + case SCC_AST_EXPR_IDENTIFIER: { + scc_ast_decl_t *decl = expr->identifier._target; + if (!decl) + return nullptr; + if (decl->base.type == SCC_AST_DECL_VAR) + return decl->var.type; + if (decl->base.type == SCC_AST_DECL_PARAM) + return decl->param.type; + return nullptr; + } + case SCC_AST_EXPR_MEMBER: { + scc_ast_qual_type_t *base_type = + resolve_expr_qual_type(sema_ctx, expr->member.base); + if (!base_type) + return nullptr; + scc_ast_decl_t *sd = resolve_to_struct_decl(base_type); + if (!sd) + return nullptr; + scc_ast_decl_vec_t *fields = &sd->record.fields; + if (expr->member._target_idx >= scc_vec_size(*fields)) + return nullptr; + scc_ast_decl_t *field = scc_vec_at(*fields, expr->member._target_idx); + if (field->base.type == SCC_AST_DECL_VAR) + return field->var.type; + return nullptr; + } + case SCC_AST_EXPR_PTR_MEMBER: { + scc_ast_qual_type_t *base_type = + resolve_expr_qual_type(sema_ctx, expr->member.base); + if (!base_type || base_type->base.type != SCC_AST_TYPE_POINTER) + return nullptr; + scc_ast_qual_type_t *pointee = + base_type->type ? base_type->type->pointer.pointee : nullptr; + if (!pointee) + return nullptr; + scc_ast_decl_t *sd = resolve_to_struct_decl(pointee); + if (!sd) + return nullptr; + scc_ast_decl_vec_t *fields = &sd->record.fields; + if (expr->member._target_idx >= scc_vec_size(*fields)) + return nullptr; + scc_ast_decl_t *field = scc_vec_at(*fields, expr->member._target_idx); + if (field->base.type == SCC_AST_DECL_VAR) + return field->var.type; + return nullptr; + } + case SCC_AST_EXPR_UNARY: { + if (expr->unary.op == SCC_AST_OP_INDIRECTION) { + scc_ast_qual_type_t *op_type = + resolve_expr_qual_type(sema_ctx, expr->unary.operand); + if (!op_type || op_type->base.type != SCC_AST_TYPE_POINTER) + return nullptr; + return op_type->type ? op_type->type->pointer.pointee : nullptr; + } + return nullptr; + } + default: + return nullptr; + } +} + static void expr_callback(scc_sema_ctx_t *sema_ctx, scc_ast_node_kind_t node_type, void *node) { scc_sema_symtab_t *sema_symtab = sema_ctx->context; @@ -67,18 +161,78 @@ static void expr_callback(scc_sema_ctx_t *sema_ctx, } scc_ast_expr_t *expr = SCC_AST_CAST_TO(scc_ast_expr_t, node); if (node_type == SCC_AST_EXPR_IDENTIFIER) { - scc_ast_node_t *node = + scc_ast_node_t *sym_node = scc_sema_symtab_lookup_symbol(sema_symtab, expr->identifier.name); - if (node == nullptr) { + if (sym_node == nullptr) { SCC_ERROR(expr->base.loc, "sema error: Identifier '%s' not found", expr->identifier.name); - } else if (!SCC_AST_IS_A(scc_ast_decl_t, node)) { + } else if (!SCC_AST_IS_A(scc_ast_decl_t, sym_node)) { SCC_ERROR(expr->base.loc, "sema error: Identifier '%s' is not a variable", expr->identifier.name); } else { - expr->identifier._target = SCC_AST_CAST_TO(scc_ast_decl_t, node); + expr->identifier._target = + SCC_AST_CAST_TO(scc_ast_decl_t, sym_node); } + return; + } + + if (node_type == SCC_AST_EXPR_MEMBER || + node_type == SCC_AST_EXPR_PTR_MEMBER) { + scc_ast_expr_t *base = expr->member.base; + + // 获取基表达式的 qual_type + scc_ast_qual_type_t *base_type = resolve_expr_qual_type(sema_ctx, base); + if (!base_type) { + SCC_ERROR(expr->base.loc, + "cannot determine type for member access"); + return; + } + + // 对于 ->,基表达式应为指针类型,解引用得到目标 struct/union + scc_ast_decl_t *struct_decl = nullptr; + if (node_type == SCC_AST_EXPR_PTR_MEMBER) { + if (base_type->base.type != SCC_AST_TYPE_POINTER) { + SCC_ERROR(expr->base.loc, + "base expression of '->' must be a pointer"); + return; + } + scc_ast_qual_type_t *pointee = + base_type->type ? base_type->type->pointer.pointee : nullptr; + if (!pointee) { + SCC_ERROR(expr->base.loc, + "cannot dereference pointer for '->'"); + return; + } + struct_decl = resolve_to_struct_decl(pointee); + } else { + struct_decl = resolve_to_struct_decl(base_type); + } + + if (!struct_decl) { + SCC_ERROR(expr->base.loc, + "base expression is not a struct or union"); + return; + } + + // 按名称查找字段,计算 field index + scc_ast_decl_vec_t *fields = &struct_decl->record.fields; + cbool found = false; + for (usize i = 0; i < scc_vec_size(*fields); i++) { + scc_ast_decl_t *field = scc_vec_at(*fields, i); + if (field && field->name && + scc_strcmp(field->name, expr->member.name) == 0) { + expr->member._target_idx = i; + found = true; + break; + } + } + + if (!found) { + SCC_ERROR(expr->base.loc, "struct/union has no member '%s'", + expr->member.name); + } + return; } return; diff --git a/libs/pproc/src/pproc_expand.c b/libs/pproc/src/pproc_expand.c index bbfabc8..bd2fc5b 100644 --- a/libs/pproc/src/pproc_expand.c +++ b/libs/pproc/src/pproc_expand.c @@ -150,6 +150,7 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table, break; } } + scc_ring_reset(*input); scc_lexer_tok_vec_t output_vec; scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false, diff --git a/libs/target/type_abi/include/scc_type_abi.h b/libs/target/type_abi/include/scc_type_abi.h index 5f43b2d..8f2ed0a 100644 --- a/libs/target/type_abi/include/scc_type_abi.h +++ b/libs/target/type_abi/include/scc_type_abi.h @@ -9,7 +9,7 @@ typedef struct scc_type_abi scc_type_abi_t; struct scc_type_abi { int ptr_size; int ptr_align; - int endian; // 0 = little, 1 = big + int endian; // 0 = little, 1 = big // C 类型大小 (AST → HIR 时需要) int char_size; @@ -22,30 +22,30 @@ struct scc_type_abi { int long_double_size; int va_list_size; - // byte_size → 对齐。NULL = 自然对齐 (return byte_size) + // byte_size → 对齐。nullptr = 自然对齐 (return byte_size) int (*type_align)(int byte_size); - // 字段对齐覆盖。NULL = 用 type_align 的值 + // 字段对齐覆盖。nullptr = 用 type_align 的值 int (*field_align)(int field_size, int natural_align); - // 聚合体总对齐。NULL = max 字段 align + // 聚合体总对齐。nullptr = max 字段 align int (*aggregate_align)(int max_field_align); }; static inline int scc_type_abi_get_type_align(const scc_type_abi_t *abi, - int byte_size) { + int byte_size) { return abi->type_align ? abi->type_align(byte_size) : byte_size; } static inline int scc_type_abi_get_field_align(const scc_type_abi_t *abi, - int field_size, - int natural_align) { + int field_size, + int natural_align) { return abi->field_align ? abi->field_align(field_size, natural_align) : natural_align; } static inline int scc_type_abi_get_aggregate_align(const scc_type_abi_t *abi, - int max_field_align) { + int max_field_align) { return abi->aggregate_align ? abi->aggregate_align(max_field_align) : max_field_align; } diff --git a/libs/target/type_abi/include/scc_type_abi_systemv_x64.h b/libs/target/type_abi/include/scc_type_abi_systemv_x64.h index bf510fa..0e9d732 100644 --- a/libs/target/type_abi/include/scc_type_abi_systemv_x64.h +++ b/libs/target/type_abi/include/scc_type_abi_systemv_x64.h @@ -12,16 +12,17 @@ static const scc_type_abi_t SCC_TYPE_ABI_SYSTEMV_X64 = { .char_size = 1, .short_size = 2, .int_size = 4, - .long_size = 8, // SysV: long = 8 bytes + .long_size = 8, // SysV: long = 8 bytes .long_long_size = 8, .float_size = 4, .double_size = 8, - .long_double_size = 16, // SysV x86-64: long double = 80-bit extended precision, padded to 16 + .long_double_size = 16, // SysV x86-64: long double = 80-bit extended + // precision, padded to 16 .va_list_size = 8, - .type_align = NULL, - .field_align = NULL, - .aggregate_align = NULL, + .type_align = nullptr, + .field_align = nullptr, + .aggregate_align = nullptr, }; #endif /* __SCC_TYPE_ABI_SYSTEMV_X64_H__ */ diff --git a/libs/target/type_abi/include/scc_type_abi_win_x64.h b/libs/target/type_abi/include/scc_type_abi_win_x64.h index fb4cee4..267953f 100644 --- a/libs/target/type_abi/include/scc_type_abi_win_x64.h +++ b/libs/target/type_abi/include/scc_type_abi_win_x64.h @@ -27,9 +27,9 @@ static const scc_type_abi_t SCC_TYPE_ABI_WIN_X64 = { .long_double_size = 8, .va_list_size = 4, - .type_align = NULL, + .type_align = nullptr, .field_align = scc_win64_field_align, - .aggregate_align = NULL, + .aggregate_align = nullptr, }; #endif /* __SCC_TYPE_ABI_WIN_X64_H__ */