feat(ast): 重构AST节点类型定义并实现数组下标访问

- 将scc_ast_node_type_t重命名为scc_ast_node_kind_t以提高语义清晰度
- 为scc_ast_node结构体添加名称定义
- 更新所有相关头文件中的类型引用
- 实现数组下标表达式的IR转换逻辑
- 添加对sizeof和alignof表达式的基本支持

fix(ast2ir): 修复表达式求值和类型处理问题

- 修复数组类型退化为指针的逻辑
- 修复变量声明初始化值检查条件
- 添加结构体和枚举类型的IR生成支持
- 移除未使用的代码段

refactor(ir): 完善IR上下文错误处理

- 为未处理的类型标签添加恐慌处理
- 修复联合类型的哈希计算

chore(build): 更新依赖项配置

- 修正lexer模块中的依赖项名称

style(parser): 清理解析器代码

- 移除未使用的类型哈希表
- 更新语义分析回调函数签名
- 添加属性语法的占位符实现
- 完善内存清理逻辑

test: 添加数组下标和枚举测试用例

- 新增15_array_subscript.c测试数组下标访问
- 新增16_enum.c测试枚举类型功能
- 更新期望结果配置文件
This commit is contained in:
zzy
2026-04-09 11:18:32 +08:00
parent d88475cc06
commit eeb4c4fc3c
22 changed files with 190 additions and 71 deletions

View File

@@ -79,10 +79,10 @@ typedef enum {
scc_ast_translation_unit_t_BEGIN,
SCC_AST_TRANSLATION_UNIT, // 翻译单元(根节点)
scc_ast_translation_unit_t_END,
} scc_ast_node_type_t;
} scc_ast_node_kind_t;
typedef struct {
scc_ast_node_type_t type;
typedef struct scc_ast_node {
scc_ast_node_kind_t type;
scc_pos_t loc;
} scc_ast_node_t;

View File

@@ -83,7 +83,7 @@ static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
}
static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl,
scc_ast_node_type_t type,
scc_ast_node_kind_t type,
const char *name,
scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
@@ -352,7 +352,7 @@ static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr,
}
static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr,
scc_ast_node_type_t type,
scc_ast_node_kind_t type,
scc_ast_expr_t *object,
const char *member,
scc_pos_t loc) {
@@ -441,7 +441,7 @@ static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr,
}
static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr,
scc_ast_node_type_t type,
scc_ast_node_kind_t type,
const char *value, cbool owned,
scc_pos_t loc) {
Assert(expr != nullptr && value != nullptr);
@@ -550,7 +550,7 @@ static inline void scc_ast_type_function_init(scc_ast_type_t *type,
}
static inline void _scc_ast_type_record_init(scc_ast_type_t *type,
scc_ast_node_type_t type_kind,
scc_ast_node_kind_t type_kind,
const char *name,
scc_ast_decl_t *decl,
scc_pos_t loc) {

View File

@@ -68,7 +68,7 @@ static const char *node_type_names[] = {
[scc_ast_translation_unit_t_END] = "ERROR",
};
static const char *get_node_type_str(scc_ast_node_type_t type) {
static const char *get_node_type_str(scc_ast_node_kind_t type) {
return node_type_names[type];
}

View File

@@ -108,8 +108,8 @@ scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx,
scc_ast_expr_t *expr,
scc_ir_value_ref_t lhs,
scc_ir_value_ref_t rhs) {
scc_ir_bblock_ref_t start_block =
scc_ir_builder_current_bblock(&ctx->builder);
// scc_ir_bblock_ref_t start_block =
// scc_ir_builder_current_bblock(&ctx->builder);
scc_ir_bblock_ref_t right_block =
scc_ir_builder_bblock(&ctx->builder, "logic_right");
@@ -421,12 +421,39 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
scc_vec_free(args);
return node;
}
// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标
case SCC_AST_EXPR_ARRAY_SUBSCRIPT: {
// 1. 计算数组/指针基址(右值,得到地址)
scc_ir_value_ref_t base_ptr =
scc_ast2ir_expr(ctx, expr->subscript.array, true);
// 2. 计算下标值
scc_ir_value_ref_t index =
scc_ast2ir_expr(ctx, expr->subscript.index, false);
// 3. 生成 getptrGEP
scc_ir_value_ref_t elem_ptr =
scc_ir_builder_get_ptr(&ctx->builder, base_ptr, index);
// 4. 根据左值/右值返回
if (is_lvalue) {
return elem_ptr; // 作为左值:返回地址
} else {
return scc_ir_builder_load(&ctx->builder,
elem_ptr); // 作为右值:加载值
}
}
// SCC_AST_EXPR_MEMBER, // 成员访问 .
// SCC_AST_EXPR_PTR_MEMBER, // 指针成员访问 ->
// SCC_AST_EXPR_CAST, // 类型转换
// SCC_AST_EXPR_SIZE_OF, // sizeof
// SCC_AST_EXPR_ALIGN_OF, // _Alignof
case SCC_AST_EXPR_SIZE_OF: {
scc_ir_const_int_t val;
val.int64 = 1;
return scc_ir_builder_const_int(
&ctx->builder, scc_ir_builder_type_u64(&ctx->builder), val);
}
case SCC_AST_EXPR_ALIGN_OF: {
scc_ir_const_int_t val;
val.int64 = 1;
return scc_ir_builder_const_int(
&ctx->builder, scc_ir_builder_type_u64(&ctx->builder), val);
}
// SCC_AST_EXPR_COMPOUND, // 复合字面量
// SCC_AST_EXPR_LVALUE, // 右值
// SCC_AST_EXPR_BUILTIN,// 内置表达式 ... directive map to ir builtin
@@ -491,16 +518,19 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
// 右值:如果是数组类型,退化为指针(返回地址)
scc_ir_type_t *ir_type =
scc_ir_module_get_type_by_value(ctx->builder.ctx.module, in);
Assert(ir_type->tag == SCC_IR_TYPE_PTR);
scc_ir_type_t *target_type = scc_ir_module_get_type(
ctx->builder.ctx.module, ir_type->data.pointer.base);
if (target_type->tag == SCC_IR_TYPE_ARRAY) {
// 生成 getptr 获取数组首地址
return scc_ir_builder_get_ptr(&ctx->builder, in,
SCC_IR_REF_nullptr);
if (ir_type->tag == SCC_IR_TYPE_PTR) {
scc_ir_type_t *target_type = scc_ir_module_get_type(
ctx->builder.ctx.module, ir_type->data.pointer.base);
if (target_type->tag == SCC_IR_TYPE_ARRAY) {
// 生成 getptr 获取数组首地址
return scc_ir_builder_get_ptr(&ctx->builder, in,
SCC_IR_REF_nullptr);
} else {
// 标量类型:加载值
return scc_ir_builder_load(&ctx->builder, in);
}
} else {
// 标量类型:加载值
return scc_ir_builder_load(&ctx->builder, in);
return in;
}
}
}
@@ -719,7 +749,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
}
scc_ir_value_ref_t init_val_node =
scc_ast2ir_expr(ctx, decl->var.init, false);
Assert(init_val_node != nullptr);
Assert(init_val_node != SCC_IR_REF_nullptr);
// FIXME array auto calucate size
scc_ir_type_t *ir_type =
@@ -802,10 +832,29 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
break;
}
case SCC_AST_DECL_STRUCT:
break;
case SCC_AST_DECL_UNION:
scc_vec_foreach(decl->record.fields, i) {
scc_ast_decl_t *item = scc_vec_at(decl->record.fields, i);
scc_ast2ir_decl(ctx, item);
}
break;
case SCC_AST_DECL_ENUM:
scc_ir_const_int_t val;
val.int32 = 0;
scc_vec_foreach(decl->record.fields, i) {
scc_ast_decl_t *item = scc_vec_at(decl->record.fields, i);
Assert(item->base.type == SCC_AST_DECL_VAR);
if (item->var.init) {
Assert(item->var.init->base.type == SCC_AST_EXPR_INT_LITERAL);
parse_lexme2const_int(item->var.init->literal.lexme, &val);
}
scc_ir_value_ref_t item_val_ref = scc_ir_builder_const_int(
&ctx->builder, scc_ir_builder_type_i32(&ctx->builder), val);
scc_hashtable_set(&ctx->decl2ir_ref, item,
(void *)(usize)item_val_ref);
val.int32 += 1;
}
break;
case SCC_AST_DECL_TYPEDEF:
break;
default:

View File

@@ -54,14 +54,17 @@ static u32 hash_type(const void *_key) {
break;
case SCC_IR_TYPE_STRUCT:
case SCC_IR_TYPE_UNION:
return 0;
case SCC_IR_TYPE_VECTOR:
default:
UNREACHABLE();
Panic("Invalid type tag %d", key->tag);
return 0;
}
return hash;
}
static int cmp_type(const void *_key1, const void *_key2) {
const scc_ir_type_t *key1 = _key1, *key2 = _key2;
Assert(key1 != nullptr && key2 != nullptr);

View File

@@ -77,11 +77,10 @@ static void win64_finalize(scc_frame_alloc_ops_t *ops) {
current_offset -= (align - rem);
}
current_offset -= slot->size;
slot->offset = current_offset;
scc_hashtable_set(&self->offset_cache, (void *)(intptr_t)slot->slot_id,
(void *)(intptr_t)slot->offset);
current_offset -= slot->size;
}
int total_size = -current_offset + 32; // 加上影子空间

View File

@@ -294,38 +294,46 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
scc_ir_value_t *src_addr = scc_ir_module_get_value(
GET_MODULE(ctx), value->data.get_ptr.src_addr);
Assert(src_addr != nullptr);
if (value->data.get_ptr.index == 0) {
if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
// 全局变量RIP相对寻址
scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode,
SCC_AMD64_RAX, 0);
usize sym_idx =
sccf_builder_get_symbol_idx(ctx->builder, src_addr->name);
Assert(sym_idx != 0);
sccf_builder_add_reloc(
ctx->builder,
(sccf_reloc_t){
.reloc_type = SCCF_RELOC_TYPE_REL,
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
.addend = 4,
.sect_type = SCCF_SECT_CODE,
.sym_idx = sym_idx,
});
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
// 栈上变量:地址为 rbp - offset
scc_reg_loc_t src_loc;
parse_location(ctx, &src_loc, value->data.get_ptr.src_addr);
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
} else {
// 其他情况(如链式
// getptr源地址值已经存储在某个位置直接加载到 RAX
scc_reg_loc_t src_loc;
parse_location(ctx, &src_loc, value->data.get_ptr.src_addr);
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
}
if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
// 全局变量RIP相对寻址
scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode, SCC_AMD64_RAX,
0);
usize sym_idx =
sccf_builder_get_symbol_idx(ctx->builder, src_addr->name);
Assert(sym_idx != 0);
sccf_builder_add_reloc(
ctx->builder,
(sccf_reloc_t){
.reloc_type = SCCF_RELOC_TYPE_REL,
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
.addend = 4,
.sect_type = SCCF_SECT_CODE,
.sym_idx = sym_idx,
});
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
// 栈上变量:地址为 rbp - offset
scc_reg_loc_t src_loc;
parse_location(ctx, &src_loc, value->data.get_ptr.src_addr);
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
} else {
// 其他情况(如链式 getptr源地址值已经存储在某个位置直接加载到
// RAX
scc_reg_loc_t src_loc;
parse_location(ctx, &src_loc, value->data.get_ptr.src_addr);
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
// TODO
scc_ir_value_t *index = scc_ir_module_get_value(
GET_MODULE(ctx), value->data.get_ptr.index);
Assert(index != nullptr &&
index->tag == SCC_IR_VALUE_TAG_CONST_INT);
}
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
break;
}
case SCC_IR_VALUE_TAG_GET_ELEM_PTR: ///< 获取元素指针(used by array)

View File

@@ -9,7 +9,10 @@ void scc_ir2mcode_init(scc_ir2mcode_ctx_t *ctx, scc_ir_cprog_t *cprog,
sccf_builder_init(ctx->builder);
}
void scc_ir2mcode_drop(scc_ir2mcode_ctx_t *ctx) {}
void scc_ir2mcode_drop(scc_ir2mcode_ctx_t *ctx) {
// TODO drop all objs
scc_ir_cprog_drop(ctx->cprog);
}
void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx);

View File

@@ -4,5 +4,5 @@ version = "0.1.0"
dependencies = [
{ name = "scc_core", path = "../../runtime/scc_core" },
{ name = "lex_parser", path = "../sstream" },
{ name = "scc_sstream", path = "../sstream" },
]

View File

@@ -14,8 +14,6 @@ typedef struct scc_parser {
scc_lexer_tok_ring_t *ring;
usize checkpoint;
scc_hashtable_t type_ht;
scc_sema_callbacks_t sema_callbacks;
scc_ast_translation_unit_t *translation_unit;
int errcode;

View File

@@ -7,7 +7,7 @@
* @brief 语义分析回调函数类型
*/
typedef void (*scc_sema_callback_t)(void *context,
scc_ast_node_type_t node_type, void *node);
scc_ast_node_kind_t node_type, void *node);
typedef scc_ast_type_t *(*scc_sema_got_type_t)(void *context, const char *name);

View File

@@ -0,0 +1,32 @@
/*
ISO/IEC 9899:2024 (en) — N3220 working draft
(6.7.13.2) attribute-specifier-sequence:
attribute-specifier-sequence(opt) attribute-specifier
(6.7.13.2) attribute-specifier:
[ [ attribute-list ] ]
(6.7.13.2) attribute-list:
attribute(opt)
attribute-list , attribute(opt)
(6.7.13.2) attribute:
attribute-token attribute-argument-clause(opt)
(6.7.13.2) attribute-token:
standard-attribute
attribute-prefixed-token
(6.7.13.2) standard-attribute:
identifier
(6.7.13.2) attribute-prefixed-token:
attribute-prefix :: identifier
(6.7.13.2) attribute-prefix:
identifier
(6.7.13.2) attribute-argument-clause:
( balanced-token-sequence(opt) )
(6.7.13.2) balanced-token-sequence:
balanced-token
balanced-token-sequence balanced-token
(6.7.13.2) balanced-token:
( balanced-token-sequence(opt) )
[ balanced-token-sequence(opt) ]
{ balanced-token-sequence(opt) }
any token other than a parenthesis, a bracket, or a brace
*/

View File

@@ -537,7 +537,7 @@ static scc_ast_type_t *build_type_from_info(type_spec_info_t *info,
return type;
}
static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
scc_ast_node_type_t type_kind) {
scc_ast_node_kind_t type_kind) {
/*
(6.7.2.1)
struct-or-union-specifier:

View File

@@ -1,7 +1,7 @@
#include <parser_utils.h>
#include <scc_parser.h>
static void dummy_sema_callback(void *context, scc_ast_node_type_t node_type,
static void dummy_sema_callback(void *context, scc_ast_node_kind_t node_type,
void *node) {
(void)context;
(void)node_type;
@@ -49,6 +49,8 @@ void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring,
void scc_parser_drop(scc_parser_t *parser) {
// TODO: 释放 AST 内存
scc_ring_free(*parser->ring);
scc_sema_drop(&parser->sema_callbacks);
}
scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {

View File

@@ -2,7 +2,7 @@
#include <scc_sema.h>
#include <sema_symtab.h>
static void type_callback(void *context, scc_ast_node_type_t node_type,
static void type_callback(void *context, scc_ast_node_kind_t node_type,
void *node) {
scc_sema_symtab_t *sema_symtab = context;
(void)context;
@@ -11,7 +11,7 @@ static void type_callback(void *context, scc_ast_node_type_t node_type,
return;
}
static void expr_callback(void *context, scc_ast_node_type_t node_type,
static void expr_callback(void *context, scc_ast_node_kind_t node_type,
void *node) {
scc_sema_symtab_t *sema_symtab = context;
@@ -37,7 +37,7 @@ static void expr_callback(void *context, scc_ast_node_type_t node_type,
return;
}
static void stmt_callback(void *context, scc_ast_node_type_t node_type,
static void stmt_callback(void *context, scc_ast_node_kind_t node_type,
void *node) {
scc_sema_symtab_t *sema_symtab = context;
@@ -54,7 +54,7 @@ static void stmt_callback(void *context, scc_ast_node_type_t node_type,
return;
}
static void decl_callback(void *context, scc_ast_node_type_t node_type,
static void decl_callback(void *context, scc_ast_node_kind_t node_type,
void *node) {
scc_sema_symtab_t *sema_symtab = context;
@@ -196,4 +196,7 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
&builin_func->base);
}
void scc_sema_drop(scc_sema_callbacks_t *callbacks) {}
void scc_sema_drop(scc_sema_callbacks_t *callbacks) {
// FIXME drop obj
scc_sema_symtab_drop(callbacks->context);
}

View File

@@ -30,6 +30,7 @@ static int switch_file_stack(scc_pproc_t *pp, scc_str_t *fname, scc_pos_t *pos,
scc_str_append(&fpath, fname);
ret = scc_fexists(scc_str_as_cstr(&fpath));
if (ret == true) {
SCC_DEBUG(*pos, "include file '%s' found", scc_str_as_cstr(&fpath));
goto FOPEN;
}
}

View File

@@ -11,6 +11,9 @@ typedef struct scc_pos {
usize offset;
} scc_pos_t;
#define scc_pos_pnt_fmt "%s:%zu:%zu"
#define scc_pos_pnt_val(val) (val).name, (val).line, (val).col
static inline scc_pos_t scc_pos_create() { return (scc_pos_t){0, 1, 1, 0}; }
static inline void scc_pos_next(scc_pos_t *pos) {

View File

@@ -9,9 +9,8 @@ extern logger_t __scc_usr_log;
#define SCC_POS_LOG(level, pos, fmt, ...) \
do { \
char _full_msg[LOGGER_MAX_BUF_SIZE]; \
int _n = \
scc_snprintf(_full_msg, sizeof(_full_msg), \
"%s:%zu:%zu: ", (pos).name, (pos).line, (pos).col); \
int _n = scc_snprintf(_full_msg, sizeof(_full_msg), \
scc_pos_pnt_fmt ": ", scc_pos_pnt_val(pos)); \
scc_snprintf(_full_msg + _n, sizeof(_full_msg) - _n, fmt, \
##__VA_ARGS__); \
__scc_usr_log.handler(&__scc_usr_log, level, nullptr, 0, nullptr, \

View File

@@ -35,7 +35,7 @@ static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path,
Assert(read_size == fsize);
scc_fclose(fp);
scc_pe_name_vec_t symbol_names;
// scc_pe_name_vec_t symbol_names;
usize line = 0;
for (usize i = 0; i < fsize; i += 1) {
if (buffer[i] == '\n') {

View File

@@ -0,0 +1,8 @@
int main(void) {
char buff[] = "hello buffer";
int res = 0;
for (int i = 0; i < sizeof(buff); i += 1) {
res += buff[i];
}
return res;
}

9
tests/simple/16_enum.c Normal file
View File

@@ -0,0 +1,9 @@
int main(void) {
enum {
ENUM_0,
ENUM_2 = 2,
ENUM_3,
};
return ENUM_0 + ENUM_2 + ENUM_3;
}

View File

@@ -16,4 +16,6 @@
"./12_logic.c" = 10
"./13_array.c" = 1198
"./14_pointer.c" = 2
"./15_array_subscript.c" = 1198
"./16_enum.c" = 5
[stdout_val_cases]