diff --git a/libs/README.md b/libs/README.md index 43e35e7..99a9345 100644 --- a/libs/README.md +++ b/libs/README.md @@ -15,6 +15,8 @@ ir 中间代码标识 opt 优化器 +asm 汇编器 + mcode 机器码 sccf 统一输出格式 diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index 7bd1748..8ac74f6 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -10,7 +10,7 @@ typedef enum { SCC_AST_UNKNOWN, // 声明 - scc_ast_decl_t_BEGIN, // 声明开始 + scc_ast_decl_t_BEGIN, // 声明开始 sema 函数作用域开始 SCC_AST_DECL_LIST, // 声明列表 SCC_AST_DECL_VAR, // 变量声明 SCC_AST_DECL_FUNC, // 函数声明 @@ -19,10 +19,10 @@ typedef enum { SCC_AST_DECL_UNION, // 联合声明 SCC_AST_DECL_ENUM, // 枚举声明 SCC_AST_DECL_TYPEDEF, // typedef 声明 - scc_ast_decl_t_END, // 声明结束 + scc_ast_decl_t_END, // 声明结束 sema 函数作用域结束 // 语句 - scc_ast_stmt_t_BEGIN, // 语句开始 + scc_ast_stmt_t_BEGIN, // 语句开始 sema 作用域开始 SCC_AST_STMT_COMPOUND, // 复合语句 { ... } SCC_AST_STMT_EXPR, // 表达式语句 SCC_AST_STMT_IF, // if 语句 @@ -37,7 +37,7 @@ typedef enum { SCC_AST_STMT_RETURN, // return 语句 SCC_AST_STMT_GOTO, // goto 语句 SCC_AST_STMT_LABEL, // 标签语句 - scc_ast_stmt_t_END, // 结束语句 + scc_ast_stmt_t_END, // 结束语句 sema 作用域结束 // 表达式 scc_ast_expr_t_BEGIN, // 表达式开始 @@ -180,7 +180,7 @@ struct scc_ast_type { } array; struct { scc_ast_type_t *return_type; - scc_ast_decl_vec_t param_types; // va_list <=> ... + scc_ast_decl_vec_t params; // va_list <=> ... } function; struct { const char *name; @@ -294,7 +294,6 @@ struct scc_ast_expr { struct { const char *name; scc_ast_expr_t *callee; - scc_ast_expr_t *_target; scc_ast_expr_vec_t args; } call; // 数组下标 @@ -306,7 +305,7 @@ struct scc_ast_expr { struct { scc_ast_expr_t *base; const char *name; - usize _target_idx; + usize _target_idx; ///< fill by sema } member; // cast 类型转换 struct { @@ -332,7 +331,7 @@ struct scc_ast_expr { // 标识符 struct { const char *name; - scc_ast_decl_t *_target; + scc_ast_decl_t *_target; ///< fill by sema } identifier; struct { scc_ast_type_t *type; @@ -393,6 +392,7 @@ struct scc_ast_stmt { } default_stmt; // break/continue struct { + scc_ast_stmt_t *_target; // fill by sema } jump; // return 语句 struct { diff --git a/libs/ast/include/scc_ast.h b/libs/ast/include/scc_ast.h index 9a1a03e..e188832 100644 --- a/libs/ast/include/scc_ast.h +++ b/libs/ast/include/scc_ast.h @@ -8,10 +8,10 @@ // decls can be null 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_ast_decl_vec_t *decls, scc_pos_t loc) { Assert(translation_unit != null); translation_unit->base.type = SCC_AST_TRANSLATION_UNIT; - translation_unit->base.loc = scc_pos_create(); + translation_unit->base.loc = loc; if (decls == null) { scc_vec_init(translation_unit->declarations); } else { @@ -21,9 +21,10 @@ scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit, } static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl, - scc_ast_decl_vec_t *list_move) { + scc_ast_decl_vec_t *list_move, + scc_pos_t loc) { Assert(decl != null && list_move != null); - decl->base.loc = scc_pos_create(); + decl->base.loc = loc; decl->base.type = SCC_AST_DECL_LIST; decl->name = null; decl->list.vars = *list_move; @@ -34,9 +35,10 @@ static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl, 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_ast_expr_t *var_init, + scc_pos_t loc) { Assert(decl != null && type != null); - decl->base.loc = scc_pos_create(); + decl->base.loc = loc; decl->base.type = SCC_AST_DECL_VAR; decl->name = name; decl->var.type = type; @@ -46,9 +48,10 @@ static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl, // var_init can be null 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_ast_expr_t *var_init, + scc_pos_t loc) { Assert(decl != null && name != null && type != null); - decl->base.loc = scc_pos_create(); + decl->base.loc = loc; decl->base.type = SCC_AST_DECL_VAR; decl->name = name; decl->var.type = type; @@ -59,9 +62,9 @@ static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl, 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_ast_stmt_t *body, scc_pos_t loc) { Assert(decl != null && name != null && type != null); - decl->base.loc = scc_pos_create(); + decl->base.loc = loc; decl->base.type = SCC_AST_DECL_FUNC; decl->name = name; decl->func.type = type; @@ -72,9 +75,9 @@ static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl, // name can be null static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl, scc_ast_type_t *type, - const char *name) { + const char *name, scc_pos_t loc) { Assert(decl != null && type != null); - decl->base.loc = scc_pos_create(); + decl->base.loc = loc; decl->base.type = SCC_AST_DECL_PARAM; decl->name = name; decl->param.type = type; @@ -83,9 +86,10 @@ static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl, // name and fields can be null static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl, const char *name, - scc_ast_decl_vec_t *fields_move) { + scc_ast_decl_vec_t *fields_move, + scc_pos_t loc) { Assert(decl != null); - decl->base.loc = scc_pos_create(); + decl->base.loc = loc; decl->base.type = SCC_AST_DECL_STRUCT; decl->name = name; if (fields_move == null) { @@ -99,9 +103,10 @@ static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl, // name and fields can be null static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl, const char *name, - scc_ast_decl_vec_t *fields_move) { + scc_ast_decl_vec_t *fields_move, + scc_pos_t loc) { Assert(decl != null); - decl->base.loc = scc_pos_create(); + decl->base.loc = loc; decl->base.type = SCC_AST_DECL_UNION; decl->name = name; if (fields_move == null) { @@ -115,9 +120,10 @@ static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl, // name and fields can be null static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl, const char *name, - scc_ast_expr_vec_t *fields_move) { + scc_ast_expr_vec_t *fields_move, + scc_pos_t loc) { Assert(decl != null); - decl->base.loc = scc_pos_create(); + decl->base.loc = loc; decl->base.type = SCC_AST_DECL_ENUM; decl->name = name; if (fields_move == null) { @@ -130,20 +136,20 @@ static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl, static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl, const char *name, - scc_ast_type_t *type) { + scc_ast_type_t *type, + scc_pos_t loc) { Assert(decl != null && name != null && type != null); - decl->base.loc = scc_pos_create(); + decl->base.loc = loc; decl->base.type = SCC_AST_DECL_TYPEDEF; decl->name = name; decl->typedef_decl.type = type; } // items can be null -static inline void -scc_ast_stmt_compound_init(scc_ast_stmt_t *stmt, - scc_ast_block_item_vec_t *items_move) { +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 != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_COMPOUND; if (items_move == null) { scc_vec_init(stmt->compound.block_items); @@ -155,9 +161,9 @@ scc_ast_stmt_compound_init(scc_ast_stmt_t *stmt, // expr can be null static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt, - scc_ast_expr_t *expr) { + scc_ast_expr_t *expr, scc_pos_t loc) { Assert(stmt != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_EXPR; stmt->expr.expr = expr; } @@ -166,9 +172,10 @@ static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt, 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_ast_stmt_t *opt_else, + scc_pos_t loc) { Assert(stmt != null && cond != null && then != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_IF; stmt->if_stmt.cond = cond; stmt->if_stmt.then_stmt = then; @@ -177,9 +184,10 @@ static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt, static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt, scc_ast_expr_t *cond, - scc_ast_stmt_t *body) { + scc_ast_stmt_t *body, + scc_pos_t loc) { Assert(stmt != null && cond != null && body != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_WHILE; stmt->while_stmt.cond = cond; stmt->while_stmt.body = body; @@ -187,9 +195,10 @@ static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt, 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_ast_stmt_t *body, + scc_pos_t loc) { Assert(stmt != null && cond != null && body != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_DO_WHILE; stmt->while_stmt.cond = cond; stmt->while_stmt.body = body; @@ -200,9 +209,9 @@ static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt, scc_ast_type_t *init, scc_ast_expr_t *cond, scc_ast_expr_t *incr, - scc_ast_stmt_t *body) { + scc_ast_stmt_t *body, scc_pos_t loc) { Assert(stmt != null && body != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_FOR; stmt->for_stmt.init = init; stmt->for_stmt.cond = cond; @@ -212,9 +221,10 @@ static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt, static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt, scc_ast_expr_t *cond, - scc_ast_stmt_t *body) { + scc_ast_stmt_t *body, + scc_pos_t loc) { Assert(stmt != null && cond != null && body != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_SWITCH; stmt->switch_stmt.cond = cond; stmt->switch_stmt.body = body; @@ -222,47 +232,53 @@ static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt, static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt, scc_ast_expr_t *cond, - scc_ast_stmt_t *body) { + scc_ast_stmt_t *body, scc_pos_t loc) { Assert(stmt != null && cond != null && body != null); - stmt->base.loc = scc_pos_create(); + 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_ast_stmt_t *body, + scc_pos_t loc) { Assert(stmt != null && body != null); - stmt->base.loc = scc_pos_create(); + 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) { +static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt, + scc_pos_t loc) { Assert(stmt != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_BREAK; + stmt->jump._target = null; } -static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt) { +static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt, + scc_pos_t loc) { Assert(stmt != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_CONTINUE; + stmt->jump._target = null; } // expr can be null static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt, - scc_ast_expr_t *expr) { + scc_ast_expr_t *expr, + scc_pos_t loc) { Assert(stmt != null); - stmt->base.loc = scc_pos_create(); + 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) { + const char *label, scc_pos_t loc) { Assert(stmt != null && label != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_GOTO; stmt->goto_stmt.label = label; stmt->goto_stmt._target = null; @@ -270,9 +286,10 @@ static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt, static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt, const char *label, - scc_ast_stmt_t *body) { + scc_ast_stmt_t *body, + scc_pos_t loc) { Assert(stmt != null); - stmt->base.loc = scc_pos_create(); + stmt->base.loc = loc; stmt->base.type = SCC_AST_STMT_LABEL; stmt->label_stmt.label = label; stmt->label_stmt.stmt = body; @@ -281,9 +298,10 @@ static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt, 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_ast_expr_t *rhs, + scc_pos_t loc) { Assert(expr != null && lhs != null && rhs != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_BINARY; expr->binary.op = op; expr->binary.lhs = lhs; @@ -292,9 +310,10 @@ static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr, 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_ast_expr_t *operand, + scc_pos_t loc) { Assert(expr != null && operand != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_UNARY; expr->unary.op = op; expr->unary.operand = operand; @@ -303,10 +322,11 @@ static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr, 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_ast_expr_t *else_expr, + scc_pos_t loc) { Assert(expr != null && cond != null && then_expr != null && else_expr != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_COND; expr->cond.cond = cond; expr->cond.then_expr = then_expr; @@ -316,12 +336,12 @@ static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr, // args can be null 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_ast_expr_vec_t *args, + scc_pos_t loc) { Assert(expr != null && callee != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_CALL; expr->call.callee = callee; - expr->call._target = null; if (args == null) { scc_vec_init(expr->call.args); } else { @@ -332,9 +352,10 @@ static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr, // 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_ast_expr_t *index, + scc_pos_t loc) { Assert(expr != null && array != null && index != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT; expr->subscript.array = array; expr->subscript.index = index; @@ -343,9 +364,10 @@ static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr, static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr, scc_ast_node_type_t type, scc_ast_expr_t *object, - const char *member) { + const char *member, + scc_pos_t loc) { Assert(expr != null && object != null && member != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = type; expr->member.base = object; expr->member.name = member; @@ -354,21 +376,24 @@ static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr, static inline void scc_ast_expr_member_init(scc_ast_expr_t *expr, scc_ast_expr_t *object, - const char *member) { - _scc_ast_expr_member_init(expr, SCC_AST_EXPR_MEMBER, object, member); + 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_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member); + 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_ast_expr_t *operand, + scc_pos_t loc) { Assert(expr != null && type != null && operand != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_CAST; expr->cast.type = type; expr->cast.expr = operand; @@ -377,9 +402,10 @@ static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr, // type and target_expr can be null but it only one of them can be null 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_ast_expr_t *target_expr, + scc_pos_t loc) { Assert(expr != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_SIZE_OF; expr->attr_of.type = type; expr->attr_of.expr = target_expr; @@ -388,10 +414,12 @@ static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr, // type and target_expr can be null but it only one of them can be null 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_ast_expr_t *target_expr, + scc_pos_t loc) { Assert(expr != null); - expr->base.loc = scc_pos_create(); - expr->base.type = SCC_AST_EXPR_SIZE_OF; + 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; } @@ -400,9 +428,10 @@ static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr, 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_ast_expr_vec_t *rhs_exprs, + scc_pos_t loc) { Assert(expr != null && base != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_COMPOUND; expr->compound.base = base; @@ -423,67 +452,77 @@ static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr, static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr, scc_ast_node_type_t type, - const char *value, cbool owned) { + const char *value, cbool owned, + scc_pos_t loc) { Assert(expr != null && value != null); - expr->base.loc = scc_pos_create(); + 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_ast_expr_literal_init(expr, SCC_AST_EXPR_INT_LITERAL, value, owned); + 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_ast_expr_literal_init(expr, SCC_AST_EXPR_FLOAT_LITERAL, value, owned); + 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_ast_expr_literal_init(expr, SCC_AST_EXPR_CHAR_LITERAL, value, owned); + 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_ast_expr_literal_init(expr, SCC_AST_EXPR_STRING_LITERAL, value, owned); + 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) { + const char *name, + scc_pos_t loc) { Assert(expr != null && name != null); - expr->base.loc = scc_pos_create(); + expr->base.loc = loc; expr->base.type = SCC_AST_EXPR_IDENTIFIER; expr->identifier.name = name; expr->identifier._target = null; } static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr, - scc_ast_type_t *type) { + scc_ast_type_t *type, + scc_pos_t loc) { Assert(expr != null && type != null); - expr->base.loc = scc_pos_create(); + 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_ast_builtin_type_t builtin, + scc_pos_t loc) { Assert(type != null); - type->base.loc = scc_pos_create(); + type->base.loc = loc; type->base.type = SCC_AST_TYPE_BUILTIN; type->builtin.type = builtin; 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_ast_type_t *pointee, + scc_pos_t loc) { Assert(type != null && pointee != null); - type->base.loc = scc_pos_create(); + type->base.loc = loc; type->base.type = SCC_AST_TYPE_POINTER; type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->pointer.pointee = pointee; @@ -492,9 +531,10 @@ static inline void scc_ast_type_pointer_init(scc_ast_type_t *type, // size can be null static inline void scc_ast_type_array_init(scc_ast_type_t *type, scc_ast_type_t *element, - scc_ast_expr_t *size) { + scc_ast_expr_t *size, + scc_pos_t loc) { Assert(type != null && element != null); - type->base.loc = scc_pos_create(); + type->base.loc = loc; type->base.type = SCC_AST_TYPE_ARRAY; type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->array.element = element; @@ -504,16 +544,17 @@ static inline void scc_ast_type_array_init(scc_ast_type_t *type, // return_type and params can be null 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_ast_decl_vec_t *params, + scc_pos_t loc) { Assert(type != null); - type->base.loc = scc_pos_create(); + 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 == null) { - scc_vec_init(type->function.param_types); + scc_vec_init(type->function.params); } else { - type->function.param_types = *params; + type->function.params = *params; scc_vec_init(*params); } } @@ -521,9 +562,10 @@ static inline void scc_ast_type_function_init(scc_ast_type_t *type, static inline void _scc_ast_type_record_init(scc_ast_type_t *type, scc_ast_node_type_t type_kind, const char *name, - scc_ast_decl_t *decl) { + scc_ast_decl_t *decl, + scc_pos_t loc) { Assert(type != null); - type->base.loc = scc_pos_create(); + type->base.loc = loc; type->base.type = type_kind; type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->record.name = name; @@ -533,23 +575,25 @@ static inline void _scc_ast_type_record_init(scc_ast_type_t *type, // name and decl can be null static inline void scc_ast_type_struct_init(scc_ast_type_t *type, const char *name, - scc_ast_decl_t *decl) { - _scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl); + 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 null static inline void scc_ast_type_union_init(scc_ast_type_t *type, const char *name, - scc_ast_decl_t *decl) { - _scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl); + 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 null static inline void scc_ast_type_enum_init(scc_ast_type_t *type, const char *name, - scc_ast_decl_t *decl) { + scc_ast_decl_t *decl, scc_pos_t loc) { Assert(type != null); - type->base.loc = scc_pos_create(); + type->base.loc = loc; type->base.type = SCC_AST_TYPE_ENUM; type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->enumeration.name = name; @@ -558,9 +602,10 @@ static inline void scc_ast_type_enum_init(scc_ast_type_t *type, static inline void scc_ast_type_typedef_init(scc_ast_type_t *type, const char *name, - scc_ast_decl_t *target) { + scc_ast_decl_t *target, + scc_pos_t loc) { Assert(type != null && target != null); - type->base.loc = scc_pos_create(); + 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; diff --git a/libs/ast/src/ast_dump.c b/libs/ast/src/ast_dump.c index f37a4c5..1e83304 100644 --- a/libs/ast/src/ast_dump.c +++ b/libs/ast/src/ast_dump.c @@ -347,10 +347,9 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) { (void)scc_vec_pop(ctx->stack); scc_vec_push(ctx->stack, true); - if (scc_vec_size(type->function.param_types) != 0) { - scc_vec_foreach(type->function.param_types, i) { - scc_ast_decl_t *param = - scc_vec_at(type->function.param_types, i); + 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); if (param->name) { // FIXME param name } diff --git a/libs/ast2ir/include/scc_ast2ir.h b/libs/ast2ir/include/scc_ast2ir.h index 11de474..9b787ca 100644 --- a/libs/ast2ir/include/scc_ast2ir.h +++ b/libs/ast2ir/include/scc_ast2ir.h @@ -5,8 +5,22 @@ #include #include -void scc_ast2ir_translation_unit(scc_ir_builder_t *builder, - scc_ast_translation_unit_t *tu, - const scc_type_abi_t *abi); +typedef struct { + scc_ir_builder_t builder; + scc_hashtable_t node2ir; ///< decl to ir_ref + scc_hashtable_t symtab; ///< symbol to ir_ref + scc_strpool_t strpool; ///< string pool + const scc_type_abi_t *abi; +} scc_ast2ir_ctx_t; + +void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi); + +void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, + scc_ast_translation_unit_t *tu); +void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl); +scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr); +void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt); +scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, + scc_ast_type_t *ast_type); #endif /* __SCC_AST2IR_H__ */ diff --git a/libs/ast2ir/src/ast2ir.c b/libs/ast2ir/src/ast2ir.c deleted file mode 100644 index 3dfc3f0..0000000 --- a/libs/ast2ir/src/ast2ir.c +++ /dev/null @@ -1,561 +0,0 @@ -#include -#include - -static scc_ir_node_ref_t ast_expr_to_ir(scc_ir_builder_t *ctx, - scc_ast_expr_t *expr); -static void ast_stmt_to_ir(scc_ir_builder_t *ctx, scc_ast_stmt_t *stmt); -static void ast_decl_to_ir(scc_ir_builder_t *ctx, scc_ast_decl_t *decl); -static scc_ir_type_ref_t ast_type_to_ir_type(scc_ir_builder_t *ctx, - scc_ast_type_t *ast_type); - -// 转换AST类型为IR类型 -static scc_ir_type_ref_t ast_type_to_ir_type(scc_ir_builder_t *ctx, - scc_ast_type_t *ast_type) { - if (ctx == null || ast_type == null) { - LOG_ERROR("args is null"); - return 0; - } - scc_ir_type_t ir_type; - - switch (ast_type->base.type) { - case SCC_AST_TYPE_BUILTIN: { - // 映射内置类型 - scc_ir_type_init(&ir_type, SCC_IR_TYPE_I32); - // TODO: 根据具体内置类型设置 - break; - } - - case SCC_AST_TYPE_POINTER: { - scc_ir_type_init(&ir_type, SCC_IR_TYPE_PTR); - - // 创建指向类型并添加到程序类型列表 - scc_ir_type_ref_t pointee_type = - ast_type_to_ir_type(ctx, ast_type->pointer.pointee); - - // 注意:我们需要找到一种合适的方式来存储类型信息 - // 目前的IR设计中类型信息应该直接存储在类型结构中 - ir_type.data.pointer.base = pointee_type; - break; - } - - case SCC_AST_TYPE_ARRAY: { - scc_ir_type_init(&ir_type, SCC_IR_TYPE_ARRAY); - - // 创建元素类型并添加到程序类型列表 - scc_ir_type_ref_t element_type = - ast_type_to_ir_type(ctx, ast_type->array.element); - - // 将类型添加到程序的类型容器中 - ir_type.data.array.base = element_type; - // TODO: 处理数组大小表达式 - ir_type.data.array.len = 0; // 暂时设为0 - break; - } - - case SCC_AST_TYPE_FUNCTION: { - scc_ir_type_init(&ir_type, SCC_IR_TYPE_FUNC); - - // 处理返回类型 - scc_ir_type_ref_t ret_type = - ast_type_to_ir_type(ctx, ast_type->function.return_type); - - // 将返回类型添加到程序的类型容器中 - ir_type.data.function.ret_type = ret_type; - - // 转换参数类型 - scc_ir_type_ref_vec_t params; - scc_vec_init(params); - scc_vec_foreach(ast_type->function.param_types, i) { - scc_ast_decl_t *decl_param = - scc_vec_at(ast_type->function.param_types, i); - Assert(decl_param->base.type == SCC_AST_DECL_PARAM); - scc_ir_type_ref_t tmp_type = - ast_type_to_ir_type(ctx, decl_param->param.type); - scc_vec_push(params, tmp_type); - } - ir_type.data.function.params = params; - break; - } - - default: - LOG_FATAL("Unsupported AST type: %d", ast_type->base.type); - return 0; - } - return scc_ir_ctx_new_type(&ctx->ctx, &ir_type); -} - -// 转换AST表达式为IR节点 -static scc_ir_node_ref_t ast_expr_to_ir(scc_ir_builder_t *ctx, - scc_ast_expr_t *expr) { - if (ctx == null || expr == null) { - LOG_ERROR("args is null"); - return 0; - } - - switch (expr->base.type) { - case SCC_AST_EXPR_IDENTIFIER: { - // TODO maybe error or need symtab - scc_ir_node_t in; - scc_ir_node_init(&in, expr->identifier.name, SCC_IR_NODE_LOAD); - return scc_ir_ctx_new_node(&ctx->ctx, &in); - } - - case SCC_AST_EXPR_INT_LITERAL: { - // TODO parse i32 value - return scc_ir_ctx_get_i32_const(&ctx->ctx, 0); - } - - case SCC_AST_EXPR_BINARY: { - // 转换左右操作数 - scc_ir_node_ref_t lhs, rhs; - lhs = ast_expr_to_ir(ctx, expr->binary.lhs); - rhs = ast_expr_to_ir(ctx, expr->binary.rhs); - - // 映射操作符 - scc_ir_op_type_t op; - switch (expr->binary.op) { - /* clang-format off */ - case SCC_AST_OP_ADD: op = SCC_IR_OP_ADD; break; - case SCC_AST_OP_SUB: op = SCC_IR_OP_SUB; break; - case SCC_AST_OP_MUL: op = SCC_IR_OP_MUL; break; - case SCC_AST_OP_DIV: op = SCC_IR_OP_DIV; break; - case SCC_AST_OP_MOD: op = SCC_IR_OP_MOD; break; - case SCC_AST_OP_LOGICAL_AND: op = SCC_IR_OP_AND; break; - case SCC_AST_OP_LOGICAL_OR: op = SCC_IR_OP_OR; break; - case SCC_AST_OP_BITWISE_XOR: op = SCC_IR_OP_XOR; break; - case SCC_AST_OP_LEFT_SHIFT: op = SCC_IR_OP_SHL; break; - case SCC_AST_OP_RIGHT_SHIFT: op = SCC_IR_OP_SHR; break; - case SCC_AST_OP_EQUAL: op = SCC_IR_OP_EQ; break; - case SCC_AST_OP_NOT_EQUAL: op = SCC_IR_OP_NEQ; break; - case SCC_AST_OP_LESS: op = SCC_IR_OP_LT; break; - case SCC_AST_OP_LESS_EQUAL: op = SCC_IR_OP_LE; break; - case SCC_AST_OP_GREATER: op = SCC_IR_OP_GT; break; - case SCC_AST_OP_GREATER_EQUAL: op = SCC_IR_OP_GE; break; - case SCC_AST_OP_ASSIGN: { - // 赋值表达式:存储右值到左值位置 - return scc_ir_builder_store(ctx, lhs, rhs); - - } - case SCC_AST_OP_ASSIGN_ADD: - TODO(); - /* clang-format on */ - default: - LOG_WARN("Unsupported binary operator: %d", expr->binary.op); - op = SCC_IR_OP_ADD; // 默认 - } - - // 创建操作节点 - return scc_ir_builder_binop(ctx, op, lhs, rhs); - } - - case SCC_AST_EXPR_UNARY: { - // 转换操作数 - scc_ir_node_ref_t operand = ast_expr_to_ir(ctx, expr->unary.operand); - - // 映射一元操作符 - switch (expr->unary.op) { - case SCC_AST_OP_SUB: - // 负号 - // 实现为0 - operand - return scc_ir_builder_binop(ctx, SCC_IR_OP_SUB, - scc_ir_ctx_get_builtin_zero(&ctx->ctx), - operand); - case SCC_AST_OP_BITWISE_NOT: - // 按位取反 - return scc_ir_builder_binop(ctx, SCC_IR_OP_NOT, operand, 0); - case SCC_AST_OP_LOGICAL_NOT: - // 逻辑非 - // 实现为与0比较 - return scc_ir_builder_binop(ctx, SCC_IR_OP_EQ, - scc_ir_ctx_get_builtin_zero(&ctx->ctx), - operand); - default: - LOG_WARN("Unsupported unary operator: %d", expr->unary.op); - return 0; - } - } - - case SCC_AST_EXPR_COND: { - TODO(); - break; - } - - case SCC_AST_EXPR_CALL: { - // 转换参数 - scc_ir_node_ref_vec_t args; - scc_vec_init(args); - - // 检查参数是否为空 - if (expr->call.args.data != null) { - scc_vec_foreach(expr->call.args, i) { - scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i); - scc_ir_node_ref_t arg_node; - arg_node = ast_expr_to_ir(ctx, arg_expr); - scc_vec_push(args, arg_node); - } - } - - // 创建调用节点(需要查找函数定义) - // TODO: 需要符号表查找函数 - scc_ir_node_ref_t func = - scc_ir_builder_call(ctx, 0, args.data, args.size); - scc_vec_free(args); - return func; - } - - default: - LOG_WARN("Unsupported expression type: %d", expr->base.type); - return 0; - } -} - -// 转换AST语句为IR -static void ast_stmt_to_ir(scc_ir_builder_t *ctx, scc_ast_stmt_t *stmt) { - if (stmt == null) { - return; - } - - switch (stmt->base.type) { - case SCC_AST_STMT_COMPOUND: { - // 进入新的作用域 - scc_vec_foreach(stmt->compound.block_items, i) { - scc_ast_node_t *child_stmt = - scc_vec_at(stmt->compound.block_items, i); - if (SCC_AST_IS_A(scc_ast_stmt_t, child_stmt)) { - ast_stmt_to_ir(ctx, - SCC_AST_CAST_TO(scc_ast_stmt_t, child_stmt)); - } else if (SCC_AST_IS_A(scc_ast_decl_t, child_stmt)) { - ast_decl_to_ir(ctx, - SCC_AST_CAST_TO(scc_ast_decl_t, child_stmt)); - } else { - UNREACHABLE(); - } - } - break; - } - - case SCC_AST_STMT_EXPR: { - ast_expr_to_ir(ctx, stmt->expr.expr); - break; - } - - // case SCC_AST_STMT_IF: { - // // 创建基本块 - 统一使用栈上分配 - // scc_ir_bblock_t true_block; - // scc_ir_bblock_init(&true_block, "if_true"); - - // scc_ir_bblock_t false_block; - // scc_ir_bblock_init(&false_block, "if_false"); - - // scc_ir_bblock_t merge_block; - // scc_ir_bblock_init(&merge_block, "if_merge"); - - // // 转换条件 - // scc_ir_node_ref_t cond_node = ast_expr_to_ir(ctx, - // stmt->if_stmt.cond); - - // // 创建分支指令 - // scc_ir_builder_branch(); - // scc_ir_node_t br_node; - // init_branch_node(&br_node, cond, &true_block, &false_block); - // emit_instruction(ctx, &br_node); - - // // 保存当前块 - // ast2ir_ctx_t saved = ctx->current_ctx; - - // // 生成true分支 - // emit_basicblock(ctx, &true_block); - // ast_stmt_to_ir(ctx, stmt->if_stmt.then_stmt); - - // // 跳转到合并块 - // scc_ir_node_t jump_node; - // init_jump_node(&jump_node, &merge_block); - // emit_instruction(ctx, &jump_node); - - // // 生成false分支(如果有) - // emit_basicblock(ctx, &false_block); - // if (stmt->if_stmt.opt_else_stmt) { - // ast_stmt_to_ir(ctx, stmt->if_stmt.opt_else_stmt); - // } - - // // 跳转到合并块 - // init_jump_node(&jump_node, &merge_block); - // emit_instruction(ctx, &jump_node); - - // // 恢复上下文并设置当前块为合并块 - // ctx->current_ctx = saved; - // emit_basicblock(ctx, &merge_block); - // break; - // } - - // case SCC_AST_STMT_WHILE: { - // // 创建基本块 - 统一使用栈上分配 - // scc_ir_bblock_t cond_block; - // scc_ir_bblock_init(&cond_block, "while_cond"); - - // scc_ir_bblock_t body_block; - // scc_ir_bblock_init(&body_block, "while_body"); - - // scc_ir_bblock_t exit_block; - // scc_ir_bblock_init(&exit_block, "while_exit"); - - // // 跳转到条件块 - // scc_ir_node_t jump_node; - // init_jump_node(&jump_node, &cond_block); - // emit_instruction(ctx, &jump_node); - - // // 保存当前块 - // ast2ir_ctx_t saved = ctx->current_ctx; - - // // 生成条件块 - // emit_basicblock(ctx, &cond_block); - // scc_ir_node_t cond_node; - // ast_expr_to_ir(ctx, stmt->while_stmt.cond, &cond_node); - - // // 将条件节点添加到程序节点列表 - // scc_vec_push(ctx->program->global_vals, cond_node); - // scc_ir_node_t *cond = - // &scc_vec_at(ctx->program->global_vals, - // scc_vec_size(ctx->program->global_vals) - 1); - - // // 创建分支 - // scc_ir_node_t br_node; - // init_branch_node(&br_node, cond, &body_block, &exit_block); - // emit_instruction(ctx, &br_node); - - // // 生成循环体 - // emit_basicblock(ctx, &body_block); - // ast_stmt_to_ir(ctx, stmt->while_stmt.body); - - // // 跳转回条件块 - // init_jump_node(&jump_node, &cond_block); - // emit_instruction(ctx, &jump_node); - - // // 恢复上下文并设置当前块为退出块 - // ctx->current_ctx = saved; - // emit_basicblock(ctx, &exit_block); - // break; - // } - - // case SCC_AST_STMT_DO_WHILE: { - // // 创建基本块 - 统一使用栈上分配 - // scc_ir_bblock_t cond_block; - // scc_ir_bblock_init(&cond_block, "do_while_cond"); - - // scc_ir_bblock_t body_block; - // scc_ir_bblock_init(&body_block, "do_while_body"); - - // scc_ir_bblock_t exit_block; - // scc_ir_bblock_init(&exit_block, "do_while_exit"); - - // // 跳转到循环体块 - // scc_ir_node_t jump_node; - // init_jump_node(&jump_node, &body_block); - // emit_instruction(ctx, &jump_node); - - // // 保存当前块 - // ast2ir_ctx_t saved = ctx->current_ctx; - - // // 生成循环体 - // emit_basicblock(ctx, &body_block); - // ast_stmt_to_ir(ctx, stmt->do_while_stmt.body); - - // // 跳转到条件块 - // init_jump_node(&jump_node, &cond_block); - // emit_instruction(ctx, &jump_node); - - // // 生成条件块 - // emit_basicblock(ctx, &cond_block); - // scc_ir_node_t cond_node; - // ast_expr_to_ir(ctx, stmt->do_while_stmt.cond, &cond_node); - - // // 将条件节点添加到程序节点列表 - // scc_vec_push(ctx->program->global_vals, cond_node); - // scc_ir_node_t *cond = - // &scc_vec_at(ctx->program->global_vals, - // scc_vec_size(ctx->program->global_vals) - 1); - - // // 创建分支 - // scc_ir_node_t br_node; - // init_branch_node(&br_node, cond, &body_block, &exit_block); - // emit_instruction(ctx, &br_node); - - // // 恢复上下文并设置当前块为退出块 - // ctx->current_ctx = saved; - // emit_basicblock(ctx, &exit_block); - // break; - // } - - // case SCC_AST_STMT_FOR: { - // // 初始化部分 - // if (SCC_AST_IS_A(scc_ast_expr_t, stmt->for_stmt.init)) { - // scc_ir_node_t dummy_node; - // ast_expr_to_ir(ctx, - // SCC_AST_CAST_TO(scc_ast_expr_t, - // stmt->for_stmt.init), &dummy_node); - // } else if (SCC_AST_IS_A(scc_ast_decl_t, stmt->for_stmt.init)) { - // ast_decl_to_ir( - // ctx, SCC_AST_CAST_TO(scc_ast_decl_t, - // stmt->for_stmt.init)); - // } else { - // UNREACHABLE(); - // } - - // // 创建基本块 - 统一使用栈上分配 - // scc_ir_bblock_t cond_block; - // scc_ir_bblock_init(&cond_block, "for_cond"); - - // scc_ir_bblock_t body_block; - // scc_ir_bblock_init(&body_block, "for_body"); - - // scc_ir_bblock_t exit_block; - // scc_ir_bblock_init(&exit_block, "for_exit"); - - // // 跳转到条件块 - // scc_ir_node_t jump_node; - // init_jump_node(&jump_node, &cond_block); - // emit_instruction(ctx, &jump_node); - - // // 保存当前块 - // ast2ir_ctx_t saved = ctx->current_ctx; - - // // 生成条件块 - // emit_basicblock(ctx, &cond_block); - - // scc_ir_node_t *cond = null; - // if (stmt->for_stmt.cond) { - // scc_ir_node_t cond_node; - // ast_expr_to_ir(ctx, stmt->for_stmt.cond, &cond_node); - - // // 将条件节点添加到程序节点列表 - // scc_vec_push(ctx->program->global_vals, cond_node); - // cond = &scc_vec_at(ctx->program->global_vals, - // scc_vec_size(ctx->program->global_vals) - - // 1); - // } else { - // // 无条件循环,条件为真 - // scc_ir_node_t true_node; - // init_const_int_node(&true_node, 1, null); - - // // 将true节点添加到程序节点列表 - // scc_vec_push(ctx->program->global_vals, true_node); - // cond = &scc_vec_at(ctx->program->global_vals, - // scc_vec_size(ctx->program->global_vals) - - // 1); - // } - - // // 创建分支 - // scc_ir_node_t br_node; - // init_branch_node(&br_node, cond, &body_block, &exit_block); - // emit_instruction(ctx, &br_node); - - // // 生成循环体 - // emit_basicblock(ctx, &body_block); - // ast_stmt_to_ir(ctx, stmt->for_stmt.body); - - // // 执行迭代表达式(如果存在) - // if (stmt->for_stmt.incr) { - // scc_ir_node_t dummy_node; - // ast_expr_to_ir(ctx, stmt->for_stmt.incr, &dummy_node); - // } - - // // 跳转回条件块 - // init_jump_node(&jump_node, &cond_block); - // emit_instruction(ctx, &jump_node); - - // // 恢复上下文并设置当前块为退出块 - // ctx->current_ctx = saved; - // emit_basicblock(ctx, &exit_block); - // break; - // } - - case SCC_AST_STMT_RETURN: { - if (stmt->return_stmt.expr) { - scc_ir_node_ref_t ret_val_node = - ast_expr_to_ir(ctx, stmt->return_stmt.expr); - - scc_ir_builder_ret(ctx, ret_val_node); - } else { - scc_ir_builder_ret_void(ctx); - } - break; - } - - default: - LOG_WARN("Unsupported statement type: %d", stmt->base.type); - break; - } -} - -// 转换AST声明为IR -static void ast_decl_to_ir(scc_ir_builder_t *ctx, scc_ast_decl_t *decl) { - if (ctx == null || decl == null) { - LOG_ERROR("Invalid argument"); - return; - } - - switch (decl->base.type) { - case SCC_AST_DECL_VAR: { - // 转换类型 - scc_ir_type_ref_t ir_type = ast_type_to_ir_type(ctx, decl->var.type); - - // 创建分配节点 - scc_ir_node_ref_t alloc_val_node = - scc_ir_builder_alloca(ctx, ir_type, decl->name); - - // 如果有初始化表达式 - if (!decl->var.init) { - break; - } - scc_ir_node_ref_t init_val_node = ast_expr_to_ir(ctx, decl->var.init); - - // 将初始化值节点添加到程序节点列表 - // scc_vec_push(ctx->program->global_vals, init_val_node); - // scc_ir_node_t *init_val = - // &scc_vec_at(ctx->program->global_vals, - // scc_vec_size(ctx->program->global_vals) - 1); - - scc_ir_builder_store(ctx, alloc_val_node, init_val_node); - break; - } - - case SCC_AST_DECL_FUNC: { - // TODO params name - scc_ir_type_ref_t func_type = ast_type_to_ir_type(ctx, decl->func.type); - scc_ir_builder_begin_func(ctx, decl->name, func_type, null); - // 处理函数体(如果有) - if (decl->func.body) { - scc_ir_builder_begin_bblock(ctx, "entry"); - ast_stmt_to_ir(ctx, decl->func.body); - scc_ir_builder_end_bblock(ctx); - } - scc_ir_builder_end_func(ctx); - break; - } - - default: - LOG_WARN("Unsupported declaration type: %d", decl->base.type); - break; - } -} - -/** - * @brief 将AST的翻译单元转换为IR - * @warning 需要初始化builder且保证tu合法 - * - * @param builder - * @param tu - */ -void scc_ast2ir_translation_unit(scc_ir_builder_t *builder, - scc_ast_translation_unit_t *tu, - const scc_type_abi_t *abi) { - if (tu == null || builder == null) { - LOG_ERROR("Invalid argument"); - return; - } - - scc_vec_foreach(tu->declarations, i) { - scc_ast_decl_t *decl = scc_vec_at(tu->declarations, i); - ast_decl_to_ir(builder, decl); - } -} diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c new file mode 100644 index 0000000..f9bed28 --- /dev/null +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -0,0 +1,530 @@ +#include +#include + +scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, + scc_ast_type_t *ast_type) { + if (ctx == null || ast_type == null) { + LOG_ERROR("args is null"); + return 0; + } + scc_ir_type_t ir_type; + + switch (ast_type->base.type) { + case SCC_AST_TYPE_BUILTIN: { + // 映射内置类型 + scc_ir_type_init(&ir_type, SCC_IR_TYPE_I32); + // TODO: 根据具体内置类型设置 + break; + } + + case SCC_AST_TYPE_POINTER: { + scc_ir_type_init(&ir_type, SCC_IR_TYPE_PTR); + + // 创建指向类型并添加到程序类型列表 + scc_ir_type_ref_t pointee_type = + scc_ast2ir_type(ctx, ast_type->pointer.pointee); + + // 注意:我们需要找到一种合适的方式来存储类型信息 + // 目前的IR设计中类型信息应该直接存储在类型结构中 + ir_type.data.pointer.base = pointee_type; + break; + } + + case SCC_AST_TYPE_ARRAY: { + scc_ir_type_init(&ir_type, SCC_IR_TYPE_ARRAY); + + // 创建元素类型并添加到程序类型列表 + scc_ir_type_ref_t element_type = + scc_ast2ir_type(ctx, ast_type->array.element); + + // 将类型添加到程序的类型容器中 + ir_type.data.array.base = element_type; + // TODO: 处理数组大小表达式 + ir_type.data.array.len = 0; // 暂时设为0 + break; + } + + case SCC_AST_TYPE_FUNCTION: { + scc_ir_type_init(&ir_type, SCC_IR_TYPE_FUNC); + + // 处理返回类型 + scc_ir_type_ref_t ret_type = + scc_ast2ir_type(ctx, ast_type->function.return_type); + + // 将返回类型添加到程序的类型容器中 + ir_type.data.function.ret_type = ret_type; + + // 转换参数类型 + scc_ir_type_ref_vec_t params; + scc_vec_init(params); + scc_vec_foreach(ast_type->function.params, i) { + scc_ast_decl_t *decl_param = + scc_vec_at(ast_type->function.params, i); + Assert(decl_param->base.type == SCC_AST_DECL_PARAM); + scc_ir_type_ref_t tmp_type = + scc_ast2ir_type(ctx, decl_param->param.type); + scc_vec_push(params, tmp_type); + } + ir_type.data.function.params = params; + break; + } + + // 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 类型 + + default: + LOG_FATAL("Unsupported AST type: %d", ast_type->base.type); + return 0; + } + return scc_ir_ctx_new_type(&ctx->builder.ctx, &ir_type); +} + +/** + * @brief + * + * @param ctx + * @param expr + * @return scc_ir_node_ref_t + */ +scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr) { + if (ctx == null || expr == null) { + LOG_ERROR("args is null"); + return 0; + } + + switch (expr->base.type) { + case SCC_AST_EXPR_BINARY: { + scc_ir_node_ref_t lhs, rhs; + lhs = scc_ast2ir_expr(ctx, expr->binary.lhs); + rhs = scc_ast2ir_expr(ctx, expr->binary.rhs); + + // 映射操作符 + scc_ir_op_type_t op; + switch (expr->binary.op) { + /* clang-format off */ + case SCC_AST_OP_ADD: op = SCC_IR_OP_ADD; break; + case SCC_AST_OP_SUB: op = SCC_IR_OP_SUB; break; + case SCC_AST_OP_MUL: op = SCC_IR_OP_MUL; break; + case SCC_AST_OP_DIV: op = SCC_IR_OP_DIV; break; + case SCC_AST_OP_MOD: op = SCC_IR_OP_MOD; break; + case SCC_AST_OP_LOGICAL_AND: op = SCC_IR_OP_AND; break; + case SCC_AST_OP_LOGICAL_OR: op = SCC_IR_OP_OR; break; + case SCC_AST_OP_BITWISE_XOR: op = SCC_IR_OP_XOR; break; + case SCC_AST_OP_LEFT_SHIFT: op = SCC_IR_OP_SHL; break; + case SCC_AST_OP_RIGHT_SHIFT: op = SCC_IR_OP_SHR; break; + case SCC_AST_OP_EQUAL: op = SCC_IR_OP_EQ; break; + case SCC_AST_OP_NOT_EQUAL: op = SCC_IR_OP_NEQ; break; + case SCC_AST_OP_LESS: op = SCC_IR_OP_LT; break; + case SCC_AST_OP_LESS_EQUAL: op = SCC_IR_OP_LE; break; + case SCC_AST_OP_GREATER: op = SCC_IR_OP_GT; break; + case SCC_AST_OP_GREATER_EQUAL: op = SCC_IR_OP_GE; break; + // SCC_AST_OP_ASSIGN, // = + // SCC_AST_OP_ASSIGN_ADD, // += + // SCC_AST_OP_ASSIGN_SUB, // -= + // SCC_AST_OP_ASSIGN_MUL, // *= + // SCC_AST_OP_ASSIGN_DIV, // /= + // SCC_AST_OP_ASSIGN_MOD, // %= + // SCC_AST_OP_ASSIGN_AND, // &= + // SCC_AST_OP_ASSIGN_XOR, // ^= + // SCC_AST_OP_ASSIGN_OR, // |= + // SCC_AST_OP_ASSIGN_LSHIFT, // <<= + // SCC_AST_OP_ASSIGN_RSHIFT, // >>= + case SCC_AST_OP_ASSIGN: { + return scc_ir_builder_store(&ctx->builder, lhs, rhs); + } + case SCC_AST_OP_ASSIGN_ADD: + TODO(); + // /* 赋值操作符 */ + // /* 条件操作符 */ + // SCC_AST_OP_CONDITIONAL, // ?: + // /* 逗号操作符 */ + // SCC_AST_OP_COMMA, // , + // /* 逻辑操作符 */ + // SCC_AST_OP_LOGICAL_OR, // || + // SCC_AST_OP_LOGICAL_AND, // && + // /* 位操作符 */ + // SCC_AST_OP_BITWISE_OR, // | + // SCC_AST_OP_BITWISE_XOR, // ^ + // SCC_AST_OP_BITWISE_AND, // & + // /* 相等性操作符 */ + // SCC_AST_OP_EQUAL, // == + // SCC_AST_OP_NOT_EQUAL, // != + // /* 关系操作符 */ + // SCC_AST_OP_LESS, // < + // SCC_AST_OP_GREATER, // > + // SCC_AST_OP_LESS_EQUAL, // <= + // SCC_AST_OP_GREATER_EQUAL, // >= + // /* 移位操作符 */ + // SCC_AST_OP_LEFT_SHIFT, // << + // SCC_AST_OP_RIGHT_SHIFT, // >> + // /* 算术操作符 */ + // SCC_AST_OP_ADD, // + + // SCC_AST_OP_SUB, // - + // SCC_AST_OP_MUL, // * + // SCC_AST_OP_DIV, // / + // SCC_AST_OP_MOD, // % + // /* 一元操作符 */ + // SCC_AST_OP_UNARY_PLUS, // + (一元) + // SCC_AST_OP_UNARY_MINUS, // - (一元) + // SCC_AST_OP_ADDRESS_OF, // & + // SCC_AST_OP_INDIRECTION, // * + // SCC_AST_OP_BITWISE_NOT, // ~ + // SCC_AST_OP_LOGICAL_NOT, // ! + // SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀) + // SCC_AST_OP_PREFIX_DECREMENT, // -- (前缀) + // SCC_AST_OP_POSTFIX_INCREMENT, // ++ (后缀) + // SCC_AST_OP_POSTFIX_DECREMENT, // -- (后缀) + // /* 成员访问 */ + // SCC_AST_OP_MEMBER_ACCESS, // . + // SCC_AST_OP_PTR_MEMBER_ACCESS, // -> + /* clang-format on */ + default: + LOG_FATAL("Unsupported binary operator: %d", expr->binary.op); + return 0; + } + + // 创建操作节点 + return scc_ir_builder_binop(&ctx->builder, op, lhs, rhs); + } + + case SCC_AST_EXPR_UNARY: { + scc_ir_node_ref_t operand = scc_ast2ir_expr(ctx, expr->unary.operand); + + // 映射一元操作符 + switch (expr->unary.op) { + case SCC_AST_OP_SUB: + // 负号 + // 实现为0 - operand + return scc_ir_builder_binop( + &ctx->builder, SCC_IR_OP_SUB, + scc_ir_ctx_get_builtin_zero(&ctx->builder.ctx), operand); + case SCC_AST_OP_BITWISE_NOT: + // 按位取反 + return scc_ir_builder_binop(&ctx->builder, SCC_IR_OP_NOT, operand, + 0); + case SCC_AST_OP_LOGICAL_NOT: + // 逻辑非 + // 实现为与0比较 + return scc_ir_builder_binop( + &ctx->builder, SCC_IR_OP_EQ, + scc_ir_ctx_get_builtin_zero(&ctx->builder.ctx), operand); + default: + LOG_FATAL("Unsupported unary operator: %d", expr->unary.op); + return 0; + } + } + + case SCC_AST_EXPR_COND: { + TODO(); + break; + } + + case SCC_AST_EXPR_CALL: { + // 转换参数 + scc_ir_node_ref_vec_t args; + scc_vec_init(args); + + // 检查参数是否为空 + if (expr->call.args.data != null) { + scc_vec_foreach(expr->call.args, i) { + scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i); + scc_ir_node_ref_t arg_node; + arg_node = scc_ast2ir_expr(ctx, arg_expr); + scc_vec_push(args, arg_node); + } + } + + // 创建调用节点(需要查找函数定义) + // TODO: 需要符号表查找函数 + scc_ir_node_ref_t func = + scc_ir_builder_call(&ctx->builder, 0, args.data, args.size); + scc_vec_free(args); + return func; + } + + // SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标 + // SCC_AST_EXPR_MEMBER, // 成员访问 . + // SCC_AST_EXPR_PTR_MEMBER, // 指针成员访问 -> + // SCC_AST_EXPR_CAST, // 类型转换 + // SCC_AST_EXPR_SIZE_OF, // sizeof + // SCC_AST_EXPR_ALIGN_OF, // _Alignof + // SCC_AST_EXPR_COMPOUND, // 复合字面量 + // SCC_AST_EXPR_LVALUE, // 右值 + // SCC_AST_EXPR_BUILTIN, // 内置表达式 + + case SCC_AST_EXPR_INT_LITERAL: { + // FIXME maybe using some array to int; + usize int_lit = 0; + for (usize i = 0; i < scc_strlen(expr->literal.lexme); i++) { + int_lit = int_lit * 10 + (expr->literal.lexme[i] - '0'); + } + return scc_ir_ctx_get_i32_const(&ctx->builder.ctx, int_lit); + } + + // SCC_AST_EXPR_INT_LITERAL, // 整数字面量 + // SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量 + // SCC_AST_EXPR_CHAR_LITERAL, // 字符字面量 + // SCC_AST_EXPR_STRING_LITERAL, // 字符串字面量 + + case SCC_AST_EXPR_IDENTIFIER: { + // FIXME hack hashtable + scc_ir_node_ref_t in = (scc_ir_node_ref_t)(usize)scc_hashtable_get( + &ctx->node2ir, expr->identifier._target); + return scc_ir_builder_load(&ctx->builder, in); + } + + default: + LOG_FATAL("Unsupported expression type: %d", expr->base.type); + return 0; + } +} + +/** + * @brief + * + * @param ctx + * @param stmt + */ +void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) { + if (stmt == null) { + return; + } + + switch (stmt->base.type) { + case SCC_AST_STMT_COMPOUND: { + scc_vec_foreach(stmt->compound.block_items, i) { + scc_ast_node_t *child_stmt = + scc_vec_at(stmt->compound.block_items, i); + if (SCC_AST_IS_A(scc_ast_stmt_t, child_stmt)) { + scc_ast2ir_stmt(ctx, + SCC_AST_CAST_TO(scc_ast_stmt_t, child_stmt)); + } else if (SCC_AST_IS_A(scc_ast_decl_t, child_stmt)) { + scc_ast2ir_decl(ctx, + SCC_AST_CAST_TO(scc_ast_decl_t, child_stmt)); + } else { + UNREACHABLE(); + } + } + break; + } + + case SCC_AST_STMT_EXPR: { + scc_ast2ir_expr(ctx, stmt->expr.expr); + break; + } + + case SCC_AST_STMT_IF: { + /* + branch cond + / \ + true_block false_block + \ / + merge_block + */ + scc_ir_bblock_ref_t true_block = + scc_ir_builder_bblock(&ctx->builder, "if_true"); + + scc_ir_bblock_ref_t false_block = + scc_ir_builder_bblock(&ctx->builder, "if_false"); + + scc_ir_bblock_ref_t merge_block = + scc_ir_builder_bblock(&ctx->builder, "if_merge"); + + scc_ir_node_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->if_stmt.cond); + scc_ir_builder_branch(&ctx->builder, cond_node, true_block, + false_block); + + // 生成true分支 + scc_ir_builder_set_current_bblock(&ctx->builder, true_block); + scc_ast2ir_stmt(ctx, stmt->if_stmt.then_stmt); + scc_ir_builder_jump(&ctx->builder, merge_block); + + // 生成false分支 + if (stmt->if_stmt.opt_else_stmt) { + scc_ir_builder_set_current_bblock(&ctx->builder, true_block); + scc_ast2ir_stmt(ctx, stmt->if_stmt.opt_else_stmt); + scc_ir_builder_jump(&ctx->builder, merge_block); + } + + scc_ir_builder_set_current_bblock(&ctx->builder, merge_block); + break; + } + + case SCC_AST_STMT_WHILE: { + scc_ir_bblock_ref_t cond_block = + scc_ir_builder_bblock(&ctx->builder, "while_cond"); + scc_ir_bblock_ref_t body_block = + scc_ir_builder_bblock(&ctx->builder, "while_body"); + scc_ir_bblock_ref_t exit_block = + scc_ir_builder_bblock(&ctx->builder, "while_exit"); + + scc_ir_builder_jump(&ctx->builder, cond_block); + + scc_ir_builder_set_current_bblock(&ctx->builder, cond_block); + scc_ir_node_ref_t cond_node = + scc_ast2ir_expr(ctx, stmt->while_stmt.cond); + scc_ir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); + + scc_ir_builder_set_current_bblock(&ctx->builder, body_block); + scc_ast2ir_stmt(ctx, stmt->while_stmt.body); + scc_ir_builder_jump(&ctx->builder, cond_block); + + scc_ir_builder_set_current_bblock(&ctx->builder, exit_block); + break; + } + + case SCC_AST_STMT_DO_WHILE: { + scc_ir_bblock_ref_t cond_block = + scc_ir_builder_bblock(&ctx->builder, "do_while_cond"); + scc_ir_bblock_ref_t body_block = + scc_ir_builder_bblock(&ctx->builder, "do_while_body"); + scc_ir_bblock_ref_t exit_block = + scc_ir_builder_bblock(&ctx->builder, "do_while_exit"); + + scc_ir_builder_jump(&ctx->builder, body_block); + + scc_ir_builder_set_current_bblock(&ctx->builder, body_block); + scc_ast2ir_stmt(ctx, stmt->while_stmt.body); + scc_ir_builder_jump(&ctx->builder, cond_block); + + scc_ir_builder_set_current_bblock(&ctx->builder, cond_block); + scc_ir_node_ref_t cond_node = + scc_ast2ir_expr(ctx, stmt->while_stmt.cond); + scc_ir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); + + scc_ir_builder_set_current_bblock(&ctx->builder, exit_block); + break; + } + + case SCC_AST_STMT_FOR: { + TODO(); + scc_ir_bblock_ref_t cond_block = + scc_ir_builder_bblock(&ctx->builder, "for_while_cond"); + scc_ir_bblock_ref_t body_block = + scc_ir_builder_bblock(&ctx->builder, "for_while_body"); + scc_ir_bblock_ref_t exit_block = + scc_ir_builder_bblock(&ctx->builder, "for_while_exit"); + break; + } + + // SCC_AST_STMT_SWITCH, // switch 语句 + // SCC_AST_STMT_CASE, // case 语句 + // SCC_AST_STMT_DEFAULT, // default 语句 + // SCC_AST_STMT_BREAK, // break 语句 + // SCC_AST_STMT_CONTINUE, // continue 语句 + case SCC_AST_STMT_RETURN: { + if (stmt->return_stmt.expr) { + scc_ir_node_ref_t ret_val_node = + scc_ast2ir_expr(ctx, stmt->return_stmt.expr); + scc_ir_builder_ret(&ctx->builder, ret_val_node); + } else { + scc_ir_builder_ret_void(&ctx->builder); + } + break; + } + // SCC_AST_STMT_GOTO, // goto 语句 + // SCC_AST_STMT_LABEL, // 标签语句 + default: + LOG_FATAL("Unsupported statement type: %d", stmt->base.type); + break; + } +} + +/** + * @brief + * + * @param ctx + * @param decl + */ +void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { + if (ctx == null || decl == null) { + LOG_ERROR("Invalid argument"); + return; + } + + switch (decl->base.type) { + case SCC_AST_DECL_VAR: { + // 转换类型 + scc_ir_type_ref_t ir_type = scc_ast2ir_type(ctx, decl->var.type); + + // 创建分配节点 + scc_ir_node_ref_t alloc_val_node = + scc_ir_builder_alloca(&ctx->builder, ir_type, decl->name); + + // 如果有初始化表达式 + if (!decl->var.init) { + break; + } + scc_ir_node_ref_t init_val_node = scc_ast2ir_expr(ctx, decl->var.init); + scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node); + break; + } + + case SCC_AST_DECL_FUNC: { + // TODO params name + scc_ir_type_ref_t func_type = scc_ast2ir_type(ctx, decl->func.type); + if (decl->func.body == null) { + // function decl + break; + } + scc_ir_builder_begin_func(&ctx->builder, decl->name, func_type, null); + scc_ir_builder_begin_bblock(&ctx->builder, "entry"); + scc_ast2ir_stmt(ctx, decl->func.body); + scc_ir_builder_end_bblock(&ctx->builder); + scc_ir_builder_end_func(&ctx->builder); + break; + } + + case SCC_AST_DECL_LIST: { + scc_vec_foreach(decl->list.vars, i) { + scc_ast_decl_t *sub_decl = scc_vec_at(decl->list.vars, i); + scc_ast2ir_decl(ctx, sub_decl); + } + break; + } + case SCC_AST_DECL_PARAM: { + break; + } + case SCC_AST_DECL_STRUCT: + break; + case SCC_AST_DECL_UNION: + break; + + case SCC_AST_DECL_ENUM: + case SCC_AST_DECL_TYPEDEF: + break; + + default: + LOG_FATAL("Unsupported declaration type: %d", decl->base.type); + break; + } +} + +void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, + scc_ast_translation_unit_t *tu) { + Assert(ctx != null && tu != null); + + scc_vec_foreach(tu->declarations, i) { + scc_ast_decl_t *decl = scc_vec_at(tu->declarations, i); + scc_ast2ir_decl(ctx, decl); + } +} + +static u32 scc_hash_node(const void *key) { return (u32)(usize)key; } +static int scc_cmp_node(const void *key1, const void *key2) { + return key1 == key2; +} + +void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi) { + Assert(ctx != null); + ctx->abi = abi; + scc_ir_builder_init(&ctx->builder); + + scc_hashtable_init(&ctx->node2ir, scc_hash_node, scc_cmp_node); +} diff --git a/libs/ast2ir/tests/test_ast2ir_unit.c b/libs/ast2ir/tests/test_ast2ir_unit.c index e69de29..673e532 100644 --- a/libs/ast2ir/tests/test_ast2ir_unit.c +++ b/libs/ast2ir/tests/test_ast2ir_unit.c @@ -0,0 +1,14 @@ +#include +#include + +void test_type(void) {} + +void test_expr(void) {} + +void test_stmt(void) {} + +void test_decl(void) {} + +TEST_LIST = { + +}; diff --git a/libs/ir/include/ir_builder.h b/libs/ir/include/ir_builder.h index dfcab6d..a788cf9 100644 --- a/libs/ir/include/ir_builder.h +++ b/libs/ir/include/ir_builder.h @@ -56,6 +56,15 @@ void scc_ir_builder_end_func(scc_ir_builder_t *builder); */ scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder); +/** + * @brief 创建一个新的基本块,并自动添加到当前函数中,但不改变当前块。 + * @param builder IR构建器 + * @param label 基本块标签(可为 NULL,自动生成) + * @return 新基本块的引用 + */ +scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder, + const char *label); + /** * @brief 开始构建新的基本块 * @param label 基本块标签(可为NULL,自动生成) diff --git a/libs/ir/include/ir_def.h b/libs/ir/include/ir_def.h index aae1d0a..2127c2c 100644 --- a/libs/ir/include/ir_def.h +++ b/libs/ir/include/ir_def.h @@ -52,8 +52,8 @@ typedef enum scc_ir_type_tag { struct scc_ir_type { scc_ir_type_tag_t tag; - // int size; // 字节大小 - // int align; // 对齐要求 + int size; // 字节大小 + int align; // 对齐要求 union { struct { scc_ir_type_ref_t base; @@ -85,6 +85,8 @@ struct scc_ir_func { typedef enum scc_ir_node_tag { SCC_IR_NODE_NULL, SCC_IR_NODE_CONST_INT, + SCC_IR_NODE_CONST_UINT, + SCC_IR_NODE_CONST_FLOAT, SCC_IR_NODE_CONV, ///< 类型转换 SCC_IR_NODE_FUNC_ARG_REF, ///< 函数参数引用 SCC_IR_NODE_BLOCK_ARG_REF, ///< 基本块参数引用 diff --git a/libs/ir/src/ir_builder.c b/libs/ir/src/ir_builder.c index f1e6b3f..810d175 100644 --- a/libs/ir/src/ir_builder.c +++ b/libs/ir/src/ir_builder.c @@ -80,8 +80,8 @@ scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder) { return builder->current_func; } -scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder, - const char *label) { +scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder, + const char *label) { scc_ir_bblock_t bblock = {0}; if (label) { @@ -100,16 +100,22 @@ scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder, scc_ir_bblock_ref_t bblock_ref = scc_ir_ctx_new_bblock(&builder->ctx, &bblock); - builder->current_bblock = bblock_ref; + return bblock_ref; +} + +scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder, + const char *label) { + + builder->current_bblock = scc_ir_builder_bblock(builder, label); // 将基本块添加到当前函数 scc_ir_func_t *current_func = scc_ir_ctx_get_func(&builder->ctx, builder->current_func); if (current_func) { - scc_vec_push(current_func->bblocks, bblock_ref); + scc_vec_push(current_func->bblocks, builder->current_bblock); } - return bblock_ref; + return builder->current_bblock; } void scc_ir_builder_end_bblock(scc_ir_builder_t *builder) { @@ -152,13 +158,13 @@ scc_ir_node_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder, } scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder, - scc_ir_node_ref_t ptr) { + scc_ir_node_ref_t target) { scc_ir_node_t load_node = {0}; load_node.tag = SCC_IR_NODE_LOAD; - load_node.data.load.target = ptr; + load_node.data.load.target = target; // 设置类型为指针指向的类型 - scc_ir_node_t *ptr_node = scc_ir_ctx_get_node(&builder->ctx, ptr); + scc_ir_node_t *ptr_node = scc_ir_ctx_get_node(&builder->ctx, target); if (ptr_node) { scc_ir_type_t *ptr_type = scc_ir_ctx_get_type(&builder->ctx, ptr_node->type); @@ -176,11 +182,11 @@ scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder, } scc_ir_node_ref_t scc_ir_builder_store(scc_ir_builder_t *builder, - scc_ir_node_ref_t ptr, + scc_ir_node_ref_t target, scc_ir_node_ref_t value) { scc_ir_node_t store_node = {0}; store_node.tag = SCC_IR_NODE_STORE; - store_node.data.store.target = ptr; + store_node.data.store.target = target; store_node.data.store.value = value; scc_ir_node_ref_t node_ref = @@ -193,15 +199,15 @@ scc_ir_node_ref_t scc_ir_builder_store(scc_ir_builder_t *builder, } scc_ir_node_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder, - scc_ir_node_ref_t ptr, + scc_ir_node_ref_t target, scc_ir_node_ref_t index) { scc_ir_node_t get_ptr_node = {0}; get_ptr_node.tag = SCC_IR_NODE_GET_PTR; - get_ptr_node.data.get_ptr.src_addr = ptr; + get_ptr_node.data.get_ptr.src_addr = target; get_ptr_node.data.get_ptr.index = index; // 类型应与源地址相同(都是指针) - scc_ir_node_t *src_node = scc_ir_ctx_get_node(&builder->ctx, ptr); + scc_ir_node_t *src_node = scc_ir_ctx_get_node(&builder->ctx, target); if (src_node) { get_ptr_node.type = src_node->type; } diff --git a/libs/parser/include/scc_parser.h b/libs/parser/include/scc_parser.h index 5c5d7f4..cb1ce8d 100644 --- a/libs/parser/include/scc_parser.h +++ b/libs/parser/include/scc_parser.h @@ -87,6 +87,20 @@ static inline void scc_parse_decl_sema(scc_parser_t *parser, decl); } +static inline void scc_parse_expr_sema(scc_parser_t *parser, + scc_ast_expr_t *expr) { + parser->sema_callbacks.on_expr(parser->sema_callbacks.context, + expr ? expr->base.type : SCC_AST_UNKNOWN, + expr); +} + +static inline void scc_parse_stmt_sema(scc_parser_t *parser, + scc_ast_stmt_t *stmt) { + parser->sema_callbacks.on_stmt(parser->sema_callbacks.context, + stmt ? stmt->base.type : SCC_AST_UNKNOWN, + stmt); +} + static inline void scc_parse_type_sema(scc_parser_t *parser, scc_ast_type_t *type) { parser->sema_callbacks.on_type(parser->sema_callbacks.context, diff --git a/libs/parser/src/parse_decl.c b/libs/parser/src/parse_decl.c index 1f5e1fd..e3a080f 100644 --- a/libs/parser/src/parse_decl.c +++ b/libs/parser/src/parse_decl.c @@ -182,7 +182,9 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, init = scc_parse_assignment_expression(parser); return init; } - scc_parser_next_consume(parser, null); + scc_parser_next_consume(parser, &tok); + scc_pos_t pos = tok.loc; + scc_lexer_tok_drop(&tok); init = scc_malloc(sizeof(scc_ast_expr_t)); Assert(init != null); @@ -202,8 +204,8 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, scc_parser_next_consume(parser, &tok); lhs = scc_malloc(sizeof(scc_ast_expr_t)); Assert(lhs != null); - scc_ast_expr_member_init(lhs, ptr, - scc_cstring_as_cstr(&tok.lexeme)); + scc_ast_expr_member_init( + lhs, ptr, scc_cstring_as_cstr(&tok.lexeme), tok.loc); if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { ptr = lhs; continue; @@ -230,7 +232,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, } lhs = scc_malloc(sizeof(scc_ast_expr_t)); Assert(lhs != null); - scc_ast_expr_array_subscript_init(lhs, ptr, idx); + scc_ast_expr_array_subscript_init(lhs, ptr, idx, tok_ptr->loc); if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { ptr = lhs; continue; @@ -253,7 +255,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, scc_vec_push(rhs_exprs, expr); } } - scc_ast_expr_compound_init(init, base, &lhs_exprs, &rhs_exprs); + scc_ast_expr_compound_init(init, base, &lhs_exprs, &rhs_exprs, pos); return init; } @@ -283,10 +285,14 @@ CONTINUE: scc_parser_next_consume(parser, null); // TODO maybe memory leak scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t)); - scc_ast_expr_lvalue_init(lvalue, decl->var.type); + 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) { + parser->sema_callbacks.on_decl(parser->sema_callbacks.context, + scc_ast_decl_t_BEGIN, null); scc_ast_stmt_t *body = scc_parse_statement(parser); + parser->sema_callbacks.on_decl(parser->sema_callbacks.context, + scc_ast_decl_t_END, null); Assert(decl->base.type == SCC_AST_DECL_FUNC); decl->func.body = body; Assert(decl->func.type != null); @@ -305,10 +311,12 @@ CONTINUE: if (decl_list) { scc_vec_foreach(decl_list_vec, i) { decl = scc_vec_at(decl_list_vec, i); - scc_ast_decl_typedef_init(decl, decl->name, decl->var.type); + scc_ast_decl_typedef_init(decl, decl->name, decl->var.type, + decl->base.loc); } } else { - scc_ast_decl_typedef_init(decl, decl->name, decl->var.type); + scc_ast_decl_typedef_init(decl, decl->name, decl->var.type, + decl->base.loc); } } if (decl_list != null) { @@ -316,7 +324,9 @@ CONTINUE: decl = scc_vec_at(decl_list_vec, i); scc_parse_decl_sema(parser, decl); } - scc_ast_decl_list_init(decl_list, &decl_list_vec); + // FIXME + scc_ast_decl_list_init(decl_list, &decl_list_vec, + scc_vec_at(decl_list_vec, 0)->base.loc); decl = decl_list; } else { scc_parse_decl_sema(parser, decl); diff --git a/libs/parser/src/parse_expr.c b/libs/parser/src/parse_expr.c index e4080b1..01dbe5e 100644 --- a/libs/parser/src/parse_expr.c +++ b/libs/parser/src/parse_expr.c @@ -374,7 +374,8 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser, scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_binary_init(expr, op, left, right); + // FIXME pos + scc_ast_expr_binary_init(expr, op, left, right, left->base.loc); left = expr; } return left; @@ -391,6 +392,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) { const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); if (!tok_ptr) return left; + scc_pos_t pos = tok_ptr->loc; int prec = get_token_precedence(tok_ptr->type); if (prec == PREC_ASSIGNMENT && is_binary_operator(tok_ptr->type)) { @@ -411,7 +413,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) { scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_binary_init(expr, op, left, right); + scc_ast_expr_binary_init(expr, op, left, right, pos); left = expr; } return left; @@ -425,6 +427,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) { return null; const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); + scc_pos_t pos = tok_ptr->loc; if (tok_ptr && tok_ptr->type == SCC_TOK_COND) { // 消耗 '?' scc_lexer_tok_t q_tok; @@ -456,7 +459,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) { scc_ast_expr_t *cond = scc_malloc(sizeof(scc_ast_expr_t)); Assert(cond != null); - scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr); + scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr, pos); cond_expr = cond; } return cond_expr; @@ -480,13 +483,15 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) { if (!operand) { // FIXME postfix-expression scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); - scc_ast_expr_lvalue_init(expr, type); + // 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)); Assert(expr != null); - scc_ast_expr_cast_init(expr, type, operand); + // FIXME pos + scc_ast_expr_cast_init(expr, type, operand, type->base.loc); return expr; } else { // 不是类型转换,回退 @@ -538,6 +543,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) { if (!scc_parser_next_consume(parser, &tok)) return null; scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true); + scc_pos_t pos = tok.loc; scc_lexer_tok_drop(&tok); // 一元运算符右结合,递归调用 parse_unary_expression @@ -556,7 +562,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) { scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_unary_init(expr, op, operand); + scc_ast_expr_unary_init(expr, op, operand, pos); return expr; } case SCC_TOK_SIZEOF: @@ -573,6 +579,7 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) { tok_ptr.type != SCC_TOK_SIZEOF) { return null; } + scc_pos_t pos = tok_ptr.loc; scc_lexer_tok_drop(&tok_ptr); const scc_lexer_tok_t *next = scc_parser_peek(parser); @@ -599,14 +606,14 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) { } Assert(type_name != null); - scc_ast_expr_sizeof_init(expr, type_name, null); + scc_ast_expr_sizeof_init(expr, type_name, null, pos); return expr; } next: // 尝试解析 sizeof unary-expression scc_ast_expr_t *operand = parse_unary_expression(parser); if (operand != null) { - scc_ast_expr_sizeof_init(expr, null, operand); + scc_ast_expr_sizeof_init(expr, null, operand, pos); return expr; } @@ -618,11 +625,14 @@ next: static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { scc_ast_expr_t *left = parse_primary_expression(parser); const scc_lexer_tok_t *tok_ptr = null; + scc_pos_t pos = scc_pos_create(); if (!left) { tok_ptr = scc_parser_peek(parser); if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN)) { return null; } + pos = tok_ptr->loc; + scc_parser_store(parser); scc_parser_next(parser); scc_ast_type_t *type = scc_parse_type_name(parser); @@ -635,7 +645,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'"); } scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); - scc_ast_expr_lvalue_init(expr, type); + scc_ast_expr_lvalue_init(expr, type, pos); left = scc_parse_initializer(parser, expr); return left; } @@ -650,6 +660,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { { if (!scc_parser_next_consume(parser, null)) return left; + pos = left->base.loc; scc_ast_expr_t *index = scc_parse_expression(parser); if (!index) { @@ -664,7 +675,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { } scc_ast_expr_t *subscript = scc_malloc(sizeof(scc_ast_expr_t)); Assert(subscript != null); - scc_ast_expr_array_subscript_init(subscript, left, index); + scc_ast_expr_array_subscript_init(subscript, left, index, pos); left = subscript; break; } @@ -672,6 +683,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { { if (!scc_parser_next_consume(parser, null)) return left; + pos = left->base.loc; scc_ast_expr_vec_t args; scc_vec_init(args); @@ -700,7 +712,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { } scc_ast_expr_t *call = scc_malloc(sizeof(scc_ast_expr_t)); Assert(call != null); - scc_ast_expr_call_init(call, left, &args); + scc_ast_expr_call_init(call, left, &args, pos); left = call; break; } @@ -723,9 +735,9 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t)); Assert(member != null); if (op_tok.type == SCC_TOK_DOT) { - scc_ast_expr_member_init(member, left, name); + scc_ast_expr_member_init(member, left, name, ident_tok.loc); } else { - scc_ast_expr_ptr_member_init(member, left, name); + scc_ast_expr_ptr_member_init(member, left, name, ident_tok.loc); } scc_lexer_tok_drop(&op_tok); @@ -739,10 +751,10 @@ 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_lexer_tok_drop(&op_tok); scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_unary_init(expr, op, left); + scc_ast_expr_unary_init(expr, op, left, op_tok.loc); + scc_lexer_tok_drop(&op_tok); left = expr; break; } @@ -776,7 +788,8 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return null; expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_identifier_init(expr, scc_cstring_as_cstr(&tok.lexeme)); + scc_ast_expr_identifier_init(expr, scc_cstring_as_cstr(&tok.lexeme), + tok.loc); return expr; } case SCC_TOK_INT_LITERAL: { @@ -785,7 +798,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); scc_ast_expr_literal_int_init(expr, scc_cstring_as_cstr(&tok.lexeme), - false); + false, tok.loc); return expr; } case SCC_TOK_FLOAT_LITERAL: { @@ -794,7 +807,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); scc_ast_expr_literal_float_init(expr, scc_cstring_as_cstr(&tok.lexeme), - false); + false, tok.loc); return expr; } case SCC_TOK_CHAR_LITERAL: { @@ -803,7 +816,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); scc_ast_expr_literal_char_init(expr, scc_cstring_as_cstr(&tok.lexeme), - false); + false, tok.loc); return expr; } case SCC_TOK_STRING_LITERAL: { @@ -825,8 +838,9 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); + // FIXME loc scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string), - true); + true, tok.loc); return expr; } case SCC_TOK_L_PAREN: @@ -847,7 +861,12 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) { if (!left) return null; - while (scc_parser_consume_if(parser, SCC_TOK_COMMA)) { + const scc_lexer_tok_t *tok_ptr = null; + while (1) { + tok_ptr = scc_parser_peek(parser); + if (tok_ptr == null || tok_ptr->type != SCC_TOK_COMMA) { + break; + } scc_ast_expr_t *right = scc_parse_assignment_expression(parser); if (!right) { parser_sync(parser); @@ -855,7 +874,8 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) { } scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right); + scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right, + tok_ptr->loc); left = expr; } return left; diff --git a/libs/parser/src/parse_stmt.c b/libs/parser/src/parse_stmt.c index 48b0572..76eb060 100644 --- a/libs/parser/src/parse_stmt.c +++ b/libs/parser/src/parse_stmt.c @@ -73,7 +73,8 @@ static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) { return ret; } -static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) { +static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser, + scc_pos_t pos) { scc_lexer_tok_t tok = {0}; if (!scc_parser_next_consume(parser, &tok)) { return null; @@ -91,11 +92,13 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) { scc_ast_stmt_t *stmt = ast_stmt_alloc(); Assert(stmt != null); - scc_ast_stmt_label_init(stmt, scc_cstring_as_cstr(&tok.lexeme), statement); + scc_ast_stmt_label_init(stmt, scc_cstring_as_cstr(&tok.lexeme), statement, + pos); return stmt; } -static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) { +static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser, + scc_pos_t pos) { if (!scc_parser_consume_if(parser, SCC_TOK_CASE)) { return null; } @@ -120,11 +123,12 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) { } scc_ast_stmt_t *stmt = ast_stmt_alloc(); - scc_ast_stmt_case_init(stmt, expr, statement); + scc_ast_stmt_case_init(stmt, expr, statement, pos); return stmt; } -static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) { +static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser, + scc_pos_t pos) { if (!scc_parser_consume_if(parser, SCC_TOK_DEFAULT)) { return null; } @@ -141,17 +145,20 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) { } scc_ast_stmt_t *stmt = ast_stmt_alloc(); - scc_ast_stmt_default_init(stmt, statement); + scc_ast_stmt_default_init(stmt, statement, pos); return stmt; } -static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) { +static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser, + scc_pos_t pos) { if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) { return null; } scc_ast_block_item_vec_t block_items; scc_vec_init(block_items); + parser->sema_callbacks.on_stmt(parser->sema_callbacks.context, + scc_ast_stmt_t_BEGIN, null); while (!scc_parser_consume_if(parser, SCC_TOK_R_BRACE)) { /// TODO // scc_parse_is_decl(); @@ -168,13 +175,15 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) { } scc_vec_push(block_items, ret); } + parser->sema_callbacks.on_stmt(parser->sema_callbacks.context, + scc_ast_stmt_t_END, null); scc_ast_stmt_t *stmt = ast_stmt_alloc(); - scc_ast_stmt_compound_init(stmt, &block_items); + scc_ast_stmt_compound_init(stmt, &block_items, pos); return stmt; } -static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser) { +static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) { if (!scc_parser_consume_if(parser, SCC_TOK_IF)) { return null; } @@ -190,11 +199,12 @@ static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser) { } scc_ast_stmt_t *stmt = ast_stmt_alloc(); - scc_ast_stmt_if_init(stmt, expression, statement, opt_else); + scc_ast_stmt_if_init(stmt, expression, statement, opt_else, pos); return stmt; } -static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser) { +static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser, + scc_pos_t pos) { if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) { return null; } @@ -203,11 +213,12 @@ static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser) { scc_ast_stmt_t *statement = scc_parse_statement(parser); scc_ast_stmt_t *stmt = ast_stmt_alloc(); - scc_ast_stmt_switch_init(stmt, expression, statement); + scc_ast_stmt_switch_init(stmt, expression, statement, pos); return stmt; } -static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser) { +static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser, + scc_pos_t pos) { if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) { return null; } @@ -216,11 +227,12 @@ static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser) { scc_ast_stmt_t *statement = scc_parse_statement(parser); scc_ast_stmt_t *stmt = ast_stmt_alloc(); - scc_ast_stmt_while_init(stmt, expression, statement); + scc_ast_stmt_while_init(stmt, expression, statement, pos); return stmt; } -static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser) { +static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser, + scc_pos_t pos) { if (!scc_parser_consume_if(parser, SCC_TOK_DO)) { return null; } @@ -237,11 +249,12 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser) { scc_ast_expr_t *expression = ast_parse_paren_expression(parser); scc_ast_stmt_t *stmt = ast_stmt_alloc(); - scc_ast_stmt_do_while_init(stmt, expression, statement); + scc_ast_stmt_do_while_init(stmt, expression, statement, pos); return stmt; } -static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) { +static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser, + scc_pos_t pos) { if (!scc_parser_consume_if(parser, SCC_TOK_FOR)) { return null; } @@ -288,27 +301,28 @@ 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_for_init(stmt, init, cond, incr, body); + 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) { +static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser, + scc_pos_t pos) { scc_ast_stmt_t *stmt = ast_stmt_alloc(); if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) { scc_lexer_tok_t tok = {0}; if (scc_parser_next_consume(parser, &tok)) { - scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme)); + scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme), pos); } else { SCC_ERROR(scc_parser_got_current_pos(parser), "Expected label after goto."); } } else if (scc_parser_consume_if(parser, SCC_TOK_CONTINUE)) { - scc_ast_stmt_continue_init(stmt); + scc_ast_stmt_continue_init(stmt, pos); } else if (scc_parser_consume_if(parser, SCC_TOK_BREAK)) { - scc_ast_stmt_break_init(stmt); + scc_ast_stmt_break_init(stmt, pos); } else if (scc_parser_consume_if(parser, SCC_TOK_RETURN)) { - scc_ast_stmt_return_init(stmt, scc_parse_expression(parser)); + scc_ast_stmt_return_init(stmt, scc_parse_expression(parser), pos); } else { UNREACHABLE(); } @@ -320,11 +334,12 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) { return stmt; } -static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) { +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_expr_init(stmt, null); + scc_ast_stmt_expr_init(stmt, null, pos); return stmt; } @@ -334,7 +349,7 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) { } scc_ast_stmt_t *stmt = ast_stmt_alloc(); - scc_ast_stmt_expr_init(stmt, expr); + scc_ast_stmt_expr_init(stmt, expr, pos); if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { SCC_ERROR(scc_parser_got_current_pos(parser), @@ -350,6 +365,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) { if (!tok_ref) { return null; } + scc_pos_t pos = tok_ref->loc; switch (tok_ref->type) { /* (6.8.1) @@ -366,14 +382,14 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) { break; } scc_parser_reset(parser); - stmt = parse_label_statement(parser); + stmt = parse_label_statement(parser, pos); goto RETURN; case SCC_TOK_CASE: { - stmt = parse_case_statement(parser); + stmt = parse_case_statement(parser, pos); goto RETURN; } case SCC_TOK_DEFAULT: - stmt = parse_default_statement(parser); + stmt = parse_default_statement(parser, pos); goto RETURN; /* (6.8.2) @@ -389,7 +405,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) { statement */ case SCC_TOK_L_BRACE: - stmt = parse_compound_statement(parser); + stmt = parse_compound_statement(parser, pos); goto RETURN; /* (6.8.4) @@ -399,10 +415,10 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) { switch ( expression ) statement */ case SCC_TOK_IF: - stmt = parse_if_statement(parser); + stmt = parse_if_statement(parser, pos); goto RETURN; case SCC_TOK_SWITCH: - stmt = parse_switch_statement(parser); + stmt = parse_switch_statement(parser, pos); goto RETURN; /* (6.8.5) @@ -415,13 +431,13 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) { statement */ case SCC_TOK_WHILE: - stmt = parse_while_statement(parser); + stmt = parse_while_statement(parser, pos); goto RETURN; case SCC_TOK_DO: - stmt = parse_do_while_statement(parser); + stmt = parse_do_while_statement(parser, pos); goto RETURN; case SCC_TOK_FOR: - stmt = parse_for_statement(parser); + stmt = parse_for_statement(parser, pos); goto RETURN; /* (6.8.6) @@ -435,7 +451,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) { case SCC_TOK_CONTINUE: case SCC_TOK_BREAK: case SCC_TOK_RETURN: - stmt = parse_jump_statement(parser); + stmt = parse_jump_statement(parser, pos); goto RETURN; default: break; @@ -445,12 +461,9 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) { expression-statement: expression(opt) ; */ - stmt = parse_expression_statement(parser); + stmt = parse_expression_statement(parser, pos); RETURN: scc_parser_reset(parser); - if (stmt) { - parser->sema_callbacks.on_stmt(parser->sema_callbacks.context, - stmt->base.type, stmt); - } + scc_parse_stmt_sema(parser, stmt); return stmt; } diff --git a/libs/parser/src/parse_type.c b/libs/parser/src/parse_type.c index 63cb362..c671027 100644 --- a/libs/parser/src/parse_type.c +++ b/libs/parser/src/parse_type.c @@ -467,7 +467,8 @@ 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) { +static scc_ast_type_t *build_type_from_info(type_spec_info_t *info, + scc_pos_t pos) { // 如果有用户定义类型,直接返回(注意可能需要复制或共享) if (info->user_type) { return info->user_type; // 假设 parse_struct_union_enum 已分配好节点 @@ -528,7 +529,7 @@ 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); + _scc_ast_type_builtin_init(type, builtin, pos); // 注意:限定符(const, volatile)不应在此处处理,应由上层函数负责 return type; } @@ -564,9 +565,12 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, declarator(opt) : constant-expression */ // FIXME check struct/union - scc_parser_next_consume(parser, null); - const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); scc_lexer_tok_t tok; + scc_parser_next_consume(parser, &tok); + scc_pos_t pos = tok.loc; + scc_lexer_tok_drop(&tok); + + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); const char *name = null; scc_ast_decl_t *decl = null; scc_ast_decl_vec_t member; @@ -614,9 +618,9 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, decl = scc_malloc(sizeof(scc_ast_decl_t)); Assert(decl != null); if (type_kind == SCC_AST_TYPE_STRUCT) { - scc_ast_decl_struct_init(decl, name, &member); + scc_ast_decl_struct_init(decl, name, &member, pos); } else { - scc_ast_decl_union_init(decl, name, &member); + scc_ast_decl_union_init(decl, name, &member, pos); } scc_parse_decl_sema(parser, decl); } else { @@ -629,7 +633,7 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, } scc_ast_type_t *type = ast_type_alloc(); - _scc_ast_type_record_init(type, type_kind, name, decl); + _scc_ast_type_record_init(type, type_kind, name, decl, pos); return type; } @@ -649,12 +653,16 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { enumeration-constant enumeration-constant = constant-expression */ - if (!scc_parser_consume_if(parser, SCC_TOK_ENUM)) { + 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 null; } + scc_lexer_tok_drop(&tok); + const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); - scc_lexer_tok_t tok; const char *name = null; scc_ast_decl_t *decl = null; scc_ast_expr_vec_t member; @@ -697,7 +705,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { } decl = scc_malloc(sizeof(scc_ast_decl_t)); Assert(decl != null); - scc_ast_decl_enum_init(decl, name, &member); + scc_ast_decl_enum_init(decl, name, &member, pos); scc_parse_decl_sema(parser, decl); } else { if (name == null) { @@ -709,7 +717,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { } scc_ast_type_t *type = ast_type_alloc(); - scc_ast_type_enum_init(type, name, decl); + scc_ast_type_enum_init(type, name, decl, pos); return type; } @@ -719,6 +727,10 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) { return null; const scc_lexer_tok_t *tok_ptr = null; tok_ptr = scc_parser_peek(parser); + if (tok_ptr == null) { + return null; + } + scc_pos_t pos = tok_ptr->loc; switch (tok_ptr->type) { case SCC_TOK_STRUCT: @@ -840,7 +852,7 @@ done: if (!check_type_combinations(parser, &info)) { return null; } - return build_type_from_info(&info); + return build_type_from_info(&info, pos); duplicate_error: SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier"); return null; @@ -858,6 +870,7 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser, if (tok_ptr == null || tok_ptr->type != SCC_TOK_MUL) { return pointee; } + scc_pos_t pos = tok_ptr->loc; scc_parser_next_consume(parser, null); scc_ast_type_t *pointer = ast_type_alloc(); @@ -866,7 +879,7 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser, *delay_pointee_ptr = pointer; pointee = pointer; } - scc_ast_type_pointer_init(pointer, pointee); + scc_ast_type_pointer_init(pointer, pointee, pos); pointer->quals = parse_type_qualifier_list(parser, pointer->quals); return parse_pointer(parser, pointer, delay_pointee_ptr); @@ -887,6 +900,7 @@ static void parse_parameter_type_list(scc_parser_t *parser, */ scc_ast_decl_t *param = null; scc_ast_decl_t *decl = null; + const scc_lexer_tok_t *tok_ptr = null; while (1) { // FIXME scc_ast_type_t *type = scc_parse_declaration_specifiers(parser); @@ -904,14 +918,20 @@ static void parse_parameter_type_list(scc_parser_t *parser, param->base.type = SCC_AST_DECL_PARAM; scc_vec_push(*params, param); - if (!scc_parser_consume_if(parser, SCC_TOK_COMMA)) { + + tok_ptr = scc_parser_peek(parser); + if (tok_ptr->type != SCC_TOK_COMMA) { break; } - if (scc_parser_consume_if(parser, SCC_TOK_ELLIPSIS)) { + + scc_parser_next_consume(parser, null); + tok_ptr = scc_parser_peek(parser); + if (tok_ptr->type == SCC_TOK_ELLIPSIS) { param = scc_malloc(sizeof(scc_ast_decl_t)); Assert(param != null); // FIXME - scc_ast_decl_param_init(param, &scc_ast_builtin_type_va_list, null); + scc_ast_decl_param_init(param, &scc_ast_builtin_type_va_list, null, + tok_ptr->loc); scc_vec_push(*params, param); break; } @@ -1041,7 +1061,8 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, scc_ast_decl_vec_t params; parse_function_parameters(parser, ¶ms); ret = ast_type_alloc(); - scc_ast_type_function_init(ret, base, ¶ms); + // FIXME + scc_ast_type_function_init(ret, base, ¶ms, base->base.loc); return parse_direct_declarator(parser, ret, delay_pointee_ptr, tok_ident); } else { @@ -1063,7 +1084,8 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base, scc_ast_type_t *ret = ast_type_alloc(); base = parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident); - scc_ast_type_array_init(ret, base, size); + // FIXME + scc_ast_type_array_init(ret, base, size, base->base.loc); return ret; } else { return base; @@ -1112,7 +1134,8 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, scc_ast_decl_vec_t params; parse_function_parameters(parser, ¶ms); ret = ast_type_alloc(); - scc_ast_type_function_init(ret, base, ¶ms); + // FIXME + scc_ast_type_function_init(ret, base, ¶ms, base->base.loc); return parse_direct_abstract_declarator(parser, ret, delay_pointee_ptr); } else { @@ -1133,7 +1156,8 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base, scc_ast_type_t *ret = ast_type_alloc(); base = parse_direct_abstract_declarator(parser, base, delay_pointee_ptr); - scc_ast_type_array_init(ret, base, size); + // FIXME + scc_ast_type_array_init(ret, base, size, base->base.loc); return ret; } else { return base; @@ -1157,7 +1181,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser, : null; if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) { - scc_ast_decl_func_init(decl, decl_type, name, null); + scc_ast_decl_func_init(decl, decl_type, name, null, decl_name_tok.loc); // TODO using sema to change it if (type->quals.is_inline) { decl_type->quals.is_inline = true; @@ -1165,7 +1189,8 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser, type->quals.is_inline = false; } } else { - scc_ast_decl_unsafe_val_init(decl, decl_type, name, null); + scc_ast_decl_unsafe_val_init(decl, decl_type, name, null, + decl_name_tok.loc); } if (decl_name_tok.type != SCC_TOK_IDENT) { @@ -1175,10 +1200,11 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser, decl = scc_malloc(sizeof(scc_ast_decl_t)); Assert(decl != null); if (decl_type->base.type == SCC_AST_TYPE_STRUCT) { - scc_ast_decl_struct_init(decl, decl_type->record.name, - null); + scc_ast_decl_struct_init(decl, decl_type->record.name, null, + decl_type->base.loc); } else { - scc_ast_decl_union_init(decl, decl_type->record.name, null); + scc_ast_decl_union_init(decl, decl_type->record.name, null, + decl_type->base.loc); } } else { decl = decl_type->record.decl; @@ -1188,14 +1214,16 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser, if (decl_type->enumeration.decl == null) { decl = scc_malloc(sizeof(scc_ast_decl_t)); Assert(decl != null); - scc_ast_decl_enum_init(decl, type->enumeration.name, null); + scc_ast_decl_enum_init(decl, type->enumeration.name, null, + decl_type->base.loc); } else { decl = type->enumeration.decl; scc_free(decl_type); // FIXME } } else { decl = scc_malloc(sizeof(scc_ast_decl_t)); - scc_ast_decl_unsafe_val_init(decl, type, null, null); + scc_ast_decl_unsafe_val_init(decl, type, null, null, + decl_type->base.loc); } } return decl; diff --git a/libs/parser/src/scc_sema.c b/libs/parser/src/scc_sema.c index 12524a0..a4ef18f 100644 --- a/libs/parser/src/scc_sema.c +++ b/libs/parser/src/scc_sema.c @@ -1,3 +1,4 @@ +#include #include #include @@ -10,12 +11,55 @@ static void type_callback(void *context, scc_ast_node_type_t node_type, return; } -static void decl_callback(void *context, scc_ast_node_type_t node_type, +static void expr_callback(void *context, scc_ast_node_type_t node_type, void *node) { + scc_sema_symtab_t *sema_symtab = context; + if (node_type == SCC_AST_UNKNOWN || node == null) { return; } + scc_ast_expr_t *decl = SCC_AST_CAST_TO(scc_ast_expr_t, node); + if (node_type == SCC_AST_EXPR_IDENTIFIER) { + scc_ast_node_t *node = + scc_sema_symtab_lookup_symbol(sema_symtab, decl->identifier.name); + if (node == null) { + SCC_ERROR(decl->base.loc, "Identifier '%s' not found", + decl->identifier.name); + } + } + return; +} + +static void stmt_callback(void *context, scc_ast_node_type_t node_type, + void *node) { scc_sema_symtab_t *sema_symtab = context; + + if (node_type == scc_ast_stmt_t_BEGIN) { + scc_sema_symtab_enter_scope(sema_symtab); + return; + } else if (node_type == scc_ast_stmt_t_END) { + scc_sema_symtab_leave_scope(sema_symtab); + return; + } + if (node_type == SCC_AST_UNKNOWN || node == null) { + return; + } + return; +} + +static void decl_callback(void *context, scc_ast_node_type_t node_type, + void *node) { + scc_sema_symtab_t *sema_symtab = context; + if (node_type == scc_ast_decl_t_BEGIN) { + scc_sema_symtab_enter_scope(sema_symtab); + return; + } else if (node_type == scc_ast_decl_t_END) { + scc_sema_symtab_leave_scope(sema_symtab); + return; + } + if (node_type == SCC_AST_UNKNOWN || node == null) { + return; + } 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)); @@ -24,25 +68,25 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type, return; } if (decl->base.type == SCC_AST_DECL_STRUCT) { - scc_ast_type_struct_init(type, decl->name, decl); + scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc); scc_cstring_t name = scc_cstring_from_cstr("$S_"); scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), &type->base); } else if (decl->base.type == SCC_AST_DECL_UNION) { - scc_ast_type_union_init(type, decl->name, decl); + scc_ast_type_union_init(type, decl->name, decl, decl->base.loc); scc_cstring_t name = scc_cstring_from_cstr("$U_"); scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), &type->base); } else if (decl->base.type == SCC_AST_DECL_ENUM) { - scc_ast_type_enum_init(type, decl->name, decl); + scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc); scc_cstring_t name = scc_cstring_from_cstr("$E_"); scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), &type->base); } else if (decl->base.type == SCC_AST_DECL_TYPEDEF) { - scc_ast_type_typedef_init(type, decl->name, decl); + scc_ast_type_typedef_init(type, decl->name, decl, decl->base.loc); scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); } return; @@ -67,8 +111,8 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) { } callbacks->context = sema_symtab; callbacks->on_decl = decl_callback; - callbacks->on_expr = null; - callbacks->on_stmt = null; + callbacks->on_expr = expr_callback; + callbacks->on_stmt = stmt_callback; callbacks->on_type = type_callback; callbacks->got_type = got_type_callback; diff --git a/libs/parser/tests/test_sema_unit.c b/libs/parser/tests/test_sema_unit.c new file mode 100644 index 0000000..fed92f7 --- /dev/null +++ b/libs/parser/tests/test_sema_unit.c @@ -0,0 +1,5 @@ +#include + +TEST_LIST = { + {NULL, NULL}, +}; \ No newline at end of file diff --git a/libs/target/pe/include/scc_pe_builder.h b/libs/target/pe/include/scc_pe_builder.h index a5445a3..f426a7e 100644 --- a/libs/target/pe/include/scc_pe_builder.h +++ b/libs/target/pe/include/scc_pe_builder.h @@ -69,6 +69,66 @@ scc_pe_section_range scc_pe_reserve_section_header(scc_pe_builder_t *builder, u32 virtual_size, u32 data_size); +static inline scc_pe_section_range +scc_pe_reserve_text_section_header(scc_pe_builder_t *builder, u32 data_size) { + return scc_pe_reserve_section_header( + builder, (BYTE *)".text\0\0", + IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ, + data_size, data_size); +} + +static inline scc_pe_section_range +scc_pe_reserve_data_section_header(scc_pe_builder_t *builder, u32 data_size) { + return scc_pe_reserve_section_header(builder, (BYTE *)".data\0\0", + IMAGE_SCN_CNT_INITIALIZED_DATA | + IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE, + data_size, data_size); +} + +static inline scc_pe_section_range +scc_pe_reserve_rdata_section_header(scc_pe_builder_t *builder, u32 data_size) { + return scc_pe_reserve_section_header(builder, (BYTE *)".rdata\0", + IMAGE_SCN_CNT_INITIALIZED_DATA | + IMAGE_SCN_MEM_READ, + data_size, data_size); +} + +static inline scc_pe_section_range +scc_pe_reserve_bss_section_header(scc_pe_builder_t *builder, u32 data_size) { + return scc_pe_reserve_section_header(builder, (BYTE *)".bss\0\0\0", + IMAGE_SCN_CNT_UNINITIALIZED_DATA | + IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE, + data_size, 0); +} + +static inline scc_pe_section_range +scc_pe_reserve_idata_section_header(scc_pe_builder_t *builder, u32 data_size) { + scc_pe_section_range range = scc_pe_reserve_section_header( + builder, (BYTE *)".idata\0", + IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE, + data_size, data_size); + scc_vec_at(builder->image_data_directory_vec, + IMAGE_DIRECTORY_ENTRY_IMPORT) = (IMAGE_DATA_DIRECTORY){ + .VirtualAddress = range.virual_address, .Size = range.virual_size}; + return range; +} + +static inline scc_pe_section_range +scc_pe_reserve_reloc_section_header(scc_pe_builder_t *builder, u32 data_size) { + scc_pe_section_range range = scc_pe_reserve_section_header( + builder, (BYTE *)".reloc\0\0", + IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_DISCARDABLE, + data_size, data_size); + scc_vec_at(builder->image_data_directory_vec, + IMAGE_DIRECTORY_ENTRY_BASERELOC) = (IMAGE_DATA_DIRECTORY){ + .VirtualAddress = range.virual_address, .Size = range.virual_size}; + return range; +} + void scc_pe_write_header(scc_pe_builder_t *builder, scc_pe_config_t *config); void scc_pe_write_section(scc_pe_builder_t *builder, diff --git a/libs/target/pe/include/scc_pe_def.h b/libs/target/pe/include/scc_pe_def.h index 6d7fb65..56cd72e 100644 --- a/libs/target/pe/include/scc_pe_def.h +++ b/libs/target/pe/include/scc_pe_def.h @@ -15,6 +15,9 @@ * * @bug 可以有更好的方式解决这个问题 */ +#ifdef DUMMYUNIONNAME +#undef DUMMYUNIONNAME +#endif #define DUMMYUNIONNAME DUMMYUNIONNAME // 基本类型定义 diff --git a/libs/target/pe/include/scc_pe_idata.h b/libs/target/pe/include/scc_pe_idata.h index 41500bc..7f3d508 100644 --- a/libs/target/pe/include/scc_pe_idata.h +++ b/libs/target/pe/include/scc_pe_idata.h @@ -10,33 +10,21 @@ typedef struct { scc_pe_buffer_t data; ///< 具体数据 scc_hashtable_t str_map; ///< 符号名称映射到data的idx u32 section_offset; ///< 在idata中的偏移 -} scc_winpe_hnt_builder_t; - -typedef struct { - u32 offset; ///< 相对代码段的偏移地址 - i32 addend; ///< 可选的偏移量的附加值 可选默认为0 - u8 size; ///< 引用的地址的大小 - const char *library_name; ///< 库名称 eg. "Kernel32.dll" - const char *symbol_name; ///< 导入dll的符号名称 eg. "CreateFileW" - u16 ordinal; ///< 符号的序号 eg. 可选 -} scc_winpe_extern_t; -typedef SCC_VEC(scc_winpe_extern_t) scc_winpe_extern_vec_t; +} scc_pe_hnt_builder_t; typedef SCC_VEC(const char *) scc_winpe_name_vec_t; typedef struct { const char *name; scc_winpe_name_vec_t symbol_names; } scc_winpe_idata_lib_t; -typedef SCC_VEC(scc_winpe_idata_lib_t) scc_winpe_idata_lib_vec_t; +typedef SCC_VEC(scc_winpe_idata_lib_t) scc_pe_idata_lib_vec_t; typedef struct { scc_pe_buffer_t buffer; ///< 导入表数据 - scc_winpe_extern_vec_t externs; - scc_hashtable_t externs_set; - scc_winpe_hnt_builder_t hnt_builder; + scc_pe_hnt_builder_t hnt_builder; scc_hashtable_t iat_map; ///< 符号名称映射到idata的虚拟镜像地址 - scc_winpe_idata_lib_vec_t idata_libs; -} scc_winpe_idata_builder_t; + scc_pe_idata_lib_vec_t idata_libs; +} scc_pe_idata_builder_t; /** * @brief PE格式导入表构建器初始化 @@ -45,8 +33,8 @@ typedef struct { * @param builder * @param idata_libs */ -void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder, - scc_winpe_idata_lib_vec_t *idata_libs); +void scc_pe_idata_builder_init(scc_pe_idata_builder_t *builder, + scc_pe_idata_lib_vec_t *idata_libs); /** * @brief 获取导入表占据的大小 @@ -55,7 +43,7 @@ void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder, * @param builder * @return u32 */ -u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder); +u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder); /** * @brief 构造导入表 @@ -64,13 +52,12 @@ u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder); * @param builder * @param idata_range */ -scc_pe_buffer_t scc_pe_construct_idata(scc_winpe_idata_builder_t *builder, +scc_pe_buffer_t scc_pe_construct_idata(scc_pe_idata_builder_t *builder, scc_pe_section_range *idata_range); // RVA Relative Virtual Address -static inline u64 -scc_pe_idata_get_symbol_rva(scc_winpe_idata_builder_t *builder, - const char *symbol_name) { +static inline u64 scc_pe_idata_get_symbol_rva(scc_pe_idata_builder_t *builder, + const char *symbol_name) { return (u64)scc_hashtable_get(&builder->iat_map, symbol_name); } diff --git a/libs/target/pe/include/scc_pe_reloc.h b/libs/target/pe/include/scc_pe_reloc.h new file mode 100644 index 0000000..914f536 --- /dev/null +++ b/libs/target/pe/include/scc_pe_reloc.h @@ -0,0 +1,45 @@ +#ifndef __SCC_PE_RELOC_H__ +#define __SCC_PE_RELOC_H__ + +#include "scc_pe_def.h" + +typedef struct { + u32 offset; ///< 相对代码段的偏移地址 + i32 addend; ///< 可选的偏移量的附加值 可选默认为0 + u8 size; ///< 引用的地址的大小 + const char *library_name; ///< 库名称 eg. "Kernel32.dll" + const char *symbol_name; ///< 导入dll的符号名称 eg. "CreateFileW" + u16 ordinal; ///< 符号的序号 eg. 可选 +} scc_pe_extern_t; +typedef SCC_VEC(scc_pe_extern_t) scc_pe_extern_vec_t; + +typedef struct { + scc_pe_extern_vec_t externs; + scc_hashtable_t externs_set; + +} scc_pe_reloc_builder_t; + +void scc_pe_reloc_builder_init(scc_pe_reloc_builder_t *builder); + +// void scc_pe_reloc_add_item(scc_pe_reloc_builder_t *builder, ); + +/** + * @brief + * @warning + * + * @param builder + * @return u32 + */ +u32 scc_pe_reserve_reloc(scc_pe_reloc_builder_t *builder); + +/** + * @brief + * @warning + * + * @param builder + * @param reloc_range + */ +scc_pe_buffer_t scc_pe_construct_reloc(scc_pe_reloc_builder_t *builder, + scc_pe_section_range *reloc_range); + +#endif /* __SCC_PE_RELOC_H__ */ diff --git a/libs/target/pe/src/scc_pe_idata.c b/libs/target/pe/src/scc_pe_idata.c index 34df2cb..bfac113 100644 --- a/libs/target/pe/src/scc_pe_idata.c +++ b/libs/target/pe/src/scc_pe_idata.c @@ -13,9 +13,9 @@ image_import_descriptor_init(u32 import_lookup_table_rva, u32 name_rva, return iid; }; -static void scc_winpe_hnt_builder_push(scc_winpe_hnt_builder_t *builder, +static void scc_winpe_hnt_builder_push(scc_pe_hnt_builder_t *builder, const char *name, u16 hint); -static void scc_winpe_hnt_builder_init(scc_winpe_hnt_builder_t *builder) { +static void scc_winpe_hnt_builder_init(scc_pe_hnt_builder_t *builder) { scc_vec_init(builder->data); builder->section_offset = 0; scc_hashtable_init(&builder->str_map, @@ -23,7 +23,7 @@ static void scc_winpe_hnt_builder_init(scc_winpe_hnt_builder_t *builder) { (scc_hashtable_equal_func_t)scc_strcmp); } -static void scc_winpe_hnt_builder_push(scc_winpe_hnt_builder_t *builder, +static void scc_winpe_hnt_builder_push(scc_pe_hnt_builder_t *builder, const char *name, u16 hint) { ///< 可选哈希表去重 if (scc_hashtable_get(&builder->str_map, name)) { @@ -49,13 +49,13 @@ static void scc_winpe_hnt_builder_push(scc_winpe_hnt_builder_t *builder, Assert(scc_vec_size(builder->data) % 2 == 0); } -static u64 scc_winpe_hnt_get_offset(scc_winpe_hnt_builder_t *builder, +static u64 scc_winpe_hnt_get_offset(scc_pe_hnt_builder_t *builder, const char *name) { return (u64)scc_hashtable_get(&builder->str_map, name); } -void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder, - scc_winpe_idata_lib_vec_t *idata_libs) { +void scc_pe_idata_builder_init(scc_pe_idata_builder_t *builder, + scc_pe_idata_lib_vec_t *idata_libs) { scc_vec_init(builder->buffer); builder->idata_libs = *idata_libs; @@ -66,7 +66,7 @@ void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder, (scc_hashtable_equal_func_t)scc_strcmp); } -u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder) { +u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder) { u32 idata_size = (scc_vec_size(builder->idata_libs) + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR); @@ -89,7 +89,7 @@ u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder) { return idata_size; } -scc_pe_buffer_t scc_pe_construct_idata(scc_winpe_idata_builder_t *builder, +scc_pe_buffer_t scc_pe_construct_idata(scc_pe_idata_builder_t *builder, scc_pe_section_range *idata_range) { u32 idata_rva = idata_range->virual_address; u32 hnt_offset = builder->hnt_builder.section_offset; diff --git a/libs/target/pe/src/scc_pe_reloc.c b/libs/target/pe/src/scc_pe_reloc.c new file mode 100644 index 0000000..e69de29 diff --git a/libs/target/pe/src/main.c b/libs/target/pe/tests/test_pe_write_idata.c similarity index 75% rename from libs/target/pe/src/main.c rename to libs/target/pe/tests/test_pe_write_idata.c index 763b362..c2e74a9 100644 --- a/libs/target/pe/src/main.c +++ b/libs/target/pe/tests/test_pe_write_idata.c @@ -24,19 +24,14 @@ int main() { scc_pe_builder_t builder = {0}; scc_pe_builder_init(&builder, true, 4096, 512); scc_pe_reserve_header(&builder, 3); - scc_pe_section_range code_range = scc_pe_reserve_section_header( - &builder, (BYTE *)".text\0\0", - IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, - sizeof(code), sizeof(code)); + scc_pe_section_range code_range = + scc_pe_reserve_text_section_header(&builder, sizeof(code)); - scc_pe_section_range data_range = scc_pe_reserve_section_header( - &builder, (BYTE *)".data\0\0", - IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | - IMAGE_SCN_MEM_WRITE, - sizeof(data), sizeof(data)); + scc_pe_section_range data_range = + scc_pe_reserve_data_section_header(&builder, sizeof(data)); - scc_winpe_idata_builder_t idata_builder; - scc_winpe_idata_lib_vec_t idata_libs; + scc_pe_idata_builder_t idata_builder; + scc_pe_idata_lib_vec_t idata_libs; scc_vec_init(idata_libs); scc_winpe_idata_lib_t ucrtbase; ucrtbase.name = "ucrtbase.dll"; @@ -45,14 +40,8 @@ int main() { scc_vec_push(idata_libs, ucrtbase); scc_pe_idata_builder_init(&idata_builder, &idata_libs); u32 idata_size = scc_pe_reserve_idata(&idata_builder); - scc_pe_section_range idata_range = scc_pe_reserve_section_header( - &builder, (BYTE *)".idata\0", - IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | - IMAGE_SCN_MEM_WRITE, - idata_size, idata_size); - scc_vec_at(builder.image_data_directory_vec, IMAGE_DIRECTORY_ENTRY_IMPORT) = - (IMAGE_DATA_DIRECTORY){.VirtualAddress = idata_range.virual_address, - .Size = idata_range.virual_size}; + scc_pe_section_range idata_range = + scc_pe_reserve_idata_section_header(&builder, idata_size); scc_pe_buffer_t idata_buffer = scc_pe_construct_idata(&idata_builder, &idata_range); @@ -97,5 +86,5 @@ int main() { scc_pe_write_section(&builder, &idata_range, scc_vec_unsafe_get_data(idata_buffer), scc_vec_size(idata_buffer)); - scc_pe_dump_to_file(&builder, "hello_world.exe"); + scc_pe_dump_to_file(&builder, __FILE__ "/../pe_write_idata.exe"); } diff --git a/libs/target/pe/tests/test_pe_write_reloc.c b/libs/target/pe/tests/test_pe_write_reloc.c new file mode 100644 index 0000000..dd0c8a7 --- /dev/null +++ b/libs/target/pe/tests/test_pe_write_reloc.c @@ -0,0 +1,2 @@ + +int main(void) { return 0; } \ No newline at end of file diff --git a/libs/target/pe/tests/test_winpe_unit.c b/libs/target/pe/tests/test_winpe_unit.c deleted file mode 100644 index 1616237..0000000 --- a/libs/target/pe/tests/test_winpe_unit.c +++ /dev/null @@ -1,10 +0,0 @@ -#include - -void test_example() { - printf("Test passed!\n"); -} - -int main() { - test_example(); - return 0; -} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..3ed8960 --- /dev/null +++ b/src/config.h @@ -0,0 +1,142 @@ +#ifndef __SCC_CONFIG_H__ +#define __SCC_CONFIG_H__ + +#include + +typedef struct { + const char *input_file; + const char *output_file; + int verbose; + scc_argparse_list_t include_paths; + scc_argparse_list_t define_macros; + cbool emit_lex; + cbool emit_pp; + cbool emit_ast; + cbool emit_ir; +} scc_config_t; + +static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, + scc_argparse_lang_t lang) { + enum { + SCC_HINT_PROG_NAME, + SCC_HINT_DESCRIPTION, + SCC_HINT_OUTPUT_FILE, + SCC_HINT_INPUT_FILE, + SCC_HINT_INCLUDE_PATH, + SCC_HINT_DEFINED_MACRO, + SCC_HINT_VERBOSE, + + SCC_HINT_EMIT_LEX, + SCC_HINT_EMIT_PP, + SCC_HINT_EMIT_AST, + SCC_HINT_EMIT_IR, + }; + static const char *scc_hints_en[] = { + [SCC_HINT_PROG_NAME] = "scc", + [SCC_HINT_DESCRIPTION] = "A simple C compiler", + [SCC_HINT_OUTPUT_FILE] = + "Output file (`-` means standard output stream file)", + [SCC_HINT_INPUT_FILE] = "Input source file", + [SCC_HINT_INCLUDE_PATH] = "Add directory to the include search paths", + [SCC_HINT_DEFINED_MACRO] = "Define a macro", + [SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)", + [SCC_HINT_EMIT_LEX] = "Generate lexer sources tokens and exit", + [SCC_HINT_EMIT_PP] = "Generate preprocessed tokens and exit", + [SCC_HINT_EMIT_AST] = "Generate AST and exit", + [SCC_HINT_EMIT_IR] = "Generate IR and exit", + }; + static const char *scc_hints_zh[] = { + [SCC_HINT_PROG_NAME] = "scc", + [SCC_HINT_DESCRIPTION] = "一个简单的C编译器", + [SCC_HINT_OUTPUT_FILE] = "输出文件(`-`表示标准输出流文件)", + [SCC_HINT_INPUT_FILE] = "输入源文件", + [SCC_HINT_INCLUDE_PATH] = "添加系统头文件到搜索路径", + [SCC_HINT_DEFINED_MACRO] = "定义宏", + [SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)", + [SCC_HINT_EMIT_LEX] = "生成`源代码的词法单元`并退出", + [SCC_HINT_EMIT_PP] = "生成`预处理后的词法单元`并退出", + [SCC_HINT_EMIT_AST] = "生成`抽象语法树`并退出", + [SCC_HINT_EMIT_IR] = "生成`中间代码`并退出", + }; + + const char **scc_hints; + switch (lang) { + case SCC_ARGPARSE_LANG_EN: + scc_hints = scc_hints_en; + break; + case SCC_ARGPARSE_LANG_ZH: + scc_hints = scc_hints_zh; + break; + default: + scc_hints = scc_hints_en; + break; + } + + scc_argparse_init(argparse, scc_hints[SCC_HINT_PROG_NAME], + scc_hints[SCC_HINT_DESCRIPTION]); + argparse->lang = lang; + scc_argparse_cmd_t *root = scc_argparse_get_root(argparse); + + // -o, --output + scc_argparse_opt_t opt_output; + scc_argparse_opt_init(&opt_output, 'o', "output", + scc_hints[SCC_HINT_OUTPUT_FILE]); + scc_argparse_spec_setup_string(&opt_output.spec, &(config->output_file)); + scc_argparse_cmd_add_opt(root, &opt_output); + + // input file (必需) + scc_argparse_arg_t arg_input; + scc_argparse_arg_init(&arg_input, "input", scc_hints[SCC_HINT_INPUT_FILE]); + scc_argparse_spec_setup_string(&arg_input.spec, &(config->input_file)); + scc_argparse_spec_set_required(&arg_input.spec, true); + scc_argparse_cmd_add_arg(root, &arg_input); + + // -I, --include (添加额外的系统头文件搜索路径) + scc_argparse_opt_t opt_include; + scc_argparse_opt_init(&opt_include, 'I', "include", + scc_hints[SCC_HINT_INCLUDE_PATH]); + scc_argparse_spec_setup_list(&opt_include.spec, &(config->include_paths)); + scc_argparse_cmd_add_opt(root, &opt_include); + + // -D, --define (定义宏) + scc_argparse_opt_t opt_define; + scc_argparse_opt_init(&opt_define, 'D', "define", + scc_hints[SCC_HINT_DEFINED_MACRO]); + scc_argparse_spec_setup_list(&opt_define.spec, &(config->define_macros)); + scc_argparse_cmd_add_opt(root, &opt_define); + + // -v, --verbose (计数) + scc_argparse_opt_t opt_verbose; + scc_argparse_opt_init(&opt_verbose, 'V', "verbose", + scc_hints[SCC_HINT_VERBOSE]); + scc_argparse_spec_setup_count(&opt_verbose.spec, &(config->verbose)); + scc_argparse_cmd_add_opt(root, &opt_verbose); + + // --emit-lex + scc_argparse_opt_t opt_lex; + scc_argparse_opt_init(&opt_lex, 0, "emit-lex", + scc_hints[SCC_HINT_EMIT_LEX]); + scc_argparse_spec_setup_bool(&opt_lex.spec, &(config->emit_lex)); + scc_argparse_cmd_add_opt(root, &opt_lex); + + // --emit-pp + scc_argparse_opt_t opt_pp; + scc_argparse_opt_init(&opt_pp, 0, "emit-pp", scc_hints[SCC_HINT_EMIT_PP]); + scc_argparse_spec_setup_bool(&opt_pp.spec, &(config->emit_pp)); + scc_argparse_cmd_add_opt(root, &opt_pp); + + // -T, --emit-ast + scc_argparse_opt_t opt_ast; + scc_argparse_opt_init(&opt_ast, 'T', "emit-ast", + scc_hints[SCC_HINT_EMIT_AST]); + scc_argparse_spec_setup_bool(&opt_ast.spec, &(config->emit_ast)); + scc_argparse_cmd_add_opt(root, &opt_ast); + + // -R, --emit-ir + scc_argparse_opt_t opt_ir; + scc_argparse_opt_init(&opt_ir, 'R', "emit-ir", scc_hints[SCC_HINT_EMIT_IR]); + scc_argparse_spec_setup_bool(&opt_ir.spec, &(config->emit_ir)); + scc_argparse_cmd_add_opt(root, &opt_ir); +} + +#endif /* __SCC_CONFIG_H___ */ diff --git a/src/main.c b/src/main.c index 02b4364..063de03 100644 --- a/src/main.c +++ b/src/main.c @@ -7,130 +7,7 @@ #include #include -typedef struct { - const char *input_file; - const char *output_file; - int verbose; - scc_argparse_list_t include_paths; - cbool emit_lex; - cbool emit_pp; - cbool emit_ast; - cbool emit_ir; -} scc_config_t; - -static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, - scc_argparse_lang_t lang) { - enum { - SCC_HINT_PROG_NAME, - SCC_HINT_DESCRIPTION, - SCC_HINT_OUTPUT_FILE, - SCC_HINT_INPUT_FILE, - SCC_HINT_INCLUDE_PATH, - SCC_HINT_VERBOSE, - - SCC_HINT_EMIT_LEX, - SCC_HINT_EMIT_PP, - SCC_HINT_EMIT_AST, - SCC_HINT_EMIT_IR, - }; - static const char *scc_hints_en[] = { - [SCC_HINT_PROG_NAME] = "scc", - [SCC_HINT_DESCRIPTION] = "A simple C compiler", - [SCC_HINT_OUTPUT_FILE] = - "Output file (`-` means standard output stream file)", - [SCC_HINT_INPUT_FILE] = "Input source file", - [SCC_HINT_INCLUDE_PATH] = "Add directory to the include search paths", - [SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)", - [SCC_HINT_EMIT_LEX] = "Generate lexer sources tokens and exit", - [SCC_HINT_EMIT_PP] = "Generate preprocessed tokens and exit", - [SCC_HINT_EMIT_AST] = "Generate AST and exit", - [SCC_HINT_EMIT_IR] = "Generate IR and exit", - }; - static const char *scc_hints_zh[] = { - [SCC_HINT_PROG_NAME] = "scc", - [SCC_HINT_DESCRIPTION] = "一个简单的C编译器", - [SCC_HINT_OUTPUT_FILE] = "输出文件(`-`表示标准输出流文件)", - [SCC_HINT_INPUT_FILE] = "输入源文件", - [SCC_HINT_INCLUDE_PATH] = "添加系统头文件到搜索路径", - [SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)", - [SCC_HINT_EMIT_LEX] = "生成`源代码的词法单元`并退出", - [SCC_HINT_EMIT_PP] = "生成`预处理后的词法单元`并退出", - [SCC_HINT_EMIT_AST] = "生成`抽象语法树`并退出", - [SCC_HINT_EMIT_IR] = "生成`中间代码`并退出", - }; - - const char **scc_hints; - switch (lang) { - case SCC_ARGPARSE_LANG_EN: - scc_hints = scc_hints_en; - break; - case SCC_ARGPARSE_LANG_ZH: - scc_hints = scc_hints_zh; - break; - default: - scc_hints = scc_hints_en; - break; - } - - scc_argparse_init(argparse, scc_hints[SCC_HINT_PROG_NAME], - scc_hints[SCC_HINT_DESCRIPTION]); - argparse->lang = lang; - scc_argparse_cmd_t *root = scc_argparse_get_root(argparse); - - // -o, --output - scc_argparse_opt_t opt_output; - scc_argparse_opt_init(&opt_output, 'o', "output", - scc_hints[SCC_HINT_OUTPUT_FILE]); - scc_argparse_spec_setup_string(&opt_output.spec, &(config->output_file)); - scc_argparse_cmd_add_opt(root, &opt_output); - - // input file (必需) - scc_argparse_arg_t arg_input; - scc_argparse_arg_init(&arg_input, "input", scc_hints[SCC_HINT_INPUT_FILE]); - scc_argparse_spec_setup_string(&arg_input.spec, &(config->input_file)); - scc_argparse_spec_set_required(&arg_input.spec, true); - scc_argparse_cmd_add_arg(root, &arg_input); - - // -I, --include (添加额外的系统头文件搜索路径) - scc_argparse_opt_t opt_include; - scc_argparse_opt_init(&opt_include, 'I', "include", - scc_hints[SCC_HINT_INCLUDE_PATH]); - scc_argparse_spec_setup_list(&opt_include.spec, &(config->include_paths)); - scc_argparse_cmd_add_opt(root, &opt_include); - - // -v, --verbose (计数) - scc_argparse_opt_t opt_verbose; - scc_argparse_opt_init(&opt_verbose, 'V', "verbose", - scc_hints[SCC_HINT_VERBOSE]); - scc_argparse_spec_setup_count(&opt_verbose.spec, &(config->verbose)); - scc_argparse_cmd_add_opt(root, &opt_verbose); - - // --emit-lex - scc_argparse_opt_t opt_lex; - scc_argparse_opt_init(&opt_lex, 0, "emit-lex", - scc_hints[SCC_HINT_EMIT_LEX]); - scc_argparse_spec_setup_bool(&opt_lex.spec, &(config->emit_lex)); - scc_argparse_cmd_add_opt(root, &opt_lex); - - // --emit-pp - scc_argparse_opt_t opt_pp; - scc_argparse_opt_init(&opt_pp, 0, "emit-pp", scc_hints[SCC_HINT_EMIT_PP]); - scc_argparse_spec_setup_bool(&opt_pp.spec, &(config->emit_pp)); - scc_argparse_cmd_add_opt(root, &opt_pp); - - // -T, --emit-ast - scc_argparse_opt_t opt_ast; - scc_argparse_opt_init(&opt_ast, 'T', "emit-ast", - scc_hints[SCC_HINT_EMIT_AST]); - scc_argparse_spec_setup_bool(&opt_ast.spec, &(config->emit_ast)); - scc_argparse_cmd_add_opt(root, &opt_ast); - - // -R, --emit-ir - scc_argparse_opt_t opt_ir; - scc_argparse_opt_init(&opt_ir, 'R', "emit-ir", scc_hints[SCC_HINT_EMIT_IR]); - scc_argparse_spec_setup_bool(&opt_ir.spec, &(config->emit_ir)); - scc_argparse_cmd_add_opt(root, &opt_ir); -} +#include "config.h" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -332,11 +209,10 @@ sstream_drop: return 0; } - scc_ir_builder_t ir_builder; - scc_ir_builder_init(&ir_builder); + scc_ast2ir_ctx_t ast2ir_ctx; #include - scc_ast2ir_translation_unit(&ir_builder, translation_unit, - scc_win_x64_type_abi); + scc_ast2ir_ctx_init(&ast2ir_ctx, scc_win_x64_type_abi); + scc_ast2ir_translation_unit(&ast2ir_ctx, translation_unit); if (config.emit_ir) { scc_ir_dump_ctx_t ir_dump_ctx; @@ -348,8 +224,9 @@ sstream_drop: scc_tree_dump_ctx_init(&tree_dump, false, (void *)scc_fprintf, (void *)fp); } - scc_ir_dump_ctx_init(&ir_dump_ctx, &tree_dump, &ir_builder.cprog, - &ir_builder.ctx); + scc_ir_dump_ctx_init(&ir_dump_ctx, &tree_dump, + &ast2ir_ctx.builder.cprog, + &ast2ir_ctx.builder.ctx); // scc_ir_dump_cprog(&ir_dump_ctx); scc_ir_dump_cprog_linear(&ir_dump_ctx); scc_tree_dump_ctx_drop(&tree_dump);