#include #include scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, scc_ast_type_t *ast_type) { if (ctx == null || ast_type == null) { LOG_ERROR("args is null"); return 0; } scc_ir_type_t ir_type; switch (ast_type->base.type) { case SCC_AST_TYPE_BUILTIN: { // 映射内置类型 scc_ir_type_init(&ir_type, SCC_IR_TYPE_I32); // TODO: 根据具体内置类型设置 break; } case SCC_AST_TYPE_POINTER: { scc_ir_type_init(&ir_type, SCC_IR_TYPE_PTR); // 创建指向类型并添加到程序类型列表 scc_ir_type_ref_t pointee_type = scc_ast2ir_type(ctx, ast_type->pointer.pointee); // 注意:我们需要找到一种合适的方式来存储类型信息 // 目前的IR设计中类型信息应该直接存储在类型结构中 ir_type.data.pointer.base = pointee_type; break; } case SCC_AST_TYPE_ARRAY: { scc_ir_type_init(&ir_type, SCC_IR_TYPE_ARRAY); // 创建元素类型并添加到程序类型列表 scc_ir_type_ref_t element_type = scc_ast2ir_type(ctx, ast_type->array.element); // 将类型添加到程序的类型容器中 ir_type.data.array.base = element_type; // TODO: 处理数组大小表达式 ir_type.data.array.len = 0; // 暂时设为0 break; } case SCC_AST_TYPE_FUNCTION: { scc_ir_type_init(&ir_type, SCC_IR_TYPE_FUNC); // 处理返回类型 scc_ir_type_ref_t ret_type = scc_ast2ir_type(ctx, ast_type->function.return_type); // 将返回类型添加到程序的类型容器中 ir_type.data.function.ret_type = ret_type; // 转换参数类型 scc_ir_type_ref_vec_t params; scc_vec_init(params); scc_vec_foreach(ast_type->function.params, i) { scc_ast_decl_t *decl_param = scc_vec_at(ast_type->function.params, i); Assert(decl_param->base.type == SCC_AST_DECL_PARAM); scc_ir_type_ref_t tmp_type = scc_ast2ir_type(ctx, decl_param->param.type); scc_vec_push(params, tmp_type); } ir_type.data.function.params = params; break; } // SCC_AST_TYPE_BUILTIN, // 内置类型 // SCC_AST_TYPE_POINTER, // 指针类型 // SCC_AST_TYPE_ARRAY, // 数组类型 // SCC_AST_TYPE_FUNCTION, // 函数类型 // SCC_AST_TYPE_STRUCT, // 结构体类型 // SCC_AST_TYPE_UNION, // 联合类型 // SCC_AST_TYPE_ENUM, // 枚举类型 // SCC_AST_TYPE_TYPEDEF, // typedef 类型 default: LOG_FATAL("Unsupported AST type: %d", ast_type->base.type); return 0; } return scc_ir_ctx_new_type(&ctx->builder.ctx, &ir_type); } /** * @brief * * @param ctx * @param expr * @return scc_ir_node_ref_t */ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, 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); // 检查参数是否为空 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, false); 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,// 内置表达式 ... 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); 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 = scc_ast2ir_type(ctx, decl->func.type); if (decl->func.body == null) { // function decl break; } // TODO params name 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 (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); }