feat(ast2ir): 添加数组初始化支持和AST转IR优化
添加了对未知长度数组的自动长度推导功能,支持字符串字面量和复合 初始化的数组长度计算。新增辅助函数resolve_array_length用于计算 数组实际长度,以及emit_array_initialization用于生成数组初始化 代码。 同时将AST转IR过程中的参数改为const引用,提高代码安全性。 新增IR构建器的借用检查机制,防止在借用期间进行重分配操作。 fix(ast): 为AST结构体添加详细注释说明字段用途
This commit is contained in:
@@ -188,6 +188,7 @@ struct scc_ast_type {
|
||||
} record;
|
||||
struct {
|
||||
const char *name;
|
||||
/// @brief 指向typedef的声明(可以间接找到typedef的指向的类型)
|
||||
scc_ast_decl_t *decl;
|
||||
} typedef_type;
|
||||
};
|
||||
@@ -312,7 +313,9 @@ struct scc_ast_expr {
|
||||
// 复合字面量
|
||||
struct {
|
||||
scc_ast_expr_t *base;
|
||||
/// @brief 赋值语句的左值
|
||||
scc_ast_expr_vec_t lhs_exprs;
|
||||
/// @brief 赋值语句的右值
|
||||
scc_ast_expr_vec_t rhs_exprs;
|
||||
} compound;
|
||||
// 字面量
|
||||
@@ -429,10 +432,11 @@ struct scc_ast_decl {
|
||||
} param;
|
||||
// 结构体/联合/枚举声明
|
||||
struct {
|
||||
/// @brief 结构体/联合/枚举的字段
|
||||
scc_ast_decl_vec_t fields;
|
||||
} record;
|
||||
// typedef 声明
|
||||
struct {
|
||||
/// @brief 被 typedef 的类型
|
||||
scc_ast_type_t *type;
|
||||
} typedef_decl;
|
||||
};
|
||||
|
||||
@@ -19,13 +19,13 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
||||
void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx);
|
||||
|
||||
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,
|
||||
const scc_ast_translation_unit_t *tu);
|
||||
void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
||||
cbool is_global);
|
||||
scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
cbool is_lvalue);
|
||||
void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt);
|
||||
scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
const scc_ast_expr_t *expr, cbool is_lvalue);
|
||||
void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt);
|
||||
scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast_type_t *ast_type);
|
||||
const scc_ast_type_t *ast_type);
|
||||
|
||||
#endif /* __SCC_AST2IR_H__ */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <scc_ast2ir.h>
|
||||
|
||||
static scc_ir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast_type_t *ast_type) {
|
||||
const scc_ast_type_t *ast_type) {
|
||||
scc_abi_type_layout_t layout;
|
||||
// 映射内置类型
|
||||
ctx->abi->compute_type_layout(ctx->abi, ast_type, &layout);
|
||||
@@ -37,8 +37,100 @@ static inline void parse_lexme2const_int(const char *lexme,
|
||||
value->int64 = int_lit;
|
||||
}
|
||||
|
||||
// 辅助函数:计算数组实际长度(如果原长度为0)
|
||||
static void resolve_array_length(scc_ast2ir_ctx_t *ctx,
|
||||
const scc_ir_type_t *orig_array_type,
|
||||
scc_ir_type_t *resolved_array_type,
|
||||
const scc_ast_expr_t *init_expr) {
|
||||
*resolved_array_type = *orig_array_type; // 拷贝
|
||||
Assert(orig_array_type->tag == SCC_IR_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_ir_value_ref_t array_ptr,
|
||||
const scc_ir_type_t *array_type,
|
||||
const scc_ast_expr_t *init_expr) {
|
||||
Assert(array_type->tag == SCC_IR_TYPE_ARRAY);
|
||||
scc_ir_type_ref_t elem_type_ref = array_type->data.array.base;
|
||||
const scc_ir_type_t *elem_type =
|
||||
scc_ir_module_get_type(ctx->builder.ctx.module, elem_type_ref);
|
||||
usize array_len = array_type->data.array.len;
|
||||
|
||||
// 字符串字面量初始化:直接 memcpy
|
||||
if (init_expr->base.type == SCC_AST_EXPR_STRING_LITERAL) {
|
||||
scc_ir_value_ref_t str_val = scc_ast2ir_expr(ctx, init_expr, false);
|
||||
scc_ir_const_int_t len_const = {.int64 = array_len};
|
||||
scc_ir_value_ref_t len_ref = scc_ir_builder_const_int(
|
||||
&ctx->builder, scc_ir_builder_type_u64(&ctx->builder), len_const);
|
||||
scc_ir_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_ir_value_ref_t idx_val = scc_ir_builder_const_int(
|
||||
&ctx->builder, scc_ir_builder_type_u64(&ctx->builder),
|
||||
(scc_ir_const_int_t){.int64 = idx});
|
||||
scc_ir_value_ref_t elem_ptr =
|
||||
scc_ir_builder_get_elem_ptr(&ctx->builder, array_ptr, idx_val);
|
||||
|
||||
// 递归处理:如果元素本身是数组且初始化表达式是复合初始化,需要嵌套处理
|
||||
if (elem_type->tag == SCC_IR_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_ir_value_ref_t val = scc_ast2ir_expr(ctx, elem_expr, false);
|
||||
scc_ir_builder_store(&ctx->builder, elem_ptr, val);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
// 如果初始化列表元素少于数组长度,剩余元素默认零初始化(C 标准要求)
|
||||
// 这里简单忽略,实际可生成 memset 循环,但为简化暂不处理
|
||||
}
|
||||
|
||||
scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast_type_t *ast_type) {
|
||||
const scc_ast_type_t *ast_type) {
|
||||
if (ctx == nullptr || ast_type == nullptr) {
|
||||
LOG_ERROR("args is nullptr");
|
||||
return 0;
|
||||
@@ -104,6 +196,7 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ir_type_init(&ir_type, ast_type->base.type == SCC_AST_TYPE_STRUCT
|
||||
? SCC_IR_TYPE_STRUCT
|
||||
: SCC_IR_TYPE_UNION);
|
||||
Assert(ast_type->record.decl != nullptr);
|
||||
scc_vec_foreach(ast_type->record.decl->record.fields, i) {
|
||||
scc_ast_decl_t *decl_field =
|
||||
scc_vec_at(ast_type->record.decl->record.fields, i);
|
||||
@@ -119,7 +212,9 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
ctx, &(scc_ast_type_t){.base.type = SCC_AST_TYPE_BUILTIN,
|
||||
.builtin = SCC_AST_BUILTIN_TYPE_INT});
|
||||
case SCC_AST_TYPE_TYPEDEF:
|
||||
return 0;
|
||||
// TODO maybe using cache
|
||||
return scc_ast2ir_type(ctx,
|
||||
ast_type->typedef_type.decl->typedef_decl.type);
|
||||
default:
|
||||
LOG_FATAL("Unsupported AST type: %d", ast_type->base.type);
|
||||
return 0;
|
||||
@@ -128,7 +223,7 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast_expr_t *expr,
|
||||
const scc_ast_expr_t *expr,
|
||||
scc_ir_value_ref_t lhs,
|
||||
scc_ir_value_ref_t rhs) {
|
||||
// scc_ir_bblock_ref_t start_block =
|
||||
@@ -220,7 +315,8 @@ scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx,
|
||||
* @param expr
|
||||
* @return scc_ir_value_ref_t
|
||||
*/
|
||||
scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
scc_ir_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");
|
||||
@@ -466,7 +562,8 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
break;
|
||||
case SCC_AST_EXPR_PTR_MEMBER:
|
||||
break;
|
||||
// SCC_AST_EXPR_CAST, // 类型转换
|
||||
case SCC_AST_EXPR_CAST:
|
||||
break;
|
||||
case SCC_AST_EXPR_SIZE_OF: {
|
||||
scc_ir_const_int_t val;
|
||||
// FIXME
|
||||
@@ -577,7 +674,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
* @param ctx
|
||||
* @param stmt
|
||||
*/
|
||||
void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
|
||||
void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) {
|
||||
if (stmt == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -757,7 +854,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
|
||||
* @param ctx
|
||||
* @param decl
|
||||
*/
|
||||
void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *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");
|
||||
@@ -766,58 +863,64 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl,
|
||||
|
||||
switch (decl->base.type) {
|
||||
case SCC_AST_DECL_VAR: {
|
||||
// 转换类型
|
||||
scc_ir_type_ref_t ir_type_ref = scc_ast2ir_type(ctx, decl->var.type);
|
||||
// 1. 获取原始类型(可能数组长度为0)
|
||||
scc_ir_type_ref_t orig_type_ref = scc_ast2ir_type(ctx, decl->var.type);
|
||||
// 借用指针并拷贝类型(避免悬空)
|
||||
const scc_ir_type_t *orig_type;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
&ctx->builder, orig_type,
|
||||
scc_ir_module_get_type(ctx->builder.ctx.module, orig_type_ref));
|
||||
scc_ir_type_t final_type_desc = *orig_type;
|
||||
SCC_IR_BUILDER_END_BORROW(&ctx->builder);
|
||||
|
||||
// 创建分配节点
|
||||
scc_ir_value_ref_t alloc_val_node = SCC_IR_REF_nullptr;
|
||||
// 2. 如果是未知长度数组且有初始化,解析实际长度
|
||||
scc_ir_type_ref_t final_type_ref = orig_type_ref;
|
||||
if (decl->var.init && final_type_desc.tag == SCC_IR_TYPE_ARRAY &&
|
||||
final_type_desc.data.array.len == 0) {
|
||||
scc_ir_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_ir_builder_type(&ctx->builder, &final_type_desc);
|
||||
// 此时 final_type_desc 中的长度已经确定
|
||||
}
|
||||
|
||||
// 3. 分配变量(栈或全局)
|
||||
scc_ir_value_ref_t alloc_val_node;
|
||||
if (is_global) {
|
||||
// alloc_val_node = scc_ir_builder_global_alloca(
|
||||
// &ctx->builder, ir_type_ref, decl->name);
|
||||
// 全局变量:需要生成全局分配,当前代码暂未实现,保留 TODO
|
||||
// alloc_val_node = scc_ir_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_ir_builder_alloca(&ctx->builder, ir_type_ref, decl->name);
|
||||
alloc_val_node = scc_ir_builder_alloca(&ctx->builder,
|
||||
final_type_ref, decl->name);
|
||||
}
|
||||
Assert(alloc_val_node != SCC_IR_REF_nullptr);
|
||||
|
||||
scc_hashtable_set(&ctx->ast2ir_cache, decl,
|
||||
(void *)(usize)alloc_val_node);
|
||||
|
||||
// 如果有初始化表达式
|
||||
if (!decl->var.init) {
|
||||
break;
|
||||
}
|
||||
scc_ir_value_ref_t init_val_node =
|
||||
scc_ast2ir_expr(ctx, decl->var.init, false);
|
||||
Assert(init_val_node != SCC_IR_REF_nullptr);
|
||||
|
||||
// FIXME array auto calucate size
|
||||
scc_ir_type_t *ir_type =
|
||||
scc_ir_module_get_type(ctx->builder.ctx.module, ir_type_ref);
|
||||
if (ir_type->tag == SCC_IR_TYPE_ARRAY) {
|
||||
if (ir_type->data.array.len == 0) {
|
||||
scc_ast_expr_t *init_expr = decl->var.init;
|
||||
if (init_expr->base.type == SCC_AST_EXPR_COMPOUND) {
|
||||
Panic(
|
||||
"TODO: init_expr->base.type == SCC_AST_EXPR_COMPOUND");
|
||||
} else if (init_expr->base.type ==
|
||||
SCC_AST_EXPR_STRING_LITERAL) {
|
||||
ir_type->data.array.len =
|
||||
scc_strlen(init_expr->literal.lexme) + 1;
|
||||
|
||||
scc_ir_const_int_t len = {.int64 = ir_type->data.array.len};
|
||||
scc_ir_value_ref_t len_ref = scc_ir_builder_const_int(
|
||||
&ctx->builder, scc_ir_builder_type_u64(&ctx->builder),
|
||||
len);
|
||||
scc_ir_builder_builtin_memcpy(&ctx->builder, alloc_val_node,
|
||||
init_val_node, len_ref);
|
||||
} else {
|
||||
Panic("unknown init expr in array decl");
|
||||
}
|
||||
// 4. 处理初始化
|
||||
if (decl->var.init) {
|
||||
// 再次借用 final_type 以判断是否为数组
|
||||
const scc_ir_type_t *final_type;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
&ctx->builder, final_type,
|
||||
scc_ir_module_get_type(ctx->builder.ctx.module,
|
||||
final_type_ref));
|
||||
scc_ir_type_t type = *final_type;
|
||||
SCC_IR_BUILDER_END_BORROW(&ctx->builder);
|
||||
if (type.tag == SCC_IR_TYPE_ARRAY) {
|
||||
emit_array_initialization(ctx, alloc_val_node, &type,
|
||||
decl->var.init);
|
||||
} else {
|
||||
// 标量类型
|
||||
scc_ir_value_ref_t init_val =
|
||||
scc_ast2ir_expr(ctx, decl->var.init, false);
|
||||
scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val);
|
||||
}
|
||||
} else {
|
||||
scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -881,8 +984,8 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl,
|
||||
.record.name = decl->name,
|
||||
};
|
||||
scc_ir_type_ref_t type_ref = scc_ast2ir_type(ctx, &type);
|
||||
scc_ir_builder_global_alloca(&ctx->builder, type_ref,
|
||||
SCC_IR_REF_nullptr);
|
||||
// scc_ir_builder_global_alloca(&ctx->builder, type_ref,
|
||||
// SCC_IR_REF_nullptr);
|
||||
break;
|
||||
case SCC_AST_DECL_ENUM:
|
||||
scc_ir_const_int_t val;
|
||||
@@ -910,7 +1013,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl,
|
||||
}
|
||||
|
||||
void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast_translation_unit_t *tu) {
|
||||
const scc_ast_translation_unit_t *tu) {
|
||||
Assert(ctx != nullptr && tu != nullptr);
|
||||
|
||||
scc_vec_foreach(tu->declarations, i) {
|
||||
|
||||
@@ -20,8 +20,41 @@ struct scc_ir_builder {
|
||||
scc_ir_ctx_t ctx; ///< 核心上下文
|
||||
scc_ir_func_ref_t current_func; ///< 当前正在构建的函数
|
||||
scc_ir_bblock_ref_t current_bblock; ///< 当前基本块
|
||||
#ifndef SCC_NO_DEBUG
|
||||
int borrow_depth;
|
||||
const char *dbg_file;
|
||||
int dbg_line;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef SCC_NO_DEBUG
|
||||
#define SCC_IR_BUILDER_BEGIN_BORROW(builder, ptr_var, ptr_expr) \
|
||||
do { \
|
||||
(builder)->borrow_depth++; \
|
||||
(builder)->dbg_file = __FILE__; \
|
||||
(builder)->dbg_line = __LINE__; \
|
||||
ptr_var = (ptr_expr); \
|
||||
} while (0)
|
||||
|
||||
#define SCC_IR_BUILDER_END_BORROW(builder) \
|
||||
do { \
|
||||
(builder)->borrow_depth--; \
|
||||
} while (0)
|
||||
|
||||
#define SCC_IR_BUILDER_CHECK_NO_BORROW(builder) \
|
||||
do { \
|
||||
if ((builder)->borrow_depth != 0) { \
|
||||
Panic("IR Builder: attempt to reallocate while borrowed at %s:%d", \
|
||||
(builder)->dbg_file, (builder)->dbg_line); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define SCC_IR_BUILDER_BEGIN_BORROW(builder, ptr_var, ptr_expr) \
|
||||
ptr_var = (ptr_expr)
|
||||
#define SCC_IR_BUILDER_END_BORROW(builder) ((void)0)
|
||||
#define SCC_IR_BUILDER_CHECK_NO_BORROW(builder) ((void)0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 初始化 IR 构建器
|
||||
*/
|
||||
@@ -110,52 +143,8 @@ scc_ir_builder_const_int(scc_ir_builder_t *builder, scc_ir_type_ref_t type,
|
||||
return scc_ir_module_add_value(&builder->cprog->module, &value);
|
||||
}
|
||||
|
||||
static inline scc_ir_value_ref_t
|
||||
scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str,
|
||||
usize len) {
|
||||
scc_ir_type_ref_t u8_type = scc_ir_builder_type_u8(builder);
|
||||
scc_ir_type_t array_type = {
|
||||
.tag = SCC_IR_TYPE_ARRAY,
|
||||
.data.array.base = u8_type,
|
||||
.data.array.len = len - 1, // 包含 nullptr 结尾
|
||||
};
|
||||
scc_ir_type_ref_t array_type_ref =
|
||||
scc_ir_ctx_get_type(&builder->ctx, &array_type);
|
||||
|
||||
// 5. 创建聚合节点
|
||||
scc_ir_value_t const_array_value = {
|
||||
.tag = SCC_IR_VALUE_TAG_CONST_ARRAY,
|
||||
.type = array_type_ref,
|
||||
.data.const_array.base_type = u8_type,
|
||||
};
|
||||
char *buff = scc_malloc(len - 1);
|
||||
Assert(buff);
|
||||
// FIXME content to real string
|
||||
for (usize i = 1; i < len - 1; i++) {
|
||||
buff[i - 1] = str[i];
|
||||
}
|
||||
buff[len - 2] = '\0';
|
||||
scc_vec_unsafe_from_buffer(const_array_value.data.const_array.fields,
|
||||
(u8 *)buff, len - 1);
|
||||
scc_ir_value_ref_t const_array_ref =
|
||||
scc_ir_module_add_value(builder->ctx.module, &const_array_value);
|
||||
Assert(const_array_ref != SCC_IR_REF_nullptr);
|
||||
|
||||
// 3. 创建全局变量节点,类型为指针,初始值指向常量数组
|
||||
scc_ir_value_ref_t global_value_ref =
|
||||
scc_ir_builder_global_alloca(builder, array_type_ref, const_array_ref);
|
||||
// scc_hashtable_insert(builder);
|
||||
|
||||
scc_ir_value_ref_t pointer_to_global_value = scc_ir_module_add_value(
|
||||
builder->ctx.module,
|
||||
&(scc_ir_value_t){
|
||||
.tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR,
|
||||
.data.get_elem_ptr.src_addr = global_value_ref,
|
||||
.data.get_elem_ptr.index = SCC_IR_VALUE_TAG_NULLPTR,
|
||||
});
|
||||
scc_ir_builder_add_instr(builder, pointer_to_global_value);
|
||||
return pointer_to_global_value;
|
||||
}
|
||||
scc_ir_value_ref_t scc_ir_builder_const_string(scc_ir_builder_t *builder,
|
||||
const char *str, usize len);
|
||||
|
||||
/**
|
||||
* @brief 开始构建函数
|
||||
|
||||
@@ -10,6 +10,11 @@ void scc_ir_builder_init(scc_ir_builder_t *builder, scc_ir_cprog_t *cprog) {
|
||||
builder->cprog = cprog;
|
||||
|
||||
scc_ir_ctx_init(&builder->ctx, GET_MODULE(builder));
|
||||
#ifndef SCC_NO_DEBUG
|
||||
builder->borrow_depth = 0;
|
||||
builder->dbg_file = nullptr;
|
||||
builder->dbg_line = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void scc_ir_builder_drop(scc_ir_builder_t *builder) {
|
||||
@@ -19,6 +24,7 @@ void scc_ir_builder_drop(scc_ir_builder_t *builder) {
|
||||
scc_ir_func_ref_t scc_ir_builder_func(scc_ir_builder_t *builder,
|
||||
scc_ir_type_ref_t type_ref,
|
||||
const char *name) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_func_ref_t func_ref =
|
||||
scc_ir_ctx_declare_func(&builder->ctx, type_ref, name);
|
||||
scc_vec_push(builder->cprog->func_decls, func_ref);
|
||||
@@ -27,43 +33,108 @@ scc_ir_func_ref_t scc_ir_builder_func(scc_ir_builder_t *builder,
|
||||
|
||||
scc_ir_type_ref_t scc_ir_builder_type(scc_ir_builder_t *builder,
|
||||
const scc_ir_type_t *type_desc) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
return scc_ir_ctx_get_type(&builder->ctx, type_desc);
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_const_string(scc_ir_builder_t *builder,
|
||||
const char *str, usize len) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_type_ref_t u8_type = scc_ir_builder_type_u8(builder);
|
||||
scc_ir_type_t array_type = {
|
||||
.tag = SCC_IR_TYPE_ARRAY,
|
||||
.data.array.base = u8_type,
|
||||
.data.array.len = len - 1, // 包含 nullptr 结尾
|
||||
};
|
||||
scc_ir_type_ref_t array_type_ref =
|
||||
scc_ir_ctx_get_type(&builder->ctx, &array_type);
|
||||
|
||||
// 5. 创建聚合节点
|
||||
scc_ir_value_t const_array_value = {
|
||||
.tag = SCC_IR_VALUE_TAG_CONST_ARRAY,
|
||||
.type = array_type_ref,
|
||||
.data.const_array.base_type = u8_type,
|
||||
};
|
||||
char *buff = scc_malloc(len - 1);
|
||||
Assert(buff);
|
||||
// FIXME content to real string
|
||||
for (usize i = 1; i < len - 1; i++) {
|
||||
buff[i - 1] = str[i];
|
||||
}
|
||||
buff[len - 2] = '\0';
|
||||
scc_vec_unsafe_from_buffer(const_array_value.data.const_array.fields,
|
||||
(u8 *)buff, len - 1);
|
||||
scc_ir_value_ref_t const_array_ref =
|
||||
scc_ir_module_add_value(builder->ctx.module, &const_array_value);
|
||||
Assert(const_array_ref != SCC_IR_REF_nullptr);
|
||||
|
||||
// 3. 创建全局变量节点,类型为指针,初始值指向常量数组
|
||||
scc_ir_value_ref_t global_value_ref =
|
||||
scc_ir_builder_global_alloca(builder, array_type_ref, const_array_ref);
|
||||
// scc_hashtable_insert(builder);
|
||||
|
||||
scc_ir_value_ref_t pointer_to_global_value = scc_ir_module_add_value(
|
||||
builder->ctx.module,
|
||||
&(scc_ir_value_t){
|
||||
.tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR,
|
||||
.data.get_elem_ptr.src_addr = global_value_ref,
|
||||
.data.get_elem_ptr.index = SCC_IR_VALUE_TAG_NULLPTR,
|
||||
});
|
||||
scc_ir_builder_add_instr(builder, pointer_to_global_value);
|
||||
return pointer_to_global_value;
|
||||
}
|
||||
|
||||
void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
|
||||
scc_ir_func_ref_t func_ref,
|
||||
const char **param_names) {
|
||||
// 创建函数并设置为当前函数
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
builder->current_func = func_ref;
|
||||
|
||||
scc_ir_func_t *func_ptr =
|
||||
scc_ir_module_get_func(GET_MODULE(builder), func_ref);
|
||||
scc_ir_type_t *func_type =
|
||||
scc_ir_module_get_type(GET_MODULE(builder), func_ptr->type);
|
||||
// 借用 func_ptr 和 func_type 以获取参数类型列表
|
||||
scc_ir_func_t *func_ptr = nullptr;
|
||||
scc_ir_type_t *func_type = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, func_ptr,
|
||||
scc_ir_module_get_func(GET_MODULE(builder), func_ref));
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, func_type,
|
||||
scc_ir_module_get_type(GET_MODULE(builder), func_ptr->type));
|
||||
|
||||
if (func_type == nullptr || func_type->tag != SCC_IR_TYPE_FUNC) {
|
||||
LOG_ERROR("Invalid function type");
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_type
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_ptr
|
||||
return;
|
||||
}
|
||||
|
||||
if (func_ptr == nullptr) {
|
||||
LOG_ERROR("Invalid function reference");
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_type
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_ptr
|
||||
return;
|
||||
}
|
||||
|
||||
if (scc_vec_size(func_ptr->bblocks) != 0 ||
|
||||
scc_vec_size(func_ptr->params) != 0) {
|
||||
LOG_FATAL("Multiple function definitions");
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_type
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_ptr
|
||||
return;
|
||||
}
|
||||
|
||||
scc_ir_type_ref_vec_t params = func_type->data.function.params;
|
||||
func_type = nullptr;
|
||||
scc_vec_foreach(params, i) {
|
||||
scc_ir_type_ref_t param_type = scc_vec_at(params, i);
|
||||
// 释放借用,因为下面要调用 add_value(可能 realloc)
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_type
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_ptr
|
||||
|
||||
// 预先分配所有参数值(临时数组,避免在循环中 push 到 func_ptr->params 时
|
||||
// func_ptr 失效)
|
||||
usize param_count = scc_vec_size(params);
|
||||
scc_ir_value_ref_t *param_refs =
|
||||
scc_malloc(sizeof(scc_ir_value_ref_t) * param_count);
|
||||
|
||||
for (usize i = 0; i < param_count; i++) {
|
||||
scc_ir_type_ref_t param_type = scc_vec_at(params, i);
|
||||
scc_ir_value_t param_node = {0};
|
||||
param_node.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF; // 参数节点标记
|
||||
param_node.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF;
|
||||
param_node.type = scc_ir_module_add_type(
|
||||
GET_MODULE(builder),
|
||||
&(scc_ir_type_t){.tag = SCC_IR_TYPE_PTR,
|
||||
@@ -71,36 +142,48 @@ void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
|
||||
param_node.name = param_names ? param_names[i] : nullptr;
|
||||
param_node.data.arg_ref.idx = i;
|
||||
scc_vec_init(param_node.used_by);
|
||||
|
||||
scc_ir_value_ref_t param_ref =
|
||||
param_refs[i] =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), ¶m_node);
|
||||
scc_vec_push(func_ptr->params, param_ref);
|
||||
}
|
||||
return;
|
||||
|
||||
// 重新借用 func_ptr 以添加参数到函数
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, func_ptr,
|
||||
scc_ir_module_get_func(GET_MODULE(builder), func_ref));
|
||||
for (usize i = 0; i < param_count; i++) {
|
||||
scc_vec_push(func_ptr->params, param_refs[i]);
|
||||
}
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_ptr
|
||||
}
|
||||
|
||||
void scc_ir_builder_end_func(scc_ir_builder_t *builder) {
|
||||
scc_ir_func_t *func_ptr =
|
||||
scc_ir_module_get_func(GET_MODULE(builder), builder->current_func);
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_func_t *func_ptr = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, func_ptr,
|
||||
scc_ir_module_get_func(GET_MODULE(builder), builder->current_func));
|
||||
if (func_ptr == nullptr) {
|
||||
LOG_FATAL("Invalid function reference");
|
||||
SCC_IR_BUILDER_END_BORROW(builder);
|
||||
return;
|
||||
}
|
||||
if (scc_vec_size(func_ptr->bblocks) == 0) {
|
||||
// FIXME
|
||||
scc_vec_push(builder->cprog->func_decls, builder->current_func);
|
||||
} else {
|
||||
scc_vec_push(builder->cprog->func_defs, builder->current_func);
|
||||
}
|
||||
SCC_IR_BUILDER_END_BORROW(builder);
|
||||
builder->current_func = 0;
|
||||
}
|
||||
|
||||
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_bblock(scc_ir_builder_t *builder,
|
||||
const char *label) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_bblock_t bblock = {0};
|
||||
if (label) {
|
||||
bblock.label = label;
|
||||
@@ -109,27 +192,33 @@ scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder,
|
||||
scc_ir_bblock_ref_t bblock_ref =
|
||||
scc_ir_module_add_bblock(GET_MODULE(builder), &bblock);
|
||||
|
||||
scc_ir_func_t *current_func =
|
||||
scc_ir_module_get_func(GET_MODULE(builder), builder->current_func);
|
||||
// 将基本块添加到当前函数
|
||||
scc_ir_func_t *current_func = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, current_func,
|
||||
scc_ir_module_get_func(GET_MODULE(builder), builder->current_func));
|
||||
if (current_func) {
|
||||
scc_vec_push(current_func->bblocks, bblock_ref);
|
||||
}
|
||||
SCC_IR_BUILDER_END_BORROW(builder);
|
||||
return bblock_ref;
|
||||
}
|
||||
|
||||
scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder,
|
||||
const char *label) {
|
||||
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
builder->current_bblock = scc_ir_builder_bblock(builder, label);
|
||||
return builder->current_bblock;
|
||||
}
|
||||
|
||||
void scc_ir_builder_end_bblock(scc_ir_builder_t *builder) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
builder->current_bblock = 0;
|
||||
}
|
||||
|
||||
void scc_ir_builder_set_current_bblock(scc_ir_builder_t *builder,
|
||||
scc_ir_bblock_ref_t bblock) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
builder->current_bblock = bblock;
|
||||
}
|
||||
|
||||
@@ -139,19 +228,23 @@ scc_ir_func_ref_t scc_ir_builder_current_bblock(scc_ir_builder_t *builder) {
|
||||
|
||||
void scc_ir_builder_add_instr(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t instr) {
|
||||
scc_ir_bblock_t *current_bblock =
|
||||
scc_ir_module_get_bblock(GET_MODULE(builder), builder->current_bblock);
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_bblock_t *current_bblock = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, current_bblock,
|
||||
scc_ir_module_get_bblock(GET_MODULE(builder), builder->current_bblock));
|
||||
if (current_bblock) {
|
||||
scc_vec_push(current_bblock->instrs, instr);
|
||||
} else {
|
||||
LOG_ERROR("Current basic block is not set");
|
||||
}
|
||||
SCC_IR_BUILDER_END_BORROW(builder);
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_global_alloca(scc_ir_builder_t *builder,
|
||||
scc_ir_type_ref_t type,
|
||||
scc_ir_value_ref_t value) {
|
||||
// FIXME MAYBE MEMORY LEAK
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
char *name = scc_malloc(32);
|
||||
scc_ir_value_ref_t global_value_ref = scc_ir_module_add_value(
|
||||
builder->ctx.module, &(scc_ir_value_t){
|
||||
@@ -161,7 +254,6 @@ scc_ir_value_ref_t scc_ir_builder_global_alloca(scc_ir_builder_t *builder,
|
||||
.data.global_alloc.value = value,
|
||||
});
|
||||
scc_snprintf(name, 32, "$G%u", global_value_ref);
|
||||
|
||||
scc_vec_push(builder->cprog->global_vals, global_value_ref);
|
||||
return global_value_ref;
|
||||
}
|
||||
@@ -169,6 +261,7 @@ scc_ir_value_ref_t scc_ir_builder_global_alloca(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
|
||||
scc_ir_type_ref_t type,
|
||||
const char *name) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t alloc_node = {0};
|
||||
alloc_node.tag = SCC_IR_VALUE_TAG_ALLOC;
|
||||
alloc_node.type = scc_ir_module_add_type(
|
||||
@@ -178,7 +271,6 @@ scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &alloc_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
@@ -187,6 +279,7 @@ scc_ir_value_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder,
|
||||
scc_ir_type_ref_t type,
|
||||
const char *name,
|
||||
usize arg_idx) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t value = {0};
|
||||
value.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF;
|
||||
value.type = type;
|
||||
@@ -195,31 +288,36 @@ scc_ir_value_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder,
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &value);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t target) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t load_node = {0};
|
||||
load_node.tag = SCC_IR_VALUE_TAG_LOAD;
|
||||
load_node.data.load.target = target;
|
||||
|
||||
// 设置类型为指针指向的类型
|
||||
scc_ir_value_t *ptr_node =
|
||||
scc_ir_module_get_value(GET_MODULE(builder), target);
|
||||
// 借用 ptr_node 和 ptr_type 获取类型信息
|
||||
scc_ir_value_t *ptr_node = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, ptr_node,
|
||||
scc_ir_module_get_value(GET_MODULE(builder), target));
|
||||
if (ptr_node) {
|
||||
scc_ir_type_t *ptr_type =
|
||||
scc_ir_module_get_type(GET_MODULE(builder), ptr_node->type);
|
||||
scc_ir_type_t *ptr_type = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, ptr_type,
|
||||
scc_ir_module_get_type(GET_MODULE(builder), ptr_node->type));
|
||||
if (ptr_type && ptr_type->tag == SCC_IR_TYPE_PTR) {
|
||||
load_node.type = ptr_type->data.pointer.base;
|
||||
}
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // ptr_type
|
||||
}
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // ptr_node
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &load_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
@@ -227,6 +325,7 @@ scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t target,
|
||||
scc_ir_value_ref_t value) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
Assert(target != SCC_IR_REF_nullptr && value != SCC_IR_REF_nullptr);
|
||||
scc_ir_value_t store_node = {0};
|
||||
store_node.tag = SCC_IR_VALUE_TAG_STORE;
|
||||
@@ -235,7 +334,6 @@ scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &store_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
@@ -243,35 +341,44 @@ scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t scc_ir_builder_get_elem_ptr(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t target,
|
||||
scc_ir_value_ref_t index) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t get_ptr_node = {0};
|
||||
get_ptr_node.tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR;
|
||||
get_ptr_node.data.get_elem_ptr.src_addr = target;
|
||||
get_ptr_node.data.get_elem_ptr.index = index;
|
||||
|
||||
// 类型应与源地址相同(都是指针)
|
||||
scc_ir_type_t *type =
|
||||
scc_ir_module_get_type_by_value(GET_MODULE(builder), target);
|
||||
Assert(type != nullptr);
|
||||
if (type->tag == SCC_IR_TYPE_PTR) {
|
||||
scc_ir_type_t *base_type = scc_ir_module_get_type(
|
||||
GET_MODULE(builder), type->data.pointer.base);
|
||||
// 借用类型信息
|
||||
scc_ir_type_t *type_ref = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, type_ref,
|
||||
scc_ir_module_get_type_by_value(GET_MODULE(builder), target));
|
||||
Assert(type_ref != nullptr);
|
||||
scc_ir_type_t type = *type_ref; // 拷贝一份,避免后续借用
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // type_ref
|
||||
|
||||
if (type.tag == SCC_IR_TYPE_PTR) {
|
||||
scc_ir_type_t *base_type = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, base_type,
|
||||
scc_ir_module_get_type(GET_MODULE(builder),
|
||||
type_ref->data.pointer.base));
|
||||
if (base_type->tag == SCC_IR_TYPE_ARRAY) {
|
||||
// FIXME GEP maybe multiple levels
|
||||
get_ptr_node.type = scc_ir_builder_type(
|
||||
builder, &(scc_ir_type_t){
|
||||
.tag = SCC_IR_TYPE_PTR,
|
||||
.data.pointer.base = base_type->data.array.base,
|
||||
});
|
||||
scc_ir_type_t type = (scc_ir_type_t){
|
||||
.tag = SCC_IR_TYPE_PTR,
|
||||
.data.pointer.base = base_type->data.array.base,
|
||||
};
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // base_type
|
||||
get_ptr_node.type = scc_ir_builder_type(builder, &type);
|
||||
} else {
|
||||
get_ptr_node.type = scc_ir_builder_type(builder, type);
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // base_type
|
||||
get_ptr_node.type = scc_ir_builder_type(builder, &type);
|
||||
}
|
||||
} else {
|
||||
get_ptr_node.type = scc_ir_builder_type(builder, type);
|
||||
get_ptr_node.type = scc_ir_builder_type(builder, &type);
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &get_ptr_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
@@ -280,22 +387,24 @@ scc_ir_value_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
|
||||
scc_ir_op_type_t op,
|
||||
scc_ir_value_ref_t lhs,
|
||||
scc_ir_value_ref_t rhs) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t binop_node = {0};
|
||||
binop_node.tag = SCC_IR_VALUE_TAG_OP;
|
||||
binop_node.data.op.op = op;
|
||||
binop_node.data.op.lhs = lhs;
|
||||
binop_node.data.op.rhs = rhs;
|
||||
|
||||
// 类型通常与操作数相同(对于算术运算)
|
||||
scc_ir_value_t *lhs_node =
|
||||
scc_ir_module_get_value(GET_MODULE(builder), lhs);
|
||||
// 借用 lhs_node 获取类型
|
||||
scc_ir_value_t *lhs_node = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, lhs_node, scc_ir_module_get_value(GET_MODULE(builder), lhs));
|
||||
if (lhs_node) {
|
||||
binop_node.type = lhs_node->type;
|
||||
}
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // lhs_node
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &binop_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
@@ -304,34 +413,29 @@ scc_ir_value_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
|
||||
scc_ir_op_type_t op,
|
||||
scc_ir_value_ref_t lhs,
|
||||
scc_ir_value_ref_t rhs) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t cmp_node = {0};
|
||||
cmp_node.tag = SCC_IR_VALUE_TAG_OP;
|
||||
cmp_node.data.op.op = op;
|
||||
cmp_node.data.op.lhs = lhs;
|
||||
cmp_node.data.op.rhs = rhs;
|
||||
|
||||
// 比较操作的结果通常是布尔值
|
||||
cmp_node.type =
|
||||
0; // FIXME scc_ir_module_get_builtin_i32(GET_MODULE(builder));
|
||||
cmp_node.type = 0; // FIXME
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &cmp_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
|
||||
scc_ir_bblock_ref_t target) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t jump_node = {0};
|
||||
jump_node.tag = SCC_IR_VALUE_TAG_JUMP;
|
||||
jump_node.data.jump.target_bblock = target;
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &jump_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
@@ -340,6 +444,7 @@ scc_ir_value_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t cond,
|
||||
scc_ir_bblock_ref_t true_target,
|
||||
scc_ir_bblock_ref_t false_target) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t branch_node = {0};
|
||||
branch_node.tag = SCC_IR_VALUE_TAG_BRANCH;
|
||||
branch_node.data.branch.cond = cond;
|
||||
@@ -348,7 +453,6 @@ scc_ir_value_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &branch_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
@@ -357,6 +461,7 @@ scc_ir_value_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
|
||||
scc_ir_func_ref_t callee,
|
||||
const scc_ir_value_ref_t *args,
|
||||
usize arg_count) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t call_node = {0};
|
||||
call_node.tag = SCC_IR_VALUE_TAG_CALL;
|
||||
call_node.data.call.callee = callee;
|
||||
@@ -366,45 +471,50 @@ scc_ir_value_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
|
||||
scc_vec_push(call_node.data.call.args, args[i]);
|
||||
}
|
||||
|
||||
// 设置返回类型为被调用函数的返回类型
|
||||
scc_ir_func_t *callee_func =
|
||||
scc_ir_module_get_func(GET_MODULE(builder), callee);
|
||||
// 借用 callee_func 和 func_type 获取返回类型
|
||||
scc_ir_func_t *callee_func = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, callee_func,
|
||||
scc_ir_module_get_func(GET_MODULE(builder), callee));
|
||||
if (callee_func) {
|
||||
scc_ir_type_t *func_type =
|
||||
scc_ir_module_get_type(GET_MODULE(builder), callee_func->type);
|
||||
scc_ir_type_t *func_type = nullptr;
|
||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
||||
builder, func_type,
|
||||
scc_ir_module_get_type(GET_MODULE(builder), callee_func->type));
|
||||
if (func_type && func_type->tag == SCC_IR_TYPE_FUNC) {
|
||||
call_node.type = func_type->data.function.ret_type;
|
||||
}
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // func_type
|
||||
}
|
||||
SCC_IR_BUILDER_END_BORROW(builder); // callee_func
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &call_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t value) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t ret_node = {0};
|
||||
ret_node.tag = SCC_IR_VALUE_TAG_RET;
|
||||
ret_node.data.ret.ret_val = value;
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &ret_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder) {
|
||||
SCC_IR_BUILDER_CHECK_NO_BORROW(builder);
|
||||
scc_ir_value_t ret_node = {0};
|
||||
ret_node.tag = SCC_IR_VALUE_TAG_RET;
|
||||
ret_node.data.ret.ret_val = 0; // 无返回值
|
||||
ret_node.data.ret.ret_val = 0;
|
||||
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &ret_node);
|
||||
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
parse_value(ctx, value->data.get_elem_ptr.index, patches);
|
||||
// parse_value(ctx, value->data.get_elem_ptr.index, patches);
|
||||
|
||||
scc_reg_loc_t src_loc;
|
||||
scc_reg_loc_t idx_loc;
|
||||
@@ -337,8 +337,21 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
|
||||
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
|
||||
load_value_to_reg(ctx, &idx_loc, SCC_AMD64_RDX);
|
||||
|
||||
// 获取 src_addr 所指向的类型的元素大小
|
||||
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
|
||||
GET_MODULE(ctx), value->data.get_elem_ptr.src_addr);
|
||||
scc_ir_type_t *base_type = scc_ir_module_get_type(
|
||||
GET_MODULE(ctx), ptr_type->data.pointer.base);
|
||||
scc_ir_type_t ir_type = *base_type;
|
||||
if (ir_type.tag == SCC_IR_TYPE_ARRAY) {
|
||||
ir_type.tag = SCC_IR_TYPE_PTR;
|
||||
}
|
||||
int elem_size = scc_ir2mcode_type_width(GET_MODULE(ctx), &ir_type);
|
||||
// 然后生成 LEA 时使用 scale = elem_size
|
||||
scc_mcode_amd64_lea_r64_m64_sib(&ctx->sect_mcode, SCC_AMD64_RAX,
|
||||
SCC_AMD64_RAX, SCC_AMD64_RDX, 1, 0);
|
||||
SCC_AMD64_RAX, SCC_AMD64_RDX,
|
||||
elem_size, 0);
|
||||
}
|
||||
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
|
||||
break;
|
||||
@@ -483,28 +496,36 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||
///< 调用函数
|
||||
case SCC_IR_VALUE_TAG_CALL: {
|
||||
scc_reg_loc_t loc;
|
||||
/*
|
||||
ABI
|
||||
RAX 不稳定的 返回值寄存器
|
||||
RCX 不稳定的 第一个整型自变量
|
||||
RDX 不稳定的 第二个整型自变量
|
||||
R8 不稳定的 第三个整型自变量
|
||||
R9 不稳定的 第四个整型自变量
|
||||
*/
|
||||
scc_vec_foreach(value->data.call.args, i) {
|
||||
usize nargs = scc_vec_size(value->data.call.args);
|
||||
// 影子空间 32 字节 + 每个额外参数 8 字节(按 8 字节对齐)
|
||||
usize stack_args_count = (nargs > 4) ? (nargs - 4) : 0;
|
||||
usize stack_args_size = stack_args_count * 8;
|
||||
usize total_stack_alloc = 32 + stack_args_size;
|
||||
|
||||
// 调整栈指针(保持 16 字节对齐)
|
||||
if (total_stack_alloc > 0) {
|
||||
scc_mcode_amd64_sub_rsp_imm32(&ctx->sect_mcode, total_stack_alloc);
|
||||
}
|
||||
|
||||
// 处理寄存器参数(前 4 个)
|
||||
for (usize i = 0; i < nargs && i < 4; i++) {
|
||||
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
|
||||
if (i == 0) {
|
||||
load_value_to_reg(ctx, &loc, SCC_AMD64_RCX);
|
||||
} else if (i == 1) {
|
||||
load_value_to_reg(ctx, &loc, SCC_AMD64_RDX);
|
||||
} else if (i == 2) {
|
||||
load_value_to_reg(ctx, &loc, SCC_AMD64_R8);
|
||||
} else if (i == 3) {
|
||||
load_value_to_reg(ctx, &loc, SCC_AMD64_R9);
|
||||
} else {
|
||||
LOG_FATAL("not support more than 4 args");
|
||||
}
|
||||
// scc_mcode_amd64_push_r64();
|
||||
int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8,
|
||||
SCC_AMD64_R9};
|
||||
load_value_to_reg(ctx, &loc, reg[i]);
|
||||
}
|
||||
|
||||
// 处理栈参数(第 5 个及以后)
|
||||
// 从右向左依次写入栈(即最后一个参数放在最高地址)
|
||||
for (usize i = 4; i < nargs; i++) {
|
||||
scc_reg_loc_t loc;
|
||||
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
|
||||
// 加载到临时寄存器(如 RAX)
|
||||
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
|
||||
// 计算栈偏移:影子空间(32) + (i-4)*8
|
||||
int offset = 32 + (i - 4) * 8;
|
||||
scc_mcode_amd64_mov_m64_disp32_r64(&ctx->sect_mcode, SCC_AMD64_RSP,
|
||||
offset, SCC_AMD64_RAX);
|
||||
}
|
||||
|
||||
scc_ir_func_t *func =
|
||||
@@ -530,7 +551,10 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||
.sect_type = SCCF_SECT_CODE,
|
||||
.sym_idx = sym_idx,
|
||||
});
|
||||
|
||||
// 恢复栈指针
|
||||
if (total_stack_alloc > 0) {
|
||||
scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, total_stack_alloc);
|
||||
}
|
||||
// 处理返回值
|
||||
scc_ir_type_t *func_type =
|
||||
scc_ir_module_get_type(GET_MODULE(ctx), func->type);
|
||||
@@ -604,22 +628,22 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
|
||||
SCC_AMD64_RSP, ctx->stack_size);
|
||||
scc_reg_loc_t loc;
|
||||
scc_vec_foreach(func->params, i) {
|
||||
// scc_ir_value_t *param =
|
||||
// scc_ir_module_get_value(GET_MODULE(ctx), );
|
||||
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
|
||||
parse_location(ctx, &loc, node_ref);
|
||||
if (i == 0) {
|
||||
store_value_from_reg(ctx, &loc, SCC_AMD64_RCX);
|
||||
} else if (i == 1) {
|
||||
store_value_from_reg(ctx, &loc, SCC_AMD64_RDX);
|
||||
} else if (i == 2) {
|
||||
store_value_from_reg(ctx, &loc, SCC_AMD64_R8);
|
||||
} else if (i == 3) {
|
||||
store_value_from_reg(ctx, &loc, SCC_AMD64_R9);
|
||||
if (i < 4) {
|
||||
// 前 4 个参数:从寄存器存入槽位
|
||||
int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8,
|
||||
SCC_AMD64_R9};
|
||||
store_value_from_reg(ctx, &loc, reg[i]);
|
||||
} else {
|
||||
LOG_FATAL("not support more than 4 args");
|
||||
// 额外参数:从栈中加载到槽位
|
||||
// 偏移 = 16 (old rbp+retaddr) + 32 (shadow) + (i-4)*8
|
||||
int offset = 16 + 32 + (i - 4) * 8;
|
||||
// 临时将栈值加载到 RAX,再存储到槽位
|
||||
scc_mcode_amd64_mov_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RAX,
|
||||
SCC_AMD64_RBP, offset);
|
||||
store_value_from_reg(ctx, &loc, SCC_AMD64_RAX);
|
||||
}
|
||||
// scc_mcode_amd64_push_r64();
|
||||
}
|
||||
|
||||
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
|
||||
@@ -759,6 +783,4 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
|
||||
sccf_builder_add_text_section(ctx->builder, &text_section);
|
||||
|
||||
sccf_builder_add_data_section(ctx->builder, &ctx->sect_data);
|
||||
// FIXME maybe _entry and add crt
|
||||
ctx->builder->entry_symbol_name = "main";
|
||||
}
|
||||
|
||||
@@ -247,6 +247,10 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
||||
}
|
||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected semicolon after jump statement.");
|
||||
}
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_do_while_init(stmt, expression, statement, pos);
|
||||
return stmt;
|
||||
|
||||
@@ -21,6 +21,11 @@ usize sccf_builder_add_symbol(sccf_builder_t *builder, const char *name,
|
||||
sccf_sym_t *sym);
|
||||
usize sccf_builder_get_symbol_idx(sccf_builder_t *builder, const char *name);
|
||||
|
||||
static inline void sccf_builder_set_entry_symbol_name(sccf_builder_t *builder,
|
||||
const char *name) {
|
||||
builder->entry_symbol_name = name ? name : "_scc_entry";
|
||||
}
|
||||
|
||||
static inline sccf_sym_t *
|
||||
sccf_builder_get_symbol_unsafe(sccf_builder_t *builder, const char *name) {
|
||||
usize idx = sccf_builder_get_symbol_idx(builder, name);
|
||||
|
||||
@@ -75,7 +75,9 @@ const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) {
|
||||
sccf_sym_t *sym =
|
||||
sccf_builder_get_symbol_unsafe(builder, builder->entry_symbol_name);
|
||||
if (sym == nullptr || sym->sccf_sect_type != SCCF_SECT_CODE) {
|
||||
LOG_ERROR("entry symbol %s not found");
|
||||
LOG_ERROR(
|
||||
"entry symbol %s not found, using 0 for entry point address",
|
||||
builder->entry_symbol_name);
|
||||
builder->sccf.header.entry_point = 0;
|
||||
} else {
|
||||
builder->sccf.header.entry_point = sym->sccf_sect_offset;
|
||||
|
||||
@@ -66,7 +66,7 @@ static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx, const char *find_path) {
|
||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
||||
scc_vec_init(ctx->idata_libs);
|
||||
ctx->find_path = find_path;
|
||||
load_from_def(ctx, ctx->find_path, "ucrtbase.dll");
|
||||
load_from_def(ctx, ctx->find_path, "msvcrt.dll");
|
||||
}
|
||||
|
||||
static cbool pe_idata_get(pe_idata_lib_ctx_t *ctx, const char *name) {
|
||||
@@ -170,6 +170,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
|
||||
scc_pe_construct_idata(&idata_builder, &idata_range);
|
||||
|
||||
u32 entry_point_offset = sccf->header.entry_point;
|
||||
Assert(entry_point_offset < scc_vec_size(*code_data));
|
||||
u64 base_address = 0x140000000;
|
||||
u32 entry_point = code_range.virual_address + entry_point_offset;
|
||||
scc_pe_config_t config = (scc_pe_config_t){
|
||||
|
||||
Reference in New Issue
Block a user