feat(ast2ir): 添加数组初始化支持和AST转IR优化

添加了对未知长度数组的自动长度推导功能,支持字符串字面量和复合
初始化的数组长度计算。新增辅助函数resolve_array_length用于计算
数组实际长度,以及emit_array_initialization用于生成数组初始化
代码。

同时将AST转IR过程中的参数改为const引用,提高代码安全性。
新增IR构建器的借用检查机制,防止在借用期间进行重分配操作。

fix(ast): 为AST结构体添加详细注释说明字段用途
This commit is contained in:
zzy
2026-04-13 11:36:52 +08:00
parent 694778e4a0
commit ffb23afaf4
13 changed files with 480 additions and 220 deletions

View File

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

View File

@@ -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__ */

View File

@@ -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) {

View File

@@ -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 开始构建函数

View File

@@ -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), &param_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;
}

View File

@@ -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";
}

View File

@@ -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;

View File

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

View File

@@ -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;

View File

@@ -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){

View File

@@ -10,6 +10,7 @@ typedef struct {
int verbose;
scc_argparse_list_t include_paths;
scc_argparse_list_t define_macros;
const char *entry_point_symbol;
cbool emit_lex;
cbool emit_pp;
cbool emit_ast;
@@ -28,6 +29,8 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
SCC_HINT_TARGET_DESC,
SCC_HINT_VERBOSE,
SCC_HINT_ENTRY_POINT_SYMBOL,
SCC_HINT_EMIT_LEX,
SCC_HINT_EMIT_PP,
SCC_HINT_EMIT_AST,
@@ -44,6 +47,9 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
[SCC_HINT_TARGET_DESC] =
"Target description(eg. x86_64-pc-windows-msvc)",
[SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)",
[SCC_HINT_ENTRY_POINT_SYMBOL] = "Entry point symbol name",
[SCC_HINT_EMIT_LEX] = "Generate lexer sources tokens and exit",
[SCC_HINT_EMIT_PP] = "Generate preprocessed tokens and exit",
[SCC_HINT_EMIT_AST] = "Generate AST and exit",
@@ -58,6 +64,9 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
[SCC_HINT_DEFINED_MACRO] = "定义宏",
[SCC_HINT_TARGET_DESC] = "目标机器描述(eg. x86_64-pc-windows-msvc)",
[SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)",
[SCC_HINT_ENTRY_POINT_SYMBOL] = "入口点符号名称",
[SCC_HINT_EMIT_LEX] = "生成`源代码的词法单元`并退出",
[SCC_HINT_EMIT_PP] = "生成`预处理后的词法单元`并退出",
[SCC_HINT_EMIT_AST] = "生成`抽象语法树`并退出",
@@ -110,6 +119,14 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
scc_argparse_spec_setup_list(&opt_define.spec, &(config->define_macros));
scc_argparse_cmd_add_opt(root, &opt_define);
// --entry-point-symbol (设置入口点符号名称)
scc_argparse_opt_t opt_entry_point_symbol;
scc_argparse_opt_init(&opt_entry_point_symbol, 0, "entry-point-symbol",
scc_hints[SCC_HINT_ENTRY_POINT_SYMBOL]);
scc_argparse_spec_setup_string(&opt_entry_point_symbol.spec,
&(config->entry_point_symbol));
scc_argparse_cmd_add_opt(root, &opt_entry_point_symbol);
// --target
scc_argparse_opt_t opt_target;
scc_argparse_opt_init(&opt_target, 0, "target",

View File

@@ -80,6 +80,7 @@ int main(int argc, const char **argv, const char **envp) {
.input_file = nullptr,
.verbose = 0,
.output_file = nullptr,
.entry_point_symbol = nullptr,
.emit_ast = false,
.emit_ir = false,
.target_description = "x86_64-pc-windows-msvc",
@@ -243,6 +244,8 @@ sstream_drop:
scc_ir2mcode(&ir2mcode_ctx);
scc_ir2mcode_drop(&ir2mcode_ctx);
sccf_builder_set_entry_symbol_name(&sccf_builder,
config.entry_point_symbol);
const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder);
scc_pe_builder_t pe_builder;
sccf2pe(&pe_builder, sccf);

View File

@@ -36,7 +36,7 @@ def run_test(test_file, expected):
exe_path = WORKSPACE / exe_filename
# 1. 编译
compile_cmd = [str(CC_PATH), str(test_file), "-o", exe_filename]
compile_cmd = [str(CC_PATH), str(test_file), "-o", exe_filename, "--entry-point-symbol", "main"]
# 编译时关注 stderr 和返回码
_, compile_err, compile_ret = run_command(compile_cmd)