feat(argparse): 支持列表类型参数解析
当参数指定为列表类型时,验证和处理逻辑现在会检查 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): 简化词法分析器非空白标记预览逻辑 优化非空白标记预览函数,减少不必要的标记消费和销毁操作。
This commit is contained in:
@@ -171,12 +171,20 @@ static int validate_and_cleanup(scc_argparse_context_t *ctx,
|
|||||||
scc_vec_foreach(ctx->current_cmd->args, i) {
|
scc_vec_foreach(ctx->current_cmd->args, i) {
|
||||||
scc_argparse_arg_t *arg = &scc_vec_at(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.flag_required) {
|
||||||
// 检查是否已存储(非空)
|
if (arg->spec.value_type == SCC_ARGPARSE_VAL_TYPE_LIST) {
|
||||||
if (arg->spec.store.str_store == nullptr ||
|
if (arg->spec.store.vec_store == nullptr ||
|
||||||
*arg->spec.store.str_store == nullptr) {
|
scc_vec_size(*arg->spec.store.vec_store) == 0) {
|
||||||
errcode = SCC_ARGPARSE_ERR_MISSING_ARG;
|
errcode = SCC_ARGPARSE_ERR_MISSING_ARG;
|
||||||
ctx->err_ctx = arg->name;
|
ctx->err_ctx = arg->name;
|
||||||
goto END;
|
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)) {
|
if (ctx->positional_index < (int)scc_vec_size(ctx->current_cmd->args)) {
|
||||||
scc_argparse_arg_t *arg =
|
scc_argparse_arg_t *arg =
|
||||||
&scc_vec_at(ctx->current_cmd->args, ctx->positional_index);
|
&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;
|
arg->spec.raw_value = ctx->result.value;
|
||||||
ctx->positional_index++;
|
|
||||||
} else {
|
} else {
|
||||||
ctx->parsing_done = true;
|
ctx->parsing_done = true;
|
||||||
return SCC_ARGPARSE_ERR_UNKNOWN_ARG;
|
return SCC_ARGPARSE_ERR_UNKNOWN_ARG;
|
||||||
|
|||||||
@@ -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.operand = 0;
|
||||||
in->data.conv.target_type = 0;
|
in->data.conv.target_type = 0;
|
||||||
break;
|
break;
|
||||||
|
case SCC_HIR_VALUE_TAG_AGGREGATE:
|
||||||
|
scc_vec_init(in->data.aggregate.fields);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -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_type_ref_t type,
|
||||||
scc_hir_value_ref_t value) {
|
scc_hir_value_ref_t value) {
|
||||||
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
|
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
|
||||||
// 全局变量的实际类型是指向 type 的指针
|
scc_hir_type_ref_t ptr_type_ref = scc_hir_builder_type(
|
||||||
scc_hir_type_t ptr_type = {.tag = SCC_HIR_TYPE_PTR,
|
builder,
|
||||||
.data.pointer.base = type};
|
&(scc_hir_type_t){.tag = SCC_HIR_TYPE_PTR, .data.pointer.base = type});
|
||||||
scc_hir_type_ref_t ptr_type_ref = scc_hir_builder_type(builder, &ptr_type);
|
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
char *name = scc_malloc(32);
|
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,
|
builder, type_ref,
|
||||||
scc_hir_module_get_type_by_value(GET_MODULE(builder), target));
|
scc_hir_module_get_type_by_value(GET_MODULE(builder), target));
|
||||||
Assert(type_ref != nullptr);
|
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
|
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_type_t *base_type = nullptr;
|
||||||
SCC_HIR_BUILDER_BEGIN_BORROW(
|
SCC_HIR_BUILDER_BEGIN_BORROW(
|
||||||
builder, base_type,
|
builder, base_type,
|
||||||
scc_hir_module_get_type(GET_MODULE(builder),
|
scc_hir_module_get_type(GET_MODULE(builder), base_ref));
|
||||||
type_ref->data.pointer.base));
|
Assert(base_type != nullptr);
|
||||||
if (base_type->tag == SCC_HIR_TYPE_ARRAY) {
|
scc_hir_type_tag_t base_tag = base_type->tag;
|
||||||
scc_hir_type_t type = (scc_hir_type_t){
|
|
||||||
.tag = SCC_HIR_TYPE_PTR,
|
if (base_tag == SCC_HIR_TYPE_ARRAY) {
|
||||||
.data.pointer.base = base_type->data.array.base,
|
// 数组 GEP:返回指向元素类型的指针
|
||||||
};
|
scc_hir_type_ref_t elem_ref = base_type->data.array.base;
|
||||||
SCC_HIR_BUILDER_END_BORROW(builder); // base_type
|
SCC_HIR_BUILDER_END_BORROW(builder);
|
||||||
get_ptr_node.type = scc_hir_builder_type(builder, &type);
|
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 {
|
} 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 {
|
} 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 =
|
scc_hir_value_ref_t value_ref =
|
||||||
|
|||||||
@@ -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,
|
static void dump_type_linear_with_visited(scc_hir_dump_t *ctx,
|
||||||
scc_hir_type_ref_t type_ref,
|
scc_hir_type_ref_t type_ref,
|
||||||
scc_hashtable_t *visited) {
|
scc_hashtable_t *visited,
|
||||||
|
cbool extened) {
|
||||||
if (!ctx || !type_ref) {
|
if (!ctx || !type_ref) {
|
||||||
LOG_ERROR("invalid parameter");
|
LOG_ERROR("invalid parameter");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 检查循环
|
// 检查循环
|
||||||
if (scc_hashtable_get(visited, (void *)(usize)type_ref)) {
|
if (scc_hashtable_get(visited, (void *)(usize)type_ref)) {
|
||||||
scc_tree_dump_append(ctx->dump_ctx, " <recursive>");
|
extened = false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
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);
|
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
|
||||||
if (!type) {
|
if (!type) {
|
||||||
@@ -117,12 +116,14 @@ static void dump_type_linear_with_visited(scc_hir_dump_t *ctx,
|
|||||||
break;
|
break;
|
||||||
case SCC_HIR_TYPE_ARRAY:
|
case SCC_HIR_TYPE_ARRAY:
|
||||||
scc_tree_dump_append(ctx->dump_ctx, "[");
|
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);
|
scc_tree_dump_append_fmt(ctx->dump_ctx, ", %zu]", type->data.array.len);
|
||||||
break;
|
break;
|
||||||
case SCC_HIR_TYPE_PTR:
|
case SCC_HIR_TYPE_PTR:
|
||||||
scc_tree_dump_append(ctx->dump_ctx, "*");
|
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;
|
break;
|
||||||
case SCC_HIR_TYPE_FUNC:
|
case SCC_HIR_TYPE_FUNC:
|
||||||
scc_tree_dump_append(ctx->dump_ctx, "(");
|
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)
|
if (i > 0)
|
||||||
scc_tree_dump_append(ctx->dump_ctx, ", ");
|
scc_tree_dump_append(ctx->dump_ctx, ", ");
|
||||||
dump_type_linear_with_visited(
|
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) {
|
if (type->data.function.ret_type) {
|
||||||
scc_tree_dump_append(ctx->dump_ctx, ") -> ");
|
scc_tree_dump_append(ctx->dump_ctx, ") -> ");
|
||||||
dump_type_linear_with_visited(ctx, type->data.function.ret_type,
|
dump_type_linear_with_visited(ctx, type->data.function.ret_type,
|
||||||
visited);
|
visited, extened);
|
||||||
} else {
|
} else {
|
||||||
scc_tree_dump_append(ctx->dump_ctx, ")");
|
scc_tree_dump_append(ctx->dump_ctx, ")");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCC_HIR_TYPE_STRUCT:
|
case SCC_HIR_TYPE_STRUCT:
|
||||||
case SCC_HIR_TYPE_UNION:
|
case SCC_HIR_TYPE_UNION:
|
||||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "%s {",
|
scc_hashtable_set(visited, (void *)(usize)type_ref, (void *)1);
|
||||||
type->tag == SCC_HIR_TYPE_STRUCT ? "struct"
|
const char *tag_name =
|
||||||
: "union");
|
type->tag == SCC_HIR_TYPE_STRUCT ? "struct" : "union";
|
||||||
for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) {
|
if (type->name) {
|
||||||
dump_type_linear_with_visited(
|
scc_tree_dump_append_fmt(ctx->dump_ctx, "%s %s {", tag_name,
|
||||||
ctx, scc_vec_at(type->data.aggregate.fields, i), visited);
|
type->name);
|
||||||
scc_tree_dump_append(ctx->dump_ctx, ";");
|
} 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, "}");
|
scc_tree_dump_append(ctx->dump_ctx, "}");
|
||||||
break;
|
break;
|
||||||
@@ -162,9 +177,29 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
|
|||||||
scc_hir_type_ref_t type_ref) {
|
scc_hir_type_ref_t type_ref) {
|
||||||
scc_hashtable_t visited;
|
scc_hashtable_t visited;
|
||||||
scc_hashtable_usize_init(&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);
|
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,
|
static void format_ref_or_value(scc_hir_dump_t *ctx,
|
||||||
scc_hir_value_ref_t value_ref) {
|
scc_hir_value_ref_t value_ref) {
|
||||||
@@ -249,12 +284,18 @@ void scc_hir_dump_value_linear(scc_hir_dump_t *ctx,
|
|||||||
// 值已经在 format 中输出,这里不需要再做
|
// 值已经在 format 中输出,这里不需要再做
|
||||||
break;
|
break;
|
||||||
case SCC_HIR_VALUE_TAG_AGGREGATE:
|
case SCC_HIR_VALUE_TAG_AGGREGATE:
|
||||||
// 聚合类型:递归输出每个元素(每个占一行)
|
scc_tree_dump_append(ctx->dump_ctx, "{");
|
||||||
scc_vec_foreach(value->data.aggregate.fields, i) {
|
if (scc_vec_size(value->data.aggregate.fields) > 0) {
|
||||||
scc_hir_dump_value_linear(
|
scc_tree_dump_push(ctx->dump_ctx, true);
|
||||||
ctx, scc_vec_at(value->data.aggregate.fields, i));
|
scc_vec_foreach(value->data.aggregate.fields, i) {
|
||||||
scc_tree_dump_append(ctx->dump_ctx, "\n");
|
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;
|
return;
|
||||||
case SCC_HIR_VALUE_TAG_ALLOC:
|
case SCC_HIR_VALUE_TAG_ALLOC:
|
||||||
scc_tree_dump_append(ctx->dump_ctx, "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);
|
value->data.arg_ref.idx);
|
||||||
break;
|
break;
|
||||||
case SCC_HIR_VALUE_TAG_GLOBAL_ALLOC:
|
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_begin_line(ctx->dump_ctx);
|
||||||
|
scc_tree_dump_append(ctx->dump_ctx, " ");
|
||||||
if (value->data.global_alloc.value) {
|
if (value->data.global_alloc.value) {
|
||||||
scc_hir_dump_value_linear(ctx, value->data.global_alloc.value);
|
scc_hir_dump_value_linear(ctx, value->data.global_alloc.value);
|
||||||
} else {
|
} 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) {
|
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++) {
|
for (usize i = 0; i < scc_vec_size(ctx->cprog->global_vals); i++) {
|
||||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||||
scc_hir_dump_value_linear(ctx, scc_vec_at(ctx->cprog->global_vals, i));
|
scc_hir_dump_value_linear(ctx, scc_vec_at(ctx->cprog->global_vals, i));
|
||||||
|
|||||||
@@ -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);
|
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 fa_bits = scc_hir_type_align(mod, fr, abi);
|
||||||
int fs_bits = scc_hir_type_size(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)
|
if (fa2_bits > max_align_bits)
|
||||||
max_align_bits = fa2_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);
|
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 fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||||
int fa_bits = scc_hir_type_align(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 = SCC_ALIGN_UP(offset_bits, fa2_bits);
|
||||||
offset_bits += fs_bits;
|
offset_bits += fs_bits;
|
||||||
if (fa2_bits > max_align_bits)
|
if (fa2_bits > max_align_bits)
|
||||||
max_align_bits = fa2_bits;
|
max_align_bits = fa2_bits;
|
||||||
}
|
}
|
||||||
return SCC_ALIGN_UP(offset_bits,
|
return SCC_ALIGN_UP(
|
||||||
scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8);
|
offset_bits,
|
||||||
|
scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
case SCC_HIR_TYPE_UNION: {
|
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)
|
if (fa_bits > max_align_bits)
|
||||||
max_align_bits = fa_bits;
|
max_align_bits = fa_bits;
|
||||||
}
|
}
|
||||||
return SCC_ALIGN_UP(max_size_bits,
|
return SCC_ALIGN_UP(
|
||||||
scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8);
|
max_size_bits,
|
||||||
|
scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
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 scc_hir_field_offset(scc_hir_module_t *mod, scc_hir_type_ref_t ref,
|
||||||
int field_idx, const scc_type_abi_t *abi) {
|
int field_idx, const scc_type_abi_t *abi) {
|
||||||
scc_hir_type_t *type = scc_hir_module_get_type(mod, ref);
|
scc_hir_type_t *type = scc_hir_module_get_type(mod, ref);
|
||||||
if (!type || (type->tag != SCC_HIR_TYPE_STRUCT &&
|
if (!type ||
|
||||||
type->tag != SCC_HIR_TYPE_UNION))
|
(type->tag != SCC_HIR_TYPE_STRUCT && type->tag != SCC_HIR_TYPE_UNION))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (type->tag == SCC_HIR_TYPE_UNION)
|
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;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
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 fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||||
int fa_bits = scc_hir_type_align(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 = SCC_ALIGN_UP(offset_bits, fa2_bits);
|
||||||
if (i == field_idx)
|
if (i == field_idx)
|
||||||
return offset_bits;
|
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,
|
scc_hir_aggregate_layout(scc_hir_module_t *mod, scc_hir_type_ref_t ref,
|
||||||
const scc_type_abi_t *abi) {
|
const scc_type_abi_t *abi) {
|
||||||
scc_hir_type_t *type = scc_hir_module_get_type(mod, ref);
|
scc_hir_type_t *type = scc_hir_module_get_type(mod, ref);
|
||||||
if (!type || (type->tag != SCC_HIR_TYPE_STRUCT &&
|
if (!type ||
|
||||||
type->tag != SCC_HIR_TYPE_UNION))
|
(type->tag != SCC_HIR_TYPE_STRUCT && type->tag != SCC_HIR_TYPE_UNION))
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
int fc = (int)scc_vec_size(type->data.aggregate.fields);
|
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);
|
scc_vec_at(type->data.aggregate.fields, (usize)i);
|
||||||
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
int fs_bits = scc_hir_type_size(mod, fr, abi);
|
||||||
int fa_bits = scc_hir_type_align(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 = SCC_ALIGN_UP(offset_bits, fa2_bits);
|
||||||
|
|
||||||
al->fields[i].offset = offset_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;
|
max_align_bits = fa2_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
al->size = SCC_ALIGN_UP(offset_bits,
|
al->size = SCC_ALIGN_UP(
|
||||||
scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8);
|
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;
|
al->align = scc_type_abi_get_aggregate_align(abi, max_align_bits / 8) * 8;
|
||||||
return al;
|
return al;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,8 +46,16 @@ void scc_hir_module_drop(scc_hir_module_t *ctx) {
|
|||||||
|
|
||||||
for (usize i = 1; i < ctx->types.size; i++) {
|
for (usize i = 1; i < ctx->types.size; i++) {
|
||||||
scc_hir_type_t *type = &ctx->types.data[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);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *lir_module,
|
|||||||
* @param mod 模块
|
* @param mod 模块
|
||||||
* @param name 符号名
|
* @param name 符号名
|
||||||
* @param kind 种类 (DATA 或 EXTERN)
|
* @param kind 种类 (DATA 或 EXTERN)
|
||||||
* @param init_data 初始化数据 (若为 DATA 定义;若为 NULL 则零初始化)
|
* @param init_data 初始化数据 (若为 DATA 定义;若为 nullptr 则零初始化)
|
||||||
* @param size 数据大小 (若为 EXTERN 可为 0)
|
* @param size 数据大小 (若为 EXTERN 可为 0)
|
||||||
* @param align 对齐要求
|
* @param align 对齐要求
|
||||||
* @param attr 属性
|
* @param attr 属性
|
||||||
|
|||||||
@@ -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,
|
static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
||||||
scc_hir_value_ref_t value_ref);
|
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_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) {
|
switch (type->tag) {
|
||||||
case SCC_HIR_TYPE_i8:
|
case SCC_HIR_TYPE_i8:
|
||||||
*out_size = SCC_LIR_SIZE_8;
|
*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_size = 0;
|
||||||
*out_ext = SCC_LIR_EXT_NONE;
|
*out_ext = SCC_LIR_EXT_NONE;
|
||||||
break;
|
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:
|
default:
|
||||||
Panic("unsupported IR type in lowering at %d", type->tag);
|
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))
|
if (scc_hashtable_get(&ctx->value_to_vreg, (void *)(uintptr_t)value_ref))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
scc_hir_type_t *ty = scc_hir_module_get_type(ctx->hir_module, value->type);
|
|
||||||
u8 size_bits = 0;
|
u8 size_bits = 0;
|
||||||
scc_lir_ext_t ext = SCC_LIR_EXT_NONE;
|
scc_lir_ext_t ext = SCC_LIR_EXT_NONE;
|
||||||
if (ty != nullptr) {
|
ir_type_to_lir_size_ext(ctx->hir_module, value->type, &size_bits, &ext);
|
||||||
ir_type_to_lir_size_ext(ty, &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);
|
bool is_float = (ext == SCC_LIR_EXT_FLOAT);
|
||||||
|
|
||||||
int dst_vreg = get_vreg_for_value(ctx, value_ref);
|
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 宽度而非源值类型 */
|
/* 修复: 使用目标指针的元素类型确定 store 宽度而非源值类型 */
|
||||||
scc_hir_type_t *ptr_type = scc_hir_module_get_type_by_value(
|
scc_hir_type_t *ptr_type = scc_hir_module_get_type_by_value(
|
||||||
ctx->hir_module, value->data.store.target);
|
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) {
|
if (ptr_type && ptr_type->tag == SCC_HIR_TYPE_PTR) {
|
||||||
scc_hir_type_t *elem_type = scc_hir_module_get_type(
|
store_type = ptr_type->data.pointer.base;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
ir_type_to_lir_size_ext(ctx->hir_module, store_type, &size_bits, &ext);
|
||||||
scc_lir_instr_t instr = {.op = SCC_LIR_STORE,
|
scc_lir_instr_t instr = {.op = SCC_LIR_STORE,
|
||||||
.ext = ext,
|
.ext = ext,
|
||||||
.size_bits = size_bits,
|
.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);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
} break;
|
} break;
|
||||||
case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: {
|
case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: {
|
||||||
// 1. 获取基址和索引的 LIR 操作数
|
|
||||||
scc_lir_val_t base =
|
scc_lir_val_t base =
|
||||||
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.src_addr);
|
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.src_addr);
|
||||||
scc_lir_val_t index =
|
scc_lir_val_t index =
|
||||||
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.index);
|
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.index);
|
||||||
|
|
||||||
// 2. 获取元素类型和大小
|
// 获取 src_addr 的原始指针类型,判断是否为结构体字段访问
|
||||||
scc_hir_type_t *ptr_type =
|
scc_hir_type_t *src_type = scc_hir_module_get_type_by_value(
|
||||||
scc_hir_module_get_type(ctx->hir_module, value->type);
|
ctx->hir_module, value->data.get_elem_ptr.src_addr);
|
||||||
scc_hir_type_ref_t pointee = SCC_CFG_ID_nullptr;
|
int scale = 0, offset = 0;
|
||||||
if (ptr_type->tag == SCC_HIR_TYPE_PTR) {
|
|
||||||
pointee = ptr_type->data.pointer.base;
|
if (src_type && src_type->tag == SCC_HIR_TYPE_PTR) {
|
||||||
} else if (ptr_type->tag == SCC_HIR_TYPE_ARRAY) {
|
scc_hir_type_ref_t pointee_ref = src_type->data.pointer.base;
|
||||||
// 数组名退化为指针,元素类型为数组的元素类型
|
scc_hir_type_t *pointee =
|
||||||
pointee = ptr_type->data.array.base;
|
scc_hir_module_get_type(ctx->hir_module, pointee_ref);
|
||||||
} else {
|
if (pointee && (pointee->tag == SCC_HIR_TYPE_STRUCT ||
|
||||||
Panic("GET_ELEM_PTR on non-pointer/array type");
|
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);
|
int dst_vreg = get_vreg_for_value(ctx, value_ref);
|
||||||
scc_lir_instr_t instr = {
|
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),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.arg0 = base,
|
.arg0 = base,
|
||||||
.arg1 = index,
|
.arg1 = index,
|
||||||
// FIXME
|
.metadata.addr.scale = scale,
|
||||||
.metadata.addr.scale = elem_size_bits / 8,
|
.metadata.addr.offset = offset,
|
||||||
.metadata.addr.offset = 0,
|
|
||||||
};
|
};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
} break;
|
} 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: {
|
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;
|
u8 size = 0;
|
||||||
scc_lir_ext_t ext = SCC_LIR_EXT_NONE;
|
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);
|
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_val_t ap = ir_value_to_lir_operand(ctx, b->func.va_arg.ap);
|
||||||
scc_lir_instr_t instr = {
|
scc_lir_instr_t instr = {
|
||||||
@@ -598,6 +627,13 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
} break;
|
} break;
|
||||||
case SCC_HIR_VALUE_TAG_FUNC_ARG_REF:
|
case SCC_HIR_VALUE_TAG_FUNC_ARG_REF:
|
||||||
case SCC_HIR_VALUE_TAG_BLOCK_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;
|
break;
|
||||||
default:
|
default:
|
||||||
Panic("unsupported opcode %d", value->tag);
|
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);
|
&cprog->module, galloc->data.global_alloc.value);
|
||||||
scc_lir_symbol_id_t id = SCC_CFG_ID_nullptr;
|
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);
|
Assert(size > 0);
|
||||||
if (val == nullptr) {
|
if (val == nullptr) {
|
||||||
// TODO char == 8 bit
|
// TODO char == 8 bit
|
||||||
|
|||||||
@@ -266,58 +266,60 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
|
|||||||
i64 offset) {
|
i64 offset) {
|
||||||
usize size_bits = dst.size_bits;
|
usize size_bits = dst.size_bits;
|
||||||
Assert(size_bits == 64);
|
Assert(size_bits == 64);
|
||||||
// 前置断言:dst 必须是寄存器
|
|
||||||
Assert(dst.kind == SCC_X86_OPR_REG);
|
Assert(dst.kind == SCC_X86_OPR_REG);
|
||||||
// scale 必须是 1,2,4,8 之一
|
|
||||||
Assert(scale == 1 || scale == 2 || scale == 4 || scale == 8);
|
|
||||||
|
|
||||||
// ---- 处理 base ----
|
// ---- 处理 base ----
|
||||||
scc_x86_operand_value_t base_reg = base;
|
scc_x86_operand_value_t base_reg = base;
|
||||||
switch (base.kind) {
|
switch (base.kind) {
|
||||||
case SCC_X86_OPR_REG: {
|
case SCC_X86_OPR_REG:
|
||||||
base_reg = base;
|
break;
|
||||||
} break;
|
case SCC_X86_OPR_RELOC:
|
||||||
case SCC_X86_OPR_RELOC: {
|
|
||||||
Assert(base.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL);
|
Assert(base.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL);
|
||||||
base_reg = new_vreg_temp(isel, 64);
|
base_reg = new_vreg_temp(isel, 64);
|
||||||
scc_x86_emit_move(isel, base_reg, base);
|
scc_x86_emit_move(isel, base_reg, base);
|
||||||
} break;
|
break;
|
||||||
case SCC_X86_OPR_MEM: {
|
case SCC_X86_OPR_MEM:
|
||||||
base_reg = new_vreg_temp(isel, 64);
|
base_reg = new_vreg_temp(isel, 64);
|
||||||
scc_x86_emit_move(isel, base_reg, base);
|
scc_x86_emit_move(isel, base_reg, base);
|
||||||
} break;
|
break;
|
||||||
default: {
|
default:
|
||||||
Panic("Unsupported base kind %d in load_addr", base.kind);
|
Panic("Unsupported base kind %d in load_addr", base.kind);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
scc_x86_operand_value_t index_reg = index;
|
// ---- 处理 index 和 scale ----
|
||||||
switch (index.kind) {
|
// scale=0 表示 struct/union 字段 GEP:字段索引已被折叠进 offset,
|
||||||
case SCC_X86_OPR_REG: {
|
// x86-64 SIB 不支持 scale=0,所以跳 index register,直接用 base+disp
|
||||||
index_reg = index;
|
scc_x86_reg_t index_reg = SCC_X86_REG_INVALID;
|
||||||
} break;
|
int sib_scale = 1;
|
||||||
case SCC_X86_OPR_RELOC: {
|
if (scale != 0) {
|
||||||
Assert(index.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL);
|
Assert(scale == 1 || scale == 2 || scale == 4 || scale == 8);
|
||||||
index_reg = new_vreg_temp(isel, 64);
|
sib_scale = scale;
|
||||||
scc_x86_emit_move(isel, index_reg, index);
|
switch (index.kind) {
|
||||||
} break;
|
case SCC_X86_OPR_REG:
|
||||||
case SCC_X86_OPR_MEM: {
|
index_reg = index.reg;
|
||||||
index_reg = new_vreg_temp(isel, 64);
|
break;
|
||||||
scc_x86_emit_move(isel, index_reg, index);
|
case SCC_X86_OPR_RELOC:
|
||||||
} break;
|
Assert(index.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL);
|
||||||
case SCC_X86_OPR_IMM: {
|
index_reg = new_vreg_temp(isel, 64).reg;
|
||||||
index_reg = new_vreg_temp(isel, index.size_bits);
|
scc_x86_emit_move(isel, scc_x86_op_preg(index_reg, 64), index);
|
||||||
scc_x86_emit_move(isel, index_reg, index);
|
break;
|
||||||
} break;
|
case SCC_X86_OPR_MEM:
|
||||||
default: {
|
index_reg = new_vreg_temp(isel, 64).reg;
|
||||||
Panic("Unsupported index kind %d in load_addr", base.kind);
|
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_operand_value_t mem_op =
|
||||||
scc_x86_op_mem((scc_x86_mem_t){.base = base_reg.reg,
|
scc_x86_op_mem((scc_x86_mem_t){.base = base_reg.reg,
|
||||||
.index = index_reg.reg,
|
.index = index_reg,
|
||||||
.scale = scale,
|
.scale = sib_scale,
|
||||||
.disp.displacement = offset,
|
.disp.displacement = offset,
|
||||||
.disp.displacement_bits = 8},
|
.disp.displacement_bits = 8},
|
||||||
size_bits);
|
size_bits);
|
||||||
|
|||||||
@@ -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]);
|
scc_vec_push(*sect_data, meta->data.init_data[i]);
|
||||||
}
|
}
|
||||||
// struct {
|
// struct {
|
||||||
// u8 *init_data; // 初始化数据(若为 NULL 则零初始化)
|
// u8 *init_data; // 初始化数据(若为 nullptr 则零初始化)
|
||||||
// usize size; // 数据大小(字节)
|
// usize size; // 数据大小(字节)
|
||||||
// int align; // 对齐要求
|
// int align; // 对齐要求
|
||||||
// } data;
|
// } data;
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ static inline cbool scc_lexer_peek_non_blank(scc_lexer_tok_ring_t *stream,
|
|||||||
scc_ring_peek(*stream, *out, ok);
|
scc_ring_peek(*stream, *out, ok);
|
||||||
if (!ok || out->type != SCC_TOK_BLANK)
|
if (!ok || out->type != SCC_TOK_BLANK)
|
||||||
break;
|
break;
|
||||||
scc_ring_next_consume(*stream, *out, ok);
|
scc_ring_next(*stream, *out, ok);
|
||||||
scc_lexer_tok_drop(out);
|
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
||||||
if (!operand) {
|
if (!operand) {
|
||||||
// FIXME postfix-expression
|
// 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
|
// FIXME pos
|
||||||
scc_ast_expr_lvalue_init(expr, type, type->base.loc);
|
scc_ast_expr_lvalue_init(expr, type, type->base.loc);
|
||||||
operand = scc_parse_initializer(parser, expr);
|
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)
|
case SCC_TOK_L_PAREN: // left(args)
|
||||||
{
|
{
|
||||||
if (!scc_parser_next_consume(parser, nullptr))
|
if (!scc_parser_next_consume(parser, nullptr))
|
||||||
return left;
|
goto done;
|
||||||
pos = left->base.loc;
|
pos = left->base.loc;
|
||||||
scc_ast_expr_vec_t args;
|
scc_ast_expr_vec_t args;
|
||||||
scc_vec_init(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: {
|
case SCC_TOK_DEREF: {
|
||||||
scc_lexer_tok_t op_tok;
|
scc_lexer_tok_t op_tok;
|
||||||
if (!scc_parser_next_consume(parser, &op_tok))
|
if (!scc_parser_next_consume(parser, &op_tok))
|
||||||
return left;
|
goto done;
|
||||||
scc_lexer_tok_t ident_tok;
|
scc_lexer_tok_t ident_tok;
|
||||||
if (!scc_parser_next_consume(parser, &ident_tok) ||
|
if (!scc_parser_next_consume(parser, &ident_tok) ||
|
||||||
ident_tok.type != SCC_TOK_IDENT) {
|
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);
|
parser_sync(parser);
|
||||||
return nullptr;
|
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);
|
scc_ast_expr_t *member = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(member != nullptr);
|
Assert(member != nullptr);
|
||||||
if (op_tok.type == SCC_TOK_DOT) {
|
if (op_tok.type == SCC_TOK_DOT) {
|
||||||
scc_ast_expr_member_init(member, left, name, ident_tok.loc);
|
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);
|
scc_ast_expr_ptr_member_init(member, left, name, ident_tok.loc);
|
||||||
|
} else {
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_lexer_tok_drop(&op_tok);
|
scc_lexer_tok_drop(&op_tok);
|
||||||
left = member;
|
left = member;
|
||||||
|
scc_parse_expr_sema(parser, member);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_ADD_ADD: // left++
|
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;
|
scc_lexer_tok_t op_tok;
|
||||||
if (!scc_parser_next_consume(parser, &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_op_t op = map_token_to_unary_op(op_tok.type, false);
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
@@ -762,6 +767,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
|
scc_parse_expr_sema(parser, left);
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,8 +793,11 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_identifier_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)),
|
scc_ast_expr_identifier_init(
|
||||||
tok.loc);
|
expr,
|
||||||
|
scc_ast_module_intern(parser->ast_module,
|
||||||
|
scc_str_as_cstr(&tok.lexeme)),
|
||||||
|
tok.loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_INT_LITERAL: {
|
case SCC_TOK_INT_LITERAL: {
|
||||||
@@ -796,8 +805,11 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_literal_int_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), false,
|
scc_ast_expr_literal_int_init(
|
||||||
tok.loc);
|
expr,
|
||||||
|
scc_ast_module_intern(parser->ast_module,
|
||||||
|
scc_str_as_cstr(&tok.lexeme)),
|
||||||
|
false, tok.loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_FLOAT_LITERAL: {
|
case SCC_TOK_FLOAT_LITERAL: {
|
||||||
@@ -805,8 +817,11 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_literal_float_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)),
|
scc_ast_expr_literal_float_init(
|
||||||
false, tok.loc);
|
expr,
|
||||||
|
scc_ast_module_intern(parser->ast_module,
|
||||||
|
scc_str_as_cstr(&tok.lexeme)),
|
||||||
|
false, tok.loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_CHAR_LITERAL: {
|
case SCC_TOK_CHAR_LITERAL: {
|
||||||
@@ -814,8 +829,11 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_literal_char_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)),
|
scc_ast_expr_literal_char_init(
|
||||||
false, tok.loc);
|
expr,
|
||||||
|
scc_ast_module_intern(parser->ast_module,
|
||||||
|
scc_str_as_cstr(&tok.lexeme)),
|
||||||
|
false, tok.loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_STRING_LITERAL: {
|
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);
|
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);
|
scc_str_drop(&string);
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
// FIXME loc
|
// FIXME loc
|
||||||
scc_ast_expr_literal_string_init(expr, pooled_str, false,
|
scc_ast_expr_literal_string_init(expr, pooled_str, false, tok.loc);
|
||||||
tok.loc);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_L_PAREN:
|
case SCC_TOK_L_PAREN:
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ static void symtab_add_symbol(scc_sema_symtab_t *sema_symtab,
|
|||||||
if (scc_str_is_empty(&name)) {
|
if (scc_str_is_empty(&name)) {
|
||||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, ast_node_ref);
|
scc_sema_symtab_add_symbol(sema_symtab, decl->name, ast_node_ref);
|
||||||
} else {
|
} else {
|
||||||
const char *pooled = scc_strpool_intern(&sema_symtab->name_pool,
|
const char *pooled =
|
||||||
scc_str_as_cstr(&name));
|
scc_strpool_intern(&sema_symtab->name_pool, scc_str_as_cstr(&name));
|
||||||
scc_sema_symtab_add_symbol(sema_symtab, pooled, ast_node_ref);
|
scc_sema_symtab_add_symbol(sema_symtab, pooled, ast_node_ref);
|
||||||
scc_str_drop(&name);
|
scc_str_drop(&name);
|
||||||
}
|
}
|
||||||
@@ -58,6 +58,100 @@ static void type_callback(scc_sema_ctx_t *sema_ctx,
|
|||||||
return;
|
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,
|
static void expr_callback(scc_sema_ctx_t *sema_ctx,
|
||||||
scc_ast_node_kind_t node_type, void *node) {
|
scc_ast_node_kind_t node_type, void *node) {
|
||||||
scc_sema_symtab_t *sema_symtab = sema_ctx->context;
|
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);
|
scc_ast_expr_t *expr = SCC_AST_CAST_TO(scc_ast_expr_t, node);
|
||||||
if (node_type == SCC_AST_EXPR_IDENTIFIER) {
|
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);
|
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",
|
SCC_ERROR(expr->base.loc, "sema error: Identifier '%s' not found",
|
||||||
expr->identifier.name);
|
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,
|
SCC_ERROR(expr->base.loc,
|
||||||
"sema error: Identifier '%s' is not a variable",
|
"sema error: Identifier '%s' is not a variable",
|
||||||
expr->identifier.name);
|
expr->identifier.name);
|
||||||
} else {
|
} 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;
|
return;
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
scc_ring_reset(*input);
|
||||||
|
|
||||||
scc_lexer_tok_vec_t output_vec;
|
scc_lexer_tok_vec_t output_vec;
|
||||||
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false,
|
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ typedef struct scc_type_abi scc_type_abi_t;
|
|||||||
struct scc_type_abi {
|
struct scc_type_abi {
|
||||||
int ptr_size;
|
int ptr_size;
|
||||||
int ptr_align;
|
int ptr_align;
|
||||||
int endian; // 0 = little, 1 = big
|
int endian; // 0 = little, 1 = big
|
||||||
|
|
||||||
// C 类型大小 (AST → HIR 时需要)
|
// C 类型大小 (AST → HIR 时需要)
|
||||||
int char_size;
|
int char_size;
|
||||||
@@ -22,30 +22,30 @@ struct scc_type_abi {
|
|||||||
int long_double_size;
|
int long_double_size;
|
||||||
int va_list_size;
|
int va_list_size;
|
||||||
|
|
||||||
// byte_size → 对齐。NULL = 自然对齐 (return byte_size)
|
// byte_size → 对齐。nullptr = 自然对齐 (return byte_size)
|
||||||
int (*type_align)(int byte_size);
|
int (*type_align)(int byte_size);
|
||||||
|
|
||||||
// 字段对齐覆盖。NULL = 用 type_align 的值
|
// 字段对齐覆盖。nullptr = 用 type_align 的值
|
||||||
int (*field_align)(int field_size, int natural_align);
|
int (*field_align)(int field_size, int natural_align);
|
||||||
|
|
||||||
// 聚合体总对齐。NULL = max 字段 align
|
// 聚合体总对齐。nullptr = max 字段 align
|
||||||
int (*aggregate_align)(int max_field_align);
|
int (*aggregate_align)(int max_field_align);
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int scc_type_abi_get_type_align(const scc_type_abi_t *abi,
|
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;
|
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,
|
static inline int scc_type_abi_get_field_align(const scc_type_abi_t *abi,
|
||||||
int field_size,
|
int field_size,
|
||||||
int natural_align) {
|
int natural_align) {
|
||||||
return abi->field_align ? abi->field_align(field_size, natural_align)
|
return abi->field_align ? abi->field_align(field_size, natural_align)
|
||||||
: natural_align;
|
: natural_align;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int scc_type_abi_get_aggregate_align(const scc_type_abi_t *abi,
|
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)
|
return abi->aggregate_align ? abi->aggregate_align(max_field_align)
|
||||||
: max_field_align;
|
: max_field_align;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,16 +12,17 @@ static const scc_type_abi_t SCC_TYPE_ABI_SYSTEMV_X64 = {
|
|||||||
.char_size = 1,
|
.char_size = 1,
|
||||||
.short_size = 2,
|
.short_size = 2,
|
||||||
.int_size = 4,
|
.int_size = 4,
|
||||||
.long_size = 8, // SysV: long = 8 bytes
|
.long_size = 8, // SysV: long = 8 bytes
|
||||||
.long_long_size = 8,
|
.long_long_size = 8,
|
||||||
.float_size = 4,
|
.float_size = 4,
|
||||||
.double_size = 8,
|
.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,
|
.va_list_size = 8,
|
||||||
|
|
||||||
.type_align = NULL,
|
.type_align = nullptr,
|
||||||
.field_align = NULL,
|
.field_align = nullptr,
|
||||||
.aggregate_align = NULL,
|
.aggregate_align = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __SCC_TYPE_ABI_SYSTEMV_X64_H__ */
|
#endif /* __SCC_TYPE_ABI_SYSTEMV_X64_H__ */
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ static const scc_type_abi_t SCC_TYPE_ABI_WIN_X64 = {
|
|||||||
.long_double_size = 8,
|
.long_double_size = 8,
|
||||||
.va_list_size = 4,
|
.va_list_size = 4,
|
||||||
|
|
||||||
.type_align = NULL,
|
.type_align = nullptr,
|
||||||
.field_align = scc_win64_field_align,
|
.field_align = scc_win64_field_align,
|
||||||
.aggregate_align = NULL,
|
.aggregate_align = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __SCC_TYPE_ABI_WIN_X64_H__ */
|
#endif /* __SCC_TYPE_ABI_WIN_X64_H__ */
|
||||||
|
|||||||
Reference in New Issue
Block a user