#include #include #include #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; }