- 将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]>
706 lines
26 KiB
C
706 lines
26 KiB
C
#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;
|
||
}
|