feat(ast): 添加汇编器模块并改进AST定义和IR转换

- 在README.md中添加asm汇编器模块说明
- 更新ast_def.h中的枚举注释,添加sema相关信息以明确语义分析作用域
- 重命名函数参数param_types为params,使命名更清晰
- 移除call表达式中的_target字段,简化结构
- 为member、identifier等字段添加///< fill by sema注释说明填充时机
- 为jump语句添加_target字段用于语义分析
- 更新所有AST初始化函数,接受位置信息参数以改进错误定位
- 修复alignof表达式的类型应为ALIGN_OF而非SIZE_OF的问题
- 重构ast2ir.h,引入scc_ast2ir_ctx_t上下文结构体统一管理转换状态
- 添加符号表、节点到IR映射等必要的转换上下文信息
This commit is contained in:
zzy
2026-03-17 20:29:40 +08:00
parent cabd1710ed
commit 2e5e98868d
29 changed files with 1289 additions and 1000 deletions

View File

@@ -15,6 +15,8 @@ ir 中间代码标识
opt 优化器 opt 优化器
asm 汇编器
mcode 机器码 mcode 机器码
sccf 统一输出格式 sccf 统一输出格式

View File

@@ -10,7 +10,7 @@
typedef enum { typedef enum {
SCC_AST_UNKNOWN, SCC_AST_UNKNOWN,
// 声明 // 声明
scc_ast_decl_t_BEGIN, // 声明开始 scc_ast_decl_t_BEGIN, // 声明开始 sema 函数作用域开始
SCC_AST_DECL_LIST, // 声明列表 SCC_AST_DECL_LIST, // 声明列表
SCC_AST_DECL_VAR, // 变量声明 SCC_AST_DECL_VAR, // 变量声明
SCC_AST_DECL_FUNC, // 函数声明 SCC_AST_DECL_FUNC, // 函数声明
@@ -19,10 +19,10 @@ typedef enum {
SCC_AST_DECL_UNION, // 联合声明 SCC_AST_DECL_UNION, // 联合声明
SCC_AST_DECL_ENUM, // 枚举声明 SCC_AST_DECL_ENUM, // 枚举声明
SCC_AST_DECL_TYPEDEF, // typedef 声明 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_COMPOUND, // 复合语句 { ... }
SCC_AST_STMT_EXPR, // 表达式语句 SCC_AST_STMT_EXPR, // 表达式语句
SCC_AST_STMT_IF, // if 语句 SCC_AST_STMT_IF, // if 语句
@@ -37,7 +37,7 @@ typedef enum {
SCC_AST_STMT_RETURN, // return 语句 SCC_AST_STMT_RETURN, // return 语句
SCC_AST_STMT_GOTO, // goto 语句 SCC_AST_STMT_GOTO, // goto 语句
SCC_AST_STMT_LABEL, // 标签语句 SCC_AST_STMT_LABEL, // 标签语句
scc_ast_stmt_t_END, // 结束语句 scc_ast_stmt_t_END, // 结束语句 sema 作用域结束
// 表达式 // 表达式
scc_ast_expr_t_BEGIN, // 表达式开始 scc_ast_expr_t_BEGIN, // 表达式开始
@@ -180,7 +180,7 @@ struct scc_ast_type {
} array; } array;
struct { struct {
scc_ast_type_t *return_type; scc_ast_type_t *return_type;
scc_ast_decl_vec_t param_types; // va_list <=> ... scc_ast_decl_vec_t params; // va_list <=> ...
} function; } function;
struct { struct {
const char *name; const char *name;
@@ -294,7 +294,6 @@ struct scc_ast_expr {
struct { struct {
const char *name; const char *name;
scc_ast_expr_t *callee; scc_ast_expr_t *callee;
scc_ast_expr_t *_target;
scc_ast_expr_vec_t args; scc_ast_expr_vec_t args;
} call; } call;
// 数组下标 // 数组下标
@@ -306,7 +305,7 @@ struct scc_ast_expr {
struct { struct {
scc_ast_expr_t *base; scc_ast_expr_t *base;
const char *name; const char *name;
usize _target_idx; usize _target_idx; ///< fill by sema
} member; } member;
// cast 类型转换 // cast 类型转换
struct { struct {
@@ -332,7 +331,7 @@ struct scc_ast_expr {
// 标识符 // 标识符
struct { struct {
const char *name; const char *name;
scc_ast_decl_t *_target; scc_ast_decl_t *_target; ///< fill by sema
} identifier; } identifier;
struct { struct {
scc_ast_type_t *type; scc_ast_type_t *type;
@@ -393,6 +392,7 @@ struct scc_ast_stmt {
} default_stmt; } default_stmt;
// break/continue // break/continue
struct { struct {
scc_ast_stmt_t *_target; // fill by sema
} jump; } jump;
// return 语句 // return 语句
struct { struct {

View File

@@ -8,10 +8,10 @@
// decls can be null but maybe warning // decls can be null but maybe warning
static inline void static inline void
scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit, 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); Assert(translation_unit != null);
translation_unit->base.type = SCC_AST_TRANSLATION_UNIT; translation_unit->base.type = SCC_AST_TRANSLATION_UNIT;
translation_unit->base.loc = scc_pos_create(); translation_unit->base.loc = loc;
if (decls == null) { if (decls == null) {
scc_vec_init(translation_unit->declarations); scc_vec_init(translation_unit->declarations);
} else { } 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, 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); Assert(decl != null && list_move != null);
decl->base.loc = scc_pos_create(); decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_LIST; decl->base.type = SCC_AST_DECL_LIST;
decl->name = null; decl->name = null;
decl->list.vars = *list_move; 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, static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl,
scc_ast_type_t *type, scc_ast_type_t *type,
const char *name, const char *name,
scc_ast_expr_t *var_init) { scc_ast_expr_t *var_init,
scc_pos_t loc) {
Assert(decl != null && type != null); Assert(decl != null && type != null);
decl->base.loc = scc_pos_create(); decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_VAR; decl->base.type = SCC_AST_DECL_VAR;
decl->name = name; decl->name = name;
decl->var.type = type; 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 // var_init can be null
static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl, static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl,
scc_ast_type_t *type, const char *name, 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); 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->base.type = SCC_AST_DECL_VAR;
decl->name = name; decl->name = name;
decl->var.type = type; 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, static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
scc_ast_type_t *type, scc_ast_type_t *type,
const char *name, const char *name,
scc_ast_stmt_t *body) { scc_ast_stmt_t *body, scc_pos_t loc) {
Assert(decl != null && name != null && type != null); 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->base.type = SCC_AST_DECL_FUNC;
decl->name = name; decl->name = name;
decl->func.type = type; 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 // name can be null
static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl, static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
scc_ast_type_t *type, scc_ast_type_t *type,
const char *name) { const char *name, scc_pos_t loc) {
Assert(decl != null && type != null); Assert(decl != null && type != null);
decl->base.loc = scc_pos_create(); decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_PARAM; decl->base.type = SCC_AST_DECL_PARAM;
decl->name = name; decl->name = name;
decl->param.type = type; 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 // name and fields can be null
static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl, static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
const char *name, const char *name,
scc_ast_decl_vec_t *fields_move) { scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
Assert(decl != null); Assert(decl != null);
decl->base.loc = scc_pos_create(); decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_STRUCT; decl->base.type = SCC_AST_DECL_STRUCT;
decl->name = name; decl->name = name;
if (fields_move == null) { 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 // name and fields can be null
static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl, static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
const char *name, const char *name,
scc_ast_decl_vec_t *fields_move) { scc_ast_decl_vec_t *fields_move,
scc_pos_t loc) {
Assert(decl != null); Assert(decl != null);
decl->base.loc = scc_pos_create(); decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_UNION; decl->base.type = SCC_AST_DECL_UNION;
decl->name = name; decl->name = name;
if (fields_move == null) { 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 // name and fields can be null
static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl, static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl,
const char *name, const char *name,
scc_ast_expr_vec_t *fields_move) { scc_ast_expr_vec_t *fields_move,
scc_pos_t loc) {
Assert(decl != null); Assert(decl != null);
decl->base.loc = scc_pos_create(); decl->base.loc = loc;
decl->base.type = SCC_AST_DECL_ENUM; decl->base.type = SCC_AST_DECL_ENUM;
decl->name = name; decl->name = name;
if (fields_move == null) { 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, static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl,
const char *name, const char *name,
scc_ast_type_t *type) { scc_ast_type_t *type,
scc_pos_t loc) {
Assert(decl != null && name != null && type != null); 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->base.type = SCC_AST_DECL_TYPEDEF;
decl->name = name; decl->name = name;
decl->typedef_decl.type = type; decl->typedef_decl.type = type;
} }
// items can be null // items can be null
static inline void static inline void scc_ast_stmt_compound_init(
scc_ast_stmt_compound_init(scc_ast_stmt_t *stmt, scc_ast_stmt_t *stmt, scc_ast_block_item_vec_t *items_move, scc_pos_t loc) {
scc_ast_block_item_vec_t *items_move) {
Assert(stmt != null); Assert(stmt != null);
stmt->base.loc = scc_pos_create(); stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_COMPOUND; stmt->base.type = SCC_AST_STMT_COMPOUND;
if (items_move == null) { if (items_move == null) {
scc_vec_init(stmt->compound.block_items); 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 // expr can be null
static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt, 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); Assert(stmt != null);
stmt->base.loc = scc_pos_create(); stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_EXPR; stmt->base.type = SCC_AST_STMT_EXPR;
stmt->expr.expr = 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, static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond, scc_ast_expr_t *cond,
scc_ast_stmt_t *then, 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); 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->base.type = SCC_AST_STMT_IF;
stmt->if_stmt.cond = cond; stmt->if_stmt.cond = cond;
stmt->if_stmt.then_stmt = then; 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, static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond, 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); 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->base.type = SCC_AST_STMT_WHILE;
stmt->while_stmt.cond = cond; stmt->while_stmt.cond = cond;
stmt->while_stmt.body = body; 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, static inline void scc_ast_stmt_do_while_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond, 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); 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->base.type = SCC_AST_STMT_DO_WHILE;
stmt->while_stmt.cond = cond; stmt->while_stmt.cond = cond;
stmt->while_stmt.body = body; 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_type_t *init,
scc_ast_expr_t *cond, scc_ast_expr_t *cond,
scc_ast_expr_t *incr, scc_ast_expr_t *incr,
scc_ast_stmt_t *body) { scc_ast_stmt_t *body, scc_pos_t loc) {
Assert(stmt != null && body != null); Assert(stmt != null && body != null);
stmt->base.loc = scc_pos_create(); stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_FOR; stmt->base.type = SCC_AST_STMT_FOR;
stmt->for_stmt.init = init; stmt->for_stmt.init = init;
stmt->for_stmt.cond = cond; 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, static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond, 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); 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->base.type = SCC_AST_STMT_SWITCH;
stmt->switch_stmt.cond = cond; stmt->switch_stmt.cond = cond;
stmt->switch_stmt.body = body; 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, static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt,
scc_ast_expr_t *cond, 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); 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->base.type = SCC_AST_STMT_CASE;
stmt->case_stmt.expr = cond; stmt->case_stmt.expr = cond;
stmt->case_stmt.stmt = body; stmt->case_stmt.stmt = body;
} }
static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt, 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); Assert(stmt != null && body != null);
stmt->base.loc = scc_pos_create(); stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_DEFAULT; stmt->base.type = SCC_AST_STMT_DEFAULT;
stmt->default_stmt.stmt = body; 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); Assert(stmt != null);
stmt->base.loc = scc_pos_create(); stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_BREAK; 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); Assert(stmt != null);
stmt->base.loc = scc_pos_create(); stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_CONTINUE; stmt->base.type = SCC_AST_STMT_CONTINUE;
stmt->jump._target = null;
} }
// expr can be null // expr can be null
static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt, 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); Assert(stmt != null);
stmt->base.loc = scc_pos_create(); stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_RETURN; stmt->base.type = SCC_AST_STMT_RETURN;
stmt->return_stmt.expr = expr; stmt->return_stmt.expr = expr;
} }
static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt, 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); Assert(stmt != null && label != null);
stmt->base.loc = scc_pos_create(); stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_GOTO; stmt->base.type = SCC_AST_STMT_GOTO;
stmt->goto_stmt.label = label; stmt->goto_stmt.label = label;
stmt->goto_stmt._target = null; 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, static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt,
const char *label, const char *label,
scc_ast_stmt_t *body) { scc_ast_stmt_t *body,
scc_pos_t loc) {
Assert(stmt != null); Assert(stmt != null);
stmt->base.loc = scc_pos_create(); stmt->base.loc = loc;
stmt->base.type = SCC_AST_STMT_LABEL; stmt->base.type = SCC_AST_STMT_LABEL;
stmt->label_stmt.label = label; stmt->label_stmt.label = label;
stmt->label_stmt.stmt = body; 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, static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr,
scc_ast_expr_op_t op, scc_ast_expr_op_t op,
scc_ast_expr_t *lhs, 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); 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->base.type = SCC_AST_EXPR_BINARY;
expr->binary.op = op; expr->binary.op = op;
expr->binary.lhs = lhs; 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, static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr,
scc_ast_expr_op_t op, 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); Assert(expr != null && operand != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_UNARY; expr->base.type = SCC_AST_EXPR_UNARY;
expr->unary.op = op; expr->unary.op = op;
expr->unary.operand = operand; 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, static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr,
scc_ast_expr_t *cond, scc_ast_expr_t *cond,
scc_ast_expr_t *then_expr, 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 && Assert(expr != null && cond != null && then_expr != null &&
else_expr != null); else_expr != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_COND; expr->base.type = SCC_AST_EXPR_COND;
expr->cond.cond = cond; expr->cond.cond = cond;
expr->cond.then_expr = then_expr; 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 // args can be null
static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr, static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr,
scc_ast_expr_t *callee, 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); Assert(expr != null && callee != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_CALL; expr->base.type = SCC_AST_EXPR_CALL;
expr->call.callee = callee; expr->call.callee = callee;
expr->call._target = null;
if (args == null) { if (args == null) {
scc_vec_init(expr->call.args); scc_vec_init(expr->call.args);
} else { } else {
@@ -332,9 +352,10 @@ static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr,
// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标 // SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标
static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr, static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr,
scc_ast_expr_t *array, 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); 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->base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT;
expr->subscript.array = array; expr->subscript.array = array;
expr->subscript.index = index; 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, static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr,
scc_ast_node_type_t type, scc_ast_node_type_t type,
scc_ast_expr_t *object, scc_ast_expr_t *object,
const char *member) { const char *member,
scc_pos_t loc) {
Assert(expr != null && object != null && member != null); Assert(expr != null && object != null && member != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = type; expr->base.type = type;
expr->member.base = object; expr->member.base = object;
expr->member.name = member; 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, static inline void scc_ast_expr_member_init(scc_ast_expr_t *expr,
scc_ast_expr_t *object, scc_ast_expr_t *object,
const char *member) { const char *member, scc_pos_t loc) {
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_MEMBER, object, member); _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, static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr,
scc_ast_expr_t *object, scc_ast_expr_t *object,
const char *member) { const char *member,
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, 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, static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr,
scc_ast_type_t *type, 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); 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->base.type = SCC_AST_EXPR_CAST;
expr->cast.type = type; expr->cast.type = type;
expr->cast.expr = operand; 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 // 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, static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr,
scc_ast_type_t *type, scc_ast_type_t *type,
scc_ast_expr_t *target_expr) { scc_ast_expr_t *target_expr,
scc_pos_t loc) {
Assert(expr != null); Assert(expr != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_SIZE_OF; expr->base.type = SCC_AST_EXPR_SIZE_OF;
expr->attr_of.type = type; expr->attr_of.type = type;
expr->attr_of.expr = target_expr; 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 // 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, static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
scc_ast_type_t *type, scc_ast_type_t *type,
scc_ast_expr_t *target_expr) { scc_ast_expr_t *target_expr,
scc_pos_t loc) {
Assert(expr != null); Assert(expr != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_SIZE_OF; expr->base.type =
SCC_AST_EXPR_SIZE_OF; // 注意:这里使用了 SIZE_OF可能需要改为 ALIGN_OF
expr->attr_of.type = type; expr->attr_of.type = type;
expr->attr_of.expr = target_expr; 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, static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr,
scc_ast_expr_t *base, scc_ast_expr_t *base,
scc_ast_expr_vec_t *lhs_exprs, 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); Assert(expr != null && base != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_COMPOUND; expr->base.type = SCC_AST_EXPR_COMPOUND;
expr->compound.base = base; 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, static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr,
scc_ast_node_type_t type, 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); Assert(expr != null && value != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = type; expr->base.type = type;
expr->literal.lexme = value; expr->literal.lexme = value;
expr->literal.owned = owned; expr->literal.owned = owned;
} }
static inline void scc_ast_expr_literal_int_init(scc_ast_expr_t *expr, static inline void scc_ast_expr_literal_int_init(scc_ast_expr_t *expr,
const char *value, const char *value, cbool owned,
cbool owned) { scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_INT_LITERAL, value, owned); 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, static inline void scc_ast_expr_literal_float_init(scc_ast_expr_t *expr,
const char *value, const char *value,
cbool owned) { cbool owned, scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_FLOAT_LITERAL, value, owned); 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, static inline void scc_ast_expr_literal_char_init(scc_ast_expr_t *expr,
const char *value, const char *value,
cbool owned) { cbool owned, scc_pos_t loc) {
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_CHAR_LITERAL, value, owned); 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, static inline void scc_ast_expr_literal_string_init(scc_ast_expr_t *expr,
const char *value, const char *value,
cbool owned) { cbool owned,
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_STRING_LITERAL, value, 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, 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); Assert(expr != null && name != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_IDENTIFIER; expr->base.type = SCC_AST_EXPR_IDENTIFIER;
expr->identifier.name = name; expr->identifier.name = name;
expr->identifier._target = null; expr->identifier._target = null;
} }
static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr, 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); Assert(expr != null && type != null);
expr->base.loc = scc_pos_create(); expr->base.loc = loc;
expr->base.type = SCC_AST_EXPR_LVALUE; expr->base.type = SCC_AST_EXPR_LVALUE;
expr->lvalue.type = type; expr->lvalue.type = type;
} }
// have defined builtin type // have defined builtin type
static inline void _scc_ast_type_builtin_init(scc_ast_type_t *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); Assert(type != null);
type->base.loc = scc_pos_create(); type->base.loc = loc;
type->base.type = SCC_AST_TYPE_BUILTIN; type->base.type = SCC_AST_TYPE_BUILTIN;
type->builtin.type = builtin; type->builtin.type = builtin;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
} }
static inline void scc_ast_type_pointer_init(scc_ast_type_t *type, 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); Assert(type != null && pointee != null);
type->base.loc = scc_pos_create(); type->base.loc = loc;
type->base.type = SCC_AST_TYPE_POINTER; type->base.type = SCC_AST_TYPE_POINTER;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->pointer.pointee = pointee; 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 // size can be null
static inline void scc_ast_type_array_init(scc_ast_type_t *type, static inline void scc_ast_type_array_init(scc_ast_type_t *type,
scc_ast_type_t *element, scc_ast_type_t *element,
scc_ast_expr_t *size) { scc_ast_expr_t *size,
scc_pos_t loc) {
Assert(type != null && element != null); Assert(type != null && element != null);
type->base.loc = scc_pos_create(); type->base.loc = loc;
type->base.type = SCC_AST_TYPE_ARRAY; type->base.type = SCC_AST_TYPE_ARRAY;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->array.element = element; 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 // return_type and params can be null
static inline void scc_ast_type_function_init(scc_ast_type_t *type, static inline void scc_ast_type_function_init(scc_ast_type_t *type,
scc_ast_type_t *return_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); Assert(type != null);
type->base.loc = scc_pos_create(); type->base.loc = loc;
type->base.type = SCC_AST_TYPE_FUNCTION; type->base.type = SCC_AST_TYPE_FUNCTION;
type->function.return_type = return_type; type->function.return_type = return_type;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
if (params == null) { if (params == null) {
scc_vec_init(type->function.param_types); scc_vec_init(type->function.params);
} else { } else {
type->function.param_types = *params; type->function.params = *params;
scc_vec_init(*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, static inline void _scc_ast_type_record_init(scc_ast_type_t *type,
scc_ast_node_type_t type_kind, scc_ast_node_type_t type_kind,
const char *name, const char *name,
scc_ast_decl_t *decl) { scc_ast_decl_t *decl,
scc_pos_t loc) {
Assert(type != null); Assert(type != null);
type->base.loc = scc_pos_create(); type->base.loc = loc;
type->base.type = type_kind; type->base.type = type_kind;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->record.name = name; 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 // name and decl can be null
static inline void scc_ast_type_struct_init(scc_ast_type_t *type, static inline void scc_ast_type_struct_init(scc_ast_type_t *type,
const char *name, const char *name,
scc_ast_decl_t *decl) { scc_ast_decl_t *decl,
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl); scc_pos_t loc) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl, loc);
} }
// name and decl can be null // name and decl can be null
static inline void scc_ast_type_union_init(scc_ast_type_t *type, static inline void scc_ast_type_union_init(scc_ast_type_t *type,
const char *name, const char *name,
scc_ast_decl_t *decl) { scc_ast_decl_t *decl,
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl); scc_pos_t loc) {
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl, loc);
} }
// name and decl can be null // name and decl can be null
static inline void scc_ast_type_enum_init(scc_ast_type_t *type, static inline void scc_ast_type_enum_init(scc_ast_type_t *type,
const char *name, const char *name,
scc_ast_decl_t *decl) { scc_ast_decl_t *decl, scc_pos_t loc) {
Assert(type != null); Assert(type != null);
type->base.loc = scc_pos_create(); type->base.loc = loc;
type->base.type = SCC_AST_TYPE_ENUM; type->base.type = SCC_AST_TYPE_ENUM;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->enumeration.name = name; 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, static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,
const char *name, const char *name,
scc_ast_decl_t *target) { scc_ast_decl_t *target,
scc_pos_t loc) {
Assert(type != null && target != null); Assert(type != null && target != null);
type->base.loc = scc_pos_create(); type->base.loc = loc;
type->base.type = SCC_AST_TYPE_TYPEDEF; type->base.type = SCC_AST_TYPE_TYPEDEF;
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
type->typedef_type.name = name; type->typedef_type.name = name;

View File

@@ -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); (void)scc_vec_pop(ctx->stack);
scc_vec_push(ctx->stack, true); scc_vec_push(ctx->stack, true);
if (scc_vec_size(type->function.param_types) != 0) { if (scc_vec_size(type->function.params) != 0) {
scc_vec_foreach(type->function.param_types, i) { scc_vec_foreach(type->function.params, i) {
scc_ast_decl_t *param = scc_ast_decl_t *param = scc_vec_at(type->function.params, i);
scc_vec_at(type->function.param_types, i);
if (param->name) { if (param->name) {
// FIXME param name // FIXME param name
} }

View File

@@ -5,8 +5,22 @@
#include <scc_ast.h> #include <scc_ast.h>
#include <scc_ir.h> #include <scc_ir.h>
void scc_ast2ir_translation_unit(scc_ir_builder_t *builder, typedef struct {
scc_ast_translation_unit_t *tu, scc_ir_builder_t builder;
const scc_type_abi_t *abi); 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__ */ #endif /* __SCC_AST2IR_H__ */

View File

@@ -1,561 +0,0 @@
#include <ir_builtin.h>
#include <scc_ast2ir.h>
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);
}
}

View File

@@ -0,0 +1,530 @@
#include <ir_builtin.h>
#include <scc_ast2ir.h>
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);
}

View File

@@ -0,0 +1,14 @@
#include <scc_ast2ir.h>
#include <utest/acutest.h>
void test_type(void) {}
void test_expr(void) {}
void test_stmt(void) {}
void test_decl(void) {}
TEST_LIST = {
};

View File

@@ -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); 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 开始构建新的基本块 * @brief 开始构建新的基本块
* @param label 基本块标签可为NULL自动生成 * @param label 基本块标签可为NULL自动生成

View File

@@ -52,8 +52,8 @@ typedef enum scc_ir_type_tag {
struct scc_ir_type { struct scc_ir_type {
scc_ir_type_tag_t tag; scc_ir_type_tag_t tag;
// int size; // 字节大小 int size; // 字节大小
// int align; // 对齐要求 int align; // 对齐要求
union { union {
struct { struct {
scc_ir_type_ref_t base; scc_ir_type_ref_t base;
@@ -85,6 +85,8 @@ struct scc_ir_func {
typedef enum scc_ir_node_tag { typedef enum scc_ir_node_tag {
SCC_IR_NODE_NULL, SCC_IR_NODE_NULL,
SCC_IR_NODE_CONST_INT, SCC_IR_NODE_CONST_INT,
SCC_IR_NODE_CONST_UINT,
SCC_IR_NODE_CONST_FLOAT,
SCC_IR_NODE_CONV, ///< 类型转换 SCC_IR_NODE_CONV, ///< 类型转换
SCC_IR_NODE_FUNC_ARG_REF, ///< 函数参数引用 SCC_IR_NODE_FUNC_ARG_REF, ///< 函数参数引用
SCC_IR_NODE_BLOCK_ARG_REF, ///< 基本块参数引用 SCC_IR_NODE_BLOCK_ARG_REF, ///< 基本块参数引用

View File

@@ -80,7 +80,7 @@ scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder) {
return builder->current_func; return builder->current_func;
} }
scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder, scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder,
const char *label) { const char *label) {
scc_ir_bblock_t bblock = {0}; scc_ir_bblock_t bblock = {0};
@@ -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_bblock_ref_t bblock_ref =
scc_ir_ctx_new_bblock(&builder->ctx, &bblock); 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_func_t *current_func =
scc_ir_ctx_get_func(&builder->ctx, builder->current_func); scc_ir_ctx_get_func(&builder->ctx, builder->current_func);
if (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) { 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 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}; scc_ir_node_t load_node = {0};
load_node.tag = SCC_IR_NODE_LOAD; 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) { if (ptr_node) {
scc_ir_type_t *ptr_type = scc_ir_type_t *ptr_type =
scc_ir_ctx_get_type(&builder->ctx, ptr_node->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 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_ref_t value) {
scc_ir_node_t store_node = {0}; scc_ir_node_t store_node = {0};
store_node.tag = SCC_IR_NODE_STORE; 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; store_node.data.store.value = value;
scc_ir_node_ref_t node_ref = 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 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_ref_t index) {
scc_ir_node_t get_ptr_node = {0}; scc_ir_node_t get_ptr_node = {0};
get_ptr_node.tag = SCC_IR_NODE_GET_PTR; 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; 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) { if (src_node) {
get_ptr_node.type = src_node->type; get_ptr_node.type = src_node->type;
} }

View File

@@ -87,6 +87,20 @@ static inline void scc_parse_decl_sema(scc_parser_t *parser,
decl); 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, static inline void scc_parse_type_sema(scc_parser_t *parser,
scc_ast_type_t *type) { scc_ast_type_t *type) {
parser->sema_callbacks.on_type(parser->sema_callbacks.context, parser->sema_callbacks.on_type(parser->sema_callbacks.context,

View File

@@ -182,7 +182,9 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
init = scc_parse_assignment_expression(parser); init = scc_parse_assignment_expression(parser);
return init; 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)); init = scc_malloc(sizeof(scc_ast_expr_t));
Assert(init != null); Assert(init != null);
@@ -202,8 +204,8 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
scc_parser_next_consume(parser, &tok); scc_parser_next_consume(parser, &tok);
lhs = scc_malloc(sizeof(scc_ast_expr_t)); lhs = scc_malloc(sizeof(scc_ast_expr_t));
Assert(lhs != null); Assert(lhs != null);
scc_ast_expr_member_init(lhs, ptr, scc_ast_expr_member_init(
scc_cstring_as_cstr(&tok.lexeme)); lhs, ptr, scc_cstring_as_cstr(&tok.lexeme), tok.loc);
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
ptr = lhs; ptr = lhs;
continue; continue;
@@ -230,7 +232,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
} }
lhs = scc_malloc(sizeof(scc_ast_expr_t)); lhs = scc_malloc(sizeof(scc_ast_expr_t));
Assert(lhs != null); 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
ptr = lhs; ptr = lhs;
continue; continue;
@@ -253,7 +255,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
scc_vec_push(rhs_exprs, expr); 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; return init;
} }
@@ -283,10 +285,14 @@ CONTINUE:
scc_parser_next_consume(parser, null); scc_parser_next_consume(parser, null);
// TODO maybe memory leak // TODO maybe memory leak
scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t)); 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); decl->var.init = scc_parse_initializer(parser, lvalue);
} else if (tok_ptr->type == SCC_TOK_L_BRACE) { } 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); 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); Assert(decl->base.type == SCC_AST_DECL_FUNC);
decl->func.body = body; decl->func.body = body;
Assert(decl->func.type != null); Assert(decl->func.type != null);
@@ -305,10 +311,12 @@ CONTINUE:
if (decl_list) { if (decl_list) {
scc_vec_foreach(decl_list_vec, i) { scc_vec_foreach(decl_list_vec, i) {
decl = scc_vec_at(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 { } 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) { if (decl_list != null) {
@@ -316,7 +324,9 @@ CONTINUE:
decl = scc_vec_at(decl_list_vec, i); decl = scc_vec_at(decl_list_vec, i);
scc_parse_decl_sema(parser, decl); 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; decl = decl_list;
} else { } else {
scc_parse_decl_sema(parser, decl); scc_parse_decl_sema(parser, decl);

View File

@@ -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)); scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); 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; left = expr;
} }
return left; 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); const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
if (!tok_ptr) if (!tok_ptr)
return left; return left;
scc_pos_t pos = tok_ptr->loc;
int prec = get_token_precedence(tok_ptr->type); int prec = get_token_precedence(tok_ptr->type);
if (prec == PREC_ASSIGNMENT && is_binary_operator(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)); scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); Assert(expr != null);
scc_ast_expr_binary_init(expr, op, left, right); scc_ast_expr_binary_init(expr, op, left, right, pos);
left = expr; left = expr;
} }
return left; return left;
@@ -425,6 +427,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
return null; return null;
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); 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) { if (tok_ptr && tok_ptr->type == SCC_TOK_COND) {
// 消耗 '?' // 消耗 '?'
scc_lexer_tok_t q_tok; 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)); scc_ast_expr_t *cond = scc_malloc(sizeof(scc_ast_expr_t));
Assert(cond != null); 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; cond_expr = cond;
} }
return cond_expr; return cond_expr;
@@ -480,13 +483,15 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
if (!operand) { if (!operand) {
// FIXME postfix-expression // FIXME postfix-expression
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); 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); operand = scc_parse_initializer(parser, expr);
return operand; return operand;
} }
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); 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; return expr;
} else { } else {
// 不是类型转换,回退 // 不是类型转换,回退
@@ -538,6 +543,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
if (!scc_parser_next_consume(parser, &tok)) if (!scc_parser_next_consume(parser, &tok))
return null; return null;
scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true); 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); scc_lexer_tok_drop(&tok);
// 一元运算符右结合,递归调用 parse_unary_expression // 一元运算符右结合,递归调用 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)); scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); Assert(expr != null);
scc_ast_expr_unary_init(expr, op, operand); scc_ast_expr_unary_init(expr, op, operand, pos);
return expr; return expr;
} }
case SCC_TOK_SIZEOF: 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) { tok_ptr.type != SCC_TOK_SIZEOF) {
return null; return null;
} }
scc_pos_t pos = tok_ptr.loc;
scc_lexer_tok_drop(&tok_ptr); scc_lexer_tok_drop(&tok_ptr);
const scc_lexer_tok_t *next = scc_parser_peek(parser); 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); 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; return expr;
} }
next: next:
// 尝试解析 sizeof unary-expression // 尝试解析 sizeof unary-expression
scc_ast_expr_t *operand = parse_unary_expression(parser); scc_ast_expr_t *operand = parse_unary_expression(parser);
if (operand != null) { if (operand != null) {
scc_ast_expr_sizeof_init(expr, null, operand); scc_ast_expr_sizeof_init(expr, null, operand, pos);
return expr; return expr;
} }
@@ -618,11 +625,14 @@ next:
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
scc_ast_expr_t *left = parse_primary_expression(parser); scc_ast_expr_t *left = parse_primary_expression(parser);
const scc_lexer_tok_t *tok_ptr = null; const scc_lexer_tok_t *tok_ptr = null;
scc_pos_t pos = scc_pos_create();
if (!left) { if (!left) {
tok_ptr = scc_parser_peek(parser); tok_ptr = scc_parser_peek(parser);
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN)) { if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN)) {
return null; return null;
} }
pos = tok_ptr->loc;
scc_parser_store(parser); scc_parser_store(parser);
scc_parser_next(parser); scc_parser_next(parser);
scc_ast_type_t *type = scc_parse_type_name(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_ERROR(scc_parser_got_current_pos(parser), "Expected ')'");
} }
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); scc_ast_expr_t *expr = scc_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); left = scc_parse_initializer(parser, expr);
return left; 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)) if (!scc_parser_next_consume(parser, null))
return left; return left;
pos = left->base.loc;
scc_ast_expr_t *index = scc_parse_expression(parser); scc_ast_expr_t *index = scc_parse_expression(parser);
if (!index) { 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)); scc_ast_expr_t *subscript = scc_malloc(sizeof(scc_ast_expr_t));
Assert(subscript != null); Assert(subscript != null);
scc_ast_expr_array_subscript_init(subscript, left, index); scc_ast_expr_array_subscript_init(subscript, left, index, pos);
left = subscript; left = subscript;
break; break;
} }
@@ -672,6 +683,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
{ {
if (!scc_parser_next_consume(parser, null)) if (!scc_parser_next_consume(parser, null))
return left; return left;
pos = left->base.loc;
scc_ast_expr_vec_t args; scc_ast_expr_vec_t args;
scc_vec_init(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)); scc_ast_expr_t *call = scc_malloc(sizeof(scc_ast_expr_t));
Assert(call != null); Assert(call != null);
scc_ast_expr_call_init(call, left, &args); scc_ast_expr_call_init(call, left, &args, pos);
left = call; left = call;
break; 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)); scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t));
Assert(member != null); Assert(member != null);
if (op_tok.type == SCC_TOK_DOT) { 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 { } 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); 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)) if (!scc_parser_next_consume(parser, &op_tok))
return left; return left;
scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false); scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false);
scc_lexer_tok_drop(&op_tok);
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t)); scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); 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; left = expr;
break; break;
} }
@@ -776,7 +788,8 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
return null; return null;
expr = scc_malloc(sizeof(scc_ast_expr_t)); expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); 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; return expr;
} }
case SCC_TOK_INT_LITERAL: { 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)); expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); Assert(expr != null);
scc_ast_expr_literal_int_init(expr, scc_cstring_as_cstr(&tok.lexeme), scc_ast_expr_literal_int_init(expr, scc_cstring_as_cstr(&tok.lexeme),
false); false, tok.loc);
return expr; return expr;
} }
case SCC_TOK_FLOAT_LITERAL: { 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)); expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); Assert(expr != null);
scc_ast_expr_literal_float_init(expr, scc_cstring_as_cstr(&tok.lexeme), scc_ast_expr_literal_float_init(expr, scc_cstring_as_cstr(&tok.lexeme),
false); false, tok.loc);
return expr; return expr;
} }
case SCC_TOK_CHAR_LITERAL: { 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)); expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); Assert(expr != null);
scc_ast_expr_literal_char_init(expr, scc_cstring_as_cstr(&tok.lexeme), scc_ast_expr_literal_char_init(expr, scc_cstring_as_cstr(&tok.lexeme),
false); false, tok.loc);
return expr; return expr;
} }
case SCC_TOK_STRING_LITERAL: { 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)); expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); Assert(expr != null);
// FIXME loc
scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string), scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string),
true); true, tok.loc);
return expr; return expr;
} }
case SCC_TOK_L_PAREN: case SCC_TOK_L_PAREN:
@@ -847,7 +861,12 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
if (!left) if (!left)
return null; 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); scc_ast_expr_t *right = scc_parse_assignment_expression(parser);
if (!right) { if (!right) {
parser_sync(parser); 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)); scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null); 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; left = expr;
} }
return left; return left;

View File

@@ -73,7 +73,8 @@ static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
return ret; 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}; scc_lexer_tok_t tok = {0};
if (!scc_parser_next_consume(parser, &tok)) { if (!scc_parser_next_consume(parser, &tok)) {
return null; 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(); scc_ast_stmt_t *stmt = ast_stmt_alloc();
Assert(stmt != null); 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; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_CASE)) {
return null; 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_t *stmt = ast_stmt_alloc();
scc_ast_stmt_case_init(stmt, expr, statement); scc_ast_stmt_case_init(stmt, expr, statement, pos);
return stmt; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_DEFAULT)) {
return null; 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_t *stmt = ast_stmt_alloc();
scc_ast_stmt_default_init(stmt, statement); scc_ast_stmt_default_init(stmt, statement, pos);
return stmt; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) {
return null; return null;
} }
scc_ast_block_item_vec_t block_items; scc_ast_block_item_vec_t block_items;
scc_vec_init(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)) { while (!scc_parser_consume_if(parser, SCC_TOK_R_BRACE)) {
/// TODO /// TODO
// scc_parse_is_decl(); // 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); 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_t *stmt = ast_stmt_alloc();
scc_ast_stmt_compound_init(stmt, &block_items); scc_ast_stmt_compound_init(stmt, &block_items, pos);
return stmt; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_IF)) {
return null; 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_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; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) {
return null; 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 *statement = scc_parse_statement(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc(); 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; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
return null; 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 *statement = scc_parse_statement(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc(); 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; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_DO)) {
return null; 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_expr_t *expression = ast_parse_paren_expression(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc(); 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; 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)) { if (!scc_parser_consume_if(parser, SCC_TOK_FOR)) {
return null; return null;
} }
@@ -288,27 +301,28 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
body = scc_parse_statement(parser); body = scc_parse_statement(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc(); 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; 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(); scc_ast_stmt_t *stmt = ast_stmt_alloc();
if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) { if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) {
scc_lexer_tok_t tok = {0}; scc_lexer_tok_t tok = {0};
if (scc_parser_next_consume(parser, &tok)) { 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 { } else {
SCC_ERROR(scc_parser_got_current_pos(parser), SCC_ERROR(scc_parser_got_current_pos(parser),
"Expected label after goto."); "Expected label after goto.");
} }
} else if (scc_parser_consume_if(parser, SCC_TOK_CONTINUE)) { } 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)) { } 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)) { } 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 { } else {
UNREACHABLE(); UNREACHABLE();
} }
@@ -320,11 +334,12 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
return stmt; 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)) { if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
scc_ast_stmt_t *stmt = ast_stmt_alloc(); 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; 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_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)) { if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
SCC_ERROR(scc_parser_got_current_pos(parser), 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) { if (!tok_ref) {
return null; return null;
} }
scc_pos_t pos = tok_ref->loc;
switch (tok_ref->type) { switch (tok_ref->type) {
/* /*
(6.8.1) (6.8.1)
@@ -366,14 +382,14 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
break; break;
} }
scc_parser_reset(parser); scc_parser_reset(parser);
stmt = parse_label_statement(parser); stmt = parse_label_statement(parser, pos);
goto RETURN; goto RETURN;
case SCC_TOK_CASE: { case SCC_TOK_CASE: {
stmt = parse_case_statement(parser); stmt = parse_case_statement(parser, pos);
goto RETURN; goto RETURN;
} }
case SCC_TOK_DEFAULT: case SCC_TOK_DEFAULT:
stmt = parse_default_statement(parser); stmt = parse_default_statement(parser, pos);
goto RETURN; goto RETURN;
/* /*
(6.8.2) (6.8.2)
@@ -389,7 +405,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
statement statement
*/ */
case SCC_TOK_L_BRACE: case SCC_TOK_L_BRACE:
stmt = parse_compound_statement(parser); stmt = parse_compound_statement(parser, pos);
goto RETURN; goto RETURN;
/* /*
(6.8.4) (6.8.4)
@@ -399,10 +415,10 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
switch ( expression ) statement switch ( expression ) statement
*/ */
case SCC_TOK_IF: case SCC_TOK_IF:
stmt = parse_if_statement(parser); stmt = parse_if_statement(parser, pos);
goto RETURN; goto RETURN;
case SCC_TOK_SWITCH: case SCC_TOK_SWITCH:
stmt = parse_switch_statement(parser); stmt = parse_switch_statement(parser, pos);
goto RETURN; goto RETURN;
/* /*
(6.8.5) (6.8.5)
@@ -415,13 +431,13 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
statement statement
*/ */
case SCC_TOK_WHILE: case SCC_TOK_WHILE:
stmt = parse_while_statement(parser); stmt = parse_while_statement(parser, pos);
goto RETURN; goto RETURN;
case SCC_TOK_DO: case SCC_TOK_DO:
stmt = parse_do_while_statement(parser); stmt = parse_do_while_statement(parser, pos);
goto RETURN; goto RETURN;
case SCC_TOK_FOR: case SCC_TOK_FOR:
stmt = parse_for_statement(parser); stmt = parse_for_statement(parser, pos);
goto RETURN; goto RETURN;
/* /*
(6.8.6) (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_CONTINUE:
case SCC_TOK_BREAK: case SCC_TOK_BREAK:
case SCC_TOK_RETURN: case SCC_TOK_RETURN:
stmt = parse_jump_statement(parser); stmt = parse_jump_statement(parser, pos);
goto RETURN; goto RETURN;
default: default:
break; break;
@@ -445,12 +461,9 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
expression-statement: expression-statement:
expression(opt) ; expression(opt) ;
*/ */
stmt = parse_expression_statement(parser); stmt = parse_expression_statement(parser, pos);
RETURN: RETURN:
scc_parser_reset(parser); scc_parser_reset(parser);
if (stmt) { scc_parse_stmt_sema(parser, stmt);
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
stmt->base.type, stmt);
}
return stmt; return stmt;
} }

View File

@@ -467,7 +467,8 @@ static cbool check_type_combinations(scc_parser_t *parser,
} }
return true; 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) { if (info->user_type) {
return info->user_type; // 假设 parse_struct_union_enum 已分配好节点 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_t *type = ast_type_alloc();
_scc_ast_type_builtin_init(type, builtin); _scc_ast_type_builtin_init(type, builtin, pos);
// 注意限定符const, volatile不应在此处处理应由上层函数负责 // 注意限定符const, volatile不应在此处处理应由上层函数负责
return type; return type;
} }
@@ -564,9 +565,12 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
declarator(opt) : constant-expression declarator(opt) : constant-expression
*/ */
// FIXME check struct/union // 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_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; const char *name = null;
scc_ast_decl_t *decl = null; scc_ast_decl_t *decl = null;
scc_ast_decl_vec_t member; 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)); decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null); Assert(decl != null);
if (type_kind == SCC_AST_TYPE_STRUCT) { 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 { } else {
scc_ast_decl_union_init(decl, name, &member); scc_ast_decl_union_init(decl, name, &member, pos);
} }
scc_parse_decl_sema(parser, decl); scc_parse_decl_sema(parser, decl);
} else { } 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_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; return type;
} }
@@ -649,12 +653,16 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
enumeration-constant enumeration-constant
enumeration-constant = constant-expression 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'"); SCC_ERROR(scc_parser_got_current_pos(parser), "Expected 'enum'");
return null; return null;
} }
scc_lexer_tok_drop(&tok);
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
scc_lexer_tok_t tok;
const char *name = null; const char *name = null;
scc_ast_decl_t *decl = null; scc_ast_decl_t *decl = null;
scc_ast_expr_vec_t member; 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)); decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null); 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); scc_parse_decl_sema(parser, decl);
} else { } else {
if (name == null) { 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_t *type = ast_type_alloc();
scc_ast_type_enum_init(type, name, decl); scc_ast_type_enum_init(type, name, decl, pos);
return type; return type;
} }
@@ -719,6 +727,10 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
return null; return null;
const scc_lexer_tok_t *tok_ptr = null; const scc_lexer_tok_t *tok_ptr = null;
tok_ptr = scc_parser_peek(parser); tok_ptr = scc_parser_peek(parser);
if (tok_ptr == null) {
return null;
}
scc_pos_t pos = tok_ptr->loc;
switch (tok_ptr->type) { switch (tok_ptr->type) {
case SCC_TOK_STRUCT: case SCC_TOK_STRUCT:
@@ -840,7 +852,7 @@ done:
if (!check_type_combinations(parser, &info)) { if (!check_type_combinations(parser, &info)) {
return null; return null;
} }
return build_type_from_info(&info); return build_type_from_info(&info, pos);
duplicate_error: duplicate_error:
SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier"); SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
return null; 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) { if (tok_ptr == null || tok_ptr->type != SCC_TOK_MUL) {
return pointee; return pointee;
} }
scc_pos_t pos = tok_ptr->loc;
scc_parser_next_consume(parser, null); scc_parser_next_consume(parser, null);
scc_ast_type_t *pointer = ast_type_alloc(); 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; *delay_pointee_ptr = pointer;
pointee = 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); pointer->quals = parse_type_qualifier_list(parser, pointer->quals);
return parse_pointer(parser, pointer, delay_pointee_ptr); 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 *param = null;
scc_ast_decl_t *decl = null; scc_ast_decl_t *decl = null;
const scc_lexer_tok_t *tok_ptr = null;
while (1) { while (1) {
// FIXME // FIXME
scc_ast_type_t *type = scc_parse_declaration_specifiers(parser); 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; param->base.type = SCC_AST_DECL_PARAM;
scc_vec_push(*params, 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; 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)); param = scc_malloc(sizeof(scc_ast_decl_t));
Assert(param != null); Assert(param != null);
// FIXME // 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); scc_vec_push(*params, param);
break; break;
} }
@@ -1041,7 +1061,8 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
scc_ast_decl_vec_t params; scc_ast_decl_vec_t params;
parse_function_parameters(parser, &params); parse_function_parameters(parser, &params);
ret = ast_type_alloc(); ret = ast_type_alloc();
scc_ast_type_function_init(ret, base, &params); // FIXME
scc_ast_type_function_init(ret, base, &params, base->base.loc);
return parse_direct_declarator(parser, ret, delay_pointee_ptr, return parse_direct_declarator(parser, ret, delay_pointee_ptr,
tok_ident); tok_ident);
} else { } 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(); scc_ast_type_t *ret = ast_type_alloc();
base = base =
parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident); 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; return ret;
} else { } else {
return base; 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; scc_ast_decl_vec_t params;
parse_function_parameters(parser, &params); parse_function_parameters(parser, &params);
ret = ast_type_alloc(); ret = ast_type_alloc();
scc_ast_type_function_init(ret, base, &params); // FIXME
scc_ast_type_function_init(ret, base, &params, base->base.loc);
return parse_direct_abstract_declarator(parser, ret, return parse_direct_abstract_declarator(parser, ret,
delay_pointee_ptr); delay_pointee_ptr);
} else { } 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(); scc_ast_type_t *ret = ast_type_alloc();
base = base =
parse_direct_abstract_declarator(parser, base, delay_pointee_ptr); 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; return ret;
} else { } else {
return base; return base;
@@ -1157,7 +1181,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
: null; : null;
if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) { 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 // TODO using sema to change it
if (type->quals.is_inline) { if (type->quals.is_inline) {
decl_type->quals.is_inline = true; 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; type->quals.is_inline = false;
} }
} else { } 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) { 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)); decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null); Assert(decl != null);
if (decl_type->base.type == SCC_AST_TYPE_STRUCT) { if (decl_type->base.type == SCC_AST_TYPE_STRUCT) {
scc_ast_decl_struct_init(decl, decl_type->record.name, scc_ast_decl_struct_init(decl, decl_type->record.name, null,
null); decl_type->base.loc);
} else { } 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 { } else {
decl = decl_type->record.decl; 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) { if (decl_type->enumeration.decl == null) {
decl = scc_malloc(sizeof(scc_ast_decl_t)); decl = scc_malloc(sizeof(scc_ast_decl_t));
Assert(decl != null); 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 { } else {
decl = type->enumeration.decl; decl = type->enumeration.decl;
scc_free(decl_type); // FIXME scc_free(decl_type); // FIXME
} }
} else { } else {
decl = scc_malloc(sizeof(scc_ast_decl_t)); 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; return decl;

View File

@@ -1,3 +1,4 @@
#include <scc_pos_log.h>
#include <scc_sema.h> #include <scc_sema.h>
#include <sema_symtab.h> #include <sema_symtab.h>
@@ -10,12 +11,55 @@ static void type_callback(void *context, scc_ast_node_type_t node_type,
return; 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) { void *node) {
scc_sema_symtab_t *sema_symtab = context;
if (node_type == SCC_AST_UNKNOWN || node == null) { if (node_type == SCC_AST_UNKNOWN || node == null) {
return; 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; 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_decl_t *decl = SCC_AST_CAST_TO(scc_ast_decl_t, node);
scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t)); 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; return;
} }
if (decl->base.type == SCC_AST_DECL_STRUCT) { 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_t name = scc_cstring_from_cstr("$S_");
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
&type->base); &type->base);
} else if (decl->base.type == SCC_AST_DECL_UNION) { } 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_t name = scc_cstring_from_cstr("$U_");
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
&type->base); &type->base);
} else if (decl->base.type == SCC_AST_DECL_ENUM) { } 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_t name = scc_cstring_from_cstr("$E_");
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
&type->base); &type->base);
} else if (decl->base.type == SCC_AST_DECL_TYPEDEF) { } 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); scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);
} }
return; return;
@@ -67,8 +111,8 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
} }
callbacks->context = sema_symtab; callbacks->context = sema_symtab;
callbacks->on_decl = decl_callback; callbacks->on_decl = decl_callback;
callbacks->on_expr = null; callbacks->on_expr = expr_callback;
callbacks->on_stmt = null; callbacks->on_stmt = stmt_callback;
callbacks->on_type = type_callback; callbacks->on_type = type_callback;
callbacks->got_type = got_type_callback; callbacks->got_type = got_type_callback;

View File

@@ -0,0 +1,5 @@
#include <utest/acutest.h>
TEST_LIST = {
{NULL, NULL},
};

View File

@@ -69,6 +69,66 @@ scc_pe_section_range scc_pe_reserve_section_header(scc_pe_builder_t *builder,
u32 virtual_size, u32 virtual_size,
u32 data_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_header(scc_pe_builder_t *builder, scc_pe_config_t *config);
void scc_pe_write_section(scc_pe_builder_t *builder, void scc_pe_write_section(scc_pe_builder_t *builder,

View File

@@ -15,6 +15,9 @@
* *
* @bug 可以有更好的方式解决这个问题 * @bug 可以有更好的方式解决这个问题
*/ */
#ifdef DUMMYUNIONNAME
#undef DUMMYUNIONNAME
#endif
#define DUMMYUNIONNAME DUMMYUNIONNAME #define DUMMYUNIONNAME DUMMYUNIONNAME
// 基本类型定义 // 基本类型定义

View File

@@ -10,33 +10,21 @@ typedef struct {
scc_pe_buffer_t data; ///< 具体数据 scc_pe_buffer_t data; ///< 具体数据
scc_hashtable_t str_map; ///< 符号名称映射到data的idx scc_hashtable_t str_map; ///< 符号名称映射到data的idx
u32 section_offset; ///< 在idata中的偏移 u32 section_offset; ///< 在idata中的偏移
} scc_winpe_hnt_builder_t; } scc_pe_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;
typedef SCC_VEC(const char *) scc_winpe_name_vec_t; typedef SCC_VEC(const char *) scc_winpe_name_vec_t;
typedef struct { typedef struct {
const char *name; const char *name;
scc_winpe_name_vec_t symbol_names; scc_winpe_name_vec_t symbol_names;
} scc_winpe_idata_lib_t; } 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 { typedef struct {
scc_pe_buffer_t buffer; ///< 导入表数据 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_hashtable_t iat_map; ///< 符号名称映射到idata的虚拟镜像地址
scc_winpe_idata_lib_vec_t idata_libs; scc_pe_idata_lib_vec_t idata_libs;
} scc_winpe_idata_builder_t; } scc_pe_idata_builder_t;
/** /**
* @brief PE格式导入表构建器初始化 * @brief PE格式导入表构建器初始化
@@ -45,8 +33,8 @@ typedef struct {
* @param builder * @param builder
* @param idata_libs * @param idata_libs
*/ */
void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder, void scc_pe_idata_builder_init(scc_pe_idata_builder_t *builder,
scc_winpe_idata_lib_vec_t *idata_libs); scc_pe_idata_lib_vec_t *idata_libs);
/** /**
* @brief 获取导入表占据的大小 * @brief 获取导入表占据的大小
@@ -55,7 +43,7 @@ void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder,
* @param builder * @param builder
* @return u32 * @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 构造导入表 * @brief 构造导入表
@@ -64,12 +52,11 @@ u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder);
* @param builder * @param builder
* @param idata_range * @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); scc_pe_section_range *idata_range);
// RVA Relative Virtual Address // RVA Relative Virtual Address
static inline u64 static inline u64 scc_pe_idata_get_symbol_rva(scc_pe_idata_builder_t *builder,
scc_pe_idata_get_symbol_rva(scc_winpe_idata_builder_t *builder,
const char *symbol_name) { const char *symbol_name) {
return (u64)scc_hashtable_get(&builder->iat_map, symbol_name); return (u64)scc_hashtable_get(&builder->iat_map, symbol_name);
} }

View File

@@ -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__ */

View File

@@ -13,9 +13,9 @@ image_import_descriptor_init(u32 import_lookup_table_rva, u32 name_rva,
return iid; 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); 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); scc_vec_init(builder->data);
builder->section_offset = 0; builder->section_offset = 0;
scc_hashtable_init(&builder->str_map, 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); (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) { const char *name, u16 hint) {
///< 可选哈希表去重 ///< 可选哈希表去重
if (scc_hashtable_get(&builder->str_map, name)) { 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); 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) { const char *name) {
return (u64)scc_hashtable_get(&builder->str_map, name); return (u64)scc_hashtable_get(&builder->str_map, name);
} }
void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder, void scc_pe_idata_builder_init(scc_pe_idata_builder_t *builder,
scc_winpe_idata_lib_vec_t *idata_libs) { scc_pe_idata_lib_vec_t *idata_libs) {
scc_vec_init(builder->buffer); scc_vec_init(builder->buffer);
builder->idata_libs = *idata_libs; 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); (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) * u32 idata_size = (scc_vec_size(builder->idata_libs) + 1) *
sizeof(IMAGE_IMPORT_DESCRIPTOR); sizeof(IMAGE_IMPORT_DESCRIPTOR);
@@ -89,7 +89,7 @@ u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder) {
return idata_size; 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) { scc_pe_section_range *idata_range) {
u32 idata_rva = idata_range->virual_address; u32 idata_rva = idata_range->virual_address;
u32 hnt_offset = builder->hnt_builder.section_offset; u32 hnt_offset = builder->hnt_builder.section_offset;

View File

View File

@@ -24,19 +24,14 @@ int main() {
scc_pe_builder_t builder = {0}; scc_pe_builder_t builder = {0};
scc_pe_builder_init(&builder, true, 4096, 512); scc_pe_builder_init(&builder, true, 4096, 512);
scc_pe_reserve_header(&builder, 3); scc_pe_reserve_header(&builder, 3);
scc_pe_section_range code_range = scc_pe_reserve_section_header( scc_pe_section_range code_range =
&builder, (BYTE *)".text\0\0", scc_pe_reserve_text_section_header(&builder, sizeof(code));
IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE,
sizeof(code), sizeof(code));
scc_pe_section_range data_range = scc_pe_reserve_section_header( scc_pe_section_range data_range =
&builder, (BYTE *)".data\0\0", scc_pe_reserve_data_section_header(&builder, sizeof(data));
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
IMAGE_SCN_MEM_WRITE,
sizeof(data), sizeof(data));
scc_winpe_idata_builder_t idata_builder; scc_pe_idata_builder_t idata_builder;
scc_winpe_idata_lib_vec_t idata_libs; scc_pe_idata_lib_vec_t idata_libs;
scc_vec_init(idata_libs); scc_vec_init(idata_libs);
scc_winpe_idata_lib_t ucrtbase; scc_winpe_idata_lib_t ucrtbase;
ucrtbase.name = "ucrtbase.dll"; ucrtbase.name = "ucrtbase.dll";
@@ -45,14 +40,8 @@ int main() {
scc_vec_push(idata_libs, ucrtbase); scc_vec_push(idata_libs, ucrtbase);
scc_pe_idata_builder_init(&idata_builder, &idata_libs); scc_pe_idata_builder_init(&idata_builder, &idata_libs);
u32 idata_size = scc_pe_reserve_idata(&idata_builder); u32 idata_size = scc_pe_reserve_idata(&idata_builder);
scc_pe_section_range idata_range = scc_pe_reserve_section_header( scc_pe_section_range idata_range =
&builder, (BYTE *)".idata\0", scc_pe_reserve_idata_section_header(&builder, idata_size);
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_buffer_t idata_buffer = scc_pe_buffer_t idata_buffer =
scc_pe_construct_idata(&idata_builder, &idata_range); scc_pe_construct_idata(&idata_builder, &idata_range);
@@ -97,5 +86,5 @@ int main() {
scc_pe_write_section(&builder, &idata_range, scc_pe_write_section(&builder, &idata_range,
scc_vec_unsafe_get_data(idata_buffer), scc_vec_unsafe_get_data(idata_buffer),
scc_vec_size(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");
} }

View File

@@ -0,0 +1,2 @@
int main(void) { return 0; }

View File

@@ -1,10 +0,0 @@
#include <stdio.h>
void test_example() {
printf("Test passed!\n");
}
int main() {
test_example();
return 0;
}

142
src/config.h Normal file
View File

@@ -0,0 +1,142 @@
#ifndef __SCC_CONFIG_H__
#define __SCC_CONFIG_H__
#include <argparse.h>
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___ */

View File

@@ -7,130 +7,7 @@
#include <scc_ast2ir.h> #include <scc_ast2ir.h>
#include <scc_parser.h> #include <scc_parser.h>
typedef struct { #include "config.h"
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);
}
#ifdef _WIN32 #ifdef _WIN32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
@@ -332,11 +209,10 @@ sstream_drop:
return 0; return 0;
} }
scc_ir_builder_t ir_builder; scc_ast2ir_ctx_t ast2ir_ctx;
scc_ir_builder_init(&ir_builder);
#include <abi/win_x64_type_abi.h> #include <abi/win_x64_type_abi.h>
scc_ast2ir_translation_unit(&ir_builder, translation_unit, scc_ast2ir_ctx_init(&ast2ir_ctx, scc_win_x64_type_abi);
scc_win_x64_type_abi); scc_ast2ir_translation_unit(&ast2ir_ctx, translation_unit);
if (config.emit_ir) { if (config.emit_ir) {
scc_ir_dump_ctx_t ir_dump_ctx; 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, scc_tree_dump_ctx_init(&tree_dump, false, (void *)scc_fprintf,
(void *)fp); (void *)fp);
} }
scc_ir_dump_ctx_init(&ir_dump_ctx, &tree_dump, &ir_builder.cprog, scc_ir_dump_ctx_init(&ir_dump_ctx, &tree_dump,
&ir_builder.ctx); &ast2ir_ctx.builder.cprog,
&ast2ir_ctx.builder.ctx);
// scc_ir_dump_cprog(&ir_dump_ctx); // scc_ir_dump_cprog(&ir_dump_ctx);
scc_ir_dump_cprog_linear(&ir_dump_ctx); scc_ir_dump_cprog_linear(&ir_dump_ctx);
scc_tree_dump_ctx_drop(&tree_dump); scc_tree_dump_ctx_drop(&tree_dump);