From f6bc40ae4a3843cee0d8396766f2b967d0ee060d Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Mon, 27 Apr 2026 20:40:03 +0800 Subject: [PATCH] =?UTF-8?q?refactor(ast):=20=E5=B0=86AST=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E9=87=8D=E6=9E=84=E4=B8=BA=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将scc_ast_type_t替换为scc_ast_qual_type_t,引入规范类型概念 - 添加scc_ast_canonical_type_t联合体用于表示规范类型 - 修改头文件结构,移除大量内联初始化函数,改为使用AST上下文分配器 - 添加SCC_AST_ALLOC宏用于统一节点分配管理 - 更新builtin类型枚举定义,添加类型计数常量 feat(ast): 引入AST上下文管理器 - 创建scc_ast_ctx_t结构体用于管理AST节点生命周期 - 实现类型池化机制,支持内置类型的统一管理 - 添加canonical类型获取和分配接口 refactor(abi): 适配新的AST类型系统 - 更新头文件包含,从改为 - 适配函数参数类型,使用qual_type替代原始type - 使用scc_ast_canon_type()函数获取规范类型进行处理 Co-authored-by: Copilot --- libs/abi/src/scc_type_abi.c | 9 +- libs/ast/include/scc_ast.h | 625 ++------------------------- libs/ast/include/scc_ast_def.h | 111 +++-- libs/ast/include/scc_ast_utils.h | 505 ++++++++++++++++++++++ libs/ast/src/ast_dump.c | 87 ++-- libs/ast/src/scc_ast.c | 42 ++ libs/ast2ir/include/scc_ast2ir.h | 6 +- libs/ast2ir/src/scc_ast2ir.c | 125 ++++-- libs/ir/hir/src/scc_hir_builder.c | 16 +- libs/ir/hir/src/scc_hir_dump.c | 12 + libs/parser/include/scc_parse_type.h | 108 +++++ libs/parser/include/scc_parser.h | 19 +- libs/parser/include/scc_sema.h | 12 +- libs/parser/src/parse_decl.c | 18 +- libs/parser/src/parse_expr.c | 43 +- libs/parser/src/parse_stmt.c | 34 +- libs/parser/src/parse_type.c | 400 +++++++++-------- libs/parser/src/scc_parser.c | 9 +- libs/parser/src/scc_sema.c | 156 +++---- src/main.c | 10 +- 20 files changed, 1302 insertions(+), 1045 deletions(-) create mode 100644 libs/ast/include/scc_ast_utils.h create mode 100644 libs/ast/src/scc_ast.c create mode 100644 libs/parser/include/scc_parse_type.h diff --git a/libs/abi/src/scc_type_abi.c b/libs/abi/src/scc_type_abi.c index 933665e..223df7e 100644 --- a/libs/abi/src/scc_type_abi.c +++ b/libs/abi/src/scc_type_abi.c @@ -1,12 +1,12 @@ #include -#include +#include #include void scc_abi_compute_ast_type_layout(const scc_abi_type_calc_t *ctx, void *type, scc_abi_type_layout_t *layout) { - scc_ast_type_t *ast_type = type; + scc_ast_qual_type_t *ast_type = type; scc_abi_base_type_kind_t kind = SCC_ABI_TYPE_VOID; - switch (ast_type->builtin.type) { + switch (scc_ast_canon_type(ast_type)->builtin.type) { case SCC_AST_BUILTIN_TYPE_VOID: kind = SCC_ABI_TYPE_VOID; break; @@ -56,7 +56,8 @@ void scc_abi_compute_ast_type_layout(const scc_abi_type_calc_t *ctx, void *type, kind = SCC_ABI_TYPE_U_LONG_LONG; break; default: - Panic("Unsupported AST type: %d", ast_type->builtin.type); + Panic("Unsupported AST type: %d", + scc_ast_canon_type(ast_type)->builtin.type); break; } scc_abi_get_base_type_layout(ctx->impls, kind, layout); diff --git a/libs/ast/include/scc_ast.h b/libs/ast/include/scc_ast.h index bd41afd..3c83ee3 100644 --- a/libs/ast/include/scc_ast.h +++ b/libs/ast/include/scc_ast.h @@ -3,599 +3,46 @@ #include "scc_ast_def.h" -// decls can be nullptr but maybe warning +typedef struct scc_ast_ctx { + scc_ast_canon_type_vec_t canonical_type_pool; + scc_ast_canon_type_t *builtin_types[SCC_AST_BUILTIN_TYPE_COUNT]; + scc_ast_node_vec_t all_nodes; +} scc_ast_ctx_t; + +void scc_ast_ctx_init(scc_ast_ctx_t *ctx); +void scc_ast_ctx_drop(scc_ast_ctx_t *ctx); + +scc_ast_canon_type_t *scc_ast_ctx_get_builtin_type(scc_ast_ctx_t *ctx, + scc_ast_builtin_type_t kind); + +scc_ast_canon_type_t *scc_ast_ctx_alloc_type(scc_ast_ctx_t *ctx); + +static inline void *scc_ast_ctx_alloc_node(scc_ast_ctx_t *ctx, usize size) { + void *ptr = scc_malloc(size); + if (ptr == nullptr) { + Panic("Out of memory"); + } + scc_memset(ptr, 0, size); + scc_vec_push(ctx->all_nodes, (scc_ast_node_t *)ptr); + return ptr; +} + +#define SCC_AST_ALLOC(ctx, type) \ + ((type *)scc_ast_ctx_alloc_node(ctx, sizeof(type))) +#define SCC_AST_ALLOC_QUAL_TYPE(ctx) SCC_AST_ALLOC(ctx, scc_ast_qual_type_t) +#define SCC_AST_ALLOC_DECL(ctx) SCC_AST_ALLOC(ctx, scc_ast_decl_t) +#define SCC_AST_ALLOC_EXPR(ctx) SCC_AST_ALLOC(ctx, scc_ast_expr_t) +#define SCC_AST_ALLOC_STMT(ctx) SCC_AST_ALLOC(ctx, scc_ast_stmt_t) + +// have defined cannoical_type type static inline void -scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit, - scc_ast_decl_vec_t *decls, scc_pos_t loc) { - Assert(translation_unit != nullptr); - translation_unit->base.type = SCC_AST_TRANSLATION_UNIT; - translation_unit->base.loc = loc; - if (decls == nullptr) { - scc_vec_init(translation_unit->declarations); - } else { - translation_unit->declarations = *decls; - scc_vec_init(*decls); - } -} - -static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl, - scc_ast_decl_vec_t *list_move, - scc_pos_t loc) { - Assert(decl != nullptr && list_move != nullptr); - decl->base.loc = loc; - decl->base.type = SCC_AST_DECL_LIST; - decl->name = nullptr; - decl->list.vars = *list_move; - scc_vec_init(*list_move); -} - -// name and var_init can be nullptr -static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl, - scc_ast_type_t *type, - const char *name, - scc_ast_expr_t *var_init, - scc_pos_t loc) { - Assert(decl != nullptr && type != nullptr); - decl->base.loc = loc; - decl->base.type = SCC_AST_DECL_VAR; - decl->name = name; - decl->var.type = type; - decl->var.init = var_init; -} - -// var_init can be nullptr -static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl, - scc_ast_type_t *type, const char *name, - scc_ast_expr_t *var_init, - scc_pos_t loc) { - Assert(decl != nullptr && name != nullptr && type != nullptr); - decl->base.loc = loc; - decl->base.type = SCC_AST_DECL_VAR; - decl->name = name; - decl->var.type = type; - decl->var.init = var_init; -} - -// body can be nullptr -static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl, - scc_ast_type_t *type, - const char *name, - scc_ast_stmt_t *body, scc_pos_t loc) { - Assert(decl != nullptr && name != nullptr && type != nullptr); - decl->base.loc = loc; - decl->base.type = SCC_AST_DECL_FUNC; - decl->name = name; - decl->func.type = type; - Assert(type->base.type == SCC_AST_TYPE_FUNCTION); - decl->func.body = body; -} - -// name can be nullptr -static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl, - scc_ast_type_t *type, - const char *name, int idx, - scc_pos_t loc) { - Assert(decl != nullptr && type != nullptr); - decl->base.loc = loc; - decl->base.type = SCC_AST_DECL_PARAM; - decl->name = name; - decl->param.type = type; - decl->param.param_idx = idx; -} - -static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl, - scc_ast_node_kind_t type, - const char *name, - scc_ast_decl_vec_t *fields_move, - scc_pos_t loc) { - Assert(decl != nullptr); - decl->base.loc = loc; - decl->base.type = type; - decl->name = name; - if (fields_move == nullptr) { - scc_vec_init(decl->record.fields); - } else { - decl->record.fields = *fields_move; - scc_vec_init(*fields_move); - } -} - -// name and fields can be nullptr -static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl, - const char *name, - scc_ast_decl_vec_t *fields_move, - scc_pos_t loc) { - _scc_ast_decl_record_init(decl, SCC_AST_DECL_STRUCT, name, fields_move, - loc); -} - -// name and fields can be nullptr -static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl, - const char *name, - scc_ast_decl_vec_t *fields_move, - scc_pos_t loc) { - _scc_ast_decl_record_init(decl, SCC_AST_DECL_UNION, name, fields_move, loc); -} - -// name and fields can be nullptr -static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl, - const char *name, - scc_ast_decl_vec_t *fields_move, - scc_pos_t loc) { - _scc_ast_decl_record_init(decl, SCC_AST_DECL_ENUM, name, fields_move, loc); -} - -static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl, - const char *name, - scc_ast_type_t *type, - scc_pos_t loc) { - Assert(decl != nullptr && name != nullptr && type != nullptr); - decl->base.loc = loc; - decl->base.type = SCC_AST_DECL_TYPEDEF; - decl->name = name; - decl->typedef_decl.type = type; -} - -// items can be nullptr -static inline void scc_ast_stmt_compound_init( - scc_ast_stmt_t *stmt, scc_ast_block_item_vec_t *items_move, scc_pos_t loc) { - Assert(stmt != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_COMPOUND; - if (items_move == nullptr) { - scc_vec_init(stmt->compound.block_items); - } else { - stmt->compound.block_items = *items_move; - scc_vec_init(*items_move); - } -} - -// expr can be nullptr -static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt, - scc_ast_expr_t *expr, scc_pos_t loc) { - Assert(stmt != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_EXPR; - stmt->expr.expr = expr; -} - -// opt_else can be nullptr -static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt, - scc_ast_expr_t *cond, - scc_ast_stmt_t *then, - scc_ast_stmt_t *opt_else, - scc_pos_t loc) { - Assert(stmt != nullptr && cond != nullptr && then != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_IF; - stmt->if_stmt.cond = cond; - stmt->if_stmt.then_stmt = then; - stmt->if_stmt.opt_else_stmt = opt_else; -} - -static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt, - scc_ast_expr_t *cond, - scc_ast_stmt_t *body, - scc_pos_t loc) { - Assert(stmt != nullptr && cond != nullptr && body != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_WHILE; - stmt->while_stmt.cond = cond; - stmt->while_stmt.body = body; -} - -static inline void scc_ast_stmt_do_while_init(scc_ast_stmt_t *stmt, - scc_ast_expr_t *cond, - scc_ast_stmt_t *body, - scc_pos_t loc) { - Assert(stmt != nullptr && cond != nullptr && body != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_DO_WHILE; - stmt->while_stmt.cond = cond; - stmt->while_stmt.body = body; -} - -// FIXME -static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt, - scc_ast_node_t *init, - scc_ast_expr_t *cond, - scc_ast_expr_t *incr, - scc_ast_stmt_t *body, scc_pos_t loc) { - Assert(stmt != nullptr && body != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_FOR; - stmt->for_stmt.init = init; - stmt->for_stmt.cond = cond; - stmt->for_stmt.incr = incr; - stmt->for_stmt.body = body; -} - -static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt, - scc_ast_expr_t *cond, - scc_ast_stmt_t *body, - scc_pos_t loc) { - Assert(stmt != nullptr && cond != nullptr && body != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_SWITCH; - stmt->switch_stmt.cond = cond; - stmt->switch_stmt.body = body; -} - -static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt, - scc_ast_expr_t *cond, - scc_ast_stmt_t *body, scc_pos_t loc) { - Assert(stmt != nullptr && cond != nullptr && body != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_CASE; - stmt->case_stmt.expr = cond; - stmt->case_stmt.stmt = body; -} - -static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt, - scc_ast_stmt_t *body, - scc_pos_t loc) { - Assert(stmt != nullptr && body != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_DEFAULT; - stmt->default_stmt.stmt = body; -} - -static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt, - scc_pos_t loc) { - Assert(stmt != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_BREAK; - stmt->jump._target = nullptr; -} - -static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt, - scc_pos_t loc) { - Assert(stmt != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_CONTINUE; - stmt->jump._target = nullptr; -} - -// expr can be nullptr -static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt, - scc_ast_expr_t *expr, - scc_pos_t loc) { - Assert(stmt != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_RETURN; - stmt->return_stmt.expr = expr; -} - -static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt, - const char *label, scc_pos_t loc) { - Assert(stmt != nullptr && label != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_GOTO; - stmt->goto_stmt.label = label; - stmt->goto_stmt._target = nullptr; -} - -static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt, - const char *label, - scc_ast_stmt_t *body, - scc_pos_t loc) { - Assert(stmt != nullptr); - stmt->base.loc = loc; - stmt->base.type = SCC_AST_STMT_LABEL; - stmt->label_stmt.label = label; - stmt->label_stmt.stmt = body; -} - -static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr, - scc_ast_expr_op_t op, - scc_ast_expr_t *lhs, - scc_ast_expr_t *rhs, - scc_pos_t loc) { - Assert(expr != nullptr && lhs != nullptr && rhs != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_BINARY; - expr->binary.op = op; - expr->binary.lhs = lhs; - expr->binary.rhs = rhs; -} - -static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr, - scc_ast_expr_op_t op, - scc_ast_expr_t *operand, - scc_pos_t loc) { - Assert(expr != nullptr && operand != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_UNARY; - expr->unary.op = op; - expr->unary.operand = operand; -} - -static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr, - scc_ast_expr_t *cond, - scc_ast_expr_t *then_expr, - scc_ast_expr_t *else_expr, - scc_pos_t loc) { - Assert(expr != nullptr && cond != nullptr && then_expr != nullptr && - else_expr != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_COND; - expr->cond.cond = cond; - expr->cond.then_expr = then_expr; - expr->cond.else_expr = else_expr; -} - -// args can be nullptr -static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr, - scc_ast_expr_t *callee, - scc_ast_expr_vec_t *args, - scc_pos_t loc) { - Assert(expr != nullptr && callee != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_CALL; - expr->call.callee = callee; - if (args == nullptr) { - scc_vec_init(expr->call.args); - } else { - expr->call.args = *args; - } -} - -// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标 -static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr, - scc_ast_expr_t *array, - scc_ast_expr_t *index, - scc_pos_t loc) { - Assert(expr != nullptr && array != nullptr && index != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT; - expr->subscript.array = array; - expr->subscript.index = index; -} - -static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr, - scc_ast_node_kind_t type, - scc_ast_expr_t *object, - const char *member, - scc_pos_t loc) { - Assert(expr != nullptr && object != nullptr && member != nullptr); - expr->base.loc = loc; - expr->base.type = type; - expr->member.base = object; - expr->member.name = member; - expr->member._target_idx = 0; -} - -static inline void scc_ast_expr_member_init(scc_ast_expr_t *expr, - scc_ast_expr_t *object, - const char *member, scc_pos_t loc) { - _scc_ast_expr_member_init(expr, SCC_AST_EXPR_MEMBER, object, member, loc); -} - -static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr, - scc_ast_expr_t *object, - const char *member, - scc_pos_t loc) { - _scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member, - loc); -} - -static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr, - scc_ast_type_t *type, - scc_ast_expr_t *operand, - scc_pos_t loc) { - Assert(expr != nullptr && type != nullptr && operand != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_CAST; - expr->cast.type = type; - expr->cast.expr = operand; -} - -// type and target_expr can be nullptr but it only one of them can be nullptr -static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr, - scc_ast_type_t *type, - scc_ast_expr_t *target_expr, - scc_pos_t loc) { - Assert(expr != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_SIZE_OF; - expr->attr_of.type = type; - expr->attr_of.expr = target_expr; -} - -// type and target_expr can be nullptr but it only one of them can be nullptr -static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr, - scc_ast_type_t *type, - scc_ast_expr_t *target_expr, - scc_pos_t loc) { - Assert(expr != nullptr); - expr->base.loc = loc; - expr->base.type = - SCC_AST_EXPR_SIZE_OF; // 注意:这里使用了 SIZE_OF,可能需要改为 ALIGN_OF - expr->attr_of.type = type; - expr->attr_of.expr = target_expr; -} - -// lhs_exprs and rhs_exprs can be nullptr -static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr, - scc_ast_expr_t *base, - scc_ast_expr_vec_t *lhs_exprs, - scc_ast_expr_vec_t *rhs_exprs, - scc_pos_t loc) { - Assert(expr != nullptr && base != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_COMPOUND; - expr->compound.base = base; - - if (lhs_exprs == nullptr) { - scc_vec_init(expr->compound.lhs_exprs); - } else { - expr->compound.lhs_exprs = *lhs_exprs; - scc_vec_init(*lhs_exprs); - } - - if (rhs_exprs == nullptr) { - scc_vec_init(expr->compound.rhs_exprs); - } else { - expr->compound.rhs_exprs = *rhs_exprs; - scc_vec_init(*rhs_exprs); - } -} - -static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr, - scc_ast_node_kind_t type, - const char *value, cbool owned, - scc_pos_t loc) { - Assert(expr != nullptr && value != nullptr); - expr->base.loc = loc; - expr->base.type = type; - expr->literal.lexme = value; - expr->literal.owned = owned; -} - -static inline void scc_ast_expr_literal_int_init(scc_ast_expr_t *expr, - const char *value, cbool owned, - scc_pos_t loc) { - scc_ast_expr_literal_init(expr, SCC_AST_EXPR_INT_LITERAL, value, owned, - loc); -} - -static inline void scc_ast_expr_literal_float_init(scc_ast_expr_t *expr, - const char *value, - cbool owned, scc_pos_t loc) { - scc_ast_expr_literal_init(expr, SCC_AST_EXPR_FLOAT_LITERAL, value, owned, - loc); -} -static inline void scc_ast_expr_literal_char_init(scc_ast_expr_t *expr, - const char *value, - cbool owned, scc_pos_t loc) { - scc_ast_expr_literal_init(expr, SCC_AST_EXPR_CHAR_LITERAL, value, owned, - loc); -} -static inline void scc_ast_expr_literal_string_init(scc_ast_expr_t *expr, - const char *value, - cbool owned, - scc_pos_t loc) { - scc_ast_expr_literal_init(expr, SCC_AST_EXPR_STRING_LITERAL, value, owned, - loc); -} - -static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr, - const char *name, - scc_pos_t loc) { - Assert(expr != nullptr && name != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_IDENTIFIER; - expr->identifier.name = name; - expr->identifier._target = nullptr; -} - -static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr, - scc_ast_type_t *type, - scc_pos_t loc) { - Assert(expr != nullptr && type != nullptr); - expr->base.loc = loc; - expr->base.type = SCC_AST_EXPR_LVALUE; - expr->lvalue.type = type; -} - -// have defined builtin type -static inline void scc_ast_type_builtin_init(scc_ast_type_t *type, - scc_ast_builtin_type_t builtin, - scc_pos_t loc) { +scc_ast_type_builtin_init(scc_ast_qual_type_t *type, scc_ast_ctx_t *ctx, + scc_ast_builtin_type_t builtin_type, scc_pos_t loc) { Assert(type != nullptr); type->base.loc = loc; type->base.type = SCC_AST_TYPE_BUILTIN; - type->builtin.type = builtin; + type->type = scc_ast_ctx_get_builtin_type(ctx, builtin_type); type->quals = (scc_ast_decl_specifier_t){0}; // FIXME } -static inline void scc_ast_type_pointer_init(scc_ast_type_t *type, - scc_ast_type_t *pointee, - scc_pos_t loc) { - Assert(type != nullptr && pointee != nullptr); - type->base.loc = loc; - type->base.type = SCC_AST_TYPE_POINTER; - type->quals = (scc_ast_decl_specifier_t){0}; // FIXME - type->pointer.pointee = pointee; -} - -// size can be nullptr -static inline void scc_ast_type_array_init(scc_ast_type_t *type, - scc_ast_type_t *element, - scc_ast_expr_t *size, - scc_pos_t loc) { - Assert(type != nullptr && element != nullptr); - type->base.loc = loc; - type->base.type = SCC_AST_TYPE_ARRAY; - type->quals = (scc_ast_decl_specifier_t){0}; // FIXME - type->array.element = element; - type->array.size = size; -} - -// return_type and params can be nullptr -static inline void scc_ast_type_function_init(scc_ast_type_t *type, - scc_ast_type_t *return_type, - scc_ast_decl_vec_t *params, - scc_pos_t loc) { - Assert(type != nullptr); - type->base.loc = loc; - type->base.type = SCC_AST_TYPE_FUNCTION; - type->function.return_type = return_type; - type->quals = (scc_ast_decl_specifier_t){0}; // FIXME - if (params == nullptr) { - scc_vec_init(type->function.params); - } else { - type->function.params = *params; - scc_vec_init(*params); - } -} - -static inline void _scc_ast_type_record_init(scc_ast_type_t *type, - scc_ast_node_kind_t type_kind, - const char *name, - scc_ast_decl_t *decl, - scc_pos_t loc) { - Assert(type != nullptr); - type->base.loc = loc; - type->base.type = type_kind; - type->quals = (scc_ast_decl_specifier_t){0}; // FIXME - type->record.name = name; - type->record.decl = decl; -} - -// name and decl can be nullptr -static inline void scc_ast_type_struct_init(scc_ast_type_t *type, - const char *name, - scc_ast_decl_t *decl, - scc_pos_t loc) { - _scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl, loc); -} - -// name and decl can be nullptr -static inline void scc_ast_type_union_init(scc_ast_type_t *type, - const char *name, - scc_ast_decl_t *decl, - scc_pos_t loc) { - _scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl, loc); -} - -// name and decl can be nullptr -static inline void scc_ast_type_enum_init(scc_ast_type_t *type, - const char *name, - scc_ast_decl_t *decl, scc_pos_t loc) { - _scc_ast_type_record_init(type, SCC_AST_TYPE_ENUM, name, decl, loc); -} - -static inline void scc_ast_type_typedef_init(scc_ast_type_t *type, - const char *name, - scc_ast_decl_t *target, - scc_pos_t loc) { - Assert(type != nullptr && target != nullptr); - type->base.loc = loc; - type->base.type = SCC_AST_TYPE_TYPEDEF; - type->quals = (scc_ast_decl_specifier_t){0}; // FIXME - type->typedef_type.name = name; - type->typedef_type.decl = target; -} - -#endif /* __SCC_AST_H__ */ +#endif /* __SCC_AST_H__*/ diff --git a/libs/ast/include/scc_ast_def.h b/libs/ast/include/scc_ast_def.h index c7d496d..c2a73f8 100644 --- a/libs/ast/include/scc_ast_def.h +++ b/libs/ast/include/scc_ast_def.h @@ -64,16 +64,16 @@ typedef enum { scc_ast_expr_t_END, // 表达式结束 // 类型 - scc_ast_type_t_BEGIN, // 类型开始 - SCC_AST_TYPE_BUILTIN, // 内置类型 - SCC_AST_TYPE_POINTER, // 指针类型 - SCC_AST_TYPE_ARRAY, // 数组类型 - SCC_AST_TYPE_FUNCTION, // 函数类型 - SCC_AST_TYPE_STRUCT, // 结构体类型 - SCC_AST_TYPE_UNION, // 联合类型 - SCC_AST_TYPE_ENUM, // 枚举类型 - SCC_AST_TYPE_TYPEDEF, // typedef 类型 - scc_ast_type_t_END, // 类型结束 + scc_ast_qual_type_t_BEGIN, // 类型开始 + SCC_AST_TYPE_BUILTIN, // 内置类型 + SCC_AST_TYPE_POINTER, // 指针类型 + SCC_AST_TYPE_ARRAY, // 数组类型 + SCC_AST_TYPE_FUNCTION, // 函数类型 + SCC_AST_TYPE_STRUCT, // 结构体类型 + SCC_AST_TYPE_UNION, // 联合类型 + SCC_AST_TYPE_ENUM, // 枚举类型 + SCC_AST_TYPE_TYPEDEF, // typedef 类型 + scc_ast_qual_type_t_END, // 类型结束 // 其他 scc_ast_translation_unit_t_BEGIN, @@ -85,6 +85,7 @@ typedef struct scc_ast_node { scc_ast_node_kind_t type; scc_pos_t loc; } scc_ast_node_t; +typedef SCC_VEC(scc_ast_node_t *) scc_ast_node_vec_t; #define SCC_AST_CAST_TO(kind, expr) \ ((kind *)(Assert(((scc_ast_node_t *)expr)->type > kind##_BEGIN && \ @@ -126,6 +127,8 @@ typedef enum { SCC_AST_BUILTIN_TYPE_COMPLEX_FLOAT, SCC_AST_BUILTIN_TYPE_COMPLEX_DOUBLE, SCC_AST_BUILTIN_TYPE_COMPLEX_LONG_DOUBLE, + + SCC_AST_BUILTIN_TYPE_COUNT, } scc_ast_builtin_type_t; /** @@ -147,13 +150,14 @@ typedef struct { cbool is_inline; } scc_ast_decl_specifier_t; -// 前向声明 -typedef struct scc_ast_type scc_ast_type_t; +typedef union scc_ast_canonical_type scc_ast_canon_type_t; +typedef struct scc_ast_qual_type scc_ast_qual_type_t; typedef struct scc_ast_expr scc_ast_expr_t; typedef struct scc_ast_stmt scc_ast_stmt_t; typedef struct scc_ast_decl scc_ast_decl_t; -typedef SCC_VEC(scc_ast_type_t *) scc_ast_type_vec_t; +typedef SCC_VEC(scc_ast_canon_type_t *) scc_ast_canon_type_vec_t; +typedef SCC_VEC(scc_ast_qual_type_t *) scc_ast_qual_type_vec_t; typedef SCC_VEC(scc_ast_expr_t *) scc_ast_expr_vec_t; typedef SCC_VEC(scc_ast_stmt_t *) scc_ast_stmt_vec_t; typedef SCC_VEC(scc_ast_decl_t *) scc_ast_decl_vec_t; @@ -161,39 +165,52 @@ typedef SCC_VEC(scc_ast_decl_t *) scc_ast_decl_vec_t; // 通过指针实现泛型 only stmt or decl typedef SCC_VEC(scc_ast_node_t *) scc_ast_block_item_vec_t; +// 规范类型 Canonical Type +union scc_ast_canonical_type { + struct { + scc_ast_builtin_type_t type; + } builtin; + struct { + scc_ast_qual_type_t *pointee; + } pointer; + struct { + scc_ast_qual_type_t *element; + scc_ast_expr_t *size; // 可为 nullptr <=> 不定长数组 + } array; + struct { + scc_ast_qual_type_t *return_type; + scc_ast_decl_vec_t params; // va_list <=> ... + } function; + struct { + const char *name; + scc_ast_decl_t *decl; // can be nullptr + } record; + struct { + const char *name; + /// @brief 指向typedef的声明(可以间接找到typedef的指向的类型) + scc_ast_decl_t *decl; + } typedef_type; +}; + /** * @brief 类型表示 */ -struct scc_ast_type { +struct scc_ast_qual_type { scc_ast_node_t base; scc_ast_decl_specifier_t quals; - union { - struct { - scc_ast_builtin_type_t type; - } builtin; - struct { - scc_ast_type_t *pointee; - } pointer; - struct { - scc_ast_type_t *element; - scc_ast_expr_t *size; // 可为 nullptr <=> 不定长数组 - } array; - struct { - scc_ast_type_t *return_type; - scc_ast_decl_vec_t params; // va_list <=> ... - } function; - struct { - const char *name; - scc_ast_decl_t *decl; // can be nullptr - } record; - struct { - const char *name; - /// @brief 指向typedef的声明(可以间接找到typedef的指向的类型) - scc_ast_decl_t *decl; - } typedef_type; - }; + scc_ast_canon_type_t *type; }; +static inline const scc_ast_canon_type_t * +scc_ast_canon_type(const scc_ast_qual_type_t *type) { + return type->type; +} + +static inline scc_ast_canon_type_t * +scc_ast_mut_canon_type(scc_ast_qual_type_t *type) { + return type->type; +} + /** * @brief AST 操作符枚举 * 这个枚举定义了所有在AST中使用的操作符,与词法token分离 @@ -302,12 +319,12 @@ struct scc_ast_expr { } member; // cast 类型转换 struct { - scc_ast_type_t *type; + scc_ast_qual_type_t *type; scc_ast_expr_t *expr; } cast; // sizeof / _Alignof / ... union { - scc_ast_type_t *type; + scc_ast_qual_type_t *type; scc_ast_expr_t *expr; } attr_of; // 复合字面量 @@ -329,7 +346,7 @@ struct scc_ast_expr { scc_ast_decl_t *_target; ///< fill by sema } identifier; struct { - scc_ast_type_t *type; + scc_ast_qual_type_t *type; } lvalue; // 内置表达式 struct { @@ -418,17 +435,17 @@ struct scc_ast_decl { } list; // 变量声明 struct { - scc_ast_type_t *type; + scc_ast_qual_type_t *type; scc_ast_expr_t *init; // 可为 nullptr } var; // 函数声明 struct { - scc_ast_type_t *type; // 函数类型 - scc_ast_stmt_t *body; // 可为 nullptr 表示只有声明 + scc_ast_qual_type_t *type; // 函数类型 + scc_ast_stmt_t *body; // 可为 nullptr 表示只有声明 } func; // 参数声明 struct { - scc_ast_type_t *type; + scc_ast_qual_type_t *type; int param_idx; } param; // 结构体/联合/枚举声明 @@ -438,7 +455,7 @@ struct scc_ast_decl { } record; struct { /// @brief 被 typedef 的类型 - scc_ast_type_t *type; + scc_ast_qual_type_t *type; } typedef_decl; }; }; diff --git a/libs/ast/include/scc_ast_utils.h b/libs/ast/include/scc_ast_utils.h new file mode 100644 index 0000000..61a20ff --- /dev/null +++ b/libs/ast/include/scc_ast_utils.h @@ -0,0 +1,505 @@ +#ifndef __SCC_AST_UTILS_H__ +#define __SCC_AST_UTILS_H__ + +#include "scc_ast_def.h" + +// decls can be nullptr but maybe warning +static inline void +scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit, + scc_ast_decl_vec_t *decls, scc_pos_t loc) { + Assert(translation_unit != nullptr); + translation_unit->base.type = SCC_AST_TRANSLATION_UNIT; + translation_unit->base.loc = loc; + if (decls == nullptr) { + scc_vec_init(translation_unit->declarations); + } else { + translation_unit->declarations = *decls; + scc_vec_init(*decls); + } +} + +static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl, + scc_ast_decl_vec_t *list_move, + scc_pos_t loc) { + Assert(decl != nullptr && list_move != nullptr); + decl->base.loc = loc; + decl->base.type = SCC_AST_DECL_LIST; + decl->name = nullptr; + decl->list.vars = *list_move; + scc_vec_init(*list_move); +} + +// name and var_init can be nullptr +static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl, + scc_ast_qual_type_t *type, + const char *name, + scc_ast_expr_t *var_init, + scc_pos_t loc) { + Assert(decl != nullptr && type != nullptr); + decl->base.loc = loc; + decl->base.type = SCC_AST_DECL_VAR; + decl->name = name; + decl->var.type = type; + decl->var.init = var_init; +} + +// var_init can be nullptr +static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl, + scc_ast_qual_type_t *type, + const char *name, + scc_ast_expr_t *var_init, + scc_pos_t loc) { + Assert(decl != nullptr && name != nullptr && type != nullptr); + decl->base.loc = loc; + decl->base.type = SCC_AST_DECL_VAR; + decl->name = name; + decl->var.type = type; + decl->var.init = var_init; +} + +// body can be nullptr +static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl, + scc_ast_qual_type_t *type, + const char *name, + scc_ast_stmt_t *body, scc_pos_t loc) { + Assert(decl != nullptr && name != nullptr && type != nullptr); + decl->base.loc = loc; + decl->base.type = SCC_AST_DECL_FUNC; + decl->name = name; + decl->func.type = type; + Assert(type->base.type == SCC_AST_TYPE_FUNCTION); + decl->func.body = body; +} + +// name can be nullptr +static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl, + scc_ast_qual_type_t *type, + const char *name, int idx, + scc_pos_t loc) { + Assert(decl != nullptr && type != nullptr); + decl->base.loc = loc; + decl->base.type = SCC_AST_DECL_PARAM; + decl->name = name; + decl->param.type = type; + decl->param.param_idx = idx; +} + +static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl, + scc_ast_node_kind_t type, + const char *name, + scc_ast_decl_vec_t *fields_move, + scc_pos_t loc) { + Assert(decl != nullptr); + if (name == nullptr) { + name = ""; + } + decl->base.loc = loc; + decl->base.type = type; + decl->name = name; + if (fields_move == nullptr) { + scc_vec_init(decl->record.fields); + } else { + decl->record.fields = *fields_move; + scc_vec_init(*fields_move); + } +} + +// name and fields can be nullptr +static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl, + const char *name, + scc_ast_decl_vec_t *fields_move, + scc_pos_t loc) { + _scc_ast_decl_record_init(decl, SCC_AST_DECL_STRUCT, name, fields_move, + loc); +} + +// name and fields can be nullptr +static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl, + const char *name, + scc_ast_decl_vec_t *fields_move, + scc_pos_t loc) { + _scc_ast_decl_record_init(decl, SCC_AST_DECL_UNION, name, fields_move, loc); +} + +// name and fields can be nullptr +static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl, + const char *name, + scc_ast_decl_vec_t *fields_move, + scc_pos_t loc) { + _scc_ast_decl_record_init(decl, SCC_AST_DECL_ENUM, name, fields_move, loc); +} + +static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl, + const char *name, + scc_ast_qual_type_t *type, + scc_pos_t loc) { + Assert(decl != nullptr && name != nullptr && type != nullptr); + decl->base.loc = loc; + decl->base.type = SCC_AST_DECL_TYPEDEF; + decl->name = name; + decl->typedef_decl.type = type; +} + +// items can be nullptr +static inline void scc_ast_stmt_compound_init( + scc_ast_stmt_t *stmt, scc_ast_block_item_vec_t *items_move, scc_pos_t loc) { + Assert(stmt != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_COMPOUND; + if (items_move == nullptr) { + scc_vec_init(stmt->compound.block_items); + } else { + stmt->compound.block_items = *items_move; + scc_vec_init(*items_move); + } +} + +// expr can be nullptr +static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt, + scc_ast_expr_t *expr, scc_pos_t loc) { + Assert(stmt != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_EXPR; + stmt->expr.expr = expr; +} + +// opt_else can be nullptr +static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt, + scc_ast_expr_t *cond, + scc_ast_stmt_t *then, + scc_ast_stmt_t *opt_else, + scc_pos_t loc) { + Assert(stmt != nullptr && cond != nullptr && then != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_IF; + stmt->if_stmt.cond = cond; + stmt->if_stmt.then_stmt = then; + stmt->if_stmt.opt_else_stmt = opt_else; +} + +static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt, + scc_ast_expr_t *cond, + scc_ast_stmt_t *body, + scc_pos_t loc) { + Assert(stmt != nullptr && cond != nullptr && body != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_WHILE; + stmt->while_stmt.cond = cond; + stmt->while_stmt.body = body; +} + +static inline void scc_ast_stmt_do_while_init(scc_ast_stmt_t *stmt, + scc_ast_expr_t *cond, + scc_ast_stmt_t *body, + scc_pos_t loc) { + Assert(stmt != nullptr && cond != nullptr && body != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_DO_WHILE; + stmt->while_stmt.cond = cond; + stmt->while_stmt.body = body; +} + +// FIXME +static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt, + scc_ast_node_t *init, + scc_ast_expr_t *cond, + scc_ast_expr_t *incr, + scc_ast_stmt_t *body, scc_pos_t loc) { + Assert(stmt != nullptr && body != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_FOR; + stmt->for_stmt.init = init; + stmt->for_stmt.cond = cond; + stmt->for_stmt.incr = incr; + stmt->for_stmt.body = body; +} + +static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt, + scc_ast_expr_t *cond, + scc_ast_stmt_t *body, + scc_pos_t loc) { + Assert(stmt != nullptr && cond != nullptr && body != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_SWITCH; + stmt->switch_stmt.cond = cond; + stmt->switch_stmt.body = body; +} + +static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt, + scc_ast_expr_t *cond, + scc_ast_stmt_t *body, scc_pos_t loc) { + Assert(stmt != nullptr && cond != nullptr && body != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_CASE; + stmt->case_stmt.expr = cond; + stmt->case_stmt.stmt = body; +} + +static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt, + scc_ast_stmt_t *body, + scc_pos_t loc) { + Assert(stmt != nullptr && body != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_DEFAULT; + stmt->default_stmt.stmt = body; +} + +static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt, + scc_pos_t loc) { + Assert(stmt != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_BREAK; + stmt->jump._target = nullptr; +} + +static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt, + scc_pos_t loc) { + Assert(stmt != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_CONTINUE; + stmt->jump._target = nullptr; +} + +// expr can be nullptr +static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt, + scc_ast_expr_t *expr, + scc_pos_t loc) { + Assert(stmt != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_RETURN; + stmt->return_stmt.expr = expr; +} + +static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt, + const char *label, scc_pos_t loc) { + Assert(stmt != nullptr && label != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_GOTO; + stmt->goto_stmt.label = label; + stmt->goto_stmt._target = nullptr; +} + +static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt, + const char *label, + scc_ast_stmt_t *body, + scc_pos_t loc) { + Assert(stmt != nullptr); + stmt->base.loc = loc; + stmt->base.type = SCC_AST_STMT_LABEL; + stmt->label_stmt.label = label; + stmt->label_stmt.stmt = body; +} + +static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr, + scc_ast_expr_op_t op, + scc_ast_expr_t *lhs, + scc_ast_expr_t *rhs, + scc_pos_t loc) { + Assert(expr != nullptr && lhs != nullptr && rhs != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_BINARY; + expr->binary.op = op; + expr->binary.lhs = lhs; + expr->binary.rhs = rhs; +} + +static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr, + scc_ast_expr_op_t op, + scc_ast_expr_t *operand, + scc_pos_t loc) { + Assert(expr != nullptr && operand != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_UNARY; + expr->unary.op = op; + expr->unary.operand = operand; +} + +static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr, + scc_ast_expr_t *cond, + scc_ast_expr_t *then_expr, + scc_ast_expr_t *else_expr, + scc_pos_t loc) { + Assert(expr != nullptr && cond != nullptr && then_expr != nullptr && + else_expr != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_COND; + expr->cond.cond = cond; + expr->cond.then_expr = then_expr; + expr->cond.else_expr = else_expr; +} + +// args can be nullptr +static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr, + scc_ast_expr_t *callee, + scc_ast_expr_vec_t *args, + scc_pos_t loc) { + Assert(expr != nullptr && callee != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_CALL; + expr->call.callee = callee; + if (args == nullptr) { + scc_vec_init(expr->call.args); + } else { + expr->call.args = *args; + } +} + +// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标 +static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr, + scc_ast_expr_t *array, + scc_ast_expr_t *index, + scc_pos_t loc) { + Assert(expr != nullptr && array != nullptr && index != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT; + expr->subscript.array = array; + expr->subscript.index = index; +} + +static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr, + scc_ast_node_kind_t type, + scc_ast_expr_t *object, + const char *member, + scc_pos_t loc) { + Assert(expr != nullptr && object != nullptr && member != nullptr); + expr->base.loc = loc; + expr->base.type = type; + expr->member.base = object; + expr->member.name = member; + expr->member._target_idx = 0; +} + +static inline void scc_ast_expr_member_init(scc_ast_expr_t *expr, + scc_ast_expr_t *object, + const char *member, scc_pos_t loc) { + _scc_ast_expr_member_init(expr, SCC_AST_EXPR_MEMBER, object, member, loc); +} + +static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr, + scc_ast_expr_t *object, + const char *member, + scc_pos_t loc) { + _scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member, + loc); +} + +static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr, + scc_ast_qual_type_t *type, + scc_ast_expr_t *operand, + scc_pos_t loc) { + Assert(expr != nullptr && type != nullptr && operand != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_CAST; + expr->cast.type = type; + expr->cast.expr = operand; +} + +// type and target_expr can be nullptr but it only one of them can be nullptr +static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr, + scc_ast_qual_type_t *type, + scc_ast_expr_t *target_expr, + scc_pos_t loc) { + Assert(expr != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_SIZE_OF; + expr->attr_of.type = type; + expr->attr_of.expr = target_expr; +} + +// type and target_expr can be nullptr but it only one of them can be nullptr +static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr, + scc_ast_qual_type_t *type, + scc_ast_expr_t *target_expr, + scc_pos_t loc) { + Assert(expr != nullptr); + expr->base.loc = loc; + expr->base.type = + SCC_AST_EXPR_SIZE_OF; // 注意:这里使用了 SIZE_OF,可能需要改为 ALIGN_OF + expr->attr_of.type = type; + expr->attr_of.expr = target_expr; +} + +// lhs_exprs and rhs_exprs can be nullptr +static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr, + scc_ast_expr_t *base, + scc_ast_expr_vec_t *lhs_exprs, + scc_ast_expr_vec_t *rhs_exprs, + scc_pos_t loc) { + Assert(expr != nullptr && base != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_COMPOUND; + expr->compound.base = base; + + if (lhs_exprs == nullptr) { + scc_vec_init(expr->compound.lhs_exprs); + } else { + expr->compound.lhs_exprs = *lhs_exprs; + scc_vec_init(*lhs_exprs); + } + + if (rhs_exprs == nullptr) { + scc_vec_init(expr->compound.rhs_exprs); + } else { + expr->compound.rhs_exprs = *rhs_exprs; + scc_vec_init(*rhs_exprs); + } +} + +static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr, + scc_ast_node_kind_t type, + const char *value, cbool owned, + scc_pos_t loc) { + Assert(expr != nullptr && value != nullptr); + expr->base.loc = loc; + expr->base.type = type; + expr->literal.lexme = value; + expr->literal.owned = owned; +} + +static inline void scc_ast_expr_literal_int_init(scc_ast_expr_t *expr, + const char *value, cbool owned, + scc_pos_t loc) { + scc_ast_expr_literal_init(expr, SCC_AST_EXPR_INT_LITERAL, value, owned, + loc); +} + +static inline void scc_ast_expr_literal_float_init(scc_ast_expr_t *expr, + const char *value, + cbool owned, scc_pos_t loc) { + scc_ast_expr_literal_init(expr, SCC_AST_EXPR_FLOAT_LITERAL, value, owned, + loc); +} +static inline void scc_ast_expr_literal_char_init(scc_ast_expr_t *expr, + const char *value, + cbool owned, scc_pos_t loc) { + scc_ast_expr_literal_init(expr, SCC_AST_EXPR_CHAR_LITERAL, value, owned, + loc); +} +static inline void scc_ast_expr_literal_string_init(scc_ast_expr_t *expr, + const char *value, + cbool owned, + scc_pos_t loc) { + scc_ast_expr_literal_init(expr, SCC_AST_EXPR_STRING_LITERAL, value, owned, + loc); +} + +static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr, + const char *name, + scc_pos_t loc) { + Assert(expr != nullptr && name != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_IDENTIFIER; + expr->identifier.name = name; + expr->identifier._target = nullptr; +} + +static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr, + scc_ast_qual_type_t *type, + scc_pos_t loc) { + Assert(expr != nullptr && type != nullptr); + expr->base.loc = loc; + expr->base.type = SCC_AST_EXPR_LVALUE; + expr->lvalue.type = type; +} + +#endif /* __SCC_AST_UTILS_H__ */ diff --git a/libs/ast/src/ast_dump.c b/libs/ast/src/ast_dump.c index 1afdbad..ea0251e 100644 --- a/libs/ast/src/ast_dump.c +++ b/libs/ast/src/ast_dump.c @@ -53,7 +53,7 @@ static const char *node_type_names[] = { [SCC_AST_EXPR_STRING_LITERAL] = "StringLiteralExpr", [SCC_AST_EXPR_IDENTIFIER] = "IdentifierExpr", [scc_ast_expr_t_END] = "ERROR", - [scc_ast_type_t_BEGIN] = "ERROR", + [scc_ast_qual_type_t_BEGIN] = "ERROR", [SCC_AST_TYPE_BUILTIN] = "BuiltinType", [SCC_AST_TYPE_POINTER] = "PointerType", [SCC_AST_TYPE_ARRAY] = "ArrayType", @@ -62,7 +62,7 @@ static const char *node_type_names[] = { [SCC_AST_TYPE_UNION] = "UnionType", [SCC_AST_TYPE_ENUM] = "EnumType", [SCC_AST_TYPE_TYPEDEF] = "TypedefType", - [scc_ast_type_t_END] = "ERROR", + [scc_ast_qual_type_t_END] = "ERROR", [scc_ast_translation_unit_t_BEGIN] = "ERROR", [SCC_AST_TRANSLATION_UNIT] = "TranslationUnit", [scc_ast_translation_unit_t_END] = "ERROR", @@ -200,8 +200,8 @@ static inline void dump_child_node(scc_tree_dump_t *td, scc_ast_node_t *child, scc_tree_dump_pop(td); } -static inline void dump_quals(scc_ast_decl_specifier_t quals, - scc_tree_dump_t *td) { +static inline void dump_quals(scc_tree_dump_t *td, + scc_ast_decl_specifier_t quals) { if (quals.is_atomic) scc_tree_dump_value(td, " atomic"); if (quals.is_restrict) @@ -216,18 +216,20 @@ static inline void dump_quals(scc_ast_decl_specifier_t quals, scc_tree_dump_value(td, " extern"); } -static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_t *td) { +static void dump_type_impl(scc_tree_dump_t *td, + const scc_ast_qual_type_t *type) { if (!type) return; scc_tree_dump_begin_line(td); scc_tree_dump_node(td, "%s", get_node_type_str(type->base.type)); - dump_quals(type->quals, td); + dump_quals(td, type->quals); switch (type->base.type) { case SCC_AST_TYPE_BUILTIN: - scc_tree_dump_value(td, " '%s'", - get_builtin_type_str(type->builtin.type)); + scc_tree_dump_value( + td, " '%s'", + get_builtin_type_str(scc_ast_canon_type(type)->builtin.type)); break; case SCC_AST_TYPE_POINTER: scc_tree_dump_value(td, " pointer"); @@ -239,25 +241,29 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_t *td) { scc_tree_dump_value(td, " function"); break; case SCC_AST_TYPE_STRUCT: - if (type->record.name) - scc_tree_dump_value(td, " 'struct %s'", type->record.name); + if (scc_ast_canon_type(type)->record.name) + scc_tree_dump_value(td, " 'struct %s'", + scc_ast_canon_type(type)->record.name); else scc_tree_dump_value(td, " "); break; case SCC_AST_TYPE_UNION: - if (type->record.name) - scc_tree_dump_value(td, " 'union %s'", type->record.name); + if (scc_ast_canon_type(type)->record.name) + scc_tree_dump_value(td, " 'union %s'", + scc_ast_canon_type(type)->record.name); else scc_tree_dump_value(td, " "); break; case SCC_AST_TYPE_ENUM: - if (type->record.name) - scc_tree_dump_value(td, " 'enum %s'", type->record.name); + if (scc_ast_canon_type(type)->record.name) + scc_tree_dump_value(td, " 'enum %s'", + scc_ast_canon_type(type)->record.name); else scc_tree_dump_value(td, " anonymous enum"); break; case SCC_AST_TYPE_TYPEDEF: - scc_tree_dump_value(td, " '%s'", type->typedef_type.name); + scc_tree_dump_value(td, " '%s'", + scc_ast_canon_type(type)->typedef_type.name); break; default: break; @@ -265,26 +271,35 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_t *td) { switch (type->base.type) { case SCC_AST_TYPE_POINTER: - dump_child_node(td, (scc_ast_node_t *)type->pointer.pointee, true); + dump_child_node( + td, (scc_ast_node_t *)scc_ast_canon_type(type)->pointer.pointee, + true); break; case SCC_AST_TYPE_ARRAY: - dump_child_node(td, (scc_ast_node_t *)type->array.element, - type->array.size == nullptr); - if (type->array.size) - dump_child_node(td, (scc_ast_node_t *)type->array.size, true); + dump_child_node( + td, (scc_ast_node_t *)scc_ast_canon_type(type)->array.element, + scc_ast_canon_type(type)->array.size == nullptr); + if (scc_ast_canon_type(type)->array.size) + dump_child_node( + td, (scc_ast_node_t *)scc_ast_canon_type(type)->array.size, + true); break; case SCC_AST_TYPE_FUNCTION: scc_tree_dump_push(td, false); scc_tree_dump_begin_line(td); scc_tree_dump_node(td, "%s", "ReturnType"); - dump_child_node(td, (scc_ast_node_t *)type->function.return_type, true); + dump_child_node( + td, + (scc_ast_node_t *)scc_ast_canon_type(type)->function.return_type, + true); scc_tree_dump_pop(td); scc_tree_dump_push(td, true); - if (scc_vec_size(type->function.params) != 0) { - scc_vec_foreach(type->function.params, i) { - scc_ast_decl_t *param = scc_vec_at(type->function.params, i); - dump_type_impl(param->param.type, td); + if (scc_vec_size(scc_ast_canon_type(type)->function.params) != 0) { + scc_vec_foreach(scc_ast_canon_type(type)->function.params, i) { + scc_ast_decl_t *param = + scc_vec_at(scc_ast_canon_type(type)->function.params, i); + dump_type_impl(td, param->param.type); } } else { scc_tree_dump_begin_line(td); @@ -297,7 +312,7 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_t *td) { } } -static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_t *td) { +static void dump_expr_impl(scc_tree_dump_t *td, const scc_ast_expr_t *expr) { if (!expr) return; @@ -401,7 +416,7 @@ static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_t *td) { } } -static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_t *td) { +static void dump_stmt_impl(scc_tree_dump_t *td, const scc_ast_stmt_t *stmt) { if (!stmt) return; @@ -479,7 +494,7 @@ static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_t *td) { } } -static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_t *td) { +static void dump_decl_impl(scc_tree_dump_t *td, const scc_ast_decl_t *decl) { if (!decl) return; @@ -535,8 +550,8 @@ static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_t *td) { } } -static void dump_unit_impl(scc_ast_translation_unit_t *unit, - scc_tree_dump_t *td) { +static void dump_unit_impl(scc_tree_dump_t *td, + const scc_ast_translation_unit_t *unit) { if (!unit) return; @@ -552,13 +567,13 @@ void scc_ast_dump_node(scc_tree_dump_t *td, const scc_ast_node_t *node) { if (!node) return; if (SCC_AST_IS_A(scc_ast_expr_t, node)) - dump_expr_impl(SCC_AST_CAST_TO(scc_ast_expr_t, node), td); + dump_expr_impl(td, SCC_AST_CAST_TO(scc_ast_expr_t, node)); else if (SCC_AST_IS_A(scc_ast_stmt_t, node)) - dump_stmt_impl(SCC_AST_CAST_TO(scc_ast_stmt_t, node), td); + dump_stmt_impl(td, SCC_AST_CAST_TO(scc_ast_stmt_t, node)); else if (SCC_AST_IS_A(scc_ast_decl_t, node)) - dump_decl_impl(SCC_AST_CAST_TO(scc_ast_decl_t, node), td); - else if (SCC_AST_IS_A(scc_ast_type_t, node)) - dump_type_impl(SCC_AST_CAST_TO(scc_ast_type_t, node), td); + dump_decl_impl(td, SCC_AST_CAST_TO(scc_ast_decl_t, node)); + else if (SCC_AST_IS_A(scc_ast_qual_type_t, node)) + dump_type_impl(td, SCC_AST_CAST_TO(scc_ast_qual_type_t, node)); else if (SCC_AST_IS_A(scc_ast_translation_unit_t, node)) - dump_unit_impl(SCC_AST_CAST_TO(scc_ast_translation_unit_t, node), td); + dump_unit_impl(td, SCC_AST_CAST_TO(scc_ast_translation_unit_t, node)); } diff --git a/libs/ast/src/scc_ast.c b/libs/ast/src/scc_ast.c new file mode 100644 index 0000000..c117752 --- /dev/null +++ b/libs/ast/src/scc_ast.c @@ -0,0 +1,42 @@ +#include + +static scc_ast_canon_type_t *alloc_canonical_type(scc_ast_ctx_t *ctx) { + scc_ast_canon_type_t *type = scc_malloc(sizeof(scc_ast_canon_type_t)); + if (type == nullptr) { + Panic("alloc_canonical_type: malloc failed"); + } + scc_vec_push(ctx->canonical_type_pool, type); + return type; +} + +void scc_ast_ctx_init(scc_ast_ctx_t *ctx) { + scc_vec_init(ctx->canonical_type_pool); + scc_vec_init(ctx->all_nodes); + + // 创建全部内置类型 + for (int i = 0; i < SCC_AST_BUILTIN_TYPE_COUNT; i += 1) { + scc_ast_canon_type_t *t = alloc_canonical_type(ctx); + t->builtin.type = (scc_ast_builtin_type_t)i; // 直接按顺序对应 + ctx->builtin_types[i] = t; + } +} + +void scc_ast_ctx_drop(scc_ast_ctx_t *ctx) { + // 释放所有规范类型 + scc_vec_foreach(ctx->canonical_type_pool, i) { + scc_free(ctx->canonical_type_pool.data[i]); + } + scc_vec_foreach(ctx->all_nodes, i) { scc_free(ctx->all_nodes.data[i]); } + scc_vec_free(ctx->canonical_type_pool); +} + +scc_ast_canon_type_t * +scc_ast_ctx_get_builtin_type(scc_ast_ctx_t *ctx, scc_ast_builtin_type_t kind) { + assert(kind < SCC_AST_BUILTIN_TYPE_COUNT && + kind > SCC_AST_BUILTIN_TYPE_UNKNOWN); + return ctx->builtin_types[kind]; +} + +scc_ast_canon_type_t *scc_ast_ctx_alloc_type(scc_ast_ctx_t *ctx) { + return alloc_canonical_type(ctx); +} diff --git a/libs/ast2ir/include/scc_ast2ir.h b/libs/ast2ir/include/scc_ast2ir.h index 2a65d3f..9da4243 100644 --- a/libs/ast2ir/include/scc_ast2ir.h +++ b/libs/ast2ir/include/scc_ast2ir.h @@ -18,8 +18,8 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, scc_hir_cprog_t *cprog); void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx); -void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, - const scc_ast_translation_unit_t *tu); +void scc_ast2ir_run(scc_ast2ir_ctx_t *ctx, + const scc_ast_translation_unit_t *tu); void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, cbool is_global); scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, @@ -27,6 +27,6 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, cbool is_lvalue); void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt); scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, - const scc_ast_type_t *ast_type); + const scc_ast_qual_type_t *ast_type); #endif /* __SCC_AST2IR_H__ */ diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index c93d655..220b80f 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -1,10 +1,11 @@ #include #include +#include #include #include static scc_hir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx, - const scc_ast_type_t *ast_type) { + const scc_ast_qual_type_t *ast_type) { scc_abi_type_layout_t layout; // 映射内置类型 ctx->abi->compute_type_layout(ctx->abi, (void *)ast_type, &layout); @@ -26,7 +27,7 @@ static scc_hir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx, return SCC_HIR_REF_nullptr; } -static inline void parse_struct_union_layout(scc_ast_type_t *type) {} +static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {} // 辅助函数:计算数组实际长度(如果原长度为0) static void resolve_array_length(scc_ast2ir_ctx_t *ctx, @@ -123,7 +124,7 @@ static void emit_array_initialization(scc_ast2ir_ctx_t *ctx, } scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, - const scc_ast_type_t *ast_type) { + const scc_ast_qual_type_t *ast_type) { if (ctx == nullptr || ast_type == nullptr) { LOG_ERROR("args is nullptr"); return 0; @@ -137,7 +138,7 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, case SCC_AST_TYPE_POINTER: { scc_hir_type_init(&ir_type, SCC_HIR_TYPE_PTR); scc_hir_type_ref_t pointee_type = - scc_ast2ir_type(ctx, ast_type->pointer.pointee); + scc_ast2ir_type(ctx, scc_ast_canon_type(ast_type)->pointer.pointee); ir_type.data.pointer.base = pointee_type; break; } @@ -145,17 +146,20 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, scc_hir_type_init(&ir_type, SCC_HIR_TYPE_ARRAY); scc_hir_type_ref_t element_type = - scc_ast2ir_type(ctx, ast_type->array.element); + scc_ast2ir_type(ctx, scc_ast_canon_type(ast_type)->array.element); ir_type.data.array.base = element_type; ir_type.data.array.len = 0; - if (ast_type->array.size) { + if (scc_ast_canon_type(ast_type)->array.size) { // TODO constant expression - if (ast_type->array.size->base.type != SCC_AST_EXPR_INT_LITERAL) { + if (scc_ast_canon_type(ast_type)->array.size->base.type != + SCC_AST_EXPR_INT_LITERAL) { Panic("TODO: array size expression"); } scc_ap_t value; - scc_ap_from_cstr(&value, ast_type->array.size->literal.lexme, 10); + scc_ap_from_cstr( + &value, scc_ast_canon_type(ast_type)->array.size->literal.lexme, + 10); // FIXME hack ir_type.data.array.len = value.data.digit; } @@ -165,8 +169,8 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, scc_hir_type_init(&ir_type, SCC_HIR_TYPE_FUNC); // 处理返回类型 - scc_hir_type_ref_t ret_type = - scc_ast2ir_type(ctx, ast_type->function.return_type); + scc_hir_type_ref_t ret_type = scc_ast2ir_type( + ctx, scc_ast_canon_type(ast_type)->function.return_type); // 将返回类型添加到程序的类型容器中 ir_type.data.function.ret_type = ret_type; @@ -174,9 +178,9 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, // 转换参数类型 scc_hir_type_ref_vec_t params; scc_vec_init(params); - scc_vec_foreach(ast_type->function.params, i) { + scc_vec_foreach(scc_ast_canon_type(ast_type)->function.params, i) { scc_ast_decl_t *decl_param = - scc_vec_at(ast_type->function.params, i); + scc_vec_at(scc_ast_canon_type(ast_type)->function.params, i); Assert(decl_param->base.type == SCC_AST_DECL_PARAM); scc_hir_type_ref_t tmp_type = scc_ast2ir_type(ctx, decl_param->param.type); @@ -190,10 +194,14 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, scc_hir_type_init(&ir_type, ast_type->base.type == SCC_AST_TYPE_STRUCT ? SCC_HIR_TYPE_STRUCT : SCC_HIR_TYPE_UNION); - Assert(ast_type->record.decl != nullptr); - scc_vec_foreach(ast_type->record.decl->record.fields, i) { - scc_ast_decl_t *decl_field = - scc_vec_at(ast_type->record.decl->record.fields, i); + if (scc_ast_canon_type(ast_type)->record.decl == nullptr) { + Panic("%s record fields is nullptr", + scc_ast_canon_type(ast_type)->record.name); + } + scc_vec_foreach( + scc_ast_canon_type(ast_type)->record.decl->record.fields, i) { + scc_ast_decl_t *decl_field = scc_vec_at( + scc_ast_canon_type(ast_type)->record.decl->record.fields, i); Assert(decl_field->base.type == SCC_AST_DECL_VAR); scc_hir_type_ref_t field_type = scc_ast2ir_type(ctx, decl_field->var.type); @@ -202,13 +210,19 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, break; } case SCC_AST_TYPE_ENUM: - return parse_base_type( - ctx, &(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN, - .builtin = SCC_AST_BUILTIN_TYPE_INT}); + scc_ast_canon_type_t int_canon_type = { + .builtin = SCC_AST_BUILTIN_TYPE_INT, + }; + scc_ast_qual_type_t int_type = { + .base.type = SCC_AST_TYPE_BUILTIN, + .type = &int_canon_type, + }; + return parse_base_type(ctx, &int_type); case SCC_AST_TYPE_TYPEDEF: // TODO maybe using cache - return scc_ast2ir_type(ctx, - ast_type->typedef_type.decl->typedef_decl.type); + return scc_ast2ir_type( + ctx, + scc_ast_canon_type(ast_type)->typedef_type.decl->typedef_decl.type); default: LOG_FATAL("Unsupported AST type: %d", ast_type->base.type); return 0; @@ -560,10 +574,45 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, elem_ptr); // 作为右值:加载值 } } - case SCC_AST_EXPR_MEMBER: - break; - case SCC_AST_EXPR_PTR_MEMBER: - break; + case SCC_AST_EXPR_MEMBER: { + // 1. 获取基对象的左值(地址) + scc_hir_value_ref_t base_ptr = + scc_ast2ir_expr(ctx, expr->member.base, true); + // 2. 通过偏移生成字段地址 + // 需要基对象类型来计算索引:假设 sema 填好了 _target_idx + usize field_idx = expr->member._target_idx; + scc_ap_t idx_ap; + scc_ap_set_int(&idx_ap, field_idx); + scc_hir_value_ref_t idx_val = scc_hir_builder_integer( + &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap); + scc_hir_value_ref_t field_ptr = + scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, idx_val); + if (is_lvalue) + return field_ptr; + else + return scc_hir_builder_load(&ctx->builder, field_ptr); + } + case SCC_AST_EXPR_PTR_MEMBER: { + // 1. 计算指针值(obj->field 等价于 (*obj).field) + scc_hir_value_ref_t obj_ptr = + scc_ast2ir_expr(ctx, expr->member.base, false); + // 2. 解引用得到对象地址,再访问成员 + // 但更简单:先 load 出对象值?不对:obj + // 是指向结构体的指针,我们需要指针的地址? 实际上,obj->field 相当于 + // (*(obj)).field,所以可以直接用 obj 作为基地址进行 get_elem_ptr + // 因为 get_elem_ptr 接收一个指针,obj 本身就是指向结构体的指针。 + usize field_idx = expr->member._target_idx; + scc_ap_t idx_ap; + scc_ap_set_int(&idx_ap, field_idx); + scc_hir_value_ref_t idx_val = scc_hir_builder_integer( + &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap); + scc_hir_value_ref_t field_ptr = + scc_hir_builder_get_elem_ptr(&ctx->builder, obj_ptr, idx_val); + if (is_lvalue) + return field_ptr; + else + return scc_hir_builder_load(&ctx->builder, field_ptr); + } case SCC_AST_EXPR_CAST: break; case SCC_AST_EXPR_SIZE_OF: { @@ -576,8 +625,9 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, // return scc_hir_builder_integer( // &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val); } - case SCC_AST_EXPR_COMPOUND: + case SCC_AST_EXPR_COMPOUND: { break; + } case SCC_AST_EXPR_LVALUE: break; // SCC_AST_EXPR_BUILTIN,// 内置表达式 ... directive map to ir builtin @@ -945,9 +995,10 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, scc_hir_builder_begin_func(&ctx->builder, func_ref); scc_hir_builder_begin_bblock(&ctx->builder, "entry"); - scc_vec_foreach(decl->func.type->function.params, i) { - scc_ast_decl_t *param = - scc_vec_at(decl->func.type->function.params, i); + scc_vec_foreach(scc_ast_canon_type(decl->func.type)->function.params, + i) { + scc_ast_decl_t *param = scc_vec_at( + scc_ast_canon_type(decl->func.type)->function.params, i); scc_ast2ir_decl(ctx, param, false); } @@ -968,7 +1019,8 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, } case SCC_AST_DECL_PARAM: { if (decl->param.type->base.type == SCC_AST_TYPE_BUILTIN && - decl->param.type->builtin.type == SCC_AST_BUILTIN_TYPE_VOID) { + scc_ast_canon_type(decl->param.type)->builtin.type == + SCC_AST_BUILTIN_TYPE_VOID) { break; } scc_hir_type_ref_t parma_type_ref = @@ -988,12 +1040,15 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, } case SCC_AST_DECL_STRUCT: case SCC_AST_DECL_UNION: - scc_ast_type_t type = { - .base.type = - SCC_AST_DECL_STRUCT ? SCC_AST_TYPE_STRUCT : SCC_AST_TYPE_UNION, + scc_ast_canon_type_t canon_type = { .record.decl = decl, .record.name = decl->name, }; + scc_ast_qual_type_t type = { + .base.type = + SCC_AST_DECL_STRUCT ? SCC_AST_TYPE_STRUCT : SCC_AST_TYPE_UNION, + .type = &canon_type, + }; scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, &type); // scc_hir_builder_global_alloca(&ctx->builder, type_ref, // SCC_HIR_REF_nullptr); @@ -1024,8 +1079,8 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, } } -void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, - const scc_ast_translation_unit_t *tu) { +void scc_ast2ir_run(scc_ast2ir_ctx_t *ctx, + const scc_ast_translation_unit_t *tu) { Assert(ctx != nullptr && tu != nullptr); scc_vec_foreach(tu->declarations, i) { diff --git a/libs/ir/hir/src/scc_hir_builder.c b/libs/ir/hir/src/scc_hir_builder.c index ed58dec..21bbad2 100644 --- a/libs/ir/hir/src/scc_hir_builder.c +++ b/libs/ir/hir/src/scc_hir_builder.c @@ -123,7 +123,7 @@ static int cmp_type(const void *_key1, const void *_key2, void *userdata) { key2->data.function.params.size) { return 1; } - for (usize i = 0; i < key1->data.function.params.size; i++) { + scc_vec_foreach(key1->data.function.params, i) { if (key1->data.function.params.data[i] != key2->data.function.params.data[i]) { return 1; @@ -131,6 +131,20 @@ static int cmp_type(const void *_key1, const void *_key2, void *userdata) { } return 0; } + case SCC_HIR_TYPE_STRUCT: + case SCC_HIR_TYPE_UNION: { + if (key1->data.aggregate.fields.size != + key2->data.aggregate.fields.size) { + return 1; + } + scc_vec_foreach(key1->data.aggregate.fields, i) { + if (key1->data.aggregate.fields.data[i] != + key2->data.aggregate.fields.data[i]) { + return 1; + } + } + return 0; + } default: Panic("Unknown key type %d", key1->tag); return 1; diff --git a/libs/ir/hir/src/scc_hir_dump.c b/libs/ir/hir/src/scc_hir_dump.c index fdda5f4..c69fc9e 100644 --- a/libs/ir/hir/src/scc_hir_dump.c +++ b/libs/ir/hir/src/scc_hir_dump.c @@ -429,6 +429,18 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx, 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"); + scc_vec_foreach(type->data.aggregate.fields, i) { + scc_hir_dump_type_linear( + ctx, scc_vec_at(type->data.aggregate.fields, i)); + scc_tree_dump_append(ctx->dump_ctx, ";"); + } + scc_tree_dump_append(ctx->dump_ctx, "}"); + break; default: LOG_ERROR("invalid type tag"); break; diff --git a/libs/parser/include/scc_parse_type.h b/libs/parser/include/scc_parse_type.h new file mode 100644 index 0000000..2916694 --- /dev/null +++ b/libs/parser/include/scc_parse_type.h @@ -0,0 +1,108 @@ +#ifndef __SCC_PARSE_TYPE_H__ +#define __SCC_PARSE_TYPE_H__ + +#include +#include + +static inline void scc_ast_type_pointer_init(scc_ast_qual_type_t *type, + scc_ast_canon_type_t *canon, + scc_ast_qual_type_t *pointee, + scc_pos_t loc) { + Assert(type != nullptr && pointee != nullptr); + type->base.loc = loc; + type->base.type = SCC_AST_TYPE_POINTER; + type->quals = (scc_ast_decl_specifier_t){0}; + type->type = canon; + canon->pointer.pointee = pointee; +} + +// size can be nullptr +static inline void scc_ast_type_array_init(scc_ast_qual_type_t *type, + scc_ast_canon_type_t *canon, + scc_ast_qual_type_t *element, + scc_ast_expr_t *size, + scc_pos_t loc) { + Assert(type != nullptr && element != nullptr); + type->base.loc = loc; + type->base.type = SCC_AST_TYPE_ARRAY; + type->quals = (scc_ast_decl_specifier_t){0}; + type->type = canon; + canon->array.element = element; + canon->array.size = size; +} + +// return_type and params can be nullptr +static inline void scc_ast_type_function_init(scc_ast_qual_type_t *type, + scc_ast_canon_type_t *canon, + scc_ast_qual_type_t *return_type, + scc_ast_decl_vec_t *params, + scc_pos_t loc) { + Assert(type != nullptr); + type->base.loc = loc; + type->base.type = SCC_AST_TYPE_FUNCTION; + type->quals = (scc_ast_decl_specifier_t){0}; + type->type = canon; + canon->function.return_type = return_type; + if (params == nullptr) { + scc_vec_init(canon->function.params); + } else { + canon->function.params = *params; + scc_vec_init(*params); + } +} + +static inline void _scc_ast_type_record_init(scc_ast_qual_type_t *type, + scc_ast_canon_type_t *canon, + scc_ast_node_kind_t type_kind, + const char *name, + scc_ast_decl_t *decl, + scc_pos_t loc) { + Assert(type != nullptr); + type->base.loc = loc; + type->base.type = type_kind; + type->quals = (scc_ast_decl_specifier_t){0}; + type->type = canon; + canon->record.name = name; + canon->record.decl = decl; +} + +// name and decl can be nullptr +static inline void scc_ast_type_struct_init(scc_ast_qual_type_t *type, + scc_ast_canon_type_t *canon, + const char *name, + scc_ast_decl_t *decl, + scc_pos_t loc) { + _scc_ast_type_record_init(type, canon, SCC_AST_TYPE_STRUCT, name, decl, + loc); +} + +// name and decl can be nullptr +static inline void +scc_ast_type_union_init(scc_ast_qual_type_t *type, scc_ast_canon_type_t *canon, + const char *name, scc_ast_decl_t *decl, scc_pos_t loc) { + _scc_ast_type_record_init(type, canon, SCC_AST_TYPE_UNION, name, decl, loc); +} + +// name and decl can be nullptr +static inline void scc_ast_type_enum_init(scc_ast_qual_type_t *type, + scc_ast_canon_type_t *canon, + const char *name, + scc_ast_decl_t *decl, scc_pos_t loc) { + _scc_ast_type_record_init(type, canon, SCC_AST_TYPE_ENUM, name, decl, loc); +} + +static inline void scc_ast_type_typedef_init(scc_ast_qual_type_t *type, + scc_ast_canon_type_t *canon, + const char *name, + scc_ast_decl_t *target, + scc_pos_t loc) { + Assert(type != nullptr && target != nullptr); + type->base.loc = loc; + type->base.type = SCC_AST_TYPE_TYPEDEF; + type->quals = (scc_ast_decl_specifier_t){0}; + type->type = canon; + canon->typedef_type.name = name; + canon->typedef_type.decl = target; +} + +#endif /* __SCC_PARSE_TYPE_H__ */ diff --git a/libs/parser/include/scc_parser.h b/libs/parser/include/scc_parser.h index e867c28..28c7737 100644 --- a/libs/parser/include/scc_parser.h +++ b/libs/parser/include/scc_parser.h @@ -14,12 +14,13 @@ typedef struct scc_parser { scc_lexer_tok_ring_t *ring; usize checkpoint; - scc_sema_callbacks_t sema_callbacks; + scc_ast_ctx_t *ast_ctx; + scc_sema_ctx_t sema_callbacks; scc_ast_translation_unit_t *translation_unit; int errcode; } scc_parser_t; -// static inline scc_ast_type_t *scc_parser_ +// static inline scc_ast_qual_type_t *scc_parser_ /** * @brief 初始化解析器 @@ -28,7 +29,7 @@ typedef struct scc_parser { * @param callbacks 语义分析回调(可为 nullptr) */ void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring, - scc_sema_callbacks_t *callbacks); + scc_ast_ctx_t *ast_ctx, scc_sema_ctx_t *callbacks); /** * @brief 销毁解析器 @@ -74,9 +75,9 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser); * @return 类型 AST 节点 */ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser, - scc_ast_type_t *type); -scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser); -scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser); + scc_ast_qual_type_t *type); +scc_ast_qual_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser); +scc_ast_qual_type_t *scc_parse_type_name(scc_parser_t *parser); static inline void scc_parse_decl_sema(scc_parser_t *parser, scc_ast_decl_t *decl) { @@ -100,14 +101,14 @@ static inline void scc_parse_stmt_sema(scc_parser_t *parser, } static inline void scc_parse_type_sema(scc_parser_t *parser, - scc_ast_type_t *type) { + scc_ast_qual_type_t *type) { parser->sema_callbacks.on_type(parser->sema_callbacks.context, type ? type->base.type : SCC_AST_UNKNOWN, type); } -static inline scc_ast_type_t *scc_parse_got_type(scc_parser_t *parser, - const char *name) { +static inline const scc_ast_qual_type_t * +scc_parse_got_type(scc_parser_t *parser, const char *name) { return parser->sema_callbacks.got_type(parser->sema_callbacks.context, name); } diff --git a/libs/parser/include/scc_sema.h b/libs/parser/include/scc_sema.h index 32c0bae..bc3b426 100644 --- a/libs/parser/include/scc_sema.h +++ b/libs/parser/include/scc_sema.h @@ -9,21 +9,23 @@ typedef void (*scc_sema_callback_t)(void *context, scc_ast_node_kind_t node_type, void *node); -typedef scc_ast_type_t *(*scc_sema_got_type_t)(void *context, const char *name); +typedef const scc_ast_qual_type_t *(*scc_sema_got_type_t)(void *context, + const char *name); /** * @brief 语义分析回调集合 */ -typedef struct scc_sema_callbacks { +typedef struct scc_sema_ctx { scc_sema_callback_t on_decl; scc_sema_callback_t on_stmt; scc_sema_callback_t on_expr; scc_sema_callback_t on_type; scc_sema_got_type_t got_type; + scc_ast_ctx_t *ast_ctx; void *context; -} scc_sema_callbacks_t; +} scc_sema_ctx_t; -void scc_sema_init(scc_sema_callbacks_t *callbacks); -void scc_sema_drop(scc_sema_callbacks_t *callbacks); +void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_ctx_t *ast_ctx); +void scc_sema_drop(scc_sema_ctx_t *sema_ctx); #endif /* __SCC_SEMA_H__ */ diff --git a/libs/parser/src/parse_decl.c b/libs/parser/src/parse_decl.c index 309b84e..8cfc872 100644 --- a/libs/parser/src/parse_decl.c +++ b/libs/parser/src/parse_decl.c @@ -152,6 +152,7 @@ A.2.4 External definitions */ #include +#include #include scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, @@ -186,7 +187,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, scc_pos_t pos = tok.loc; scc_lexer_tok_drop(&tok); - init = scc_malloc(sizeof(scc_ast_expr_t)); + init = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(init != nullptr); scc_ast_expr_vec_t lhs_exprs; scc_vec_init(lhs_exprs); @@ -202,7 +203,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, tok_ptr = scc_parser_peek(parser); if (tok_ptr && tok_ptr->type == SCC_TOK_IDENT) { scc_parser_next_consume(parser, &tok); - lhs = scc_malloc(sizeof(scc_ast_expr_t)); + lhs = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(lhs != nullptr); scc_ast_expr_member_init(lhs, ptr, scc_str_as_cstr(&tok.lexeme), tok.loc); @@ -230,7 +231,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) { SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ']'"); } - lhs = scc_malloc(sizeof(scc_ast_expr_t)); + lhs = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(lhs != nullptr); scc_ast_expr_array_subscript_init(lhs, ptr, idx, tok_ptr->loc); if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { @@ -266,7 +267,7 @@ scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { scc_ast_decl_vec_t decl_list_vec; scc_vec_init(decl_list_vec); - scc_ast_type_t *type = scc_parse_declaration_specifiers(parser); + scc_ast_qual_type_t *type = scc_parse_declaration_specifiers(parser); if (type == nullptr) { return nullptr; } @@ -284,16 +285,17 @@ CONTINUE: if (tok_ptr->type == SCC_TOK_ASSIGN) { scc_parser_next_consume(parser, nullptr); // TODO maybe memory leak - scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *lvalue = SCC_AST_ALLOC_EXPR(parser->ast_ctx); scc_ast_expr_lvalue_init(lvalue, decl->var.type, decl->base.loc); decl->var.init = scc_parse_initializer(parser, lvalue); } else if (tok_ptr->type == SCC_TOK_L_BRACE) { scc_parse_decl_sema(parser, decl); parser->sema_callbacks.on_decl(parser->sema_callbacks.context, scc_ast_decl_t_BEGIN, nullptr); - scc_vec_foreach(decl->func.type->function.params, i) { + // FIXME hack struct + scc_vec_foreach(decl->func.type->type->function.params, i) { scc_ast_decl_t *param = - scc_vec_at(decl->func.type->function.params, i); + scc_vec_at(decl->func.type->type->function.params, i); // Add params to decl scc_parse_decl_sema(parser, param); } @@ -342,7 +344,7 @@ CONTINUE: } else if (tok_ptr->type == SCC_TOK_COMMA) { scc_parser_next_consume(parser, nullptr); if (decl_list == nullptr) { - decl_list = scc_malloc(sizeof(scc_ast_decl_t)); + decl_list = SCC_AST_ALLOC_DECL(parser->ast_ctx); Assert(decl_list != nullptr); scc_vec_push(decl_list_vec, decl); } else { diff --git a/libs/parser/src/parse_expr.c b/libs/parser/src/parse_expr.c index 945e0c0..dfe4a9a 100644 --- a/libs/parser/src/parse_expr.c +++ b/libs/parser/src/parse_expr.c @@ -106,6 +106,7 @@ A.2.1 Expressions */ #include +#include #include /** @@ -370,7 +371,7 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser, return nullptr; } - scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); // FIXME pos scc_ast_expr_binary_init(expr, op, left, right, left->base.loc); @@ -409,7 +410,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) { return nullptr; } - scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); scc_ast_expr_binary_init(expr, op, left, right, pos); left = expr; @@ -455,7 +456,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) { return nullptr; } - scc_ast_expr_t *cond = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *cond = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(cond != nullptr); scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr, pos); cond_expr = cond; @@ -466,7 +467,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) { // 类型转换表达式 (type-name) cast-expression static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); - scc_ast_type_t *type = nullptr; + scc_ast_qual_type_t *type = nullptr; if (tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN) { // 尝试解析类型名 scc_parser_store(parser); @@ -480,13 +481,13 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { scc_ast_expr_t *operand = parse_cast_expression(parser); if (!operand) { // FIXME postfix-expression - scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); // FIXME pos scc_ast_expr_lvalue_init(expr, type, type->base.loc); operand = scc_parse_initializer(parser, expr); return operand; } - scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); // FIXME pos scc_ast_expr_cast_init(expr, type, operand, type->base.loc); @@ -558,7 +559,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) { return nullptr; } - scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); scc_ast_expr_unary_init(expr, op, operand, pos); return expr; @@ -587,12 +588,12 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) { return nullptr; } - scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); if (next->type == SCC_TOK_L_PAREN) { scc_parser_store(parser); scc_parser_next(parser); - scc_ast_type_t *type_name = scc_parse_type_name(parser); + scc_ast_qual_type_t *type_name = scc_parse_type_name(parser); if (type_name == nullptr) { scc_parser_restore(parser); goto next; @@ -633,7 +634,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { scc_parser_store(parser); scc_parser_next(parser); - scc_ast_type_t *type = scc_parse_type_name(parser); + scc_ast_qual_type_t *type = scc_parse_type_name(parser); if (!type) { scc_parser_restore(parser); return nullptr; @@ -642,7 +643,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'"); } - scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); scc_ast_expr_lvalue_init(expr, type, pos); left = scc_parse_initializer(parser, expr); return left; @@ -671,7 +672,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { parser_sync(parser); return nullptr; } - scc_ast_expr_t *subscript = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *subscript = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(subscript != nullptr); scc_ast_expr_array_subscript_init(subscript, left, index, pos); left = subscript; @@ -708,7 +709,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { return nullptr; } } - scc_ast_expr_t *call = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *call = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(call != nullptr); scc_ast_expr_call_init(call, left, &args, pos); left = call; @@ -730,7 +731,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { } const char *name = scc_str_as_cstr(&ident_tok.lexeme); - scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *member = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(member != nullptr); if (op_tok.type == SCC_TOK_DOT) { scc_ast_expr_member_init(member, left, name, ident_tok.loc); @@ -749,7 +750,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { if (!scc_parser_next_consume(parser, &op_tok)) return left; scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false); - scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); scc_ast_expr_unary_init(expr, op, left, op_tok.loc); scc_lexer_tok_drop(&op_tok); @@ -784,7 +785,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { case SCC_TOK_IDENT: { if (!scc_parser_next_consume(parser, &tok)) return nullptr; - expr = scc_malloc(sizeof(scc_ast_expr_t)); + expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); scc_ast_expr_identifier_init(expr, scc_str_as_cstr(&tok.lexeme), tok.loc); @@ -793,7 +794,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { case SCC_TOK_INT_LITERAL: { if (!scc_parser_next_consume(parser, &tok)) return nullptr; - expr = scc_malloc(sizeof(scc_ast_expr_t)); + expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); scc_ast_expr_literal_int_init(expr, scc_str_as_cstr(&tok.lexeme), false, tok.loc); @@ -802,7 +803,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { case SCC_TOK_FLOAT_LITERAL: { if (!scc_parser_next_consume(parser, &tok)) return nullptr; - expr = scc_malloc(sizeof(scc_ast_expr_t)); + expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); scc_ast_expr_literal_float_init(expr, scc_str_as_cstr(&tok.lexeme), false, tok.loc); @@ -811,7 +812,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { case SCC_TOK_CHAR_LITERAL: { if (!scc_parser_next_consume(parser, &tok)) return nullptr; - expr = scc_malloc(sizeof(scc_ast_expr_t)); + expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); scc_ast_expr_literal_char_init(expr, scc_str_as_cstr(&tok.lexeme), false, tok.loc); @@ -834,7 +835,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { scc_str_append(&string, &tmp); } - expr = scc_malloc(sizeof(scc_ast_expr_t)); + expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); // FIXME loc scc_ast_expr_literal_string_init(expr, scc_str_as_cstr(&string), true, @@ -879,7 +880,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) { parser_sync(parser); return nullptr; } - scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); + scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx); Assert(expr != nullptr); scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right, pos); left = expr; diff --git a/libs/parser/src/parse_stmt.c b/libs/parser/src/parse_stmt.c index fe2625c..61bfa6d 100644 --- a/libs/parser/src/parse_stmt.c +++ b/libs/parser/src/parse_stmt.c @@ -48,16 +48,9 @@ A.2.3 Statements */ #include +#include #include -static inline scc_ast_stmt_t *ast_stmt_alloc() { - scc_ast_stmt_t *stmt = (scc_ast_stmt_t *)scc_malloc(sizeof(scc_ast_stmt_t)); - if (stmt == nullptr) { - LOG_FATAL("Out of memory"); - } - return stmt; -} - static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) { if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) { SCC_ERROR(scc_parser_got_current_pos(parser), @@ -90,7 +83,7 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser, Panic("expect stmt"); } - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); Assert(stmt != nullptr); scc_ast_stmt_label_init(stmt, scc_str_as_cstr(&tok.lexeme), statement, pos); return stmt; @@ -121,7 +114,7 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser, Panic("expect stmt"); } - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_case_init(stmt, expr, statement, pos); return stmt; } @@ -143,7 +136,7 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser, Panic("expect stmt"); } - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_default_init(stmt, statement, pos); return stmt; } @@ -177,7 +170,7 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser, parser->sema_callbacks.on_stmt(parser->sema_callbacks.context, scc_ast_stmt_t_END, nullptr); - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_compound_init(stmt, &block_items, pos); return stmt; } @@ -197,7 +190,7 @@ static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) { opt_else = nullptr; } - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_if_init(stmt, expression, statement, opt_else, pos); return stmt; } @@ -211,7 +204,7 @@ static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser, scc_ast_expr_t *expression = ast_parse_paren_expression(parser); scc_ast_stmt_t *statement = scc_parse_statement(parser); - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_switch_init(stmt, expression, statement, pos); return stmt; } @@ -225,7 +218,7 @@ static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser, scc_ast_expr_t *expression = ast_parse_paren_expression(parser); scc_ast_stmt_t *statement = scc_parse_statement(parser); - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_while_init(stmt, expression, statement, pos); return stmt; } @@ -242,7 +235,6 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser, SCC_ERROR(scc_parser_got_current_pos(parser), "Expected 'while' after do."); // TODO 使用更好的错误处理,未来应当采用更好的内存管理器 - scc_free(statement); return nullptr; } scc_ast_expr_t *expression = ast_parse_paren_expression(parser); @@ -251,7 +243,7 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser, SCC_ERROR(scc_parser_got_current_pos(parser), "Expected semicolon after jump statement."); } - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_do_while_init(stmt, expression, statement, pos); return stmt; } @@ -303,14 +295,14 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser, body = scc_parse_statement(parser); - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_for_init(stmt, init, cond, incr, body, pos); return stmt; } static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser, scc_pos_t pos) { - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) { scc_lexer_tok_t tok = {0}; @@ -341,7 +333,7 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser, scc_pos_t pos) { if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_expr_init(stmt, nullptr, pos); return stmt; } @@ -351,7 +343,7 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser, return nullptr; } - scc_ast_stmt_t *stmt = ast_stmt_alloc(); + scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx); scc_ast_stmt_expr_init(stmt, expr, pos); if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { diff --git a/libs/parser/src/parse_type.c b/libs/parser/src/parse_type.c index fc34254..a70aba7 100644 --- a/libs/parser/src/parse_type.c +++ b/libs/parser/src/parse_type.c @@ -157,31 +157,24 @@ EXAMPLE The constructions */ #include +#include #include -static scc_ast_type_t *parse_declarator(scc_parser_t *parser, - scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr, - scc_lexer_tok_t *tok_ident); -static scc_ast_type_t * -parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr, +static scc_ast_qual_type_t * +parse_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base, + scc_ast_qual_type_t **delay_pointee_ptr, + scc_lexer_tok_t *tok_ident); +static scc_ast_qual_type_t * +parse_direct_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base, + scc_ast_qual_type_t **delay_pointee_ptr, scc_lexer_tok_t *tok_ident); -static scc_ast_type_t * -parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr); -static scc_ast_type_t * -parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr); - -static inline scc_ast_type_t *ast_type_alloc() { - scc_ast_type_t *ast_type = scc_malloc(sizeof(scc_ast_type_t)); - ast_type->base.type = SCC_AST_UNKNOWN; - if (ast_type == nullptr) { - LOG_FATAL("Out of memory"); - } - return ast_type; -} +static scc_ast_qual_type_t * +parse_abstract_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base, + scc_ast_qual_type_t **delay_pointee_ptr); +static scc_ast_qual_type_t * +parse_direct_abstract_declarator(scc_parser_t *parser, + scc_ast_qual_type_t *base, + scc_ast_qual_type_t **delay_pointee_ptr); /** * @brief 判断 token 是否为声明说明符的开始 @@ -306,6 +299,7 @@ cbool scc_parse_is_storage_class_start(scc_parser_t *parser) { goto duplicate_error; \ expr = true; \ } while (0) + static scc_ast_decl_specifier_t parse_type_qualifier_list(scc_parser_t *parser, scc_ast_decl_specifier_t quals) { @@ -407,7 +401,7 @@ typedef struct { cbool is_unsigned; // 显式 unsigned // 以下用于 struct/union/enum/typedef-name - scc_ast_type_t *user_type; // 如果是用户定义类型,直接存储解析结果 + scc_ast_qual_type_t *user_type; // 如果是用户定义类型,直接存储解析结果 } type_spec_info_t; static cbool check_type_combinations(scc_parser_t *parser, @@ -467,8 +461,9 @@ static cbool check_type_combinations(scc_parser_t *parser, } return true; } -static scc_ast_type_t *build_type_from_info(type_spec_info_t *info, - scc_pos_t pos) { +static scc_ast_qual_type_t *build_type_from_info(scc_parser_t *parser, + type_spec_info_t *info, + scc_pos_t pos) { // 如果有用户定义类型,直接返回(注意可能需要复制或共享) if (info->user_type) { return info->user_type; // 假设 parse_struct_union_enum 已分配好节点 @@ -531,13 +526,86 @@ static scc_ast_type_t *build_type_from_info(type_spec_info_t *info, } } - scc_ast_type_t *type = ast_type_alloc(); - scc_ast_type_builtin_init(type, builtin, pos); - // 注意:限定符(const, volatile)不应在此处处理,应由上层函数负责 + scc_ast_ctx_get_builtin_type(parser->ast_ctx, builtin); + scc_ast_qual_type_t *type = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx); + scc_ast_type_builtin_init(type, parser->ast_ctx, builtin, pos); return type; } -static scc_ast_type_t *parse_record_type(scc_parser_t *parser, - scc_ast_node_kind_t type_kind) { + +static scc_ast_qual_type_t *parse_record_type(scc_parser_t *parser, + scc_pos_t *pos, + scc_ast_node_kind_t type_kind) { + scc_lexer_tok_t tok; + // skip 'struct' or 'union' or 'enum' + scc_parser_next_consume(parser, &tok); + *pos = tok.loc; + scc_lexer_tok_drop(&tok); + + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + if (tok_ptr == nullptr) { + SCC_ERROR(scc_parser_got_current_pos(parser), "Unexpected EOF"); + return nullptr; + } + const char *name = nullptr; + + if (tok_ptr->type == SCC_TOK_IDENT) { + scc_parser_next_consume(parser, &tok); + tok_ptr = scc_parser_peek(parser); + name = scc_str_as_cstr(&tok.lexeme); + } else if (tok_ptr->type != SCC_TOK_L_BRACE) { + SCC_ERROR(scc_parser_got_current_pos(parser), + "Expected name in struct/union/enum specifier"); + return nullptr; + } + + scc_str_t symbol_name; + switch (type_kind) { + case SCC_AST_TYPE_ENUM: + symbol_name = scc_str_from_cstr("$E_"); + break; + case SCC_AST_TYPE_STRUCT: + symbol_name = scc_str_from_cstr("$S_"); + break; + case SCC_AST_TYPE_UNION: + symbol_name = scc_str_from_cstr("$U_"); + break; + default: + UNREACHABLE(); + break; + } + const scc_ast_qual_type_t *type = nullptr; + if (name == nullptr) { + scc_ast_canon_type_t *canon = scc_ast_ctx_alloc_type(parser->ast_ctx); + scc_ast_decl_t *decl = SCC_AST_ALLOC_DECL(parser->ast_ctx); + _scc_ast_decl_record_init(decl, type_kind, name, nullptr, *pos); + + const scc_ast_qual_type_t *type = + SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx); + _scc_ast_type_record_init(type, canon, type_kind, name, decl, *pos); + return type; + } + scc_str_append_cstr(&symbol_name, name, scc_strlen(name)); + + type = scc_parse_got_type(parser, scc_str_as_cstr(&symbol_name)); + if (type == nullptr) { + scc_ast_canon_type_t *canon = scc_ast_ctx_alloc_type(parser->ast_ctx); + scc_ast_decl_t *decl = SCC_AST_ALLOC_DECL(parser->ast_ctx); + _scc_ast_decl_record_init(decl, type_kind, name, nullptr, *pos); + + const scc_ast_qual_type_t *qual_type = + SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx); + _scc_ast_type_record_init(qual_type, canon, type_kind, name, decl, + *pos); + scc_parse_type_sema(parser, qual_type); + type = scc_parse_got_type(parser, scc_str_as_cstr(&symbol_name)); + Assert(type == qual_type); + } + Assert(type != nullptr); + return type; +} + +static scc_ast_qual_type_t * +parse_struct_union_type(scc_parser_t *parser, scc_ast_node_kind_t type_kind) { /* (6.7.2.1) struct-or-union-specifier: @@ -568,27 +636,15 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, declarator(opt) : constant-expression */ // FIXME check struct/union - scc_lexer_tok_t tok; - scc_parser_next_consume(parser, &tok); - scc_pos_t pos = tok.loc; - scc_lexer_tok_drop(&tok); + scc_lexer_tok_t tok = {0}; + scc_pos_t pos = scc_pos_create(); + + scc_ast_qual_type_t *type = parse_record_type(parser, &pos, type_kind); + Assert(type != nullptr); + scc_ast_decl_t *decl = type->type->record.decl; + Assert(decl != nullptr); const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); - if (tok_ptr == nullptr) { - SCC_ERROR(scc_parser_got_current_pos(parser), "Unexpected EOF"); - return nullptr; - } - const char *name = nullptr; - scc_ast_decl_t *decl = nullptr; - scc_ast_decl_vec_t member; - scc_vec_init(member); - - if (tok_ptr->type == SCC_TOK_IDENT) { - scc_parser_next_consume(parser, &tok); - name = scc_str_as_cstr(&tok.lexeme); - tok_ptr = scc_parser_peek(parser); - } - if (tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE) { scc_parser_next_consume(parser, nullptr); while (1) { @@ -599,11 +655,13 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, break; } - scc_ast_type_t *type = scc_parse_declaration_specifiers(parser); - if (type != nullptr) { - decl = scc_parse_declarator(parser, type); - if (decl != nullptr) { - scc_vec_push(member, decl); + scc_ast_qual_type_t *new_type = + scc_parse_declaration_specifiers(parser); + if (new_type != nullptr) { + scc_ast_decl_t *new_decl = + scc_parse_declarator(parser, new_type); + if (new_decl != nullptr) { + scc_vec_push(decl->record.fields, new_decl); continue; } } @@ -621,30 +679,12 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, break; } } - - decl = scc_malloc(sizeof(scc_ast_decl_t)); - Assert(decl != nullptr); - if (type_kind == SCC_AST_TYPE_STRUCT) { - scc_ast_decl_struct_init(decl, name, &member, pos); - } else { - scc_ast_decl_union_init(decl, name, &member, pos); - } - scc_parse_decl_sema(parser, decl); - } else { - if (name == nullptr) { - SCC_ERROR(scc_parser_got_current_pos(parser), - "Expected name in struct/union specifier"); - // FIXME memory leak - return nullptr; - } } - scc_ast_type_t *type = ast_type_alloc(); - _scc_ast_type_record_init(type, type_kind, name, decl, pos); return type; } -static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { +static scc_ast_qual_type_t *parse_enum_type(scc_parser_t *parser) { /* (6.7.2.2) enum-specifier: @@ -661,31 +701,15 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { enumeration-constant = constant-expression */ scc_lexer_tok_t tok; - scc_parser_next_consume(parser, &tok); - scc_pos_t pos = tok.loc; - if (tok.type != SCC_TOK_ENUM) { - SCC_ERROR(scc_parser_got_current_pos(parser), "Expected 'enum'"); - return nullptr; - } - scc_lexer_tok_drop(&tok); + scc_pos_t pos = scc_pos_create(); + + scc_ast_qual_type_t *type = + parse_record_type(parser, &pos, SCC_AST_TYPE_ENUM); + Assert(type != nullptr); + scc_ast_decl_t *decl = type->type->record.decl; + Assert(decl != nullptr); const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); - if (tok_ptr == nullptr) { - SCC_ERROR(scc_parser_got_current_pos(parser), "Unexpected EOF"); - return nullptr; - } - scc_ast_type_t *type = ast_type_alloc(); - const char *name = nullptr; - scc_ast_decl_t *decl = nullptr; - scc_ast_decl_vec_t member; - scc_vec_init(member); - - if (tok_ptr->type == SCC_TOK_IDENT) { - scc_parser_next_consume(parser, &tok); - tok_ptr = scc_parser_peek(parser); - name = scc_str_as_cstr(&tok.lexeme); - } - if (tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE) { scc_parser_next_consume(parser, nullptr); while (1) { @@ -708,12 +732,13 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { enum_item_init = scc_parser_constant_expression(parser); } - scc_ast_decl_t *enum_item_decl = scc_malloc(sizeof(scc_ast_decl_t)); + scc_ast_decl_t *enum_item_decl = + SCC_AST_ALLOC_DECL(parser->ast_ctx); Assert(enum_item_decl != nullptr); scc_ast_decl_val_init(enum_item_decl, type, scc_str_as_cstr(&tok.lexeme), enum_item_init, tok.loc); - scc_vec_push(member, enum_item_decl); + scc_vec_push(decl->record.fields, enum_item_decl); tok_ptr = scc_parser_peek(parser); @@ -738,24 +763,17 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { break; } } - decl = scc_malloc(sizeof(scc_ast_decl_t)); - Assert(decl != nullptr); - scc_ast_decl_enum_init(decl, name, &member, pos); - scc_parse_decl_sema(parser, decl); - } else { - if (name == nullptr) { - SCC_ERROR(scc_parser_got_current_pos(parser), - "Expected name in enum specifier"); - // FIXME memory leak - return nullptr; - } } - scc_ast_type_enum_init(type, name, decl, pos); + scc_vec_foreach(decl->record.fields, i) { + scc_ast_decl_t *enum_decl = scc_vec_at(decl->record.fields, i); + scc_parse_decl_sema(parser, enum_decl); + } + return type; } -static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) { +static scc_ast_qual_type_t *parse_type_specifier(scc_parser_t *parser) { type_spec_info_t info = {0}; if (!scc_parse_is_type_specifier_start(parser)) return nullptr; @@ -769,7 +787,7 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) { switch (tok_ptr->type) { case SCC_TOK_STRUCT: case SCC_TOK_UNION: - info.user_type = parse_record_type( + info.user_type = parse_struct_union_type( parser, tok_ptr->type == SCC_TOK_STRUCT ? SCC_AST_TYPE_STRUCT : SCC_AST_TYPE_UNION); goto done; @@ -886,15 +904,15 @@ done: if (!check_type_combinations(parser, &info)) { return nullptr; } - return build_type_from_info(&info, pos); + return build_type_from_info(parser, &info, pos); duplicate_error: SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier"); return nullptr; } -static scc_ast_type_t *parse_pointer(scc_parser_t *parser, - scc_ast_type_t *pointee, - scc_ast_type_t **delay_pointee_ptr) { +static scc_ast_qual_type_t * +parse_pointer(scc_parser_t *parser, scc_ast_qual_type_t *pointee, + scc_ast_qual_type_t **delay_pointee_ptr) { /* pointer: * type-qualifier-list(opt) @@ -907,13 +925,15 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser, scc_pos_t pos = tok_ptr->loc; scc_parser_next_consume(parser, nullptr); - scc_ast_type_t *pointer = ast_type_alloc(); + scc_ast_qual_type_t *pointer = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx); if (pointee == nullptr) { Assert(delay_pointee_ptr != nullptr); *delay_pointee_ptr = pointer; pointee = pointer; } - scc_ast_type_pointer_init(pointer, pointee, pos); + + scc_ast_canon_type_t *canon = scc_ast_ctx_alloc_type(parser->ast_ctx); + scc_ast_type_pointer_init(pointer, canon, pointee, pos); pointer->quals = parse_type_qualifier_list(parser, pointer->quals); return parse_pointer(parser, pointer, delay_pointee_ptr); @@ -937,7 +957,7 @@ static void parse_parameter_type_list(scc_parser_t *parser, const scc_lexer_tok_t *tok_ptr = nullptr; while (1) { // FIXME - scc_ast_type_t *type = scc_parse_declaration_specifiers(parser); + scc_ast_qual_type_t *type = scc_parse_declaration_specifiers(parser); if (type == nullptr) { break; } @@ -947,7 +967,7 @@ static void parse_parameter_type_list(scc_parser_t *parser, } // TODO Check validation - param = scc_malloc(sizeof(scc_ast_decl_t)); + param = SCC_AST_ALLOC_DECL(parser->ast_ctx); Assert(param != nullptr); scc_ast_decl_param_init(param, decl->var.type, decl->name, scc_vec_size(*params), decl->base.loc); @@ -964,12 +984,12 @@ static void parse_parameter_type_list(scc_parser_t *parser, scc_parser_next_consume(parser, nullptr); tok_ptr = scc_parser_peek(parser); if (tok_ptr->type == SCC_TOK_ELLIPSIS) { - param = scc_malloc(sizeof(scc_ast_decl_t)); + param = SCC_AST_ALLOC_DECL(parser->ast_ctx); Assert(param != nullptr); // FIXME - type = scc_malloc(sizeof(scc_ast_type_t)); - Assert(type != nullptr); - scc_ast_type_builtin_init(type, SCC_AST_BUILTIN_TYPE_VA_LIST, + type = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx); + scc_ast_type_builtin_init(type, parser->ast_ctx, + SCC_AST_BUILTIN_TYPE_VA_LIST, tok_ptr->loc); scc_ast_decl_param_init(param, type, nullptr, scc_vec_size(*params), tok_ptr->loc); @@ -1048,10 +1068,10 @@ static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) { return size; } -static scc_ast_type_t *parse_declarator(scc_parser_t *parser, - scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr, - scc_lexer_tok_t *tok_ident) { +static scc_ast_qual_type_t * +parse_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base, + scc_ast_qual_type_t **delay_pointee_ptr, + scc_lexer_tok_t *tok_ident) { /* (6.7.5) declarator: pointer(opt) direct-declarator @@ -1068,16 +1088,17 @@ static scc_ast_type_t *parse_declarator(scc_parser_t *parser, direct-declarator ( parameter-type-list ) direct-declarator ( identifier-list(opt) ) */ - scc_ast_type_t *ret = parse_pointer(parser, base, delay_pointee_ptr); + scc_ast_qual_type_t *ret = parse_pointer(parser, base, delay_pointee_ptr); return parse_direct_declarator(parser, ret, delay_pointee_ptr, tok_ident); } -static scc_ast_type_t * -parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr, +static scc_ast_qual_type_t * +parse_direct_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base, + scc_ast_qual_type_t **delay_pointee_ptr, scc_lexer_tok_t *tok_ident) { const scc_lexer_tok_t *tok_ptr = nullptr; - scc_ast_type_t *ret = nullptr; + scc_ast_qual_type_t *ret = nullptr; + scc_ast_canon_type_t *canon = scc_ast_ctx_alloc_type(parser->ast_ctx); // direct-abstract-declarator tok_ptr = scc_parser_peek(parser); if (tok_ptr == nullptr) { @@ -1098,13 +1119,14 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, } else if (tok_ptr->type == SCC_TOK_L_PAREN) { // () SCC_TOK_L_PAREN scc_parser_next_consume(parser, nullptr); - scc_ast_type_t *delay_pointee = nullptr; + scc_ast_qual_type_t *delay_pointee = nullptr; if (parse_function_parameters_start(parser)) { scc_ast_decl_vec_t params; parse_function_parameters(parser, ¶ms); - ret = ast_type_alloc(); + ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx); // FIXME - scc_ast_type_function_init(ret, base, ¶ms, base->base.loc); + scc_ast_type_function_init(ret, canon, base, ¶ms, + base->base.loc); return parse_direct_declarator(parser, ret, delay_pointee_ptr, tok_ident); } else { @@ -1118,28 +1140,28 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, } base = parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident); - Assert(SCC_AST_IS_A(scc_ast_type_t, base)); + Assert(SCC_AST_IS_A(scc_ast_qual_type_t, base)); Assert(delay_pointee != nullptr); - delay_pointee->pointer.pointee = base; + scc_ast_mut_canon_type(delay_pointee)->pointer.pointee = base; return ret; } } else if (tok_ptr->type == SCC_TOK_L_BRACKET) { // [] SCC_TOK_L_BRACKET scc_ast_expr_t *size = parse_array_size_type(parser); - scc_ast_type_t *ret = ast_type_alloc(); + scc_ast_qual_type_t *ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx); base = parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident); // FIXME - scc_ast_type_array_init(ret, base, size, base->base.loc); + scc_ast_type_array_init(ret, canon, base, size, base->base.loc); return ret; } else { return base; } } -static scc_ast_type_t * -parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr) { +static scc_ast_qual_type_t * +parse_abstract_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base, + scc_ast_qual_type_t **delay_pointee_ptr) { /* (6.7.6) abstract-declarator: pointer @@ -1155,16 +1177,18 @@ parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, direct-abstract-declarator(opt) [ * ] direct-abstract-declarator(opt) ( parameter-type-list(opt) ) */ - scc_ast_type_t *ret = parse_pointer(parser, base, delay_pointee_ptr); + scc_ast_qual_type_t *ret = parse_pointer(parser, base, delay_pointee_ptr); ret = parse_direct_abstract_declarator(parser, ret, delay_pointee_ptr); return ret; } -static scc_ast_type_t * -parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, - scc_ast_type_t **delay_pointee_ptr) { +static scc_ast_qual_type_t * +parse_direct_abstract_declarator(scc_parser_t *parser, + scc_ast_qual_type_t *base, + scc_ast_qual_type_t **delay_pointee_ptr) { const scc_lexer_tok_t *tok_ptr = nullptr; - scc_ast_type_t *ret = nullptr; + scc_ast_qual_type_t *ret = nullptr; + scc_ast_canon_type_t *canon = scc_ast_ctx_alloc_type(parser->ast_ctx); // direct-abstract-declarator tok_ptr = scc_parser_peek(parser); if (tok_ptr == nullptr) { @@ -1174,13 +1198,14 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, if (tok_ptr->type == SCC_TOK_L_PAREN) { // () SCC_TOK_L_PAREN scc_parser_next_consume(parser, nullptr); - scc_ast_type_t *delay_pointee = nullptr; + scc_ast_qual_type_t *delay_pointee = nullptr; if (parse_function_parameters_start(parser)) { scc_ast_decl_vec_t params; parse_function_parameters(parser, ¶ms); - ret = ast_type_alloc(); + ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx); // FIXME - scc_ast_type_function_init(ret, base, ¶ms, base->base.loc); + scc_ast_type_function_init(ret, canon, base, ¶ms, + base->base.loc); return parse_direct_abstract_declarator(parser, ret, delay_pointee_ptr); } else { @@ -1192,17 +1217,17 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, base = parse_direct_abstract_declarator(parser, base, delay_pointee_ptr); Assert(delay_pointee != nullptr); - delay_pointee->pointer.pointee = base; + scc_ast_mut_canon_type(delay_pointee)->pointer.pointee = base; } return ret; } else if (tok_ptr->type == SCC_TOK_L_BRACKET) { // [] SCC_TOK_L_BRACKET scc_ast_expr_t *size = parse_array_size_type(parser); - scc_ast_type_t *ret = ast_type_alloc(); + scc_ast_qual_type_t *ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx); base = parse_direct_abstract_declarator(parser, base, delay_pointee_ptr); // FIXME - scc_ast_type_array_init(ret, base, size, base->base.loc); + scc_ast_type_array_init(ret, canon, base, size, base->base.loc); return ret; } else { return base; @@ -1210,12 +1235,12 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, } scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser, - scc_ast_type_t *type) { + scc_ast_qual_type_t *type) { scc_lexer_tok_t decl_name_tok = {0}; - scc_ast_type_t *decl_type = + scc_ast_qual_type_t *decl_type = parse_declarator(parser, type, nullptr, &decl_name_tok); scc_ast_decl_t *decl = nullptr; - decl = scc_malloc(sizeof(scc_ast_decl_t)); + decl = SCC_AST_ALLOC_DECL(parser->ast_ctx); Assert(decl != nullptr); Assert(decl_name_tok.type == SCC_TOK_IDENT || decl_name_tok.type == SCC_TOK_UNKNOWN); @@ -1240,36 +1265,39 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser, } if (decl_name_tok.type != SCC_TOK_IDENT) { - if (decl_type->base.type == SCC_AST_TYPE_STRUCT || - decl_type->base.type == SCC_AST_TYPE_UNION || - decl_type->base.type == SCC_AST_TYPE_ENUM) { - if (decl_type->record.decl == nullptr) { - decl = scc_malloc(sizeof(scc_ast_decl_t)); - Assert(decl != nullptr); - if (decl_type->base.type == SCC_AST_TYPE_STRUCT) { - scc_ast_decl_struct_init(decl, decl_type->record.name, - nullptr, decl_type->base.loc); - } else if (decl_type->base.type == SCC_AST_TYPE_UNION) { - scc_ast_decl_union_init(decl, decl_type->record.name, - nullptr, decl_type->base.loc); - } else { - scc_ast_decl_enum_init(decl, type->record.name, nullptr, - decl_type->base.loc); - } - } else { - decl = decl_type->record.decl; - scc_free(decl_type); // FIXME - } - } else { - decl = scc_malloc(sizeof(scc_ast_decl_t)); - scc_ast_decl_unsafe_val_init(decl, type, nullptr, nullptr, - decl_type->base.loc); - } + // TODO(); + // if (decl_type->base.type == SCC_AST_TYPE_STRUCT || + // decl_type->base.type == SCC_AST_TYPE_UNION || + // decl_type->base.type == SCC_AST_TYPE_ENUM) { + // if (scc_ast_canon_type(decl_type)->record.decl == nullptr) { + // decl = SCC_AST_ALLOC_DECL(parser->ast_ctx); + // Assert(decl != nullptr); + // if (decl_type->base.type == SCC_AST_TYPE_STRUCT) { + // scc_ast_decl_struct_init( + // decl, scc_ast_canon_type(decl_type)->record.name, + // nullptr, decl_type->base.loc); + // } else if (decl_type->base.type == SCC_AST_TYPE_UNION) { + // scc_ast_decl_union_init( + // decl, scc_ast_canon_type(decl_type)->record.name, + // nullptr, decl_type->base.loc); + // } else { + // scc_ast_decl_enum_init( + // decl, scc_ast_canon_type(decl_type)->record.name, + // nullptr, decl_type->base.loc); + // } + // } else { + // decl = scc_ast_canon_type(decl_type)->record.decl; + // } + // } else { + // decl = SCC_AST_ALLOC_DECL(parser->ast_ctx); + // scc_ast_decl_unsafe_val_init(decl, type, nullptr, nullptr, + // decl_type->base.loc); + // } } return decl; } -scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) { +scc_ast_qual_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) { if (!scc_parse_is_decl_specifier_start(parser)) { return nullptr; } @@ -1280,7 +1308,7 @@ scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) { } spec = parse_declaration_specifiers_list(parser, spec); - scc_ast_type_t *specifier = parse_type_specifier(parser); + scc_ast_qual_type_t *specifier = parse_type_specifier(parser); if (specifier == nullptr) { SCC_ERROR(scc_parser_got_current_pos(parser), "declaration specifier can't have type specifier"); @@ -1291,13 +1319,13 @@ scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) { return specifier; } -scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) { +scc_ast_qual_type_t *scc_parse_type_name(scc_parser_t *parser) { if (!(scc_parse_is_type_specifier_start(parser) || scc_parse_is_type_qualifier_start(parser))) { return nullptr; } - scc_ast_type_t *ret = nullptr; + scc_ast_qual_type_t *ret = nullptr; scc_ast_decl_specifier_t spec = {0}; spec = parse_type_qualifier_list(parser, spec); ret = parse_type_specifier(parser); diff --git a/libs/parser/src/scc_parser.c b/libs/parser/src/scc_parser.c index ea5e6eb..17e026e 100644 --- a/libs/parser/src/scc_parser.c +++ b/libs/parser/src/scc_parser.c @@ -9,8 +9,8 @@ static void dummy_sema_callback(void *context, scc_ast_node_kind_t node_type, return; } -static scc_ast_type_t *dummy_got_type_callback(void *context, - const char *name) { +static const scc_ast_qual_type_t *dummy_got_type_callback(void *context, + const char *name) { (void)context; (void)name; return nullptr; @@ -20,8 +20,11 @@ static scc_ast_type_t *dummy_got_type_callback(void *context, assigned_val = value ? value : default void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring, - scc_sema_callbacks_t *callbacks) { + scc_ast_ctx_t *ast_ctx, scc_sema_ctx_t *callbacks) { Assert(parser != nullptr && tok_ring != nullptr); + Assert(ast_ctx != nullptr); + parser->ast_ctx = ast_ctx; + parser->ring = tok_ring; parser->errcode = 0; parser->translation_unit = nullptr; diff --git a/libs/parser/src/scc_sema.c b/libs/parser/src/scc_sema.c index 214bd74..c3e6714 100644 --- a/libs/parser/src/scc_sema.c +++ b/libs/parser/src/scc_sema.c @@ -1,13 +1,59 @@ +#include #include #include #include +static const scc_ast_qual_type_t *got_type_callback(void *context, + const char *name); + +static void gen_symbol_name(const scc_ast_decl_t *decl, scc_str_t *name) { + switch (decl->base.type) { + case SCC_AST_TYPE_ENUM: + *name = scc_str_from_cstr("$E_"); + scc_str_append_cstr(name, decl->name, scc_strlen(decl->name)); + break; + case SCC_AST_TYPE_STRUCT: + *name = scc_str_from_cstr("$S_"); + scc_str_append_cstr(name, decl->name, scc_strlen(decl->name)); + break; + case SCC_AST_TYPE_UNION: + *name = scc_str_from_cstr("$U_"); + scc_str_append_cstr(name, decl->name, scc_strlen(decl->name)); + break; + default: + break; + } +} + +static void symtab_add_symbol(scc_sema_symtab_t *sema_symtab, + scc_ast_decl_t *decl, + scc_ast_node_t *ast_node_ref) { + + if (decl->name == nullptr) + return; + // FIXME memory leak + scc_str_t name = scc_str_empty(); + gen_symbol_name(decl, &name); + if (scc_str_is_empty(&name)) { + scc_sema_symtab_add_symbol(sema_symtab, decl->name, ast_node_ref); + } else { + scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name), + ast_node_ref); + } +} + static void type_callback(void *context, scc_ast_node_kind_t node_type, void *node) { scc_sema_symtab_t *sema_symtab = context; - (void)context; - (void)node_type; - (void)node; + scc_ast_qual_type_t *type = SCC_AST_CAST_TO(scc_ast_qual_type_t, node); + + if (node_type == SCC_AST_TYPE_STRUCT) { + symtab_add_symbol(sema_symtab, type->type->record.decl, &type->base); + } else if (node_type == SCC_AST_TYPE_UNION) { + symtab_add_symbol(sema_symtab, type->type->record.decl, &type->base); + } else if (node_type == SCC_AST_TYPE_ENUM) { + symtab_add_symbol(sema_symtab, type->type->record.decl, &type->base); + } return; } @@ -71,119 +117,83 @@ static void decl_callback(void *context, scc_ast_node_kind_t node_type, } scc_ast_decl_t *decl = SCC_AST_CAST_TO(scc_ast_decl_t, node); - scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t)); - Assert(type != nullptr); - - if (node_type == SCC_AST_DECL_STRUCT) { - scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc); - // FIXME memory leak - scc_str_t name = scc_str_from_cstr("$S_"); - - if (decl->name == nullptr) { - decl->name = ""; - } - scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name)); - scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name), - &type->base); - } else if (node_type == SCC_AST_DECL_UNION) { - scc_ast_type_union_init(type, decl->name, decl, decl->base.loc); - scc_str_t name = scc_str_from_cstr("$U_"); - if (decl->name == nullptr) { - decl->name = ""; - } - scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name)); - scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name), - &type->base); - } else if (node_type == SCC_AST_DECL_ENUM) { - scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc); - scc_str_t name = scc_str_from_cstr("$E_"); - if (decl->name == nullptr) { - decl->name = ""; - } - scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name)); - scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name), - &type->base); - - scc_vec_foreach(decl->record.fields, i) { - scc_ast_decl_t *enum_decl = scc_vec_at(decl->record.fields, i); - scc_sema_symtab_add_symbol(sema_symtab, enum_decl->name, - &enum_decl->base); - // LOG_INFO("enum added %s", enum_decl->name); - } - } else if (node_type == SCC_AST_DECL_TYPEDEF) { + if (node_type == SCC_AST_DECL_TYPEDEF) { if (decl->name == nullptr) { SCC_ERROR(decl->base.loc, "typedef without name"); return; } - scc_ast_type_typedef_init(type, decl->name, decl, decl->base.loc); - scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); + symtab_add_symbol(sema_symtab, decl, &decl->typedef_decl.type->base); } else if (node_type == SCC_AST_DECL_VAR) { - scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base); + symtab_add_symbol(sema_symtab, decl, &decl->base); } else if (node_type == SCC_AST_DECL_PARAM) { if (decl->name == nullptr) { if (decl->param.type->base.type == SCC_AST_TYPE_BUILTIN && - (decl->param.type->builtin.type == + (decl->param.type->type->builtin.type == SCC_AST_BUILTIN_TYPE_VA_LIST || - decl->param.type->builtin.type == SCC_AST_BUILTIN_TYPE_VOID)) { + decl->param.type->type->builtin.type == + SCC_AST_BUILTIN_TYPE_VOID)) { return; } SCC_ERROR(decl->base.loc, "sema error: Parameter must have a name"); return; } - scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base); + symtab_add_symbol(sema_symtab, decl, &decl->base); } else if (node_type == SCC_AST_DECL_FUNC) { if (decl->name == nullptr) { SCC_ERROR(decl->base.loc, "sema error: Function must have a name"); } else { // FIXME 重名函数... - scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base); + symtab_add_symbol(sema_symtab, decl, &decl->base); } } return; } -static scc_ast_type_t *got_type_callback(void *context, const char *name) { +static const scc_ast_qual_type_t *got_type_callback(void *context, + const char *name) { scc_sema_symtab_t *sema_symtab = context; scc_ast_node_t *node = scc_sema_symtab_lookup_symbol(sema_symtab, name); - if (SCC_AST_IS_A(scc_ast_type_t, node)) { - scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t)); - *type = *(scc_ast_type_t *)node; - return type; + if (SCC_AST_IS_A(scc_ast_qual_type_t, node)) { + return (scc_ast_qual_type_t *)node; } return nullptr; } -void scc_sema_init(scc_sema_callbacks_t *callbacks) { +void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_ctx_t *ast_ctx) { + sema_ctx->ast_ctx = ast_ctx; scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t)); if (sema_symtab == nullptr) { LOG_FATAL("out of memory"); return; } - callbacks->context = sema_symtab; - callbacks->on_decl = decl_callback; - callbacks->on_expr = expr_callback; - callbacks->on_stmt = stmt_callback; - callbacks->on_type = type_callback; - callbacks->got_type = got_type_callback; + sema_ctx->context = sema_symtab; + sema_ctx->on_decl = decl_callback; + sema_ctx->on_expr = expr_callback; + sema_ctx->on_stmt = stmt_callback; + sema_ctx->on_type = type_callback; + sema_ctx->got_type = got_type_callback; scc_sema_symtab_init(sema_symtab); // FIXME memory leak - scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t)); - scc_ast_type_builtin_init(type, SCC_AST_BUILTIN_TYPE_VA_LIST, - scc_pos_create()); + + scc_ast_qual_type_t *type = SCC_AST_ALLOC_QUAL_TYPE(sema_ctx->ast_ctx); + scc_ast_type_builtin_init(type, sema_ctx->ast_ctx, + SCC_AST_BUILTIN_TYPE_VA_LIST, scc_pos_create()); scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_list", &type->base); - scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t)); + scc_ast_decl_t *decl = SCC_AST_ALLOC_DECL(sema_ctx->ast_ctx); scc_ast_decl_val_init(decl, type, "__scc_builtin__", nullptr, scc_pos_create()); scc_sema_symtab_add_symbol(sema_symtab, "__func__", &decl->base); - scc_ast_type_t *built_func_type = scc_malloc(sizeof(scc_ast_type_t)); - scc_ast_type_function_init(built_func_type, nullptr, nullptr, - scc_pos_create()); - scc_ast_decl_t *builin_func = scc_malloc(sizeof(scc_ast_decl_t)); + scc_ast_qual_type_t *built_func_type = + SCC_AST_ALLOC_QUAL_TYPE(sema_ctx->ast_ctx); + // FIXME hack + built_func_type->base.type = SCC_AST_TYPE_FUNCTION; + + scc_ast_decl_t *builin_func = SCC_AST_ALLOC_DECL(sema_ctx->ast_ctx); scc_ast_decl_func_init(builin_func, built_func_type, "__scc_builtin_func", nullptr, scc_pos_create()); scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_start", @@ -196,9 +206,9 @@ 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_ctx_t *sema_ctx) { // FIXME drop obj - if (callbacks->context) { - scc_sema_symtab_drop(callbacks->context); + if (sema_ctx->context) { + scc_sema_symtab_drop(sema_ctx->context); } } diff --git a/src/main.c b/src/main.c index 3c171d2..99e402d 100644 --- a/src/main.c +++ b/src/main.c @@ -184,9 +184,11 @@ int main(int argc, const char **argv, const char **envp) { scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pproc, 1024, false, false); scc_parser_t parser; - scc_sema_callbacks_t sema_callbacks; - scc_sema_init(&sema_callbacks); - scc_parser_init(&parser, tok_ring, &sema_callbacks); + scc_ast_ctx_t ast_ctx; + scc_ast_ctx_init(&ast_ctx); + scc_sema_ctx_t sema_callbacks; + scc_sema_init(&sema_callbacks, &ast_ctx); + scc_parser_init(&parser, tok_ring, &ast_ctx, &sema_callbacks); scc_ast_translation_unit_t *translation_unit = scc_parse_translation_unit(&parser); @@ -221,7 +223,7 @@ sstream_drop: scc_hir_cprog_t cprog; scc_hir_cprog_init(&cprog); scc_ast2ir_ctx_init(&ast2ir_ctx, &scc_ast_abi_impl, &cprog); - scc_ast2ir_translation_unit(&ast2ir_ctx, translation_unit); + scc_ast2ir_run(&ast2ir_ctx, translation_unit); scc_ast2ir_ctx_drop(&ast2ir_ctx); if (config.emit_hir) {