feat(ir): 启用LIR模块并重构HIR组件结构

- 在cbuild.toml中启用lir依赖项,取消注释相关配置
- 重构libs/README.md文档,添加详细的库说明和层级结构
- 重命名头文件以统一命名规范:ast_def.h → scc_ast_def.h,
  ast_dump.h → scc_ast_dump.h, hir相关文件添加scc前缀
- 更新include路径以匹配新的文件命名
- 在cfg模块中添加symbol ID类型和linkage枚举,完善符号表功能
- 实现cfg模块中的符号添加、查找和获取功能
- 修改HIR中meta字段替换原有的attribute字段,更新相关访问宏
- 修复HIR构建器中的函数元数据访问错误
- 为LIR模块创建完整的头文件结构,包括指令定义、转换器等组件
This commit is contained in:
zzy committed 2026-04-21 20:35:37 +08:00
1 parent 0fbfb36262
commit e850b5c981
30 files changed
+1588 -2627

No files matched your search

+691
View File
@@ -0,0 +1,691 @@
#include <scc_hir_builder.h>
#include <scc_hir_def.h>
#include <scc_hir_prog.h>
#define GET_MODULE(builder) (&(builder->cprog->module))
/**
* @brief 哈希混合函数(类似Rust的hash combine)
*
* Rust的默认哈希实现(SipHash 1-3)使用旋转和异或,
* 这里使用简单的FNV-1a变体,类似于Rust的`#[derive(Hash)]`
*/
static inline u32 scc_hash_mix(u32 seed, u32 value) {
// FNV-1a风格混合
return (seed ^ value) * 16777619u;
}
static u32 hash_type(const void *_key, void *userdata) {
scc_hir_module_t *module = userdata;
const scc_hir_type_t *key =
_key == SCC_HIR_REF_nullptr
? &scc_vec_at(module->types, 0)
: scc_hir_module_get_type(module, (usize)_key);
// 初始哈希:tag
u32 hash = (u32)key->tag;
switch (key->tag) {
case SCC_HIR_TYPE_void:
case SCC_HIR_TYPE_u8:
case SCC_HIR_TYPE_u16:
case SCC_HIR_TYPE_u32:
case SCC_HIR_TYPE_u64:
case SCC_HIR_TYPE_u128:
case SCC_HIR_TYPE_i8:
case SCC_HIR_TYPE_i16:
case SCC_HIR_TYPE_i32:
case SCC_HIR_TYPE_i64:
case SCC_HIR_TYPE_i128:
case SCC_HIR_TYPE_f16:
case SCC_HIR_TYPE_f32:
case SCC_HIR_TYPE_f64:
case SCC_HIR_TYPE_f128:
// 基本类型,只有tag
break;
case SCC_HIR_TYPE_PTR:
hash = scc_hash_mix(hash, (u32)key->data.array.base);
break;
case SCC_HIR_TYPE_ARRAY:
hash = scc_hash_mix(hash, (u32)key->data.array.base);
hash = scc_hash_mix(hash, (u32)key->data.array.len);
break;
case SCC_HIR_TYPE_FUNC:
// 注意:这里需要递归哈希参数类型
hash = scc_hash_mix(hash, (u32)key->data.function.ret_type);
for (usize i = 0; i < key->data.function.params.size; i++) {
hash = scc_hash_mix(hash, (u32)key->data.function.params.data[i]);
}
hash = scc_hash_mix(hash, (u32)key->data.function.params.size);
break;
case SCC_HIR_TYPE_STRUCT:
case SCC_HIR_TYPE_UNION:
return 0;
case SCC_HIR_TYPE_VECTOR:
default:
Panic("Invalid type tag %d", key->tag);
return 0;
}
return hash;
}
static int cmp_type(const void *_key1, const void *_key2, void *userdata) {
scc_hir_module_t *module = userdata;
const scc_hir_type_t *key1 = _key1 == SCC_HIR_REF_nullptr
? &scc_vec_at(module->types, 0)
: scc_hir_module_get_type(module,
(usize)_key1),
*key2 = _key2 == SCC_HIR_REF_nullptr
? &scc_vec_at(module->types, 0)
: scc_hir_module_get_type(module,
(usize)_key2);
Assert(key1 != nullptr && key2 != nullptr);
if (key1->tag == SCC_HIR_TYPE_unknown ||
key2->tag == SCC_HIR_TYPE_unknown) {
return 1;
}
// tag不同
if (key1->tag != key2->tag) {
return 1;
}
switch (key1->tag) {
case SCC_HIR_TYPE_void:
case SCC_HIR_TYPE_u8:
case SCC_HIR_TYPE_u16:
case SCC_HIR_TYPE_u32:
case SCC_HIR_TYPE_u64:
case SCC_HIR_TYPE_u128:
case SCC_HIR_TYPE_i8:
case SCC_HIR_TYPE_i16:
case SCC_HIR_TYPE_i32:
case SCC_HIR_TYPE_i64:
case SCC_HIR_TYPE_i128:
case SCC_HIR_TYPE_f16:
case SCC_HIR_TYPE_f32:
case SCC_HIR_TYPE_f64:
case SCC_HIR_TYPE_f128:
return 0; // 基本类型,tag相同即可
case SCC_HIR_TYPE_PTR:
return key1->data.pointer.base != key2->data.pointer.base;
case SCC_HIR_TYPE_ARRAY:
return (key1->data.array.base != key2->data.array.base) ||
(key1->data.array.len != key2->data.array.len);
case SCC_HIR_TYPE_FUNC: {
if (key1->data.function.ret_type != key2->data.function.ret_type) {
return 1;
}
if (key1->data.function.params.size !=
key2->data.function.params.size) {
return 1;
}
for (usize i = 0; i < key1->data.function.params.size; i++) {
if (key1->data.function.params.data[i] !=
key2->data.function.params.data[i]) {
return 1;
}
}
return 0;
}
default:
Panic("Unknown key type %d", key1->tag);
return 1;
}
return 1;
}
void scc_hir_builder_init(scc_hir_builder_t *builder, scc_hir_cprog_t *cprog) {
builder->current_bblock = SCC_HIR_REF_nullptr;
builder->current_func = SCC_HIR_REF_nullptr;
builder->cprog = cprog;
scc_hashtable_init(&builder->type_uniquing, hash_type, cmp_type,
GET_MODULE(builder));
// scc_hashtable_init(&builder->const_pool, /* 常量哈希函数 */,
// /* 常量比较函数 */);
scc_hashtable_cstr_init(&builder->func_decl_set);
#ifndef SCC_NO_DEBUG
builder->borrow_depth = 0;
builder->dbg_file = nullptr;
builder->dbg_line = 0;
#endif
}
void scc_hir_builder_drop(scc_hir_builder_t *builder) {
scc_hashtable_drop(&builder->type_uniquing);
// scc_hashtable_drop(&builder->const_pool);
scc_hashtable_drop(&builder->func_decl_set);
}
scc_hir_func_ref_t scc_hir_builder_func(scc_hir_builder_t *builder,
scc_hir_type_ref_t type_ref,
const char *name) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
// 检查是否已声明
void *found = scc_hashtable_get(&builder->func_decl_set, (void *)name);
if (found) {
return (scc_hir_func_ref_t)(usize)found;
}
// 创建新函数
scc_hir_func_t func;
scc_hir_func_meta_t *meta = scc_malloc(sizeof(scc_hir_func_meta_t));
Assert(meta != nullptr);
func.meta = meta;
scc_hir_func_init(&func, name);
meta->type = type_ref;
scc_hir_func_ref_t func_ref =
scc_hir_module_add_func(GET_MODULE(builder), &func);
scc_hashtable_set(&builder->func_decl_set, (void *)name,
(void *)(usize)func_ref);
scc_vec_push(builder->cprog->func_decls, func_ref);
return func_ref;
}
scc_hir_bblock_ref_t scc_hir_builder_bblock(scc_hir_builder_t *builder,
const char *label) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_bblock_t bblock = {0};
if (label) {
bblock.name = label;
}
// scc_hir_bblock_meta_t bblock_meta = {0};
// FIXME 当前没有bblock meta
bblock.meta = nullptr;
scc_vec_init(*SCC_HIR_BBLOCK_VALUES(&bblock));
scc_hir_bblock_ref_t bblock_ref =
scc_hir_module_add_bblock(GET_MODULE(builder), &bblock);
// 将基本块添加到当前函数
scc_hir_func_t *current_func = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, current_func,
scc_hir_module_get_func(GET_MODULE(builder), builder->current_func));
if (current_func) {
// FIXME hack cfg
scc_vec_push(current_func->bblocks, bblock_ref);
}
SCC_HIR_BUILDER_END_BORROW(builder);
return bblock_ref;
}
scc_hir_type_ref_t scc_hir_builder_type(scc_hir_builder_t *builder,
const scc_hir_type_t *type_desc) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
Assert(type_desc->tag != SCC_HIR_TYPE_unknown);
scc_vec_at(GET_MODULE(builder)->types, 0) = *type_desc;
// 先查哈希表
void *found = scc_hashtable_get(&builder->type_uniquing, (void *)(usize)0);
if (found) {
return (scc_hir_type_ref_t)(usize)found;
}
// 不存在,添加新类型
scc_hir_type_ref_t new_ref =
scc_hir_module_add_type(GET_MODULE(builder), type_desc);
scc_hashtable_set(&builder->type_uniquing, (void *)(usize)new_ref,
(void *)(usize)new_ref);
return new_ref;
}
scc_hir_value_ref_t scc_hir_builder_const_string(scc_hir_builder_t *builder,
const char *str, usize len) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_type_ref_t u8_type = scc_hir_builder_type_u8(builder);
scc_hir_type_t array_type = {
.tag = SCC_HIR_TYPE_ARRAY,
.data.array.base = u8_type,
.data.array.len = len - 1, // 包含 nullptr 结尾
};
scc_hir_type_ref_t array_type_ref =
scc_hir_builder_type(builder, &array_type);
// 5. 创建聚合节点
scc_hir_value_t const_array_value = {
.tag = SCC_HIR_VALUE_TAG_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_hir_value_ref_t const_array_ref =
scc_hir_module_add_value(GET_MODULE(builder), &const_array_value);
Assert(const_array_ref != SCC_HIR_REF_nullptr);
// 3. 创建全局变量节点,类型为指针,初始值指向常量数组
scc_hir_value_ref_t global_value_ref =
scc_hir_builder_global_alloca(builder, array_type_ref, const_array_ref);
// scc_hashtable_insert(builder);
scc_hir_value_ref_t pointer_to_global_value = scc_hir_module_add_value(
GET_MODULE(builder),
&(scc_hir_value_t){
.tag = SCC_HIR_VALUE_TAG_GET_ELEM_PTR,
.data.get_elem_ptr.src_addr = global_value_ref,
.data.get_elem_ptr.index = SCC_HIR_VALUE_TAG_NULLPTR,
});
scc_hir_builder_add_instr(builder, pointer_to_global_value);
return pointer_to_global_value;
}
void scc_hir_builder_begin_func(scc_hir_builder_t *builder,
scc_hir_func_ref_t func_ref) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
builder->current_func = func_ref;
// 借用 func_ptr 和 func_type 以获取参数类型列表
scc_hir_func_t *func_ptr = nullptr;
scc_hir_type_t *func_type = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, func_ptr,
scc_hir_module_get_func(GET_MODULE(builder), func_ref));
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, func_type,
scc_hir_module_get_type(GET_MODULE(builder),
SCC_HIR_FUNC_META(func_ptr)->type));
if (func_type == nullptr || func_type->tag != SCC_HIR_TYPE_FUNC) {
LOG_ERROR("Invalid function type");
SCC_HIR_BUILDER_END_BORROW(builder); // func_type
SCC_HIR_BUILDER_END_BORROW(builder); // func_ptr
return;
}
if (func_ptr == nullptr) {
LOG_ERROR("Invalid function reference");
SCC_HIR_BUILDER_END_BORROW(builder); // func_type
SCC_HIR_BUILDER_END_BORROW(builder); // func_ptr
return;
}
if (scc_vec_size(func_ptr->bblocks) != 0 ||
scc_vec_size(SCC_HIR_FUNC_META(func_ptr)->params) != 0) {
LOG_FATAL("Multiple function definitions");
SCC_HIR_BUILDER_END_BORROW(builder); // func_type
SCC_HIR_BUILDER_END_BORROW(builder); // func_ptr
return;
}
// 释放借用,因为下面要调用 add_value(可能 realloc)
SCC_HIR_BUILDER_END_BORROW(builder); // func_type
SCC_HIR_BUILDER_END_BORROW(builder); // func_ptr
}
void scc_hir_builder_end_func(scc_hir_builder_t *builder) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_func_t *func_ptr = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, func_ptr,
scc_hir_module_get_func(GET_MODULE(builder), builder->current_func));
if (func_ptr == nullptr) {
LOG_FATAL("Invalid function reference");
SCC_HIR_BUILDER_END_BORROW(builder);
return;
}
if (scc_vec_size(func_ptr->bblocks) == 0) {
scc_vec_push(builder->cprog->func_decls, builder->current_func);
} else {
scc_vec_push(builder->cprog->func_defs, builder->current_func);
}
SCC_HIR_BUILDER_END_BORROW(builder);
builder->current_func = 0;
}
scc_hir_func_ref_t scc_hir_builder_current_func(scc_hir_builder_t *builder) {
// 只读操作,无需检查借用
return builder->current_func;
}
scc_hir_bblock_ref_t scc_hir_builder_begin_bblock(scc_hir_builder_t *builder,
const char *label) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
builder->current_bblock = scc_hir_builder_bblock(builder, label);
return builder->current_bblock;
}
void scc_hir_builder_end_bblock(scc_hir_builder_t *builder) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
builder->current_bblock = 0;
}
void scc_hir_builder_set_current_bblock(scc_hir_builder_t *builder,
scc_hir_bblock_ref_t bblock) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
builder->current_bblock = bblock;
}
scc_hir_func_ref_t scc_hir_builder_current_bblock(scc_hir_builder_t *builder) {
return builder->current_bblock;
}
void scc_hir_builder_add_instr(scc_hir_builder_t *builder,
scc_hir_value_ref_t instr) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_bblock_t *current_bblock = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, current_bblock,
scc_hir_module_get_bblock(GET_MODULE(builder),
builder->current_bblock));
if (current_bblock) {
scc_vec_push(*SCC_HIR_BBLOCK_VALUES(current_bblock), instr);
} else {
LOG_ERROR("Current basic block is not set");
}
SCC_HIR_BUILDER_END_BORROW(builder);
}
scc_hir_value_ref_t scc_hir_builder_global_alloca(scc_hir_builder_t *builder,
scc_hir_type_ref_t type,
scc_hir_value_ref_t value) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
char *name = scc_malloc(32);
scc_hir_value_ref_t global_value_ref = scc_hir_module_add_value(
GET_MODULE(builder), &(scc_hir_value_t){
.name = name,
.tag = SCC_HIR_VALUE_TAG_GLOBAL_ALLOC,
.type = type,
.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;
}
scc_hir_value_ref_t scc_hir_builder_alloca(scc_hir_builder_t *builder,
scc_hir_type_ref_t type,
const char *name) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t alloc_node = {0};
alloc_node.tag = SCC_HIR_VALUE_TAG_ALLOC;
alloc_node.type = scc_hir_module_add_type(
GET_MODULE(builder),
&(scc_hir_type_t){.tag = SCC_HIR_TYPE_PTR, .data.pointer.base = type});
alloc_node.name = name;
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &alloc_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_func_arg_ref(scc_hir_builder_t *builder,
scc_hir_type_ref_t type,
const char *name,
usize arg_idx) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t value = {0};
value.tag = SCC_HIR_VALUE_TAG_FUNC_ARG_REF;
value.type = type;
value.name = name;
value.data.arg_ref.idx = arg_idx;
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &value);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_load(scc_hir_builder_t *builder,
scc_hir_value_ref_t target) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t load_node = {0};
load_node.tag = SCC_HIR_VALUE_TAG_LOAD;
load_node.data.load.target = target;
// 借用 ptr_node 和 ptr_type 获取类型信息
scc_hir_value_t *ptr_node = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, ptr_node,
scc_hir_module_get_value(GET_MODULE(builder), target));
if (ptr_node) {
scc_hir_type_t *ptr_type = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, ptr_type,
scc_hir_module_get_type(GET_MODULE(builder), ptr_node->type));
if (ptr_type && ptr_type->tag == SCC_HIR_TYPE_PTR) {
load_node.type = ptr_type->data.pointer.base;
}
SCC_HIR_BUILDER_END_BORROW(builder); // ptr_type
}
SCC_HIR_BUILDER_END_BORROW(builder); // ptr_node
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &load_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_store(scc_hir_builder_t *builder,
scc_hir_value_ref_t target,
scc_hir_value_ref_t value) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
Assert(target != SCC_HIR_REF_nullptr && value != SCC_HIR_REF_nullptr);
scc_hir_value_t store_node = {0};
store_node.tag = SCC_HIR_VALUE_TAG_STORE;
store_node.data.store.target = target;
store_node.data.store.value = value;
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &store_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_get_elem_ptr(scc_hir_builder_t *builder,
scc_hir_value_ref_t target,
scc_hir_value_ref_t index) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t get_ptr_node = {0};
get_ptr_node.tag = SCC_HIR_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_hir_type_t *type_ref = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, type_ref,
scc_hir_module_get_type_by_value(GET_MODULE(builder), target));
Assert(type_ref != nullptr);
scc_hir_type_t type = *type_ref; // 拷贝一份,避免后续借用
SCC_HIR_BUILDER_END_BORROW(builder); // type_ref
if (type.tag == SCC_HIR_TYPE_PTR) {
scc_hir_type_t *base_type = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, base_type,
scc_hir_module_get_type(GET_MODULE(builder),
type_ref->data.pointer.base));
if (base_type->tag == SCC_HIR_TYPE_ARRAY) {
scc_hir_type_t type = (scc_hir_type_t){
.tag = SCC_HIR_TYPE_PTR,
.data.pointer.base = base_type->data.array.base,
};
SCC_HIR_BUILDER_END_BORROW(builder); // base_type
get_ptr_node.type = scc_hir_builder_type(builder, &type);
} else {
SCC_HIR_BUILDER_END_BORROW(builder); // base_type
get_ptr_node.type = scc_hir_builder_type(builder, &type);
}
} else {
get_ptr_node.type = scc_hir_builder_type(builder, &type);
}
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &get_ptr_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_binop(scc_hir_builder_t *builder,
scc_hir_op_type_t op,
scc_hir_value_ref_t lhs,
scc_hir_value_ref_t rhs) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t binop_node = {0};
binop_node.tag = SCC_HIR_VALUE_TAG_OP;
binop_node.data.op.op = op;
binop_node.data.op.lhs = lhs;
binop_node.data.op.rhs = rhs;
// 借用 lhs_node 获取类型
scc_hir_value_t *lhs_node = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, lhs_node, scc_hir_module_get_value(GET_MODULE(builder), lhs));
if (lhs_node) {
binop_node.type = lhs_node->type;
}
SCC_HIR_BUILDER_END_BORROW(builder); // lhs_node
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &binop_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_cmp(scc_hir_builder_t *builder,
scc_hir_op_type_t op,
scc_hir_value_ref_t lhs,
scc_hir_value_ref_t rhs) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t cmp_node = {0};
cmp_node.tag = SCC_HIR_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_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &cmp_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_jump(scc_hir_builder_t *builder,
scc_hir_bblock_ref_t target) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t jump_node = {0};
jump_node.tag = SCC_HIR_VALUE_TAG_JUMP;
jump_node.data.jump.target_bblock = target;
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &jump_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_branch(scc_hir_builder_t *builder,
scc_hir_value_ref_t cond,
scc_hir_bblock_ref_t true_target,
scc_hir_bblock_ref_t false_target) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t branch_node = {0};
branch_node.tag = SCC_HIR_VALUE_TAG_BRANCH;
branch_node.data.branch.cond = cond;
branch_node.data.branch.true_bblock = true_target;
branch_node.data.branch.false_bblock = false_target;
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &branch_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_call(scc_hir_builder_t *builder,
scc_hir_func_ref_t callee,
const scc_hir_value_ref_t *args,
usize arg_count) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t call_node = {0};
call_node.tag = SCC_HIR_VALUE_TAG_CALL;
call_node.data.call.callee = callee;
scc_vec_init(call_node.data.call.args);
for (usize i = 0; i < arg_count; i++) {
scc_vec_push(call_node.data.call.args, args[i]);
}
// 借用 callee_func 和 func_type 获取返回类型
scc_hir_func_t *callee_func = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, callee_func,
scc_hir_module_get_func(GET_MODULE(builder), callee));
if (callee_func) {
scc_hir_type_t *func_type = nullptr;
SCC_HIR_BUILDER_BEGIN_BORROW(
builder, func_type,
scc_hir_module_get_type(GET_MODULE(builder),
SCC_HIR_FUNC_META(callee_func)->type));
if (func_type && func_type->tag == SCC_HIR_TYPE_FUNC) {
call_node.type = func_type->data.function.ret_type;
}
SCC_HIR_BUILDER_END_BORROW(builder); // func_type
}
SCC_HIR_BUILDER_END_BORROW(builder); // callee_func
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &call_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_ret(scc_hir_builder_t *builder,
scc_hir_value_ref_t value) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t ret_node = {0};
ret_node.tag = SCC_HIR_VALUE_TAG_RET;
ret_node.data.ret.ret_val = value;
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &ret_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_ret_void(scc_hir_builder_t *builder) {
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t ret_node = {0};
ret_node.tag = SCC_HIR_VALUE_TAG_RET;
scc_hir_value_t ret_val_node;
scc_hir_value_init(&ret_val_node, nullptr, SCC_HIR_VALUE_TAG_NULLPTR);
ret_val_node.type = scc_hir_builder_type_void(builder);
ret_node.data.ret.ret_val =
scc_hir_module_add_value(GET_MODULE(builder), &ret_val_node);
scc_hir_value_ref_t value_ref =
scc_hir_module_add_value(GET_MODULE(builder), &ret_node);
scc_hir_builder_add_instr(builder, value_ref);
return value_ref;
}
scc_hir_value_ref_t scc_hir_builder_builtin_memcpy(scc_hir_builder_t *builder,
scc_hir_value_ref_t dest,
scc_hir_value_ref_t src,
scc_hir_value_ref_t len) {
Assert(builder && src && dest && len);
scc_hir_value_t value;
scc_hir_value_init(&value, nullptr, SCC_HIR_VALUE_TAG_BUILTIN);
value.type = scc_hir_builder_type_void(builder); // memcpy 返回 void*
value.data.builtin.tag = SCC_HIR_BUILTIN_TAG_MEMCPY;
value.data.builtin.func.memcpy.dest = dest;
value.data.builtin.func.memcpy.src = src;
value.data.builtin.func.memcpy.size = len;
scc_hir_value_ref_t ref =
scc_hir_module_add_value(GET_MODULE(builder), &value);
scc_hir_builder_add_instr(builder, ref);
return ref;
}