- 在AST定义中移除函数调用结构体中的冗余name字段 - 实现完整的函数声明和定义处理流程,支持符号表查找 - 添加函数参数引用节点类型,支持参数传递和访问 - 实现函数调用的IR生成,包括参数处理和符号解析 - 添加断言确保节点有效性,提升代码健壮性 fix(ast2ir): 优化类型转换处理逻辑 - 移除多余的注释说明 - 简化参数为空检查逻辑,提高代码简洁性 - 修复函数调用时的符号表查找机制 refactor(ir): 改进IR构建器接口设计 - 修改函数构建相关API,使接口更加清晰 - 添加函数声明集合管理 - 重构内置类型缓存机制 feat(ir2mcode): 完善AMD64代码生成 - 实现函数参数到寄存器的映射 - 添加函数调用约定支持(最多4个参数) - 实现函数符号和重定位处理 - 添加栈帧管理机制 - 修正栈偏移计算 chore(ir): 清理和优化IR dump输出 - 更新节点类型描述信息 - 改进函数声明和定义的输出格式 - 修正格式化输出中的符号显示问题 style: 代码格式化和命名规范化 - 统一重定位类型枚举命名 - 优化函数参数验证和错误处理
631 lines
23 KiB
C
631 lines
23 KiB
C
#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_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,
|
|
cbool is_lvalue) {
|
|
if (ctx == null || expr == null) {
|
|
LOG_ERROR("args is null");
|
|
return 0;
|
|
}
|
|
|
|
cbool is_assign = true;
|
|
switch (expr->base.type) {
|
|
case SCC_AST_EXPR_BINARY: {
|
|
scc_ast_expr_t tmp_expr;
|
|
scc_ir_node_ref_t lhs, rhs;
|
|
switch (expr->binary.op) {
|
|
case SCC_AST_OP_ASSIGN: // =
|
|
rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_ADD: // +=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_ADD,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_SUB: // -=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_SUB,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_MUL: // *=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_MUL,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_DIV: // /=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_DIV,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_MOD: // %=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_MOD,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_AND: // &=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_AND,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_XOR: // ^=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_XOR,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_OR: // |=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_OR,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_LSHIFT: // <<=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_LEFT_SHIFT,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
case SCC_AST_OP_ASSIGN_RSHIFT: // >>=
|
|
scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_RIGHT_SHIFT,
|
|
expr->binary.lhs, expr->binary.rhs,
|
|
expr->base.loc);
|
|
rhs = scc_ast2ir_expr(ctx, &tmp_expr, false);
|
|
break;
|
|
default:
|
|
is_assign = false;
|
|
break;
|
|
}
|
|
if (is_assign) {
|
|
lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, true);
|
|
return scc_ir_builder_store(&ctx->builder, lhs, rhs);
|
|
}
|
|
|
|
rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false);
|
|
lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, false);
|
|
// 映射操作符
|
|
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_BITWISE_AND: op = SCC_IR_OP_AND; break;
|
|
case SCC_AST_OP_BITWISE_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;
|
|
// FIXME op = SCC_IR_OP_SAR;
|
|
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_COMMA: {
|
|
// 逗号运算符:计算左表达式,丢弃结果,返回右表达式
|
|
return rhs;
|
|
}
|
|
/* 逻辑操作符 */
|
|
case SCC_AST_OP_LOGICAL_OR: // ||
|
|
case SCC_AST_OP_LOGICAL_AND: // &&
|
|
TODO();
|
|
/* 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, is_lvalue);
|
|
// /* 一元操作符 */
|
|
// 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, // -- (后缀)
|
|
switch (expr->unary.op) {
|
|
case SCC_AST_OP_UNARY_MINUS:
|
|
// 负号
|
|
// 实现为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);
|
|
|
|
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, false);
|
|
scc_vec_push(args, arg_node);
|
|
}
|
|
|
|
// 创建调用节点(需要查找函数定义)
|
|
scc_ir_func_ref_t func = (scc_ir_node_ref_t)(usize)scc_hashtable_get(
|
|
&ctx->symtab, expr->call.callee->identifier._target->name);
|
|
scc_ir_node_ref_t node =
|
|
scc_ir_builder_call(&ctx->builder, func, args.data, args.size);
|
|
scc_vec_free(args);
|
|
return node;
|
|
}
|
|
|
|
// 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,// 内置表达式 ... directive map to ir 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: {
|
|
if (expr->identifier._target == null) {
|
|
LOG_ERROR("unknown identifier %s", expr->identifier.name);
|
|
}
|
|
// FIXME hack hashtable
|
|
scc_ir_node_ref_t in = (scc_ir_node_ref_t)(usize)scc_hashtable_get(
|
|
&ctx->node2ir, expr->identifier._target);
|
|
Assert(in != 0);
|
|
if (is_lvalue) {
|
|
return in;
|
|
} else {
|
|
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, false);
|
|
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, false);
|
|
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, false_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, false);
|
|
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, false);
|
|
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: {
|
|
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");
|
|
|
|
if (stmt->for_stmt.init) {
|
|
if (SCC_AST_IS_A(scc_ast_decl_t, stmt->for_stmt.init)) {
|
|
scc_ast2ir_decl(
|
|
ctx, SCC_AST_CAST_TO(scc_ast_decl_t, stmt->for_stmt.init));
|
|
} else if (SCC_AST_IS_A(scc_ast_expr_t, stmt->for_stmt.init)) {
|
|
scc_ast2ir_expr(
|
|
ctx, SCC_AST_CAST_TO(scc_ast_expr_t, stmt->for_stmt.init),
|
|
false);
|
|
} else {
|
|
LOG_FATAL("invalid for init statement");
|
|
}
|
|
}
|
|
|
|
scc_ir_builder_jump(&ctx->builder, cond_block);
|
|
|
|
scc_ir_builder_set_current_bblock(&ctx->builder, cond_block);
|
|
if (stmt->for_stmt.cond) {
|
|
scc_ir_node_ref_t cond_node =
|
|
scc_ast2ir_expr(ctx, stmt->for_stmt.cond, false);
|
|
scc_ir_builder_branch(&ctx->builder, cond_node, body_block,
|
|
exit_block);
|
|
} else {
|
|
scc_ir_builder_jump(&ctx->builder, body_block);
|
|
}
|
|
|
|
scc_ir_builder_set_current_bblock(&ctx->builder, body_block);
|
|
scc_ast2ir_stmt(ctx, stmt->for_stmt.body);
|
|
if (stmt->for_stmt.incr) {
|
|
scc_ast2ir_expr(ctx, stmt->for_stmt.incr, false);
|
|
}
|
|
scc_ir_builder_jump(&ctx->builder, cond_block);
|
|
|
|
scc_ir_builder_set_current_bblock(&ctx->builder, exit_block);
|
|
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, false);
|
|
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);
|
|
|
|
scc_hashtable_set(&ctx->node2ir, decl, (void *)(usize)alloc_val_node);
|
|
|
|
// 如果有初始化表达式
|
|
if (!decl->var.init) {
|
|
break;
|
|
}
|
|
scc_ir_node_ref_t init_val_node =
|
|
scc_ast2ir_expr(ctx, decl->var.init, false);
|
|
scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node);
|
|
break;
|
|
}
|
|
|
|
case SCC_AST_DECL_FUNC: {
|
|
scc_ir_type_ref_t func_type_ref = scc_ast2ir_type(ctx, decl->func.type);
|
|
scc_ir_func_ref_t func_ref =
|
|
(usize)scc_hashtable_get(&ctx->symtab, decl->name);
|
|
if (func_ref == 0) {
|
|
func_ref =
|
|
scc_ir_builder_func(&ctx->builder, func_type_ref, decl->name);
|
|
scc_hashtable_set(&ctx->symtab, decl->name,
|
|
(void *)(usize)func_ref);
|
|
scc_vec_push(ctx->builder.cprog.func_decls, func_ref);
|
|
}
|
|
|
|
if (decl->func.body == null) {
|
|
// function decl
|
|
break;
|
|
}
|
|
|
|
scc_ir_builder_begin_func(&ctx->builder, func_ref, null);
|
|
scc_ir_func_t *func = scc_ir_ctx_get_func(&ctx->builder.ctx, func_ref);
|
|
Assert(func != null);
|
|
scc_ir_builder_begin_bblock(&ctx->builder, "entry");
|
|
scc_vec_foreach(decl->func.type->function.params, i) {
|
|
scc_ast_decl_t *param =
|
|
scc_vec_at(decl->func.type->function.params, i);
|
|
|
|
scc_ir_node_ref_t param_node_ref = scc_vec_at(func->params, i);
|
|
scc_ir_node_t *param_node =
|
|
scc_ir_ctx_get_node(&ctx->builder.ctx, param_node_ref);
|
|
Assert(param_node != null);
|
|
param_node->name = param->name;
|
|
scc_hashtable_set(&ctx->node2ir, param,
|
|
(void *)(usize)param_node_ref);
|
|
}
|
|
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 (u32)(usize)key1 - (u32)(usize)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);
|
|
scc_hashtable_init(&ctx->symtab, (scc_hashtable_hash_func_t)scc_strhash32,
|
|
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
}
|