Files
scc/libs/ir/hir/src/scc_hir_builder.c
T
zzyandCopilot f6bc40ae4a refactor(ast): 将AST类型系统重构为规范类型系统
- 将scc_ast_type_t替换为scc_ast_qual_type_t,引入规范类型概念
- 添加scc_ast_canonical_type_t联合体用于表示规范类型
- 修改头文件结构,移除大量内联初始化函数,改为使用AST上下文分配器
- 添加SCC_AST_ALLOC宏用于统一节点分配管理
- 更新builtin类型枚举定义,添加类型计数常量

feat(ast): 引入AST上下文管理器

- 创建scc_ast_ctx_t结构体用于管理AST节点生命周期
- 实现类型池化机制,支持内置类型的统一管理
- 添加canonical类型获取和分配接口

refactor(abi): 适配新的AST类型系统

- 更新头文件包含,从<scc_ir.h>改为<scc_hir.h>
- 适配函数参数类型,使用qual_type替代原始type
- 使用scc_ast_canon_type()函数获取规范类型进行处理

Co-authored-by: Copilot <[email protected]>
2026-04-27 20:40:03 +08:00

706 lines
26 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}
scc_vec_foreach(key1->data.function.params, i) {
if (key1->data.function.params.data[i] !=
key2->data.function.params.data[i]) {
return 1;
}
}
return 0;
}
case SCC_HIR_TYPE_STRUCT:
case SCC_HIR_TYPE_UNION: {
if (key1->data.aggregate.fields.size !=
key2->data.aggregate.fields.size) {
return 1;
}
scc_vec_foreach(key1->data.aggregate.fields, i) {
if (key1->data.aggregate.fields.data[i] !=
key2->data.aggregate.fields.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;
}