#include #include #include #include #include static scc_hir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx, const scc_ast_qual_type_t *ast_type) { scc_abi_type_layout_t layout; // 映射内置类型 ctx->abi->compute_type_layout(ctx->abi, (void *)ast_type, &layout); switch (layout.size) { case 0: return scc_hir_builder_type_void(&ctx->builder); case 1: return scc_hir_builder_type_i8(&ctx->builder); case 2: return scc_hir_builder_type_i16(&ctx->builder); case 4: return scc_hir_builder_type_i32(&ctx->builder); case 8: return scc_hir_builder_type_i64(&ctx->builder); break; default: break; } return SCC_HIR_REF_nullptr; } // static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {} // 辅助函数:计算数组实际长度(如果原长度为0) static void resolve_array_length(scc_ast2ir_ctx_t *ctx, const scc_hir_type_t *orig_array_type, scc_hir_type_t *resolved_array_type, const scc_ast_expr_t *init_expr) { *resolved_array_type = *orig_array_type; // 拷贝 Assert(orig_array_type->tag == SCC_HIR_TYPE_ARRAY); if (orig_array_type->data.array.len != 0) return; // 长度已知,无需推断 usize new_len = 0; switch (init_expr->base.type) { case SCC_AST_EXPR_STRING_LITERAL: // 字符串字面量:长度 = 字符串字符数 + 1('\0') // TODO: L"" \n \r 计算 暂不支持 new_len = scc_strlen(init_expr->literal.lexme) + 1; break; case SCC_AST_EXPR_COMPOUND: { // 复合初始化:元素个数 = 初始化列表长度 scc_vec_foreach(init_expr->compound.lhs_exprs, i) { scc_ast_expr_t *elem = scc_vec_at(init_expr->compound.lhs_exprs, i); // TODO: 支持嵌套的多维数组初始化(递归) // 这里简化:只统计顶层元素个数,假设是一维数组 new_len++; } break; } default: Panic("unsupported initializer for zero-length array"); } resolved_array_type->data.array.len = new_len; } // 辅助函数:生成数组初始化代码 static void emit_array_initialization(scc_ast2ir_ctx_t *ctx, scc_hir_value_ref_t array_ptr, const scc_hir_type_t *array_type, const scc_ast_expr_t *init_expr) { Assert(array_type->tag == SCC_HIR_TYPE_ARRAY); scc_hir_type_ref_t elem_type_ref = array_type->data.array.base; const scc_hir_type_t *elem_type = scc_hir_module_get_type(&ctx->builder.cprog->module, elem_type_ref); usize array_len = array_type->data.array.len; // 字符串字面量初始化:直接 memcpy if (init_expr->base.type == SCC_AST_EXPR_STRING_LITERAL) { scc_hir_value_ref_t str_val = scc_ast2ir_expr(ctx, init_expr, false); scc_ap_t len_ap; scc_ap_set_int(&len_ap, array_len); scc_hir_value_ref_t len_ref = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &len_ap); scc_hir_builder_builtin_memcpy(&ctx->builder, array_ptr, str_val, len_ref); return; } // 复合初始化:逐个元素 store if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) { Panic("unsupported initializer for array"); } // 遍历初始化列表 usize idx = 0; scc_vec_foreach(init_expr->compound.rhs_exprs, i) { scc_ast_expr_t *elem_expr = scc_vec_at(init_expr->compound.rhs_exprs, i); Assert(elem_expr != nullptr); if (idx >= array_len) break; // 防止溢出 // 生成元素地址:array_ptr + idx * elem_size scc_ap_t offset_ap; scc_ap_set_int(&offset_ap, idx); scc_hir_value_ref_t idx_val = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &offset_ap); scc_hir_value_ref_t elem_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, array_ptr, idx_val); // 递归处理:如果元素本身是数组且初始化表达式是复合初始化,需要嵌套处理 if (elem_type->tag == SCC_HIR_TYPE_ARRAY && elem_expr->base.type == SCC_AST_EXPR_COMPOUND) { // 递归调用自身,但注意 elem_ptr 已经是子数组的首地址 emit_array_initialization(ctx, elem_ptr, elem_type, elem_expr); } else { // 标量元素:计算右值并 store scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, elem_expr, false); scc_hir_builder_store(&ctx->builder, elem_ptr, val); } idx++; } // 如果初始化列表元素少于数组长度,剩余元素默认零初始化(C 标准要求) // 这里简单忽略,实际可生成 memset 循环,但为简化暂不处理 } scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, const scc_ast_qual_type_t *ast_type) { if (ctx == nullptr || ast_type == nullptr) { LOG_ERROR("args is nullptr"); return 0; } scc_hir_type_t ir_type; switch (ast_type->base.type) { case SCC_AST_TYPE_BUILTIN: { return parse_base_type(ctx, ast_type); } case SCC_AST_TYPE_POINTER: { scc_hir_type_init(&ir_type, SCC_HIR_TYPE_PTR); scc_hir_type_ref_t pointee_type = scc_ast2ir_type(ctx, scc_ast_canon_type(ast_type)->pointer.pointee); ir_type.data.pointer.base = pointee_type; break; } case SCC_AST_TYPE_ARRAY: { scc_hir_type_init(&ir_type, SCC_HIR_TYPE_ARRAY); scc_hir_type_ref_t element_type = scc_ast2ir_type(ctx, scc_ast_canon_type(ast_type)->array.element); ir_type.data.array.base = element_type; ir_type.data.array.len = 0; if (scc_ast_canon_type(ast_type)->array.size) { // TODO constant expression if (scc_ast_canon_type(ast_type)->array.size->base.type != SCC_AST_EXPR_INT_LITERAL) { Panic("TODO: array size expression"); } scc_ap_t value; scc_ap_from_cstr( &value, scc_ast_canon_type(ast_type)->array.size->literal.lexme, 10); // FIXME hack ir_type.data.array.len = value.data.digit; } } break; case SCC_AST_TYPE_FUNCTION: { scc_hir_type_init(&ir_type, SCC_HIR_TYPE_FUNC); // 处理返回类型 scc_hir_type_ref_t ret_type = scc_ast2ir_type( ctx, scc_ast_canon_type(ast_type)->function.return_type); // 将返回类型添加到程序的类型容器中 ir_type.data.function.ret_type = ret_type; // 转换参数类型 scc_hir_type_ref_vec_t params; scc_vec_init(params); scc_vec_foreach(scc_ast_canon_type(ast_type)->function.params, i) { scc_ast_decl_t *decl_param = scc_vec_at(scc_ast_canon_type(ast_type)->function.params, i); Assert(decl_param->base.type == SCC_AST_DECL_PARAM); scc_hir_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; case SCC_AST_TYPE_STRUCT: case SCC_AST_TYPE_UNION: { scc_hir_type_init(&ir_type, ast_type->base.type == SCC_AST_TYPE_STRUCT ? SCC_HIR_TYPE_STRUCT : SCC_HIR_TYPE_UNION); if (scc_ast_canon_type(ast_type)->record.decl == nullptr) { Panic("%s record fields is nullptr", scc_ast_canon_type(ast_type)->record.name); } scc_vec_foreach( scc_ast_canon_type(ast_type)->record.decl->record.fields, i) { scc_ast_decl_t *decl_field = scc_vec_at( scc_ast_canon_type(ast_type)->record.decl->record.fields, i); Assert(decl_field->base.type == SCC_AST_DECL_VAR); scc_hir_type_ref_t field_type = scc_ast2ir_type(ctx, decl_field->var.type); scc_vec_push(ir_type.data.aggregate.fields, field_type); } } break; case SCC_AST_TYPE_ENUM: scc_ast_canon_type_t *int_canon_type = scc_ast_ctx_get_builtin_type( ctx->ast_ctx, SCC_AST_BUILTIN_TYPE_INT); scc_ast_qual_type_t int_type = { .base.type = SCC_AST_TYPE_BUILTIN, .type = int_canon_type, }; return parse_base_type(ctx, &int_type); case SCC_AST_TYPE_TYPEDEF: // TODO maybe using cache return scc_ast2ir_type( ctx, scc_ast_canon_type(ast_type)->typedef_type.decl->typedef_decl.type); default: LOG_FATAL("Unsupported AST type: %d", ast_type->base.type); return 0; } return scc_hir_builder_type(&ctx->builder, &ir_type); } scc_hir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, const scc_ast_expr_t *expr, scc_hir_value_ref_t lhs, scc_hir_value_ref_t rhs) { // scc_hir_bblock_ref_t start_block = // scc_hir_builder_current_bblock(&ctx->builder); scc_hir_value_ref_t right_block = scc_hir_builder_bblock(&ctx->builder, "logic_right"); scc_hir_value_ref_t end_block = scc_hir_builder_bblock(&ctx->builder, "logic_end"); // 为结果创建临时存储空间 scc_hir_type_ref_t int32_type = scc_hir_builder_type_i32(&ctx->builder); scc_hir_value_ref_t result_var = scc_hir_builder_alloca(&ctx->builder, int32_type, "logic_result"); // 计算左操作数 scc_hir_value_ref_t left_val = scc_ast2ir_expr(ctx, expr->binary.lhs, false); scc_ap_t zero_ap; scc_ap_set_int(&zero_ap, 0); scc_ap_t one_ap; scc_ap_set_int(&one_ap, 1); scc_hir_value_ref_t zero_val = scc_hir_builder_integer(&ctx->builder, int32_type, &zero_ap); scc_hir_value_ref_t one_val = scc_hir_builder_integer(&ctx->builder, int32_type, &one_ap); if (expr->binary.op == SCC_AST_OP_LOGICAL_AND) { // a && b scc_hir_value_ref_t false_block = scc_hir_builder_bblock(&ctx->builder, "and_false"); // 如果左操作数为0,结果为0(短路) scc_hir_value_ref_t is_left_zero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_EQ, left_val, zero_val); scc_hir_builder_branch(&ctx->builder, is_left_zero, false_block, right_block); // false_block: 左边为0,结果为0 scc_hir_builder_set_current_bblock(&ctx->builder, false_block); scc_hir_builder_store(&ctx->builder, result_var, zero_val); scc_hir_builder_jump(&ctx->builder, end_block); // right_block: 左边非0,计算右边 scc_hir_builder_set_current_bblock(&ctx->builder, right_block); scc_hir_value_ref_t right_val = scc_ast2ir_expr(ctx, expr->binary.rhs, false); scc_hir_value_ref_t is_right_zero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_EQ, right_val, zero_val); scc_hir_value_ref_t result = scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_XOR, is_right_zero, one_val); // !right == 0 ? 1 : 0 scc_hir_builder_store(&ctx->builder, result_var, result); scc_hir_builder_jump(&ctx->builder, end_block); } else { // SCC_AST_OP_LOGICAL_OR // a || b scc_hir_value_ref_t true_block = scc_hir_builder_bblock(&ctx->builder, "or_true"); // 如果左操作数非0,结果为1(短路) scc_hir_value_ref_t is_left_nonzero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_NEQ, left_val, zero_val); scc_hir_builder_branch(&ctx->builder, is_left_nonzero, true_block, right_block); // true_block: 左边非0,结果为1 scc_hir_builder_set_current_bblock(&ctx->builder, true_block); scc_hir_builder_store(&ctx->builder, result_var, one_val); scc_hir_builder_jump(&ctx->builder, end_block); // right_block: 左边为0,计算右边 scc_hir_builder_set_current_bblock(&ctx->builder, right_block); scc_hir_value_ref_t right_val = scc_ast2ir_expr(ctx, expr->binary.rhs, false); scc_hir_value_ref_t is_right_zero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_EQ, right_val, zero_val); scc_hir_value_ref_t result = scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_XOR, is_right_zero, one_val); // !right == 0 ? 1 : 0 scc_hir_builder_store(&ctx->builder, result_var, result); scc_hir_builder_jump(&ctx->builder, end_block); } // 设置结束块为当前块,并返回结果 scc_hir_builder_set_current_bblock(&ctx->builder, end_block); return scc_hir_builder_load(&ctx->builder, result_var); } /** * @brief * * @param ctx * @param expr * @return scc_hir_value_ref_t */ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, const scc_ast_expr_t *expr, cbool is_lvalue) { if (ctx == nullptr || expr == nullptr) { LOG_ERROR("args is nullptr"); return 0; } cbool is_assign = true; switch (expr->base.type) { case SCC_AST_EXPR_BINARY: { scc_ast_expr_t tmp_expr; scc_hir_value_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_hir_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_hir_op_type_t op; switch (expr->binary.op) { /* clang-format off */ case SCC_AST_OP_ADD: op = SCC_HIR_OP_ADD; break; case SCC_AST_OP_SUB: op = SCC_HIR_OP_SUB; break; case SCC_AST_OP_MUL: op = SCC_HIR_OP_MUL; break; case SCC_AST_OP_DIV: op = SCC_HIR_OP_DIV; break; case SCC_AST_OP_MOD: op = SCC_HIR_OP_MOD; break; case SCC_AST_OP_BITWISE_AND: op = SCC_HIR_OP_AND; break; case SCC_AST_OP_BITWISE_OR: op = SCC_HIR_OP_OR; break; case SCC_AST_OP_BITWISE_XOR: op = SCC_HIR_OP_XOR; break; case SCC_AST_OP_LEFT_SHIFT: op = SCC_HIR_OP_SHL; break; case SCC_AST_OP_RIGHT_SHIFT: { op = SCC_HIR_OP_SHR; // FIXME op = SCC_HIR_OP_SAR; break; } case SCC_AST_OP_EQUAL: op = SCC_HIR_OP_EQ; break; case SCC_AST_OP_NOT_EQUAL: op = SCC_HIR_OP_NEQ; break; case SCC_AST_OP_LESS: op = SCC_HIR_OP_LT; break; case SCC_AST_OP_LESS_EQUAL: op = SCC_HIR_OP_LE; break; case SCC_AST_OP_GREATER: op = SCC_HIR_OP_GT; break; case SCC_AST_OP_GREATER_EQUAL: op = SCC_HIR_OP_GE; break; case SCC_AST_OP_COMMA: { // 逗号运算符:计算左表达式,丢弃结果,返回右表达式 return rhs; } /* 逻辑操作符 */ case SCC_AST_OP_LOGICAL_OR: // || case SCC_AST_OP_LOGICAL_AND: // && return scc_ast2ir_logical_expr(ctx, expr, lhs, rhs); /* clang-format on */ default: LOG_FATAL("Unsupported binary operator: %d", expr->binary.op); return 0; } // 创建操作节点 return scc_hir_builder_binop(&ctx->builder, op, lhs, rhs); } case SCC_AST_EXPR_UNARY: { if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) { return scc_ast2ir_expr(ctx, expr->unary.operand, true); } else if (expr->unary.op == SCC_AST_OP_INDIRECTION) { // 从地址取值 scc_hir_value_ref_t ptr = scc_ast2ir_expr(ctx, expr->unary.operand, false); if (is_lvalue) { // 作为左值使用(如 *ptr = ...),直接返回指针值(地址) return ptr; } else { // 作为右值使用(如 x = *ptr),加载指针指向的值 return scc_hir_builder_load(&ctx->builder, ptr); } } scc_hir_value_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_PLUS: /* just pass */ return operand; case SCC_AST_OP_UNARY_MINUS: { // 负号 // 实现为0 - operand scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_t value; scc_ap_set_int(&value, 0); scc_hir_value_ref_t zero_ref = scc_hir_builder_integer(&ctx->builder, type_ref, &value); return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_SUB, zero_ref, operand); } case SCC_AST_OP_ADDRESS_OF: case SCC_AST_OP_INDIRECTION: UNREACHABLE(); break; case SCC_AST_OP_BITWISE_NOT: // 按位取反 return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_NOT, operand, 0); case SCC_AST_OP_LOGICAL_NOT: { // 逻辑非 // 实现为与0比较 scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_t value; scc_ap_set_int(&value, 0); scc_hir_value_ref_t zero_ref = scc_hir_builder_integer(&ctx->builder, type_ref, &value); return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_EQ, zero_ref, operand); } default: LOG_FATAL("Unsupported unary operator: %d", expr->unary.op); return 0; } UNREACHABLE(); break; } case SCC_AST_EXPR_COND: { TODO(); break; } case SCC_AST_EXPR_CALL: { // 转换参数 scc_hir_value_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_hir_value_ref_t arg_node; arg_node = scc_ast2ir_expr(ctx, arg_expr, false); scc_vec_push(args, arg_node); } // 创建调用节点(需要查找函数定义) scc_hir_func_ref_t func = (scc_hir_value_ref_t)(usize)scc_hashtable_get( &ctx->symtab, expr->call.callee->identifier._target->name); if (!func) { LOG_ERROR("Function %s not found", expr->call.callee->identifier._target->name); } scc_hir_value_ref_t node = scc_hir_builder_call(&ctx->builder, func, args.data, args.size); scc_vec_free(args); return node; } case SCC_AST_EXPR_ARRAY_SUBSCRIPT: { // 1. 计算数组/指针基址(右值,得到地址) scc_hir_value_ref_t base_ptr = scc_ast2ir_expr(ctx, expr->subscript.array, true); // 2. 计算下标值 scc_hir_value_ref_t index = scc_ast2ir_expr(ctx, expr->subscript.index, false); // 3. 生成 getptr(GEP) scc_hir_value_ref_t elem_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, index); // 4. 根据左值/右值返回 if (is_lvalue) { return elem_ptr; // 作为左值:返回地址 } else { return scc_hir_builder_load(&ctx->builder, elem_ptr); // 作为右值:加载值 } } case SCC_AST_EXPR_MEMBER: { // 1. 获取基对象的左值(地址) scc_hir_value_ref_t base_ptr = scc_ast2ir_expr(ctx, expr->member.base, true); // 2. 通过偏移生成字段地址 // 需要基对象类型来计算索引:假设 sema 填好了 _target_idx usize field_idx = expr->member._target_idx; scc_ap_t idx_ap; scc_ap_set_int(&idx_ap, field_idx); scc_hir_value_ref_t idx_val = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap); scc_hir_value_ref_t field_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, idx_val); if (is_lvalue) return field_ptr; else return scc_hir_builder_load(&ctx->builder, field_ptr); } case SCC_AST_EXPR_PTR_MEMBER: { // 1. 计算指针值(obj->field 等价于 (*obj).field) scc_hir_value_ref_t obj_ptr = scc_ast2ir_expr(ctx, expr->member.base, false); // 2. 解引用得到对象地址,再访问成员 // 但更简单:先 load 出对象值?不对:obj // 是指向结构体的指针,我们需要指针的地址? 实际上,obj->field 相当于 // (*(obj)).field,所以可以直接用 obj 作为基地址进行 get_elem_ptr // 因为 get_elem_ptr 接收一个指针,obj 本身就是指向结构体的指针。 usize field_idx = expr->member._target_idx; scc_ap_t idx_ap; scc_ap_set_int(&idx_ap, field_idx); scc_hir_value_ref_t idx_val = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap); scc_hir_value_ref_t field_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, obj_ptr, idx_val); if (is_lvalue) return field_ptr; else return scc_hir_builder_load(&ctx->builder, field_ptr); } case SCC_AST_EXPR_CAST: break; case SCC_AST_EXPR_SIZE_OF: { TODO(); // return scc_hir_builder_integer( // &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val); } case SCC_AST_EXPR_ALIGN_OF: { TODO(); // return scc_hir_builder_integer( // &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val); } case SCC_AST_EXPR_COMPOUND: { } break; case SCC_AST_EXPR_LVALUE: break; // SCC_AST_EXPR_BUILTIN,// 内置表达式 ... directive map to ir builtin case SCC_AST_EXPR_INT_LITERAL: { // FIXME maybe using some array to int; scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_t value; scc_ap_from_cstr(&value, expr->literal.lexme, 10); return scc_hir_builder_integer(&ctx->builder, type_ref, &value); } // SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量 case SCC_AST_EXPR_CHAR_LITERAL: { // FIXME just 'a' '\n' scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); const char *lexme = expr->literal.lexme; Assert(lexme[0] == '\''); u8 int_lit = 0; if (lexme[1] == '\\') { switch (lexme[2]) { case 'a': int_lit = '\a'; break; case 'b': int_lit = '\b'; break; case 'f': int_lit = '\f'; break; case 'n': int_lit = '\n'; break; case 'r': int_lit = '\r'; } } else { int_lit = lexme[1]; } scc_ap_t value; scc_ap_set_int(&value, int_lit); return scc_hir_builder_integer(&ctx->builder, type_ref, &value); } case SCC_AST_EXPR_STRING_LITERAL: { // FIXME scc_hir_value_ref_t value = scc_hir_builder_const_string(&ctx->builder, expr->literal.lexme, scc_strlen(expr->literal.lexme)); if (is_lvalue) TODO(); return value; } case SCC_AST_EXPR_IDENTIFIER: { if (expr->identifier._target == nullptr) { LOG_ERROR("unknown identifier %s", expr->identifier.name); } // FIXME hack hashtable scc_hir_value_ref_t in = (scc_hir_value_ref_t)(usize)scc_hashtable_get( &ctx->ast2ir_cache, expr->identifier._target); Assert(in != 0); if (is_lvalue) { return in; } else { // 右值:如果是数组类型,退化为指针(返回地址) scc_hir_type_t *ir_type = scc_hir_module_get_type_by_value( &ctx->builder.cprog->module, in); if (ir_type->tag == SCC_HIR_TYPE_PTR) { scc_hir_type_t *target_type = scc_hir_module_get_type( &ctx->builder.cprog->module, ir_type->data.pointer.base); if (target_type->tag == SCC_HIR_TYPE_ARRAY) { // 生成 getptr 获取数组首地址 return scc_hir_builder_get_elem_ptr(&ctx->builder, in, SCC_HIR_REF_nullptr); } else { // 标量类型:加载值 return scc_hir_builder_load(&ctx->builder, in); } } else { return in; } } } default: LOG_FATAL("Unsupported expression type: %d", expr->base.type); return 0; } UNREACHABLE(); } /** * @brief * * @param ctx * @param stmt */ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { if (stmt == nullptr) { 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), false); } 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_hir_value_ref_t true_block = scc_hir_builder_bblock(&ctx->builder, "if_true"); scc_hir_value_ref_t false_block = scc_hir_builder_bblock(&ctx->builder, "if_false"); scc_hir_value_ref_t merge_block = scc_hir_builder_bblock(&ctx->builder, "if_merge"); scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->if_stmt.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, true_block, false_block); // 生成true分支 scc_hir_builder_set_current_bblock(&ctx->builder, true_block); scc_ast2ir_stmt(ctx, stmt->if_stmt.then_stmt); scc_hir_builder_jump(&ctx->builder, merge_block); // 生成false分支 if (stmt->if_stmt.opt_else_stmt) { scc_hir_builder_set_current_bblock(&ctx->builder, false_block); scc_ast2ir_stmt(ctx, stmt->if_stmt.opt_else_stmt); scc_hir_builder_jump(&ctx->builder, merge_block); } scc_hir_builder_set_current_bblock(&ctx->builder, merge_block); break; } case SCC_AST_STMT_WHILE: { scc_hir_value_ref_t cond_block = scc_hir_builder_bblock(&ctx->builder, "while_cond"); scc_hir_value_ref_t body_block = scc_hir_builder_bblock(&ctx->builder, "while_body"); scc_hir_value_ref_t exit_block = scc_hir_builder_bblock(&ctx->builder, "while_exit"); scc_hashtable_set(&ctx->break_cache, stmt, (void *)exit_block); scc_hashtable_set(&ctx->continue_cache, stmt, (void *)cond_block); scc_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_set_current_bblock(&ctx->builder, cond_block); scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->while_stmt.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); scc_hir_builder_set_current_bblock(&ctx->builder, body_block); scc_ast2ir_stmt(ctx, stmt->while_stmt.body); scc_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_set_current_bblock(&ctx->builder, exit_block); break; } case SCC_AST_STMT_DO_WHILE: { scc_hir_value_ref_t cond_block = scc_hir_builder_bblock(&ctx->builder, "do_while_cond"); scc_hir_value_ref_t body_block = scc_hir_builder_bblock(&ctx->builder, "do_while_body"); scc_hir_value_ref_t exit_block = scc_hir_builder_bblock(&ctx->builder, "do_while_exit"); scc_hashtable_set(&ctx->break_cache, stmt, (void *)exit_block); scc_hashtable_set(&ctx->continue_cache, stmt, (void *)cond_block); scc_hir_builder_jump(&ctx->builder, body_block); scc_hir_builder_set_current_bblock(&ctx->builder, body_block); scc_ast2ir_stmt(ctx, stmt->while_stmt.body); scc_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_set_current_bblock(&ctx->builder, cond_block); scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->while_stmt.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); scc_hir_builder_set_current_bblock(&ctx->builder, exit_block); break; } case SCC_AST_STMT_FOR: { scc_hir_value_ref_t cond_block = scc_hir_builder_bblock(&ctx->builder, "for_cond"); scc_hir_value_ref_t body_block = scc_hir_builder_bblock(&ctx->builder, "for_body"); scc_hir_value_ref_t incr_block = scc_hir_builder_bblock(&ctx->builder, "for_incr"); scc_hir_value_ref_t exit_block = scc_hir_builder_bblock(&ctx->builder, "for_exit"); scc_hashtable_set(&ctx->break_cache, stmt, (void *)exit_block); scc_hashtable_set(&ctx->continue_cache, stmt, (void *)incr_block); 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), false); } 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_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_set_current_bblock(&ctx->builder, cond_block); if (stmt->for_stmt.cond) { scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->for_stmt.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); } else { scc_hir_builder_jump(&ctx->builder, body_block); } scc_hir_builder_set_current_bblock(&ctx->builder, body_block); scc_ast2ir_stmt(ctx, stmt->for_stmt.body); scc_hir_builder_jump(&ctx->builder, incr_block); scc_hir_builder_set_current_bblock(&ctx->builder, incr_block); if (stmt->for_stmt.incr) { scc_ast2ir_expr(ctx, stmt->for_stmt.incr, false); } scc_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_set_current_bblock(&ctx->builder, exit_block); break; } // SCC_AST_STMT_SWITCH, // switch 语句 // SCC_AST_STMT_CASE, // case 语句 // SCC_AST_STMT_DEFAULT, // default 语句 case SCC_AST_STMT_BREAK: { scc_hir_bblock_ref_t target = (usize)scc_hashtable_get(&ctx->break_cache, stmt->jump._target); Assert(target != SCC_HIR_REF_nullptr); scc_hir_builder_jump(&ctx->builder, target); } break; case SCC_AST_STMT_CONTINUE: { scc_hir_bblock_ref_t target = (usize)scc_hashtable_get(&ctx->continue_cache, stmt->jump._target); Assert(target != SCC_HIR_REF_nullptr); scc_hir_builder_jump(&ctx->builder, target); } break; case SCC_AST_STMT_RETURN: { if (stmt->return_stmt.expr) { scc_hir_value_ref_t ret_val_node = scc_ast2ir_expr(ctx, stmt->return_stmt.expr, false); scc_hir_builder_ret(&ctx->builder, ret_val_node); } else { scc_hir_builder_ret_void(&ctx->builder); } break; } case SCC_AST_STMT_GOTO: { scc_hir_bblock_ref_t target = (usize)scc_hashtable_get( &ctx->ast2ir_cache, (void *)stmt->goto_stmt._target); Assert(target != SCC_HIR_REF_nullptr); scc_hir_builder_jump(&ctx->builder, target); } break; case SCC_AST_STMT_LABEL: { scc_hir_value_ref_t label_block = scc_hir_builder_bblock(&ctx->builder, stmt->label_stmt.label); scc_hir_builder_set_current_bblock(&ctx->builder, label_block); scc_hashtable_set(&ctx->ast2ir_cache, stmt, (void *)label_block); scc_ast2ir_stmt(ctx, stmt->label_stmt.stmt); } break; 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, const scc_ast_decl_t *decl, cbool is_global) { if (ctx == nullptr || decl == nullptr) { LOG_ERROR("Invalid argument"); return; } switch (decl->base.type) { case SCC_AST_DECL_VAR: { // 1. 获取原始类型(可能数组长度为0) scc_hir_type_ref_t orig_type_ref = scc_ast2ir_type(ctx, decl->var.type); // 借用指针并拷贝类型(避免悬空) const scc_hir_type_t *orig_type; SCC_HIR_BUILDER_BEGIN_BORROW( &ctx->builder, orig_type, scc_hir_module_get_type(&ctx->builder.cprog->module, orig_type_ref)); scc_hir_type_t final_type_desc = *orig_type; SCC_HIR_BUILDER_END_BORROW(&ctx->builder); // 2. 如果是未知长度数组且有初始化,解析实际长度 scc_hir_type_ref_t final_type_ref = orig_type_ref; if (decl->var.init && final_type_desc.tag == SCC_HIR_TYPE_ARRAY && final_type_desc.data.array.len == 0) { scc_hir_type_t tmp_type_desc; resolve_array_length(ctx, &final_type_desc, &tmp_type_desc, decl->var.init); final_type_desc = tmp_type_desc; final_type_ref = scc_hir_builder_type(&ctx->builder, &final_type_desc); // 此时 final_type_desc 中的长度已经确定 } // 3. 分配变量(栈或全局) scc_hir_value_ref_t alloc_val_node; if (is_global) { // 全局变量:需要生成全局分配,当前代码暂未实现,保留 TODO // alloc_val_node = scc_hir_builder_global_alloca(&ctx->builder, // final_type_ref, decl->name); // scc_vec_push(builder->cprog->global_vals, alloc_val_node); // 这里先返回,后续补充 return; } else { alloc_val_node = scc_hir_builder_alloca(&ctx->builder, final_type_ref, decl->name); } scc_hashtable_set(&ctx->ast2ir_cache, decl, (void *)(usize)alloc_val_node); // 4. 处理初始化 if (decl->var.init) { // 再次借用 final_type 以判断是否为数组 const scc_hir_type_t *final_type; SCC_HIR_BUILDER_BEGIN_BORROW( &ctx->builder, final_type, scc_hir_module_get_type(&ctx->builder.cprog->module, final_type_ref)); scc_hir_type_t type = *final_type; SCC_HIR_BUILDER_END_BORROW(&ctx->builder); if (type.tag == SCC_HIR_TYPE_ARRAY) { emit_array_initialization(ctx, alloc_val_node, &type, decl->var.init); } else { // 标量类型 scc_hir_value_ref_t init_val = scc_ast2ir_expr(ctx, decl->var.init, false); scc_hir_builder_store(&ctx->builder, alloc_val_node, init_val); } } break; } case SCC_AST_DECL_FUNC: { scc_hir_type_ref_t func_type_ref = scc_ast2ir_type(ctx, decl->func.type); scc_hir_func_ref_t func_ref = (usize)scc_hashtable_get(&ctx->symtab, decl->name); if (func_ref == SCC_HIR_REF_nullptr) { func_ref = scc_hir_builder_func(&ctx->builder, func_type_ref, decl->name); scc_hashtable_set(&ctx->symtab, decl->name, (void *)(usize)func_ref); } if (decl->func.body == nullptr) { // function decl break; } scc_hir_builder_begin_func(&ctx->builder, func_ref); scc_hir_builder_begin_bblock(&ctx->builder, "entry"); scc_vec_foreach(scc_ast_canon_type(decl->func.type)->function.params, i) { scc_ast_decl_t *param = scc_vec_at( scc_ast_canon_type(decl->func.type)->function.params, i); scc_ast2ir_decl(ctx, param, false); } scc_ast2ir_stmt(ctx, decl->func.body); // FIXME need ret for none return or other default ret scc_hir_builder_ret_void(&ctx->builder); scc_hir_builder_end_bblock(&ctx->builder); scc_hir_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, is_global); } break; } case SCC_AST_DECL_PARAM: { if (decl->param.type->base.type == SCC_AST_TYPE_BUILTIN && scc_ast_canon_type(decl->param.type)->builtin.type == SCC_AST_BUILTIN_TYPE_VOID) { break; } scc_hir_type_ref_t parma_type_ref = scc_ast2ir_type(ctx, decl->param.type); scc_hir_value_ref_t param_ref = scc_hir_builder_func_arg_ref( &ctx->builder, parma_type_ref, decl->name, decl->param.param_idx); if (!ctx->hint_using_value) { scc_hir_value_ref_t val_ref = scc_hir_builder_alloca( &ctx->builder, parma_type_ref, decl->name); scc_hir_builder_store(&ctx->builder, val_ref, param_ref); scc_hashtable_set(&ctx->ast2ir_cache, decl, (void *)(usize)val_ref); } else { Panic("using value is not supported"); } break; } case SCC_AST_DECL_STRUCT: case SCC_AST_DECL_UNION: { scc_ast_canon_type_t canon_type = { .record.decl = decl, .record.name = decl->name, }; scc_ast_qual_type_t type = { .base.type = SCC_AST_DECL_STRUCT ? SCC_AST_TYPE_STRUCT : SCC_AST_TYPE_UNION, .type = &canon_type, }; scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, &type); // scc_hir_builder_global_alloca(&ctx->builder, type_ref, // SCC_HIR_REF_nullptr); } break; case SCC_AST_DECL_ENUM: { scc_ap_t val; int idx = 0; scc_ap_set_int(&val, idx); scc_vec_foreach(decl->record.fields, i) { scc_ast_decl_t *item = scc_vec_at(decl->record.fields, i); Assert(item->base.type == SCC_AST_DECL_VAR); if (item->var.init) { Assert(item->var.init->base.type == SCC_AST_EXPR_INT_LITERAL); scc_ap_from_cstr(&val, item->var.init->literal.lexme, 10); } scc_hir_value_ref_t item_val_ref = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_i32(&ctx->builder), &val); scc_hashtable_set(&ctx->ast2ir_cache, item, (void *)(usize)item_val_ref); scc_ap_set_int(&val, ++idx); } } break; case SCC_AST_DECL_TYPEDEF: break; default: LOG_FATAL("Unsupported declaration type: %d", decl->base.type); break; } } void scc_ast2ir_run(scc_ast2ir_ctx_t *ctx, const scc_ast_translation_unit_t *tu) { Assert(ctx != nullptr && tu != nullptr); scc_vec_foreach(tu->declarations, i) { scc_ast_decl_t *decl = scc_vec_at(tu->declarations, i); scc_ast2ir_decl(ctx, decl, true); } } void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, scc_ast_ctx_t *ast_ctx, scc_hir_cprog_t *cprog) { Assert(ctx != nullptr); Assert(abi != nullptr); Assert(ast_ctx != nullptr); Assert(cprog != nullptr); ctx->abi = abi; ctx->ast_ctx = ast_ctx; scc_hir_builder_init(&ctx->builder, cprog); scc_hashtable_usize_init(&ctx->ast2ir_cache); scc_hashtable_usize_init(&ctx->break_cache); scc_hashtable_usize_init(&ctx->continue_cache); scc_hashtable_cstr_init(&ctx->symtab); ctx->hint_using_value = false; } void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) { scc_hir_builder_drop(&ctx->builder); scc_hashtable_drop(&ctx->ast2ir_cache); scc_hashtable_drop(&ctx->break_cache); scc_hashtable_drop(&ctx->continue_cache); scc_hashtable_drop(&ctx->symtab); }