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:
@@ -15,6 +15,8 @@ ir 中间代码标识
|
||||
|
||||
opt 优化器
|
||||
|
||||
asm 汇编器
|
||||
|
||||
mcode 机器码
|
||||
|
||||
sccf 统一输出格式
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
typedef enum {
|
||||
SCC_AST_UNKNOWN,
|
||||
// 声明
|
||||
scc_ast_decl_t_BEGIN, // 声明开始
|
||||
scc_ast_decl_t_BEGIN, // 声明开始 sema 函数作用域开始
|
||||
SCC_AST_DECL_LIST, // 声明列表
|
||||
SCC_AST_DECL_VAR, // 变量声明
|
||||
SCC_AST_DECL_FUNC, // 函数声明
|
||||
@@ -19,10 +19,10 @@ typedef enum {
|
||||
SCC_AST_DECL_UNION, // 联合声明
|
||||
SCC_AST_DECL_ENUM, // 枚举声明
|
||||
SCC_AST_DECL_TYPEDEF, // typedef 声明
|
||||
scc_ast_decl_t_END, // 声明结束
|
||||
scc_ast_decl_t_END, // 声明结束 sema 函数作用域结束
|
||||
|
||||
// 语句
|
||||
scc_ast_stmt_t_BEGIN, // 语句开始
|
||||
scc_ast_stmt_t_BEGIN, // 语句开始 sema 作用域开始
|
||||
SCC_AST_STMT_COMPOUND, // 复合语句 { ... }
|
||||
SCC_AST_STMT_EXPR, // 表达式语句
|
||||
SCC_AST_STMT_IF, // if 语句
|
||||
@@ -37,7 +37,7 @@ typedef enum {
|
||||
SCC_AST_STMT_RETURN, // return 语句
|
||||
SCC_AST_STMT_GOTO, // goto 语句
|
||||
SCC_AST_STMT_LABEL, // 标签语句
|
||||
scc_ast_stmt_t_END, // 结束语句
|
||||
scc_ast_stmt_t_END, // 结束语句 sema 作用域结束
|
||||
|
||||
// 表达式
|
||||
scc_ast_expr_t_BEGIN, // 表达式开始
|
||||
@@ -180,7 +180,7 @@ struct scc_ast_type {
|
||||
} array;
|
||||
struct {
|
||||
scc_ast_type_t *return_type;
|
||||
scc_ast_decl_vec_t param_types; // va_list <=> ...
|
||||
scc_ast_decl_vec_t params; // va_list <=> ...
|
||||
} function;
|
||||
struct {
|
||||
const char *name;
|
||||
@@ -294,7 +294,6 @@ struct scc_ast_expr {
|
||||
struct {
|
||||
const char *name;
|
||||
scc_ast_expr_t *callee;
|
||||
scc_ast_expr_t *_target;
|
||||
scc_ast_expr_vec_t args;
|
||||
} call;
|
||||
// 数组下标
|
||||
@@ -306,7 +305,7 @@ struct scc_ast_expr {
|
||||
struct {
|
||||
scc_ast_expr_t *base;
|
||||
const char *name;
|
||||
usize _target_idx;
|
||||
usize _target_idx; ///< fill by sema
|
||||
} member;
|
||||
// cast 类型转换
|
||||
struct {
|
||||
@@ -332,7 +331,7 @@ struct scc_ast_expr {
|
||||
// 标识符
|
||||
struct {
|
||||
const char *name;
|
||||
scc_ast_decl_t *_target;
|
||||
scc_ast_decl_t *_target; ///< fill by sema
|
||||
} identifier;
|
||||
struct {
|
||||
scc_ast_type_t *type;
|
||||
@@ -393,6 +392,7 @@ struct scc_ast_stmt {
|
||||
} default_stmt;
|
||||
// break/continue
|
||||
struct {
|
||||
scc_ast_stmt_t *_target; // fill by sema
|
||||
} jump;
|
||||
// return 语句
|
||||
struct {
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
// decls can be null but maybe warning
|
||||
static inline void
|
||||
scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit,
|
||||
scc_ast_decl_vec_t *decls) {
|
||||
scc_ast_decl_vec_t *decls, scc_pos_t loc) {
|
||||
Assert(translation_unit != null);
|
||||
translation_unit->base.type = SCC_AST_TRANSLATION_UNIT;
|
||||
translation_unit->base.loc = scc_pos_create();
|
||||
translation_unit->base.loc = loc;
|
||||
if (decls == null) {
|
||||
scc_vec_init(translation_unit->declarations);
|
||||
} else {
|
||||
@@ -21,9 +21,10 @@ scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit,
|
||||
}
|
||||
|
||||
static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl,
|
||||
scc_ast_decl_vec_t *list_move) {
|
||||
scc_ast_decl_vec_t *list_move,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null && list_move != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_LIST;
|
||||
decl->name = null;
|
||||
decl->list.vars = *list_move;
|
||||
@@ -34,9 +35,10 @@ static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl,
|
||||
static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_expr_t *var_init) {
|
||||
scc_ast_expr_t *var_init,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null && type != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_VAR;
|
||||
decl->name = name;
|
||||
decl->var.type = type;
|
||||
@@ -46,9 +48,10 @@ static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl,
|
||||
// var_init can be null
|
||||
static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type, const char *name,
|
||||
scc_ast_expr_t *var_init) {
|
||||
scc_ast_expr_t *var_init,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null && name != null && type != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_VAR;
|
||||
decl->name = name;
|
||||
decl->var.type = type;
|
||||
@@ -59,9 +62,9 @@ static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl,
|
||||
static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_stmt_t *body) {
|
||||
scc_ast_stmt_t *body, scc_pos_t loc) {
|
||||
Assert(decl != null && name != null && type != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_FUNC;
|
||||
decl->name = name;
|
||||
decl->func.type = type;
|
||||
@@ -72,9 +75,9 @@ static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
|
||||
// name can be null
|
||||
static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type,
|
||||
const char *name) {
|
||||
const char *name, scc_pos_t loc) {
|
||||
Assert(decl != null && type != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_PARAM;
|
||||
decl->name = name;
|
||||
decl->param.type = type;
|
||||
@@ -83,9 +86,10 @@ static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
|
||||
// name and fields can be null
|
||||
static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
|
||||
const char *name,
|
||||
scc_ast_decl_vec_t *fields_move) {
|
||||
scc_ast_decl_vec_t *fields_move,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_STRUCT;
|
||||
decl->name = name;
|
||||
if (fields_move == null) {
|
||||
@@ -99,9 +103,10 @@ static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
|
||||
// name and fields can be null
|
||||
static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
|
||||
const char *name,
|
||||
scc_ast_decl_vec_t *fields_move) {
|
||||
scc_ast_decl_vec_t *fields_move,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_UNION;
|
||||
decl->name = name;
|
||||
if (fields_move == null) {
|
||||
@@ -115,9 +120,10 @@ static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
|
||||
// name and fields can be null
|
||||
static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl,
|
||||
const char *name,
|
||||
scc_ast_expr_vec_t *fields_move) {
|
||||
scc_ast_expr_vec_t *fields_move,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_ENUM;
|
||||
decl->name = name;
|
||||
if (fields_move == null) {
|
||||
@@ -130,20 +136,20 @@ static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl,
|
||||
|
||||
static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl,
|
||||
const char *name,
|
||||
scc_ast_type_t *type) {
|
||||
scc_ast_type_t *type,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null && name != null && type != null);
|
||||
decl->base.loc = scc_pos_create();
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_TYPEDEF;
|
||||
decl->name = name;
|
||||
decl->typedef_decl.type = type;
|
||||
}
|
||||
|
||||
// items can be null
|
||||
static inline void
|
||||
scc_ast_stmt_compound_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_block_item_vec_t *items_move) {
|
||||
static inline void scc_ast_stmt_compound_init(
|
||||
scc_ast_stmt_t *stmt, scc_ast_block_item_vec_t *items_move, scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_COMPOUND;
|
||||
if (items_move == null) {
|
||||
scc_vec_init(stmt->compound.block_items);
|
||||
@@ -155,9 +161,9 @@ scc_ast_stmt_compound_init(scc_ast_stmt_t *stmt,
|
||||
|
||||
// expr can be null
|
||||
static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *expr) {
|
||||
scc_ast_expr_t *expr, scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_EXPR;
|
||||
stmt->expr.expr = expr;
|
||||
}
|
||||
@@ -166,9 +172,10 @@ static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt,
|
||||
static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *then,
|
||||
scc_ast_stmt_t *opt_else) {
|
||||
scc_ast_stmt_t *opt_else,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && then != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_IF;
|
||||
stmt->if_stmt.cond = cond;
|
||||
stmt->if_stmt.then_stmt = then;
|
||||
@@ -177,9 +184,10 @@ static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt,
|
||||
|
||||
static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *body) {
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && body != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_WHILE;
|
||||
stmt->while_stmt.cond = cond;
|
||||
stmt->while_stmt.body = body;
|
||||
@@ -187,9 +195,10 @@ static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt,
|
||||
|
||||
static inline void scc_ast_stmt_do_while_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *body) {
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && body != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_DO_WHILE;
|
||||
stmt->while_stmt.cond = cond;
|
||||
stmt->while_stmt.body = body;
|
||||
@@ -200,9 +209,9 @@ static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_type_t *init,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_expr_t *incr,
|
||||
scc_ast_stmt_t *body) {
|
||||
scc_ast_stmt_t *body, scc_pos_t loc) {
|
||||
Assert(stmt != null && body != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_FOR;
|
||||
stmt->for_stmt.init = init;
|
||||
stmt->for_stmt.cond = cond;
|
||||
@@ -212,9 +221,10 @@ static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt,
|
||||
|
||||
static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *body) {
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && body != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_SWITCH;
|
||||
stmt->switch_stmt.cond = cond;
|
||||
stmt->switch_stmt.body = body;
|
||||
@@ -222,47 +232,53 @@ static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt,
|
||||
|
||||
static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *body) {
|
||||
scc_ast_stmt_t *body, scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && body != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_CASE;
|
||||
stmt->case_stmt.expr = cond;
|
||||
stmt->case_stmt.stmt = body;
|
||||
}
|
||||
|
||||
static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_stmt_t *body) {
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && body != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_DEFAULT;
|
||||
stmt->default_stmt.stmt = body;
|
||||
}
|
||||
|
||||
static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt) {
|
||||
static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_BREAK;
|
||||
stmt->jump._target = null;
|
||||
}
|
||||
|
||||
static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt) {
|
||||
static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_CONTINUE;
|
||||
stmt->jump._target = null;
|
||||
}
|
||||
|
||||
// expr can be null
|
||||
static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *expr) {
|
||||
scc_ast_expr_t *expr,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_RETURN;
|
||||
stmt->return_stmt.expr = expr;
|
||||
}
|
||||
|
||||
static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt,
|
||||
const char *label) {
|
||||
const char *label, scc_pos_t loc) {
|
||||
Assert(stmt != null && label != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_GOTO;
|
||||
stmt->goto_stmt.label = label;
|
||||
stmt->goto_stmt._target = null;
|
||||
@@ -270,9 +286,10 @@ static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt,
|
||||
|
||||
static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt,
|
||||
const char *label,
|
||||
scc_ast_stmt_t *body) {
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
stmt->base.loc = scc_pos_create();
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_LABEL;
|
||||
stmt->label_stmt.label = label;
|
||||
stmt->label_stmt.stmt = body;
|
||||
@@ -281,9 +298,10 @@ static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt,
|
||||
static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_op_t op,
|
||||
scc_ast_expr_t *lhs,
|
||||
scc_ast_expr_t *rhs) {
|
||||
scc_ast_expr_t *rhs,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && lhs != null && rhs != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_BINARY;
|
||||
expr->binary.op = op;
|
||||
expr->binary.lhs = lhs;
|
||||
@@ -292,9 +310,10 @@ static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr,
|
||||
|
||||
static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_op_t op,
|
||||
scc_ast_expr_t *operand) {
|
||||
scc_ast_expr_t *operand,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && operand != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_UNARY;
|
||||
expr->unary.op = op;
|
||||
expr->unary.operand = operand;
|
||||
@@ -303,10 +322,11 @@ static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr,
|
||||
static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_expr_t *then_expr,
|
||||
scc_ast_expr_t *else_expr) {
|
||||
scc_ast_expr_t *else_expr,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && cond != null && then_expr != null &&
|
||||
else_expr != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_COND;
|
||||
expr->cond.cond = cond;
|
||||
expr->cond.then_expr = then_expr;
|
||||
@@ -316,12 +336,12 @@ static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr,
|
||||
// args can be null
|
||||
static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *callee,
|
||||
scc_ast_expr_vec_t *args) {
|
||||
scc_ast_expr_vec_t *args,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && callee != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_CALL;
|
||||
expr->call.callee = callee;
|
||||
expr->call._target = null;
|
||||
if (args == null) {
|
||||
scc_vec_init(expr->call.args);
|
||||
} else {
|
||||
@@ -332,9 +352,10 @@ static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr,
|
||||
// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标
|
||||
static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *array,
|
||||
scc_ast_expr_t *index) {
|
||||
scc_ast_expr_t *index,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && array != null && index != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT;
|
||||
expr->subscript.array = array;
|
||||
expr->subscript.index = index;
|
||||
@@ -343,9 +364,10 @@ static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr,
|
||||
static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr,
|
||||
scc_ast_node_type_t type,
|
||||
scc_ast_expr_t *object,
|
||||
const char *member) {
|
||||
const char *member,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && object != null && member != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = type;
|
||||
expr->member.base = object;
|
||||
expr->member.name = member;
|
||||
@@ -354,21 +376,24 @@ static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr,
|
||||
|
||||
static inline void scc_ast_expr_member_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *object,
|
||||
const char *member) {
|
||||
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_MEMBER, object, member);
|
||||
const char *member, scc_pos_t loc) {
|
||||
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_MEMBER, object, member, loc);
|
||||
}
|
||||
|
||||
static inline void scc_ast_expr_ptr_member_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *object,
|
||||
const char *member) {
|
||||
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member);
|
||||
const char *member,
|
||||
scc_pos_t loc) {
|
||||
_scc_ast_expr_member_init(expr, SCC_AST_EXPR_PTR_MEMBER, object, member,
|
||||
loc);
|
||||
}
|
||||
|
||||
static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type,
|
||||
scc_ast_expr_t *operand) {
|
||||
scc_ast_expr_t *operand,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && type != null && operand != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_CAST;
|
||||
expr->cast.type = type;
|
||||
expr->cast.expr = operand;
|
||||
@@ -377,9 +402,10 @@ static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr,
|
||||
// type and target_expr can be null but it only one of them can be null
|
||||
static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type,
|
||||
scc_ast_expr_t *target_expr) {
|
||||
scc_ast_expr_t *target_expr,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_SIZE_OF;
|
||||
expr->attr_of.type = type;
|
||||
expr->attr_of.expr = target_expr;
|
||||
@@ -388,10 +414,12 @@ static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr,
|
||||
// type and target_expr can be null but it only one of them can be null
|
||||
static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type,
|
||||
scc_ast_expr_t *target_expr) {
|
||||
scc_ast_expr_t *target_expr,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.type = SCC_AST_EXPR_SIZE_OF;
|
||||
expr->base.loc = loc;
|
||||
expr->base.type =
|
||||
SCC_AST_EXPR_SIZE_OF; // 注意:这里使用了 SIZE_OF,可能需要改为 ALIGN_OF
|
||||
expr->attr_of.type = type;
|
||||
expr->attr_of.expr = target_expr;
|
||||
}
|
||||
@@ -400,9 +428,10 @@ static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
|
||||
static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *base,
|
||||
scc_ast_expr_vec_t *lhs_exprs,
|
||||
scc_ast_expr_vec_t *rhs_exprs) {
|
||||
scc_ast_expr_vec_t *rhs_exprs,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && base != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_COMPOUND;
|
||||
expr->compound.base = base;
|
||||
|
||||
@@ -423,67 +452,77 @@ static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr,
|
||||
|
||||
static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr,
|
||||
scc_ast_node_type_t type,
|
||||
const char *value, cbool owned) {
|
||||
const char *value, cbool owned,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && value != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = type;
|
||||
expr->literal.lexme = value;
|
||||
expr->literal.owned = owned;
|
||||
}
|
||||
|
||||
static inline void scc_ast_expr_literal_int_init(scc_ast_expr_t *expr,
|
||||
const char *value,
|
||||
cbool owned) {
|
||||
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_INT_LITERAL, value, owned);
|
||||
const char *value, cbool owned,
|
||||
scc_pos_t loc) {
|
||||
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_INT_LITERAL, value, owned,
|
||||
loc);
|
||||
}
|
||||
|
||||
static inline void scc_ast_expr_literal_float_init(scc_ast_expr_t *expr,
|
||||
const char *value,
|
||||
cbool owned) {
|
||||
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_FLOAT_LITERAL, value, owned);
|
||||
cbool owned, scc_pos_t loc) {
|
||||
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_FLOAT_LITERAL, value, owned,
|
||||
loc);
|
||||
}
|
||||
static inline void scc_ast_expr_literal_char_init(scc_ast_expr_t *expr,
|
||||
const char *value,
|
||||
cbool owned) {
|
||||
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_CHAR_LITERAL, value, owned);
|
||||
cbool owned, scc_pos_t loc) {
|
||||
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_CHAR_LITERAL, value, owned,
|
||||
loc);
|
||||
}
|
||||
static inline void scc_ast_expr_literal_string_init(scc_ast_expr_t *expr,
|
||||
const char *value,
|
||||
cbool owned) {
|
||||
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_STRING_LITERAL, value, owned);
|
||||
cbool owned,
|
||||
scc_pos_t loc) {
|
||||
scc_ast_expr_literal_init(expr, SCC_AST_EXPR_STRING_LITERAL, value, owned,
|
||||
loc);
|
||||
}
|
||||
|
||||
static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr,
|
||||
const char *name) {
|
||||
const char *name,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && name != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_IDENTIFIER;
|
||||
expr->identifier.name = name;
|
||||
expr->identifier._target = null;
|
||||
}
|
||||
|
||||
static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type) {
|
||||
scc_ast_type_t *type,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && type != null);
|
||||
expr->base.loc = scc_pos_create();
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_LVALUE;
|
||||
expr->lvalue.type = type;
|
||||
}
|
||||
|
||||
// have defined builtin type
|
||||
static inline void _scc_ast_type_builtin_init(scc_ast_type_t *type,
|
||||
scc_ast_builtin_type_t builtin) {
|
||||
scc_ast_builtin_type_t builtin,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_BUILTIN;
|
||||
type->builtin.type = builtin;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
}
|
||||
|
||||
static inline void scc_ast_type_pointer_init(scc_ast_type_t *type,
|
||||
scc_ast_type_t *pointee) {
|
||||
scc_ast_type_t *pointee,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null && pointee != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_POINTER;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
type->pointer.pointee = pointee;
|
||||
@@ -492,9 +531,10 @@ static inline void scc_ast_type_pointer_init(scc_ast_type_t *type,
|
||||
// size can be null
|
||||
static inline void scc_ast_type_array_init(scc_ast_type_t *type,
|
||||
scc_ast_type_t *element,
|
||||
scc_ast_expr_t *size) {
|
||||
scc_ast_expr_t *size,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null && element != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_ARRAY;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
type->array.element = element;
|
||||
@@ -504,16 +544,17 @@ static inline void scc_ast_type_array_init(scc_ast_type_t *type,
|
||||
// return_type and params can be null
|
||||
static inline void scc_ast_type_function_init(scc_ast_type_t *type,
|
||||
scc_ast_type_t *return_type,
|
||||
scc_ast_decl_vec_t *params) {
|
||||
scc_ast_decl_vec_t *params,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_FUNCTION;
|
||||
type->function.return_type = return_type;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
if (params == null) {
|
||||
scc_vec_init(type->function.param_types);
|
||||
scc_vec_init(type->function.params);
|
||||
} else {
|
||||
type->function.param_types = *params;
|
||||
type->function.params = *params;
|
||||
scc_vec_init(*params);
|
||||
}
|
||||
}
|
||||
@@ -521,9 +562,10 @@ static inline void scc_ast_type_function_init(scc_ast_type_t *type,
|
||||
static inline void _scc_ast_type_record_init(scc_ast_type_t *type,
|
||||
scc_ast_node_type_t type_kind,
|
||||
const char *name,
|
||||
scc_ast_decl_t *decl) {
|
||||
scc_ast_decl_t *decl,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.loc = loc;
|
||||
type->base.type = type_kind;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
type->record.name = name;
|
||||
@@ -533,23 +575,25 @@ static inline void _scc_ast_type_record_init(scc_ast_type_t *type,
|
||||
// name and decl can be null
|
||||
static inline void scc_ast_type_struct_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_decl_t *decl) {
|
||||
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl);
|
||||
scc_ast_decl_t *decl,
|
||||
scc_pos_t loc) {
|
||||
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl, loc);
|
||||
}
|
||||
|
||||
// name and decl can be null
|
||||
static inline void scc_ast_type_union_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_decl_t *decl) {
|
||||
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl);
|
||||
scc_ast_decl_t *decl,
|
||||
scc_pos_t loc) {
|
||||
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl, loc);
|
||||
}
|
||||
|
||||
// name and decl can be null
|
||||
static inline void scc_ast_type_enum_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_decl_t *decl) {
|
||||
scc_ast_decl_t *decl, scc_pos_t loc) {
|
||||
Assert(type != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_ENUM;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
type->enumeration.name = name;
|
||||
@@ -558,9 +602,10 @@ static inline void scc_ast_type_enum_init(scc_ast_type_t *type,
|
||||
|
||||
static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_decl_t *target) {
|
||||
scc_ast_decl_t *target,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null && target != null);
|
||||
type->base.loc = scc_pos_create();
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_TYPEDEF;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
type->typedef_type.name = name;
|
||||
|
||||
@@ -347,10 +347,9 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
|
||||
(void)scc_vec_pop(ctx->stack);
|
||||
|
||||
scc_vec_push(ctx->stack, true);
|
||||
if (scc_vec_size(type->function.param_types) != 0) {
|
||||
scc_vec_foreach(type->function.param_types, i) {
|
||||
scc_ast_decl_t *param =
|
||||
scc_vec_at(type->function.param_types, i);
|
||||
if (scc_vec_size(type->function.params) != 0) {
|
||||
scc_vec_foreach(type->function.params, i) {
|
||||
scc_ast_decl_t *param = scc_vec_at(type->function.params, i);
|
||||
if (param->name) {
|
||||
// FIXME param name
|
||||
}
|
||||
|
||||
@@ -5,8 +5,22 @@
|
||||
#include <scc_ast.h>
|
||||
#include <scc_ir.h>
|
||||
|
||||
void scc_ast2ir_translation_unit(scc_ir_builder_t *builder,
|
||||
scc_ast_translation_unit_t *tu,
|
||||
const scc_type_abi_t *abi);
|
||||
typedef struct {
|
||||
scc_ir_builder_t builder;
|
||||
scc_hashtable_t node2ir; ///< decl to ir_ref
|
||||
scc_hashtable_t symtab; ///< symbol to ir_ref
|
||||
scc_strpool_t strpool; ///< string pool
|
||||
const scc_type_abi_t *abi;
|
||||
} scc_ast2ir_ctx_t;
|
||||
|
||||
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi);
|
||||
|
||||
void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast_translation_unit_t *tu);
|
||||
void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl);
|
||||
scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr);
|
||||
void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt);
|
||||
scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast_type_t *ast_type);
|
||||
|
||||
#endif /* __SCC_AST2IR_H__ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
530
libs/ast2ir/src/scc_ast2ir.c
Normal file
530
libs/ast2ir/src/scc_ast2ir.c
Normal 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);
|
||||
}
|
||||
@@ -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 = {
|
||||
|
||||
};
|
||||
|
||||
@@ -56,6 +56,15 @@ void scc_ir_builder_end_func(scc_ir_builder_t *builder);
|
||||
*/
|
||||
scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder);
|
||||
|
||||
/**
|
||||
* @brief 创建一个新的基本块,并自动添加到当前函数中,但不改变当前块。
|
||||
* @param builder IR构建器
|
||||
* @param label 基本块标签(可为 NULL,自动生成)
|
||||
* @return 新基本块的引用
|
||||
*/
|
||||
scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder,
|
||||
const char *label);
|
||||
|
||||
/**
|
||||
* @brief 开始构建新的基本块
|
||||
* @param label 基本块标签(可为NULL,自动生成)
|
||||
|
||||
@@ -52,8 +52,8 @@ typedef enum scc_ir_type_tag {
|
||||
|
||||
struct scc_ir_type {
|
||||
scc_ir_type_tag_t tag;
|
||||
// int size; // 字节大小
|
||||
// int align; // 对齐要求
|
||||
int size; // 字节大小
|
||||
int align; // 对齐要求
|
||||
union {
|
||||
struct {
|
||||
scc_ir_type_ref_t base;
|
||||
@@ -85,6 +85,8 @@ struct scc_ir_func {
|
||||
typedef enum scc_ir_node_tag {
|
||||
SCC_IR_NODE_NULL,
|
||||
SCC_IR_NODE_CONST_INT,
|
||||
SCC_IR_NODE_CONST_UINT,
|
||||
SCC_IR_NODE_CONST_FLOAT,
|
||||
SCC_IR_NODE_CONV, ///< 类型转换
|
||||
SCC_IR_NODE_FUNC_ARG_REF, ///< 函数参数引用
|
||||
SCC_IR_NODE_BLOCK_ARG_REF, ///< 基本块参数引用
|
||||
|
||||
@@ -80,8 +80,8 @@ scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder) {
|
||||
return builder->current_func;
|
||||
}
|
||||
|
||||
scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder,
|
||||
const char *label) {
|
||||
scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder,
|
||||
const char *label) {
|
||||
scc_ir_bblock_t bblock = {0};
|
||||
|
||||
if (label) {
|
||||
@@ -100,16 +100,22 @@ scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder,
|
||||
|
||||
scc_ir_bblock_ref_t bblock_ref =
|
||||
scc_ir_ctx_new_bblock(&builder->ctx, &bblock);
|
||||
builder->current_bblock = bblock_ref;
|
||||
return bblock_ref;
|
||||
}
|
||||
|
||||
scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder,
|
||||
const char *label) {
|
||||
|
||||
builder->current_bblock = scc_ir_builder_bblock(builder, label);
|
||||
|
||||
// 将基本块添加到当前函数
|
||||
scc_ir_func_t *current_func =
|
||||
scc_ir_ctx_get_func(&builder->ctx, builder->current_func);
|
||||
if (current_func) {
|
||||
scc_vec_push(current_func->bblocks, bblock_ref);
|
||||
scc_vec_push(current_func->bblocks, builder->current_bblock);
|
||||
}
|
||||
|
||||
return bblock_ref;
|
||||
return builder->current_bblock;
|
||||
}
|
||||
|
||||
void scc_ir_builder_end_bblock(scc_ir_builder_t *builder) {
|
||||
@@ -152,13 +158,13 @@ scc_ir_node_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
|
||||
}
|
||||
|
||||
scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
|
||||
scc_ir_node_ref_t ptr) {
|
||||
scc_ir_node_ref_t target) {
|
||||
scc_ir_node_t load_node = {0};
|
||||
load_node.tag = SCC_IR_NODE_LOAD;
|
||||
load_node.data.load.target = ptr;
|
||||
load_node.data.load.target = target;
|
||||
|
||||
// 设置类型为指针指向的类型
|
||||
scc_ir_node_t *ptr_node = scc_ir_ctx_get_node(&builder->ctx, ptr);
|
||||
scc_ir_node_t *ptr_node = scc_ir_ctx_get_node(&builder->ctx, target);
|
||||
if (ptr_node) {
|
||||
scc_ir_type_t *ptr_type =
|
||||
scc_ir_ctx_get_type(&builder->ctx, ptr_node->type);
|
||||
@@ -176,11 +182,11 @@ scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
|
||||
}
|
||||
|
||||
scc_ir_node_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
|
||||
scc_ir_node_ref_t ptr,
|
||||
scc_ir_node_ref_t target,
|
||||
scc_ir_node_ref_t value) {
|
||||
scc_ir_node_t store_node = {0};
|
||||
store_node.tag = SCC_IR_NODE_STORE;
|
||||
store_node.data.store.target = ptr;
|
||||
store_node.data.store.target = target;
|
||||
store_node.data.store.value = value;
|
||||
|
||||
scc_ir_node_ref_t node_ref =
|
||||
@@ -193,15 +199,15 @@ scc_ir_node_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
|
||||
}
|
||||
|
||||
scc_ir_node_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
|
||||
scc_ir_node_ref_t ptr,
|
||||
scc_ir_node_ref_t target,
|
||||
scc_ir_node_ref_t index) {
|
||||
scc_ir_node_t get_ptr_node = {0};
|
||||
get_ptr_node.tag = SCC_IR_NODE_GET_PTR;
|
||||
get_ptr_node.data.get_ptr.src_addr = ptr;
|
||||
get_ptr_node.data.get_ptr.src_addr = target;
|
||||
get_ptr_node.data.get_ptr.index = index;
|
||||
|
||||
// 类型应与源地址相同(都是指针)
|
||||
scc_ir_node_t *src_node = scc_ir_ctx_get_node(&builder->ctx, ptr);
|
||||
scc_ir_node_t *src_node = scc_ir_ctx_get_node(&builder->ctx, target);
|
||||
if (src_node) {
|
||||
get_ptr_node.type = src_node->type;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,20 @@ static inline void scc_parse_decl_sema(scc_parser_t *parser,
|
||||
decl);
|
||||
}
|
||||
|
||||
static inline void scc_parse_expr_sema(scc_parser_t *parser,
|
||||
scc_ast_expr_t *expr) {
|
||||
parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
|
||||
expr ? expr->base.type : SCC_AST_UNKNOWN,
|
||||
expr);
|
||||
}
|
||||
|
||||
static inline void scc_parse_stmt_sema(scc_parser_t *parser,
|
||||
scc_ast_stmt_t *stmt) {
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
stmt ? stmt->base.type : SCC_AST_UNKNOWN,
|
||||
stmt);
|
||||
}
|
||||
|
||||
static inline void scc_parse_type_sema(scc_parser_t *parser,
|
||||
scc_ast_type_t *type) {
|
||||
parser->sema_callbacks.on_type(parser->sema_callbacks.context,
|
||||
|
||||
@@ -182,7 +182,9 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
init = scc_parse_assignment_expression(parser);
|
||||
return init;
|
||||
}
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
init = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(init != null);
|
||||
@@ -202,8 +204,8 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(lhs != null);
|
||||
scc_ast_expr_member_init(lhs, ptr,
|
||||
scc_cstring_as_cstr(&tok.lexeme));
|
||||
scc_ast_expr_member_init(
|
||||
lhs, ptr, scc_cstring_as_cstr(&tok.lexeme), tok.loc);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
ptr = lhs;
|
||||
continue;
|
||||
@@ -230,7 +232,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
}
|
||||
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(lhs != null);
|
||||
scc_ast_expr_array_subscript_init(lhs, ptr, idx);
|
||||
scc_ast_expr_array_subscript_init(lhs, ptr, idx, tok_ptr->loc);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
ptr = lhs;
|
||||
continue;
|
||||
@@ -253,7 +255,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_vec_push(rhs_exprs, expr);
|
||||
}
|
||||
}
|
||||
scc_ast_expr_compound_init(init, base, &lhs_exprs, &rhs_exprs);
|
||||
scc_ast_expr_compound_init(init, base, &lhs_exprs, &rhs_exprs, pos);
|
||||
return init;
|
||||
}
|
||||
|
||||
@@ -283,10 +285,14 @@ CONTINUE:
|
||||
scc_parser_next_consume(parser, null);
|
||||
// TODO maybe memory leak
|
||||
scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(lvalue, decl->var.type);
|
||||
scc_ast_expr_lvalue_init(lvalue, decl->var.type, decl->base.loc);
|
||||
decl->var.init = scc_parse_initializer(parser, lvalue);
|
||||
} else if (tok_ptr->type == SCC_TOK_L_BRACE) {
|
||||
parser->sema_callbacks.on_decl(parser->sema_callbacks.context,
|
||||
scc_ast_decl_t_BEGIN, null);
|
||||
scc_ast_stmt_t *body = scc_parse_statement(parser);
|
||||
parser->sema_callbacks.on_decl(parser->sema_callbacks.context,
|
||||
scc_ast_decl_t_END, null);
|
||||
Assert(decl->base.type == SCC_AST_DECL_FUNC);
|
||||
decl->func.body = body;
|
||||
Assert(decl->func.type != null);
|
||||
@@ -305,10 +311,12 @@ CONTINUE:
|
||||
if (decl_list) {
|
||||
scc_vec_foreach(decl_list_vec, i) {
|
||||
decl = scc_vec_at(decl_list_vec, i);
|
||||
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type);
|
||||
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type,
|
||||
decl->base.loc);
|
||||
}
|
||||
} else {
|
||||
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type);
|
||||
scc_ast_decl_typedef_init(decl, decl->name, decl->var.type,
|
||||
decl->base.loc);
|
||||
}
|
||||
}
|
||||
if (decl_list != null) {
|
||||
@@ -316,7 +324,9 @@ CONTINUE:
|
||||
decl = scc_vec_at(decl_list_vec, i);
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
}
|
||||
scc_ast_decl_list_init(decl_list, &decl_list_vec);
|
||||
// FIXME
|
||||
scc_ast_decl_list_init(decl_list, &decl_list_vec,
|
||||
scc_vec_at(decl_list_vec, 0)->base.loc);
|
||||
decl = decl_list;
|
||||
} else {
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
|
||||
@@ -374,7 +374,8 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_binary_init(expr, op, left, right);
|
||||
// FIXME pos
|
||||
scc_ast_expr_binary_init(expr, op, left, right, left->base.loc);
|
||||
left = expr;
|
||||
}
|
||||
return left;
|
||||
@@ -391,6 +392,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (!tok_ptr)
|
||||
return left;
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
|
||||
int prec = get_token_precedence(tok_ptr->type);
|
||||
if (prec == PREC_ASSIGNMENT && is_binary_operator(tok_ptr->type)) {
|
||||
@@ -411,7 +413,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_binary_init(expr, op, left, right);
|
||||
scc_ast_expr_binary_init(expr, op, left, right, pos);
|
||||
left = expr;
|
||||
}
|
||||
return left;
|
||||
@@ -425,6 +427,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
return null;
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_COND) {
|
||||
// 消耗 '?'
|
||||
scc_lexer_tok_t q_tok;
|
||||
@@ -456,7 +459,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_expr_t *cond = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(cond != null);
|
||||
scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr);
|
||||
scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr, pos);
|
||||
cond_expr = cond;
|
||||
}
|
||||
return cond_expr;
|
||||
@@ -480,13 +483,15 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
if (!operand) {
|
||||
// FIXME postfix-expression
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(expr, type);
|
||||
// FIXME pos
|
||||
scc_ast_expr_lvalue_init(expr, type, type->base.loc);
|
||||
operand = scc_parse_initializer(parser, expr);
|
||||
return operand;
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_cast_init(expr, type, operand);
|
||||
// FIXME pos
|
||||
scc_ast_expr_cast_init(expr, type, operand, type->base.loc);
|
||||
return expr;
|
||||
} else {
|
||||
// 不是类型转换,回退
|
||||
@@ -538,6 +543,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return null;
|
||||
scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true);
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
// 一元运算符右结合,递归调用 parse_unary_expression
|
||||
@@ -556,7 +562,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_unary_init(expr, op, operand);
|
||||
scc_ast_expr_unary_init(expr, op, operand, pos);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_SIZEOF:
|
||||
@@ -573,6 +579,7 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
tok_ptr.type != SCC_TOK_SIZEOF) {
|
||||
return null;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr.loc;
|
||||
scc_lexer_tok_drop(&tok_ptr);
|
||||
|
||||
const scc_lexer_tok_t *next = scc_parser_peek(parser);
|
||||
@@ -599,14 +606,14 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
Assert(type_name != null);
|
||||
scc_ast_expr_sizeof_init(expr, type_name, null);
|
||||
scc_ast_expr_sizeof_init(expr, type_name, null, pos);
|
||||
return expr;
|
||||
}
|
||||
next:
|
||||
// 尝试解析 sizeof unary-expression
|
||||
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
||||
if (operand != null) {
|
||||
scc_ast_expr_sizeof_init(expr, null, operand);
|
||||
scc_ast_expr_sizeof_init(expr, null, operand, pos);
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -618,11 +625,14 @@ next:
|
||||
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *left = parse_primary_expression(parser);
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
scc_pos_t pos = scc_pos_create();
|
||||
if (!left) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN)) {
|
||||
return null;
|
||||
}
|
||||
pos = tok_ptr->loc;
|
||||
|
||||
scc_parser_store(parser);
|
||||
scc_parser_next(parser);
|
||||
scc_ast_type_t *type = scc_parse_type_name(parser);
|
||||
@@ -635,7 +645,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'");
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(expr, type);
|
||||
scc_ast_expr_lvalue_init(expr, type, pos);
|
||||
left = scc_parse_initializer(parser, expr);
|
||||
return left;
|
||||
}
|
||||
@@ -650,6 +660,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
{
|
||||
if (!scc_parser_next_consume(parser, null))
|
||||
return left;
|
||||
pos = left->base.loc;
|
||||
|
||||
scc_ast_expr_t *index = scc_parse_expression(parser);
|
||||
if (!index) {
|
||||
@@ -664,7 +675,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
}
|
||||
scc_ast_expr_t *subscript = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(subscript != null);
|
||||
scc_ast_expr_array_subscript_init(subscript, left, index);
|
||||
scc_ast_expr_array_subscript_init(subscript, left, index, pos);
|
||||
left = subscript;
|
||||
break;
|
||||
}
|
||||
@@ -672,6 +683,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
{
|
||||
if (!scc_parser_next_consume(parser, null))
|
||||
return left;
|
||||
pos = left->base.loc;
|
||||
scc_ast_expr_vec_t args;
|
||||
scc_vec_init(args);
|
||||
|
||||
@@ -700,7 +712,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
}
|
||||
scc_ast_expr_t *call = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(call != null);
|
||||
scc_ast_expr_call_init(call, left, &args);
|
||||
scc_ast_expr_call_init(call, left, &args, pos);
|
||||
left = call;
|
||||
break;
|
||||
}
|
||||
@@ -723,9 +735,9 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(member != null);
|
||||
if (op_tok.type == SCC_TOK_DOT) {
|
||||
scc_ast_expr_member_init(member, left, name);
|
||||
scc_ast_expr_member_init(member, left, name, ident_tok.loc);
|
||||
} else {
|
||||
scc_ast_expr_ptr_member_init(member, left, name);
|
||||
scc_ast_expr_ptr_member_init(member, left, name, ident_tok.loc);
|
||||
}
|
||||
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
@@ -739,10 +751,10 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
if (!scc_parser_next_consume(parser, &op_tok))
|
||||
return left;
|
||||
scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false);
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_unary_init(expr, op, left);
|
||||
scc_ast_expr_unary_init(expr, op, left, op_tok.loc);
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
left = expr;
|
||||
break;
|
||||
}
|
||||
@@ -776,7 +788,8 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
return null;
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_identifier_init(expr, scc_cstring_as_cstr(&tok.lexeme));
|
||||
scc_ast_expr_identifier_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_INT_LITERAL: {
|
||||
@@ -785,7 +798,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_literal_int_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
false);
|
||||
false, tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_FLOAT_LITERAL: {
|
||||
@@ -794,7 +807,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_literal_float_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
false);
|
||||
false, tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_CHAR_LITERAL: {
|
||||
@@ -803,7 +816,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_literal_char_init(expr, scc_cstring_as_cstr(&tok.lexeme),
|
||||
false);
|
||||
false, tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_STRING_LITERAL: {
|
||||
@@ -825,8 +838,9 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
// FIXME loc
|
||||
scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string),
|
||||
true);
|
||||
true, tok.loc);
|
||||
return expr;
|
||||
}
|
||||
case SCC_TOK_L_PAREN:
|
||||
@@ -847,7 +861,12 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
if (!left)
|
||||
return null;
|
||||
|
||||
while (scc_parser_consume_if(parser, SCC_TOK_COMMA)) {
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null || tok_ptr->type != SCC_TOK_COMMA) {
|
||||
break;
|
||||
}
|
||||
scc_ast_expr_t *right = scc_parse_assignment_expression(parser);
|
||||
if (!right) {
|
||||
parser_sync(parser);
|
||||
@@ -855,7 +874,8 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right);
|
||||
scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right,
|
||||
tok_ptr->loc);
|
||||
left = expr;
|
||||
}
|
||||
return left;
|
||||
|
||||
@@ -73,7 +73,8 @@ static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
scc_lexer_tok_t tok = {0};
|
||||
if (!scc_parser_next_consume(parser, &tok)) {
|
||||
return null;
|
||||
@@ -91,11 +92,13 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) {
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
Assert(stmt != null);
|
||||
scc_ast_stmt_label_init(stmt, scc_cstring_as_cstr(&tok.lexeme), statement);
|
||||
scc_ast_stmt_label_init(stmt, scc_cstring_as_cstr(&tok.lexeme), statement,
|
||||
pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_CASE)) {
|
||||
return null;
|
||||
}
|
||||
@@ -120,11 +123,12 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_case_init(stmt, expr, statement);
|
||||
scc_ast_stmt_case_init(stmt, expr, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_DEFAULT)) {
|
||||
return null;
|
||||
}
|
||||
@@ -141,17 +145,20 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_default_init(stmt, statement);
|
||||
scc_ast_stmt_default_init(stmt, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) {
|
||||
return null;
|
||||
}
|
||||
scc_ast_block_item_vec_t block_items;
|
||||
scc_vec_init(block_items);
|
||||
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
scc_ast_stmt_t_BEGIN, null);
|
||||
while (!scc_parser_consume_if(parser, SCC_TOK_R_BRACE)) {
|
||||
/// TODO
|
||||
// scc_parse_is_decl();
|
||||
@@ -168,13 +175,15 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
|
||||
}
|
||||
scc_vec_push(block_items, ret);
|
||||
}
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
scc_ast_stmt_t_END, null);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_compound_init(stmt, &block_items);
|
||||
scc_ast_stmt_compound_init(stmt, &block_items, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_IF)) {
|
||||
return null;
|
||||
}
|
||||
@@ -190,11 +199,12 @@ static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_if_init(stmt, expression, statement, opt_else);
|
||||
scc_ast_stmt_if_init(stmt, expression, statement, opt_else, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) {
|
||||
return null;
|
||||
}
|
||||
@@ -203,11 +213,12 @@ static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser) {
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_switch_init(stmt, expression, statement);
|
||||
scc_ast_stmt_switch_init(stmt, expression, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
|
||||
return null;
|
||||
}
|
||||
@@ -216,11 +227,12 @@ static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser) {
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_while_init(stmt, expression, statement);
|
||||
scc_ast_stmt_while_init(stmt, expression, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_DO)) {
|
||||
return null;
|
||||
}
|
||||
@@ -237,11 +249,12 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_do_while_init(stmt, expression, statement);
|
||||
scc_ast_stmt_do_while_init(stmt, expression, statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_FOR)) {
|
||||
return null;
|
||||
}
|
||||
@@ -288,27 +301,28 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
|
||||
body = scc_parse_statement(parser);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_for_init(stmt, init, cond, incr, body);
|
||||
scc_ast_stmt_for_init(stmt, init, cond, incr, body, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) {
|
||||
scc_lexer_tok_t tok = {0};
|
||||
if (scc_parser_next_consume(parser, &tok)) {
|
||||
scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme));
|
||||
scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme), pos);
|
||||
} else {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected label after goto.");
|
||||
}
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_CONTINUE)) {
|
||||
scc_ast_stmt_continue_init(stmt);
|
||||
scc_ast_stmt_continue_init(stmt, pos);
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_BREAK)) {
|
||||
scc_ast_stmt_break_init(stmt);
|
||||
scc_ast_stmt_break_init(stmt, pos);
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_RETURN)) {
|
||||
scc_ast_stmt_return_init(stmt, scc_parse_expression(parser));
|
||||
scc_ast_stmt_return_init(stmt, scc_parse_expression(parser), pos);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
@@ -320,11 +334,12 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) {
|
||||
static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_expr_init(stmt, null);
|
||||
scc_ast_stmt_expr_init(stmt, null, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -334,7 +349,7 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_expr_init(stmt, expr);
|
||||
scc_ast_stmt_expr_init(stmt, expr, pos);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
@@ -350,6 +365,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
if (!tok_ref) {
|
||||
return null;
|
||||
}
|
||||
scc_pos_t pos = tok_ref->loc;
|
||||
switch (tok_ref->type) {
|
||||
/*
|
||||
(6.8.1)
|
||||
@@ -366,14 +382,14 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
scc_parser_reset(parser);
|
||||
stmt = parse_label_statement(parser);
|
||||
stmt = parse_label_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_CASE: {
|
||||
stmt = parse_case_statement(parser);
|
||||
stmt = parse_case_statement(parser, pos);
|
||||
goto RETURN;
|
||||
}
|
||||
case SCC_TOK_DEFAULT:
|
||||
stmt = parse_default_statement(parser);
|
||||
stmt = parse_default_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
(6.8.2)
|
||||
@@ -389,7 +405,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
statement
|
||||
*/
|
||||
case SCC_TOK_L_BRACE:
|
||||
stmt = parse_compound_statement(parser);
|
||||
stmt = parse_compound_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
(6.8.4)
|
||||
@@ -399,10 +415,10 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
switch ( expression ) statement
|
||||
*/
|
||||
case SCC_TOK_IF:
|
||||
stmt = parse_if_statement(parser);
|
||||
stmt = parse_if_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_SWITCH:
|
||||
stmt = parse_switch_statement(parser);
|
||||
stmt = parse_switch_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
(6.8.5)
|
||||
@@ -415,13 +431,13 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
statement
|
||||
*/
|
||||
case SCC_TOK_WHILE:
|
||||
stmt = parse_while_statement(parser);
|
||||
stmt = parse_while_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_DO:
|
||||
stmt = parse_do_while_statement(parser);
|
||||
stmt = parse_do_while_statement(parser, pos);
|
||||
goto RETURN;
|
||||
case SCC_TOK_FOR:
|
||||
stmt = parse_for_statement(parser);
|
||||
stmt = parse_for_statement(parser, pos);
|
||||
goto RETURN;
|
||||
/*
|
||||
(6.8.6)
|
||||
@@ -435,7 +451,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
case SCC_TOK_CONTINUE:
|
||||
case SCC_TOK_BREAK:
|
||||
case SCC_TOK_RETURN:
|
||||
stmt = parse_jump_statement(parser);
|
||||
stmt = parse_jump_statement(parser, pos);
|
||||
goto RETURN;
|
||||
default:
|
||||
break;
|
||||
@@ -445,12 +461,9 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
expression-statement:
|
||||
expression(opt) ;
|
||||
*/
|
||||
stmt = parse_expression_statement(parser);
|
||||
stmt = parse_expression_statement(parser, pos);
|
||||
RETURN:
|
||||
scc_parser_reset(parser);
|
||||
if (stmt) {
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
stmt->base.type, stmt);
|
||||
}
|
||||
scc_parse_stmt_sema(parser, stmt);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
@@ -467,7 +467,8 @@ static cbool check_type_combinations(scc_parser_t *parser,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static scc_ast_type_t *build_type_from_info(type_spec_info_t *info) {
|
||||
static scc_ast_type_t *build_type_from_info(type_spec_info_t *info,
|
||||
scc_pos_t pos) {
|
||||
// 如果有用户定义类型,直接返回(注意可能需要复制或共享)
|
||||
if (info->user_type) {
|
||||
return info->user_type; // 假设 parse_struct_union_enum 已分配好节点
|
||||
@@ -528,7 +529,7 @@ static scc_ast_type_t *build_type_from_info(type_spec_info_t *info) {
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
_scc_ast_type_builtin_init(type, builtin);
|
||||
_scc_ast_type_builtin_init(type, builtin, pos);
|
||||
// 注意:限定符(const, volatile)不应在此处处理,应由上层函数负责
|
||||
return type;
|
||||
}
|
||||
@@ -564,9 +565,12 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
declarator(opt) : constant-expression
|
||||
*/
|
||||
// FIXME check struct/union
|
||||
scc_parser_next_consume(parser, null);
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
scc_lexer_tok_t tok;
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
const char *name = null;
|
||||
scc_ast_decl_t *decl = null;
|
||||
scc_ast_decl_vec_t member;
|
||||
@@ -614,9 +618,9 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
if (type_kind == SCC_AST_TYPE_STRUCT) {
|
||||
scc_ast_decl_struct_init(decl, name, &member);
|
||||
scc_ast_decl_struct_init(decl, name, &member, pos);
|
||||
} else {
|
||||
scc_ast_decl_union_init(decl, name, &member);
|
||||
scc_ast_decl_union_init(decl, name, &member, pos);
|
||||
}
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
} else {
|
||||
@@ -629,7 +633,7 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
_scc_ast_type_record_init(type, type_kind, name, decl);
|
||||
_scc_ast_type_record_init(type, type_kind, name, decl, pos);
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -649,12 +653,16 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
enumeration-constant
|
||||
enumeration-constant = constant-expression
|
||||
*/
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ENUM)) {
|
||||
scc_lexer_tok_t tok;
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
scc_pos_t pos = tok.loc;
|
||||
if (tok.type != SCC_TOK_ENUM) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected 'enum'");
|
||||
return null;
|
||||
}
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
scc_lexer_tok_t tok;
|
||||
const char *name = null;
|
||||
scc_ast_decl_t *decl = null;
|
||||
scc_ast_expr_vec_t member;
|
||||
@@ -697,7 +705,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
}
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
scc_ast_decl_enum_init(decl, name, &member);
|
||||
scc_ast_decl_enum_init(decl, name, &member, pos);
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
} else {
|
||||
if (name == null) {
|
||||
@@ -709,7 +717,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
scc_ast_type_enum_init(type, name, decl);
|
||||
scc_ast_type_enum_init(type, name, decl, pos);
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -719,6 +727,10 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
return null;
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
return null;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
|
||||
switch (tok_ptr->type) {
|
||||
case SCC_TOK_STRUCT:
|
||||
@@ -840,7 +852,7 @@ done:
|
||||
if (!check_type_combinations(parser, &info)) {
|
||||
return null;
|
||||
}
|
||||
return build_type_from_info(&info);
|
||||
return build_type_from_info(&info, pos);
|
||||
duplicate_error:
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
|
||||
return null;
|
||||
@@ -858,6 +870,7 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser,
|
||||
if (tok_ptr == null || tok_ptr->type != SCC_TOK_MUL) {
|
||||
return pointee;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
scc_parser_next_consume(parser, null);
|
||||
|
||||
scc_ast_type_t *pointer = ast_type_alloc();
|
||||
@@ -866,7 +879,7 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser,
|
||||
*delay_pointee_ptr = pointer;
|
||||
pointee = pointer;
|
||||
}
|
||||
scc_ast_type_pointer_init(pointer, pointee);
|
||||
scc_ast_type_pointer_init(pointer, pointee, pos);
|
||||
pointer->quals = parse_type_qualifier_list(parser, pointer->quals);
|
||||
|
||||
return parse_pointer(parser, pointer, delay_pointee_ptr);
|
||||
@@ -887,6 +900,7 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
*/
|
||||
scc_ast_decl_t *param = null;
|
||||
scc_ast_decl_t *decl = null;
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
while (1) {
|
||||
// FIXME
|
||||
scc_ast_type_t *type = scc_parse_declaration_specifiers(parser);
|
||||
@@ -904,14 +918,20 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
param->base.type = SCC_AST_DECL_PARAM;
|
||||
|
||||
scc_vec_push(*params, param);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COMMA)) {
|
||||
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type != SCC_TOK_COMMA) {
|
||||
break;
|
||||
}
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_ELLIPSIS)) {
|
||||
|
||||
scc_parser_next_consume(parser, null);
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type == SCC_TOK_ELLIPSIS) {
|
||||
param = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(param != null);
|
||||
// FIXME
|
||||
scc_ast_decl_param_init(param, &scc_ast_builtin_type_va_list, null);
|
||||
scc_ast_decl_param_init(param, &scc_ast_builtin_type_va_list, null,
|
||||
tok_ptr->loc);
|
||||
scc_vec_push(*params, param);
|
||||
break;
|
||||
}
|
||||
@@ -1041,7 +1061,8 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_decl_vec_t params;
|
||||
parse_function_parameters(parser, ¶ms);
|
||||
ret = ast_type_alloc();
|
||||
scc_ast_type_function_init(ret, base, ¶ms);
|
||||
// FIXME
|
||||
scc_ast_type_function_init(ret, base, ¶ms, base->base.loc);
|
||||
return parse_direct_declarator(parser, ret, delay_pointee_ptr,
|
||||
tok_ident);
|
||||
} else {
|
||||
@@ -1063,7 +1084,8 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t *ret = ast_type_alloc();
|
||||
base =
|
||||
parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident);
|
||||
scc_ast_type_array_init(ret, base, size);
|
||||
// FIXME
|
||||
scc_ast_type_array_init(ret, base, size, base->base.loc);
|
||||
return ret;
|
||||
} else {
|
||||
return base;
|
||||
@@ -1112,7 +1134,8 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_decl_vec_t params;
|
||||
parse_function_parameters(parser, ¶ms);
|
||||
ret = ast_type_alloc();
|
||||
scc_ast_type_function_init(ret, base, ¶ms);
|
||||
// FIXME
|
||||
scc_ast_type_function_init(ret, base, ¶ms, base->base.loc);
|
||||
return parse_direct_abstract_declarator(parser, ret,
|
||||
delay_pointee_ptr);
|
||||
} else {
|
||||
@@ -1133,7 +1156,8 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t *ret = ast_type_alloc();
|
||||
base =
|
||||
parse_direct_abstract_declarator(parser, base, delay_pointee_ptr);
|
||||
scc_ast_type_array_init(ret, base, size);
|
||||
// FIXME
|
||||
scc_ast_type_array_init(ret, base, size, base->base.loc);
|
||||
return ret;
|
||||
} else {
|
||||
return base;
|
||||
@@ -1157,7 +1181,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
: null;
|
||||
|
||||
if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) {
|
||||
scc_ast_decl_func_init(decl, decl_type, name, null);
|
||||
scc_ast_decl_func_init(decl, decl_type, name, null, decl_name_tok.loc);
|
||||
// TODO using sema to change it
|
||||
if (type->quals.is_inline) {
|
||||
decl_type->quals.is_inline = true;
|
||||
@@ -1165,7 +1189,8 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
type->quals.is_inline = false;
|
||||
}
|
||||
} else {
|
||||
scc_ast_decl_unsafe_val_init(decl, decl_type, name, null);
|
||||
scc_ast_decl_unsafe_val_init(decl, decl_type, name, null,
|
||||
decl_name_tok.loc);
|
||||
}
|
||||
|
||||
if (decl_name_tok.type != SCC_TOK_IDENT) {
|
||||
@@ -1175,10 +1200,11 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
if (decl_type->base.type == SCC_AST_TYPE_STRUCT) {
|
||||
scc_ast_decl_struct_init(decl, decl_type->record.name,
|
||||
null);
|
||||
scc_ast_decl_struct_init(decl, decl_type->record.name, null,
|
||||
decl_type->base.loc);
|
||||
} else {
|
||||
scc_ast_decl_union_init(decl, decl_type->record.name, null);
|
||||
scc_ast_decl_union_init(decl, decl_type->record.name, null,
|
||||
decl_type->base.loc);
|
||||
}
|
||||
} else {
|
||||
decl = decl_type->record.decl;
|
||||
@@ -1188,14 +1214,16 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
if (decl_type->enumeration.decl == null) {
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
scc_ast_decl_enum_init(decl, type->enumeration.name, null);
|
||||
scc_ast_decl_enum_init(decl, type->enumeration.name, null,
|
||||
decl_type->base.loc);
|
||||
} else {
|
||||
decl = type->enumeration.decl;
|
||||
scc_free(decl_type); // FIXME
|
||||
}
|
||||
} else {
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
scc_ast_decl_unsafe_val_init(decl, type, null, null);
|
||||
scc_ast_decl_unsafe_val_init(decl, type, null, null,
|
||||
decl_type->base.loc);
|
||||
}
|
||||
}
|
||||
return decl;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <scc_pos_log.h>
|
||||
#include <scc_sema.h>
|
||||
#include <sema_symtab.h>
|
||||
|
||||
@@ -10,12 +11,55 @@ static void type_callback(void *context, scc_ast_node_type_t node_type,
|
||||
return;
|
||||
}
|
||||
|
||||
static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
static void expr_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
return;
|
||||
}
|
||||
scc_ast_expr_t *decl = SCC_AST_CAST_TO(scc_ast_expr_t, node);
|
||||
if (node_type == SCC_AST_EXPR_IDENTIFIER) {
|
||||
scc_ast_node_t *node =
|
||||
scc_sema_symtab_lookup_symbol(sema_symtab, decl->identifier.name);
|
||||
if (node == null) {
|
||||
SCC_ERROR(decl->base.loc, "Identifier '%s' not found",
|
||||
decl->identifier.name);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void stmt_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
|
||||
if (node_type == scc_ast_stmt_t_BEGIN) {
|
||||
scc_sema_symtab_enter_scope(sema_symtab);
|
||||
return;
|
||||
} else if (node_type == scc_ast_stmt_t_END) {
|
||||
scc_sema_symtab_leave_scope(sema_symtab);
|
||||
return;
|
||||
}
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
if (node_type == scc_ast_decl_t_BEGIN) {
|
||||
scc_sema_symtab_enter_scope(sema_symtab);
|
||||
return;
|
||||
} else if (node_type == scc_ast_decl_t_END) {
|
||||
scc_sema_symtab_leave_scope(sema_symtab);
|
||||
return;
|
||||
}
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
return;
|
||||
}
|
||||
scc_ast_decl_t *decl = SCC_AST_CAST_TO(scc_ast_decl_t, node);
|
||||
|
||||
scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
@@ -24,25 +68,25 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
return;
|
||||
}
|
||||
if (decl->base.type == SCC_AST_DECL_STRUCT) {
|
||||
scc_ast_type_struct_init(type, decl->name, decl);
|
||||
scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_cstring_t name = scc_cstring_from_cstr("$S_");
|
||||
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
|
||||
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
|
||||
&type->base);
|
||||
} else if (decl->base.type == SCC_AST_DECL_UNION) {
|
||||
scc_ast_type_union_init(type, decl->name, decl);
|
||||
scc_ast_type_union_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_cstring_t name = scc_cstring_from_cstr("$U_");
|
||||
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
|
||||
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
|
||||
&type->base);
|
||||
} else if (decl->base.type == SCC_AST_DECL_ENUM) {
|
||||
scc_ast_type_enum_init(type, decl->name, decl);
|
||||
scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_cstring_t name = scc_cstring_from_cstr("$E_");
|
||||
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
|
||||
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
|
||||
&type->base);
|
||||
} else if (decl->base.type == SCC_AST_DECL_TYPEDEF) {
|
||||
scc_ast_type_typedef_init(type, decl->name, decl);
|
||||
scc_ast_type_typedef_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);
|
||||
}
|
||||
return;
|
||||
@@ -67,8 +111,8 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
|
||||
}
|
||||
callbacks->context = sema_symtab;
|
||||
callbacks->on_decl = decl_callback;
|
||||
callbacks->on_expr = null;
|
||||
callbacks->on_stmt = null;
|
||||
callbacks->on_expr = expr_callback;
|
||||
callbacks->on_stmt = stmt_callback;
|
||||
callbacks->on_type = type_callback;
|
||||
callbacks->got_type = got_type_callback;
|
||||
|
||||
|
||||
5
libs/parser/tests/test_sema_unit.c
Normal file
5
libs/parser/tests/test_sema_unit.c
Normal file
@@ -0,0 +1,5 @@
|
||||
#include <utest/acutest.h>
|
||||
|
||||
TEST_LIST = {
|
||||
{NULL, NULL},
|
||||
};
|
||||
@@ -69,6 +69,66 @@ scc_pe_section_range scc_pe_reserve_section_header(scc_pe_builder_t *builder,
|
||||
u32 virtual_size,
|
||||
u32 data_size);
|
||||
|
||||
static inline scc_pe_section_range
|
||||
scc_pe_reserve_text_section_header(scc_pe_builder_t *builder, u32 data_size) {
|
||||
return scc_pe_reserve_section_header(
|
||||
builder, (BYTE *)".text\0\0",
|
||||
IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ,
|
||||
data_size, data_size);
|
||||
}
|
||||
|
||||
static inline scc_pe_section_range
|
||||
scc_pe_reserve_data_section_header(scc_pe_builder_t *builder, u32 data_size) {
|
||||
return scc_pe_reserve_section_header(builder, (BYTE *)".data\0\0",
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
IMAGE_SCN_MEM_READ |
|
||||
IMAGE_SCN_MEM_WRITE,
|
||||
data_size, data_size);
|
||||
}
|
||||
|
||||
static inline scc_pe_section_range
|
||||
scc_pe_reserve_rdata_section_header(scc_pe_builder_t *builder, u32 data_size) {
|
||||
return scc_pe_reserve_section_header(builder, (BYTE *)".rdata\0",
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
IMAGE_SCN_MEM_READ,
|
||||
data_size, data_size);
|
||||
}
|
||||
|
||||
static inline scc_pe_section_range
|
||||
scc_pe_reserve_bss_section_header(scc_pe_builder_t *builder, u32 data_size) {
|
||||
return scc_pe_reserve_section_header(builder, (BYTE *)".bss\0\0\0",
|
||||
IMAGE_SCN_CNT_UNINITIALIZED_DATA |
|
||||
IMAGE_SCN_MEM_READ |
|
||||
IMAGE_SCN_MEM_WRITE,
|
||||
data_size, 0);
|
||||
}
|
||||
|
||||
static inline scc_pe_section_range
|
||||
scc_pe_reserve_idata_section_header(scc_pe_builder_t *builder, u32 data_size) {
|
||||
scc_pe_section_range range = scc_pe_reserve_section_header(
|
||||
builder, (BYTE *)".idata\0",
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
|
||||
IMAGE_SCN_MEM_WRITE,
|
||||
data_size, data_size);
|
||||
scc_vec_at(builder->image_data_directory_vec,
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT) = (IMAGE_DATA_DIRECTORY){
|
||||
.VirtualAddress = range.virual_address, .Size = range.virual_size};
|
||||
return range;
|
||||
}
|
||||
|
||||
static inline scc_pe_section_range
|
||||
scc_pe_reserve_reloc_section_header(scc_pe_builder_t *builder, u32 data_size) {
|
||||
scc_pe_section_range range = scc_pe_reserve_section_header(
|
||||
builder, (BYTE *)".reloc\0\0",
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
|
||||
IMAGE_SCN_MEM_DISCARDABLE,
|
||||
data_size, data_size);
|
||||
scc_vec_at(builder->image_data_directory_vec,
|
||||
IMAGE_DIRECTORY_ENTRY_BASERELOC) = (IMAGE_DATA_DIRECTORY){
|
||||
.VirtualAddress = range.virual_address, .Size = range.virual_size};
|
||||
return range;
|
||||
}
|
||||
|
||||
void scc_pe_write_header(scc_pe_builder_t *builder, scc_pe_config_t *config);
|
||||
|
||||
void scc_pe_write_section(scc_pe_builder_t *builder,
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*
|
||||
* @bug 可以有更好的方式解决这个问题
|
||||
*/
|
||||
#ifdef DUMMYUNIONNAME
|
||||
#undef DUMMYUNIONNAME
|
||||
#endif
|
||||
#define DUMMYUNIONNAME DUMMYUNIONNAME
|
||||
|
||||
// 基本类型定义
|
||||
|
||||
@@ -10,33 +10,21 @@ typedef struct {
|
||||
scc_pe_buffer_t data; ///< 具体数据
|
||||
scc_hashtable_t str_map; ///< 符号名称映射到data的idx
|
||||
u32 section_offset; ///< 在idata中的偏移
|
||||
} scc_winpe_hnt_builder_t;
|
||||
|
||||
typedef struct {
|
||||
u32 offset; ///< 相对代码段的偏移地址
|
||||
i32 addend; ///< 可选的偏移量的附加值 可选默认为0
|
||||
u8 size; ///< 引用的地址的大小
|
||||
const char *library_name; ///< 库名称 eg. "Kernel32.dll"
|
||||
const char *symbol_name; ///< 导入dll的符号名称 eg. "CreateFileW"
|
||||
u16 ordinal; ///< 符号的序号 eg. 可选
|
||||
} scc_winpe_extern_t;
|
||||
typedef SCC_VEC(scc_winpe_extern_t) scc_winpe_extern_vec_t;
|
||||
} scc_pe_hnt_builder_t;
|
||||
|
||||
typedef SCC_VEC(const char *) scc_winpe_name_vec_t;
|
||||
typedef struct {
|
||||
const char *name;
|
||||
scc_winpe_name_vec_t symbol_names;
|
||||
} scc_winpe_idata_lib_t;
|
||||
typedef SCC_VEC(scc_winpe_idata_lib_t) scc_winpe_idata_lib_vec_t;
|
||||
typedef SCC_VEC(scc_winpe_idata_lib_t) scc_pe_idata_lib_vec_t;
|
||||
typedef struct {
|
||||
scc_pe_buffer_t buffer; ///< 导入表数据
|
||||
scc_winpe_extern_vec_t externs;
|
||||
scc_hashtable_t externs_set;
|
||||
|
||||
scc_winpe_hnt_builder_t hnt_builder;
|
||||
scc_pe_hnt_builder_t hnt_builder;
|
||||
scc_hashtable_t iat_map; ///< 符号名称映射到idata的虚拟镜像地址
|
||||
scc_winpe_idata_lib_vec_t idata_libs;
|
||||
} scc_winpe_idata_builder_t;
|
||||
scc_pe_idata_lib_vec_t idata_libs;
|
||||
} scc_pe_idata_builder_t;
|
||||
|
||||
/**
|
||||
* @brief PE格式导入表构建器初始化
|
||||
@@ -45,8 +33,8 @@ typedef struct {
|
||||
* @param builder
|
||||
* @param idata_libs
|
||||
*/
|
||||
void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder,
|
||||
scc_winpe_idata_lib_vec_t *idata_libs);
|
||||
void scc_pe_idata_builder_init(scc_pe_idata_builder_t *builder,
|
||||
scc_pe_idata_lib_vec_t *idata_libs);
|
||||
|
||||
/**
|
||||
* @brief 获取导入表占据的大小
|
||||
@@ -55,7 +43,7 @@ void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder,
|
||||
* @param builder
|
||||
* @return u32
|
||||
*/
|
||||
u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder);
|
||||
u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder);
|
||||
|
||||
/**
|
||||
* @brief 构造导入表
|
||||
@@ -64,13 +52,12 @@ u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder);
|
||||
* @param builder
|
||||
* @param idata_range
|
||||
*/
|
||||
scc_pe_buffer_t scc_pe_construct_idata(scc_winpe_idata_builder_t *builder,
|
||||
scc_pe_buffer_t scc_pe_construct_idata(scc_pe_idata_builder_t *builder,
|
||||
scc_pe_section_range *idata_range);
|
||||
|
||||
// RVA Relative Virtual Address
|
||||
static inline u64
|
||||
scc_pe_idata_get_symbol_rva(scc_winpe_idata_builder_t *builder,
|
||||
const char *symbol_name) {
|
||||
static inline u64 scc_pe_idata_get_symbol_rva(scc_pe_idata_builder_t *builder,
|
||||
const char *symbol_name) {
|
||||
return (u64)scc_hashtable_get(&builder->iat_map, symbol_name);
|
||||
}
|
||||
|
||||
|
||||
45
libs/target/pe/include/scc_pe_reloc.h
Normal file
45
libs/target/pe/include/scc_pe_reloc.h
Normal 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__ */
|
||||
@@ -13,9 +13,9 @@ image_import_descriptor_init(u32 import_lookup_table_rva, u32 name_rva,
|
||||
return iid;
|
||||
};
|
||||
|
||||
static void scc_winpe_hnt_builder_push(scc_winpe_hnt_builder_t *builder,
|
||||
static void scc_winpe_hnt_builder_push(scc_pe_hnt_builder_t *builder,
|
||||
const char *name, u16 hint);
|
||||
static void scc_winpe_hnt_builder_init(scc_winpe_hnt_builder_t *builder) {
|
||||
static void scc_winpe_hnt_builder_init(scc_pe_hnt_builder_t *builder) {
|
||||
scc_vec_init(builder->data);
|
||||
builder->section_offset = 0;
|
||||
scc_hashtable_init(&builder->str_map,
|
||||
@@ -23,7 +23,7 @@ static void scc_winpe_hnt_builder_init(scc_winpe_hnt_builder_t *builder) {
|
||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
||||
}
|
||||
|
||||
static void scc_winpe_hnt_builder_push(scc_winpe_hnt_builder_t *builder,
|
||||
static void scc_winpe_hnt_builder_push(scc_pe_hnt_builder_t *builder,
|
||||
const char *name, u16 hint) {
|
||||
///< 可选哈希表去重
|
||||
if (scc_hashtable_get(&builder->str_map, name)) {
|
||||
@@ -49,13 +49,13 @@ static void scc_winpe_hnt_builder_push(scc_winpe_hnt_builder_t *builder,
|
||||
Assert(scc_vec_size(builder->data) % 2 == 0);
|
||||
}
|
||||
|
||||
static u64 scc_winpe_hnt_get_offset(scc_winpe_hnt_builder_t *builder,
|
||||
static u64 scc_winpe_hnt_get_offset(scc_pe_hnt_builder_t *builder,
|
||||
const char *name) {
|
||||
return (u64)scc_hashtable_get(&builder->str_map, name);
|
||||
}
|
||||
|
||||
void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder,
|
||||
scc_winpe_idata_lib_vec_t *idata_libs) {
|
||||
void scc_pe_idata_builder_init(scc_pe_idata_builder_t *builder,
|
||||
scc_pe_idata_lib_vec_t *idata_libs) {
|
||||
scc_vec_init(builder->buffer);
|
||||
builder->idata_libs = *idata_libs;
|
||||
|
||||
@@ -66,7 +66,7 @@ void scc_pe_idata_builder_init(scc_winpe_idata_builder_t *builder,
|
||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
||||
}
|
||||
|
||||
u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder) {
|
||||
u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder) {
|
||||
u32 idata_size = (scc_vec_size(builder->idata_libs) + 1) *
|
||||
sizeof(IMAGE_IMPORT_DESCRIPTOR);
|
||||
|
||||
@@ -89,7 +89,7 @@ u32 scc_pe_reserve_idata(scc_winpe_idata_builder_t *builder) {
|
||||
return idata_size;
|
||||
}
|
||||
|
||||
scc_pe_buffer_t scc_pe_construct_idata(scc_winpe_idata_builder_t *builder,
|
||||
scc_pe_buffer_t scc_pe_construct_idata(scc_pe_idata_builder_t *builder,
|
||||
scc_pe_section_range *idata_range) {
|
||||
u32 idata_rva = idata_range->virual_address;
|
||||
u32 hnt_offset = builder->hnt_builder.section_offset;
|
||||
|
||||
0
libs/target/pe/src/scc_pe_reloc.c
Normal file
0
libs/target/pe/src/scc_pe_reloc.c
Normal file
@@ -24,19 +24,14 @@ int main() {
|
||||
scc_pe_builder_t builder = {0};
|
||||
scc_pe_builder_init(&builder, true, 4096, 512);
|
||||
scc_pe_reserve_header(&builder, 3);
|
||||
scc_pe_section_range code_range = scc_pe_reserve_section_header(
|
||||
&builder, (BYTE *)".text\0\0",
|
||||
IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE,
|
||||
sizeof(code), sizeof(code));
|
||||
scc_pe_section_range code_range =
|
||||
scc_pe_reserve_text_section_header(&builder, sizeof(code));
|
||||
|
||||
scc_pe_section_range data_range = scc_pe_reserve_section_header(
|
||||
&builder, (BYTE *)".data\0\0",
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
|
||||
IMAGE_SCN_MEM_WRITE,
|
||||
sizeof(data), sizeof(data));
|
||||
scc_pe_section_range data_range =
|
||||
scc_pe_reserve_data_section_header(&builder, sizeof(data));
|
||||
|
||||
scc_winpe_idata_builder_t idata_builder;
|
||||
scc_winpe_idata_lib_vec_t idata_libs;
|
||||
scc_pe_idata_builder_t idata_builder;
|
||||
scc_pe_idata_lib_vec_t idata_libs;
|
||||
scc_vec_init(idata_libs);
|
||||
scc_winpe_idata_lib_t ucrtbase;
|
||||
ucrtbase.name = "ucrtbase.dll";
|
||||
@@ -45,14 +40,8 @@ int main() {
|
||||
scc_vec_push(idata_libs, ucrtbase);
|
||||
scc_pe_idata_builder_init(&idata_builder, &idata_libs);
|
||||
u32 idata_size = scc_pe_reserve_idata(&idata_builder);
|
||||
scc_pe_section_range idata_range = scc_pe_reserve_section_header(
|
||||
&builder, (BYTE *)".idata\0",
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
|
||||
IMAGE_SCN_MEM_WRITE,
|
||||
idata_size, idata_size);
|
||||
scc_vec_at(builder.image_data_directory_vec, IMAGE_DIRECTORY_ENTRY_IMPORT) =
|
||||
(IMAGE_DATA_DIRECTORY){.VirtualAddress = idata_range.virual_address,
|
||||
.Size = idata_range.virual_size};
|
||||
scc_pe_section_range idata_range =
|
||||
scc_pe_reserve_idata_section_header(&builder, idata_size);
|
||||
scc_pe_buffer_t idata_buffer =
|
||||
scc_pe_construct_idata(&idata_builder, &idata_range);
|
||||
|
||||
@@ -97,5 +86,5 @@ int main() {
|
||||
scc_pe_write_section(&builder, &idata_range,
|
||||
scc_vec_unsafe_get_data(idata_buffer),
|
||||
scc_vec_size(idata_buffer));
|
||||
scc_pe_dump_to_file(&builder, "hello_world.exe");
|
||||
scc_pe_dump_to_file(&builder, __FILE__ "/../pe_write_idata.exe");
|
||||
}
|
||||
2
libs/target/pe/tests/test_pe_write_reloc.c
Normal file
2
libs/target/pe/tests/test_pe_write_reloc.c
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
int main(void) { return 0; }
|
||||
@@ -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
142
src/config.h
Normal 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___ */
|
||||
137
src/main.c
137
src/main.c
@@ -7,130 +7,7 @@
|
||||
#include <scc_ast2ir.h>
|
||||
#include <scc_parser.h>
|
||||
|
||||
typedef struct {
|
||||
const char *input_file;
|
||||
const char *output_file;
|
||||
int verbose;
|
||||
scc_argparse_list_t include_paths;
|
||||
cbool emit_lex;
|
||||
cbool emit_pp;
|
||||
cbool emit_ast;
|
||||
cbool emit_ir;
|
||||
} scc_config_t;
|
||||
|
||||
static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
||||
scc_argparse_lang_t lang) {
|
||||
enum {
|
||||
SCC_HINT_PROG_NAME,
|
||||
SCC_HINT_DESCRIPTION,
|
||||
SCC_HINT_OUTPUT_FILE,
|
||||
SCC_HINT_INPUT_FILE,
|
||||
SCC_HINT_INCLUDE_PATH,
|
||||
SCC_HINT_VERBOSE,
|
||||
|
||||
SCC_HINT_EMIT_LEX,
|
||||
SCC_HINT_EMIT_PP,
|
||||
SCC_HINT_EMIT_AST,
|
||||
SCC_HINT_EMIT_IR,
|
||||
};
|
||||
static const char *scc_hints_en[] = {
|
||||
[SCC_HINT_PROG_NAME] = "scc",
|
||||
[SCC_HINT_DESCRIPTION] = "A simple C compiler",
|
||||
[SCC_HINT_OUTPUT_FILE] =
|
||||
"Output file (`-` means standard output stream file)",
|
||||
[SCC_HINT_INPUT_FILE] = "Input source file",
|
||||
[SCC_HINT_INCLUDE_PATH] = "Add directory to the include search paths",
|
||||
[SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)",
|
||||
[SCC_HINT_EMIT_LEX] = "Generate lexer sources tokens and exit",
|
||||
[SCC_HINT_EMIT_PP] = "Generate preprocessed tokens and exit",
|
||||
[SCC_HINT_EMIT_AST] = "Generate AST and exit",
|
||||
[SCC_HINT_EMIT_IR] = "Generate IR and exit",
|
||||
};
|
||||
static const char *scc_hints_zh[] = {
|
||||
[SCC_HINT_PROG_NAME] = "scc",
|
||||
[SCC_HINT_DESCRIPTION] = "一个简单的C编译器",
|
||||
[SCC_HINT_OUTPUT_FILE] = "输出文件(`-`表示标准输出流文件)",
|
||||
[SCC_HINT_INPUT_FILE] = "输入源文件",
|
||||
[SCC_HINT_INCLUDE_PATH] = "添加系统头文件到搜索路径",
|
||||
[SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)",
|
||||
[SCC_HINT_EMIT_LEX] = "生成`源代码的词法单元`并退出",
|
||||
[SCC_HINT_EMIT_PP] = "生成`预处理后的词法单元`并退出",
|
||||
[SCC_HINT_EMIT_AST] = "生成`抽象语法树`并退出",
|
||||
[SCC_HINT_EMIT_IR] = "生成`中间代码`并退出",
|
||||
};
|
||||
|
||||
const char **scc_hints;
|
||||
switch (lang) {
|
||||
case SCC_ARGPARSE_LANG_EN:
|
||||
scc_hints = scc_hints_en;
|
||||
break;
|
||||
case SCC_ARGPARSE_LANG_ZH:
|
||||
scc_hints = scc_hints_zh;
|
||||
break;
|
||||
default:
|
||||
scc_hints = scc_hints_en;
|
||||
break;
|
||||
}
|
||||
|
||||
scc_argparse_init(argparse, scc_hints[SCC_HINT_PROG_NAME],
|
||||
scc_hints[SCC_HINT_DESCRIPTION]);
|
||||
argparse->lang = lang;
|
||||
scc_argparse_cmd_t *root = scc_argparse_get_root(argparse);
|
||||
|
||||
// -o, --output
|
||||
scc_argparse_opt_t opt_output;
|
||||
scc_argparse_opt_init(&opt_output, 'o', "output",
|
||||
scc_hints[SCC_HINT_OUTPUT_FILE]);
|
||||
scc_argparse_spec_setup_string(&opt_output.spec, &(config->output_file));
|
||||
scc_argparse_cmd_add_opt(root, &opt_output);
|
||||
|
||||
// input file (必需)
|
||||
scc_argparse_arg_t arg_input;
|
||||
scc_argparse_arg_init(&arg_input, "input", scc_hints[SCC_HINT_INPUT_FILE]);
|
||||
scc_argparse_spec_setup_string(&arg_input.spec, &(config->input_file));
|
||||
scc_argparse_spec_set_required(&arg_input.spec, true);
|
||||
scc_argparse_cmd_add_arg(root, &arg_input);
|
||||
|
||||
// -I, --include (添加额外的系统头文件搜索路径)
|
||||
scc_argparse_opt_t opt_include;
|
||||
scc_argparse_opt_init(&opt_include, 'I', "include",
|
||||
scc_hints[SCC_HINT_INCLUDE_PATH]);
|
||||
scc_argparse_spec_setup_list(&opt_include.spec, &(config->include_paths));
|
||||
scc_argparse_cmd_add_opt(root, &opt_include);
|
||||
|
||||
// -v, --verbose (计数)
|
||||
scc_argparse_opt_t opt_verbose;
|
||||
scc_argparse_opt_init(&opt_verbose, 'V', "verbose",
|
||||
scc_hints[SCC_HINT_VERBOSE]);
|
||||
scc_argparse_spec_setup_count(&opt_verbose.spec, &(config->verbose));
|
||||
scc_argparse_cmd_add_opt(root, &opt_verbose);
|
||||
|
||||
// --emit-lex
|
||||
scc_argparse_opt_t opt_lex;
|
||||
scc_argparse_opt_init(&opt_lex, 0, "emit-lex",
|
||||
scc_hints[SCC_HINT_EMIT_LEX]);
|
||||
scc_argparse_spec_setup_bool(&opt_lex.spec, &(config->emit_lex));
|
||||
scc_argparse_cmd_add_opt(root, &opt_lex);
|
||||
|
||||
// --emit-pp
|
||||
scc_argparse_opt_t opt_pp;
|
||||
scc_argparse_opt_init(&opt_pp, 0, "emit-pp", scc_hints[SCC_HINT_EMIT_PP]);
|
||||
scc_argparse_spec_setup_bool(&opt_pp.spec, &(config->emit_pp));
|
||||
scc_argparse_cmd_add_opt(root, &opt_pp);
|
||||
|
||||
// -T, --emit-ast
|
||||
scc_argparse_opt_t opt_ast;
|
||||
scc_argparse_opt_init(&opt_ast, 'T', "emit-ast",
|
||||
scc_hints[SCC_HINT_EMIT_AST]);
|
||||
scc_argparse_spec_setup_bool(&opt_ast.spec, &(config->emit_ast));
|
||||
scc_argparse_cmd_add_opt(root, &opt_ast);
|
||||
|
||||
// -R, --emit-ir
|
||||
scc_argparse_opt_t opt_ir;
|
||||
scc_argparse_opt_init(&opt_ir, 'R', "emit-ir", scc_hints[SCC_HINT_EMIT_IR]);
|
||||
scc_argparse_spec_setup_bool(&opt_ir.spec, &(config->emit_ir));
|
||||
scc_argparse_cmd_add_opt(root, &opt_ir);
|
||||
}
|
||||
#include "config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
@@ -332,11 +209,10 @@ sstream_drop:
|
||||
return 0;
|
||||
}
|
||||
|
||||
scc_ir_builder_t ir_builder;
|
||||
scc_ir_builder_init(&ir_builder);
|
||||
scc_ast2ir_ctx_t ast2ir_ctx;
|
||||
#include <abi/win_x64_type_abi.h>
|
||||
scc_ast2ir_translation_unit(&ir_builder, translation_unit,
|
||||
scc_win_x64_type_abi);
|
||||
scc_ast2ir_ctx_init(&ast2ir_ctx, scc_win_x64_type_abi);
|
||||
scc_ast2ir_translation_unit(&ast2ir_ctx, translation_unit);
|
||||
|
||||
if (config.emit_ir) {
|
||||
scc_ir_dump_ctx_t ir_dump_ctx;
|
||||
@@ -348,8 +224,9 @@ sstream_drop:
|
||||
scc_tree_dump_ctx_init(&tree_dump, false, (void *)scc_fprintf,
|
||||
(void *)fp);
|
||||
}
|
||||
scc_ir_dump_ctx_init(&ir_dump_ctx, &tree_dump, &ir_builder.cprog,
|
||||
&ir_builder.ctx);
|
||||
scc_ir_dump_ctx_init(&ir_dump_ctx, &tree_dump,
|
||||
&ast2ir_ctx.builder.cprog,
|
||||
&ast2ir_ctx.builder.ctx);
|
||||
// scc_ir_dump_cprog(&ir_dump_ctx);
|
||||
scc_ir_dump_cprog_linear(&ir_dump_ctx);
|
||||
scc_tree_dump_ctx_drop(&tree_dump);
|
||||
|
||||
Reference in New Issue
Block a user