feat(ir): 重构指针操作API并优化数组访问逻辑
- 将scc_ir_builder_get_ptr重命名为scc_ir_builder_get_elem_ptr以更好地反映其功能 - 移除旧的GET_PTR相关枚举和结构体定义 - 更新IR构建器中指针类型的处理逻辑,支持数组元素指针计算 - 在代码生成阶段正确处理元素指针操作的索引计算 fix(ast2ir): 修正数组下标表达式的指针获取操作 - 将数组访问中的get_ptr调用替换为get_elem_ptr - 确保数组元素访问使用正确的IR指令 perf(runtime): 优化fprintf函数的大字符串处理性能 - 实现动态缓冲区分配策略,小字符串使用栈缓冲区,大字符串使用堆分配 - 避免固定大小缓冲区可能导致的截断问题 - 添加适当的内存清理机制
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
#include <scc_ast2ir.h>
|
#include <scc_ast2ir.h>
|
||||||
|
|
||||||
|
static inline void parse_struct_union_layout(scc_ast_type_t *type) {}
|
||||||
|
|
||||||
static inline void parse_lexme2const_int(const char *lexme,
|
static inline void parse_lexme2const_int(const char *lexme,
|
||||||
scc_ir_const_int_t *value) {
|
scc_ir_const_int_t *value) {
|
||||||
// FIXME
|
// FIXME
|
||||||
@@ -430,7 +432,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
|||||||
scc_ast2ir_expr(ctx, expr->subscript.index, false);
|
scc_ast2ir_expr(ctx, expr->subscript.index, false);
|
||||||
// 3. 生成 getptr(GEP)
|
// 3. 生成 getptr(GEP)
|
||||||
scc_ir_value_ref_t elem_ptr =
|
scc_ir_value_ref_t elem_ptr =
|
||||||
scc_ir_builder_get_ptr(&ctx->builder, base_ptr, index);
|
scc_ir_builder_get_elem_ptr(&ctx->builder, base_ptr, index);
|
||||||
// 4. 根据左值/右值返回
|
// 4. 根据左值/右值返回
|
||||||
if (is_lvalue) {
|
if (is_lvalue) {
|
||||||
return elem_ptr; // 作为左值:返回地址
|
return elem_ptr; // 作为左值:返回地址
|
||||||
@@ -523,7 +525,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
|||||||
ctx->builder.ctx.module, ir_type->data.pointer.base);
|
ctx->builder.ctx.module, ir_type->data.pointer.base);
|
||||||
if (target_type->tag == SCC_IR_TYPE_ARRAY) {
|
if (target_type->tag == SCC_IR_TYPE_ARRAY) {
|
||||||
// 生成 getptr 获取数组首地址
|
// 生成 getptr 获取数组首地址
|
||||||
return scc_ir_builder_get_ptr(&ctx->builder, in,
|
return scc_ir_builder_get_elem_ptr(&ctx->builder, in,
|
||||||
SCC_IR_REF_nullptr);
|
SCC_IR_REF_nullptr);
|
||||||
} else {
|
} else {
|
||||||
// 标量类型:加载值
|
// 标量类型:加载值
|
||||||
|
|||||||
@@ -144,10 +144,11 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str,
|
|||||||
// scc_hashtable_insert(builder);
|
// scc_hashtable_insert(builder);
|
||||||
|
|
||||||
scc_ir_value_ref_t pointer_to_global_value = scc_ir_module_add_value(
|
scc_ir_value_ref_t pointer_to_global_value = scc_ir_module_add_value(
|
||||||
builder->ctx.module, &(scc_ir_value_t){
|
builder->ctx.module,
|
||||||
.tag = SCC_IR_VALUE_TAG_GET_PTR,
|
&(scc_ir_value_t){
|
||||||
.data.get_ptr.src_addr = global_value_ref,
|
.tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR,
|
||||||
.data.get_ptr.index = SCC_IR_VALUE_TAG_NULLPTR,
|
.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);
|
scc_ir_builder_add_instr(builder, pointer_to_global_value);
|
||||||
return pointer_to_global_value;
|
return pointer_to_global_value;
|
||||||
@@ -236,7 +237,7 @@ scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
|
|||||||
* @param ptr 基础指针
|
* @param ptr 基础指针
|
||||||
* @param index 索引值
|
* @param index 索引值
|
||||||
*/
|
*/
|
||||||
scc_ir_value_ref_t scc_ir_builder_get_ptr(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 ptr,
|
scc_ir_value_ref_t ptr,
|
||||||
scc_ir_value_ref_t index);
|
scc_ir_value_ref_t index);
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ typedef enum scc_ir_value_tag {
|
|||||||
SCC_IR_VALUE_TAG_GLOBAL_ALLOC, ///< 全局分配
|
SCC_IR_VALUE_TAG_GLOBAL_ALLOC, ///< 全局分配
|
||||||
SCC_IR_VALUE_TAG_LOAD, ///< 加载数据
|
SCC_IR_VALUE_TAG_LOAD, ///< 加载数据
|
||||||
SCC_IR_VALUE_TAG_STORE, ///< 存储数据
|
SCC_IR_VALUE_TAG_STORE, ///< 存储数据
|
||||||
SCC_IR_VALUE_TAG_GET_PTR, ///< 获取指针
|
|
||||||
SCC_IR_VALUE_TAG_GET_ELEM_PTR, ///< 获取元素指针
|
SCC_IR_VALUE_TAG_GET_ELEM_PTR, ///< 获取元素指针
|
||||||
SCC_IR_VALUE_TAG_OP, ///< 二元运算
|
SCC_IR_VALUE_TAG_OP, ///< 二元运算
|
||||||
SCC_IR_VALUE_TAG_BRANCH, ///< 有条件分支
|
SCC_IR_VALUE_TAG_BRANCH, ///< 有条件分支
|
||||||
@@ -258,10 +257,6 @@ struct scc_ir_value {
|
|||||||
scc_ir_value_ref_t target;
|
scc_ir_value_ref_t target;
|
||||||
scc_ir_value_ref_t value;
|
scc_ir_value_ref_t value;
|
||||||
} store;
|
} store;
|
||||||
struct {
|
|
||||||
scc_ir_value_ref_t src_addr;
|
|
||||||
scc_ir_value_ref_t index;
|
|
||||||
} get_ptr;
|
|
||||||
struct {
|
struct {
|
||||||
scc_ir_value_ref_t src_addr;
|
scc_ir_value_ref_t src_addr;
|
||||||
scc_ir_value_ref_t index;
|
scc_ir_value_ref_t index;
|
||||||
|
|||||||
@@ -227,19 +227,33 @@ scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
|
|||||||
return value_ref;
|
return value_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ir_value_ref_t scc_ir_builder_get_ptr(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 target,
|
||||||
scc_ir_value_ref_t index) {
|
scc_ir_value_ref_t index) {
|
||||||
scc_ir_value_t get_ptr_node = {0};
|
scc_ir_value_t get_ptr_node = {0};
|
||||||
get_ptr_node.tag = SCC_IR_VALUE_TAG_GET_PTR;
|
get_ptr_node.tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR;
|
||||||
get_ptr_node.data.get_ptr.src_addr = target;
|
get_ptr_node.data.get_elem_ptr.src_addr = target;
|
||||||
get_ptr_node.data.get_ptr.index = index;
|
get_ptr_node.data.get_elem_ptr.index = index;
|
||||||
|
|
||||||
// 类型应与源地址相同(都是指针)
|
// 类型应与源地址相同(都是指针)
|
||||||
scc_ir_value_t *src_node =
|
scc_ir_type_t *type =
|
||||||
scc_ir_module_get_value(GET_MODULE(builder), target);
|
scc_ir_module_get_type_by_value(GET_MODULE(builder), target);
|
||||||
if (src_node) {
|
Assert(type != nullptr);
|
||||||
get_ptr_node.type = src_node->type;
|
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);
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
get_ptr_node.type = scc_ir_builder_type(builder, type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
get_ptr_node.type = scc_ir_builder_type(builder, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ir_value_ref_t value_ref =
|
scc_ir_value_ref_t value_ref =
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ static const char *get_node_type_str(scc_ir_value_tag_t tag) {
|
|||||||
[SCC_IR_VALUE_TAG_GLOBAL_ALLOC] = "GlobalAlloc",
|
[SCC_IR_VALUE_TAG_GLOBAL_ALLOC] = "GlobalAlloc",
|
||||||
[SCC_IR_VALUE_TAG_LOAD] = "Load",
|
[SCC_IR_VALUE_TAG_LOAD] = "Load",
|
||||||
[SCC_IR_VALUE_TAG_STORE] = "Store",
|
[SCC_IR_VALUE_TAG_STORE] = "Store",
|
||||||
[SCC_IR_VALUE_TAG_GET_PTR] = "GetPtr",
|
|
||||||
[SCC_IR_VALUE_TAG_GET_ELEM_PTR] = "GetElemPtr",
|
[SCC_IR_VALUE_TAG_GET_ELEM_PTR] = "GetElemPtr",
|
||||||
[SCC_IR_VALUE_TAG_OP] = "Op",
|
[SCC_IR_VALUE_TAG_OP] = "Op",
|
||||||
[SCC_IR_VALUE_TAG_BRANCH] = "Branch",
|
[SCC_IR_VALUE_TAG_BRANCH] = "Branch",
|
||||||
@@ -117,12 +116,12 @@ static void dump_store_node(scc_ir_dump_ctx_t *ctx,
|
|||||||
dump_child_node_ref(ctx, value->data.store.value, true);
|
dump_child_node_ref(ctx, value->data.store.value, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_get_ptr_node(scc_ir_dump_ctx_t *ctx,
|
static void dump_get_elem_ptr_node(scc_ir_dump_ctx_t *ctx,
|
||||||
const scc_ir_value_t *value) {
|
const scc_ir_value_t *value) {
|
||||||
if (value->data.get_ptr.src_addr)
|
if (value->data.get_elem_ptr.src_addr)
|
||||||
dump_child_node_ref(ctx, value->data.get_ptr.src_addr, false);
|
dump_child_node_ref(ctx, value->data.get_elem_ptr.src_addr, false);
|
||||||
if (value->data.get_ptr.index)
|
if (value->data.get_elem_ptr.index)
|
||||||
dump_child_node_ref(ctx, value->data.get_ptr.index, true);
|
dump_child_node_ref(ctx, value->data.get_elem_ptr.index, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_branch_node(scc_ir_dump_ctx_t *ctx,
|
static void dump_branch_node(scc_ir_dump_ctx_t *ctx,
|
||||||
@@ -236,8 +235,8 @@ void scc_ir_dump_value(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t value_ref) {
|
|||||||
case SCC_IR_VALUE_TAG_STORE:
|
case SCC_IR_VALUE_TAG_STORE:
|
||||||
dump_store_node(ctx, value);
|
dump_store_node(ctx, value);
|
||||||
break;
|
break;
|
||||||
case SCC_IR_VALUE_TAG_GET_PTR:
|
case SCC_IR_VALUE_TAG_GET_ELEM_PTR:
|
||||||
dump_get_ptr_node(ctx, value);
|
dump_get_elem_ptr_node(ctx, value);
|
||||||
break;
|
break;
|
||||||
case SCC_IR_VALUE_TAG_OP:
|
case SCC_IR_VALUE_TAG_OP:
|
||||||
dump_op_node(ctx, value);
|
dump_op_node(ctx, value);
|
||||||
@@ -556,13 +555,10 @@ void scc_ir_dump_value_linear(scc_ir_dump_ctx_t *ctx,
|
|||||||
format_ref_or_value(ctx, value->data.store.target);
|
format_ref_or_value(ctx, value->data.store.target);
|
||||||
break;
|
break;
|
||||||
case SCC_IR_VALUE_TAG_GET_ELEM_PTR:
|
case SCC_IR_VALUE_TAG_GET_ELEM_PTR:
|
||||||
case SCC_IR_VALUE_TAG_GET_PTR:
|
scc_tree_dump_append(ctx->dump_ctx, "getelemptr ");
|
||||||
scc_tree_dump_append(
|
format_ref_or_value(ctx, value->data.get_elem_ptr.src_addr);
|
||||||
ctx->dump_ctx,
|
|
||||||
value->tag == SCC_IR_VALUE_TAG_GET_PTR ? "getptr " : "getelemptr ");
|
|
||||||
format_ref_or_value(ctx, value->data.get_ptr.src_addr);
|
|
||||||
scc_tree_dump_append(ctx->dump_ctx, ", ");
|
scc_tree_dump_append(ctx->dump_ctx, ", ");
|
||||||
format_ref_or_value(ctx, value->data.get_ptr.index);
|
format_ref_or_value(ctx, value->data.get_elem_ptr.index);
|
||||||
break;
|
break;
|
||||||
case SCC_IR_VALUE_TAG_OP:
|
case SCC_IR_VALUE_TAG_OP:
|
||||||
format_ref_or_value(ctx, value->data.op.lhs);
|
format_ref_or_value(ctx, value->data.op.lhs);
|
||||||
|
|||||||
@@ -82,9 +82,9 @@ void scc_ir_value_init(scc_ir_value_t *in, const char *name,
|
|||||||
in->data.store.target = 0;
|
in->data.store.target = 0;
|
||||||
in->data.store.value = 0;
|
in->data.store.value = 0;
|
||||||
break;
|
break;
|
||||||
case SCC_IR_VALUE_TAG_GET_PTR:
|
case SCC_IR_VALUE_TAG_GET_ELEM_PTR:
|
||||||
in->data.get_ptr.src_addr = 0;
|
in->data.get_elem_ptr.src_addr = 0;
|
||||||
in->data.get_ptr.index = 0;
|
in->data.get_elem_ptr.index = 0;
|
||||||
break;
|
break;
|
||||||
case SCC_IR_VALUE_TAG_OP:
|
case SCC_IR_VALUE_TAG_OP:
|
||||||
in->data.op.op = SCC_IR_OP_EMPTY;
|
in->data.op.op = SCC_IR_OP_EMPTY;
|
||||||
|
|||||||
@@ -287,14 +287,14 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
///< 获取指针
|
///< 获取指针
|
||||||
case SCC_IR_VALUE_TAG_GET_PTR: {
|
case SCC_IR_VALUE_TAG_GET_ELEM_PTR: {
|
||||||
scc_reg_loc_t loc_res;
|
scc_reg_loc_t loc_res;
|
||||||
parse_location(ctx, &loc_res, node_ref);
|
parse_location(ctx, &loc_res, node_ref);
|
||||||
|
|
||||||
scc_ir_value_t *src_addr = scc_ir_module_get_value(
|
scc_ir_value_t *src_addr = scc_ir_module_get_value(
|
||||||
GET_MODULE(ctx), value->data.get_ptr.src_addr);
|
GET_MODULE(ctx), value->data.get_elem_ptr.src_addr);
|
||||||
Assert(src_addr != nullptr);
|
Assert(src_addr != nullptr);
|
||||||
if (value->data.get_ptr.index == 0) {
|
if (value->data.get_elem_ptr.index == 0) {
|
||||||
if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
|
if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
|
||||||
// 全局变量:RIP相对寻址
|
// 全局变量:RIP相对寻址
|
||||||
scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode,
|
scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode,
|
||||||
@@ -314,30 +314,35 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|||||||
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
|
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
|
||||||
// 栈上变量:地址为 rbp - offset
|
// 栈上变量:地址为 rbp - offset
|
||||||
scc_reg_loc_t src_loc;
|
scc_reg_loc_t src_loc;
|
||||||
parse_location(ctx, &src_loc, value->data.get_ptr.src_addr);
|
parse_location(ctx, &src_loc,
|
||||||
|
value->data.get_elem_ptr.src_addr);
|
||||||
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
|
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
|
||||||
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
|
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
|
||||||
} else {
|
} else {
|
||||||
// 其他情况(如链式
|
// 其他情况(如链式getptr):源地址值已经存储在某个位置,直接加载到
|
||||||
// getptr):源地址值已经存储在某个位置,直接加载到 RAX
|
// RAX
|
||||||
scc_reg_loc_t src_loc;
|
scc_reg_loc_t src_loc;
|
||||||
parse_location(ctx, &src_loc, value->data.get_ptr.src_addr);
|
parse_location(ctx, &src_loc,
|
||||||
|
value->data.get_elem_ptr.src_addr);
|
||||||
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
|
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
|
|
||||||
} else {
|
} else {
|
||||||
// TODO
|
// TODO
|
||||||
scc_ir_value_t *index = scc_ir_module_get_value(
|
parse_value(ctx, value->data.get_elem_ptr.index, patches);
|
||||||
GET_MODULE(ctx), value->data.get_ptr.index);
|
|
||||||
Assert(index != nullptr &&
|
|
||||||
index->tag == SCC_IR_VALUE_TAG_CONST_INT);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
scc_reg_loc_t src_loc;
|
||||||
|
scc_reg_loc_t idx_loc;
|
||||||
|
parse_location(ctx, &src_loc, value->data.get_elem_ptr.src_addr);
|
||||||
|
parse_location(ctx, &idx_loc, value->data.get_elem_ptr.index);
|
||||||
|
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);
|
||||||
|
scc_mcode_amd64_lea_r64_m64_sib(&ctx->sect_mcode, SCC_AMD64_RAX,
|
||||||
|
SCC_AMD64_RAX, SCC_AMD64_RDX, 1, 0);
|
||||||
|
}
|
||||||
|
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_IR_VALUE_TAG_GET_ELEM_PTR: ///< 获取元素指针(used by array)
|
|
||||||
TODO();
|
|
||||||
///< 二元运算
|
///< 二元运算
|
||||||
case SCC_IR_VALUE_TAG_OP: {
|
case SCC_IR_VALUE_TAG_OP: {
|
||||||
scc_reg_loc_t loc_lhs;
|
scc_reg_loc_t loc_lhs;
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ void scc_reg_alloc_strategy_pure_stack(scc_reg_alloc_t *ctx,
|
|||||||
switch (node->tag) {
|
switch (node->tag) {
|
||||||
case SCC_IR_VALUE_TAG_LOAD:
|
case SCC_IR_VALUE_TAG_LOAD:
|
||||||
case SCC_IR_VALUE_TAG_OP:
|
case SCC_IR_VALUE_TAG_OP:
|
||||||
case SCC_IR_VALUE_TAG_GET_PTR:
|
|
||||||
case SCC_IR_VALUE_TAG_GET_ELEM_PTR:
|
case SCC_IR_VALUE_TAG_GET_ELEM_PTR:
|
||||||
case SCC_IR_VALUE_TAG_CALL: // 返回值
|
case SCC_IR_VALUE_TAG_CALL: // 返回值
|
||||||
loc.kind = SCC_REG_KIND_STACK;
|
loc.kind = SCC_REG_KIND_STACK;
|
||||||
|
|||||||
@@ -79,8 +79,33 @@ int scc_fprintf(scc_file_t file, const char *format, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int scc_vfprintf(scc_file_t file, const char *format, va_list args) {
|
int scc_vfprintf(scc_file_t file, const char *format, va_list args) {
|
||||||
char buf[4096] = {0};
|
va_list args_copy;
|
||||||
int size = vsnprintf_(buf, sizeof(buf), format, args);
|
va_copy(args_copy, args);
|
||||||
|
|
||||||
|
// 先计算所需长度
|
||||||
|
int required_size = vsnprintf_(nullptr, 0, format, args_copy);
|
||||||
|
va_end(args_copy);
|
||||||
|
|
||||||
|
if (required_size < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char *buf = nullptr;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
if (required_size < 4096) {
|
||||||
|
// 小输出使用栈上缓冲区
|
||||||
|
char stack_buf[4096];
|
||||||
|
size = vsnprintf_(stack_buf, sizeof(stack_buf), format, args);
|
||||||
|
buf = stack_buf;
|
||||||
|
} else {
|
||||||
|
// 大输出使用堆分配
|
||||||
|
buf = scc_pal_malloc(required_size + 1);
|
||||||
|
if (!buf)
|
||||||
|
return -1;
|
||||||
|
size = vsnprintf_(buf, required_size + 1, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出处理...
|
||||||
if (file == scc_stdout) {
|
if (file == scc_stdout) {
|
||||||
scc_pal_write(buf, size);
|
scc_pal_write(buf, size);
|
||||||
} else if (file == scc_stderr) {
|
} else if (file == scc_stderr) {
|
||||||
@@ -88,6 +113,12 @@ int scc_vfprintf(scc_file_t file, const char *format, va_list args) {
|
|||||||
} else {
|
} else {
|
||||||
scc_pal_fwrite(file, buf, size);
|
scc_pal_fwrite(file, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果使用了堆分配,释放内存
|
||||||
|
if (buf && required_size >= 4096) {
|
||||||
|
scc_pal_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user