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:
zzy
2026-06-03 17:34:16 +08:00
parent be33eb3942
commit 0acea43e4e
17 changed files with 486 additions and 174 deletions

View File

@@ -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;

View File

@@ -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) {
// 结构体/联合体 GEPindex 是字段编号,返回指向字段类型的指针
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 =

View File

@@ -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, " <recursive>");
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));

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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 属性

View File

@@ -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) {
// 数组 GEPindex * 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

View File

@@ -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);