Files
scc/libs/ast2ir/src/scc_ast2ir.c
zzy 741171dbba feat(ir): 实现函数调用和参数处理功能
- 在AST定义中移除函数调用结构体中的冗余name字段
- 实现完整的函数声明和定义处理流程,支持符号表查找
- 添加函数参数引用节点类型,支持参数传递和访问
- 实现函数调用的IR生成,包括参数处理和符号解析
- 添加断言确保节点有效性,提升代码健壮性

fix(ast2ir): 优化类型转换处理逻辑

- 移除多余的注释说明
- 简化参数为空检查逻辑,提高代码简洁性
- 修复函数调用时的符号表查找机制

refactor(ir): 改进IR构建器接口设计

- 修改函数构建相关API,使接口更加清晰
- 添加函数声明集合管理
- 重构内置类型缓存机制

feat(ir2mcode): 完善AMD64代码生成

- 实现函数参数到寄存器的映射
- 添加函数调用约定支持(最多4个参数)
- 实现函数符号和重定位处理
- 添加栈帧管理机制
- 修正栈偏移计算

chore(ir): 清理和优化IR dump输出

- 更新节点类型描述信息
- 改进函数声明和定义的输出格式
- 修正格式化输出中的符号显示问题

style: 代码格式化和命名规范化

- 统一重定位类型枚举命名
- 优化函数参数验证和错误处理
2026-03-23 16:02:23 +08:00

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);
}